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

📄 prop.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 5 页
字号:
            ulBytes += ulPropSize;
    }
    if (pcBytes)
        *pcBytes = ulBytes;

    return S_OK;
}

/*************************************************************************
 * ScCopyProps@16 (MAPI32.171)
 *
 * Copy an array of property values into a buffer suited for serialisation.
 *
 * PARAMS
 *  cValues   [I] Number of properties in lpProps
 *  lpProps   [I] Property array to copy
 *  lpDst     [O] Destination for the serialised data
 *  lpCount   [O] If non-NULL, destination for the number of bytes of data written to lpDst
 *
 * RETURNS
 *  Success: S_OK. lpDst contains the serialised data from lpProps.
 *  Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid.
 *
 * NOTES
 *  The resulting property value array is stored in a contiguous block starting at lpDst.
 */
SCODE WINAPI ScCopyProps(int cValues, LPSPropValue lpProps, LPVOID lpDst, ULONG *lpCount)
{
    LPSPropValue lpDest = (LPSPropValue)lpDst;
    char *lpDataDest = (char *)(lpDest + cValues);
    ULONG ulLen, i;
    int iter;

    TRACE("(%d,%p,%p,%p)\n", cValues, lpProps, lpDst, lpCount);

    if (!lpProps || cValues < 0 || !lpDest)
        return MAPI_E_INVALID_PARAMETER;

    memcpy(lpDst, lpProps, cValues * sizeof(SPropValue));

    for (iter = 0; iter < cValues; iter++)
    {
        switch (PROP_TYPE(lpProps->ulPropTag))
        {
        case PT_CLSID:
            lpDest->Value.lpguid = (LPGUID)lpDataDest;
            memcpy(lpDest->Value.lpguid, lpProps->Value.lpguid, sizeof(GUID));
            lpDataDest += sizeof(GUID);
            break;
        case PT_STRING8:
            ulLen = lstrlenA(lpProps->Value.lpszA) + 1u;
            lpDest->Value.lpszA = lpDataDest;
            memcpy(lpDest->Value.lpszA, lpProps->Value.lpszA, ulLen);
            lpDataDest += ulLen;
            break;
        case PT_UNICODE:
            ulLen = (strlenW(lpProps->Value.lpszW) + 1u) * sizeof(WCHAR);
            lpDest->Value.lpszW = (LPWSTR)lpDataDest;
            memcpy(lpDest->Value.lpszW, lpProps->Value.lpszW, ulLen);
            lpDataDest += ulLen;
            break;
        case PT_BINARY:
            lpDest->Value.bin.lpb = (LPBYTE)lpDataDest;
            memcpy(lpDest->Value.bin.lpb, lpProps->Value.bin.lpb, lpProps->Value.bin.cb);
            lpDataDest += lpProps->Value.bin.cb;
            break;
        default:
            if (lpProps->ulPropTag & MV_FLAG)
            {
                lpDest->Value.MVi.cValues = lpProps->Value.MVi.cValues;
                /* Note: Assignment uses lppszA but covers all cases by union aliasing */
                lpDest->Value.MVszA.lppszA = (char**)lpDataDest;

                switch (PROP_TYPE(lpProps->ulPropTag))
                {
                case PT_MV_STRING8:
                {
                    lpDataDest += lpProps->Value.MVszA.cValues * sizeof(char *);

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

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

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

                        lpDest->Value.MVszW.lppszW[i] = (LPWSTR)lpDataDest;
                        memcpy(lpDataDest, lpProps->Value.MVszW.lppszW[i], ulStrLen);
                        lpDataDest += ulStrLen;
                    }
                    break;
                }
                case PT_MV_BINARY:
                {
                    lpDataDest += lpProps->Value.MVszW.cValues * sizeof(SBinary);

                    for (i = 0; i < lpProps->Value.MVszW.cValues; i++)
                    {
                        lpDest->Value.MVbin.lpbin[i].cb = lpProps->Value.MVbin.lpbin[i].cb;
                        lpDest->Value.MVbin.lpbin[i].lpb = (LPBYTE)lpDataDest;
                        memcpy(lpDataDest, lpProps->Value.MVbin.lpbin[i].lpb, lpDest->Value.MVbin.lpbin[i].cb);
                        lpDataDest += lpDest->Value.MVbin.lpbin[i].cb;
                    }
                    break;
                }
                default:
                    /* No embedded pointers, just copy the data over */
                    ulLen = UlPropSize(lpProps);
                    memcpy(lpDest->Value.MVi.lpi, lpProps->Value.MVi.lpi, ulLen);
                    lpDataDest += ulLen;
                    break;
                }
                break;
            }
        }
        lpDest++;
        lpProps++;
    }
    if (lpCount)
        *lpCount = lpDataDest - (char *)lpDst;

    return S_OK;
}

