shlwapi: FDSA functions

Huw D M Davies h.davies1 at physics.ox.ac.uk
Mon Aug 8 14:10:42 CDT 2005


        Huw Davies <huw at codeweavers.com>
        Implement and add tests for the FDSA functions.

Index: dlls/shlwapi/ordinal.c
===================================================================
RCS file: /home/wine/wine/dlls/shlwapi/ordinal.c,v
retrieving revision 1.110
diff -u -p -r1.110 ordinal.c
--- dlls/shlwapi/ordinal.c	8 Aug 2005 17:58:31 -0000	1.110
+++ dlls/shlwapi/ordinal.c	8 Aug 2005 19:07:55 -0000
@@ -2217,61 +2217,127 @@ BOOL WINAPI SHIsChildOrSelf(HWND hParent
 }
 
 /*************************************************************************
+ *    FDSA functions.  Manage a dynamic array of fixed size memory blocks.
+ */
+
+typedef struct
+{
+    DWORD num_items;       /* Number of elements inserted */
+    void *mem;             /* Ptr to array */
+    DWORD blocks_alloced;  /* Number of elements allocated */
+    BYTE inc;              /* Number of elements to grow by when we need to expand */
+    BYTE block_size;       /* Size in bytes of an element */
+    BYTE flags;            /* Flags */
+} FDSA_info;
+
+#define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
+
+/*************************************************************************
  *      @	[SHLWAPI.208]
  *
- * Some sort of memory management process.
+ * Initialize an FDSA arrary. 
  */
-DWORD WINAPI FDSA_Initialize(
-	DWORD    a,
-	DWORD    b,
-	LPVOID   c,
-	LPVOID   d,
-	DWORD    e)
+BOOL WINAPI FDSA_Initialize(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
+                            DWORD init_blocks)
 {
-    FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",
-	  a, b, c, d, e);
-    return 1;
+    TRACE("(0x%08lx 0x%08lx %p %p 0x%08lx)\n", block_size, inc, info, mem, init_blocks);
+
+    if(inc == 0)
+        inc = 1;
+
+    if(mem)
+        memset(mem, 0, block_size * init_blocks);
+    
+    info->num_items = 0;
+    info->inc = inc;
+    info->mem = mem;
+    info->blocks_alloced = init_blocks;
+    info->block_size = block_size;
+    info->flags = 0;
+
+    return TRUE;
 }
 
 /*************************************************************************
  *      @	[SHLWAPI.209]
  *
- * Some sort of memory management process.
+ * Destroy an FDSA array
  */
-DWORD WINAPI FDSA_Destroy(
-	LPVOID   a)
+BOOL WINAPI FDSA_Destroy(FDSA_info *info)
 {
-    FIXME("(%p) stub\n",
-	  a);
-    return 1;
+    TRACE("(%p)\n", info);
+
+    if(info->flags & FDSA_FLAG_INTERNAL_ALLOC)
+    {
+        HeapFree(GetProcessHeap(), 0, info->mem);
+        return FALSE;
+    }
+
+    return TRUE;
 }
 
 /*************************************************************************
  *      @	[SHLWAPI.210]
  *
- * Some sort of memory management process.
+ * Insert element into an FDSA array
  */
-DWORD WINAPI FDSA_InsertItem(
-	LPVOID   a,
-	DWORD    b,
-	LPVOID   c)
+DWORD WINAPI FDSA_InsertItem(FDSA_info *info, DWORD where, void *block)
 {
-    FIXME("(%p 0x%08lx %p) stub\n",
-	  a, b, c);
-    return 0;
+    TRACE("(%p 0x%08lx %p)\n", info, where, block);
+    if(where > info->num_items)
+        where = info->num_items;
+
+    if(info->num_items >= info->blocks_alloced)
+    {
+        DWORD size = (info->blocks_alloced + info->inc) * info->block_size;
+        if(info->flags & 0x1)
+            info->mem = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->mem, size);
+        else
+        {
+            void *old_mem = info->mem;
+            info->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
+            memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size);
+        }
+        info->blocks_alloced += info->inc;
+        info->flags |= 0x1;
+    }
+
+    if(where < info->num_items)
+    {
+        memmove((char*)info->mem + (where + 1) * info->block_size,
+                (char*)info->mem + where * info->block_size,
+                (info->num_items - where) * info->block_size);
+    }
+    memcpy((char*)info->mem + where * info->block_size, block, info->block_size);
+
+    info->num_items++;
+    return where;
 }
 
 /*************************************************************************
  *      @	[SHLWAPI.211]
+ *
+ * Delete an element from an FDSA array.
  */
