gdi32: Don't set the bitfields when the dib section is BI_RGB.
[wine] / dlls / comctl32 / comctl32undoc.c
index ba77f0f..ff94051 100644 (file)
@@ -17,7 +17,7 @@
  *
  * 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
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  *
  * NOTES
  *     All of these functions are UNDOCUMENTED!! And I mean UNDOCUMENTED!!!!
  *     These functions are used by EXPLORER.EXE, IEXPLORE.EXE and
  *     COMCTL32.DLL (internally).
  *
- * TODO
- *     - Add more functions.
- *     - Write some documentation.
  */
+#include "config.h"
+#include "wine/port.h"
 
+#include <stdarg.h>
 #include <string.h>
-#include <stdlib.h> /* atoi */
 #include <ctype.h>
 #include <limits.h>
 
+#define COBJMACROS
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winnls.h"
+#include "winreg.h"
 #include "commctrl.h"
 #include "objbase.h"
-#include "winbase.h"
 #include "winerror.h"
-#include "winreg.h"
 
 #include "wine/unicode.h"
 #include "comctl32.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
 
-
-extern HANDLE COMCTL32_hHeap; /* handle to the private heap */
-
-
-typedef struct _STREAMDATA
-{
-    DWORD dwSize;
-    DWORD dwData2;
-    DWORD dwItems;
-} STREAMDATA, *PSTREAMDATA;
-
-typedef struct _LOADDATA
-{
-    INT   nCount;
-    PVOID ptr;
-} LOADDATA, *LPLOADDATA;
-
-typedef HRESULT (CALLBACK *DPALOADPROC)(LPLOADDATA,IStream*,LPARAM);
-
-/**************************************************************************
- * DPA_LoadStream [COMCTL32.9]
- *
- * Loads a dynamic pointer array from a stream
- *
- * PARAMS
- *     phDpa    [O] pointer to a handle to a dynamic pointer array
- *     loadProc [I] pointer to a callback function
- *     pStream  [I] pointer to a stream
- *     lParam   [I] application specific value
- *
- * NOTES
- *     No more information available yet!
- */
-
-HRESULT WINAPI
-DPA_LoadStream (HDPA *phDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam)
-{
-    HRESULT errCode;
-    LARGE_INTEGER position;
-    ULARGE_INTEGER newPosition;
-    STREAMDATA  streamData;
-    LOADDATA loadData;
-    ULONG ulRead;
-    HDPA hDpa;
-    PVOID *ptr;
-
-    FIXME ("phDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
-          phDpa, loadProc, pStream, lParam);
-
-    if (!phDpa || !loadProc || !pStream)
-       return E_INVALIDARG;
-
-    *phDpa = (HDPA)NULL;
-
-    position.s.LowPart = 0;
-    position.s.HighPart = 0;
-
-    /*
-     * Zero out our streamData
-     */
-    memset(&streamData,0,sizeof(STREAMDATA));
-
-    errCode = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &newPosition);
-    if (errCode != S_OK)
-       return errCode;
-
-    errCode = IStream_Read (pStream, &streamData, sizeof(STREAMDATA), &ulRead);
-    if (errCode != S_OK)
-       return errCode;
-
-    FIXME ("dwSize=%lu dwData2=%lu dwItems=%lu\n",
-          streamData.dwSize, streamData.dwData2, streamData.dwItems);
-
-    if ( ulRead < sizeof(STREAMDATA) ||
-    lParam < sizeof(STREAMDATA) ||
-       streamData.dwSize < sizeof(STREAMDATA) ||
-       streamData.dwData2 < 1) {
-       errCode = E_FAIL;
-    }
-
-    if (streamData.dwItems > (UINT_MAX / 2 / sizeof(VOID*))) /* 536870911 */
-        return E_OUTOFMEMORY;
-
-    /* create the dpa */
-    hDpa = DPA_Create (streamData.dwItems);
-    if (!hDpa)
-       return E_OUTOFMEMORY;
-
-    if (!DPA_Grow (hDpa, streamData.dwItems))
-       return E_OUTOFMEMORY;
-
-    /* load data from the stream into the dpa */
-    ptr = hDpa->ptrs;
-    for (loadData.nCount = 0; loadData.nCount < streamData.dwItems; loadData.nCount++) {
-        errCode = (loadProc)(&loadData, pStream, lParam);
-       if (errCode != S_OK) {
-           errCode = S_FALSE;
-           break;
-       }
-
-       *ptr = loadData.ptr;
-       ptr++;
-    }
-
-    /* set the number of items */
-    hDpa->nItemCount = loadData.nCount;
-
-    /* store the handle to the dpa */
-    *phDpa = hDpa;
-    FIXME ("new hDpa=%p\n", hDpa);
-
-    return errCode;
-}
-
-
-/**************************************************************************
- * DPA_SaveStream [COMCTL32.10]
- *
- * Saves a dynamic pointer array to a stream
- *
- * PARAMS
- *     hDpa     [I] handle to a dynamic pointer array
- *     loadProc [I] pointer to a callback function
- *     pStream  [I] pointer to a stream
- *     lParam   [I] application specific value
- *
- * NOTES
- *     No more information available yet!
- */
-
-HRESULT WINAPI
-DPA_SaveStream (const HDPA hDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam)
-{
-
-    FIXME ("hDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
-          hDpa, loadProc, pStream, lParam);
-
-    return E_FAIL;
-}
-
-
-/**************************************************************************
- * DPA_Merge [COMCTL32.11]
- *
- * PARAMS
- *     hdpa1       [I] handle to a dynamic pointer array
- *     hdpa2       [I] handle to a dynamic pointer array
- *     dwFlags     [I] flags
- *     pfnCompare  [I] pointer to sort function
- *     pfnMerge    [I] pointer to merge function
- *     lParam      [I] application specific value
- *
- * NOTES
- *     No more information available yet!
- */
-
-BOOL WINAPI
-DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags,
-          PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, LPARAM lParam)
-{
-    INT nCount;
-    LPVOID *pWork1, *pWork2;
-    INT nResult, i;
-    INT nIndex;
-
-    TRACE("%p %p %08lx %p %p %08lx)\n",
-          hdpa1, hdpa2, dwFlags, pfnCompare, pfnMerge, lParam);
-
-    if (IsBadWritePtr (hdpa1, sizeof(DPA)))
-       return FALSE;
-
-    if (IsBadWritePtr (hdpa2, sizeof(DPA)))
-       return FALSE;
-
-    if (IsBadCodePtr ((FARPROC)pfnCompare))
-       return FALSE;
-
-    if (IsBadCodePtr ((FARPROC)pfnMerge))
-       return FALSE;
-
-    if (!(dwFlags & DPAM_NOSORT)) {
-       TRACE("sorting dpa's!\n");
-       if (hdpa1->nItemCount > 0)
-       DPA_Sort (hdpa1, pfnCompare, lParam);
-       TRACE ("dpa 1 sorted!\n");
-       if (hdpa2->nItemCount > 0)
-       DPA_Sort (hdpa2, pfnCompare, lParam);
-       TRACE ("dpa 2 sorted!\n");
-    }
-
-    if (hdpa2->nItemCount < 1)
-       return TRUE;
-
-    TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n",
-          hdpa1->nItemCount, hdpa2->nItemCount);
-
-
-    /* working but untrusted implementation */
-
-    pWork1 = &(hdpa1->ptrs[hdpa1->nItemCount - 1]);
-    pWork2 = &(hdpa2->ptrs[hdpa2->nItemCount - 1]);
-
-    nIndex = hdpa1->nItemCount - 1;
-    nCount = hdpa2->nItemCount - 1;
-
-    do
-    {
-        if (nIndex < 0) {
-           if ((nCount >= 0) && (dwFlags & DPAM_INSERT)) {
-               /* Now insert the remaining new items into DPA 1 */
-               TRACE("%d items to be inserted at start of DPA 1\n",
-                     nCount+1);
-               for (i=nCount; i>=0; i--) {
-                   PVOID ptr;
-
-                   ptr = (pfnMerge)(3, *pWork2, NULL, lParam);
-                   if (!ptr)
-                       return FALSE;
-                   DPA_InsertPtr (hdpa1, 0, ptr);
-                   pWork2--;
-               }
-           }
-           break;
-       }
-       nResult = (pfnCompare)(*pWork1, *pWork2, lParam);
-       TRACE("compare result=%d, dpa1.cnt=%d, dpa2.cnt=%d\n",
-             nResult, nIndex, nCount);
-
-       if (nResult == 0)
-       {
-           PVOID ptr;
-
-           ptr = (pfnMerge)(1, *pWork1, *pWork2, lParam);
-           if (!ptr)
-               return FALSE;
-
-           nCount--;
-           pWork2--;
-           *pWork1 = ptr;
-           nIndex--;
-           pWork1--;
-       }
-       else if (nResult > 0)
-       {
-           /* item in DPA 1 missing from DPA 2 */
-           if (dwFlags & DPAM_DELETE)
-           {
-               /* Now delete the extra item in DPA1 */
-               PVOID ptr;
-
-               ptr = DPA_DeletePtr (hdpa1, hdpa1->nItemCount - 1);
-
-               (pfnMerge)(2, ptr, NULL, lParam);
-           }
-           nIndex--;
-           pWork1--;
-       }
-       else
-       {
-           /* new item in DPA 2 */
-           if (dwFlags & DPAM_INSERT)
-           {
-               /* Now insert the new item in DPA 1 */
-               PVOID ptr;
-
-               ptr = (pfnMerge)(3, *pWork2, NULL, lParam);
-               if (!ptr)
-                   return FALSE;
-               DPA_InsertPtr (hdpa1, nIndex+1, ptr);
-           }
-           nCount--;
-           pWork2--;
-       }
-
-    }
-    while (nCount >= 0);
-
-    return TRUE;
-}
-
+static const WCHAR strMRUList[] = { 'M','R','U','L','i','s','t',0 };
 
 /**************************************************************************
  * Alloc [COMCTL32.71]
@@ -341,19 +69,9 @@ DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags,
  *     Success: pointer to allocated memory block
  *     Failure: NULL
  */
-
-LPVOID WINAPI
-COMCTL32_Alloc (DWORD dwSize)
+LPVOID WINAPI Alloc (DWORD dwSize)
 {
-    LPVOID lpPtr;
-
-    TRACE("(0x%lx)\n", dwSize);
-
-    lpPtr = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
-
-    TRACE("-- ret=%p\n", lpPtr);
-
-    return lpPtr;
+    return LocalAlloc( LMEM_ZEROINIT, dwSize );
 }
 
 
@@ -372,25 +90,15 @@ COMCTL32_Alloc (DWORD dwSize)
  *     Failure: NULL
  *
  * NOTES
- *     If lpSrc is a NULL-pointer, then COMCTL32_ReAlloc allocates a memory
- *     block like COMCTL32_Alloc.
+ *     If lpSrc is a NULL-pointer, then ReAlloc allocates a memory
+ *     block like Alloc.
  */
-
-LPVOID WINAPI
-COMCTL32_ReAlloc (LPVOID lpSrc, DWORD dwSize)
+LPVOID WINAPI ReAlloc (LPVOID lpSrc, DWORD dwSize)
 {
-    LPVOID lpDest;
-
-    TRACE("(%p 0x%08lx)\n", lpSrc, dwSize);
-
     if (lpSrc)
-       lpDest = HeapReAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, lpSrc, dwSize);
+        return LocalReAlloc( lpSrc, dwSize, LMEM_ZEROINIT | LMEM_MOVEABLE );
     else
-       lpDest = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
-
-    TRACE("-- ret=%p\n", lpDest);
-
-    return lpDest;
+        return LocalAlloc( LMEM_ZEROINIT, dwSize);
 }
 
 
@@ -406,13 +114,9 @@ COMCTL32_ReAlloc (LPVOID lpSrc, DWORD dwSize)
  *     Success: TRUE
  *     Failure: FALSE
  */
-
-BOOL WINAPI
-COMCTL32_Free (LPVOID lpMem)
+BOOL WINAPI Free (LPVOID lpMem)
 {
-    TRACE("(%p)\n", lpMem);
-
-    return HeapFree (COMCTL32_hHeap, 0, lpMem);
+    return !LocalFree( lpMem );
 }
 
 
@@ -429,44 +133,109 @@ COMCTL32_Free (LPVOID lpMem)
  *     Success: size of the specified memory block
  *     Failure: 0
  */
