⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 prop.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * Property functions
 *
 * Copyright 2004 Jon Griffiths
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <stdarg.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winerror.h"
#include "winternl.h"
#include "objbase.h"
#include "shlwapi.h"
#include "wine/list.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "mapival.h"

WINE_DEFAULT_DEBUG_CHANNEL(mapi);

BOOL WINAPI FBadRglpszA(LPSTR*,ULONG);

/* Internal: Check if a property value array is invalid */
static inline ULONG PROP_BadArray(LPSPropValue lpProp, size_t elemSize)
{
    return IsBadReadPtr(lpProp->Value.MVi.lpi, lpProp->Value.MVi.cValues * elemSize);
}

/*************************************************************************
 * PropCopyMore@16 (MAPI32.76)
 *
 * Copy a property value.
 *
 * PARAMS
 *  lpDest [O] Destination for the copied value
 *  lpSrc  [I] Property value to copy to lpDest
 *  lpMore [I] Linked memory allocation function (pass MAPIAllocateMore())
 *  lpOrig [I] Original allocation to which memory will be linked
 *
 * RETURNS
 *  Success: S_OK. lpDest contains a deep copy of lpSrc.
 *  Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid,
 *           MAPI_E_NOT_ENOUGH_MEMORY, if memory allocation fails.
 *
 * NOTES
 *  Any elements within the property returned should not be individually
 *  freed, as they will be freed when lpOrig is.
 */