/*************************************************************************
 * ScRelocProps@20 (MAPI32.172)
 *
 * Relocate the pointers in an array of property values after it has been copied.
 *
 * PARAMS
 *  cValues   [I] Number of properties in lpProps
 *  lpProps   [O] Property array to relocate the pointers in.
 *  lpOld     [I] Position where the data was copied from
 *  lpNew     [I] Position where the data was copied to
 *  lpCount   [O] If non-NULL, destination for the number of bytes of data at lpDst
 *
 * RETURNS
 *  Success: S_OK. Any pointers in lpProps are relocated.
 *  Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid.
 *
 * NOTES
 *  MSDN states that this function can be used for serialisation by passing
 *  NULL as either lpOld or lpNew, thus converting any pointers in lpProps
 *  between offsets and pointers. This does not work in native (it crashes),
 *  and cannot be made to work in Wine because the original interface design
 *  is deficient. The only use left for this function is to remap pointers
 *  in a contiguous property array that has been copied with memcpy() to
 *  another memory location.
 */
SCODE WINAPI ScRelocProps(int cValues, LPSPropValue lpProps, LPVOID lpOld,
                          LPVOID lpNew, ULONG *lpCount)
{
    static const BOOL bBadPtr = TRUE; /* Windows bug - Assumes source is bad */
    LPSPropValue lpDest = (LPSPropValue)lpProps;
    ULONG ulCount = cValues * sizeof(SPropValue);
    ULONG ulLen, i;
    int iter;

    TRACE("(%d,%p,%p,%p,%p)\n", cValues, lpProps, lpOld, lpNew, lpCount);

    if (!lpProps || cValues < 0 || !lpOld || !lpNew)
        return MAPI_E_INVALID_PARAMETER;

    /* The reason native doesn't work as MSDN states is that it assumes that
     * the lpProps pointer contains valid pointers. This is obviously not
     * true if the array is being read back from serialisation (the pointers
     * are just offsets). Native can't actually work converting the pointers to
     * offsets either, because it converts any array pointers to offsets then
     * _dereferences the offset_ in order to convert the array elements!
     *
     * The code below would handle both cases except that the design of this
     * function makes it impossible to know when the pointers in lpProps are
     * valid. If both lpOld and lpNew are non-NULL, native reads the pointers
     * after converting them, so we must do the same. It seems this
     * functionality was never tested by MS.
     */

#define RELOC_PTR(p) (((char*)(p)) - (char*)lpOld + (char*)lpNew)

    for (iter = 0; iter < cValues; iter++)
    {
        switch (PROP_TYPE(lpDest->ulPropTag))
        {
        case PT_CLSID:
            lpDest->Value.lpguid = (LPGUID)RELOC_PTR(lpDest->Value.lpguid);
            ulCount += sizeof(GUID);
            break;
        case PT_STRING8:
            ulLen = bBadPtr ? 0 : lstrlenA(lpDest->Value.lpszA) + 1u;
            lpDest->Value.lpszA = (LPSTR)RELOC_PTR(lpDest->Value.lpszA);
            if (bBadPtr)
                ulLen = lstrlenA(lpDest->Value.lpszA) + 1u;
            ulCount += ulLen;
            break;
        case PT_UNICODE:
            ulLen = bBadPtr ? 0 : (lstrlenW(lpDest->Value.lpszW) + 1u) * sizeof(WCHAR);
            lpDest->Value.lpszW = (LPWSTR)RELOC_PTR(lpDest->Value.lpszW);
            if (bBadPtr)
                ulLen = (strlenW(lpDest->Value.lpszW) + 1u) * sizeof(WCHAR);
            ulCount += ulLen;
            break;
        case PT_BINARY:
            lpDest->Value.bin.lpb = (LPBYTE)RELOC_PTR(lpDest->Value.bin.lpb);
            ulCount += lpDest->Value.bin.cb;
            break;
        default:
            if (lpDest->ulPropTag & MV_FLAG)
            {
                /* Since we have to access the array elements, don't map the
                 * array unless it is invalid (otherwise, map it at the end)
                 */
                if (bBadPtr)
                    lpDest->Value.MVszA.lppszA = (LPSTR*)RELOC_PTR(lpDest->Value.MVszA.lppszA);

                switch (PROP_TYPE(lpProps->ulPropTag))
                {
                case PT_MV_STRING8:
                {
                    ulCount += lpDest->Value.MVszA.cValues * sizeof(char *);

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

                        lpDest->Value.MVszA.lppszA[i] = (LPSTR)RELOC_PTR(lpDest->Value.MVszA.lppszA[i]);
                        if (bBadPtr)
                            ulStrLen = lstrlenA(lpDest->Value.MVszA.lppszA[i]) + 1u;
                        ulCount += ulStrLen;
                    }
                    break;
                }
                case PT_MV_UNICODE:
                {
                    ulCount += lpDest->Value.MVszW.cValues * sizeof(WCHAR *);

                    for (i = 0; i < lpDest->Value.MVszW.cValues; i++)
                    {
                        ULONG ulStrLen = bBadPtr ? 0 : (strlenW(lpDest->Value.MVszW.lppszW[i]) + 1u) * sizeof(WCHAR);

                        lpDest->Value.MVszW.lppszW[i] = (LPWSTR)RELOC_PTR(lpDest->Value.MVszW.lppszW[i]);
                        if (bBadPtr)
                            ulStrLen = (strlenW(lpDest->Value.MVszW.lppszW[i]) + 1u) * sizeof(WCHAR);
                        ulCount += ulStrLen;
                    }
                    break;
                }
                case PT_MV_BINARY:
                {
                    ulCount += lpDest->Value.MVszW.cValues * sizeof(SBinary);

                    for (i = 0; i < lpDest->Value.MVszW.cValues; i++)
                    {
                        lpDest->Value.MVbin.lpbin[i].lpb = (LPBYTE)RELOC_PTR(lpDest->Value.MVbin.lpbin[i].lpb);
                        ulCount += lpDest->Value.MVbin.lpbin[i].cb;
                    }
                    break;
                }
                default:
                    ulCount += UlPropSize(lpDest);
                    break;
                }
                if (!bBadPtr)
                    lpDest->Value.MVszA.lppszA = (LPSTR*)RELOC_PTR(lpDest->Value.MVszA.lppszA);
                break;
            }
        }
        lpDest++;
    }
    if (lpCount)
        *lpCount = ulCount;

    return S_OK;
}

