[MAPI32_WINETEST]
authorChristoph von Wittich <christoph_vw@reactos.org>
Fri, 5 Mar 2010 18:41:30 +0000 (18:41 +0000)
committerChristoph von Wittich <christoph_vw@reactos.org>
Fri, 5 Mar 2010 18:41:30 +0000 (18:41 +0000)
sync mapi32_winetest to wine 1.1.39

svn path=/trunk/; revision=45882

rostests/winetests/mapi32/imalloc.c
rostests/winetests/mapi32/prop.c
rostests/winetests/mapi32/util.c

index 485180c..341155c 100644 (file)
@@ -45,11 +45,18 @@ static void test_IMalloc(void)
     pMAPIGetDefaultMalloc = (void*)GetProcAddress(hMapi32,
                                                   "MAPIGetDefaultMalloc@0");
     if (!pMAPIGetDefaultMalloc)
     pMAPIGetDefaultMalloc = (void*)GetProcAddress(hMapi32,
                                                   "MAPIGetDefaultMalloc@0");
     if (!pMAPIGetDefaultMalloc)
+    {
+        win_skip("MAPIGetDefaultMalloc is not available\n");
         return;
         return;
+    }
 
     lpMalloc = pMAPIGetDefaultMalloc();
 
     lpMalloc = pMAPIGetDefaultMalloc();
+    ok(lpMalloc != NULL, "Expected MAPIGetDefaultMalloc to return non-NULL\n");
     if (!lpMalloc)
     if (!lpMalloc)
+    {
+        skip("MAPIGetDefaultMalloc failed\n");
         return;
         return;
+    }
 
     lpVoid = NULL;
     hRet = IMalloc_QueryInterface(lpMalloc, &IID_IUnknown, &lpVoid);
 
     lpVoid = NULL;
     hRet = IMalloc_QueryInterface(lpMalloc, &IID_IUnknown, &lpVoid);
index 237134b..15d6d98 100644 (file)
@@ -32,6 +32,7 @@
 static HMODULE hMapi32 = 0;
 
 static SCODE        (WINAPI *pScInitMapiUtil)(ULONG);
 static HMODULE hMapi32 = 0;
 
 static SCODE        (WINAPI *pScInitMapiUtil)(ULONG);
+static void         (WINAPI *pDeinitMapiUtil)(void);
 static SCODE        (WINAPI *pPropCopyMore)(LPSPropValue,LPSPropValue,ALLOCATEMORE*,LPVOID);
 static ULONG        (WINAPI *pUlPropSize)(LPSPropValue);
 static BOOL         (WINAPI *pFPropContainsProp)(LPSPropValue,LPSPropValue,ULONG);
 static SCODE        (WINAPI *pPropCopyMore)(LPSPropValue,LPSPropValue,ALLOCATEMORE*,LPVOID);
 static ULONG        (WINAPI *pUlPropSize)(LPSPropValue);
 static BOOL         (WINAPI *pFPropContainsProp)(LPSPropValue,LPSPropValue,ULONG);
@@ -53,26 +54,49 @@ static SCODE        (WINAPI *pCreateIProp)(LPCIID,ALLOCATEBUFFER*,ALLOCATEMORE*,
                                            FREEBUFFER*,LPVOID,LPPROPDATA*);
 static SCODE        (WINAPI *pMAPIAllocateBuffer)(ULONG, LPVOID);
 static SCODE        (WINAPI *pMAPIAllocateMore)(ULONG, LPVOID, LPVOID);
                                            FREEBUFFER*,LPVOID,LPPROPDATA*);
 static SCODE        (WINAPI *pMAPIAllocateBuffer)(ULONG, LPVOID);
 static SCODE        (WINAPI *pMAPIAllocateMore)(ULONG, LPVOID, LPVOID);
+static SCODE        (WINAPI *pMAPIInitialize)(LPVOID);
 static SCODE        (WINAPI *pMAPIFreeBuffer)(LPVOID);
 static SCODE        (WINAPI *pMAPIFreeBuffer)(LPVOID);
+static void         (WINAPI *pMAPIUninitialize)(void);
 
 static BOOL InitFuncPtrs(void)
 {
     hMapi32 = LoadLibraryA("mapi32.dll");
 
 
 static BOOL InitFuncPtrs(void)
 {
     hMapi32 = LoadLibraryA("mapi32.dll");
 
+    pPropCopyMore = (void*)GetProcAddress(hMapi32, "PropCopyMore@16");
+    pUlPropSize = (void*)GetProcAddress(hMapi32, "UlPropSize@4");
+    pFPropContainsProp = (void*)GetProcAddress(hMapi32, "FPropContainsProp@12");
+    pFPropCompareProp = (void*)GetProcAddress(hMapi32, "FPropCompareProp@12");
+    pLPropCompareProp = (void*)GetProcAddress(hMapi32, "LPropCompareProp@8");
+    pPpropFindProp = (void*)GetProcAddress(hMapi32, "PpropFindProp@12");
+    pScCountProps = (void*)GetProcAddress(hMapi32, "ScCountProps@12");
+    pScCopyProps = (void*)GetProcAddress(hMapi32, "ScCopyProps@16");
+    pScRelocProps = (void*)GetProcAddress(hMapi32, "ScRelocProps@20");
+    pLpValFindProp = (void*)GetProcAddress(hMapi32, "LpValFindProp@12");
+    pFBadRglpszA = (void*)GetProcAddress(hMapi32, "FBadRglpszA@8");
+    pFBadRglpszW = (void*)GetProcAddress(hMapi32, "FBadRglpszW@8");
+    pFBadRowSet = (void*)GetProcAddress(hMapi32, "FBadRowSet@4");
+    pFBadPropTag = (void*)GetProcAddress(hMapi32, "FBadPropTag@4");
+    pFBadRow = (void*)GetProcAddress(hMapi32, "FBadRow@4");
+    pFBadProp = (void*)GetProcAddress(hMapi32, "FBadProp@4");
+    pFBadColumnSet = (void*)GetProcAddress(hMapi32, "FBadColumnSet@4");
+    pCreateIProp = (void*)GetProcAddress(hMapi32, "CreateIProp@24");
+
     pScInitMapiUtil = (void*)GetProcAddress(hMapi32, "ScInitMapiUtil@4");
     pScInitMapiUtil = (void*)GetProcAddress(hMapi32, "ScInitMapiUtil@4");
+    pDeinitMapiUtil = (void*)GetProcAddress(hMapi32, "DeinitMapiUtil@0");
     pMAPIAllocateBuffer = (void*)GetProcAddress(hMapi32, "MAPIAllocateBuffer");
     pMAPIAllocateMore = (void*)GetProcAddress(hMapi32, "MAPIAllocateMore");
     pMAPIFreeBuffer = (void*)GetProcAddress(hMapi32, "MAPIFreeBuffer");
     pMAPIAllocateBuffer = (void*)GetProcAddress(hMapi32, "MAPIAllocateBuffer");
     pMAPIAllocateMore = (void*)GetProcAddress(hMapi32, "MAPIAllocateMore");
     pMAPIFreeBuffer = (void*)GetProcAddress(hMapi32, "MAPIFreeBuffer");
-    if(pScInitMapiUtil && pMAPIAllocateBuffer && pMAPIAllocateMore && pMAPIFreeBuffer)
-        return TRUE;
-    else
-        return FALSE;
+    pMAPIInitialize = (void*)GetProcAddress(hMapi32, "MAPIInitialize");
+    pMAPIUninitialize = (void*)GetProcAddress(hMapi32, "MAPIUninitialize");
+
+    return pMAPIAllocateBuffer && pMAPIAllocateMore && pMAPIFreeBuffer &&
+           pScInitMapiUtil && pDeinitMapiUtil;
 }
 
 }
 