-DWORD WINAPI FDSA_DeleteItem(
-	LPVOID   a,
-	DWORD    b)
+BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where)
 {
-    FIXME("(%p 0x%08lx) stub\n",
-	  a, b);
-    return 1;
+    TRACE("(%p 0x%08lx)\n", info, where);
+
+    if(where >= info->num_items)
+        return FALSE;
+
+    if(where < info->num_items - 1)
+    {
+        memmove((char*)info->mem + where * info->block_size,
+                (char*)info->mem + (where + 1) * info->block_size,
+                (info->num_items - where - 1) * info->block_size);
+    }
+    memset((char*)info->mem + (info->num_items - 1) * info->block_size,
+           0, info->block_size);
+    info->num_items--;
+    return TRUE;
 }
+
 
 typedef struct {
     REFIID   refid;
Index: dlls/shlwapi/tests/ordinal.c
===================================================================
RCS file: /home/wine/wine/dlls/shlwapi/tests/ordinal.c,v
retrieving revision 1.17
diff -u -p -r1.17 ordinal.c
--- dlls/shlwapi/tests/ordinal.c	21 Jun 2005 20:53:14 -0000	1.17
+++ dlls/shlwapi/tests/ordinal.c	8 Aug 2005 19:07:55 -0000
@@ -227,6 +227,106 @@ static void test_alloc_shared(void)
     ok( ret, "SHFreeShared failed: %ld\n", GetLastError());
 }
 