-
-DWORD WINAPI
-COMCTL32_GetSize (LPVOID lpMem)
+DWORD WINAPI GetSize (LPVOID lpMem)
 {
-    TRACE("(%p)\n", lpMem);
-
-    return HeapSize (COMCTL32_hHeap, 0, lpMem);
+    return LocalSize( lpMem );
 }
 
 
 /**************************************************************************
- * The MRU-API is a set of functions to manipulate MRU(Most Recently Used)
- * lists.
+ * MRU-Functions  {COMCTL32}
  *
- * Stored in the reg. as a set of values under a single key.  Each item in the
- * list has a value name that is a single char. 'a' - 'z', '{', '|' or '}'.
- * The order of the list is stored with value name 'MRUList' which is a string
- * containing the value names (i.e. 'a', 'b', etc.) in the relevant order.
- */
+ * NOTES
+ * The MRU-Api is a set of functions to manipulate lists of M.R.U. (Most Recently
+ * Used) items. It is an undocumented Api that is used (at least) by the shell
+ * and explorer to implement their recent documents feature.
+ *
+ * Since these functions are undocumented, they are unsupported by MS and
+ * may change at any time.
+ *
+ * Internally, the list is implemented as a last in, last out list of items
+ * persisted into the system registry under a caller chosen key. Each list
+ * item is given a one character identifier in the Ascii range from 'a' to
+ * '}'. A list of the identifiers in order from newest to oldest is stored
+ * under the same key in a value named "MRUList".
+ *
+ * Items are re-ordered by changing the order of the values in the MRUList
+ * value. When a new item is added, it becomes the new value of the oldest
+ * identifier, and that identifier is moved to the front of the MRUList value.
+ * 
+ * Wine stores MRU-lists in the same registry format as Windows, so when
+ * switching between the builtin and native comctl32.dll no problems or
+ * incompatibilities should occur.
+ *
+ * The following undocumented structure is used to create an MRU-list:
+ *|typedef INT (CALLBACK *MRUStringCmpFn)(LPCTSTR lhs, LPCTSTR rhs);
+ *|typedef INT (CALLBACK *MRUBinaryCmpFn)(LPCVOID lhs, LPCVOID rhs, DWORD length);
+ *|
+ *|typedef struct tagCREATEMRULIST
+ *|{
+ *|    DWORD   cbSize;
+ *|    DWORD   nMaxItems;
+ *|    DWORD   dwFlags;
+ *|    HKEY    hKey;
+ *|    LPTSTR  lpszSubKey;
+ *|    PROC    lpfnCompare;
+ *|} CREATEMRULIST, *LPCREATEMRULIST;
+ *
+ * MEMBERS
+ *  cbSize      [I] The size of the CREATEMRULIST structure. This must be set
+ *                  to sizeof(CREATEMRULIST) by the caller.
+ *  nMaxItems   [I] The maximum number of items allowed in the list. Because
+ *                  of the limited number of identifiers, this should be set to
+ *                  a value from 1 to 30 by the caller.
+ *  dwFlags     [I] If bit 0 is set, the list will be used to store binary
+ *                  data, otherwise it is assumed to store strings. If bit 1
+ *                  is set, every change made to the list will be reflected in
+ *                  the registry immediately, otherwise changes will only be
+ *                  written when the list is closed.
+ *  hKey        [I] The registry key that the list should be written under.
+ *                  This must be supplied by the caller.
+ *  lpszSubKey  [I] A caller supplied name of a subkey under hKey to write
+ *                  the list to. This may not be blank.
+ *  lpfnCompare [I] A caller supplied comparison function, which may be either
+ *                  an MRUStringCmpFn if dwFlags does not have bit 0 set, or a
+ *                  MRUBinaryCmpFn otherwise.
+ *
+ * FUNCTIONS
+ *  - Create an MRU-list with CreateMRUList() or CreateMRUListLazy().
+ *  - Add items to an MRU-list with AddMRUString() or AddMRUData().
+ *  - Remove items from an MRU-list with DelMRUString().
+ *  - Find data in an MRU-list with FindMRUString() or FindMRUData().
+ *  - Iterate through an MRU-list with EnumMRUList().
+ *  - Free an MRU-list with FreeMRUList().
+ */
+
+typedef INT (CALLBACK *MRUStringCmpFnA)(LPCSTR lhs, LPCSTR rhs);
+typedef INT (CALLBACK *MRUStringCmpFnW)(LPCWSTR lhs, LPCWSTR rhs);
+typedef INT (CALLBACK *MRUBinaryCmpFn)(LPCVOID lhs, LPCVOID rhs, DWORD length);
 
 typedef struct tagCREATEMRULISTA
 {
-    DWORD  cbSize;        /* size of struct */
-    DWORD  nMaxItems;     /* max no. of items in list */
-    DWORD  dwFlags;       /* see below */
-    HKEY   hKey;          /* root reg. key under which list is saved */
-    LPCSTR lpszSubKey;    /* reg. subkey */
-    PROC   lpfnCompare;   /* item compare proc */
+    DWORD  cbSize;
+    DWORD  nMaxItems;
+    DWORD  dwFlags;
+    HKEY   hKey;
+    LPSTR  lpszSubKey;
+    union
+    {
+        MRUStringCmpFnA string_cmpfn;
+        MRUBinaryCmpFn  binary_cmpfn;
+    } u;
 } CREATEMRULISTA, *LPCREATEMRULISTA;
 
 typedef struct tagCREATEMRULISTW
 {
-    DWORD   cbSize;        /* size of struct */
-    DWORD   nMaxItems;     /* max no. of items in list */
-    DWORD   dwFlags;       /* see below */
-    HKEY    hKey;          /* root reg. key under which list is saved */
-    LPCWSTR lpszSubKey;    /* reg. subkey */
-    PROC    lpfnCompare;   /* item compare proc */
+    DWORD   cbSize;
+    DWORD   nMaxItems;
+    DWORD   dwFlags;
+    HKEY    hKey;
+    LPWSTR  lpszSubKey;
+    union
+    {
+        MRUStringCmpFnW string_cmpfn;
+        MRUBinaryCmpFn  binary_cmpfn;
+    } u;
 } CREATEMRULISTW, *LPCREATEMRULISTW;
 
 /* dwFlags */
@@ -498,7 +267,7 @@ typedef struct tagWINEMRULIST
     BOOL           isUnicode;   /* is compare fn Unicode */
     DWORD          wineFlags;   /* internal flags                    */
     DWORD          cursize;     /* current size of realMRU           */
-    LPSTR          realMRU;     /* pointer to string of index names  */
+    LPWSTR         realMRU;     /* pointer to string of index names  */
     LPWINEMRUITEM  *array;      /* array of pointers to data         */
                                 /* in 'a' to 'z' order               */
 } WINEMRULIST, *LPWINEMRULIST;
@@ -507,16 +276,16 @@ typedef struct tagWINEMRULIST
 #define WMRUF_CHANGED  0x0001   /* MRU list has changed              */
 
 /**************************************************************************
- *              MRU_SaveChanged - Localize MRU saving code
+ *              MRU_SaveChanged (internal)
  *
+ * Local MRU saving code
  */
-VOID MRU_SaveChanged( LPWINEMRULIST mp )
+static void MRU_SaveChanged ( LPWINEMRULIST mp )
 {
-    INT i, err;
+    UINT i, err;
     HKEY newkey;
     WCHAR realname[2];
     LPWINEMRUITEM witem;
-    WCHAR emptyW[] = {'\0'};
 
     /* or should we do the following instead of RegOpenKeyEx:
      */
@@ -525,11 +294,11 @@ VOID MRU_SaveChanged( LPWINEMRULIST mp )
     if ((err = RegOpenKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
                              0, KEY_WRITE, &newkey))) {
        /* not present - what to do ??? */
-       ERR("Can not open key, error=%d, attempting to create\n",
+       ERR("Could not open key, error=%d, attempting to create\n",
            err);
        if ((err = RegCreateKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
                                    0,
-                                   emptyW,
+                                   NULL,
                                    REG_OPTION_NON_VOLATILE,
                                    KEY_READ | KEY_WRITE,
                                    0,
@@ -542,12 +311,12 @@ VOID MRU_SaveChanged( LPWINEMRULIST mp )
     }
     if (mp->wineFlags & WMRUF_CHANGED) {
        mp->wineFlags &= ~WMRUF_CHANGED;
-       err = RegSetValueExA(newkey, "MRUList", 0, REG_SZ,
-                            mp->realMRU, strlen(mp->realMRU) + 1);
+       err = RegSetValueExW(newkey, strMRUList, 0, REG_SZ, (LPBYTE)mp->realMRU,
+                            (strlenW(mp->realMRU) + 1)*sizeof(WCHAR));
        if (err) {
            ERR("error saving MRUList, err=%d\n", err);
        }
-       TRACE("saving MRUList=/%s/\n", mp->realMRU);
+       TRACE("saving MRUList=/%s/\n", debugstr_w(mp->realMRU));
     }
     realname[1] = 0;
     for(i=0; i<mp->cursize; i++) {
@@ -562,7 +331,7 @@ VOID MRU_SaveChanged( LPWINEMRULIST mp )
            if (err) {
                ERR("error saving /%s/, err=%d\n", debugstr_w(realname), err);
            }
-           TRACE("saving value for name /%s/ size=%ld\n",
+            TRACE("saving value for name /%s/ size=%d\n",
                  debugstr_w(realname), witem->size);
        }
     }
@@ -572,30 +341,35 @@ VOID MRU_SaveChanged( LPWINEMRULIST mp )
 /**************************************************************************
  *              FreeMRUList [COMCTL32.152]
  *
+ * Frees a most-recently-used items list.
+ *
  * PARAMS
  *     hMRUList [I] Handle to list.
  *
+ * RETURNS
+ *     Nothing.
  */
-DWORD WINAPI
-FreeMRUList (HANDLE hMRUList)
+void WINAPI FreeMRUList (HANDLE hMRUList)
 {
-    LPWINEMRULIST mp = (LPWINEMRULIST)hMRUList;
-    INT i;
+    LPWINEMRULIST mp = hMRUList;
+    UINT i;
+
+    TRACE("(%p)\n", hMRUList);
+    if (!hMRUList)
+        return;
 
-    TRACE("\n");
     if (mp->wineFlags & WMRUF_CHANGED) {
        /* need to open key and then save the info */
        MRU_SaveChanged( mp );
     }
 
-    for(i=0; i<mp->extview.nMaxItems; i++) {
-       if (mp->array[i])
-           COMCTL32_Free(mp->array[i]);
-    }
-    COMCTL32_Free(mp->realMRU);
-    COMCTL32_Free(mp->array);
-    COMCTL32_Free((LPWSTR)mp->extview.lpszSubKey);
-    return COMCTL32_Free(mp);
+    for(i=0; i<mp->extview.nMaxItems; i++)
+        Free(mp->array[i]);
+
+    Free(mp->realMRU);
+    Free(mp->array);
+    Free(mp->extview.lpszSubKey);
+    Free(mp);
 }
 
 
@@ -615,53 +389,50 @@ FreeMRUList (HANDLE hMRUList)
  * RETURNS
  *    Position in list 0 -> MRU.  -1 if item not found.
  */
-INT WINAPI
-FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum)
+INT WINAPI FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData,
+                        LPINT lpRegNum)
 {
-    LPWINEMRULIST mp = (LPWINEMRULIST)hList;
-    INT i, ret;
+    const WINEMRULIST *mp = hList;
+    INT ret;
+    UINT i;
     LPSTR dataA = NULL;
 
-    if (!mp->extview.lpfnCompare) {
-       ERR("MRU list not properly created. No compare procedure.\n");
+    if (!mp || !mp->extview.u.string_cmpfn)
        return -1;
-    }
 
     if(!(mp->extview.dwFlags & MRUF_BINARY_LIST) && !mp->isUnicode) {
         DWORD len = WideCharToMultiByte(CP_ACP, 0, lpData, -1,
                                        NULL, 0, NULL, NULL);
-       dataA = COMCTL32_Alloc(len);
+       dataA = Alloc(len);
        WideCharToMultiByte(CP_ACP, 0, lpData, -1, dataA, len, NULL, NULL);
     }
 
     for(i=0; i<mp->cursize; i++) {
        if (mp->extview.dwFlags & MRUF_BINARY_LIST) {
-           if (!mp->extview.lpfnCompare(lpData, &mp->array[i]->datastart,
-                                        cbData))
+           if (!mp->extview.u.binary_cmpfn(lpData, &mp->array[i]->datastart, cbData))
                break;
        }
        else {
            if(mp->isUnicode) {
-               if (!mp->extview.lpfnCompare(lpData, &mp->array[i]->datastart))
+               if (!mp->extview.u.string_cmpfn(lpData, (LPWSTR)&mp->array[i]->datastart))
                    break;
            } else {
                DWORD len = WideCharToMultiByte(CP_ACP, 0,
                                                (LPWSTR)&mp->array[i]->datastart, -1,
                                                NULL, 0, NULL, NULL);
-               LPSTR itemA = COMCTL32_Alloc(len);
+               LPSTR itemA = Alloc(len);
                INT cmp;
                WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&mp->array[i]->datastart, -1,
                                    itemA, len, NULL, NULL);
 
-               cmp = mp->extview.lpfnCompare(dataA, itemA);
-               COMCTL32_Free(itemA);
+               cmp = mp->extview.u.string_cmpfn((LPWSTR)dataA, (LPWSTR)itemA);
+               Free(itemA);
                if(!cmp)
                    break;
            }
        }
     }
-    if(dataA)
-        COMCTL32_Free(dataA);
+    Free(dataA);
     if (i < mp->cursize)
        ret = i;
     else
@@ -669,7 +440,7 @@ FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum)
     if (lpRegNum && (ret != -1))
        *lpRegNum = 'a' + i;
 
