reactos/modules/rostests/apitests/dbghelp/data.c
Mark Jansen b8a1a612b2
[DBGHELP_APITEST] Add rsym+pdb tests on loaded modules
Also reorder some stuff to make the tests more alike
2019-08-15 15:21:55 +02:00

279 lines
7.1 KiB
C

/*
* PROJECT: ReactOS api tests
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Support functions for dbghelp api test
* COPYRIGHT: Copyright 2017-2019 Mark Jansen (mark.jansen@reactos.org)
*/
#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_dll(char szFile[MAX_PATH], char szPath[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;
strcpy(szPath, dir);
return 1;
}
void cleanup_msvc_dll()
{
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_dll(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_dll()
{
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