Commit 34f36f66 authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

Implement and add tests for the FDSA functions.

parent 0f2c2b84
......@@ -2217,62 +2217,128 @@ BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
}
/*************************************************************************
* 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;
DWORD indx;
......
......@@ -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);
FDSA_info info;
int block_size = 10, init_blocks = 4, inc = 2;
DWORD ret;
char *mem;
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);
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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment