1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: GPLv2+ - See COPYING in the top level directory 4 * PURPOSE: Support functions for dbghelp api test 5 * PROGRAMMER: Mark Jansen 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_exe(char szFile[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 return 1; 87 } 88 89 void cleanup_msvc_exe() 90 { 91 char szFile[MAX_PATH]; 92 BOOL ret; 93 const char* dir = tmpdir(); 94 95 sprintf(szFile, "%s\\uffs.pdb", dir); 96 ret = DeleteFileA(szFile); 97 ok(ret, "DeleteFileA failed(%d)\n", GetLastError()); 98 99 sprintf(szFile, "%s\\uffs.dll", dir); 100 ret = DeleteFileA(szFile); 101 ok(ret, "DeleteFileA failed(%d)\n", GetLastError()); 102 ret = RemoveDirectoryA(dir); 103 ok(ret, "RemoveDirectoryA failed(%d)\n", GetLastError()); 104 } 105 106 int extract_gcc_exe(char szFile[MAX_PATH]) 107 { 108 const char* dir = tmpdir(); 109 BOOL ret = CreateDirectoryA(dir, NULL); 110 ok(ret, "CreateDirectoryA failed(%d)\n", GetLastError()); 111 112 sprintf(szFile, "%s\\uffs.dll", dir); 113 if (!extract_one(szFile, "gcc_uffs.dll")) 114 return 0; 115 116 return 1; 117 } 118 119 void cleanup_gcc_exe() 120 { 121 char szFile[MAX_PATH]; 122 BOOL ret; 123 const char* dir = tmpdir(); 124 125 sprintf(szFile, "%s\\uffs.dll", dir); 126 ret = DeleteFileA(szFile); 127 ok(ret, "DeleteFileA failed(%d)\n", GetLastError()); 128 ret = RemoveDirectoryA(dir); 129 ok(ret, "RemoveDirectoryA failed(%d)\n", GetLastError()); 130 } 131 132 133 #if 0 134 static int compress_one(const char* src, const char* dest) 135 { 136 DWORD size, size2, res; 137 FILE* file = fopen(src, "rb"); 138 fseek(file, 0, SEEK_END); 139 size = ftell(file); 140 fseek(file, 0, SEEK_SET); 141 142 Bytef* buffer, *buffer2; 143 DWORD dwErr = GetLastError(); 144 145 buffer = malloc(size); 146 res = fread(buffer, 1, size, file); 147 148 fclose(file); 149 150 if (res != size) 151 { 152 printf("Could not read file: 0x%x\n", dwErr); 153 free(buffer); 154 CloseHandle(file); 155 return 0; 156 } 157 size2 = size *2; 158 buffer2 = malloc(size2); 159 res = compress(buffer2, &size2, buffer, size); 160 161 free(buffer); 162 163 if (Z_OK != res) 164 { 165 free(buffer2); 166 return 0; 167 } 168 169 file = fopen(dest, "wb"); 170 res = fwrite(buffer2, 1, size2, file); 171 fclose(file); 172 173 free(buffer2); 174 175 return size2 == res; 176 } 177 178 void create_compressed_files() 179 { 180 SetCurrentDirectoryA("R:/src/trunk/reactos/modules/rostests/apitests/dbghelp"); 181 if (!compress_one("testdata/msvc_uffs.dll", "testdata/msvc_uffs.dll.compr")) 182 printf("msvc_uffs.dll failed\n"); 183 if (!compress_one("testdata/msvc_uffs.pdb", "testdata/msvc_uffs.pdb.compr")) 184 printf("msvc_uffs.pdb failed\n"); 185 if (!compress_one("testdata/gcc_uffs.dll", "testdata/gcc_uffs.dll.compr")) 186 printf("gcc_uffs.dll failed\n"); 187 } 188 #endif 189 190 #if 0 191 typedef struct _SYMBOLFILE_HEADER { 192 ULONG SymbolsOffset; 193 ULONG SymbolsLength; 194 ULONG StringsOffset; 195 ULONG StringsLength; 196 } SYMBOLFILE_HEADER, *PSYMBOLFILE_HEADER; 197 198 typedef struct _ROSSYM_ENTRY { 199 ULONG Address; 200 ULONG FunctionOffset; 201 ULONG FileOffset; 202 ULONG SourceLine; 203 } ROSSYM_ENTRY, *PROSSYM_ENTRY; 204 205 206 static int is_metadata(const char* name) 207 { 208 size_t len = name ? strlen(name) : 0; 209 return len > 3 && name[0] == '_' && name[1] != '_' && name[len-1] == '_' && name[len-2] == '_'; 210 }; 211 212 static void dump_rsym_internal(void* data) 213 { 214 PSYMBOLFILE_HEADER RosSymHeader = (PSYMBOLFILE_HEADER)data; 215 PROSSYM_ENTRY Entries = (PROSSYM_ENTRY)((char *)data + RosSymHeader->SymbolsOffset); 216 size_t symbols = RosSymHeader->SymbolsLength / sizeof(ROSSYM_ENTRY); 217 size_t i; 218 char *Strings = (char *)data + RosSymHeader->StringsOffset; 219 220 for (i = 0; i < symbols; i++) 221 { 222 PROSSYM_ENTRY Entry = Entries + i; 223 if (!Entry->FileOffset) 224 { 225 if (Entry->SourceLine) 226 printf("ERR: SOURCELINE (%D) ", Entry->SourceLine); 227 if (is_metadata(Strings + Entry->FunctionOffset)) 228 printf("metadata: %s: 0x%x\n", Strings + Entry->FunctionOffset, Entry->Address); 229 else 230 printf("0x%x: %s\n", Entry->Address, Strings + Entry->FunctionOffset); 231 } 232 else 233 { 234 printf("0x%x: %s (%s:%u)\n", Entry->Address, 235 Strings + Entry->FunctionOffset, 236 Strings + Entry->FileOffset, 237 Entry->SourceLine); 238 } 239 } 240 241 } 242 243 void dump_rsym(const char* filename) 244 { 245 char* data; 246 long size, res; 247 PIMAGE_FILE_HEADER PEFileHeader; 248 PIMAGE_OPTIONAL_HEADER PEOptHeader; 249 PIMAGE_SECTION_HEADER PESectionHeaders; 250 WORD i; 251 252 FILE* f = fopen(filename, "rb"); 253 254 fseek(f, 0, SEEK_END); 255 size = ftell(f); 256 fseek(f, 0, SEEK_SET); 257 258 data = malloc(size); 259 res = fread(data, 1, size, f); 260 fclose(f); 261 262 PEFileHeader = (PIMAGE_FILE_HEADER)((char *)data + ((PIMAGE_DOS_HEADER)data)->e_lfanew + sizeof(ULONG)); 263 PEOptHeader = (PIMAGE_OPTIONAL_HEADER)(PEFileHeader + 1); 264 PESectionHeaders = (PIMAGE_SECTION_HEADER)((char *)PEOptHeader + PEFileHeader->SizeOfOptionalHeader); 265 266 for (i = 0; i < PEFileHeader->NumberOfSections; i++) 267 { 268 if (!strcmp((char *)PESectionHeaders[i].Name, ".rossym")) 269 { 270 dump_rsym_internal(data + PESectionHeaders[i].PointerToRawData); 271 break; 272 } 273 } 274 free(data); 275 } 276 277 #endif 278