-    TRACE("(%p, %p, %ld, %p) returning %d\n",
+    TRACE("(%p, %p, %d, %p) returning %d\n",
           hList, lpData, cbData, lpRegNum, ret);
 
     return ret;
@@ -692,14 +463,22 @@ FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum)
  *     No. corresponding to registry name where value is stored 'a' -> 0 etc.
  *     -1 on error.
  */
-INT WINAPI
-AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData)
+INT WINAPI AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData)
 {
-    LPWINEMRULIST mp = (LPWINEMRULIST)hList;
+    LPWINEMRULIST mp = hList;
     LPWINEMRUITEM witem;
-    INT i, replace, ret;
+    INT i, replace;
 
-    if ((replace = FindMRUData (hList, lpData, cbData, NULL)) < 0) {
+    if ((replace = FindMRUData (hList, lpData, cbData, NULL)) >= 0) {
+        /* Item exists, just move it to the front */
+        LPWSTR pos = strchrW(mp->realMRU, replace + 'a');
+        while (pos > mp->realMRU)
+        {
+            pos[0] = pos[-1];
+            pos--;
+        }
+    }
+    else {
        /* either add a new entry or replace oldest */
        if (mp->cursize < mp->extview.nMaxItems) {
            /* Add in a new item */
@@ -709,71 +488,108 @@ AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData)
        else {
            /* get the oldest entry and replace data */
            replace = mp->realMRU[mp->cursize - 1] - 'a';
-           COMCTL32_Free(mp->array[replace]);
+           Free(mp->array[replace]);
        }
-    }
-    else {
-       /* free up the old data */
-       COMCTL32_Free(mp->array[replace]);
-    }
 
-    /* Allocate space for new item and move in the data */
-    mp->array[replace] = witem = (LPWINEMRUITEM)COMCTL32_Alloc(cbData +
-                                                              sizeof(WINEMRUITEM));
-    witem->itemFlag |= WMRUIF_CHANGED;
-    witem->size = cbData;
-    memcpy( &witem->datastart, lpData, cbData);
+        /* Allocate space for new item and move in the data */
+        mp->array[replace] = witem = Alloc(cbData + sizeof(WINEMRUITEM));
+        witem->itemFlag |= WMRUIF_CHANGED;
+        witem->size = cbData;
+        memcpy( &witem->datastart, lpData, cbData);
 
-    /* now rotate MRU list */
-    mp->wineFlags |= WMRUF_CHANGED;
-    for(i=mp->cursize-1; i>=1; i--) {
-       mp->realMRU[i] = mp->realMRU[i-1];
+        /* now rotate MRU list */
+        for(i=mp->cursize-1; i>=1; i--)
+            mp->realMRU[i] = mp->realMRU[i-1];
     }
+
+    /* The new item gets the front spot */
+    mp->wineFlags |= WMRUF_CHANGED;
     mp->realMRU[0] = replace + 'a';
-    TRACE("(%p, %p, %ld) adding data, /%c/ now most current\n",
-         hList, lpData, cbData, replace+'a');
-    ret = replace;
+
+    TRACE("(%p, %p, %d) adding data, /%c/ now most current\n",
+          hList, lpData, cbData, replace+'a');
 
     if (!(mp->extview.dwFlags & MRUF_DELAYED_SAVE)) {
        /* save changed stuff right now */
        MRU_SaveChanged( mp );
     }
 
-    return ret;
+    return replace;
 }
 
 /**************************************************************************
  *              AddMRUStringW [COMCTL32.401]
  *
- * Add item to MRU string list.  If item already exists in list them it is
- * simply moved up to the top of the list and not added again.  If list is
- * full then the least recently used item is removed to make room.
+ * Add an item to an MRU string list.
  *
  * PARAMS
- *     hList [I] Handle to list.
- *     lpszString [I] ptr to string to add.
+ *     hList      [I] Handle to list.
+ *     lpszString [I] The string to add.
  *
  * RETURNS
- *     No. corresponding to registry name where value is stored 'a' -> 0 etc.
- *     -1 on error.
+ *   Success: The number corresponding to the registry name where the string
+ *            has been stored (0 maps to 'a', 1 to 'b' and so on).
+ *   Failure: -1, if hList is NULL or memory allocation fails. If lpszString
+ *            is invalid, the function returns 0, and GetLastError() returns
+ *            ERROR_INVALID_PARAMETER. The last error value is set only in
+ *            this case.
+ *
+ * NOTES
+ *  -If lpszString exists in the list already, it is moved to the top of the
+ *   MRU list (it is not duplicated).
+ *  -If the list is full the least recently used list entry is replaced with
+ *   lpszString.
+ *  -If this function returns 0 you should check the last error value to
+ *   ensure the call really succeeded.
  */
-INT WINAPI
-AddMRUStringW(HANDLE hList, LPCWSTR lpszString)
+INT WINAPI AddMRUStringW(HANDLE hList, LPCWSTR lpszString)
 {
-    FIXME("(%p, %s) empty stub!\n", hList, debugstr_w(lpszString));
+    TRACE("(%p,%s)\n", hList, debugstr_w(lpszString));
+
+    if (!hList)
+        return -1;
+
+    if (!lpszString || IsBadStringPtrW(lpszString, -1))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return 0;
+    }
 
-    return 0;
+    return AddMRUData(hList, lpszString,
+                      (strlenW(lpszString) + 1) * sizeof(WCHAR));
 }
 
 /**************************************************************************
  *              AddMRUStringA [COMCTL32.153]
+ *
+ * See AddMRUStringW.
  */
-INT WINAPI
-AddMRUStringA(HANDLE hList, LPCSTR lpszString)
+INT WINAPI AddMRUStringA(HANDLE hList, LPCSTR lpszString)
 {
-    FIXME("(%p, %s) empty stub!\n", hList, debugstr_a(lpszString));
+    DWORD len;
+    LPWSTR stringW;
+    INT ret;
 
-    return 0;
+    TRACE("(%p,%s)\n", hList, debugstr_a(lpszString));
+
+    if (!hList)
+        return -1;
+
+    if (IsBadStringPtrA(lpszString, -1))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+       return 0;
+    }
+
+    len = MultiByteToWideChar(CP_ACP, 0, lpszString, -1, NULL, 0) * sizeof(WCHAR);
+    stringW = Alloc(len);
+    if (!stringW)
+        return -1;
+
+    MultiByteToWideChar(CP_ACP, 0, lpszString, -1, stringW, len/sizeof(WCHAR));
+    ret = AddMRUData(hList, stringW, len);
+    Free(stringW);
+    return ret;
 }
 
 /**************************************************************************
@@ -788,8 +604,7 @@ AddMRUStringA(HANDLE hList, LPCSTR lpszString)
  * RETURNS
  *    TRUE if successful, FALSE if nItemPos is out of range.
  */
-BOOL WINAPI
-DelMRUString(HANDLE hList, INT nItemPos)
+BOOL WINAPI DelMRUString(HANDLE hList, INT nItemPos)
 {
     FIXME("(%p, %d): stub\n", hList, nItemPos);
     return TRUE;
@@ -797,12 +612,13 @@ DelMRUString(HANDLE hList, INT nItemPos)
 
 /**************************************************************************
  *                  FindMRUStringW [COMCTL32.402]
+ *
+ * See FindMRUStringA.
  */
-INT WINAPI
-FindMRUStringW (HANDLE hList, LPCWSTR lpszString, LPINT lpRegNum)
+INT WINAPI FindMRUStringW (HANDLE hList, LPCWSTR lpszString, LPINT lpRegNum)
 {
-  FIXME("stub\n");
-  return -1;
+  return FindMRUData(hList, lpszString,
+                     (lstrlenW(lpszString) + 1) * sizeof(WCHAR), lpRegNum);
 }
 
 /**************************************************************************
@@ -820,71 +636,70 @@ FindMRUStringW (HANDLE hList, LPCWSTR lpszString, LPINT lpRegNum)
  * RETURNS
  *    Position in list 0 -> MRU.  -1 if item not found.
  */
-INT WINAPI
-FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum)
+INT WINAPI FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum)
 {
     DWORD len = MultiByteToWideChar(CP_ACP, 0, lpszString, -1, NULL, 0);
-    LPWSTR stringW = COMCTL32_Alloc(len * sizeof(WCHAR));
+    LPWSTR stringW = Alloc(len * sizeof(WCHAR));
     INT ret;
 
     MultiByteToWideChar(CP_ACP, 0, lpszString, -1, stringW, len);
     ret = FindMRUData(hList, stringW, len * sizeof(WCHAR), lpRegNum);
-    COMCTL32_Free(stringW);
+    Free(stringW);
     return ret;
 }
 
 /*************************************************************************
- *                 CreateMRUListLazy_common
+ *                 CreateMRUListLazy_common (internal)
  */
-HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp)
+static HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp)
 {
-    INT i, err;
+    UINT i, err;
     HKEY newkey;
     DWORD datasize, dwdisp;
     WCHAR realname[2];
     LPWINEMRUITEM witem;
     DWORD type;
-    WCHAR emptyW[] = {'\0'};
 
     /* get space to save indices that will turn into names
      * but in order of most to least recently used
      */
-    mp->realMRU = (LPSTR) COMCTL32_Alloc(mp->extview.nMaxItems + 2);
+    mp->realMRU = Alloc((mp->extview.nMaxItems + 2) * sizeof(WCHAR));
 
     /* get space to save pointers to actual data in order of
      * 'a' to 'z' (0 to n).
      */
-    mp->array = (LPVOID) COMCTL32_Alloc(mp->extview.nMaxItems *
-                                       sizeof(LPVOID));
+    mp->array = Alloc(mp->extview.nMaxItems * sizeof(LPVOID));
 
     /* open the sub key */
     if ((err = RegCreateKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
                                0,
-                               emptyW,
+                               NULL,
                                REG_OPTION_NON_VOLATILE,
                                KEY_READ | KEY_WRITE,
                                 0,
                                &newkey,
                                &dwdisp))) {
        /* error - what to do ??? */
-       ERR("(%lu %lu %lx %lx \"%s\" %p): Can not open key, error=%d\n",
+       ERR("(%u %u %x %p %s %p): Could not open key, error=%d\n",
            mp->extview.cbSize, mp->extview.nMaxItems, mp->extview.dwFlags,
-           (DWORD)mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey),
-                                mp->extview.lpfnCompare, err);
+           mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey),
+            mp->extview.u.string_cmpfn, err);
        return 0;
     }
 
     /* get values from key 'MRUList' */
     if (newkey) {
-       datasize = mp->extview.nMaxItems + 1;
-       if((err=RegQueryValueExA( newkey, "MRUList", 0, &type, mp->realMRU,
-                                 &datasize))) {
+       datasize = (mp->extview.nMaxItems + 1) * sizeof(WCHAR);
+       if((err=RegQueryValueExW( newkey, strMRUList, 0, &type,
+                                 (LPBYTE)mp->realMRU, &datasize))) {
            /* not present - set size to 1 (will become 0 later) */
            datasize = 1;
            *mp->realMRU = 0;
        }
+        else
+            datasize /= sizeof(WCHAR);
 
-       TRACE("MRU list = %s\n", mp->realMRU);
+       TRACE("MRU list = %s, datasize = %d\n", debugstr_w(mp->realMRU), datasize);
 
        mp->cursize = datasize - 1;
        /* datasize now has number of items in the MRUList */
@@ -897,8 +712,7 @@ HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp)
                /* not present - what to do ??? */
                ERR("Key %s not found 1\n", debugstr_w(realname));
            }
