1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00

dbghelp/tests: Add tests for image files lookup.

Signed-off-by: Eric Pouech <epouech@codeweavers.com>
This commit is contained in:
Eric Pouech 2023-06-19 16:42:55 +02:00 committed by Alexandre Julliard
parent 058bfeed1d
commit 2abbee9540

View file

@ -926,6 +926,292 @@ static void test_srvgetindexes_dbg(void)
}
}
static void make_path(WCHAR file[MAX_PATH], const WCHAR* topdir, const WCHAR* subdir, const WCHAR* base)
{
wcscpy(file, topdir);
if (subdir)
{
if (file[wcslen(file) - 1] != '\\') wcscat(file, L"\\");
wcscat(file, subdir);
}
if (base)
{
if (file[wcslen(file) - 1] != '\\') wcscat(file, L"\\");
wcscat(file, base);
}
}
struct path_validate
{
DWORD timestamp;
DWORD size_of_image;
unsigned cb_count;
};
static BOOL CALLBACK path_cb(PCWSTR filename, void* _usr)
{
struct path_validate* pv = _usr;
SYMSRV_INDEX_INFOW ssii;
BOOL ret;
pv->cb_count++;
/* wine returns paths in relative form, but relative to search path...
* fail (== continue search) until it's fixed
*/
todo_wine_if(!filename[0] || filename[1] != ':')
ok(filename[0] && filename[1] == ':', "Expecting full path, but got %ls\n", filename);
if (!filename[0] || filename[1] != ':') return TRUE;
memset(&ssii, 0, sizeof(ssii));
ssii.sizeofstruct = sizeof(ssii);
ret = SymSrvGetFileIndexInfoW(filename, &ssii, 0);
ok(ret, "SymSrvGetFileIndexInfo failed: %lu %ls\n", GetLastError(), filename);
return !(ret && ssii.timestamp == pv->timestamp && ssii.size == pv->size_of_image);
}
static unsigned char2index(char ch)
{
unsigned val;
if (ch >= '0' && ch <= '9')
val = ch - '0';
else if (ch >= 'a' && ch <= 'z')
val = 10 + ch - 'a';
else val = ~0u;
return val;
}
/* Despite what MS documentation states, option EXACT_SYMBOLS doesn't always work
* (it looks like it's only enabled when symsrv.dll is loaded).
* So, we don't test with EXACT_SYMBOLS set, nor with a NULL callback, and defer
* to our own custom callback the testing.
* (We always end when a full matched is found).
*/
static void test_find_in_path_pe(void)
{
HANDLE proc = (HANDLE)(DWORD_PTR)0x666002;
WCHAR topdir[MAX_PATH];
WCHAR search[MAX_PATH];
WCHAR file[MAX_PATH];
WCHAR found[MAX_PATH];
struct path_validate pv;
DWORD len;
BOOL ret;
int i;
union nt_header hdr;
static const struct file_tests
{
unsigned bitness; /* 32 or 64 */
DWORD timestamp;
DWORD size_of_image;
const WCHAR* module_path;
}
file_tests[] =
{
/* 0 */ { 64, 0x12345678, 0x0030cafe, L"foobar.dll" },
/* 1 */ { 64, 0x12345678, 0x0030cafe, L"A\\foobar.dll" },
/* 2 */ { 64, 0x12345678, 0x0030cafe, L"B\\foobar.dll" },
/* 3 */ { 64, 0x56781234, 0x0010f00d, L"foobar.dll" },
/* 4 */ { 64, 0x56781234, 0x0010f00d, L"A\\foobar.dll" },
/* 5 */ { 64, 0x56781234, 0x0010f00d, L"B\\foobar.dll" },
/* 6 */ { 32, 0x12345678, 0x0030cafe, L"foobar.dll" },
/* 7 */ { 32, 0x12345678, 0x0030cafe, L"A\\foobar.dll" },
/* 8 */ { 32, 0x12345678, 0x0030cafe, L"B\\foobar.dll" },
/* 9 */ { 32, 0x56781234, 0x0010f00d, L"foobar.dll" },
/* a */ { 32, 0x56781234, 0x0010f00d, L"A\\foobar.dll" },
/* b */ { 32, 0x56781234, 0x0010f00d, L"B\\foobar.dll" },
};
static const struct image_tests
{
/* files to generate */
const char* files;
/* parameters for lookup */
DWORD lookup_timestamp;
DWORD lookup_size_of_image;
const char* search; /* several of ., A, B to link to directories */
const WCHAR* module;
/* expected results */
const WCHAR* found_subdir;
DWORD expected_cb_count;
}
image_tests[] =
{
/* all files 64 bit */
/* the passed timestamp & size are not checked before calling the callback! */
/* 0 */ { "0", 0x00000000, 0x00000000, ".", L"foobar.dll", NULL, 1},
/* 1 */ { "0", 0x12345678, 0x00000000, ".", L"foobar.dll", NULL, 1},
/* 2 */ { "0", 0x00000000, 0x0030cafe, ".", L"foobar.dll", NULL, 1},
/* 3 */ { "0", 0x12345678, 0x0030cafe, ".", L"foobar.dll", L"", 1},
/* no recursion into subdirectories */
/* 4 */ { "1", 0x12345678, 0x0030cafe, ".", L"foobar.dll", NULL, 0},
/* directories are searched in order */
/* 5 */ { "15", 0x12345678, 0x0030cafe, "AB", L"foobar.dll", L"A\\", 1},
/* 6 */ { "15", 0x12345678, 0x0030cafe, "BA", L"foobar.dll", L"A\\", 2},
/* 7 */ { "12", 0x12345678, 0x0030cafe, "AB", L"foobar.dll", L"A\\", 1},
/* 8 */ { "12", 0x12345678, 0x0030cafe, "BA", L"foobar.dll", L"B\\", 1},
/* all files 32 bit */
/* the passed timestamp & size is not checked ! */
/* 9 */ { "6", 0x00000000, 0x00000000, ".", L"foobar.dll", NULL, 1},
/* 10 */ { "6", 0x12345678, 0x00000000, ".", L"foobar.dll", NULL, 1},
/* 11 */ { "6", 0x00000000, 0x0030cafe, ".", L"foobar.dll", NULL, 1},
/* 12 */ { "6", 0x12345678, 0x0030cafe, ".", L"foobar.dll", L"", 1},
/* no recursion into subdirectories */
/* 13 */ { "7", 0x12345678, 0x0030cafe, ".", L"foobar.dll", NULL, 0},
/* directories are searched in order */
/* 14 */ { "7b", 0x12345678, 0x0030cafe, "AB", L"foobar.dll", L"A\\", 1},
/* 15 */ { "7b", 0x12345678, 0x0030cafe, "BA", L"foobar.dll", L"A\\", 2},
/* 16 */ { "78", 0x12345678, 0x0030cafe, "AB", L"foobar.dll", L"A\\", 1},
/* 17 */ { "78", 0x12345678, 0x0030cafe, "BA", L"foobar.dll", L"B\\", 1},
/* machine and bitness is not used */
/* 18 */ { "1b", 0x12345678, 0x0030cafe, "AB", L"foobar.dll", L"A\\", 1},
/* 19 */ { "1b", 0x12345678, 0x0030cafe, "BA", L"foobar.dll", L"A\\", 2},
/* 20 */ { "18", 0x12345678, 0x0030cafe, "AB", L"foobar.dll", L"A\\", 1},
/* 21 */ { "18", 0x12345678, 0x0030cafe, "BA", L"foobar.dll", L"B\\", 1},
/* 22 */ { "75", 0x12345678, 0x0030cafe, "AB", L"foobar.dll", L"A\\", 1},
/* 23 */ { "75", 0x12345678, 0x0030cafe, "BA", L"foobar.dll", L"A\\", 2},
/* 24 */ { "72", 0x12345678, 0x0030cafe, "AB", L"foobar.dll", L"A\\", 1},
/* 25 */ { "72", 0x12345678, 0x0030cafe, "BA", L"foobar.dll", L"B\\", 1},
/* specifying a full path to module isn't taken into account */
/* 26 */ { "0", 0x12345678, 0x0030cafe, "AB", L"@foobar.dll", NULL, 0},
/* 27 */ { "6", 0x12345678, 0x0030cafe, "AB", L"@foobar.dll", NULL, 0},
};
static const WCHAR* list_directories[] = {L"A", L"B", L"dll", L"symbols", L"symbols\\dll", L"acm", L"symbols\\acm"};
ret = SymInitializeW(proc, NULL, FALSE);
ok(ret, "Couldn't init dbghelp\n");
len = GetTempPathW(ARRAY_SIZE(topdir), topdir);
ok(len && len < ARRAY_SIZE(topdir), "Unexpected length\n");
wcscat(topdir, L"dh.tmp\\");
ret = CreateDirectoryW(topdir, NULL);
ok(ret, "Couldn't create directory\n");
for (i = 0; i < ARRAY_SIZE(list_directories); i++)
{
make_path(file, topdir, list_directories[i], NULL);
ret = CreateDirectoryW(file, NULL);
ok(ret, "Couldn't create directory %u %ls\n", i, list_directories[i]);
}
for (i = 0; i < ARRAY_SIZE(image_tests); ++i)
{
const char* ptr;
winetest_push_context("%u", i);
for (ptr = image_tests[i].files; *ptr; ptr++)
{
unsigned val = char2index(*ptr);
if (val < ARRAY_SIZE(file_tests))
{
const struct file_tests* ft = &file_tests[val];
struct debug_directory_blob* ds_blob;
make_path(file, topdir, NULL, ft->module_path);
/* all modules created with ds pdb reference so that SymSrvGetFileInfoInfo() succeeds */
ds_blob = make_pdb_ds_blob(ft->timestamp, &guid1, 124, "pdbds.pdb");
if (ft->bitness == 64)
{
init_headers64(&hdr.nt_header64, ft->timestamp, ft->size_of_image, 0);
create_test_dll(&hdr, sizeof(hdr.nt_header64), &ds_blob, 1, file);
}
else
{
init_headers32(&hdr.nt_header32, ft->timestamp, ft->size_of_image, 0);
create_test_dll(&hdr, sizeof(hdr.nt_header32), &ds_blob, 1, file);
}
free(ds_blob);
}
else ok(0, "Unrecognized file reference %c\n", *ptr);
}
search[0] = L'\0';
for (ptr = image_tests[i].search; *ptr; ptr++)
{
if (*search) wcscat(search, L";");
wcscat(search, topdir);
if (*ptr == '.')
;
else if (*ptr == 'A')
wcscat(search, L"A");
else if (*ptr == 'B')
wcscat(search, L"B");
else ok(0, "Unrecognized file reference %c\n", *ptr);
}
if (image_tests[i].module[0] == L'@')
make_path(file, topdir, NULL, &image_tests[i].module[1]);
else
wcscpy(file, image_tests[i].module);
pv.timestamp = image_tests[i].lookup_timestamp;
pv.size_of_image = image_tests[i].lookup_size_of_image;
pv.cb_count = 0;
memset(found, 0, sizeof(found));
ret = SymFindFileInPathW(proc, search, file,
(void*)&image_tests[i].lookup_timestamp,
image_tests[i].lookup_size_of_image, 0,
SSRVOPT_DWORDPTR, found, path_cb, &pv);
todo_wine
ok(pv.cb_count == image_tests[i].expected_cb_count,
"Mismatch in cb count, got %u (expected %lu)\n",
pv.cb_count, image_tests[i].expected_cb_count);
if (image_tests[i].found_subdir)
{
size_t l1, l2, l3;
ok(ret, "Couldn't find file: %ls %lu\n", search, GetLastError());
l1 = wcslen(topdir);
l2 = wcslen(image_tests[i].found_subdir);
l3 = wcslen(image_tests[i].module);
ok(l1 + l2 + l3 == wcslen(found) &&
!memcmp(found, topdir, l1 * sizeof(WCHAR)) &&
!memcmp(&found[l1], image_tests[i].found_subdir, l2 * sizeof(WCHAR)) &&
!memcmp(&found[l1 + l2], image_tests[i].module, l3 * sizeof(WCHAR)),
"Mismatch in found file %ls (expecting %ls)\n",
found, image_tests[i].found_subdir);
}
else
{
todo_wine_if(i == 26 || i == 27)
ok(!ret, "File reported found, while failure is expected\n");
todo_wine_if(i == 26 || i == 27 || (GetLastError() != ERROR_FILE_NOT_FOUND))
ok(GetLastError() == ERROR_FILE_NOT_FOUND, "Unexpected error %lu\n", GetLastError());
}
for (ptr = image_tests[i].files; *ptr; ptr++)
{
unsigned val = char2index(*ptr);
if (val < ARRAY_SIZE(file_tests))
{
const struct file_tests* ft = &file_tests[val];
make_path(file, topdir, NULL, ft->module_path);
ret = DeleteFileW(file);
ok(ret, "Couldn't delete file %c %ls\n", *ptr, file);
}
else ok(0, "Unrecognized file reference %c\n", *ptr);
}
winetest_pop_context();
}
SymCleanup(proc);
for (i = ARRAY_SIZE(list_directories) - 1; i >= 0; i--)
{
make_path(file, topdir, list_directories[i], NULL);
ret = RemoveDirectoryW(file);
ok(ret, "Couldn't remove directory %u %ls\n", i, list_directories[i]);
}
ret = RemoveDirectoryW(topdir);
ok(ret, "Couldn't remove directory\n");
}
START_TEST(path)
{
/* cleanup env variables that affect dbghelp's behavior */
@ -935,4 +1221,5 @@ START_TEST(path)
test_srvgetindexes_pe();
test_srvgetindexes_pdb();
test_srvgetindexes_dbg();
test_find_in_path_pe();
}