+/* FIXME: Test PT_I2, PT_I4, PT_R4, PT_R8, PT_CURRENCY, PT_APPTIME, PT_SYSTIME,
+ * PT_ERROR, PT_BOOLEAN, PT_I8, and PT_CLSID. */
 static ULONG ptTypes[] = {
 static ULONG ptTypes[] = {
-    PT_I2, PT_I4, PT_R4, PT_R8, PT_CURRENCY, PT_APPTIME, PT_SYSTIME,
-    PT_ERROR, PT_BOOLEAN, PT_I8, PT_CLSID, PT_STRING8, PT_BINARY,
-    PT_UNICODE
+    PT_STRING8, PT_BINARY, PT_UNICODE
 };
 
 static inline int strcmpW(const WCHAR *str1, const WCHAR *str2)
 };
 
 static inline int strcmpW(const WCHAR *str1, const WCHAR *str2)
@@ -89,18 +113,27 @@ static void test_PropCopyMore(void)
     ULONG i;
     SCODE scode;
 
     ULONG i;
     SCODE scode;
 
-    pPropCopyMore = (void*)GetProcAddress(hMapi32, "PropCopyMore@16");
-
     if (!pPropCopyMore)
     if (!pPropCopyMore)
+    {
+        win_skip("PropCopyMore is not available\n");
         return;
         return;
+    }
 
 
-    scode = pMAPIAllocateBuffer(sizeof(LPSPropValue), lpDest);
+    scode = pMAPIAllocateBuffer(sizeof(SPropValue), &lpDest);
+    ok(scode == S_OK, "Expected MAPIAllocateBuffer to return S_OK, got 0x%x\n", scode);
     if (FAILED(scode))
     if (FAILED(scode))
+    {
+        skip("MAPIAllocateBuffer failed\n");
         return;
         return;
+    }
 
 
-    scode = pMAPIAllocateMore(sizeof(LPSPropValue), lpDest, lpSrc);
+    scode = pMAPIAllocateMore(sizeof(SPropValue), lpDest, &lpSrc);
+    ok(scode == S_OK, "Expected MAPIAllocateMore to return S_OK, got 0x%x\n", scode);
     if (FAILED(scode))
     if (FAILED(scode))
+    {
+        skip("MAPIAllocateMore failed\n");
         return;
         return;
+    }
 
     for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
     {
 
     for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
     {
@@ -148,7 +181,8 @@ static void test_PropCopyMore(void)
     }
 
     /* Since all allocations are linked, freeing lpDest frees everything */
     }
 
     /* Since all allocations are linked, freeing lpDest frees everything */
-    pMAPIFreeBuffer(lpDest);
+    scode = pMAPIFreeBuffer(lpDest);
+    ok(scode == S_OK, "Expected MAPIFreeBuffer to return S_OK, got 0x%x\n", scode);
 }
 
 static void test_UlPropSize(void)
 }
 
 static void test_UlPropSize(void)
@@ -160,10 +194,11 @@ static void test_UlPropSize(void)
     SBinary buffbin[2];
     ULONG pt, exp, res;
 
     SBinary buffbin[2];
     ULONG pt, exp, res;
 
-    pUlPropSize = (void*)GetProcAddress(hMapi32, "UlPropSize@4");
-
     if (!pUlPropSize)
     if (!pUlPropSize)
