From 18b26d893a777e37e3066c20450c96c2380db0aa Mon Sep 17 00:00:00 2001 From: Jon Griffiths Date: Tue, 30 Nov 2004 17:38:52 +0000 Subject: [PATCH] Implement DllMain, DllCanUnloadNow, WrapProgress, MAPIGetDefaultMalloc, IsBadBoundedStringPtr, UFromSz, UlFromSzHex, CbOfEncoded. Add tests for the above. --- dlls/mapi32/Makefile.in | 3 +- dlls/mapi32/imalloc.c | 181 ++++++++++++++++++++++++++++++++++ dlls/mapi32/mapi32.spec | 14 +-- dlls/mapi32/mapi32_main.c | 38 +++++++ dlls/mapi32/tests/.cvsignore | 1 + dlls/mapi32/tests/Makefile.in | 1 + dlls/mapi32/tests/imalloc.c | 101 +++++++++++++++++++ dlls/mapi32/tests/util.c | 65 ++++++++++++ dlls/mapi32/util.c | 133 +++++++++++++++++++++++-- 9 files changed, 522 insertions(+), 15 deletions(-) create mode 100644 dlls/mapi32/imalloc.c create mode 100644 dlls/mapi32/tests/imalloc.c diff --git a/dlls/mapi32/Makefile.in b/dlls/mapi32/Makefile.in index 58426d2471..72d3da669f 100644 --- a/dlls/mapi32/Makefile.in +++ b/dlls/mapi32/Makefile.in @@ -3,10 +3,11 @@ TOPOBJDIR = ../.. SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = mapi32.dll -IMPORTS = shlwapi ole32 kernel32 +IMPORTS = shlwapi ole32 user32 kernel32 EXTRALIBS = -luuid $(LIBUNICODE) C_SRCS = \ + imalloc.c \ mapi32_main.c \ prop.c \ util.c diff --git a/dlls/mapi32/imalloc.c b/dlls/mapi32/imalloc.c new file mode 100644 index 0000000000..52ea5a72af --- /dev/null +++ b/dlls/mapi32/imalloc.c @@ -0,0 +1,181 @@ +/* + * MAPI Default IMalloc implementation + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winuser.h" +#include "winerror.h" +#include "winternl.h" +#include "objbase.h" +#include "shlwapi.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mapi); + +static const IMallocVtbl MAPI_IMalloc_vt; + +typedef struct +{ + const IMallocVtbl *lpVtbl; + LONG lRef; +} MAPI_IMALLOC; + +static MAPI_IMALLOC MAPI_IMalloc = { &MAPI_IMalloc_vt, 0u }; + +extern LONG MAPI_ObjectCount; /* In mapi32_main.c */ + +/************************************************************************* + * MAPIGetDefaultMalloc@0 (MAPI32.59) + * + * Get the default MAPI IMalloc interface. + * + * PARAMS + * None. + * + * RETURNS + * A pointer to the MAPI default allocator. + */ +LPMALLOC WINAPI MAPIGetDefaultMalloc(void) +{ + TRACE("()\n"); + + IMalloc_AddRef((LPMALLOC)&MAPI_IMalloc); + return (LPMALLOC)&MAPI_IMalloc; +} + +/************************************************************************** + * IMAPIMalloc_QueryInterface + */ +static HRESULT WINAPI IMAPIMalloc_fnQueryInterface(LPMALLOC iface, REFIID refiid, + LPVOID *ppvObj) +{ + TRACE("(%s,%p)\n", debugstr_guid(refiid), ppvObj); + + if (IsEqualIID(refiid, &IID_IUnknown) || + IsEqualIID(refiid, &IID_IMalloc)) + { + *ppvObj = (LPMALLOC) &MAPI_IMalloc; + TRACE("Returning IMalloc (%p)\n", *ppvObj); + return S_OK; + } + TRACE("Returning E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +/************************************************************************** + * IMAPIMalloc_AddRef + */ +static ULONG WINAPI IMAPIMalloc_fnAddRef(LPMALLOC iface) +{ + TRACE("(%p)\n", iface); + InterlockedIncrement(&MAPI_ObjectCount); + return 1u; +} + +/************************************************************************** + * IMAPIMalloc_Release + */ +static ULONG WINAPI IMAPIMalloc_fnRelease(LPMALLOC iface) +{ + TRACE("(%p)\n", iface); + InterlockedDecrement(&MAPI_ObjectCount); + return 1u; +} + +/************************************************************************** + * IMAPIMalloc_Alloc + */ +static LPVOID WINAPI IMAPIMalloc_fnAlloc(LPMALLOC iface, DWORD cb) +{ + TRACE("(%p)->(%ld)\n", iface, cb); + + return LocalAlloc(GMEM_FIXED, cb); +} + +/************************************************************************** + * IMAPIMalloc_Realloc + */ +static LPVOID WINAPI IMAPIMalloc_fnRealloc(LPMALLOC iface, LPVOID pv, DWORD cb) +{ + TRACE("(%p)->(%p, %ld)\n", iface, pv, cb); + + if (!pv) + return LocalAlloc(GMEM_FIXED, cb); + + if (cb) + return LocalReAlloc((HANDLE) pv, cb, GMEM_MOVEABLE); + + LocalFree((HANDLE) pv); + return NULL; +} + +/************************************************************************** + * IMAPIMalloc_Free + */ +static void WINAPI IMAPIMalloc_fnFree(LPMALLOC iface, LPVOID pv) +{ + TRACE("(%p)->(%p)\n", iface, pv); + LocalFree((HANDLE) pv); +} + +/************************************************************************** + * IMAPIMalloc_GetSize + */ +static DWORD WINAPI IMAPIMalloc_fnGetSize(LPMALLOC iface, LPVOID pv) +{ + TRACE("(%p)->(%p)\n", iface, pv); + return LocalSize((HANDLE) pv); +} + +/************************************************************************** + * IMAPIMalloc_DidAlloc + */ +static INT WINAPI IMAPIMalloc_fnDidAlloc(LPMALLOC iface, LPVOID pv) +{ + TRACE("(%p)->(%p)\n", iface, pv); + return -1; +} + +/************************************************************************** + * IMAPIMalloc_HeapMinimize + */ +static void WINAPI IMAPIMalloc_fnHeapMinimize(LPMALLOC iface) +{ + TRACE("(%p)\n", iface); +} + +static const IMallocVtbl MAPI_IMalloc_vt = +{ + IMAPIMalloc_fnQueryInterface, + IMAPIMalloc_fnAddRef, + IMAPIMalloc_fnRelease, + IMAPIMalloc_fnAlloc, + IMAPIMalloc_fnRealloc, + IMAPIMalloc_fnFree, + IMAPIMalloc_fnGetSize, + IMAPIMalloc_fnDidAlloc, + IMAPIMalloc_fnHeapMinimize +}; diff --git a/dlls/mapi32/mapi32.spec b/dlls/mapi32/mapi32.spec index 8f3dc0290a..b39c158bb5 100644 --- a/dlls/mapi32/mapi32.spec +++ b/dlls/mapi32/mapi32.spec @@ -17,7 +17,7 @@ 25 stub LAUNCHWIZARD 26 stub LaunchWizard@20 27 stub DllGetClassObject - 28 stub DllCanUnloadNow + 28 stdcall -private DllCanUnloadNow() MAPI32_DllCanUnloadNow 29 stub MAPIOpenFormMgr 30 stub MAPIOpenFormMgr@8 31 stub MAPIOpenLocalFormContainer @@ -26,7 +26,7 @@ 34 stdcall DeinitMapiUtil@0() DeinitMapiUtil 35 stub ScGenerateMuid@4 36 stub HrAllocAdviseSink@12 - 41 stub WrapProgress@20 + 41 stdcall WrapProgress@20(ptr ptr ptr ptr ptr) WrapProgress 42 stdcall HrThisThreadAdviseSink@8(ptr ptr) HrThisThreadAdviseSink 43 stub ScBinFromHexBounded@12 44 stdcall FBinFromHex@8(ptr ptr) FBinFromHex @@ -41,7 +41,7 @@ 53 stub EnableIdleRoutine@8 54 stub DeregisterIdleRoutine@4 55 stub ChangeIdleRoutine@28 - 59 stub MAPIGetDefaultMalloc@0 + 59 stdcall MAPIGetDefaultMalloc@0() MAPIGetDefaultMalloc 60 stub CreateIProp@24 61 stub CreateTable@36 62 stdcall MNLS_lstrlenW@4(wstr) MNLS_lstrlenW @@ -53,7 +53,7 @@ 68 stdcall MNLS_IsBadStringPtrW@8(ptr long) kernel32.IsBadStringPtrW 72 stdcall FEqualNames@8(ptr ptr) FEqualNames 73 stub WrapStoreEntryID@24 - 74 stub IsBadBoundedStringPtr@8 + 74 stdcall IsBadBoundedStringPtr@8(ptr long) IsBadBoundedStringPtr 75 stub HrQueryAllRows@24 76 stdcall PropCopyMore@16(ptr ptr ptr ptr) PropCopyMore 77 stdcall UlPropSize@4(ptr) UlPropSize @@ -74,7 +74,7 @@ 130 stdcall SzFindCh@8(str long) shlwapi.StrChrA 131 stdcall SzFindLastCh@8(str str long) shlwapi.StrRChrA 132 stdcall SzFindSz@8(str str) shlwapi.StrStrA -133 stub UFromSz@4 +133 stdcall UFromSz@4(str) UFromSz 135 stdcall HrGetOneProp@12(ptr long ptr) HrGetOneProp 136 stdcall HrSetOneProp@8(ptr ptr) HrSetOneProp 137 stdcall FPropExists@8(ptr long) FPropExists @@ -95,7 +95,7 @@ 152 stub OpenTnefStreamEx 153 stub GetTnefStreamCodepage@12 154 stub GetTnefStreamCodepage -155 stub UlFromSzHex@4 +155 stdcall UlFromSzHex@4(ptr) UlFromSzHex 156 stub UNKOBJ_ScAllocate@12 157 stub UNKOBJ_ScAllocateMore@16 158 stub UNKOBJ_Free@8 @@ -144,7 +144,7 @@ 204 stub EncodeID@12 205 stub FDecodeID@12 206 stub CchOfEncoding@4 -207 stub CbOfEncoded@4 +207 stdcall CbOfEncoded@4(ptr) CbOfEncoded 208 stub MAPISendDocuments 209 stdcall MAPILogon(long ptr ptr long long ptr) 210 stub MAPILogoff diff --git a/dlls/mapi32/mapi32_main.c b/dlls/mapi32/mapi32_main.c index ac6cc97c57..c9d0c00183 100644 --- a/dlls/mapi32/mapi32_main.c +++ b/dlls/mapi32/mapi32_main.c @@ -29,6 +29,44 @@ WINE_DEFAULT_DEBUG_CHANNEL(mapi); +LONG MAPI_ObjectCount = 0; + +/*********************************************************************** + * DllMain (MAPI32.init) + */ +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad) +{ + TRACE("(%p,0x%lx,%p)\n", hinstDLL, fdwReason, fImpLoad); + + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hinstDLL); + break; + case DLL_PROCESS_DETACH: + TRACE("DLL_PROCESS_DETACH: %ld objects remaining\n", MAPI_ObjectCount); + break; + } + return TRUE; +} + +/*********************************************************************** + * DllCanUnloadNow (MAPI32.28) + * + * Determine if this dll can be unloaded from the callers address space. + * + * PARAMS + * None. + * + * RETURNS + * S_OK, if the dll can be unloaded, + * S_FALSE, otherwise. + */ +HRESULT WINAPI MAPI32_DllCanUnloadNow(void) +{ + return MAPI_ObjectCount == 0 ? S_OK : S_FALSE; +} + HRESULT WINAPI MAPIInitialize ( LPVOID lpMapiInit ) { ERR("Stub\n"); diff --git a/dlls/mapi32/tests/.cvsignore b/dlls/mapi32/tests/.cvsignore index 526e3c4862..705f9ae32d 100644 --- a/dlls/mapi32/tests/.cvsignore +++ b/dlls/mapi32/tests/.cvsignore @@ -1,4 +1,5 @@ Makefile +imalloc.ok prop.ok testlist.c util.ok diff --git a/dlls/mapi32/tests/Makefile.in b/dlls/mapi32/tests/Makefile.in index 9b93876671..626788715a 100644 --- a/dlls/mapi32/tests/Makefile.in +++ b/dlls/mapi32/tests/Makefile.in @@ -7,6 +7,7 @@ IMPORTS = mapi32 EXTRALIBS = -luuid CTESTS = \ + imalloc.c \ prop.c \ util.c diff --git a/dlls/mapi32/tests/imalloc.c b/dlls/mapi32/tests/imalloc.c new file mode 100644 index 0000000000..7fb013fca3 --- /dev/null +++ b/dlls/mapi32/tests/imalloc.c @@ -0,0 +1,101 @@ +/* + * Unit test suite for MAPI IMalloc 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT +#include "wine/test.h" +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "winerror.h" +#include "winnt.h" +#include "mapiutil.h" + +static HMODULE hMapi32 = 0; + +static SCODE (WINAPI *pScInitMapiUtil)(ULONG); +static LPMALLOC (WINAPI *pMAPIGetDefaultMalloc)(void); + +static void test_IMalloc(void) +{ + LPVOID lpMem; + ULONG ulRef; + int iRet; + HRESULT hRet; + LPMALLOC lpMalloc; + LPVOID lpVoid; + + pMAPIGetDefaultMalloc = (void*)GetProcAddress(hMapi32, + "MAPIGetDefaultMalloc@0"); + if (!pMAPIGetDefaultMalloc) + return; + + lpMalloc = pMAPIGetDefaultMalloc(); + ok (lpMalloc != NULL, "iMAPIGetDefaultMalloc returned null\n"); + if (!lpMalloc) + return; + + lpVoid = NULL; + hRet = IMalloc_QueryInterface(lpMalloc, &IID_IUnknown, &lpVoid); + ok (hRet == S_OK && lpVoid != NULL, + "IID_IUnknown: exepected S_OK, non-null, got 0x%08lx, %p\n", + hRet, lpVoid); + + lpVoid = NULL; + hRet = IMalloc_QueryInterface(lpMalloc, &IID_IMalloc, &lpVoid); + ok (hRet == S_OK && lpVoid != NULL, + "IID_IIMalloc: exepected S_OK, non-null, got 0x%08lx, %p\n", + hRet, lpVoid); + + /* Prove that native mapi uses LocalAlloc/LocalFree */ + lpMem = IMalloc_Alloc(lpMalloc, 61); + ok (lpMem && IMalloc_GetSize(lpMalloc, lpMem) == + LocalSize((HANDLE)lpMem), + "Expected non-null, same size, got %p, %s size\n", lpMem, + lpMem ? "different" : "same"); + + iRet = IMalloc_DidAlloc(lpMalloc, lpMem); + ok (iRet == -1, "DidAlloc, expected -1. got %d\n", iRet); + + IMalloc_HeapMinimize(lpMalloc); + + LocalFree(lpMem); + + ulRef = IMalloc_AddRef(lpMalloc); + ok (ulRef == 1u, "AddRef expected 1, returned %ld\n", ulRef); + + ulRef = IMalloc_Release(lpMalloc); + ok (ulRef == 1u, "AddRef expected 1, returned %ld\n", ulRef); + + IMalloc_Release(lpMalloc); +} + +START_TEST(imalloc) +{ + hMapi32 = LoadLibraryA("mapi32.dll"); + + pScInitMapiUtil = (void*)GetProcAddress(hMapi32, "ScInitMapiUtil@4"); + if (!pScInitMapiUtil) + return; + pScInitMapiUtil(0); + + test_IMalloc(); +} diff --git a/dlls/mapi32/tests/util.c b/dlls/mapi32/tests/util.c index 8a070ad5bd..927008c2de 100644 --- a/dlls/mapi32/tests/util.c +++ b/dlls/mapi32/tests/util.c @@ -36,6 +36,10 @@ 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 UINT (WINAPI *pUFromSz)(LPCSTR); +static ULONG (WINAPI *pUlFromSzHex)(LPCSTR); +static ULONG (WINAPI *pCbOfEncoded)(LPCSTR); +static BOOL (WINAPI *pIsBadBoundedStringPtr)(LPCSTR,ULONG); static void test_SwapPword(void) { @@ -107,6 +111,63 @@ static void test_HexFromBin(void) ok(bOk == TRUE, "FBinFromHex: Result differs\n"); } +static void test_UFromSz(void) +{ + pUFromSz = (void*)GetProcAddress(hMapi32, "UFromSz@4"); + if (!pUFromSz) + return; + + ok(pUFromSz("105679") == 105679u, + "UFromSz: expected 105679, got %d\n", pUFromSz("105679")); + + ok(pUFromSz(" 4") == 0, "UFromSz: exected 0. got %d\n", + pUFromSz(" 4")); +} + +static void test_UlFromSzHex(void) +{ + pUlFromSzHex = (void*)GetProcAddress(hMapi32, "UlFromSzHex@4"); + if (!pUlFromSzHex) + return; + + ok(pUlFromSzHex("fF") == 0xffu, + "UlFromSzHex: expected 0xff, got 0x%lx\n", pUlFromSzHex("fF")); + + ok(pUlFromSzHex(" c") == 0, "UlFromSzHex: exected 0x0. got 0x%lx\n", + pUlFromSzHex(" c")); +} + +static void test_CbOfEncoded(void) +{ + char buff[129]; + size_t i; + + pCbOfEncoded = (void*)GetProcAddress(hMapi32, "CbOfEncoded@4"); + if (!pCbOfEncoded) + return; + + for (i = 0; i < sizeof(buff) - 1; i++) + { + ULONG ulRet, ulExpected = (((i | 3) >> 2) + 1) * 3; + + memset(buff, '\0', sizeof(buff)); + memset(buff, '?', i); + ulRet = pCbOfEncoded(buff); + ok(ulRet == ulExpected, "CbOfEncoded(length %d): expected %ld, got %ld\n", + i, ulExpected, ulRet); + } +} + +static void test_IsBadBoundedStringPtr(void) +{ + pIsBadBoundedStringPtr = (void*)GetProcAddress(hMapi32, "IsBadBoundedStringPtr@8"); + if (!pIsBadBoundedStringPtr) + return; + + ok(pIsBadBoundedStringPtr(NULL, 0) == TRUE, "IsBadBoundedStringPtr: expected TRUE\n"); + ok(pIsBadBoundedStringPtr("TEST", 4) == TRUE, "IsBadBoundedStringPtr: expected TRUE\n"); + ok(pIsBadBoundedStringPtr("TEST", 5) == FALSE, "IsBadBoundedStringPtr: expected FALSE\n"); +} START_TEST(util) { @@ -120,4 +181,8 @@ START_TEST(util) test_SwapPword(); test_SwapPlong(); test_HexFromBin(); + test_UFromSz(); + test_UlFromSzHex(); + test_CbOfEncoded(); + test_IsBadBoundedStringPtr(); } diff --git a/dlls/mapi32/util.c b/dlls/mapi32/util.c index 72da46f229..ee158d47c9 100644 --- a/dlls/mapi32/util.c +++ b/dlls/mapi32/util.c @@ -23,10 +23,10 @@ #define COBJMACROS #define NONAMELESSUNION #define NONAMELESSSTRUCT - #include "windef.h" #include "winbase.h" #include "winreg.h" +#include "winuser.h" #include "winerror.h" #include "winternl.h" #include "objbase.h" @@ -38,6 +38,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(mapi); +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 }; + /************************************************************************** * ScInitMapiUtil (MAPI32.33) * @@ -203,6 +209,15 @@ ULONG WINAPI MAPIFreeBuffer(LPVOID lpBuffer) return S_OK; } +/************************************************************************** + * WrapProgress@20 (MAPI32.41) + */ +HRESULT WINAPI WrapProgress(PVOID unk1, PVOID unk2, PVOID unk3, PVOID unk4, PVOID unk5) +{ + /* Native does not implement this function */ + return MAPI_E_NO_SUPPORT; +} + /************************************************************************* * HrThisThreadAdviseSink@8 (MAPI32.42) * @@ -251,11 +266,6 @@ HRESULT WINAPI HrThisThreadAdviseSink(LPMAPIADVISESINK lpSink, LPMAPIADVISESINK* */ 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); @@ -457,6 +467,26 @@ BOOL WINAPI FEqualNames(LPMAPINAMEID lpName1, LPMAPINAMEID lpName2) return lpName1->Kind.lID == lpName2->Kind.lID ? TRUE : FALSE; } +/************************************************************************** + * IsBadBoundedStringPtr@8 (MAPI32.71) + * + * Determine if a string pointer is valid. + * + * PARAMS + * lpszStr [I] String to check + * ulLen [I] Maximum length of lpszStr + * + * RETURNS + * TRUE, if lpszStr is invalid or longer than ulLen, + * FALSE, otherwise. + */ +BOOL WINAPI IsBadBoundedStringPtr(LPCSTR lpszStr, ULONG ulLen) +{ + if (!lpszStr || IsBadStringPtrA(lpszStr, -1) || strlen(lpszStr) >= ulLen) + return TRUE; + return FALSE; +} + /************************************************************************** * FtAddFt@16 (MAPI32.121) * @@ -545,7 +575,7 @@ LONGLONG WINAPI MAPI32_FtMulDwDw(DWORD dwLeft, DWORD dwRight) LONGLONG WINAPI MAPI32_FtNegFt(FILETIME ft) { LONGLONG *p = (LONGLONG*)&ft; - + return - *p; } @@ -597,6 +627,39 @@ ULONG WINAPI UlRelease(void *lpUnk) return IUnknown_Release((LPUNKNOWN)lpUnk); } +/************************************************************************** + * UFromSz@4 (MAPI32.133) + * + * Read an integer from a string + * + * PARAMS + * lpszStr [I] String to read the integer from. + * + * RETURNS + * Success: The integer read from lpszStr. + * Failure: 0, if the first character in lpszStr is not 0-9. + * + * NOTES + * This function does not accept whitespace and stops at the first non-digit + * character. + */ +UINT WINAPI UFromSz(LPCSTR lpszStr) +{ + ULONG ulRet = 0; + + TRACE("(%s)\n", debugstr_a(lpszStr)); + + if (lpszStr) + { + while (*lpszStr >= '0' && *lpszStr <= '9') + { + ulRet = ulRet * 10 + (*lpszStr - '0'); + lpszStr = CharNextA(lpszStr); + } + } + return ulRet; +} + /************************************************************************* * OpenStreamOnFile@24 (MAPI32.147) * @@ -649,6 +712,62 @@ HRESULT WINAPI OpenStreamOnFile(LPALLOCATEBUFFER lpAlloc, LPFREEBUFFER lpFree, return hRet; } +/************************************************************************* + * UlFromSzHex@4 (MAPI32.155) + * + * Read an integer from a hexadecimal string. + * + * PARAMS + * lpSzHex [I] String containing the hexidecimal number to read + * + * RETURNS + * Success: The number represented by lpszHex. + * Failure: 0, if lpszHex does not contain a hex string. + * + * NOTES + * This function does not accept whitespace and stops at the first non-hex + * character. + */ +ULONG WINAPI UlFromSzHex(LPCWSTR lpszHex) +{ + LPSTR lpStr = (LPSTR)lpszHex; + ULONG ulRet = 0; + + TRACE("(%s)\n", debugstr_a(lpStr)); + + 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) + break; + + ulRet = ulRet * 16 + ((digitsToHex[lpStr[0] - '0'] << 4) | digitsToHex[lpStr[1] - '0']); + lpStr += 2; + } + return ulRet; +} + +/************************************************************************* + * CbOfEncoded@4 (MAPI32.207) + * + * Return the length of an encoded string. + * + * PARAMS + * lpSzEnc [I] Encoded string to get the length of. + * + * RETURNS + * The length of the encoded string in bytes. + */ +ULONG WINAPI CbOfEncoded(LPCSTR lpszEnc) +{ + ULONG ulRet = 0; + + TRACE("(%s)\n", debugstr_a(lpszEnc)); + + if (lpszEnc) + ulRet = (((strlen(lpszEnc) | 3) >> 2) + 1) * 3; + return ulRet; +} /************************************************************************* * cmc_query_configuration (MAPI32.235) -- 2.33.8