-           mp->array[i] = witem = (LPWINEMRUITEM)COMCTL32_Alloc(datasize +
-                                                                sizeof(WINEMRUITEM));
+           mp->array[i] = witem = Alloc(datasize + sizeof(WINEMRUITEM));
            witem->size = datasize;
            if(RegQueryValueExW( newkey, realname, 0, &type,
                                 &witem->datastart, &datasize)) {
@@ -911,32 +725,33 @@ HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp)
     else
        mp->cursize = 0;
 
-    TRACE("(%lu %lu %lx %lx \"%s\" %p): Current Size = %ld\n",
+    TRACE("(%u %u %x %p %s %p): Current Size = %d\n",
          mp->extview.cbSize, mp->extview.nMaxItems, mp->extview.dwFlags,
-         (DWORD)mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey),
-         mp->extview.lpfnCompare, mp->cursize);
-    return (HANDLE)mp;
+         mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey),
+         mp->extview.u.string_cmpfn, mp->cursize);
+    return mp;
 }
 
 /**************************************************************************
  *                  CreateMRUListLazyW [COMCTL32.404]
+ *
+ * See CreateMRUListLazyA.
  */
-HANDLE WINAPI
-CreateMRUListLazyW (LPCREATEMRULISTW lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
+HANDLE WINAPI CreateMRUListLazyW (const CREATEMRULISTW *lpcml, DWORD dwParam2,
+                                  DWORD dwParam3, DWORD dwParam4)
 {
     LPWINEMRULIST mp;
 
-    if (lpcml == NULL)
-       return 0;
+    /* Native does not check for a NULL lpcml */
 
-    if (lpcml->cbSize < sizeof(CREATEMRULISTW))
-       return 0;
+    if (lpcml->cbSize != sizeof(CREATEMRULISTW) || !lpcml->hKey ||
+        IsBadStringPtrW(lpcml->lpszSubKey, -1))
+       return NULL;
 
-    mp = (LPWINEMRULIST) COMCTL32_Alloc(sizeof(WINEMRULIST));
+    mp = Alloc(sizeof(WINEMRULIST));
     memcpy(&mp->extview, lpcml, sizeof(CREATEMRULISTW));
-    mp->extview.lpszSubKey = COMCTL32_Alloc((strlenW(lpcml->lpszSubKey) + 1) *
-                                           sizeof(WCHAR));
-    strcpyW((LPWSTR)mp->extview.lpszSubKey, lpcml->lpszSubKey);
+    mp->extview.lpszSubKey = Alloc((strlenW(lpcml->lpszSubKey) + 1) * sizeof(WCHAR));
+    strcpyW(mp->extview.lpszSubKey, lpcml->lpszSubKey);
     mp->isUnicode = TRUE;
 
     return CreateMRUListLazy_common(mp);
@@ -944,25 +759,36 @@ CreateMRUListLazyW (LPCREATEMRULISTW lpcml, DWORD dwParam2, DWORD dwParam3, DWOR
 
 /**************************************************************************
  *                  CreateMRUListLazyA [COMCTL32.157]
+ *
+ * Creates a most-recently-used list.
+ *
+ * PARAMS
+ *     lpcml    [I] ptr to CREATEMRULIST structure.
+ *     dwParam2 [I] Unknown
+ *     dwParam3 [I] Unknown
+ *     dwParam4 [I] Unknown
+ *
+ * RETURNS
+ *     Handle to MRU list.
  */
-HANDLE WINAPI
-CreateMRUListLazyA (LPCREATEMRULISTA lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
+HANDLE WINAPI CreateMRUListLazyA (const CREATEMRULISTA *lpcml, DWORD dwParam2,
+                                  DWORD dwParam3, DWORD dwParam4)
 {
     LPWINEMRULIST mp;
     DWORD len;
 
-    if (lpcml == NULL)
-       return 0;
+    /* Native does not check for a NULL lpcml */
 
-    if (lpcml->cbSize < sizeof(CREATEMRULISTA))
+    if (lpcml->cbSize != sizeof(CREATEMRULISTA) || !lpcml->hKey ||
+        IsBadStringPtrA(lpcml->lpszSubKey, -1))
        return 0;
 
-    mp = (LPWINEMRULIST) COMCTL32_Alloc(sizeof(WINEMRULIST));
+    mp = Alloc(sizeof(WINEMRULIST));
     memcpy(&mp->extview, lpcml, sizeof(CREATEMRULISTW));
     len = MultiByteToWideChar(CP_ACP, 0, lpcml->lpszSubKey, -1, NULL, 0);
-    mp->extview.lpszSubKey = COMCTL32_Alloc(len * sizeof(WCHAR));
+    mp->extview.lpszSubKey = Alloc(len * sizeof(WCHAR));
     MultiByteToWideChar(CP_ACP, 0, lpcml->lpszSubKey, -1,
-                       (LPWSTR)mp->extview.lpszSubKey, len);
+                       mp->extview.lpszSubKey, len);
     mp->isUnicode = FALSE;
     return CreateMRUListLazy_common(mp);
 }
@@ -970,23 +796,25 @@ CreateMRUListLazyA (LPCREATEMRULISTA lpcml, DWORD dwParam2, DWORD dwParam3, DWOR
 /**************************************************************************
  *              CreateMRUListW [COMCTL32.400]
  *
- * PARAMS
- *     lpcml [I] ptr to CREATEMRULIST structure.
- *
- * RETURNS
- *     Handle to MRU list.
+ * See CreateMRUListA.
  */
-HANDLE WINAPI
-CreateMRUListW (LPCREATEMRULISTW lpcml)
+HANDLE WINAPI CreateMRUListW (const CREATEMRULISTW *lpcml)
 {
     return CreateMRUListLazyW(lpcml, 0, 0, 0);
 }
 
 /**************************************************************************
  *              CreateMRUListA [COMCTL32.151]
+ *
+ * Creates a most-recently-used list.
+ *
+ * PARAMS
+ *     lpcml [I] ptr to CREATEMRULIST structure.
+ *
+ * RETURNS
+ *     Handle to MRU list.
  */
-HANDLE WINAPI
-CreateMRUListA (LPCREATEMRULISTA lpcml)
+HANDLE WINAPI CreateMRUListA (const CREATEMRULISTA *lpcml)
 {
      return CreateMRUListLazyA (lpcml, 0, 0, 0);
 }
@@ -995,7 +823,7 @@ CreateMRUListA (LPCREATEMRULISTA lpcml)
 /**************************************************************************
  *                EnumMRUListW [COMCTL32.403]
  *
- * Enumerate item in a list
+ * Enumerate item in a most-recently-used list
  *
  * PARAMS
  *    hList [I] list handle
@@ -1010,22 +838,23 @@ CreateMRUListA (LPCREATEMRULISTA lpcml)
  *    If lpBuffer == NULL or nItemPos is -ve return value is no. of items in
  *    the list.
  */
-INT WINAPI EnumMRUListW(HANDLE hList, INT nItemPos, LPVOID lpBuffer,
-DWORD nBufferSize)
+INT WINAPI EnumMRUListW (HANDLE hList, INT nItemPos, LPVOID lpBuffer,
+                         DWORD nBufferSize)
 {
-    LPWINEMRULIST mp = (LPWINEMRULIST) hList;
-    LPWINEMRUITEM witem;
+    const WINEMRULIST *mp = hList;
+    const WINEMRUITEM *witem;
     INT desired, datasize;
 
-    if (nItemPos >= mp->cursize) return -1;
+    if (!mp) return -1;
     if ((nItemPos < 0) || !lpBuffer) return mp->cursize;
+    if (nItemPos >= mp->cursize) return -1;
     desired = mp->realMRU[nItemPos];
     desired -= 'a';
     TRACE("nItemPos=%d, desired=%d\n", nItemPos, desired);
     witem = mp->array[desired];
     datasize = min( witem->size, nBufferSize );
     memcpy( lpBuffer, &witem->datastart, datasize);
-    TRACE("(%p, %d, %p, %ld): returning len=%d\n",
+    TRACE("(%p, %d, %p, %d): returning len=%d\n",
          hList, nItemPos, lpBuffer, nBufferSize, datasize);
     return datasize;
 }
@@ -1033,17 +862,19 @@ DWORD nBufferSize)
 /**************************************************************************
  *                EnumMRUListA [COMCTL32.154]
  *
+ * See EnumMRUListW.
  */
-INT WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer,
-DWORD nBufferSize)
+INT WINAPI EnumMRUListA (HANDLE hList, INT nItemPos, LPVOID lpBuffer,
+                         DWORD nBufferSize)
 {
-    LPWINEMRULIST mp = (LPWINEMRULIST) hList;
+    const WINEMRULIST *mp = hList;
     LPWINEMRUITEM witem;
     INT desired, datasize;
     DWORD lenA;
 
-    if (nItemPos >= mp->cursize) return -1;
+    if (!mp) return -1;
     if ((nItemPos < 0) || !lpBuffer) return mp->cursize;
+    if (nItemPos >= mp->cursize) return -1;
     desired = mp->realMRU[nItemPos];
     desired -= 'a';
     TRACE("nItemPos=%d, desired=%d\n", nItemPos, desired);
@@ -1054,36 +885,39 @@ DWORD nBufferSize)
     } else {
         lenA = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&witem->datastart, -1,
                                   NULL, 0, NULL, NULL);
-       datasize = min( witem->size, nBufferSize );
+       datasize = min( lenA, nBufferSize );
        WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&witem->datastart, -1,
                            lpBuffer, datasize, NULL, NULL);
+        ((char *)lpBuffer)[ datasize - 1 ] = '\0';
+        datasize = lenA - 1;
     }
-    TRACE("(%p, %d, %p, %ld): returning len=%d\n",
+    TRACE("(%p, %d, %p, %d): returning len=%d\n",
          hList, nItemPos, lpBuffer, nBufferSize, datasize);
     return datasize;
 }
 
-
 /**************************************************************************
- * Str_GetPtrA [COMCTL32.233]
+ * Str_GetPtrWtoA [internal]
+ *
+ * Converts a unicode string into a multi byte string
  *
  * PARAMS
- *     lpSrc   [I]
- *     lpDest  [O]
- *     nMaxLen [I]
+ *     lpSrc   [I] Pointer to the unicode source string
+ *     lpDest  [O] Pointer to caller supplied storage for the multi byte string
+ *     nMaxLen [I] Size, in bytes, of the destination buffer
  *
  * RETURNS
+ *     Length, in bytes, of the converted string.
  */
 
-INT WINAPI
-Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen)
+INT Str_GetPtrWtoA (LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen)
 {
     INT len;
 
-    TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
+    TRACE("(%s %p %d)\n", debugstr_w(lpSrc), lpDest, nMaxLen);
 
     if (!lpDest && lpSrc)
-       return strlen (lpSrc);
+       return WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
 
     if (nMaxLen == 0)
        return 0;
@@ -1093,1157 +927,132 @@ Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen)
        return 0;
     }
 
-    len = strlen (lpSrc);
+    len = WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
     if (len >= nMaxLen)
        len = nMaxLen - 1;
 
-    RtlMoveMemory (lpDest, lpSrc, len);
+    WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, lpDest, len, NULL, NULL);
     lpDest[len] = '\0';
 
     return len;
 }
 
-
 /**************************************************************************
- * Str_SetPtrA [COMCTL32.234]
- *
- * PARAMS
- *     lppDest [O]
- *     lpSrc   [I]
+ * Str_GetPtrAtoW [internal]
  *
- * RETURNS
- */
-
-BOOL WINAPI
-Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc)
-{
-    TRACE("(%p %p)\n", lppDest, lpSrc);
-
-    if (lpSrc) {
-       LPSTR ptr = COMCTL32_ReAlloc (*lppDest, strlen (lpSrc) + 1);
-       if (!ptr)
-           return FALSE;
-       strcpy (ptr, lpSrc);
-       *lppDest = ptr;
-    }
-    else {
-       if (*lppDest) {
-           COMCTL32_Free (*lppDest);
-           *lppDest = NULL;
-       }
-    }
-
-    return TRUE;
-}
-
-
-/**************************************************************************
- * Str_GetPtrW [COMCTL32.235]
+ * Converts a multibyte string into a unicode string
  *
  * PARAMS
- *     lpSrc   [I]
- *     lpDest  [O]
- *     nMaxLen [I]
+ *     lpSrc   [I] Pointer to the multibyte source string
+ *     lpDest  [O] Pointer to caller supplied storage for the unicode string
+ *     nMaxLen [I] Size, in characters, of the destination buffer
  *
  * RETURNS
+ *     Length, in characters, of the converted string.
  */
 