SCODE WINAPI PropCopyMore(LPSPropValue lpDest, LPSPropValue lpSrc,
                          ALLOCATEMORE *lpMore, LPVOID lpOrig)
{
    ULONG ulLen, i;
    SCODE scode = S_OK;

    TRACE("(%p,%p,%p,%p)\n", lpDest, lpSrc, lpMore, lpOrig);

    if (!lpDest || IsBadWritePtr(lpDest, sizeof(SPropValue)) ||
        FBadProp(lpSrc) || !lpMore)
        return MAPI_E_INVALID_PARAMETER;

    /* Shallow copy first, this is sufficient for properties without pointers */
    *lpDest = *lpSrc;

   switch (PROP_TYPE(lpSrc->ulPropTag))
    {
    case PT_CLSID:
        scode = lpMore(sizeof(GUID), lpOrig, (LPVOID*)&lpDest->Value.lpguid);
        if (SUCCEEDED(scode))
            memcpy(lpDest->Value.lpguid, lpSrc->Value.lpguid, sizeof(GUID));
        break;
    case PT_STRING8:
        ulLen = lstrlenA(lpSrc->Value.lpszA) + 1u;
        scode = lpMore(ulLen, lpOrig, (LPVOID*)&lpDest->Value.lpszA);
        if (SUCCEEDED(scode))
            memcpy(lpDest->Value.lpszA, lpSrc->Value.lpszA, ulLen);
        break;
    case PT_UNICODE:
        ulLen = (strlenW(lpSrc->Value.lpszW) + 1u) * sizeof(WCHAR);
        scode = lpMore(ulLen, lpOrig, (LPVOID*)&lpDest->Value.lpszW);
        if (SUCCEEDED(scode))
            memcpy(lpDest->Value.lpszW, lpSrc->Value.lpszW, ulLen);
        break;
    case PT_BINARY:
        scode = lpMore(lpSrc->Value.bin.cb, lpOrig, (LPVOID*)&lpDest->Value.bin.lpb);
        if (SUCCEEDED(scode))
            memcpy(lpDest->Value.bin.lpb, lpSrc->Value.bin.lpb, lpSrc->Value.bin.cb);
        break;
    default:
        if (lpSrc->ulPropTag & MV_FLAG)
        {
            ulLen = UlPropSize(lpSrc);

            if (PROP_TYPE(lpSrc->ulPropTag) == PT_MV_STRING8 ||
                PROP_TYPE(lpSrc->ulPropTag) == PT_MV_UNICODE)
            {
                /* UlPropSize doesn't account for the string pointers */
                ulLen += lpSrc->Value.MVszA.cValues * sizeof(char*);
            }
            else if (PROP_TYPE(lpSrc->ulPropTag) == PT_MV_BINARY)
            {
               /* UlPropSize doesn't account for the SBinary structs */
               ulLen += lpSrc->Value.MVbin.cValues * sizeof(SBinary);
            }

            lpDest->Value.MVi.cValues = lpSrc->Value.MVi.cValues;
            scode = lpMore(ulLen, lpOrig, (LPVOID*)&lpDest->Value.MVi.lpi);
            if (FAILED(scode))
                break;

            /* Note that we could allocate the memory for each value in a
             * multi-value property separately, however if an allocation failed
             * we would be left with a bunch of allocated memory, which (while
             * not really leaked) is unusable until lpOrig is freed. So for
             * strings and binary arrays we make a single allocation for all
             * of the data. This is consistent since individual elements can't
             * be freed anyway.
             */

            switch (PROP_TYPE(lpSrc->ulPropTag))
            {
            case PT_MV_STRING8:
            {
                char *lpNextStr = (char*)(lpDest->Value.MVszA.lppszA +
                                          lpDest->Value.MVszA.cValues);

                for (i = 0; i < lpSrc->Value.MVszA.cValues; i++)
                {
                    ULONG ulStrLen = lstrlenA(lpSrc->Value.MVszA.lppszA[i]) + 1u;

                    lpDest->Value.MVszA.lppszA[i] = lpNextStr;
                    memcpy(lpNextStr, lpSrc->Value.MVszA.lppszA[i], ulStrLen);
                    lpNextStr += ulStrLen;
                }
                break;
            }
            case PT_MV_UNICODE:
            {
                WCHAR *lpNextStr = (WCHAR*)(lpDest->Value.MVszW.lppszW +
                                            lpDest->Value.MVszW.cValues);

                for (i = 0; i < lpSrc->Value.MVszW.cValues; i++)
                {
                    ULONG ulStrLen = strlenW(lpSrc->Value.MVszW.lppszW[i]) + 1u;

                    lpDest->Value.MVszW.lppszW[i] = lpNextStr;
                    memcpy(lpNextStr, lpSrc->Value.MVszW.lppszW[i], ulStrLen * sizeof(WCHAR));
                    lpNextStr += ulStrLen;
                }
                break;
            }
            case PT_MV_BINARY:
            {
                LPBYTE lpNext = (LPBYTE)(lpDest->Value.MVbin.lpbin +
                                         lpDest->Value.MVbin.cValues);

                for (i = 0; i < lpSrc->Value.MVszW.cValues; i++)
                {
                    lpDest->Value.MVbin.lpbin[i].cb = lpSrc->Value.MVbin.lpbin[i].cb;
                    lpDest->Value.MVbin.lpbin[i].lpb = lpNext;
                    memcpy(lpNext, lpSrc->Value.MVbin.lpbin[i].lpb, lpDest->Value.MVbin.lpbin[i].cb);
                    lpNext += lpDest->Value.MVbin.lpbin[i].cb;
                }
                break;
            }
            default:
                /* No embedded pointers, just copy the data over */
                memcpy(lpDest->Value.MVi.lpi, lpSrc->Value.MVi.lpi, ulLen);
                break;
            }
            break;
        }
    }
    return scode;
}

/*************************************************************************
 * UlPropSize@4 (MAPI32.77)
 *
 * Determine the size of a property in bytes.
 *
 * PARAMS
 *  lpProp [I] Property to determine the size of
 *
 * RETURNS
 *  Success: The size of the value in lpProp.
 *  Failure: 0, if a multi-value (array) property is invalid or the type of lpProp
 *           is unknown.
 *
 * NOTES
 *  - The size returned does not include the size of the SPropValue struct
 *    or the size of the array of pointers for multi-valued properties that
 *    contain pointers (such as PT_MV_STRING8 or PT-MV_UNICODE).
 *  - MSDN incorrectly states that this function returns MAPI_E_CALL_FAILED if
 *    lpProp is invalid. In reality no checking is performed and this function
 *    will crash if passed an invalid property, or return 0 if the property
 *    type is PT_OBJECT or is unknown.
 */
