1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Support functions for dbghelp api test 5 * COPYRIGHT: Copyright 2017-2019 Mark Jansen (mark.jansen@reactos.org) 6 */ 7 8 #include <windows.h> 9 #include <stdio.h> 10 #include <zlib.h> 11 12 #include "wine/test.h" 13 14 extern IMAGE_DOS_HEADER __ImageBase; 15 16 static char szTempPath[MAX_PATH]; 17 18 static const char* tmpdir() 19 { 20 if (szTempPath[0] == '\0') 21 { 22 GetTempPathA(MAX_PATH, szTempPath); 23 lstrcatA(szTempPath, "dbghelp_tst"); 24 } 25 return szTempPath; 26 } 27 28 static int extract_one(const char* filename, const char* resid) 29 { 30 HMODULE mod = (HMODULE)&__ImageBase; 31 HGLOBAL glob; 32 PVOID data, decompressed; 33 uLongf size, dstsize; 34 DWORD gccSize, dwErr; 35 HANDLE file; 36 int ret; 37 HRSRC rsrc = FindResourceA(mod, resid, MAKEINTRESOURCEA(RT_RCDATA)); 38 ok(rsrc != 0, "Failed finding '%s' res\n", resid); 39 if (!rsrc) 40 return 0; 41 42 size = SizeofResource(mod, rsrc); 43 glob = LoadResource(mod, rsrc); 44 ok(glob != NULL, "Failed loading '%s' res\n", resid); 45 if (!glob) 46 return 0; 47 48 data = LockResource(glob); 49 50 dstsize = 1024 * 256; 51 decompressed = malloc(dstsize); 52 53 if (uncompress(decompressed, &dstsize, data, size) != Z_OK) 54 { 55 ok(0, "uncompress failed for %s\n", resid); 56 free(decompressed); 57 return 0; 58 } 59 60 61 file = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 62 gccSize = size; 63 ret = WriteFile(file, decompressed, dstsize, &gccSize, NULL); 64 dwErr = GetLastError(); 65 CloseHandle(file); 66 free(decompressed); 67 ok(ret, "WriteFile failed (%d)\n", dwErr); 68 return ret && dstsize == gccSize; 69 } 70 71 72 int extract_msvc_dll(char szFile[MAX_PATH], char szPath[MAX_PATH]) 73 { 74 const char* dir = tmpdir(); 75 BOOL ret = CreateDirectoryA(dir, NULL); 76 ok(ret, "CreateDirectoryA failed(%d)\n", GetLastError()); 77 78 sprintf(szFile, "%s\\uffs.pdb", dir); 79 if (!extract_one(szFile, "msvc_uffs.pdb")) 80 return 0; 81 82 sprintf(szFile, "%s\\uffs.dll", dir); 83 if (!extract_one(szFile, "msvc_uffs.dll")) 84 return 0; 85 86 strcpy(szPath, dir); 87 return 1; 88 } 89 90 void cleanup_msvc_dll() 91 { 92 char szFile[MAX_PATH]; 93 BOOL ret; 94 const char* dir = tmpdir(); 95 96 sprintf(szFile, "%s\\uffs.pdb", dir); 97 ret = DeleteFileA(szFile); 98 ok(ret, "DeleteFileA failed(%d)\n", GetLastError()); 99 100 sprintf(szFile, "%s\\uffs.dll", dir); 101 ret = DeleteFileA(szFile); 102 ok(ret, "DeleteFileA failed(%d)\n", GetLastError()); 103 ret = RemoveDirectoryA(dir); 104 ok(ret, "RemoveDirectoryA failed(%d)\n", GetLastError()); 105 } 106 107 int extract_gcc_dll(char szFile[MAX_PATH]) 108 { 109 const char* dir = tmpdir(); 110 BOOL ret = CreateDirectoryA(dir, NULL); 111 ok(ret, "CreateDirectoryA failed(%d)\n", GetLastError()); 112 113 sprintf(szFile, "%s\\uffs.dll", dir); 114 if (!extract_one(szFile, "gcc_uffs.dll")) 115 return 0; 116 117 return 1; 118 } 119 120 void cleanup_gcc_dll() 121 { 122 char szFile[MAX_PATH]; 123 BOOL ret; 124 const char* dir = tmpdir(); 125 126 sprintf(szFile, "%s\\uffs.dll", dir); 127 ret = DeleteFileA(szFile); 128 ok(ret, "DeleteFileA failed(%d)\n", GetLastError()); 129 ret = RemoveDirectoryA(dir); 130 ok(ret, "RemoveDirectoryA failed(%d)\n", GetLastError()); 131 } 132 133 134 #if 0 135 static int compress_one(const char* src, const char* dest) 136 { 137 DWORD size, size2, res; 138 FILE* file = fopen(src, "rb"); 139 fseek(file, 0, SEEK_END); 140 size = ftell(file); 141 fseek(file, 0, SEEK_SET); 142 143 Bytef* buffer, *buffer2; 144 DWORD dwErr = GetLastError(); 145 146 buffer = malloc(size); 147 res = fread(buffer, 1, size, file); 148 149 fclose(file); 150 151 if (res != size) 152 { 153 printf("Could not read file: 0x%x\n", dwErr); 154 free(buffer); 155 CloseHandle(file); 156 return 0; 157 } 158 size2 = size *2; 159 buffer2 = malloc(size2); 160 res = compress(buffer2, &size2, buffer, size); 161 162 free(buffer); 163 164 if (Z_OK != res) 165 { 166 free(buffer2); 167 return 0; 168 } 169 170 file = fopen(dest, "wb"); 171 res = fwrite(buffer2, 1, size2, file); 172 fclose(file); 173 174 free(buffer2); 175 176 return size2 == res; 177 } 178 179 void create_compressed_files() 180 { 181 SetCurrentDirectoryA("R:/src/trunk/reactos/modules/rostests/apitests/dbghelp"); 182 if (!compress_one("testdata/msvc_uffs.dll", "testdata/msvc_uffs.dll.compr")) 183 printf("msvc_uffs.dll failed\n"); 184 if (!compress_one("testdata/msvc_uffs.pdb", "testdata/msvc_uffs.pdb.compr")) 185 printf("msvc_uffs.pdb failed\n"); 186 if (!compress_one("testdata/gcc_uffs.dll", "testdata/gcc_uffs.dll.compr")) 187 printf("gcc_uffs.dll failed\n"); 188 } 189 #endif 190 191 #if 0 192 typedef struct _SYMBOLFILE_HEADER { 193 ULONG SymbolsOffset; 194 ULONG SymbolsLength; 195 ULONG StringsOffset; 196 ULONG StringsLength; 197 } SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER; 198 199 typedef struct _ROSSYM_ENTRY { 200 ULONG Address; 201 ULONG FunctionOffset; 202 ULONG FileOffset; 203 ULONG SourceLine; 204 } ROSSYM_ENTRY, *PROSSYM_ENTRY; 205 206 207 static int is_metadata(const char* name) 208 { 209 size_t len = name ? strlen(name) : 0; 210 return len > 3 && name[0] == '_' && name[1] != '_' && name[len-1] == '_' && name[len-2] == '_'; 211 }; 212 213 static void dump_rsym_internal(void* data) 214 { 215 PSYMBOLFILE_HEADER RosSymHeader = (PSYMBOLFILE_HEADER)data; 216 PROSSYM_ENTRY Entries = (PROSSYM_ENTRY)((char *)data + RosSymHeader->SymbolsOffset); 217 size_t symbols = RosSymHeader->SymbolsLength / sizeof(ROSSYM_ENTRY); 218 size_t i; 219 char *Strings = (char *)data + RosSymHeader->StringsOffset; 220 221 for (i = 0; i < symbols; i++) 222 { 223 PROSSYM_ENTRY Entry = Entries + i; 224 if (!Entry->FileOffset) 225 { 226 if (Entry->SourceLine) 227 printf("ERR: SOURCELINE (%D) ", Entry->SourceLine); 228 if (is_metadata(Strings + Entry->FunctionOffset)) 229 printf("metadata: %s: 0x%x\n", Strings + Entry->FunctionOffset, Entry->Address); 230 else 231 printf("0x%x: %s\n", Entry->Address, Strings + Entry->FunctionOffset); 232 } 233 else 234 { 235 printf("0x%x: %s (%s:%u)\n", Entry->Address, 236 Strings + Entry->FunctionOffset, 237 Strings + Entry->FileOffset, 238 Entry->SourceLine); 239 } 240 } 241 242 } 243 244 void dump_rsym(const char* filename) 245 { 246 char* data; 247 long size, res; 248 PIMAGE_FILE_HEADER PEFileHeader; 249 PIMAGE_OPTIONAL_HEADER PEOptHeader; 250 PIMAGE_SECTION_HEADER PESectionHeaders; 251 WORD i; 252 253 FILE* f = fopen(filename, "rb"); 254 255 fseek(f, 0, SEEK_END); 256 size = ftell(f); 257 fseek(f, 0, SEEK_SET); 258 259 data = malloc(size); 260 res = fread(data, 1, size, f); 261 fclose(f); 262 263 PEFileHeader = (PIMAGE_FILE_HEADER)((char *)data + ((PIMAGE_DOS_HEADER)data)->e_lfanew + sizeof(ULONG)); 264 PEOptHeader = (PIMAGE_OPTIONAL_HEADER)(PEFileHeader + 1); 265 PESectionHeaders = (PIMAGE_SECTION_HEADER)((char *)PEOptHeader + PEFileHeader->SizeOfOptionalHeader); 266 267 for (i = 0; i < PEFileHeader->NumberOfSections; i++) 268 { 269 if (!strcmp((char *)PESectionHeaders[i].Name, ".rossym")) 270 { 271 dump_rsym_internal(data + PESectionHeaders[i].PointerToRawData); 272 break; 273 } 274 } 275 free(data); 276 } 277 278 #endif 279