diff --git a/dlls/mapi32/mapi32.spec b/dlls/mapi32/mapi32.spec index 28d70fba13d..8f3dc0290a6 100644 --- a/dlls/mapi32/mapi32.spec +++ b/dlls/mapi32/mapi32.spec @@ -29,8 +29,8 @@ 41 stub WrapProgress@20 42 stdcall HrThisThreadAdviseSink@8(ptr ptr) HrThisThreadAdviseSink 43 stub ScBinFromHexBounded@12 - 44 stub FBinFromHex@8 - 45 stub HexFromBin@12 + 44 stdcall FBinFromHex@8(ptr ptr) FBinFromHex + 45 stdcall HexFromBin@12(ptr long ptr) HexFromBin 46 stub BuildDisplayTable@40 47 stdcall SwapPlong@8(ptr long) SwapPlong 48 stdcall SwapPword@8(ptr long) SwapPword @@ -51,7 +51,7 @@ 66 stdcall MNLS_MultiByteToWideChar@24(long long str long ptr long) kernel32.MultiByteToWideChar 67 stdcall MNLS_WideCharToMultiByte@32(long long wstr long ptr long ptr ptr) kernel32.WideCharToMultiByte 68 stdcall MNLS_IsBadStringPtrW@8(ptr long) kernel32.IsBadStringPtrW - 72 stub FEqualNames@8 + 72 stdcall FEqualNames@8(ptr ptr) FEqualNames 73 stub WrapStoreEntryID@24 74 stub IsBadBoundedStringPtr@8 75 stub HrQueryAllRows@24 @@ -75,12 +75,12 @@ 131 stdcall SzFindLastCh@8(str str long) shlwapi.StrRChrA 132 stdcall SzFindSz@8(str str) shlwapi.StrStrA 133 stub UFromSz@4 -135 stub HrGetOneProp@12 -136 stub HrSetOneProp@8 -137 stub FPropExists@8 +135 stdcall HrGetOneProp@12(ptr long ptr) HrGetOneProp +136 stdcall HrSetOneProp@8(ptr ptr) HrSetOneProp +137 stdcall FPropExists@8(ptr long) FPropExists 138 stdcall PpropFindProp@12(ptr long long) PpropFindProp -139 stub FreePadrlist@4 -140 stub FreeProws@4 +139 stdcall FreePadrlist@4(ptr) FreePadrlist +140 stdcall FreeProws@4(ptr) FreeProws 141 stub HrSzFromEntryID@12 142 stub HrEntryIDFromSz@12 143 stub HrComposeEID@28 @@ -111,7 +111,7 @@ 171 stdcall ScCopyProps@16(long ptr ptr ptr) ScCopyProps 172 stdcall ScRelocProps@20(long ptr ptr ptr ptr) ScRelocProps 173 stdcall LpValFindProp@12(long long ptr) LpValFindProp -174 stub ScDupPropset@16 +174 stdcall ScDupPropset@16(long ptr ptr ptr) ScDupPropset 175 stdcall FBadRglpszA@8(ptr long) FBadRglpszA 176 stdcall FBadRglpszW@8(ptr long) FBadRglpszW 177 stdcall FBadRowSet@4(ptr) FBadRowSet diff --git a/dlls/mapi32/prop.c b/dlls/mapi32/prop.c index f7572c8db2a..b13cb738bef 100644 --- a/dlls/mapi32/prop.c +++ b/dlls/mapi32/prop.c @@ -154,7 +154,7 @@ SCODE WINAPI PropCopyMore(LPSPropValue lpDest, LPSPropValue lpSrc, { 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; @@ -513,6 +513,107 @@ LONG WINAPI LPropCompareProp(LPSPropValue lpPropLeft, LPSPropValue lpPropRight) return 0; } +/************************************************************************* + * HrGetOneProp@8 (MAPI32.135) + * + * Get a property value from an IMAPIProp object. + * + * PARAMS + * lpIProp [I] IMAPIProp object to get the property value in + * ulPropTag [I] Property tag of the property to get + * lppProp [O] Destination for the returned property + * + * RETURNS + * Success: S_OK. *lppProp contains the property value requested. + * Failure: MAPI_E_NOT_FOUND, if no property value has the tag given by ulPropTag. + */ +HRESULT WINAPI HrGetOneProp(LPMAPIPROP lpIProp, ULONG ulPropTag, LPSPropValue *lppProp) +{ + SPropTagArray pta; + ULONG ulCount; + HRESULT hRet; + + TRACE("(%p,%ld,%p)\n", lpIProp, ulPropTag, lppProp); + + pta.cValues = 1u; + pta.aulPropTag[0] = ulPropTag; + hRet = IMAPIProp_GetProps(lpIProp, &pta, 0u, &ulCount, lppProp); + if (hRet == MAPI_W_ERRORS_RETURNED) + { + MAPIFreeBuffer(*lppProp); + *lppProp = NULL; + hRet = MAPI_E_NOT_FOUND; + } + return hRet; +} + +/************************************************************************* + * HrSetOneProp@8 (MAPI32.136) + * + * Set a property value in an IMAPIProp object. + * + * PARAMS + * lpIProp [I] IMAPIProp object to set the property value in + * lpProp [I] Property value to set + * + * RETURNS + * Success: S_OK. The value in lpProp is set in lpIProp. + * Failure: An error result from IMAPIProp_SetProps(). + */ +HRESULT WINAPI HrSetOneProp(LPMAPIPROP lpIProp, LPSPropValue lpProp) +{ + TRACE("(%p,%p)\n", lpIProp, lpProp); + + return IMAPIProp_SetProps(lpIProp, 1u, lpProp, NULL); +} + +/************************************************************************* + * FPropExists@8 (MAPI32.137) + * + * Find a property with a given property tag in an IMAPIProp object. + * + * PARAMS + * lpIProp [I] IMAPIProp object to find the property tag in + * ulPropTag [I] Property tag to find + * + * RETURNS + * TRUE, if ulPropTag matches a property held in lpIProp, + * FALSE, otherwise. + * + * NOTES + * if ulPropTag has a property type of PT_UNSPECIFIED, then only the property + * Ids need to match for a successful match to occur. + */ + BOOL WINAPI FPropExists(LPMAPIPROP lpIProp, ULONG ulPropTag) + { + BOOL bRet = FALSE; + + TRACE("(%p,%ld)\n", lpIProp, ulPropTag); + + if (lpIProp) + { + LPSPropTagArray lpTags; + ULONG i; + + if (FAILED(IMAPIProp_GetPropList(lpIProp, 0u, &lpTags))) + return FALSE; + + for (i = 0; i < lpTags->cValues; i++) + { + if (!FBadPropTag(lpTags->aulPropTag[i]) && + (lpTags->aulPropTag[i] == ulPropTag || + (PROP_TYPE(ulPropTag) == PT_UNSPECIFIED && + PROP_ID(lpTags->aulPropTag[i]) == lpTags->aulPropTag[i]))) + { + bRet = TRUE; + break; + } + } + MAPIFreeBuffer(lpTags); + } + return bRet; +} + /************************************************************************* * PpropFindProp@12 (MAPI32.138) * @@ -549,6 +650,51 @@ LPSPropValue WINAPI PpropFindProp(LPSPropValue lpProps, ULONG cValues, ULONG ulP return NULL; } +/************************************************************************* + * FreePadrlist@4 (MAPI32.139) + * + * Free the memory used by an address book list. + * + * PARAMS + * lpAddrs [I] Address book list to free + * + * RETURNS + * Nothing. + */ +VOID WINAPI FreePadrlist(LPADRLIST lpAddrs) +{ + TRACE("(%p)\n", lpAddrs); + + /* Structures are binary compatible; use the same implementation */ + return FreeProws((LPSRowSet)lpAddrs); +} + +/************************************************************************* + * FreeProws@4 (MAPI32.140) + * + * Free the memory used by a row set. + * + * PARAMS + * lpRowSet [I] Row set to free + * + * RETURNS + * Nothing. + */ +VOID WINAPI FreeProws(LPSRowSet lpRowSet) +{ + TRACE("(%p)\n", lpRowSet); + + if (lpRowSet) + { + ULONG i; + + for (i = 0; i < lpRowSet->cRows; i++) + MAPIFreeBuffer(lpRowSet->aRow[i].lpProps); + + MAPIFreeBuffer(lpRowSet); + } +} + /************************************************************************* * ScCountProps@12 (MAPI32.170) * @@ -623,7 +769,7 @@ SCODE WINAPI ScCountProps(INT iCount, LPSPropValue lpProps, ULONG *pcBytes) } if (pcBytes) *pcBytes = ulBytes; - + return S_OK; } @@ -649,16 +795,16 @@ SCODE WINAPI ScCopyProps(int cValues, LPSPropValue lpProps, LPVOID lpDst, ULONG { LPSPropValue lpDest = (LPSPropValue)lpDst; char *lpDataDest = (char *)(lpDest + cValues); - ULONG ulLen, i; - + ULONG ulLen, i, 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 (i = 0; i < cValues; i++) + + for (iter = 0; iter < cValues; iter++) { switch (PROP_TYPE(lpProps->ulPropTag)) { @@ -696,11 +842,11 @@ SCODE WINAPI ScCopyProps(int cValues, LPSPropValue lpProps, LPVOID lpDst, ULONG 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; @@ -710,28 +856,28 @@ SCODE WINAPI ScCopyProps(int cValues, LPSPropValue lpProps, LPVOID lpDst, ULONG 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: @@ -749,10 +895,10 @@ SCODE WINAPI ScCopyProps(int cValues, LPSPropValue lpProps, LPVOID lpDst, ULONG } if (lpCount) *lpCount = lpDataDest - (char *)lpDst; - + return S_OK; } - + /************************************************************************* * ScRelocProps@20 (MAPI32.172) * @@ -784,10 +930,10 @@ SCODE WINAPI ScRelocProps(int cValues, LPSPropValue lpProps, LPVOID lpOld, static const BOOL bBadPtr = TRUE; /* Windows bug - Assumes source is bad */ LPSPropValue lpDest = (LPSPropValue)lpProps; ULONG ulCount = cValues * sizeof(SPropValue); - ULONG ulLen, i; - + ULONG ulLen, i, iter; + TRACE("(%d,%p,%p,%p,%p)\n", cValues, lpProps, lpOld, lpNew, lpCount); - + if (!lpProps || cValues < 0 || !lpOld || !lpNew) return MAPI_E_INVALID_PARAMETER; @@ -801,13 +947,13 @@ SCODE WINAPI ScRelocProps(int cValues, LPSPropValue lpProps, LPVOID lpOld, * 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. Its seems this + * after converting them, so we must do the same. Its seems this * functionality was never tested by MS. */ - + #define RELOC_PTR(p) (((char*)(p)) - (char*)lpOld + (char*)lpNew) - - for (i = 0; i < cValues; i++) + + for (iter = 0; iter < cValues; iter++) { switch (PROP_TYPE(lpDest->ulPropTag)) { @@ -841,7 +987,7 @@ SCODE WINAPI ScRelocProps(int cValues, LPSPropValue lpProps, LPVOID lpOld, */ if (bBadPtr) lpDest->Value.MVszA.lppszA = (LPSTR*)RELOC_PTR(lpDest->Value.MVszA.lppszA); - + switch (PROP_TYPE(lpProps->ulPropTag)) { case PT_MV_STRING8: @@ -851,7 +997,7 @@ SCODE WINAPI ScRelocProps(int cValues, LPSPropValue lpProps, LPVOID lpOld, 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; @@ -862,27 +1008,27 @@ SCODE WINAPI ScRelocProps(int cValues, LPSPropValue lpProps, LPVOID lpOld, 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: @@ -898,7 +1044,7 @@ SCODE WINAPI ScRelocProps(int cValues, LPSPropValue lpProps, LPVOID lpOld, } if (lpCount) *lpCount = ulCount; - + return S_OK; } @@ -935,6 +1081,40 @@ LPSPropValue WINAPI LpValFindProp(ULONG ulPropTag, ULONG cValues, LPSPropValue l return NULL; } +/************************************************************************* + * ScDupPropset@16 (MAPI32.174) + * + * Duplicate a property value array into a contigous 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) * @@ -955,7 +1135,7 @@ BOOL WINAPI FBadRglpszA(LPSTR *lppszStrs, ULONG ulCount) if (!ulCount) return FALSE; - + if (!lppszStrs || IsBadReadPtr(lppszStrs, ulCount * sizeof(LPWSTR))) return TRUE; @@ -980,7 +1160,7 @@ BOOL WINAPI FBadRglpszW(LPWSTR *lppszStrs, ULONG ulCount) if (!ulCount) return FALSE; - + if (!lppszStrs || IsBadReadPtr(lppszStrs, ulCount * sizeof(LPWSTR))) return TRUE; diff --git a/dlls/mapi32/tests/util.c b/dlls/mapi32/tests/util.c index 4aaf98da0f2..8a070ad5bdf 100644 --- a/dlls/mapi32/tests/util.c +++ b/dlls/mapi32/tests/util.c @@ -34,6 +34,8 @@ static HMODULE hMapi32 = 0; static SCODE (WINAPI *pScInitMapiUtil)(ULONG); static void (WINAPI *pSwapPword)(PUSHORT,ULONG); static void (WINAPI *pSwapPlong)(PULONG,ULONG); +static void (WINAPI *pHexFromBin)(LPBYTE,int,LPWSTR); +static void (WINAPI *pFBinFromHex)(LPWSTR,LPBYTE); static void test_SwapPword(void) { @@ -69,10 +71,47 @@ static void test_SwapPlong(void) longs[0], longs[1], longs[2]); } +static void test_HexFromBin(void) +{ + static const char res[] = { "000102030405060708090A0B0C0D0E0F101112131415161" + "718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B" + "3C3D3E3F404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F6" + "06162636465666768696A6B6C6D6E6F707172737475767778797A7B7C7D7E7F8081828384" + "85868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A" + "9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCD" + "CECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0F1F" + "2F3F4F5F6F7F8F9FAFBFCFDFE\0X" }; + BYTE data[255]; + WCHAR strw[256]; + BOOL bOk; + int i; + + pHexFromBin = (void*)GetProcAddress(hMapi32, "HexFromBin@12"); + pFBinFromHex = (void*)GetProcAddress(hMapi32, "FBinFromHex@8"); + if (!pHexFromBin || !pFBinFromHex) + return; + + for (i = 0; i < 255; i++) + data[i] = i; + memset(strw, 'X', sizeof(strw)); + pHexFromBin(data, sizeof(data), strw); + + ok(memcmp(strw, res, sizeof(res) - 1) == 0, "HexFromBin: Result differs\n"); + + memset(data, 0, sizeof(data)); + pFBinFromHex((LPWSTR)res, data); + bOk = TRUE; + for (i = 0; i < 255; i++) + if (data[i] != i) + bOk = FALSE; + ok(bOk == TRUE, "FBinFromHex: Result differs\n"); +} + + START_TEST(util) { hMapi32 = LoadLibraryA("mapi32.dll"); - + pScInitMapiUtil = (void*)GetProcAddress(hMapi32, "ScInitMapiUtil@4"); if (!pScInitMapiUtil) return; @@ -80,4 +119,5 @@ START_TEST(util) test_SwapPword(); test_SwapPlong(); + test_HexFromBin(); } diff --git a/dlls/mapi32/util.c b/dlls/mapi32/util.c index 53651b29a92..f58b8668706 100644 --- a/dlls/mapi32/util.c +++ b/dlls/mapi32/util.c @@ -227,6 +227,85 @@ HRESULT WINAPI HrThisThreadAdviseSink(LPMAPIADVISESINK lpSink, LPMAPIADVISESINK* return S_OK; } +/************************************************************************* + * FBinFromHex (MAPI32.44) + * + * Create an array of binary data from a string. + * + * PARAMS + * lpszHex [I] String to convert to binary data + * lpOut [O] Destination for resulting binary data + * + * RETURNS + * Success: TRUE. lpOut contains the decoded binary data. + * Failure: FALSE, if lpszHex does not represent a binary string. + * + * NOTES + * - lpOut must be at least half the length of lpszHex in bytes. + * - Although the Mapi headers prototype this function as both + * Ascii and Unicode, there is only one (Ascii) implementation. This + * means that lpszHex is treated as an Ascii string (i.e. a single NUL + * character in the byte stream terminates the string). + */ +BOOL WINAPI FBinFromHex(LPWSTR lpszHex, LPBYTE lpOut) +{ + static const BYTE digitsToHex[] = { + 0,1,2,3,4,5,6,7,8,9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,10,11,12,13,14,15, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,10,11,12,13, + 14,15 }; + LPSTR lpStr = (LPSTR)lpszHex; + + TRACE("(%p,%p)\n", lpszHex, lpOut); + + while (*lpStr) + { + if (lpStr[0] < '0' || lpStr[0] > 'f' || digitsToHex[lpStr[0] - '0'] == 0xff || + lpStr[1] < '0' || lpStr[1] > 'f' || digitsToHex[lpStr[1] - '0'] == 0xff) + return FALSE; + + *lpOut++ = (digitsToHex[lpStr[0] - '0'] << 4) | digitsToHex[lpStr[1] - '0']; + lpStr += 2; + } + return TRUE; +} + +/************************************************************************* + * HexFromBin (MAPI32.45) + * + * Create a string from an array of binary data. + * + * PARAMS + * lpHex [I] Binary data to convert to string + * iCount [I] Length of lpHex in bytes + * lpszOut [O] Destination for resulting hex string + * + * RETURNS + * Nothing. + * + * NOTES + * - lpszOut must be at least 2 * iCount + 1 bytes characters long. + * - Although the Mapi headers prototype this function as both + * Ascii and Unicode, there is only one (Ascii) implementation. This + * means that the resulting string is not properly NUL terminated + * if the caller expects it to be a Unicode string. + */ +void WINAPI HexFromBin(LPBYTE lpHex, int iCount, LPWSTR lpszOut) +{ + static const char hexDigits[] = { "0123456789ABCDEF" }; + LPSTR lpStr = (LPSTR)lpszOut; + + TRACE("(%p,%d,%p)\n", lpHex, iCount, lpszOut); + + while (iCount-- > 0) + { + *lpStr++ = hexDigits[*lpHex >> 4]; + *lpStr++ = hexDigits[*lpHex & 0xf]; + lpHex++; + } + *lpStr = '\0'; +} + /************************************************************************* * SwapPlong@8 (MAPI32.47) * @@ -348,6 +427,33 @@ INT WINAPI MNLS_CompareStringW(DWORD dwCp, LPCWSTR lpszLeft, LPCWSTR lpszRight) return ret < 0 ? CSTR_LESS_THAN : ret ? CSTR_GREATER_THAN : CSTR_EQUAL; } +/************************************************************************** + * FEqualNames@8 (MAPI32.72) + * + * Compare two Mapi names. + * + * PARAMS + * lpName1 [I] First name to compare to lpName2 + * lpName2 [I] Second name to compare to lpName1 + * + * RETURNS + * TRUE, if the names are the same, + * FALSE, Otherwise. + */ +BOOL WINAPI FEqualNames(LPMAPINAMEID lpName1, LPMAPINAMEID lpName2) +{ + TRACE("(%p,%p)\n", lpName1, lpName2); + + if (!lpName1 || !lpName2 || + !IsEqualGUID(lpName1->lpguid, lpName2->lpguid) || + lpName1->ulKind != lpName2->ulKind) + return FALSE; + + if (lpName1->ulKind == MNID_STRING) + return !strcmpW(lpName1->Kind.lpwstrName, lpName2->Kind.lpwstrName); + + return lpName1->Kind.lID == lpName2->Kind.lID ? TRUE : FALSE; +} /************************************************************************** * FtAddFt@16 (MAPI32.121) @@ -364,7 +470,7 @@ INT WINAPI MNLS_CompareStringW(DWORD dwCp, LPCWSTR lpszLeft, LPCWSTR lpszRight) LONGLONG WINAPI MAPI32_FtAddFt(FILETIME ftLeft, FILETIME ftRight) { LONGLONG *pl = (LONGLONG*)&ftLeft, *pr = (LONGLONG*)&ftRight; - + return *pl + *pr; } @@ -374,7 +480,7 @@ LONGLONG WINAPI MAPI32_FtAddFt(FILETIME ftLeft, FILETIME ftRight) * Subtract two FILETIME's together. * * PARAMS - * ftLeft [I] Initial FILETIME + * ftLeft [I] Initial FILETIME * ftRight [I] FILETIME to subtract from ftLeft * * RETURNS @@ -383,7 +489,7 @@ LONGLONG WINAPI MAPI32_FtAddFt(FILETIME ftLeft, FILETIME ftRight) LONGLONG WINAPI MAPI32_FtSubFt(FILETIME ftLeft, FILETIME ftRight) { LONGLONG *pl = (LONGLONG*)&ftLeft, *pr = (LONGLONG*)&ftRight; - + return *pr - *pl; } @@ -402,10 +508,10 @@ LONGLONG WINAPI MAPI32_FtSubFt(FILETIME ftLeft, FILETIME ftRight) LONGLONG WINAPI MAPI32_FtMulDw(DWORD dwLeft, FILETIME ftRight) { LONGLONG *pr = (LONGLONG*)&ftRight; - + return (LONGLONG)dwLeft * (*pr); } - + /************************************************************************** * FtMulDwDw@8 (MAPI32.125) *