-INT WINAPI
-Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen)
+INT Str_GetPtrAtoW (LPCSTR lpSrc, LPWSTR lpDest, INT nMaxLen)
 {
     INT len;
 
-    TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
+    TRACE("(%s %p %d)\n", debugstr_a(lpSrc), lpDest, nMaxLen);
 
     if (!lpDest && lpSrc)
-       return strlenW (lpSrc);
+       return MultiByteToWideChar(CP_ACP, 0, lpSrc, -1, 0, 0);
 
     if (nMaxLen == 0)
        return 0;
 
     if (lpSrc == NULL) {
-       lpDest[0] = L'\0';
+       lpDest[0] = '\0';
        return 0;
     }
 
-    len = strlenW (lpSrc);
+    len = MultiByteToWideChar(CP_ACP, 0, lpSrc, -1, 0, 0);
     if (len >= nMaxLen)
        len = nMaxLen - 1;
 
-    RtlMoveMemory (lpDest, lpSrc, len*sizeof(WCHAR));
-    lpDest[len] = L'\0';
+    MultiByteToWideChar(CP_ACP, 0, lpSrc, -1, lpDest, len);
+    lpDest[len] = '\0';
 
     return len;
 }
 
 
 /**************************************************************************
- * Str_SetPtrW [COMCTL32.236]
+ * Str_SetPtrAtoW [internal]
+ *
+ * Converts a multi byte string to a unicode string.
+ * If the pointer to the destination buffer is NULL a buffer is allocated.
+ * If the destination buffer is too small to keep the converted multi byte
+ * string the destination buffer is reallocated. If the source pointer is
+ * NULL, the destination buffer is freed.
  *
  * PARAMS
- *     lpDest [O]
- *     lpSrc  [I]
+ *     lppDest [I/O] pointer to a pointer to the destination buffer
+ *     lpSrc   [I] pointer to a multi byte string
  *
  * RETURNS
+ *     TRUE: conversion successful
+ *     FALSE: error
  */
-
-BOOL WINAPI
-Str_SetPtrW (LPWSTR *lppDest, LPCWSTR lpSrc)
+BOOL Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc)
 {
-    TRACE("(%p %p)\n", lppDest, lpSrc);
+    TRACE("(%p %s)\n", lppDest, lpSrc);
 
     if (lpSrc) {
-       INT len = strlenW (lpSrc) + 1;
-       LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len * sizeof(WCHAR));
+       INT len = MultiByteToWideChar(CP_ACP,0,lpSrc,-1,NULL,0);
+       LPWSTR ptr = ReAlloc (*lppDest, len*sizeof(WCHAR));
+
        if (!ptr)
            return FALSE;
-       strcpyW (ptr, lpSrc);
+       MultiByteToWideChar(CP_ACP,0,lpSrc,-1,ptr,len);
        *lppDest = ptr;
     }
     else {
-       if (*lppDest) {
-           COMCTL32_Free (*lppDest);
-           *lppDest = NULL;
-       }
+        Free (*lppDest);
+        *lppDest = NULL;
     }
 
     return TRUE;
 }
 
-
 /**************************************************************************
- * Str_GetPtrWtoA [internal]
+ * Str_SetPtrWtoA [internal]
  *
- * Converts a unicode string into a multi byte string
+ * Converts a unicode string to a multi byte string.
+ * If the pointer to the destination buffer is NULL a buffer is allocated.
+ * If the destination buffer is too small to keep the converted wide
+ * string the destination buffer is reallocated. If the source pointer is
+ * NULL, the destination buffer is freed.
  *
  * PARAMS
- *     lpSrc   [I] Pointer to the unicode source string
- *     lpDest  [O] Pointer to caller supplied storage for the multi byte string
- *     nMaxLen [I] Size, in bytes, of the destination buffer
+ *     lppDest [I/O] pointer to a pointer to the destination buffer
+ *     lpSrc   [I] pointer to a wide string
  *
  * RETURNS
- *     Length, in bytes, of the converted string.
+ *     TRUE: conversion successful
+ *     FALSE: error
  */
