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
tmpdir()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
extract_one(const char * filename,const char * resid)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
extract_msvc_dll(char szFile[MAX_PATH],char szPath[MAX_PATH])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
cleanup_msvc_dll()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
extract_gcc_dll(char szFile[MAX_PATH])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
cleanup_gcc_dll()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