Implement and add tests for the FDSA functions.
This commit is contained in:
parent
0f2c2b8426
commit
34f36f662b
|
@ -2216,62 +2216,128 @@ BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
|
|||
return !IsChild(hParent, 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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue