Implement DllMain, DllCanUnloadNow, WrapProgress,
MAPIGetDefaultMalloc, IsBadBoundedStringPtr, UFromSz, UlFromSzHex,
CbOfEncoded.
Add tests for the above.

diff --git a/dlls/mapi32/Makefile.in b/dlls/mapi32/Makefile.in
index 58426d2..72d3da6 100644
--- a/dlls/mapi32/Makefile.in
+++ b/dlls/mapi32/Makefile.in
@@ -3,10 +3,11 @@
 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 0000000..52ea5a7
--- /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 <stdarg.h>
+
+#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 8f3dc02..b39c158 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 ac6cc97..c9d0c00 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 526e3c4..705f9ae 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 9b93876..6267887 100644
--- a/dlls/mapi32/tests/Makefile.in
+++ b/dlls/mapi32/tests/Makefile.in
@@ -7,6 +7,7 @@
 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 0000000..7fb013f
--- /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 8a070ad..927008c 100644
--- a/dlls/mapi32/tests/util.c
+++ b/dlls/mapi32/tests/util.c
@@ -36,6 +36,10 @@
 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 @@
     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 @@
     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 72da46f..ee158d4 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 @@
     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 @@
  */
 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);
@@ -458,6 +468,26 @@
 }
 
 /**************************************************************************
+ *  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)
  *
  * Add two FILETIME's together.
@@ -545,7 +575,7 @@
 LONGLONG WINAPI MAPI32_FtNegFt(FILETIME ft)
 {
     LONGLONG *p = (LONGLONG*)&ft;
-    
+
     return - *p;
 }
 
@@ -597,6 +627,39 @@
     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 @@
     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)