-
-INT
-Str_GetPtrWtoA (LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen)
+BOOL Str_SetPtrWtoA (LPSTR *lppDest, LPCWSTR lpSrc)
 {
-    INT len;
+    TRACE("(%p %s)\n", lppDest, debugstr_w(lpSrc));
 
-    TRACE("(%s %p %d)\n", debugstr_w(lpSrc), lpDest, nMaxLen);
+    if (lpSrc) {
+        INT len = WideCharToMultiByte(CP_ACP,0,lpSrc,-1,NULL,0,NULL,FALSE);
+        LPSTR ptr = ReAlloc (*lppDest, len*sizeof(CHAR));
 
-    if (!lpDest && lpSrc)
-       return WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
+        if (!ptr)
+            return FALSE;
+        WideCharToMultiByte(CP_ACP,0,lpSrc,-1,ptr,len,NULL,FALSE);
+        *lppDest = ptr;
+    }
+    else {
+        Free (*lppDest);
+        *lppDest = NULL;
+    }
 
-    if (nMaxLen == 0)
-       return 0;
-
-    if (lpSrc == NULL) {
-       lpDest[0] = '\0';
-       return 0;
-    }
-
-    len = WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
-    if (len >= nMaxLen)
-       len = nMaxLen - 1;
-
-    WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, lpDest, len, NULL, NULL);
-    lpDest[len] = '\0';
-
-    return len;
-}
-
-
-/**************************************************************************
- * Str_SetPtrAtoW [internal]
- *
- * Converts a multi byte string to a unicode string.
- * If the pointer to the destination buffer is NULL a buffer is allocated.
- * If the destination buffer is too small to keep the converted multi byte
- * string the destination buffer is reallocated. If the source pointer is
- * NULL, the destination buffer is freed.
- *
- * PARAMS
- *     lppDest [I/O] pointer to a pointer to the destination buffer
- *     lpSrc   [I] pointer to a multi byte string
- *
- * RETURNS
- *     TRUE: conversion successful
- *     FALSE: error
- */
-
-BOOL
-Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc)
-{
-    TRACE("(%p %s)\n", lppDest, lpSrc);
-
-    if (lpSrc) {
-       INT len = MultiByteToWideChar(CP_ACP,0,lpSrc,-1,NULL,0);
-       LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len*sizeof(WCHAR));
-
-       if (!ptr)
-           return FALSE;
-       MultiByteToWideChar(CP_ACP,0,lpSrc,-1,ptr,len);
-       *lppDest = ptr;
-    }
-    else {
-       if (*lppDest) {
-           COMCTL32_Free (*lppDest);
-           *lppDest = NULL;
-       }
-    }
-
-    return TRUE;
-}
-
-
-/**************************************************************************
- * The DSA-API is a set of functions to create and manipulate arrays of
- * fixed-size memory blocks. These arrays can store any kind of data
- * (strings, icons...).
- */
-
-/**************************************************************************
- * DSA_Create [COMCTL32.320] Creates a dynamic storage array
- *
- * PARAMS
- *     nSize [I] size of the array elements
- *     nGrow [I] number of elements by which the array grows when it is filled
- *
- * RETURNS
- *     Success: pointer to an array control structure. Use this like a handle.
- *     Failure: NULL
- */
-
-HDSA WINAPI
-DSA_Create (INT nSize, INT nGrow)
-{
-    HDSA hdsa;
-
-    TRACE("(size=%d grow=%d)\n", nSize, nGrow);
-
-    hdsa = (HDSA)COMCTL32_Alloc (sizeof(DSA));
-    if (hdsa)
-    {
-       hdsa->nItemCount = 0;
-        hdsa->pData = NULL;
-       hdsa->nMaxCount = 0;
-       hdsa->nItemSize = nSize;
-       hdsa->nGrow = max(1, nGrow);
-    }
-
-    return hdsa;
-}
-
-
-/**************************************************************************
- * DSA_Destroy [COMCTL32.321] Destroys a dynamic storage array
- *
- * PARAMS
- *     hdsa [I] pointer to the array control structure
- *
- * RETURNS
- *     Success: TRUE
- *     Failure: FALSE
- */
-
-BOOL WINAPI
-DSA_Destroy (const HDSA hdsa)
-{
-    TRACE("(%p)\n", hdsa);
-
-    if (!hdsa)
-       return FALSE;
-
-    if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
-       return FALSE;
-
-    return COMCTL32_Free (hdsa);
-}
-
-
-/**************************************************************************
- * DSA_GetItem [COMCTL32.322]
- *
- * PARAMS
- *     hdsa   [I] pointer to the array control structure
- *     nIndex [I] number of the Item to get
- *     pDest  [O] destination buffer. Has to be >= dwElementSize.
- *
- * RETURNS
- *     Success: TRUE
- *     Failure: FALSE
- */
-
-BOOL WINAPI
-DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest)
-{
-    LPVOID pSrc;
-
-    TRACE("(%p %d %p)\n", hdsa, nIndex, pDest);
-
-    if (!hdsa)
-       return FALSE;
-    if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
-       return FALSE;
-
-    pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
-    memmove (pDest, pSrc, hdsa->nItemSize);
-
-    return TRUE;
-}
-
-
-/**************************************************************************
- * DSA_GetItemPtr [COMCTL32.323]
- *
- * Retrieves a pointer to the specified item.
- *
- * PARAMS
- *     hdsa   [I] pointer to the array control structure
- *     nIndex [I] index of the desired item
- *
- * RETURNS
- *     Success: pointer to an item
- *     Failure: NULL
- */
-
-LPVOID WINAPI
-DSA_GetItemPtr (const HDSA hdsa, INT nIndex)
-{
-    LPVOID pSrc;
-
-    TRACE("(%p %d)\n", hdsa, nIndex);
-
-    if (!hdsa)
-       return NULL;
-    if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
-       return NULL;
-
-    pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
-
-    TRACE("-- ret=%p\n", pSrc);
-
-    return pSrc;
-}
-
-
-/**************************************************************************
- * DSA_SetItem [COMCTL32.325]
- *
- * Sets the contents of an item in the array.
- *
- * PARAMS
- *     hdsa   [I] pointer to the array control structure
- *     nIndex [I] index for the item
- *     pSrc   [I] pointer to the new item data
- *
- * RETURNS
- *     Success: TRUE
- *     Failure: FALSE
- */
-
-BOOL WINAPI
-DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
-{
-    INT  nSize, nNewItems;
-    LPVOID pDest, lpTemp;
-
-    TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
-
-    if ((!hdsa) || nIndex < 0)
-       return FALSE;
-
-    if (hdsa->nItemCount <= nIndex) {
-       /* within the old array */
-       if (hdsa->nMaxCount > nIndex) {
-           /* within the allocated space, set a new boundary */
-           hdsa->nItemCount = nIndex + 1;
-       }
-       else {
-           /* resize the block of memory */
-           nNewItems =
-               hdsa->nGrow * ((INT)(((nIndex + 1) - 1) / hdsa->nGrow) + 1);
-           nSize = hdsa->nItemSize * nNewItems;
-
-           lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
-           if (!lpTemp)
-               return FALSE;
-
-           hdsa->nMaxCount = nNewItems;
-           hdsa->nItemCount = nIndex + 1;
-           hdsa->pData = lpTemp;
-       }
-    }
-
-    /* put the new entry in */
-    pDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
-    TRACE("-- move dest=%p src=%p size=%d\n",
-          pDest, pSrc, hdsa->nItemSize);
-    memmove (pDest, pSrc, hdsa->nItemSize);
-
-    return TRUE;
-}
-
-
-/**************************************************************************
- * DSA_InsertItem [COMCTL32.324]
- *
- * PARAMS
- *     hdsa   [I] pointer to the array control structure
- *     nIndex [I] index for the new item
- *     pSrc   [I] pointer to the element
- *
- * RETURNS
- *     Success: position of the new item
- *     Failure: -1
- */
-
-INT WINAPI
-DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
-{
-    INT   nNewItems, nSize;
-    LPVOID  lpTemp, lpDest;
-
-    TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
-
-    if ((!hdsa) || nIndex < 0)
-       return -1;
-
-    /* when nIndex >= nItemCount then append */
-    if (nIndex >= hdsa->nItemCount)
-       nIndex = hdsa->nItemCount;
-
-    /* do we need to resize ? */
-    if (hdsa->nItemCount >= hdsa->nMaxCount) {
-       nNewItems = hdsa->nMaxCount + hdsa->nGrow;
-       nSize = hdsa->nItemSize * nNewItems;
-
-       lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
-       if (!lpTemp)
-           return -1;
-
-       hdsa->nMaxCount = nNewItems;
-       hdsa->pData = lpTemp;
-    }
-
-    /* do we need to move elements ? */
-    if (nIndex < hdsa->nItemCount) {
-       lpTemp = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
-       lpDest = (char *) lpTemp + hdsa->nItemSize;
-       nSize = (hdsa->nItemCount - nIndex) * hdsa->nItemSize;
-       TRACE("-- move dest=%p src=%p size=%d\n",
-              lpDest, lpTemp, nSize);
-       memmove (lpDest, lpTemp, nSize);
-    }
-
-    /* ok, we can put the new Item in */
-    hdsa->nItemCount++;
-    lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
-    TRACE("-- move dest=%p src=%p size=%d\n",
-          lpDest, pSrc, hdsa->nItemSize);
-    memmove (lpDest, pSrc, hdsa->nItemSize);
-
-    return nIndex;
-}
-
-
-/**************************************************************************
- * DSA_DeleteItem [COMCTL32.326]
- *
- * PARAMS
- *     hdsa   [I] pointer to the array control structure
- *     nIndex [I] index for the element to delete
- *
- * RETURNS
- *     Success: number of the deleted element
- *     Failure: -1
- */
-
-INT WINAPI
-DSA_DeleteItem (const HDSA hdsa, INT nIndex)
-{
-    LPVOID lpDest,lpSrc;
-    INT  nSize;
-
-    TRACE("(%p %d)\n", hdsa, nIndex);
-
-    if (!hdsa)
-       return -1;
-    if (nIndex < 0 || nIndex >= hdsa->nItemCount)
-       return -1;
-
-    /* do we need to move ? */
-    if (nIndex < hdsa->nItemCount - 1) {
-       lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
-       lpSrc = (char *) lpDest + hdsa->nItemSize;
-       nSize = hdsa->nItemSize * (hdsa->nItemCount - nIndex - 1);
-       TRACE("-- move dest=%p src=%p size=%d\n",
-              lpDest, lpSrc, nSize);
-       memmove (lpDest, lpSrc, nSize);
-    }
-
-    hdsa->nItemCount--;
-
-    /* free memory ? */
-    if ((hdsa->nMaxCount - hdsa->nItemCount) >= hdsa->nGrow) {
-       nSize = hdsa->nItemSize * hdsa->nItemCount;
-
-       lpDest = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
-       if (!lpDest)
-           return -1;
-
-       hdsa->nMaxCount = hdsa->nItemCount;
-       hdsa->pData = lpDest;
-    }
-
-    return nIndex;
-}
-
-
-/**************************************************************************
- * DSA_DeleteAllItems [COMCTL32.327]
- *
- * Removes all items and reinitializes the array.
- *
- * PARAMS
- *     hdsa [I] pointer to the array control structure
- *
- * RETURNS
- *     Success: TRUE
- *     Failure: FALSE
- */
-
-BOOL WINAPI
-DSA_DeleteAllItems (const HDSA hdsa)
-{
-    TRACE("(%p)\n", hdsa);
-
-    if (!hdsa)
-       return FALSE;
-    if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
-       return FALSE;
-
-    hdsa->nItemCount = 0;
-    hdsa->pData = NULL;
-    hdsa->nMaxCount = 0;
-
-    return TRUE;
-}
-
-
-/**************************************************************************
- * The DPA-API is a set of functions to create and manipulate arrays of
- * pointers.
- */
-
-/**************************************************************************
- * DPA_Create [COMCTL32.328] Creates a dynamic pointer array
- *
- * PARAMS
- *     nGrow [I] number of items by which the array grows when it is filled
- *
- * RETURNS
- *     Success: handle (pointer) to the pointer array.
- *     Failure: NULL
- */
-
-HDPA WINAPI
-DPA_Create (INT nGrow)
-{
-    HDPA hdpa;
-
-    TRACE("(%d)\n", nGrow);
-
-    hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
-    if (hdpa) {
-       hdpa->nGrow = max(8, nGrow);
-       hdpa->hHeap = COMCTL32_hHeap;
-       hdpa->nMaxCount = hdpa->nGrow * 2;
-       hdpa->ptrs =
-           (LPVOID*)COMCTL32_Alloc (hdpa->nMaxCount * sizeof(LPVOID));
-    }
-
-    TRACE("-- %p\n", hdpa);
-
-    return hdpa;
-}
-
-
-/**************************************************************************
- * DPA_Destroy [COMCTL32.329] Destroys a dynamic pointer array
- *
- * PARAMS
- *     hdpa [I] handle (pointer) to the pointer array
- *
- * RETURNS
- *     Success: TRUE
- *     Failure: FALSE
- */
-
-BOOL WINAPI
-DPA_Destroy (const HDPA hdpa)
-{
-    TRACE("(%p)\n", hdpa);
-
-    if (!hdpa)
-       return FALSE;
-
-    if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
-       return FALSE;
-
-    return HeapFree (hdpa->hHeap, 0, hdpa);
-}
-
-
-/**************************************************************************
- * DPA_Grow [COMCTL32.330]
- *
- * Sets the growth amount.
- *
- * PARAMS
- *     hdpa  [I] handle (pointer) to the existing (source) pointer array
- *     nGrow [I] number of items by which the array grows when it's too small
- *
- * RETURNS
- *     Success: TRUE
- *     Failure: FALSE
- */
-
-BOOL WINAPI
-DPA_Grow (const HDPA hdpa, INT nGrow)
-{
-    TRACE("(%p %d)\n", hdpa, nGrow);
-
-    if (!hdpa)
-       return FALSE;
-
-    hdpa->nGrow = max(8, nGrow);
-
-    return TRUE;
-}
-
-
-/**************************************************************************
- * DPA_Clone [COMCTL32.331]
- *
- * Copies a pointer array to an other one or creates a copy
- *
- * PARAMS
- *     hdpa    [I] handle (pointer) to the existing (source) pointer array
- *     hdpaNew [O] handle (pointer) to the destination pointer array
- *
- * RETURNS
- *     Success: pointer to the destination pointer array.
- *     Failure: NULL
- *
- * NOTES
- *     - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer
- *       array will be created and it's handle (pointer) is returned.
- *     - If 'hdpa' is a NULL-Pointer, the original implementation crashes,
- *       this implementation just returns NULL.
- */
-
-HDPA WINAPI
-DPA_Clone (const HDPA hdpa, const HDPA hdpaNew)
-{
-    INT nNewItems, nSize;
-    HDPA hdpaTemp;
-
-    if (!hdpa)
-       return NULL;
-
-    TRACE("(%p %p)\n", hdpa, hdpaNew);
-
-    if (!hdpaNew) {
-       /* create a new DPA */
-       hdpaTemp = (HDPA)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
-                                   sizeof(DPA));
-       hdpaTemp->hHeap = hdpa->hHeap;
-       hdpaTemp->nGrow = hdpa->nGrow;
-    }
-    else
-       hdpaTemp = hdpaNew;
-
-    if (hdpaTemp->ptrs) {
-       /* remove old pointer array */
-       HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs);
-       hdpaTemp->ptrs = NULL;
-       hdpaTemp->nItemCount = 0;
-       hdpaTemp->nMaxCount = 0;
-    }
-
-    /* create a new pointer array */
-    nNewItems = hdpaTemp->nGrow *
-               ((INT)((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1);
-    nSize = nNewItems * sizeof(LPVOID);
-    hdpaTemp->ptrs =
-       (LPVOID*)HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize);
-    hdpaTemp->nMaxCount = nNewItems;
-
-    /* clone the pointer array */
-    hdpaTemp->nItemCount = hdpa->nItemCount;
-    memmove (hdpaTemp->ptrs, hdpa->ptrs,
-            hdpaTemp->nItemCount * sizeof(LPVOID));
-
-    return hdpaTemp;
-}
-
-
-/**************************************************************************
- * DPA_GetPtr [COMCTL32.332]
- *
- * Retrieves a pointer from a dynamic pointer array
- *
- * PARAMS
- *     hdpa   [I] handle (pointer) to the pointer array
- *     nIndex [I] array index of the desired pointer
- *
- * RETURNS
- *     Success: pointer
- *     Failure: NULL
- */
-
-LPVOID WINAPI
-DPA_GetPtr (const HDPA hdpa, INT i)
-{
-    TRACE("(%p %d)\n", hdpa, i);
-
-    if (!hdpa)
-       return NULL;
-    if (!hdpa->ptrs) {
-       WARN("no pointer array.\n");
-       return NULL;
-    }
-    if ((i < 0) || (i >= hdpa->nItemCount)) {
-       WARN("not enough pointers in array (%d vs %d).\n",i,hdpa->nItemCount);
-       return NULL;
-    }
-
-    TRACE("-- %p\n", hdpa->ptrs[i]);
-
-    return hdpa->ptrs[i];
-}
-
-
-/**************************************************************************
- * DPA_GetPtrIndex [COMCTL32.333]
- *
- * Retrieves the index of the specified pointer
- *
- * PARAMS
- *     hdpa   [I] handle (pointer) to the pointer array
- *     p      [I] pointer
- *
- * RETURNS
- *     Success: index of the specified pointer
- *     Failure: -1
- */
-
-INT WINAPI
-DPA_GetPtrIndex (const HDPA hdpa, LPVOID p)
-{
-    INT i;
-
-    if (!hdpa || !hdpa->ptrs)
-       return -1;
-
-    for (i = 0; i < hdpa->nItemCount; i++) {
-       if (hdpa->ptrs[i] == p)
-           return i;
-    }
-
-    return -1;
-}
-
-
-/**************************************************************************
- * DPA_InsertPtr [COMCTL32.334]
- *
- * Inserts a pointer into a dynamic pointer array
- *
- * PARAMS
- *     hdpa [I] handle (pointer) to the array
- *     i    [I] array index
- *     p    [I] pointer to insert
- *
- * RETURNS
- *     Success: index of the inserted pointer
- *     Failure: -1
- */
-
-INT WINAPI
-DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p)
-{
-    TRACE("(%p %d %p)\n", hdpa, i, p);
-
-    if (!hdpa || i < 0) return -1;
-
-    if (i == 0x7fff)
-       i = hdpa->nItemCount;
-
-    if (i >= hdpa->nItemCount)
-       return DPA_SetPtr(hdpa, i, p) ? i : -1;
-
-    /* create empty spot at the end */
-    if (!DPA_SetPtr(hdpa, hdpa->nItemCount, 0)) return -1;
-    memmove (hdpa->ptrs + i + 1, hdpa->ptrs + i, (hdpa->nItemCount - i - 1) * sizeof(LPVOID));
-    hdpa->ptrs[i] = p;
-    return i;
-}
-
-/**************************************************************************
- * DPA_SetPtr [COMCTL32.335]
- *
- * Sets a pointer in the pointer array
- *
- * PARAMS
- *     hdpa [I] handle (pointer) to the pointer array
- *     i    [I] index of the pointer that will be set
- *     p    [I] pointer to be set
- *
- * RETURNS
- *     Success: TRUE
- *     Failure: FALSE
- */
-
-BOOL WINAPI
-DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p)
-{
-    LPVOID *lpTemp;
-
-    TRACE("(%p %d %p)\n", hdpa, i, p);
-
-    if (!hdpa || i < 0 || i > 0x7fff)
-       return FALSE;
-
-    if (hdpa->nItemCount <= i) {
-       /* within the old array */
-       if (hdpa->nMaxCount <= i) {
-           /* resize the block of memory */
-           INT nNewItems =
-               hdpa->nGrow * ((INT)(((i+1) - 1) / hdpa->nGrow) + 1);
-           INT nSize = nNewItems * sizeof(LPVOID);
-
-           if (hdpa->ptrs)
-               lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, hdpa->ptrs, nSize);
-           else
-               lpTemp = (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY, nSize);
-           
-           if (!lpTemp)
-               return FALSE;
-
-           hdpa->nMaxCount = nNewItems;
-           hdpa->ptrs = lpTemp;
-       }
-        hdpa->nItemCount = i+1;
-    }
-
-    /* put the new entry in */
-    hdpa->ptrs[i] = p;
-
-    return TRUE;
-}
-
-
-/**************************************************************************
- * DPA_DeletePtr [COMCTL32.336]
- *
- * Removes a pointer from the pointer array.
- *
- * PARAMS
- *     hdpa [I] handle (pointer) to the pointer array
- *     i    [I] index of the pointer that will be deleted
- *
- * RETURNS
- *     Success: deleted pointer
- *     Failure: NULL
- */
-
-LPVOID WINAPI
-DPA_DeletePtr (const HDPA hdpa, INT i)
-{
-    LPVOID *lpDest, *lpSrc, lpTemp = NULL;
-    INT  nSize;
-
-    TRACE("(%p %d)\n", hdpa, i);
-
-    if ((!hdpa) || i < 0 || i >= hdpa->nItemCount)
-       return NULL;
-
-    lpTemp = hdpa->ptrs[i];
-
-    /* do we need to move ?*/
-    if (i < hdpa->nItemCount - 1) {
-       lpDest = hdpa->ptrs + i;
-       lpSrc = lpDest + 1;
-       nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID);
-       TRACE("-- move dest=%p src=%p size=%x\n",
-              lpDest, lpSrc, nSize);
-       memmove (lpDest, lpSrc, nSize);
-    }
-
-    hdpa->nItemCount --;
-
-    /* free memory ?*/
-    if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) {
-       INT nNewItems = max(hdpa->nGrow * 2, hdpa->nItemCount);
-       nSize = nNewItems * sizeof(LPVOID);
-       lpDest = (LPVOID)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
-                                     hdpa->ptrs, nSize);
-       if (!lpDest)
-           return NULL;
-
-       hdpa->nMaxCount = nNewItems;
-       hdpa->ptrs = (LPVOID*)lpDest;
-    }
-
-    return lpTemp;
-}
-
-
-/**************************************************************************
- * DPA_DeleteAllPtrs [COMCTL32.337]
- *
- * Removes all pointers and reinitializes the array.
- *
- * PARAMS
- *     hdpa [I] handle (pointer) to the pointer array
- *
- * RETURNS
- *     Success: TRUE
- *     Failure: FALSE
- */
-
-BOOL WINAPI
-DPA_DeleteAllPtrs (const HDPA hdpa)
-{
-    TRACE("(%p)\n", hdpa);
-
-    if (!hdpa)
-       return FALSE;
-
-    if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
-       return FALSE;
-
-    hdpa->nItemCount = 0;
-    hdpa->nMaxCount = hdpa->nGrow * 2;
-    hdpa->ptrs = (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
-                                    hdpa->nMaxCount * sizeof(LPVOID));
-
-    return TRUE;
-}
-
-
-/**************************************************************************
- * DPA_QuickSort [Internal]
- *
- * Ordinary quicksort (used by DPA_Sort).
- *
- * PARAMS
- *     lpPtrs     [I] pointer to the pointer array
- *     l          [I] index of the "left border" of the partition
- *     r          [I] index of the "right border" of the partition
- *     pfnCompare [I] pointer to the compare function
- *     lParam     [I] user defined value (3rd parameter in compare function)
- *
- * RETURNS
- *     NONE
- */
-
-static VOID
-DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r,
-              PFNDPACOMPARE pfnCompare, LPARAM lParam)
-{
-    INT m;
-    LPVOID t;
-
-    TRACE("l=%i r=%i\n", l, r);
-
-    if (l==r)    /* one element is always sorted */
-        return;
-    if (r<l)     /* oops, got it in the wrong order */
-       {
-        DPA_QuickSort(lpPtrs, r, l, pfnCompare, lParam);
-        return;
-       }
-    m = (l+r)/2; /* divide by two */
-    DPA_QuickSort(lpPtrs, l, m, pfnCompare, lParam);
-    DPA_QuickSort(lpPtrs, m+1, r, pfnCompare, lParam);
-
-    /* join the two sides */
-    while( (l<=m) && (m<r) )
-    {
-        if(pfnCompare(lpPtrs[l],lpPtrs[m+1],lParam)>0)
-        {
-            t = lpPtrs[m+1];
-            memmove(&lpPtrs[l+1],&lpPtrs[l],(m-l+1)*sizeof lpPtrs[l]);
-            lpPtrs[l] = t;
-
-            m++;
-        }
-        l++;
-    }
-}
-
-
-/**************************************************************************
- * DPA_Sort [COMCTL32.338]
- *
- * Sorts a pointer array using a user defined compare function
- *
- * PARAMS
- *     hdpa       [I] handle (pointer) to the pointer array
- *     pfnCompare [I] pointer to the compare function
- *     lParam     [I] user defined value (3rd parameter of compare function)
- *
- * RETURNS
- *     Success: TRUE
- *     Failure: FALSE
- */
-
-BOOL WINAPI
-DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam)
-{
-    if (!hdpa || !pfnCompare)
-       return FALSE;
-
-    TRACE("(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam);
-
-    if ((hdpa->nItemCount > 1) && (hdpa->ptrs))
-       DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1,
-                      pfnCompare, lParam);
-
-    return TRUE;
-}
-
-
-/**************************************************************************
- * DPA_Search [COMCTL32.339]
- *
- * Searches a pointer array for a specified pointer
- *
- * PARAMS
- *     hdpa       [I] handle (pointer) to the pointer array
- *     pFind      [I] pointer to search for
- *     nStart     [I] start index
- *     pfnCompare [I] pointer to the compare function
- *     lParam     [I] user defined value (3rd parameter of compare function)
- *     uOptions   [I] search options
- *
- * RETURNS
- *     Success: index of the pointer in the array.
- *     Failure: -1
- *
- * NOTES
- *     Binary search taken from R.Sedgewick "Algorithms in C"!
- *     Function is NOT tested!
- *     If something goes wrong, blame HIM not ME! (Eric Kohl)
- */
-
-INT WINAPI
-DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart,
-           PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions)
-{
-    if (!hdpa || !pfnCompare || !pFind)
-       return -1;
-
-    TRACE("(%p %p %d %p 0x%08lx 0x%08x)\n",
-          hdpa, pFind, nStart, pfnCompare, lParam, uOptions);
-
-    if (uOptions & DPAS_SORTED) {
-       /* array is sorted --> use binary search */
-       INT l, r, x, n;
-       LPVOID *lpPtr;
-
-       TRACE("binary search\n");
-
-       l = (nStart == -1) ? 0 : nStart;
-       r = hdpa->nItemCount - 1;
-       lpPtr = hdpa->ptrs;
-       while (r >= l) {
-           x = (l + r) / 2;
-           n = (pfnCompare)(pFind, lpPtr[x], lParam);
-           if (n < 0)
-               r = x - 1;
-           else
-               l = x + 1;
-           if (n == 0) {
-               TRACE("-- ret=%d\n", n);
-               return n;
-           }
-       }
-
-       if (uOptions & DPAS_INSERTBEFORE) {
-           TRACE("-- ret=%d\n", r);
-           return r;
-       }
-
-       if (uOptions & DPAS_INSERTAFTER) {
-           TRACE("-- ret=%d\n", l);
-           return l;
-       }
-    }
-    else {
-       /* array is not sorted --> use linear search */
-       LPVOID *lpPtr;
-       INT  nIndex;
-
-       TRACE("linear search\n");
-
-       nIndex = (nStart == -1)? 0 : nStart;
-       lpPtr = hdpa->ptrs;
-       for (; nIndex < hdpa->nItemCount; nIndex++) {
-           if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) {
-               TRACE("-- ret=%d\n", nIndex);
-               return nIndex;
-           }
-       }
-    }
-
-    TRACE("-- not found: ret=-1\n");
-    return -1;
-}
-
-
-/**************************************************************************
- * DPA_CreateEx [COMCTL32.340]
- *
- * Creates a dynamic pointer array using the specified size and heap.
- *
- * PARAMS
- *     nGrow [I] number of items by which the array grows when it is filled
- *     hHeap [I] handle to the heap where the array is stored
- *
- * RETURNS
- *     Success: handle (pointer) to the pointer array.
- *     Failure: NULL
- */
-
-HDPA WINAPI
-DPA_CreateEx (INT nGrow, HANDLE hHeap)
-{
-    HDPA hdpa;
-
-    TRACE("(%d %p)\n", nGrow, hHeap);
-
-    if (hHeap)
-       hdpa = (HDPA)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(DPA));
-    else
-       hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
-
-    if (hdpa) {
-       hdpa->nGrow = min(8, nGrow);
-       hdpa->hHeap = hHeap ? hHeap : COMCTL32_hHeap;
-       hdpa->nMaxCount = hdpa->nGrow * 2;
-       hdpa->ptrs =
-           (LPVOID*)HeapAlloc (hHeap, HEAP_ZERO_MEMORY,
-                               hdpa->nMaxCount * sizeof(LPVOID));
-    }
-
-    TRACE("-- %p\n", hdpa);
-
-    return hdpa;
+    return TRUE;
 }
 
 