+static void test_fdsa(void)
+{
+    typedef struct
+    {
+        DWORD num_items;       /* Number of elements inserted */
+        void *mem;             /* Ptr to array */
+        DWORD blocks_alloced;  /* Number of elements allocated */
+        BYTE inc;              /* Number of elements to grow by when we need to expand */
+        BYTE block_size;       /* Size in bytes of an element */
+        BYTE flags;            /* Flags */
+    } FDSA_info;
+
+    BOOL (WINAPI *pFDSA_Initialize)(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
+                                    DWORD init_blocks);
+    BOOL (WINAPI *pFDSA_Destroy)(FDSA_info *info);
+    DWORD (WINAPI *pFDSA_InsertItem)(FDSA_info *info, DWORD where, void *block);
+    BOOL (WINAPI *pFDSA_DeleteItem)(FDSA_info *info, DWORD where);
+
+    pFDSA_Initialize = (void *)GetProcAddress(hShlwapi, (LPSTR)208);
+    pFDSA_Destroy    = (void *)GetProcAddress(hShlwapi, (LPSTR)209);
+    pFDSA_InsertItem = (void *)GetProcAddress(hShlwapi, (LPSTR)210);
+    pFDSA_DeleteItem = (void *)GetProcAddress(hShlwapi, (LPSTR)211);
+
+    FDSA_info info;
+    int block_size = 10, init_blocks = 4, inc = 2;
+    DWORD ret;
+    char *mem;
+
+    mem = HeapAlloc(GetProcessHeap(), 0, block_size * init_blocks);
+    memset(&info, 0, sizeof(info));
+
+    ok(pFDSA_Initialize(block_size, inc, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
+    ok(info.num_items == 0, "num_items = %ld\n", info.num_items);
+    ok(info.mem == mem, "mem = %p\n", info.mem);
+    ok(info.blocks_alloced == init_blocks, "blocks_alloced = %ld\n", info.blocks_alloced);
+    ok(info.inc == inc, "inc = %d\n", info.inc);
+    ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
+    ok(info.flags == 0, "flags = %d\n", info.flags);
+
+    ret = pFDSA_InsertItem(&info, 1234, "1234567890");
+    ok(ret == 0, "ret = %ld\n", ret);
+    ok(info.num_items == 1, "num_items = %ld\n", info.num_items);
+    ok(info.mem == mem, "mem = %p\n", info.mem);
+    ok(info.blocks_alloced == init_blocks, "blocks_alloced = %ld\n", info.blocks_alloced);
+    ok(info.inc == inc, "inc = %d\n", info.inc);
+    ok(info.block_size == block_size, "block_size = %d\n", info.block_size);
+    ok(info.flags == 0, "flags = %d\n", info.flags);
+
+    ret = pFDSA_InsertItem(&info, 1234, "abcdefghij");
+    ok(ret == 1, "ret = %ld\n", ret);
+
+    ret = pFDSA_InsertItem(&info, 1, "klmnopqrst");
+    ok(ret == 1, "ret = %ld\n", ret);
+
+    ret = pFDSA_InsertItem(&info, 0, "uvwxyzABCD");
+    ok(ret == 0, "ret = %ld\n", ret);
+    ok(info.mem == mem, "mem = %p\n", info.mem);
+    ok(info.flags == 0, "flags = %d\n", info.flags);
+
+    /* This next InsertItem will cause shlwapi to allocate its own mem buffer */
+    ret = pFDSA_InsertItem(&info, 0, "EFGHIJKLMN");
+    ok(ret == 0, "ret = %ld\n", ret);
+    ok(info.mem != mem, "mem = %p\n", info.mem);
+    ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %ld\n", info.blocks_alloced);
+    ok(info.flags == 0x1, "flags = %d\n", info.flags);
+
+    ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCD1234567890klmnopqrstabcdefghij", 50), "mem %s\n", (char*)info.mem);
+
+    ok(pFDSA_DeleteItem(&info, 2), "rets FALSE\n");
+    ok(info.mem != mem, "mem = %p\n", info.mem);
+    ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %ld\n", info.blocks_alloced);
+    ok(info.flags == 0x1, "flags = %d\n", info.flags);
+
+    ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrstabcdefghij", 40), "mem %s\n", (char*)info.mem);
+
+    ok(pFDSA_DeleteItem(&info, 3), "rets FALSE\n");
+    ok(info.mem != mem, "mem = %p\n", info.mem);
+    ok(info.blocks_alloced == init_blocks + inc, "blocks_alloced = %ld\n", info.blocks_alloced);
+    ok(info.flags == 0x1, "flags = %d\n", info.flags);
+
+    ok(!memcmp(info.mem, "EFGHIJKLMNuvwxyzABCDklmnopqrst", 30), "mem %s\n", (char*)info.mem);
+
+    ok(!pFDSA_DeleteItem(&info, 4), "does not ret FALSE\n");
+
+    /* As shlwapi has allocated memory internally, Destroy will ret FALSE */
+    ok(!pFDSA_Destroy(&info), "FDSA_Destroy does not ret FALSE\n");
+
+
+    /* When Initialize is called with inc = 0, set it to 1 */
+    ok(pFDSA_Initialize(block_size, 0, &info, mem, init_blocks), "FDSA_Initialize rets FALSE\n");
+    ok(info.inc == 1, "inc = %d\n", info.inc);
+
+    /* This time, because shlwapi hasn't had to allocate memory
+       internally, Destroy rets non-zero */
+    ok(pFDSA_Destroy(&info), "FDSA_Destroy rets FALSE\n");
+
+
+    HeapFree(GetProcessHeap(), 0, mem);
+}
+
 START_TEST(ordinal)
 {
   hShlwapi = LoadLibraryA("shlwapi.dll");
@@ -244,5 +344,7 @@ START_TEST(ordinal)
   test_GetAcceptLanguagesA();
   test_SHSearchMapInt();
   test_alloc_shared();
+  test_fdsa();
+
   FreeLibrary(hShlwapi);
 }



More information about the wine-patches mailing list