Index: rostests/apitests/CMakeLists.txt =================================================================== --- rostests/apitests/CMakeLists.txt (revision 73802) +++ rostests/apitests/CMakeLists.txt (working copy) @@ -7,6 +7,7 @@ add_subdirectory(browseui) add_subdirectory(com) add_subdirectory(crt) +add_subdirectory(dbghelp) add_subdirectory(dciman32) add_subdirectory(dnsapi) add_subdirectory(gdi32) Index: rostests/apitests/dbghelp/CMakeLists.txt =================================================================== --- rostests/apitests/dbghelp/CMakeLists.txt (nonexistent) +++ rostests/apitests/dbghelp/CMakeLists.txt (working copy) @@ -0,0 +1,20 @@ + +add_definitions(-D__ROS_LONG64__ -DWINETEST_USE_DBGSTR_LONGLONG) + +include_directories( + ${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/zlib + ${REACTOS_SOURCE_DIR}/sdk/tools/rsym +) + +list(APPEND SOURCE + pdb.c + rsym.c + data.c + testlist.c) + +add_executable(dbghelp_apitest ${SOURCE} resource.rc) +set_module_type(dbghelp_apitest win32cui) +target_link_libraries(dbghelp_apitest zlib) +add_delay_importlibs(dbghelp_apitest dbghelp) +add_importlibs(dbghelp_apitest msvcrt kernel32 ntdll) +add_rostests_file(TARGET dbghelp_apitest) Index: rostests/apitests/dbghelp/data.c =================================================================== --- rostests/apitests/dbghelp/data.c (nonexistent) +++ rostests/apitests/dbghelp/data.c (working copy) @@ -0,0 +1,273 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Support functions for dbghelp api test + * PROGRAMMER: Mark Jansen + */ + +#include +#include +#include + +#include "wine/test.h" + +extern IMAGE_DOS_HEADER __ImageBase; + +static char szTempPath[MAX_PATH]; + +static const char* tmpdir() +{ + if (szTempPath[0] == '\0') + { + GetTempPathA(MAX_PATH, szTempPath); + lstrcatA(szTempPath, "dbghelp_tst"); + } + return szTempPath; +} + +static int extract_one(const char* filename, const char* resid) +{ + HMODULE mod = (HMODULE)&__ImageBase; + HGLOBAL glob; + PVOID data, decompressed; + DWORD size, dstsize; + HANDLE file; + int ret; + HRSRC rsrc = FindResourceA(mod, resid, MAKEINTRESOURCEA(RT_RCDATA)); + ok(rsrc != 0, "Failed finding '%s' res\n", resid); + if (!rsrc) + return 0; + + size = SizeofResource(mod, rsrc); + glob = LoadResource(mod, rsrc); + ok(glob != NULL, "Failed loading '%s' res\n", resid); + if (!glob) + return 0; + + data = LockResource(glob); + + dstsize = 1024 * 256; + decompressed = malloc(dstsize); + + if (uncompress(decompressed, &dstsize, data, size) != Z_OK) + { + ok(0, "uncompress failed for %s\n", resid); + free(decompressed); + return 0; + } + + + file = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + ret = WriteFile(file, decompressed, dstsize, &size, NULL); + CloseHandle(file); + free(decompressed); + return ret && dstsize == size; +} + + +int extract_msvc_exe(char szFile[MAX_PATH]) +{ + const char* dir = tmpdir(); + BOOL ret = CreateDirectoryA(dir, NULL); + ok(ret, "CreateDirectoryA failed(%d)\n", GetLastError()); + + sprintf(szFile, "%s\\uffs.pdb", dir); + if (!extract_one(szFile, "msvc_uffs.pdb")) + return 0; + + sprintf(szFile, "%s\\uffs.dll", dir); + if (!extract_one(szFile, "msvc_uffs.dll")) + return 0; + + return 1; +} + +void cleanup_msvc_exe() +{ + char szFile[MAX_PATH]; + BOOL ret; + const char* dir = tmpdir(); + + sprintf(szFile, "%s\\uffs.pdb", dir); + ret = DeleteFileA(szFile); + ok(ret, "DeleteFileA failed(%d)\n", GetLastError()); + + sprintf(szFile, "%s\\uffs.dll", dir); + ret = DeleteFileA(szFile); + ok(ret, "DeleteFileA failed(%d)\n", GetLastError()); + ret = RemoveDirectoryA(dir); + ok(ret, "RemoveDirectoryA failed(%d)\n", GetLastError()); +} + +int extract_gcc_exe(char szFile[MAX_PATH]) +{ + const char* dir = tmpdir(); + BOOL ret = CreateDirectoryA(dir, NULL); + ok(ret, "CreateDirectoryA failed(%d)\n", GetLastError()); + + sprintf(szFile, "%s\\uffs.dll", dir); + if (!extract_one(szFile, "gcc_uffs.dll")) + return 0; + + return 1; +} + +void cleanup_gcc_exe() +{ + char szFile[MAX_PATH]; + BOOL ret; + const char* dir = tmpdir(); + + sprintf(szFile, "%s\\uffs.dll", dir); + ret = DeleteFileA(szFile); + ok(ret, "DeleteFileA failed(%d)\n", GetLastError()); + ret = RemoveDirectoryA(dir); + ok(ret, "RemoveDirectoryA failed(%d)\n", GetLastError()); +} + + +#if 0 +static int compress_one(const char* src, const char* dest) +{ + DWORD size, size2, res; + FILE* file = fopen(src, "rb"); + fseek(file, 0, SEEK_END); + size = ftell(file); + fseek(file, 0, SEEK_SET); + + Bytef* buffer, *buffer2; + DWORD dwErr = GetLastError(); + + buffer = malloc(size); + res = fread(buffer, 1, size, file); + + fclose(file); + + if (res != size) + { + printf("Could not read file: 0x%x\n", dwErr); + free(buffer); + CloseHandle(file); + return 0; + } + size2 = size *2; + buffer2 = malloc(size2); + res = compress(buffer2, &size2, buffer, size); + + free(buffer); + + if (Z_OK != res) + { + free(buffer2); + return 0; + } + + file = fopen(dest, "wb"); + res = fwrite(buffer2, 1, size2, file); + fclose(file); + + free(buffer2); + + return size2 == res; +} + +void create_compressed_files() +{ + SetCurrentDirectoryA("R:/src/trunk/reactos/modules/rostests/apitests/dbghelp"); + if (!compress_one("testdata/msvc_uffs.dll", "testdata/msvc_uffs.dll.compr")) + printf("msvc_uffs.dll failed\n"); + if (!compress_one("testdata/msvc_uffs.pdb", "testdata/msvc_uffs.pdb.compr")) + printf("msvc_uffs.pdb failed\n"); + if (!compress_one("testdata/gcc_uffs.dll", "testdata/gcc_uffs.dll.compr")) + printf("gcc_uffs.dll failed\n"); +} +#endif + +#if 0 +typedef struct _SYMBOLFILE_HEADER { + ULONG SymbolsOffset; + ULONG SymbolsLength; + ULONG StringsOffset; + ULONG StringsLength; +} SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER; + +typedef struct _ROSSYM_ENTRY { + ULONG Address; + ULONG FunctionOffset; + ULONG FileOffset; + ULONG SourceLine; +} ROSSYM_ENTRY, *PROSSYM_ENTRY; + + +static int is_metadata(const char* name) +{ + size_t len = name ? strlen(name) : 0; + return len > 3 && name[0] == '_' && name[1] != '_' && name[len-1] == '_' && name[len-2] == '_'; +}; + +static void dump_rsym_internal(void* data) +{ + PSYMBOLFILE_HEADER RosSymHeader = (PSYMBOLFILE_HEADER)data; + PROSSYM_ENTRY Entries = (PROSSYM_ENTRY)((char *)data + RosSymHeader->SymbolsOffset); + size_t symbols = RosSymHeader->SymbolsLength / sizeof(ROSSYM_ENTRY); + size_t i; + char *Strings = (char *)data + RosSymHeader->StringsOffset; + + for (i = 0; i < symbols; i++) + { + PROSSYM_ENTRY Entry = Entries + i; + if (!Entry->FileOffset) + { + if (Entry->SourceLine) + printf("ERR: SOURCELINE (%D) ", Entry->SourceLine); + if (is_metadata(Strings + Entry->FunctionOffset)) + printf("metadata: %s: 0x%x\n", Strings + Entry->FunctionOffset, Entry->Address); + else + printf("0x%x: %s\n", Entry->Address, Strings + Entry->FunctionOffset); + } + else + { + printf("0x%x: %s (%s:%u)\n", Entry->Address, + Strings + Entry->FunctionOffset, + Strings + Entry->FileOffset, + Entry->SourceLine); + } + } + +} + +void dump_rsym(const char* filename) +{ + char* data; + long size, res; + PIMAGE_FILE_HEADER PEFileHeader; + PIMAGE_OPTIONAL_HEADER PEOptHeader; + PIMAGE_SECTION_HEADER PESectionHeaders; + WORD i; + + FILE* f = fopen(filename, "rb"); + + fseek(f, 0, SEEK_END); + size = ftell(f); + fseek(f, 0, SEEK_SET); + + data = malloc(size); + res = fread(data, 1, size, f); + fclose(f); + + PEFileHeader = (PIMAGE_FILE_HEADER)((char *)data + ((PIMAGE_DOS_HEADER)data)->e_lfanew + sizeof(ULONG)); + PEOptHeader = (PIMAGE_OPTIONAL_HEADER)(PEFileHeader + 1); + PESectionHeaders = (PIMAGE_SECTION_HEADER)((char *)PEOptHeader + PEFileHeader->SizeOfOptionalHeader); + + for (i = 0; i < PEFileHeader->NumberOfSections; i++) + { + if (!strcmp((char *)PESectionHeaders[i].Name, ".rossym")) + { + dump_rsym_internal(data + PESectionHeaders[i].PointerToRawData); + break; + } + } + free(data); +} + +#endif Index: rostests/apitests/dbghelp/pdb.c =================================================================== --- rostests/apitests/dbghelp/pdb.c (nonexistent) +++ rostests/apitests/dbghelp/pdb.c (working copy) @@ -0,0 +1,377 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Test for dbghelp PDB functions + * PROGRAMMER: Mark Jansen + */ + +#include +#define WIN32_NO_STATUS +#include +#include +#include // SymTagXXX +#include + +#include "wine/test.h" + +#define ok_ulonglong(expression, result) \ + do { \ + ULONG64 _value = (expression); \ + ULONG64 _result = (result); \ + ok(_value == (result), "Wrong value for '%s', expected: " #result " (%s), got: %s\n", \ + #expression, wine_dbgstr_longlong(_result), wine_dbgstr_longlong(_value)); \ + } while (0) + + +// data.c +void create_compressed_files(); +int extract_msvc_exe(char szFile[MAX_PATH]); +void cleanup_msvc_exe(); + +static HANDLE proc() +{ + return GetCurrentProcess(); +} + +static BOOL init_sym_imp(const char* file, int line) +{ + if (!SymInitialize(proc(), NULL, FALSE)) + { + DWORD err = GetLastError(); + ok_(file, line)(0, "Failed to init: 0x%x\n", err); + return FALSE; + } + return TRUE; +} + +static void deinit_sym() +{ + SymCleanup(proc()); +} + +#define init_sym() init_sym_imp(__FILE__, __LINE__) + +#define INIT_PSYM(buff) do { \ + memset((buff), 0, sizeof((buff))); \ + ((PSYMBOL_INFO)(buff))->SizeOfStruct = sizeof(SYMBOL_INFO); \ + ((PSYMBOL_INFO)(buff))->MaxNameLen = MAX_SYM_NAME; \ +} while (0) + + +/* Maybe our dbghelp.dll is too old? */ +static BOOL can_enumerate(HANDLE hProc, DWORD64 BaseAddress) +{ + IMAGEHLP_MODULE64 ModuleInfo; + BOOL Ret; + + memset(&ModuleInfo, 0, sizeof(ModuleInfo)); + ModuleInfo.SizeOfStruct = sizeof(ModuleInfo); + Ret = SymGetModuleInfo64(hProc, BaseAddress, &ModuleInfo); + + return Ret && ModuleInfo.SymType == SymPdb; +} + + +static void test_SymFromName(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + + DWORD64 BaseAddress; + DWORD dwErr; + + if (!init_sym()) + return; + + SetLastError(ERROR_SUCCESS); + BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + if (!can_enumerate(hProc, BaseAddress)) + { + skip("dbghelp.dll too old or cannot enumerate symbols!\n"); + } + else + { + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "DllMain", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "_DllMain@12", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0x400000); // ?? + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagPublicSymbol); + ok_str(pSymbol->Name, "_DllMain@12"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "FfsChkdsk", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsChkdsk"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "_FfsChkdsk@24", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0x400000); // ?? + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); + ok_hex(pSymbol->Tag, SymTagPublicSymbol); + ok_str(pSymbol->Name, "_FfsChkdsk@24"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "FfsFormat", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1070); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsFormat"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "_FfsFormat@24", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0x400000); // ?? + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1070); + ok_hex(pSymbol->Tag, SymTagPublicSymbol); + ok_str(pSymbol->Name, "_FfsFormat@24"); + } + + deinit_sym(); +} + +static void test_SymFromAddr(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + + DWORD64 BaseAddress, Displacement; + DWORD dwErr; + + if (!init_sym()) + return; + + SetLastError(ERROR_SUCCESS); + BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + /* No address found before load address of module */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress -1, &Displacement, pSymbol); + dwErr = GetLastError(); + ok_int(Ret, FALSE); + ok_hex(dwErr, ERROR_MOD_NOT_FOUND); + + /* Right at the start of the module is recognized as the first symbol found */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0xffffffffffffffff); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* The actual first instruction of the function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x1010, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* The last instruction in the function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x102D, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0x1d); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* The padding below the function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x102E, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0x1e); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* One byte before the next function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x103f, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0x2f); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* First byte of the next function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x1040, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsChkdsk"); + + if (!can_enumerate(hProc, BaseAddress)) + { + skip("dbghelp.dll too old or cannot read this symbol!\n"); + } + else + { + /* .idata */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x2000, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x2000); + ok_hex(pSymbol->Tag, SymTagPublicSymbol); + ok_str(pSymbol->Name, "__imp__DbgPrint"); + } + + deinit_sym(); +} + +typedef struct _test_context +{ + DWORD64 BaseAddress; + SIZE_T Index; +} test_context; + +static struct _test_data { + DWORD64 AddressOffset; + ULONG Size; + ULONG Tag; + const char* Name; +} test_data[] = { + { 0x1070, 36, SymTagFunction, "FfsFormat" }, + { 0x1010, 32, SymTagFunction, "DllMain" }, + { 0x1040, 36, SymTagFunction, "FfsChkdsk" }, + + { 0x2100, 0, SymTagPublicSymbol, "__IMPORT_DESCRIPTOR_ntdll" }, + { 0x109a, 0, SymTagPublicSymbol, "_DbgPrint" }, + { 0x2004, 0, SymTagPublicSymbol, "\x7fntdll_NULL_THUNK_DATA" }, + { 0x2000, 0, SymTagPublicSymbol, "__imp__DbgPrint" }, + { 0x2114, 0, SymTagPublicSymbol, "__NULL_IMPORT_DESCRIPTOR" }, +}; + +static BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext) +{ + test_context* ctx = UserContext; + + if (ctx->Index < ARRAYSIZE(test_data)) + { + ok_ulonglong(pSymInfo->ModBase, ctx->BaseAddress); + ok_ulonglong(pSymInfo->Address, ctx->BaseAddress + test_data[ctx->Index].AddressOffset); + ok_hex(pSymInfo->Tag, test_data[ctx->Index].Tag); + ok_str(pSymInfo->Name, test_data[ctx->Index].Name); + + ctx->Index++; + } + else + { + ok(0, "Out of bounds (%i), max is: %i!\n", ctx->Index, ARRAYSIZE(test_data)); + } + + return TRUE; +} + +static void test_SymEnumSymbols(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + DWORD dwErr; + + test_context ctx; + + if (!init_sym()) + return; + + ctx.Index = 0; + SetLastError(ERROR_SUCCESS); + ctx.BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(ctx.BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + if (!can_enumerate(hProc, ctx.BaseAddress)) + { + skip("dbghelp.dll too old or cannot enumerate symbols!\n"); + } + else + { + Ret = SymEnumSymbols(hProc, ctx.BaseAddress, NULL, EnumSymProc, &ctx); + ok_int(Ret, TRUE); + ok_int(ctx.Index, ARRAYSIZE(test_data)); + } + + deinit_sym(); +} + + +START_TEST(pdb) +{ + char szDllName[MAX_PATH]; + //create_compressed_files(); + + DWORD Options = SymGetOptions(); + Options &= ~(SYMOPT_UNDNAME); + //Options |= SYMOPT_DEBUG; + SymSetOptions(Options); + + if (!extract_msvc_exe(szDllName)) + { + ok(0, "Failed extracting files\n"); + return; + } + + test_SymFromName(proc(), szDllName); + test_SymFromAddr(proc(), szDllName); + test_SymEnumSymbols(proc(), szDllName); + + cleanup_msvc_exe(); +} Index: rostests/apitests/dbghelp/resource.rc =================================================================== --- rostests/apitests/dbghelp/resource.rc (nonexistent) +++ rostests/apitests/dbghelp/resource.rc (working copy) @@ -0,0 +1,5 @@ +#include "windef.h" + +msvc_uffs.dll RCDATA testdata/msvc_uffs.dll.compr +msvc_uffs.pdb RCDATA testdata/msvc_uffs.pdb.compr +gcc_uffs.dll RCDATA testdata/gcc_uffs.dll.compr Index: rostests/apitests/dbghelp/rsym.c =================================================================== --- rostests/apitests/dbghelp/rsym.c (nonexistent) +++ rostests/apitests/dbghelp/rsym.c (working copy) @@ -0,0 +1,299 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Test for dbghelp rsym functions + * PROGRAMMER: Mark Jansen + * + * These tests are based on the PDB tests. + */ + +#include +#define WIN32_NO_STATUS +#include +#include +#include // SymTagXXX +#include + +#include "wine/test.h" + +#define ok_ulonglong(expression, result) \ + do { \ + ULONG64 _value = (expression); \ + ULONG64 _result = (result); \ + ok(_value == (result), "Wrong value for '%s', expected: " #result " (%s), got: %s\n", \ + #expression, wine_dbgstr_longlong(_result), wine_dbgstr_longlong(_value)); \ + } while (0) + + +// data.c +void dump_rsym(const char* filename); +int extract_gcc_exe(char szFile[MAX_PATH]); +void cleanup_gcc_exe(); + +static HANDLE proc() +{ + return GetCurrentProcess(); +} + +static BOOL init_sym_imp(const char* file, int line) +{ + if (!SymInitialize(proc(), NULL, FALSE)) + { + DWORD err = GetLastError(); + ok_(file, line)(0, "Failed to init: 0x%x\n", err); + return FALSE; + } + return TRUE; +} + +static void deinit_sym() +{ + SymCleanup(proc()); +} + +#define init_sym() init_sym_imp(__FILE__, __LINE__) + +#define INIT_PSYM(buff) do { \ + memset((buff), 0, sizeof((buff))); \ + ((PSYMBOL_INFO)(buff))->SizeOfStruct = sizeof(SYMBOL_INFO); \ + ((PSYMBOL_INFO)(buff))->MaxNameLen = MAX_SYM_NAME; \ +} while (0) + + +static void test_SymFromName(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + + DWORD64 BaseAddress; + DWORD dwErr; + + if (!init_sym()) + return; + + SetLastError(ERROR_SUCCESS); + BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "DllMain", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "FfsChkdsk", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsChkdsk"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "FfsFormat", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1070); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsFormat"); + + deinit_sym(); +} + +static void test_SymFromAddr(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + + DWORD64 BaseAddress, Displacement; + DWORD dwErr; + + if (!init_sym()) + return; + + SetLastError(ERROR_SUCCESS); + BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + /* No address found before load address of module */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress -1, &Displacement, pSymbol); + dwErr = GetLastError(); + ok_int(Ret, FALSE); + ok_hex(dwErr, ERROR_MOD_NOT_FOUND); + + /* Right at the start of the module is recognized as the first symbol found */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0xffffffffffffffff); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1000); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* The actual first instruction of the function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x1000, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1000); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* The last instruction in the function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x1009, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0x1d); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1000); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* First byte of the next function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x103F, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x103F); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsChkdsk"); + + /* .idata */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x4000, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x4000); + ok_hex(pSymbol->Tag, SymTagPublicSymbol); + ok_str(pSymbol->Name, "_head_dll_ntdll_libntdll_a"); + + deinit_sym(); +} + +typedef struct _test_context +{ + DWORD64 BaseAddress; + SIZE_T Index; +} test_context; + +static struct _test_data { + DWORD64 AddressOffset; + ULONG Size; + ULONG Tag; + const char* Name; +} test_data[] = { + { 0x1000, 12, SymTagFunction, "DllMain" }, + { 0x1070, 51, SymTagFunction, "FfsFormat" }, + { 0x1040, 53, SymTagFunction, "FfsChkdsk" }, + + { 0x1074, 0, SymTagPublicSymbol, "DbgPrint" }, + { 0x107c, 0, SymTagPublicSymbol, "__CTOR_LIST__" }, + { 0x1084, 0, SymTagPublicSymbol, "__DTOR_LIST__" }, + { 0x2074, 0, SymTagPublicSymbol, "_rt_psrelocs_start" }, + { 0x2074, 0, SymTagPublicSymbol, "__RUNTIME_PSEUDO_RELOC_LIST_END__" }, + { 0x2074, 0, SymTagPublicSymbol, "_rt_psrelocs_end" }, + { 0x4000, 0, SymTagPublicSymbol, "_head_dll_ntdll_libntdll_a" }, + { 0x4030, 0, SymTagPublicSymbol, "_imp__DbgPrint" }, + { 0x4048, 0, SymTagPublicSymbol, "_dll_ntdll_libntdll_a_iname" }, + +}; + +BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext) +{ + test_context* ctx = UserContext; + + if (ctx->Index < ARRAYSIZE(test_data)) + { + ok_ulonglong(pSymInfo->ModBase, ctx->BaseAddress); + ok_ulonglong(pSymInfo->Address, ctx->BaseAddress + test_data[ctx->Index].AddressOffset); + ok_hex(pSymInfo->Tag, test_data[ctx->Index].Tag); + ok_str(pSymInfo->Name, test_data[ctx->Index].Name); + + ctx->Index++; + } + else + { + ok(0, "Out of bounds (%i), max is: %i!\n", ctx->Index, ARRAYSIZE(test_data)); + } + + return TRUE; +} + +static void test_SymEnumSymbols(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + DWORD dwErr; + + test_context ctx; + + if (!init_sym()) + return; + + ctx.Index = 0; + SetLastError(ERROR_SUCCESS); + ctx.BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(ctx.BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + Ret = SymEnumSymbols(hProc, ctx.BaseAddress, "*", EnumSymProc, &ctx); + ok_int(Ret, TRUE); + + deinit_sym(); +} + + + + +START_TEST(rsym) +{ + char szDllName[MAX_PATH]; + //dump_rsym("R:\\src\\trunk\\reactos\\modules\\rostests\\apitests\\dbghelp\\testdata\\gcc_uffs.dll"); + + DWORD Options = SymGetOptions(); + Options &= ~(SYMOPT_UNDNAME); + //Options |= SYMOPT_DEBUG; + SymSetOptions(Options); + + if (!extract_gcc_exe(szDllName)) + { + ok(0, "Failed extracting files\n"); + return; + } + + test_SymFromName(proc(), szDllName); + test_SymFromAddr(proc(), szDllName); + test_SymEnumSymbols(proc(), szDllName); + + cleanup_gcc_exe(); +} Index: rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr =================================================================== --- rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr (nonexistent) +++ rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr (working copy) Property changes on: rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr =================================================================== --- rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr (nonexistent) +++ rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr (working copy) Property changes on: rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr =================================================================== --- rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr (nonexistent) +++ rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr (working copy) Property changes on: rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: rostests/apitests/dbghelp/testlist.c =================================================================== --- rostests/apitests/dbghelp/testlist.c (nonexistent) +++ rostests/apitests/dbghelp/testlist.c (working copy) @@ -0,0 +1,14 @@ + +#define STANDALONE +#include +#include + +extern void func_pdb(void); +extern void func_rsym(void); + +const struct test winetest_testlist[] = +{ + { "pdb", func_pdb }, + { "rsym", func_rsym }, + { 0, 0 } +}; Index: rostests/apitests/dbghelp/CMakeLists.txt =================================================================== --- rostests/apitests/dbghelp/CMakeLists.txt (nonexistent) +++ rostests/apitests/dbghelp/CMakeLists.txt (working copy) @@ -0,0 +1,20 @@ + +add_definitions(-D__ROS_LONG64__ -DWINETEST_USE_DBGSTR_LONGLONG) + +include_directories( + ${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/zlib + ${REACTOS_SOURCE_DIR}/sdk/tools/rsym +) + +list(APPEND SOURCE + pdb.c + rsym.c + data.c + testlist.c) + +add_executable(dbghelp_apitest ${SOURCE} resource.rc) +set_module_type(dbghelp_apitest win32cui) +target_link_libraries(dbghelp_apitest zlib) +add_delay_importlibs(dbghelp_apitest dbghelp) +add_importlibs(dbghelp_apitest msvcrt kernel32 ntdll) +add_rostests_file(TARGET dbghelp_apitest) Index: rostests/apitests/dbghelp/data.c =================================================================== --- rostests/apitests/dbghelp/data.c (nonexistent) +++ rostests/apitests/dbghelp/data.c (working copy) @@ -0,0 +1,273 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Support functions for dbghelp api test + * PROGRAMMER: Mark Jansen + */ + +#include +#include +#include + +#include "wine/test.h" + +extern IMAGE_DOS_HEADER __ImageBase; + +static char szTempPath[MAX_PATH]; + +static const char* tmpdir() +{ + if (szTempPath[0] == '\0') + { + GetTempPathA(MAX_PATH, szTempPath); + lstrcatA(szTempPath, "dbghelp_tst"); + } + return szTempPath; +} + +static int extract_one(const char* filename, const char* resid) +{ + HMODULE mod = (HMODULE)&__ImageBase; + HGLOBAL glob; + PVOID data, decompressed; + DWORD size, dstsize; + HANDLE file; + int ret; + HRSRC rsrc = FindResourceA(mod, resid, MAKEINTRESOURCEA(RT_RCDATA)); + ok(rsrc != 0, "Failed finding '%s' res\n", resid); + if (!rsrc) + return 0; + + size = SizeofResource(mod, rsrc); + glob = LoadResource(mod, rsrc); + ok(glob != NULL, "Failed loading '%s' res\n", resid); + if (!glob) + return 0; + + data = LockResource(glob); + + dstsize = 1024 * 256; + decompressed = malloc(dstsize); + + if (uncompress(decompressed, &dstsize, data, size) != Z_OK) + { + ok(0, "uncompress failed for %s\n", resid); + free(decompressed); + return 0; + } + + + file = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + ret = WriteFile(file, decompressed, dstsize, &size, NULL); + CloseHandle(file); + free(decompressed); + return ret && dstsize == size; +} + + +int extract_msvc_exe(char szFile[MAX_PATH]) +{ + const char* dir = tmpdir(); + BOOL ret = CreateDirectoryA(dir, NULL); + ok(ret, "CreateDirectoryA failed(%d)\n", GetLastError()); + + sprintf(szFile, "%s\\uffs.pdb", dir); + if (!extract_one(szFile, "msvc_uffs.pdb")) + return 0; + + sprintf(szFile, "%s\\uffs.dll", dir); + if (!extract_one(szFile, "msvc_uffs.dll")) + return 0; + + return 1; +} + +void cleanup_msvc_exe() +{ + char szFile[MAX_PATH]; + BOOL ret; + const char* dir = tmpdir(); + + sprintf(szFile, "%s\\uffs.pdb", dir); + ret = DeleteFileA(szFile); + ok(ret, "DeleteFileA failed(%d)\n", GetLastError()); + + sprintf(szFile, "%s\\uffs.dll", dir); + ret = DeleteFileA(szFile); + ok(ret, "DeleteFileA failed(%d)\n", GetLastError()); + ret = RemoveDirectoryA(dir); + ok(ret, "RemoveDirectoryA failed(%d)\n", GetLastError()); +} + +int extract_gcc_exe(char szFile[MAX_PATH]) +{ + const char* dir = tmpdir(); + BOOL ret = CreateDirectoryA(dir, NULL); + ok(ret, "CreateDirectoryA failed(%d)\n", GetLastError()); + + sprintf(szFile, "%s\\uffs.dll", dir); + if (!extract_one(szFile, "gcc_uffs.dll")) + return 0; + + return 1; +} + +void cleanup_gcc_exe() +{ + char szFile[MAX_PATH]; + BOOL ret; + const char* dir = tmpdir(); + + sprintf(szFile, "%s\\uffs.dll", dir); + ret = DeleteFileA(szFile); + ok(ret, "DeleteFileA failed(%d)\n", GetLastError()); + ret = RemoveDirectoryA(dir); + ok(ret, "RemoveDirectoryA failed(%d)\n", GetLastError()); +} + + +#if 0 +static int compress_one(const char* src, const char* dest) +{ + DWORD size, size2, res; + FILE* file = fopen(src, "rb"); + fseek(file, 0, SEEK_END); + size = ftell(file); + fseek(file, 0, SEEK_SET); + + Bytef* buffer, *buffer2; + DWORD dwErr = GetLastError(); + + buffer = malloc(size); + res = fread(buffer, 1, size, file); + + fclose(file); + + if (res != size) + { + printf("Could not read file: 0x%x\n", dwErr); + free(buffer); + CloseHandle(file); + return 0; + } + size2 = size *2; + buffer2 = malloc(size2); + res = compress(buffer2, &size2, buffer, size); + + free(buffer); + + if (Z_OK != res) + { + free(buffer2); + return 0; + } + + file = fopen(dest, "wb"); + res = fwrite(buffer2, 1, size2, file); + fclose(file); + + free(buffer2); + + return size2 == res; +} + +void create_compressed_files() +{ + SetCurrentDirectoryA("R:/src/trunk/reactos/modules/rostests/apitests/dbghelp"); + if (!compress_one("testdata/msvc_uffs.dll", "testdata/msvc_uffs.dll.compr")) + printf("msvc_uffs.dll failed\n"); + if (!compress_one("testdata/msvc_uffs.pdb", "testdata/msvc_uffs.pdb.compr")) + printf("msvc_uffs.pdb failed\n"); + if (!compress_one("testdata/gcc_uffs.dll", "testdata/gcc_uffs.dll.compr")) + printf("gcc_uffs.dll failed\n"); +} +#endif + +#if 0 +typedef struct _SYMBOLFILE_HEADER { + ULONG SymbolsOffset; + ULONG SymbolsLength; + ULONG StringsOffset; + ULONG StringsLength; +} SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER; + +typedef struct _ROSSYM_ENTRY { + ULONG Address; + ULONG FunctionOffset; + ULONG FileOffset; + ULONG SourceLine; +} ROSSYM_ENTRY, *PROSSYM_ENTRY; + + +static int is_metadata(const char* name) +{ + size_t len = name ? strlen(name) : 0; + return len > 3 && name[0] == '_' && name[1] != '_' && name[len-1] == '_' && name[len-2] == '_'; +}; + +static void dump_rsym_internal(void* data) +{ + PSYMBOLFILE_HEADER RosSymHeader = (PSYMBOLFILE_HEADER)data; + PROSSYM_ENTRY Entries = (PROSSYM_ENTRY)((char *)data + RosSymHeader->SymbolsOffset); + size_t symbols = RosSymHeader->SymbolsLength / sizeof(ROSSYM_ENTRY); + size_t i; + char *Strings = (char *)data + RosSymHeader->StringsOffset; + + for (i = 0; i < symbols; i++) + { + PROSSYM_ENTRY Entry = Entries + i; + if (!Entry->FileOffset) + { + if (Entry->SourceLine) + printf("ERR: SOURCELINE (%D) ", Entry->SourceLine); + if (is_metadata(Strings + Entry->FunctionOffset)) + printf("metadata: %s: 0x%x\n", Strings + Entry->FunctionOffset, Entry->Address); + else + printf("0x%x: %s\n", Entry->Address, Strings + Entry->FunctionOffset); + } + else + { + printf("0x%x: %s (%s:%u)\n", Entry->Address, + Strings + Entry->FunctionOffset, + Strings + Entry->FileOffset, + Entry->SourceLine); + } + } + +} + +void dump_rsym(const char* filename) +{ + char* data; + long size, res; + PIMAGE_FILE_HEADER PEFileHeader; + PIMAGE_OPTIONAL_HEADER PEOptHeader; + PIMAGE_SECTION_HEADER PESectionHeaders; + WORD i; + + FILE* f = fopen(filename, "rb"); + + fseek(f, 0, SEEK_END); + size = ftell(f); + fseek(f, 0, SEEK_SET); + + data = malloc(size); + res = fread(data, 1, size, f); + fclose(f); + + PEFileHeader = (PIMAGE_FILE_HEADER)((char *)data + ((PIMAGE_DOS_HEADER)data)->e_lfanew + sizeof(ULONG)); + PEOptHeader = (PIMAGE_OPTIONAL_HEADER)(PEFileHeader + 1); + PESectionHeaders = (PIMAGE_SECTION_HEADER)((char *)PEOptHeader + PEFileHeader->SizeOfOptionalHeader); + + for (i = 0; i < PEFileHeader->NumberOfSections; i++) + { + if (!strcmp((char *)PESectionHeaders[i].Name, ".rossym")) + { + dump_rsym_internal(data + PESectionHeaders[i].PointerToRawData); + break; + } + } + free(data); +} + +#endif Index: rostests/apitests/dbghelp/pdb.c =================================================================== --- rostests/apitests/dbghelp/pdb.c (nonexistent) +++ rostests/apitests/dbghelp/pdb.c (working copy) @@ -0,0 +1,377 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Test for dbghelp PDB functions + * PROGRAMMER: Mark Jansen + */ + +#include +#define WIN32_NO_STATUS +#include +#include +#include // SymTagXXX +#include + +#include "wine/test.h" + +#define ok_ulonglong(expression, result) \ + do { \ + ULONG64 _value = (expression); \ + ULONG64 _result = (result); \ + ok(_value == (result), "Wrong value for '%s', expected: " #result " (%s), got: %s\n", \ + #expression, wine_dbgstr_longlong(_result), wine_dbgstr_longlong(_value)); \ + } while (0) + + +// data.c +void create_compressed_files(); +int extract_msvc_exe(char szFile[MAX_PATH]); +void cleanup_msvc_exe(); + +static HANDLE proc() +{ + return GetCurrentProcess(); +} + +static BOOL init_sym_imp(const char* file, int line) +{ + if (!SymInitialize(proc(), NULL, FALSE)) + { + DWORD err = GetLastError(); + ok_(file, line)(0, "Failed to init: 0x%x\n", err); + return FALSE; + } + return TRUE; +} + +static void deinit_sym() +{ + SymCleanup(proc()); +} + +#define init_sym() init_sym_imp(__FILE__, __LINE__) + +#define INIT_PSYM(buff) do { \ + memset((buff), 0, sizeof((buff))); \ + ((PSYMBOL_INFO)(buff))->SizeOfStruct = sizeof(SYMBOL_INFO); \ + ((PSYMBOL_INFO)(buff))->MaxNameLen = MAX_SYM_NAME; \ +} while (0) + + +/* Maybe our dbghelp.dll is too old? */ +static BOOL can_enumerate(HANDLE hProc, DWORD64 BaseAddress) +{ + IMAGEHLP_MODULE64 ModuleInfo; + BOOL Ret; + + memset(&ModuleInfo, 0, sizeof(ModuleInfo)); + ModuleInfo.SizeOfStruct = sizeof(ModuleInfo); + Ret = SymGetModuleInfo64(hProc, BaseAddress, &ModuleInfo); + + return Ret && ModuleInfo.SymType == SymPdb; +} + + +static void test_SymFromName(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + + DWORD64 BaseAddress; + DWORD dwErr; + + if (!init_sym()) + return; + + SetLastError(ERROR_SUCCESS); + BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + if (!can_enumerate(hProc, BaseAddress)) + { + skip("dbghelp.dll too old or cannot enumerate symbols!\n"); + } + else + { + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "DllMain", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "_DllMain@12", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0x400000); // ?? + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagPublicSymbol); + ok_str(pSymbol->Name, "_DllMain@12"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "FfsChkdsk", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsChkdsk"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "_FfsChkdsk@24", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0x400000); // ?? + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); + ok_hex(pSymbol->Tag, SymTagPublicSymbol); + ok_str(pSymbol->Name, "_FfsChkdsk@24"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "FfsFormat", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1070); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsFormat"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "_FfsFormat@24", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0x400000); // ?? + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1070); + ok_hex(pSymbol->Tag, SymTagPublicSymbol); + ok_str(pSymbol->Name, "_FfsFormat@24"); + } + + deinit_sym(); +} + +static void test_SymFromAddr(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + + DWORD64 BaseAddress, Displacement; + DWORD dwErr; + + if (!init_sym()) + return; + + SetLastError(ERROR_SUCCESS); + BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + /* No address found before load address of module */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress -1, &Displacement, pSymbol); + dwErr = GetLastError(); + ok_int(Ret, FALSE); + ok_hex(dwErr, ERROR_MOD_NOT_FOUND); + + /* Right at the start of the module is recognized as the first symbol found */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0xffffffffffffffff); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* The actual first instruction of the function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x1010, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* The last instruction in the function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x102D, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0x1d); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* The padding below the function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x102E, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0x1e); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* One byte before the next function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x103f, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0x2f); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* First byte of the next function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x1040, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsChkdsk"); + + if (!can_enumerate(hProc, BaseAddress)) + { + skip("dbghelp.dll too old or cannot read this symbol!\n"); + } + else + { + /* .idata */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x2000, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x2000); + ok_hex(pSymbol->Tag, SymTagPublicSymbol); + ok_str(pSymbol->Name, "__imp__DbgPrint"); + } + + deinit_sym(); +} + +typedef struct _test_context +{ + DWORD64 BaseAddress; + SIZE_T Index; +} test_context; + +static struct _test_data { + DWORD64 AddressOffset; + ULONG Size; + ULONG Tag; + const char* Name; +} test_data[] = { + { 0x1070, 36, SymTagFunction, "FfsFormat" }, + { 0x1010, 32, SymTagFunction, "DllMain" }, + { 0x1040, 36, SymTagFunction, "FfsChkdsk" }, + + { 0x2100, 0, SymTagPublicSymbol, "__IMPORT_DESCRIPTOR_ntdll" }, + { 0x109a, 0, SymTagPublicSymbol, "_DbgPrint" }, + { 0x2004, 0, SymTagPublicSymbol, "\x7fntdll_NULL_THUNK_DATA" }, + { 0x2000, 0, SymTagPublicSymbol, "__imp__DbgPrint" }, + { 0x2114, 0, SymTagPublicSymbol, "__NULL_IMPORT_DESCRIPTOR" }, +}; + +static BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext) +{ + test_context* ctx = UserContext; + + if (ctx->Index < ARRAYSIZE(test_data)) + { + ok_ulonglong(pSymInfo->ModBase, ctx->BaseAddress); + ok_ulonglong(pSymInfo->Address, ctx->BaseAddress + test_data[ctx->Index].AddressOffset); + ok_hex(pSymInfo->Tag, test_data[ctx->Index].Tag); + ok_str(pSymInfo->Name, test_data[ctx->Index].Name); + + ctx->Index++; + } + else + { + ok(0, "Out of bounds (%i), max is: %i!\n", ctx->Index, ARRAYSIZE(test_data)); + } + + return TRUE; +} + +static void test_SymEnumSymbols(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + DWORD dwErr; + + test_context ctx; + + if (!init_sym()) + return; + + ctx.Index = 0; + SetLastError(ERROR_SUCCESS); + ctx.BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(ctx.BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + if (!can_enumerate(hProc, ctx.BaseAddress)) + { + skip("dbghelp.dll too old or cannot enumerate symbols!\n"); + } + else + { + Ret = SymEnumSymbols(hProc, ctx.BaseAddress, NULL, EnumSymProc, &ctx); + ok_int(Ret, TRUE); + ok_int(ctx.Index, ARRAYSIZE(test_data)); + } + + deinit_sym(); +} + + +START_TEST(pdb) +{ + char szDllName[MAX_PATH]; + //create_compressed_files(); + + DWORD Options = SymGetOptions(); + Options &= ~(SYMOPT_UNDNAME); + //Options |= SYMOPT_DEBUG; + SymSetOptions(Options); + + if (!extract_msvc_exe(szDllName)) + { + ok(0, "Failed extracting files\n"); + return; + } + + test_SymFromName(proc(), szDllName); + test_SymFromAddr(proc(), szDllName); + test_SymEnumSymbols(proc(), szDllName); + + cleanup_msvc_exe(); +} Index: rostests/apitests/dbghelp/resource.rc =================================================================== --- rostests/apitests/dbghelp/resource.rc (nonexistent) +++ rostests/apitests/dbghelp/resource.rc (working copy) @@ -0,0 +1,5 @@ +#include "windef.h" + +msvc_uffs.dll RCDATA testdata/msvc_uffs.dll.compr +msvc_uffs.pdb RCDATA testdata/msvc_uffs.pdb.compr +gcc_uffs.dll RCDATA testdata/gcc_uffs.dll.compr Index: rostests/apitests/dbghelp/rsym.c =================================================================== --- rostests/apitests/dbghelp/rsym.c (nonexistent) +++ rostests/apitests/dbghelp/rsym.c (working copy) @@ -0,0 +1,299 @@ +/* + * PROJECT: ReactOS api tests + * LICENSE: GPLv2+ - See COPYING in the top level directory + * PURPOSE: Test for dbghelp rsym functions + * PROGRAMMER: Mark Jansen + * + * These tests are based on the PDB tests. + */ + +#include +#define WIN32_NO_STATUS +#include +#include +#include // SymTagXXX +#include + +#include "wine/test.h" + +#define ok_ulonglong(expression, result) \ + do { \ + ULONG64 _value = (expression); \ + ULONG64 _result = (result); \ + ok(_value == (result), "Wrong value for '%s', expected: " #result " (%s), got: %s\n", \ + #expression, wine_dbgstr_longlong(_result), wine_dbgstr_longlong(_value)); \ + } while (0) + + +// data.c +void dump_rsym(const char* filename); +int extract_gcc_exe(char szFile[MAX_PATH]); +void cleanup_gcc_exe(); + +static HANDLE proc() +{ + return GetCurrentProcess(); +} + +static BOOL init_sym_imp(const char* file, int line) +{ + if (!SymInitialize(proc(), NULL, FALSE)) + { + DWORD err = GetLastError(); + ok_(file, line)(0, "Failed to init: 0x%x\n", err); + return FALSE; + } + return TRUE; +} + +static void deinit_sym() +{ + SymCleanup(proc()); +} + +#define init_sym() init_sym_imp(__FILE__, __LINE__) + +#define INIT_PSYM(buff) do { \ + memset((buff), 0, sizeof((buff))); \ + ((PSYMBOL_INFO)(buff))->SizeOfStruct = sizeof(SYMBOL_INFO); \ + ((PSYMBOL_INFO)(buff))->MaxNameLen = MAX_SYM_NAME; \ +} while (0) + + +static void test_SymFromName(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + + DWORD64 BaseAddress; + DWORD dwErr; + + if (!init_sym()) + return; + + SetLastError(ERROR_SUCCESS); + BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "DllMain", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1010); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "FfsChkdsk", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1040); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsChkdsk"); + + INIT_PSYM(buffer); + Ret = SymFromName(hProc, "FfsFormat", pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1070); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsFormat"); + + deinit_sym(); +} + +static void test_SymFromAddr(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; + PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; + + DWORD64 BaseAddress, Displacement; + DWORD dwErr; + + if (!init_sym()) + return; + + SetLastError(ERROR_SUCCESS); + BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + /* No address found before load address of module */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress -1, &Displacement, pSymbol); + dwErr = GetLastError(); + ok_int(Ret, FALSE); + ok_hex(dwErr, ERROR_MOD_NOT_FOUND); + + /* Right at the start of the module is recognized as the first symbol found */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0xffffffffffffffff); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1000); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* The actual first instruction of the function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x1000, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1000); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* The last instruction in the function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x1009, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0x1d); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x1000); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "DllMain"); + + /* First byte of the next function */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x103F, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x103F); + ok_hex(pSymbol->Tag, SymTagFunction); + ok_str(pSymbol->Name, "FfsChkdsk"); + + /* .idata */ + Displacement = 0; + INIT_PSYM(buffer); + Ret = SymFromAddr(hProc, BaseAddress + 0x4000, &Displacement, pSymbol); + ok_int(Ret, TRUE); + ok_ulonglong(Displacement, 0); + ok_ulonglong(pSymbol->ModBase, BaseAddress); + ok_hex(pSymbol->Flags, 0); + ok_ulonglong(pSymbol->Address, BaseAddress + 0x4000); + ok_hex(pSymbol->Tag, SymTagPublicSymbol); + ok_str(pSymbol->Name, "_head_dll_ntdll_libntdll_a"); + + deinit_sym(); +} + +typedef struct _test_context +{ + DWORD64 BaseAddress; + SIZE_T Index; +} test_context; + +static struct _test_data { + DWORD64 AddressOffset; + ULONG Size; + ULONG Tag; + const char* Name; +} test_data[] = { + { 0x1000, 12, SymTagFunction, "DllMain" }, + { 0x1070, 51, SymTagFunction, "FfsFormat" }, + { 0x1040, 53, SymTagFunction, "FfsChkdsk" }, + + { 0x1074, 0, SymTagPublicSymbol, "DbgPrint" }, + { 0x107c, 0, SymTagPublicSymbol, "__CTOR_LIST__" }, + { 0x1084, 0, SymTagPublicSymbol, "__DTOR_LIST__" }, + { 0x2074, 0, SymTagPublicSymbol, "_rt_psrelocs_start" }, + { 0x2074, 0, SymTagPublicSymbol, "__RUNTIME_PSEUDO_RELOC_LIST_END__" }, + { 0x2074, 0, SymTagPublicSymbol, "_rt_psrelocs_end" }, + { 0x4000, 0, SymTagPublicSymbol, "_head_dll_ntdll_libntdll_a" }, + { 0x4030, 0, SymTagPublicSymbol, "_imp__DbgPrint" }, + { 0x4048, 0, SymTagPublicSymbol, "_dll_ntdll_libntdll_a_iname" }, + +}; + +BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext) +{ + test_context* ctx = UserContext; + + if (ctx->Index < ARRAYSIZE(test_data)) + { + ok_ulonglong(pSymInfo->ModBase, ctx->BaseAddress); + ok_ulonglong(pSymInfo->Address, ctx->BaseAddress + test_data[ctx->Index].AddressOffset); + ok_hex(pSymInfo->Tag, test_data[ctx->Index].Tag); + ok_str(pSymInfo->Name, test_data[ctx->Index].Name); + + ctx->Index++; + } + else + { + ok(0, "Out of bounds (%i), max is: %i!\n", ctx->Index, ARRAYSIZE(test_data)); + } + + return TRUE; +} + +static void test_SymEnumSymbols(HANDLE hProc, const char* szModuleName) +{ + BOOL Ret; + DWORD dwErr; + + test_context ctx; + + if (!init_sym()) + return; + + ctx.Index = 0; + SetLastError(ERROR_SUCCESS); + ctx.BaseAddress = SymLoadModule64(hProc, NULL, szModuleName, NULL, 0x600000, 0); + dwErr = GetLastError(); + + ok_ulonglong(ctx.BaseAddress, 0x600000); + ok_hex(dwErr, ERROR_SUCCESS); + + Ret = SymEnumSymbols(hProc, ctx.BaseAddress, "*", EnumSymProc, &ctx); + ok_int(Ret, TRUE); + + deinit_sym(); +} + + + + +START_TEST(rsym) +{ + char szDllName[MAX_PATH]; + //dump_rsym("R:\\src\\trunk\\reactos\\modules\\rostests\\apitests\\dbghelp\\testdata\\gcc_uffs.dll"); + + DWORD Options = SymGetOptions(); + Options &= ~(SYMOPT_UNDNAME); + //Options |= SYMOPT_DEBUG; + SymSetOptions(Options); + + if (!extract_gcc_exe(szDllName)) + { + ok(0, "Failed extracting files\n"); + return; + } + + test_SymFromName(proc(), szDllName); + test_SymFromAddr(proc(), szDllName); + test_SymEnumSymbols(proc(), szDllName); + + cleanup_gcc_exe(); +} Index: rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr =================================================================== --- rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr (nonexistent) +++ rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr (working copy) Property changes on: rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr =================================================================== --- rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr (nonexistent) +++ rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr (working copy) Property changes on: rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr =================================================================== --- rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr (nonexistent) +++ rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr (working copy) Property changes on: rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr =================================================================== --- rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr (nonexistent) +++ rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr (working copy) Property changes on: rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr =================================================================== --- rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr (nonexistent) +++ rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr (working copy) Property changes on: rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr =================================================================== --- rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr (nonexistent) +++ rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr (working copy) Property changes on: rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: rostests/apitests/dbghelp/testlist.c =================================================================== --- rostests/apitests/dbghelp/testlist.c (nonexistent) +++ rostests/apitests/dbghelp/testlist.c (working copy) @@ -0,0 +1,14 @@ + +#define STANDALONE +#include +#include + +extern void func_pdb(void); +extern void func_rsym(void); + +const struct test winetest_testlist[] = +{ + { "pdb", func_pdb }, + { "rsym", func_rsym }, + { 0, 0 } +};