Author: mjansen
Date: Fri Feb 17 16:15:49 2017
New Revision: 73816
URL:
http://svn.reactos.org/svn/reactos?rev=73816&view=rev
Log:
[DBGHELP_APITEST] Add tests for pdb and rsym parsing. CORE-12773
Added:
trunk/rostests/apitests/dbghelp/
trunk/rostests/apitests/dbghelp/CMakeLists.txt (with props)
trunk/rostests/apitests/dbghelp/data.c (with props)
trunk/rostests/apitests/dbghelp/pdb.c (with props)
trunk/rostests/apitests/dbghelp/resource.rc (with props)
trunk/rostests/apitests/dbghelp/rsym.c (with props)
trunk/rostests/apitests/dbghelp/testdata/
trunk/rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr (with props)
trunk/rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr (with props)
trunk/rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr (with props)
trunk/rostests/apitests/dbghelp/testlist.c (with props)
Modified:
trunk/rostests/apitests/CMakeLists.txt
Modified: trunk/rostests/apitests/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/CMakeLists.txt?r…
==============================================================================
--- trunk/rostests/apitests/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/rostests/apitests/CMakeLists.txt [iso-8859-1] Fri Feb 17 16:15:49 2017
@@ -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)
Added: trunk/rostests/apitests/dbghelp/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/dbghelp/CMakeLis…
==============================================================================
--- trunk/rostests/apitests/dbghelp/CMakeLists.txt (added)
+++ trunk/rostests/apitests/dbghelp/CMakeLists.txt [iso-8859-1] Fri Feb 17 16:15:49 2017
@@ -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)
Propchange: trunk/rostests/apitests/dbghelp/CMakeLists.txt
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/rostests/apitests/dbghelp/data.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/dbghelp/data.c?r…
==============================================================================
--- trunk/rostests/apitests/dbghelp/data.c (added)
+++ trunk/rostests/apitests/dbghelp/data.c [iso-8859-1] Fri Feb 17 16:15:49 2017
@@ -0,0 +1,277 @@
+/*
+ * PROJECT: ReactOS api tests
+ * LICENSE: GPLv2+ - See COPYING in the top level directory
+ * PURPOSE: Support functions for dbghelp api test
+ * PROGRAMMER: Mark Jansen
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <zlib.h>
+
+#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;
+ uLongf size, dstsize;
+ DWORD gccSize, dwErr;
+ 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);
+ gccSize = size;
+ ret = WriteFile(file, decompressed, dstsize, &gccSize, NULL);
+ dwErr = GetLastError();
+ CloseHandle(file);
+ free(decompressed);
+ ok(ret, "WriteFile failed (%d)\n", dwErr);
+ return ret && dstsize == gccSize;
+}
+
+
+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
Propchange: trunk/rostests/apitests/dbghelp/data.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/rostests/apitests/dbghelp/pdb.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/dbghelp/pdb.c?re…
==============================================================================
--- trunk/rostests/apitests/dbghelp/pdb.c (added)
+++ trunk/rostests/apitests/dbghelp/pdb.c [iso-8859-1] Fri Feb 17 16:15:49 2017
@@ -0,0 +1,378 @@
+/*
+ * PROJECT: ReactOS api tests
+ * LICENSE: GPLv2+ - See COPYING in the top level directory
+ * PURPOSE: Test for dbghelp PDB functions
+ * PROGRAMMER: Mark Jansen
+ */
+
+#include <ntstatus.h>
+#define WIN32_NO_STATUS
+#include <windows.h>
+#include <dbghelp.h>
+#include <cvconst.h> // SymTagXXX
+#include <stdio.h>
+
+#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[] = {
+ /* TODO: Order is based on magic, should find entries based on name, and mark as
'seen' */
+ { 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 (%lu), 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();
+}
Propchange: trunk/rostests/apitests/dbghelp/pdb.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/rostests/apitests/dbghelp/resource.rc
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/dbghelp/resource…
==============================================================================
--- trunk/rostests/apitests/dbghelp/resource.rc (added)
+++ trunk/rostests/apitests/dbghelp/resource.rc [iso-8859-1] Fri Feb 17 16:15:49 2017
@@ -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
Propchange: trunk/rostests/apitests/dbghelp/resource.rc
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/rostests/apitests/dbghelp/rsym.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/dbghelp/rsym.c?r…
==============================================================================
--- trunk/rostests/apitests/dbghelp/rsym.c (added)
+++ trunk/rostests/apitests/dbghelp/rsym.c [iso-8859-1] Fri Feb 17 16:15:49 2017
@@ -0,0 +1,369 @@
+/*
+ * 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 <ntstatus.h>
+#define WIN32_NO_STATUS
+#include <windows.h>
+#include <dbghelp.h>
+#include <cvconst.h> // SymTagXXX
+#include <stdio.h>
+
+#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)
+
+#define ok_ulonglong_(file, line, expression, result) \
+ do { \
+ ULONG64 _value = (expression); \
+ ULONG64 _result = (result); \
+ ok_(file, line)(_value == (result), "Wrong value for '%s', expected:
" #result " (%s), got: %s\n", \
+ #expression, wine_dbgstr_longlong(_result), wine_dbgstr_longlong(_value)); \
+ } while (0)
+
+#define ok_hex_(file, line, expression, result) \
+ do { \
+ int _value = (expression); \
+ ok_(file, line)(_value == (result), "Wrong value for '%s', expected:
" #result " (0x%x), got: 0x%x\n", \
+ #expression, (int)(result), _value); \
+ } while (0)
+
+#define ok_str_(file, line, x, y) \
+ ok_(file, line)(strcmp(x, y) == 0, "Wrong string. Expected '%s', got
'%s'\n", y, x)
+
+
+// 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());
+}
+
+static BOOL supports_rsym(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 == SymDia &&
+ ModuleInfo.CVSig == ('R' | ('S' << 8) | ('Y'
<< 16) | ('M' << 24));
+}
+
+#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();
+
+ if (supports_rsym(hProc, BaseAddress))
+ {
+ 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, SYMFLAG_FUNCTION);
+ ok_ulonglong(pSymbol->Address, BaseAddress + 0x1000);
+ 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, SYMFLAG_FUNCTION);
+ ok_ulonglong(pSymbol->Address, BaseAddress + 0x103F);
+ 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, SYMFLAG_FUNCTION);
+ ok_ulonglong(pSymbol->Address, BaseAddress + 0x100C);
+ ok_hex(pSymbol->Tag, SymTagFunction);
+ ok_str(pSymbol->Name, "FfsFormat");
+ }
+ else
+ {
+ skip("dbghelp.dll cannot parse rsym\n");
+ }
+
+ 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();
+
+ if (supports_rsym(hProc, BaseAddress))
+ {
+ 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);
+ /* Our dbghelp.dll does not recognize this yet */
+ todo_if(!Ret)
+ {
+ ok_int(Ret, TRUE);
+ ok_ulonglong(Displacement, 0xffffffffffffffff);
+ ok_ulonglong(pSymbol->ModBase, BaseAddress);
+ ok_hex(pSymbol->Flags, SYMFLAG_FUNCTION);
+ 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, SYMFLAG_FUNCTION);
+ 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, 0x9);
+ ok_ulonglong(pSymbol->ModBase, BaseAddress);
+ ok_hex(pSymbol->Flags, SYMFLAG_FUNCTION);
+ 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, SYMFLAG_FUNCTION);
+ 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, SYMFLAG_EXPORT);
+ ok_ulonglong(pSymbol->Address, BaseAddress + 0x4000);
+ ok_hex(pSymbol->Tag, SymTagPublicSymbol);
+ ok_str(pSymbol->Name, "_head_dll_ntdll_libntdll_a");
+ }
+ else
+ {
+ skip("dbghelp.dll cannot parse rsym\n");
+ }
+
+ 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;
+ int Line;
+} test_data[] = {
+
+ /* TODO: Order is based on magic, should find entries based on name, and mark as
'seen' */
+ { 0x107c, 0, SymTagPublicSymbol, "__CTOR_LIST__", __LINE__ },
+ { 0x2074, 0, SymTagPublicSymbol, "__RUNTIME_PSEUDO_RELOC_LIST_END__",
__LINE__ },
+ { 0x1000, 12, SymTagPublicSymbol, "EntryPoint", __LINE__ },
+ { 0x100c, 51, SymTagFunction, "FfsFormat", __LINE__ },
+ { 0x4030, 0, SymTagPublicSymbol, "_imp__DbgPrint", __LINE__ },
+ { 0x1084, 0, SymTagPublicSymbol, "__DTOR_LIST__", __LINE__ },
+ { 0x103f, 53, SymTagFunction, "FfsChkdsk", __LINE__ },
+ { 0x2074, 0, SymTagPublicSymbol, "_rt_psrelocs_end", __LINE__ },
+ { 0x103f, 53, SymTagPublicSymbol, "ChkdskEx", __LINE__ },
+ { 0x4048, 0, SymTagPublicSymbol, "_dll_ntdll_libntdll_a_iname", __LINE__
},
+
+
+
+ { 0x2074, 0, SymTagPublicSymbol, "_rt_psrelocs_start", __LINE__ },
+ { 0x1000, 12, SymTagFunction, "DllMain", __LINE__ },
+ { 0x100c, 0, SymTagPublicSymbol, "FormatEx", __LINE__ },
+ { 0x1074, 0, SymTagPublicSymbol, "DbgPrint", __LINE__ },
+ { 0x68900000, 0, SymTagPublicSymbol, "__ImageBase", __LINE__ },
+ { 0x68902074, 0, SymTagPublicSymbol, "__RUNTIME_PSEUDO_RELOC_LIST__",
__LINE__ },
+ { 0x4000, 0, SymTagPublicSymbol, "_head_dll_ntdll_libntdll_a", __LINE__ },
+};
+
+BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID UserContext)
+{
+ test_context* ctx = UserContext;
+
+ if (ctx->Index < ARRAYSIZE(test_data))
+ {
+ ok_ulonglong_(__FILE__, test_data[ctx->Index].Line, pSymInfo->ModBase,
ctx->BaseAddress);
+ if (test_data[ctx->Index].AddressOffset > 0x100000)
+ ok_ulonglong_(__FILE__, test_data[ctx->Index].Line, pSymInfo->Address,
test_data[ctx->Index].AddressOffset);
+ else
+ ok_ulonglong_(__FILE__, test_data[ctx->Index].Line, pSymInfo->Address,
ctx->BaseAddress + test_data[ctx->Index].AddressOffset);
+ ok_hex_(__FILE__, test_data[ctx->Index].Line, pSymInfo->Tag,
test_data[ctx->Index].Tag);
+ ok_str_(__FILE__, test_data[ctx->Index].Line, pSymInfo->Name,
test_data[ctx->Index].Name);
+
+ ctx->Index++;
+ }
+ else
+ {
+ ok(0, "Out of bounds (%lu), 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();
+
+ if (supports_rsym(hProc, ctx.BaseAddress))
+ {
+ ok_ulonglong(ctx.BaseAddress, 0x600000);
+ ok_hex(dwErr, ERROR_SUCCESS);
+
+ Ret = SymEnumSymbols(hProc, ctx.BaseAddress, NULL, EnumSymProc, &ctx);
+ ok_int(Ret, TRUE);
+ ok_int(ctx.Index, ARRAYSIZE(test_data));
+ }
+ else
+ {
+ skip("dbghelp.dll cannot parse rsym\n");
+ }
+
+ 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();
+}
Propchange: trunk/rostests/apitests/dbghelp/rsym.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/dbghelp/testdata…
==============================================================================
Binary file - no diff available.
Propchange: trunk/rostests/apitests/dbghelp/testdata/gcc_uffs.dll.compr
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: trunk/rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/dbghelp/testdata…
==============================================================================
Binary file - no diff available.
Propchange: trunk/rostests/apitests/dbghelp/testdata/msvc_uffs.dll.compr
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: trunk/rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/dbghelp/testdata…
==============================================================================
Binary file - no diff available.
Propchange: trunk/rostests/apitests/dbghelp/testdata/msvc_uffs.pdb.compr
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: trunk/rostests/apitests/dbghelp/testlist.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/apitests/dbghelp/testlist…
==============================================================================
--- trunk/rostests/apitests/dbghelp/testlist.c (added)
+++ trunk/rostests/apitests/dbghelp/testlist.c [iso-8859-1] Fri Feb 17 16:15:49 2017
@@ -0,0 +1,13 @@
+
+#define STANDALONE
+#include <wine/test.h>
+
+extern void func_pdb(void);
+extern void func_rsym(void);
+
+const struct test winetest_testlist[] =
+{
+ { "pdb", func_pdb },
+ { "rsym", func_rsym },
+ { 0, 0 }
+};
Propchange: trunk/rostests/apitests/dbghelp/testlist.c
------------------------------------------------------------------------------
svn:eol-style = native