ULONG WINAPI UlPropSize(LPSPropValue lpProp)
{
    ULONG ulRet = 1u, i;

    TRACE("(%p)\n", lpProp);

    switch (PROP_TYPE(lpProp->ulPropTag))
    {
    case PT_MV_I2:       ulRet = lpProp->Value.MVi.cValues;
    case PT_BOOLEAN:
    case PT_I2:          ulRet *= sizeof(USHORT);
                         break;
    case PT_MV_I4:       ulRet = lpProp->Value.MVl.cValues;
    case PT_ERROR:
    case PT_I4:          ulRet *= sizeof(LONG);
                         break;
    case PT_MV_I8:       ulRet = lpProp->Value.MVli.cValues;
    case PT_I8:          ulRet *= sizeof(LONG64);
                         break;
    case PT_MV_R4:       ulRet = lpProp->Value.MVflt.cValues;
    case PT_R4:          ulRet *= sizeof(float);
                         break;
    case PT_MV_APPTIME:
    case PT_MV_R8:       ulRet = lpProp->Value.MVdbl.cValues;
    case PT_APPTIME:
    case PT_R8:          ulRet *= sizeof(double);
                         break;
    case PT_MV_CURRENCY: ulRet = lpProp->Value.MVcur.cValues;
    case PT_CURRENCY:    ulRet *= sizeof(CY);
                         break;
    case PT_MV_SYSTIME:  ulRet = lpProp->Value.MVft.cValues;
    case PT_SYSTIME:     ulRet *= sizeof(FILETIME);
                         break;
    case PT_MV_CLSID:    ulRet = lpProp->Value.MVguid.cValues;
    case PT_CLSID:       ulRet *= sizeof(GUID);
                         break;
    case PT_MV_STRING8:  ulRet = 0u;
                         for (i = 0; i < lpProp->Value.MVszA.cValues; i++)
                             ulRet += (lstrlenA(lpProp->Value.MVszA.lppszA[i]) + 1u);
                         break;
    case PT_STRING8:     ulRet = lstrlenA(lpProp->Value.lpszA) + 1u;
                         break;
    case PT_MV_UNICODE:  ulRet = 0u;
                         for (i = 0; i < lpProp->Value.MVszW.cValues; i++)
                             ulRet += (strlenW(lpProp->Value.MVszW.lppszW[i]) + 1u);
                         ulRet *= sizeof(WCHAR);
                         break;
    case PT_UNICODE:     ulRet = (lstrlenW(lpProp->Value.lpszW) + 1u) * sizeof(WCHAR);
                         break;
    case PT_MV_BINARY:   ulRet = 0u;
                         for (i = 0; i < lpProp->Value.MVbin.cValues; i++)
                             ulRet += lpProp->Value.MVbin.lpbin[i].cb;
                         break;
    case PT_BINARY:      ulRet = lpProp->Value.bin.cb;
                         break;
    case PT_OBJECT:
    default:             ulRet = 0u;
                         break;
    }

    return ulRet;
}

/*************************************************************************
 * FPropContainsProp@12 (MAPI32.78)
 *
 * Find a property with a given property tag in a property array.
 *
 * PARAMS
 *  lpHaystack [I] Property to match to
 *  lpNeedle   [I] Property to find in lpHaystack
 *  ulFuzzy    [I] Flags controlling match type and strictness (FL_* flags from "mapidefs.h")
 *
 * RETURNS
 *  TRUE, if lpNeedle matches lpHaystack according to the criteria of ulFuzzy.
 *
 * NOTES
 *  Only property types of PT_STRING8 and PT_BINARY are handled by this function.
 */