@@ -2266,14 +1075,13 @@ typedef struct tagNOTIFYDATA
  * DoNotify [Internal]
  */
 
-static LRESULT
-DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr)
+static LRESULT DoNotify (const NOTIFYDATA *lpNotify, UINT uCode, LPNMHDR lpHdr)
 {
     NMHDR nmhdr;
     LPNMHDR lpNmh = NULL;
     UINT idFrom = 0;
 
-    TRACE("(%p %p %d %p 0x%08lx)\n",
+    TRACE("(%p %p %d %p 0x%08x)\n",
           lpNotify->hwndFrom, lpNotify->hwndTo, uCode, lpHdr,
           lpNotify->dwParam5);
 
@@ -2285,15 +1093,8 @@ DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr)
        idFrom = lpHdr->idFrom;
     }
     else {
-       if (lpNotify->hwndFrom) {
-           HWND hwndParent = GetParent (lpNotify->hwndFrom);
-           if (hwndParent) {
-               hwndParent = GetWindow (lpNotify->hwndFrom, GW_OWNER);
-               /* the following is done even if the return from above
-                * is zero.  GLA 12/2001 */
-               idFrom = GetDlgCtrlID (lpNotify->hwndFrom);
-           }
-       }
+       if (lpNotify->hwndFrom)
+           idFrom = GetDlgCtrlID (lpNotify->hwndFrom);
 
        lpNmh = (lpHdr) ? lpHdr : &nmhdr;
 
@@ -2302,27 +1103,31 @@ DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr)
        lpNmh->code = uCode;
     }
 
-    return SendMessageA (lpNotify->hwndTo, WM_NOTIFY, idFrom, (LPARAM)lpNmh);
+    return SendMessageW (lpNotify->hwndTo, WM_NOTIFY, idFrom, (LPARAM)lpNmh);
 }
 
 
 /**************************************************************************
  * SendNotify [COMCTL32.341]
  *
+ * Sends a WM_NOTIFY message to the specified window.
+ *
  * PARAMS
- *     hwndTo   [I]
- *     hwndFrom [I]
- *     uCode    [I]
- *     lpHdr    [I]
+ *     hwndTo   [I] Window to receive the message
+ *     hwndFrom [I] Window that the message is from (see notes)
+ *     uCode    [I] Notification code
+ *     lpHdr    [I] The NMHDR and any additional information to send or NULL
  *
  * RETURNS
  *     Success: return value from notification
  *     Failure: 0
+ *
+ * NOTES
+ *     If hwndFrom is -1 then the identifier of the control sending the
+ *     message is taken from the NMHDR structure.
+ *     If hwndFrom is not -1 then lpHdr can be NULL.
  */
-
-LRESULT WINAPI
-COMCTL32_SendNotify (HWND hwndTo, HWND hwndFrom,
-                    UINT uCode, LPNMHDR lpHdr)
+LRESULT WINAPI SendNotify (HWND hwndTo, HWND hwndFrom, UINT uCode, LPNMHDR lpHdr)
 {
     NOTIFYDATA notify;
 
@@ -2341,26 +1146,31 @@ COMCTL32_SendNotify (HWND hwndTo, HWND hwndFrom,
 /**************************************************************************
  * SendNotifyEx [COMCTL32.342]
  *
+ * Sends a WM_NOTIFY message to the specified window.
+ *
  * PARAMS
- *     hwndFrom [I]
- *     hwndTo   [I]
- *     uCode    [I]
- *     lpHdr    [I]
- *     dwParam5 [I]
+ *     hwndFrom [I] Window to receive the message
+ *     hwndTo   [I] Window that the message is from
+ *     uCode    [I] Notification code
+ *     lpHdr    [I] The NMHDR and any additional information to send or NULL
+ *     dwParam5 [I] Unknown
  *
  * RETURNS
  *     Success: return value from notification
  *     Failure: 0
+ *
+ * NOTES
+ *     If hwndFrom is -1 then the identifier of the control sending the
+ *     message is taken from the NMHDR structure.
+ *     If hwndFrom is not -1 then lpHdr can be NULL.
  */
-
-LRESULT WINAPI
-COMCTL32_SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode,
-                      LPNMHDR lpHdr, DWORD dwParam5)
+LRESULT WINAPI SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode,
+                             LPNMHDR lpHdr, DWORD dwParam5)
 {
     NOTIFYDATA notify;
     HWND hwndNotify;
 
-    TRACE("(%p %p %d %p 0x%08lx)\n",
+    TRACE("(%p %p %d %p 0x%08x)\n",
           hwndFrom, hwndTo, uCode, lpHdr, dwParam5);
 
     hwndNotify = hwndTo;
@@ -2379,420 +1189,3 @@ COMCTL32_SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode,
 
     return DoNotify (&notify, uCode, lpHdr);
 }
-
-
-/**************************************************************************
- * StrChrA [COMCTL32.350]
- *
- */
-
-LPSTR WINAPI
-COMCTL32_StrChrA (LPCSTR lpString, CHAR cChar)
-{
-    return strchr (lpString, cChar);
-}
-
-
-/**************************************************************************
- * StrStrIA [COMCTL32.355]
- */
-
-LPSTR WINAPI
-COMCTL32_StrStrIA (LPCSTR lpStr1, LPCSTR lpStr2)
-{
-    INT len1, len2, i;
-    CHAR  first;
-
-    if (*lpStr2 == 0)
-       return ((LPSTR)lpStr1);
-    len1 = 0;
-    while (lpStr1[len1] != 0) ++len1;
-    len2 = 0;
-    while (lpStr2[len2] != 0) ++len2;
-    if (len2 == 0)
-       return ((LPSTR)(lpStr1 + len1));
-    first = tolower (*lpStr2);
-    while (len1 >= len2) {
-       if (tolower(*lpStr1) == first) {
-           for (i = 1; i < len2; ++i)
-               if (tolower (lpStr1[i]) != tolower(lpStr2[i]))
-                   break;
-           if (i >= len2)
-               return ((LPSTR)lpStr1);
-        }
-       ++lpStr1; --len1;
-    }
-    return (NULL);
-}
-
-
-/**************************************************************************
- * StrToIntA [COMCTL32.357] Converts a string to a signed integer.
- */
-
-INT WINAPI
-COMCTL32_StrToIntA (LPSTR lpString)
-{
-    return atoi(lpString);
-}
-
-/**************************************************************************
- * StrToIntW [COMCTL32.365] Converts a wide char string to a signed integer.
- */
-
-INT WINAPI
-COMCTL32_StrToIntW (LPWSTR lpString)
-{
-    return atoiW(lpString);
-}
-
-
-/**************************************************************************
- * DPA_EnumCallback [COMCTL32.385]
- *
- * Enumerates all items in a dynamic pointer array.
- *
- * PARAMS
- *     hdpa     [I] handle to the dynamic pointer array
- *     enumProc [I]
- *     lParam   [I]
- *
- * RETURNS
- *     none
- */
-
-VOID WINAPI
-DPA_EnumCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
-{
-    INT i;
-
-    TRACE("(%p %p %08lx)\n", hdpa, enumProc, lParam);
-
-    if (!hdpa)
-       return;
-    if (hdpa->nItemCount <= 0)
-       return;
-
-    for (i = 0; i < hdpa->nItemCount; i++) {
-       if ((enumProc)(hdpa->ptrs[i], lParam) == 0)
-           return;
-    }
-
-    return;
-}
-
-
-/**************************************************************************
- * DPA_DestroyCallback [COMCTL32.386]
- *
- * Enumerates all items in a dynamic pointer array and destroys it.
- *
- * PARAMS
- *     hdpa     [I] handle to the dynamic pointer array
- *     enumProc [I]
- *     lParam   [I]
- *
- * RETURNS
- *     Success: TRUE
- *     Failure: FALSE
- */
-
-BOOL WINAPI
-DPA_DestroyCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
-{
-    TRACE("(%p %p %08lx)\n", hdpa, enumProc, lParam);
-
-    DPA_EnumCallback (hdpa, enumProc, lParam);
-
-    return DPA_Destroy (hdpa);
-}
-
-
-/**************************************************************************
- * DSA_EnumCallback [COMCTL32.387]
- *
- * Enumerates all items in a dynamic storage array.
- *
- * PARAMS
- *     hdsa     [I] handle to the dynamic storage array
- *     enumProc [I]
- *     lParam   [I]
- *
- * RETURNS
- *     none
- */
-
-VOID WINAPI
-DSA_EnumCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
-{
-    INT i;
-
-    TRACE("(%p %p %08lx)\n", hdsa, enumProc, lParam);
-
-    if (!hdsa)
-       return;
-    if (hdsa->nItemCount <= 0)
-       return;
-
-    for (i = 0; i < hdsa->nItemCount; i++) {
-       LPVOID lpItem = DSA_GetItemPtr (hdsa, i);
-       if ((enumProc)(lpItem, lParam) == 0)
-           return;
-    }
-
-    return;
-}
-
-
-/**************************************************************************
- * DSA_DestroyCallback [COMCTL32.388]
- *
- * Enumerates all items in a dynamic storage array and destroys it.
- *
- * PARAMS
- *     hdsa     [I] handle to the dynamic storage array
- *     enumProc [I]
- *     lParam   [I]
- *
- * RETURNS
- *     Success: TRUE
- *     Failure: FALSE
- */
-
-BOOL WINAPI
-DSA_DestroyCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
-{
-    TRACE("(%p %p %08lx)\n", hdsa, enumProc, lParam);
-
-    DSA_EnumCallback (hdsa, enumProc, lParam);
-
-    return DSA_Destroy (hdsa);
-}
-
-/**************************************************************************
- * StrCSpnA [COMCTL32.356]
- *
- */
-INT WINAPI COMCTL32_StrCSpnA( LPCSTR lpStr, LPCSTR lpSet) {
-  return strcspn(lpStr, lpSet);
-}
-
-/**************************************************************************
- * StrChrW [COMCTL32.358]
- *
- */
-LPWSTR WINAPI COMCTL32_StrChrW( LPCWSTR lpStart, WORD wMatch) {
-  return strchrW(lpStart, wMatch);
-}
-
-/**************************************************************************
- * StrCmpNA [COMCTL32.352]
- *
- */
-INT WINAPI COMCTL32_StrCmpNA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
-  return strncmp(lpStr1, lpStr2, nChar);
-}
-
-/**************************************************************************
- * StrCmpNIA [COMCTL32.353]
- *
- */
-INT WINAPI COMCTL32_StrCmpNIA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
-  return strncasecmp(lpStr1, lpStr2, nChar);
-}
-
-/**************************************************************************
- * StrCmpNW [COMCTL32.360]
- *
- */
-INT WINAPI COMCTL32_StrCmpNW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
-  return strncmpW(lpStr1, lpStr2, nChar);
-}
-
-/**************************************************************************
- * StrCmpNIW [COMCTL32.361]
- *
- */
-INT WINAPI COMCTL32_StrCmpNIW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
-  FIXME("(%s, %s, %i): stub\n", debugstr_w(lpStr1), debugstr_w(lpStr2), nChar);
-  return 0;
-}
-
-/**************************************************************************
- * StrRChrA [COMCTL32.351]
- *
- */
-LPSTR WINAPI COMCTL32_StrRChrA( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch )
-{
-    LPCSTR lpGotIt = NULL;
-    BOOL dbcs = IsDBCSLeadByte( LOBYTE(wMatch) );
-
-    TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
-
-    if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
-
-    for(; lpStart < lpEnd; lpStart = CharNextA(lpStart))
-    {
-        if (*lpStart != LOBYTE(wMatch)) continue;
-        if (dbcs && lpStart[1] != HIBYTE(wMatch)) continue;
-        lpGotIt = lpStart;
-    }
-    return (LPSTR)lpGotIt;
-}
-
-
-/**************************************************************************
- * StrRChrW [COMCTL32.359]
- *
- */
-LPWSTR WINAPI COMCTL32_StrRChrW( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch)
-{
-    LPCWSTR lpGotIt = NULL;
-
-    TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
-    if (!lpEnd) lpEnd = lpStart + strlenW(lpStart);
-
-    for(; lpStart < lpEnd; lpStart = CharNextW(lpStart))
-        if (*lpStart == wMatch) lpGotIt = lpStart;
-
-    return (LPWSTR)lpGotIt;
-}
-
-
-/**************************************************************************
- * StrStrA [COMCTL32.354]
- *
- */
-LPSTR WINAPI COMCTL32_StrStrA( LPCSTR lpFirst, LPCSTR lpSrch) {
-  return strstr(lpFirst, lpSrch);
-}
-
-/**************************************************************************
- * StrStrW [COMCTL32.362]
- *
- */
-LPWSTR WINAPI COMCTL32_StrStrW( LPCWSTR lpFirst, LPCWSTR lpSrch) {
-  return strstrW(lpFirst, lpSrch);
-}
-
-/**************************************************************************
- * StrSpnW [COMCTL32.364]
- *
- */
-INT WINAPI COMCTL32_StrSpnW( LPWSTR lpStr, LPWSTR lpSet) {
-  LPWSTR lpLoop = lpStr;
-
-  /* validate ptr */
-  if ((lpStr == 0) || (lpSet == 0)) return 0;
-
-/* while(*lpLoop) { if lpLoop++; } */
-
-  for(; (*lpLoop != 0); lpLoop++)
-    if( strchrW(lpSet, *(WORD*)lpLoop))
-      return (INT)(lpLoop-lpStr);
-
-  return (INT)(lpLoop-lpStr);
-}
-
-/**************************************************************************
- * @ [COMCTL32.410]
- *
- * FIXME: What's this supposed to do?
- *        Parameter 1 is an HWND, you're on your own for the rest.
- */
-
-BOOL WINAPI COMCTL32_410( HWND hw, DWORD b, DWORD c, DWORD d) {
-
-   FIXME("(%p, %lx, %lx, %lx): stub!\n", hw, b, c, d);
-
-   return TRUE;
-}
-
-/**************************************************************************
- * @ [COMCTL32.411]
- *
- * FIXME: What's this supposed to do?
- *        Parameter 1 is an HWND, you're on your own for the rest.
- */
-
-BOOL WINAPI COMCTL32_411( HWND hw, DWORD b, DWORD c) {
-
-   FIXME("(%p, %lx, %lx): stub!\n", hw, b, c);
-
-   return TRUE;
-}
-
-/**************************************************************************
- * @ [COMCTL32.412]
- *
- * FIXME: What's this supposed to do?
- *        Parameter 1 is an HWND, you're on your own for the rest.
- */
-
-BOOL WINAPI COMCTL32_412( HWND hwnd, DWORD b, DWORD c)
-{
-    FIXME("(%p, %lx, %lx): stub!\n", hwnd, b, c);
-
-    if (IsWindow (hwnd) == FALSE)
-       return FALSE;
-
-    if (b == 0)
-       return FALSE;
-
-
-    return TRUE;
-}
-
-/**************************************************************************
- * @ [COMCTL32.413]
- *
- * FIXME: What's this supposed to do?
- *        Parameter 1 is an HWND, you're on your own for the rest.
- */
-
-BOOL WINAPI COMCTL32_413( HWND hw, DWORD b, DWORD c, DWORD d) {
-
-   FIXME("(%p, %lx, %lx, %lx): stub!\n", hw, b, c, d);
-
-   return TRUE;
-}
-
-
-/**************************************************************************
- * @ [COMCTL32.415]
- *
- * FIXME: What's this supposed to do?
- *        Parameter 1 is an HWND, you're on your own for the rest.
- */
-
-BOOL WINAPI COMCTL32_415( HWND hwnd, DWORD b, DWORD c, DWORD d, DWORD e)
-{
-
-   FIXME("(%p, %lx, %lx, %lx, %lx): stub!\n", hwnd, b, c, d, e);
-
-   return TRUE;
-}
-
-/**************************************************************************
- * @ [COMCTL32.417]
- *
- */
-BOOL WINAPI COMCTL32_417(HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,
-                         LPCWSTR str, UINT count, const INT *lpDx)
-{
-    return ExtTextOutW(hdc, x, y, flags, lprect, str, count, lpDx);
-}
-
-/**************************************************************************
- * @ [COMCTL32.419]
- *
- * FIXME: What's this supposed to do?
- */
-
-BOOL WINAPI COMCTL32_419( DWORD a, DWORD b, DWORD c, DWORD d)
-{
-
-   FIXME("(%lx, %lx, %lx, %lx): stub!\n", a, b, c, d);
-
-   return TRUE;
-}