/*************************************************************************
 * LpValFindProp@12 (MAPI32.173)
 *
 * Find a property with a given property id in a property array.
 *
 * PARAMS
 *  ulPropTag [I] Property tag containing property id to find
 *  cValues   [I] Number of properties in lpProps
 *  lpProps   [I] Property array to search
 *
 * RETURNS
 *  A pointer to the matching property, or NULL if none was found.
 *
 * NOTES
 *  This function matches only on the property id and does not care if the
 *  property types differ.
 */
LPSPropValue WINAPI LpValFindProp(ULONG ulPropTag, ULONG cValues, LPSPropValue lpProps)
{
    TRACE("(%d,%d,%p)\n", ulPropTag, cValues, lpProps);

    if (lpProps && cValues)
    {
        ULONG i;
        for (i = 0; i < cValues; i++)
        {
            if (PROP_ID(ulPropTag) == PROP_ID(lpProps[i].ulPropTag))
                return &lpProps[i];
        }
    }
    return NULL;
}

/*************************************************************************
 * ScDupPropset@16 (MAPI32.174)
 *
 * Duplicate a property value array into a contiguous block of memory.
 *
 * PARAMS
 *  cValues   [I] Number of properties in lpProps
 *  lpProps   [I] Property array to duplicate
 *  lpAlloc   [I] Memory allocation function, use MAPIAllocateBuffer()
 *  lpNewProp [O] Destination for the newly duplicated property value array
 *
 * RETURNS
 *  Success: S_OK. *lpNewProp contains the duplicated array.
 *  Failure: MAPI_E_INVALID_PARAMETER, if any parameter is invalid,
 *           MAPI_E_NOT_ENOUGH_MEMORY, if memory allocation fails.
 */
SCODE WINAPI ScDupPropset(int cValues, LPSPropValue lpProps,
                          LPALLOCATEBUFFER lpAlloc, LPSPropValue *lpNewProp)
{
    ULONG ulCount;
    SCODE sc;

    TRACE("(%d,%p,%p,%p)\n", cValues, lpProps, lpAlloc, lpNewProp);

    sc = ScCountProps(cValues, lpProps, &ulCount);
    if (SUCCEEDED(sc))
    {
        sc = lpAlloc(ulCount, (LPVOID*)lpNewProp);
        if (SUCCEEDED(sc))
            sc = ScCopyProps(cValues, lpProps, *lpNewProp, &ulCount);
    }
    return sc;
}

/*************************************************************************
 * FBadRglpszA@8 (MAPI32.175)
 *
 * Determine if an array of strings is invalid
 *
 * PARAMS
 *  lppszStrs [I] Array of strings to check
 *  ulCount   [I] Number of strings in lppszStrs
 *
 * RETURNS
 *  TRUE, if lppszStrs is invalid, FALSE otherwise.
 */
BOOL WINAPI FBadRglpszA(LPSTR *lppszStrs, ULONG ulCount)
{
    ULONG i;

    TRACE("(%p,%d)\n", lppszStrs, ulCount);

    if (!ulCount)
        return FALSE;

    if (!lppszStrs || IsBadReadPtr(lppszStrs, ulCount * sizeof(LPWSTR)))
        return TRUE;

    for (i = 0; i < ulCount; i++)
    {
        if (!lppszStrs[i] || IsBadStringPtrA(lppszStrs[i], -1))
            return TRUE;
    }
    return FALSE;
}

⌨️ 快捷键说明

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