BOOL WINAPI FPropContainsProp(LPSPropValue lpHaystack, LPSPropValue lpNeedle, ULONG ulFuzzy)
{
    TRACE("(%p,%p,0x%08x)\n", lpHaystack, lpNeedle, ulFuzzy);

    if (FBadProp(lpHaystack) || FBadProp(lpNeedle) ||
        PROP_TYPE(lpHaystack->ulPropTag) != PROP_TYPE(lpNeedle->ulPropTag))
        return FALSE;

    /* FIXME: Do later versions support Unicode as well? */

    if (PROP_TYPE(lpHaystack->ulPropTag) == PT_STRING8)
    {
        DWORD dwFlags = 0, dwNeedleLen, dwHaystackLen;

        if (ulFuzzy & FL_IGNORECASE)
            dwFlags |= NORM_IGNORECASE;
        if (ulFuzzy & FL_IGNORENONSPACE)
            dwFlags |= NORM_IGNORENONSPACE;
        if (ulFuzzy & FL_LOOSE)
            dwFlags |= (NORM_IGNORECASE|NORM_IGNORENONSPACE|NORM_IGNORESYMBOLS);

        dwNeedleLen = lstrlenA(lpNeedle->Value.lpszA);
        dwHaystackLen = lstrlenA(lpHaystack->Value.lpszA);

        if ((ulFuzzy & (FL_SUBSTRING|FL_PREFIX)) == FL_PREFIX)
        {
            if (dwNeedleLen <= dwHaystackLen &&
                CompareStringA(LOCALE_USER_DEFAULT, dwFlags,
                               lpHaystack->Value.lpszA, dwNeedleLen,
                               lpNeedle->Value.lpszA, dwNeedleLen) == CSTR_EQUAL)
                return TRUE; /* needle is a prefix of haystack */
        }
        else if ((ulFuzzy & (FL_SUBSTRING|FL_PREFIX)) == FL_SUBSTRING)
        {
            LPSTR (WINAPI *pStrChrFn)(LPCSTR,WORD) = StrChrA;
            LPSTR lpStr = lpHaystack->Value.lpszA;

            if (dwFlags & NORM_IGNORECASE)
                pStrChrFn = StrChrIA;

            while ((lpStr = pStrChrFn(lpStr, *lpNeedle->Value.lpszA)) != NULL)
            {
                dwHaystackLen -= (lpStr - lpHaystack->Value.lpszA);
                if (dwNeedleLen <= dwHaystackLen &&
                    CompareStringA(LOCALE_USER_DEFAULT, dwFlags,
                               lpStr, dwNeedleLen,
                               lpNeedle->Value.lpszA, dwNeedleLen) == CSTR_EQUAL)
                    return TRUE; /* needle is a substring of haystack */
                lpStr++;
            }
        }
        else if (CompareStringA(LOCALE_USER_DEFAULT, dwFlags,
                                lpHaystack->Value.lpszA, dwHaystackLen,
                                lpNeedle->Value.lpszA, dwNeedleLen) == CSTR_EQUAL)
            return TRUE; /* full string match */
    }
    else if (PROP_TYPE(lpHaystack->ulPropTag) == PT_BINARY)
    {
        if ((ulFuzzy & (FL_SUBSTRING|FL_PREFIX)) == FL_PREFIX)
        {
            if (lpNeedle->Value.bin.cb <= lpHaystack->Value.bin.cb &&
                !memcmp(lpNeedle->Value.bin.lpb, lpHaystack->Value.bin.lpb,
                        lpNeedle->Value.bin.cb))
                return TRUE; /* needle is a prefix of haystack */
        }
        else if ((ulFuzzy & (FL_SUBSTRING|FL_PREFIX)) == FL_SUBSTRING)
        {
            ULONG ulLen = lpHaystack->Value.bin.cb;
            LPBYTE lpb = lpHaystack->Value.bin.lpb;

            while ((lpb = memchr(lpb, *lpNeedle->Value.bin.lpb, ulLen)) != NULL)
            {
                ulLen = lpHaystack->Value.bin.cb - (lpb - lpHaystack->Value.bin.lpb);
                if (lpNeedle->Value.bin.cb <= ulLen &&
                    !memcmp(lpNeedle->Value.bin.lpb, lpb, lpNeedle->Value.bin.cb))
                    return TRUE; /* needle is a substring of haystack */
                lpb++;
            }
        }
        else if (!LPropCompareProp(lpHaystack, lpNeedle))
            return TRUE; /* needle is an exact match with haystack */

    }
    return FALSE;
}

/*************************************************************************
 * FPropCompareProp@12 (MAPI32.79)
 *
 * Compare two properties.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -