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