+    {
+        win_skip("UlPropSize is not available\n");
         return;
         return;
+    }
 
     for (pt = 0; pt < PROP_ID_INVALID; pt++)
     {
 
     for (pt = 0; pt < PROP_ID_INVALID; pt++)
     {
@@ -257,10 +292,11 @@ static void test_FPropContainsProp(void)
     ULONG pt;
     BOOL bRet;
 
     ULONG pt;
     BOOL bRet;
 
-    pFPropContainsProp = (void*)GetProcAddress(hMapi32, "FPropContainsProp@12");
-
     if (!pFPropContainsProp)
     if (!pFPropContainsProp)
+    {
+        win_skip("FPropContainsProp is not available\n");
         return;
         return;
+    }
 
     /* Ensure that only PT_STRING8 and PT_BINARY are handled */
     for (pt = 0; pt < PROP_ID_INVALID; pt++)
 
     /* Ensure that only PT_STRING8 and PT_BINARY are handled */
     for (pt = 0; pt < PROP_ID_INVALID; pt++)
@@ -406,10 +442,11 @@ static void test_FPropCompareProp(void)
     ULONG i, j;
     BOOL bRet, bExp;
 
     ULONG i, j;
     BOOL bRet, bExp;
 
-    pFPropCompareProp = (void*)GetProcAddress(hMapi32, "FPropCompareProp@12");
-
     if (!pFPropCompareProp)
     if (!pFPropCompareProp)
+    {
+        win_skip("FPropCompareProp is not available\n");
         return;
         return;
+    }
 
     lbuffa[1] = '\0';
     rbuffa[1] = '\0';
 
     lbuffa[1] = '\0';
     rbuffa[1] = '\0';
@@ -535,10 +572,11 @@ static void test_LPropCompareProp(void)
     ULONG i, j;
     INT iRet, iExp;
 
     ULONG i, j;
     INT iRet, iExp;
 
-    pLPropCompareProp = (void*)GetProcAddress(hMapi32, "LPropCompareProp@8");
-
     if (!pLPropCompareProp)
     if (!pLPropCompareProp)
+    {
+        win_skip("LPropCompareProp is not available\n");
         return;
         return;
+    }
 
     lbuffa[1] = '\0';
     rbuffa[1] = '\0';
 
     lbuffa[1] = '\0';
     rbuffa[1] = '\0';
@@ -640,10 +678,11 @@ static void test_PpropFindProp(void)
     SPropValue pvProp, *pRet;
     ULONG i;
 
     SPropValue pvProp, *pRet;
     ULONG i;
 
-    pPpropFindProp = (void*)GetProcAddress(hMapi32, "PpropFindProp@12");
-
     if (!pPpropFindProp)
     if (!pPpropFindProp)
+    {
+        win_skip("PpropFindProp is not available\n");
         return;
         return;
+    }
 
     for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
     {
 
     for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
     {
@@ -679,10 +718,11 @@ static void test_ScCountProps(void)
     ULONG pt, exp, ulRet;
     int success = 1;
 
     ULONG pt, exp, ulRet;
     int success = 1;
 
-    pScCountProps = (void*)GetProcAddress(hMapi32, "ScCountProps@12");
-
     if (!pScCountProps)
     if (!pScCountProps)
+    {
+        win_skip("ScCountProps is not available\n");
         return;
         return;
+    }
 
     for (pt = 0; pt < PROP_ID_INVALID && success; pt++)
     {
 
     for (pt = 0; pt < PROP_ID_INVALID && success; pt++)
     {
@@ -814,11 +854,11 @@ static void test_ScCopyRelocProps(void)
     ULONG ulCount;
     SCODE sc;
 
     ULONG ulCount;
     SCODE sc;
 
-    pScCopyProps = (void*)GetProcAddress(hMapi32, "ScCopyProps@16");
-    pScRelocProps = (void*)GetProcAddress(hMapi32, "ScRelocProps@20");
-
     if (!pScCopyProps || !pScRelocProps)
     if (!pScCopyProps || !pScRelocProps)
+    {
+        win_skip("SPropValue copy functions are not available\n");
         return;
         return;
+    }
 
     pvProp.ulPropTag = PROP_TAG(PT_MV_STRING8, 1u);
 
 
     pvProp.ulPropTag = PROP_TAG(PT_MV_STRING8, 1u);
 
@@ -877,10 +917,11 @@ static void test_LpValFindProp(void)
     SPropValue pvProp, *pRet;
     ULONG i;
 
     SPropValue pvProp, *pRet;
     ULONG i;
 
-    pLpValFindProp = (void*)GetProcAddress(hMapi32, "LpValFindProp@12");
-
     if (!pLpValFindProp)
     if (!pLpValFindProp)
+    {
+        win_skip("LpValFindProp is not available\n");
         return;
         return;
+    }
 
     for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
     {
 
     for (i = 0; i < sizeof(ptTypes)/sizeof(ptTypes[0]); i++)
     {
@@ -912,9 +953,11 @@ static void test_FBadRglpszA(void)
     static CHAR szString[] = "A String";
     BOOL bRet;
 
     static CHAR szString[] = "A String";
     BOOL bRet;
 
-    pFBadRglpszA = (void*)GetProcAddress(hMapi32, "FBadRglpszA@8");
     if (!pFBadRglpszA)
     if (!pFBadRglpszA)
+    {
+        win_skip("FBadRglpszA is not available\n");
         return;
         return;
+    }
 
     bRet = pFBadRglpszA(NULL, 10);
     ok(bRet == TRUE, "FBadRglpszA(Null): expected TRUE, got FALSE\n");
 
     bRet = pFBadRglpszA(NULL, 10);
     ok(bRet == TRUE, "FBadRglpszA(Null): expected TRUE, got FALSE\n");
@@ -937,9 +980,11 @@ static void test_FBadRglpszW(void)
     static WCHAR szString[] = { 'A',' ','S','t','r','i','n','g','\0' };
     BOOL bRet;
 
     static WCHAR szString[] = { 'A',' ','S','t','r','i','n','g','\0' };
     BOOL bRet;
 
-    pFBadRglpszW = (void*)GetProcAddress(hMapi32, "FBadRglpszW@8");
     if (!pFBadRglpszW)
     if (!pFBadRglpszW)
+    {
+        win_skip("FBadRglpszW is not available\n");
         return;
         return;
+    }
 
     bRet = pFBadRglpszW(NULL, 10);
     ok(bRet == TRUE, "FBadRglpszW(Null): expected TRUE, got FALSE\n");
 
     bRet = pFBadRglpszW(NULL, 10);
     ok(bRet == TRUE, "FBadRglpszW(Null): expected TRUE, got FALSE\n");
@@ -960,9 +1005,11 @@ static void test_FBadRowSet(void)
 {
     ULONG ulRet;
 
 {
     ULONG ulRet;
 
-    pFBadRowSet = (void*)GetProcAddress(hMapi32, "FBadRowSet@4");
     if (!pFBadRowSet)
     if (!pFBadRowSet)
+    {
+        win_skip("FBadRowSet is not available\n");
         return;
         return;
+    }
 
     ulRet = pFBadRowSet(NULL);
     ok(ulRet != 0, "FBadRow(null): Expected non-zero, got 0\n");
 
     ulRet = pFBadRowSet(NULL);
     ok(ulRet != 0, "FBadRow(null): Expected non-zero, got 0\n");
@@ -974,9 +1021,11 @@ static void test_FBadPropTag(void)
 {
     ULONG pt, res;
 
 {
     ULONG pt, res;
 
-    pFBadPropTag = (void*)GetProcAddress(hMapi32, "FBadPropTag@4");
     if (!pFBadPropTag)
     if (!pFBadPropTag)
+    {
+        win_skip("FBadPropTag is not available\n");
         return;
         return;
+    }
 
     for (pt = 0; pt < PROP_ID_INVALID; pt++)
     {
 
     for (pt = 0; pt < PROP_ID_INVALID; pt++)
     {
@@ -1006,9 +1055,11 @@ static void test_FBadRow(void)
 {
     ULONG ulRet;
 
 {
     ULONG ulRet;
 
-    pFBadRow = (void*)GetProcAddress(hMapi32, "FBadRow@4");
     if (!pFBadRow)
     if (!pFBadRow)
+    {
+        win_skip("FBadRow is not available\n");
         return;
         return;
+    }
 
     ulRet = pFBadRow(NULL);
     ok(ulRet != 0, "FBadRow(null): Expected non-zero, got 0\n");
 
     ulRet = pFBadRow(NULL);
     ok(ulRet != 0, "FBadRow(null): Expected non-zero, got 0\n");
@@ -1023,9 +1074,11 @@ static void test_FBadProp(void)
     ULONG pt, res;
     SPropValue pv;
 
     ULONG pt, res;
     SPropValue pv;
 
-    pFBadProp = (void*)GetProcAddress(hMapi32, "FBadProp@4");
     if (!pFBadProp)
     if (!pFBadProp)
+    {
+        win_skip("FBadProp is not available\n");
         return;
         return;
+    }
 
     for (pt = 0; pt < PROP_ID_INVALID; pt++)
     {
 
     for (pt = 0; pt < PROP_ID_INVALID; pt++)
     {
@@ -1097,9 +1150,11 @@ static void test_FBadColumnSet(void)
     SPropTagArray pta;
     ULONG pt, res;
 
     SPropTagArray pta;
     ULONG pt, res;
 
-    pFBadColumnSet = (void*)GetProcAddress(hMapi32, "FBadColumnSet@4");
     if (!pFBadColumnSet)
     if (!pFBadColumnSet)
+    {
+        win_skip("FBadColumnSet is not available\n");
         return;
         return;
+    }
 
     res = pFBadColumnSet(NULL);
     ok(res != 0, "(null): Expected non-zero, got 0\n");
 
     res = pFBadColumnSet(NULL);
     ok(res != 0, "(null): Expected non-zero, got 0\n");
@@ -1157,10 +1212,11 @@ static void test_IProp(void)
     ULONG access[2], count;
     SCODE sc;
 
     ULONG access[2], count;
     SCODE sc;
 
-    pCreateIProp = (void*)GetProcAddress(hMapi32, "CreateIProp@24");
-
     if (!pCreateIProp)
     if (!pCreateIProp)
+    {
+        win_skip("CreateIProp is not available\n");
         return;
         return;
+    }
 
     memset(&tags, 0 , sizeof(tags));
 
 
     memset(&tags, 0 , sizeof(tags));
 
@@ -1390,7 +1446,17 @@ START_TEST(prop)
 
     test_PropCopyMore();
     test_UlPropSize();
 
     test_PropCopyMore();
     test_UlPropSize();
+
+    /* We call MAPIInitialize here for the benefit of native extended MAPI
+     * providers which crash in the FPropContainsProp tests when MAPIInitialize
+     * has not been called. Since MAPIInitialize is irrelevant for FPropContainsProp
+     * on Wine, we do not care whether MAPIInitialize succeeds. */
+    if (pMAPIInitialize)
+        ret = pMAPIInitialize(NULL);
     test_FPropContainsProp();
     test_FPropContainsProp();
+    if (pMAPIUninitialize && ret == S_OK)
+        pMAPIUninitialize();
+
     test_FPropCompareProp();
     test_LPropCompareProp();
     test_PpropFindProp();
     test_FPropCompareProp();
     test_LPropCompareProp();
     test_PpropFindProp();
@@ -1406,5 +1472,7 @@ START_TEST(prop)
     test_FBadColumnSet();
 
     test_IProp();
     test_FBadColumnSet();
 
     test_IProp();
+
+    pDeinitMapiUtil();
     FreeLibrary(hMapi32);
 }
     FreeLibrary(hMapi32);
 }
index feb2c6d..0edac07 100644 (file)
 static HMODULE hMapi32 = 0;
 
 static SCODE (WINAPI *pScInitMapiUtil)(ULONG);
 static HMODULE hMapi32 = 0;
 
 static SCODE (WINAPI *pScInitMapiUtil)(ULONG);
+static void  (WINAPI *pDeinitMapiUtil)(void);
 static void  (WINAPI *pSwapPword)(PUSHORT,ULONG);
 static void  (WINAPI *pSwapPlong)(PULONG,ULONG);
 static void  (WINAPI *pHexFromBin)(LPBYTE,int,LPWSTR);
 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 BOOL  (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 UINT  (WINAPI *pUFromSz)(LPCSTR);
 static ULONG (WINAPI *pUlFromSzHex)(LPCSTR);
 static ULONG (WINAPI *pCbOfEncoded)(LPCSTR);
 static BOOL  (WINAPI *pIsBadBoundedStringPtr)(LPCSTR,ULONG);
+static SCODE (WINAPI *pMAPIInitialize)(LPVOID);
+static void  (WINAPI *pMAPIUninitialize)(void);
+
+static void init_function_pointers(void)
+{
+    hMapi32 = LoadLibraryA("mapi32.dll");
+
+    pScInitMapiUtil = (void*)GetProcAddress(hMapi32, "ScInitMapiUtil@4");
+    pDeinitMapiUtil = (void*)GetProcAddress(hMapi32, "DeinitMapiUtil@0");
+    pSwapPword = (void*)GetProcAddress(hMapi32, "SwapPword@8");
+    pSwapPlong = (void*)GetProcAddress(hMapi32, "SwapPlong@8");
+    pHexFromBin = (void*)GetProcAddress(hMapi32, "HexFromBin@12");
+    pFBinFromHex = (void*)GetProcAddress(hMapi32, "FBinFromHex@8");
+    pUFromSz = (void*)GetProcAddress(hMapi32, "UFromSz@4");
+    pUlFromSzHex = (void*)GetProcAddress(hMapi32, "UlFromSzHex@4");
+    pCbOfEncoded = (void*)GetProcAddress(hMapi32, "CbOfEncoded@4");
+    pIsBadBoundedStringPtr = (void*)GetProcAddress(hMapi32, "IsBadBoundedStringPtr@8");
+    pMAPIInitialize = (void*)GetProcAddress(hMapi32, "MAPIInitialize");
+    pMAPIUninitialize = (void*)GetProcAddress(hMapi32, "MAPIUninitialize");
+}
 
 static void test_SwapPword(void)
 {
     USHORT shorts[3];
 
 
 static void test_SwapPword(void)
 {
     USHORT shorts[3];
 
-    pSwapPword = (void*)GetProcAddress(hMapi32, "SwapPword@8");
     if (!pSwapPword)
     if (!pSwapPword)
+    {
+        win_skip("SwapPword is not available\n");
         return;
         return;
+    }
 
     shorts[0] = 0xff01;
     shorts[1] = 0x10ff;
 
     shorts[0] = 0xff01;
     shorts[1] = 0x10ff;
@@ -61,9 +84,11 @@ static void test_SwapPlong(void)
 {
     ULONG longs[3];
 
 {
     ULONG longs[3];
 
-    pSwapPlong = (void*)GetProcAddress(hMapi32, "SwapPlong@8");
     if (!pSwapPlong)
     if (!pSwapPlong)
+    {
+        win_skip("SwapPlong is not available\n");
         return;
         return;
+    }
 
     longs[0] = 0xffff0001;
     longs[1] = 0x1000ffff;
 
     longs[0] = 0xffff0001;
     longs[1] = 0x1000ffff;
@@ -89,10 +114,11 @@ static void test_HexFromBin(void)
     BOOL bOk;
     int i;
 
     BOOL bOk;
     int i;
 
-    pHexFromBin = (void*)GetProcAddress(hMapi32, "HexFromBin@12");
-    pFBinFromHex = (void*)GetProcAddress(hMapi32, "FBinFromHex@8");
     if (!pHexFromBin || !pFBinFromHex)
     if (!pHexFromBin || !pFBinFromHex)
+    {
+        win_skip("Hexadecimal conversion functions are not available\n");
         return;
         return;
+    }
 
     for (i = 0; i < 255; i++)
         data[i] = i;
 
     for (i = 0; i < 255; i++)
         data[i] = i;
@@ -112,9 +138,11 @@ static void test_HexFromBin(void)
 
 static void test_UFromSz(void)
 {
 
 static void test_UFromSz(void)
 {
-    pUFromSz = (void*)GetProcAddress(hMapi32, "UFromSz@4");
     if (!pUFromSz)
     if (!pUFromSz)
+    {
+        win_skip("UFromSz is not available\n");
         return;
         return;
+    }
 
     ok(pUFromSz("105679") == 105679u,
        "UFromSz: expected 105679, got %d\n", pUFromSz("105679"));
 
     ok(pUFromSz("105679") == 105679u,
        "UFromSz: expected 105679, got %d\n", pUFromSz("105679"));
@@ -125,9 +153,11 @@ static void test_UFromSz(void)
 
 static void test_UlFromSzHex(void)
 {
 
 static void test_UlFromSzHex(void)
 {
-    pUlFromSzHex = (void*)GetProcAddress(hMapi32, "UlFromSzHex@4");
     if (!pUlFromSzHex)
     if (!pUlFromSzHex)
+    {
+        win_skip("UlFromSzHex is not available\n");
         return;
         return;
+    }
 
     ok(pUlFromSzHex("fF") == 0xffu,
        "UlFromSzHex: expected 0xff, got 0x%x\n", pUlFromSzHex("fF"));
 
     ok(pUlFromSzHex("fF") == 0xffu,
        "UlFromSzHex: expected 0xff, got 0x%x\n", pUlFromSzHex("fF"));
@@ -141,9 +171,11 @@ static void test_CbOfEncoded(void)
     char buff[129];
     unsigned int i;
 
     char buff[129];
     unsigned int i;
 
-    pCbOfEncoded = (void*)GetProcAddress(hMapi32, "CbOfEncoded@4");
     if (!pCbOfEncoded)
     if (!pCbOfEncoded)
+    {
+        win_skip("CbOfEncoded is not available\n");
         return;
         return;
+    }
 
     for (i = 0; i < sizeof(buff) - 1; i++)
     {
 
     for (i = 0; i < sizeof(buff) - 1; i++)
     {
@@ -160,9 +192,11 @@ static void test_CbOfEncoded(void)
 
 static void test_IsBadBoundedStringPtr(void)
 {
 
 static void test_IsBadBoundedStringPtr(void)
 {
-    pIsBadBoundedStringPtr = (void*)GetProcAddress(hMapi32, "IsBadBoundedStringPtr@8");
     if (!pIsBadBoundedStringPtr)
     if (!pIsBadBoundedStringPtr)
+    {
+        win_skip("IsBadBoundedStringPtr is not available\n");
         return;
         return;
+    }
 
     ok(pIsBadBoundedStringPtr(NULL, 0) == TRUE, "IsBadBoundedStringPtr: expected TRUE\n");
     ok(pIsBadBoundedStringPtr("TEST", 4) == TRUE, "IsBadBoundedStringPtr: expected TRUE\n");
 
     ok(pIsBadBoundedStringPtr(NULL, 0) == TRUE, "IsBadBoundedStringPtr: expected TRUE\n");
     ok(pIsBadBoundedStringPtr("TEST", 4) == TRUE, "IsBadBoundedStringPtr: expected TRUE\n");
@@ -179,13 +213,11 @@ START_TEST(util)
         return;
     }
 
         return;
     }
 
-    hMapi32 = LoadLibraryA("mapi32.dll");
-
-    pScInitMapiUtil = (void*)GetProcAddress(hMapi32, "ScInitMapiUtil@4");
+    init_function_pointers();
 
 
-    if (!pScInitMapiUtil)
+    if (!pScInitMapiUtil || !pDeinitMapiUtil)
     {
     {
-        win_skip("ScInitMapiUtil is not available\n");
+        win_skip("MAPI utility initialization functions are not available\n");
         FreeLibrary(hMapi32);
         return;
     }
         FreeLibrary(hMapi32);
         return;
     }
@@ -207,11 +239,22 @@ START_TEST(util)
 
     test_SwapPword();
     test_SwapPlong();
 
     test_SwapPword();
     test_SwapPlong();
+
+    /* We call MAPIInitialize here for the benefit of native extended MAPI
+     * providers which crash in the HexFromBin tests when MAPIInitialize has
+     * not been called. Since MAPIInitialize is irrelevant for HexFromBin on
+     * Wine, we do not care whether MAPIInitialize succeeds. */
+    if (pMAPIInitialize)
+        ret = pMAPIInitialize(NULL);
     test_HexFromBin();
     test_HexFromBin();
+    if (pMAPIUninitialize && ret == S_OK)
+        pMAPIUninitialize();
+
     test_UFromSz();
     test_UlFromSzHex();
     test_CbOfEncoded();
     test_IsBadBoundedStringPtr();
 
     test_UFromSz();
     test_UlFromSzHex();
     test_CbOfEncoded();
     test_IsBadBoundedStringPtr();
 
+    pDeinitMapiUtil();
     FreeLibrary(hMapi32);
 }
     FreeLibrary(hMapi32);
 }