|
|
#include "pch.h"
typedef enum { fncRead = 0, fncWrite, fncNone };
int parseargs(int argc, char **argv, char *pdb, char *input, char *stream, DWORD size); int getcontent(char *filename, char **content); int ProcessPDB6(int argc, char **argv, char **env);
#define fileexists(path) (GetFileAttributes(path) != 0xFFFFFFFF)
extern "C" int __cdecl main(int argc, char **argv, char **env) { BOOL rc; int fnc = fncNone; char pdbname[MAX_PATH]; char input[MAX_PATH]; char streamname[MAX_PATH]; PDB *pdb; EC ec; char errormsg[cbErrMax]; Stream* pstream; char *buf = NULL; long size; long cb; bool success = false;
fnc = parseargs(argc, argv, pdbname, input, streamname, MAX_PATH); if (fnc == fncNone) return success;
*errormsg = 0; rc = PDBOpen(pdbname, (fnc == fncRead) ? "r" : "w", 0, &ec, errormsg, &pdb); if (!rc) { if (ec == ERROR_BAD_FORMAT) return ProcessPDB6(argc, argv, env);
printf("error 0x%x opening %s\n", ec, pdbname); return success; }
rc = PDBOpenStream(pdb, streamname, &pstream); if (!rc) { printf( "Could not open stream %s in %s.\n", streamname, pdbname); goto cleanup; }
if (fnc == fncWrite) { size = getcontent(input, &buf); if (!size) goto cleanup;
rc = StreamReplace(pstream, (void *)buf, (DWORD)size); if ( !rc ) { printf( "StreamReplace failed for %s(%s).\n", pdbname, streamname); goto cleanup; }
rc = PDBCommit( pdb ); if ( !rc ) { printf( "PDBCommit failed for %s.\n", pdbname); goto cleanup; } success = true; } else if (fnc == fncRead) { size = StreamQueryCb(pstream); if (!size) goto cleanup;
buf = (char *)calloc(size + 1, sizeof(char)); if (!buf) goto cleanup;
cb = size; rc = StreamRead(pstream, 0, buf, &cb); if (!rc) goto cleanup; if (cb != size) goto cleanup; printf(buf); success = true; }
cleanup: if (buf) free(buf);
if (pdb) rc = PDBClose(pdb);
return success ? 0 : -1; }
bool parsesz(char *sz, char *file, DWORD size) { if (*(sz + 2) != ':') return false;
StringCchCopy(file, size, sz + 3); return (*file) ? true : false; return (GetFileAttributes(file) == 0xFFFFFFFF) ? false : true; }
int parseerror() { printf("pdbstr -r/w -p:PdbFileName -i:StreamFileName -s:StreamName\n"); return fncNone; }
int parseargs(int argc, char **argv, char *pdb, char *input, char *stream, DWORD size) { // all input strings must be the same size
int i; int rc; char *sz;
rc = fncNone; assert(pdb && input && stream); *pdb = *input = *stream = 0;
for (i = 0; i < argc; i++, argv++) { if (!i) continue;
sz = *argv; if (*sz == '-' || *sz == '/') { switch(*(sz + 1)) { case 'r': case 'R': rc = fncRead; break; case 'w': case 'W': rc = fncWrite; break; case 'p': case 'P': if (!parsesz(sz, pdb, size)) return parseerror(); break; case 'i': case 'I': if (!parsesz(sz, input, size)) return parseerror(); break; case 's': case 'S': if (!parsesz(sz, stream, size)) return parseerror(); break; default: return parseerror(); } } }
if (rc == fncNone) return parseerror(); if (!fileexists(pdb)) return parseerror(); if (!*stream) return parseerror(); if ((rc == fncWrite) && !fileexists(input)) return parseerror();
return rc; }
int getcontent(char *filename, char **buf) { HANDLE hptr; DWORD size; DWORD cb; LPSTR p; bool success = false;
hptr = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hptr == INVALID_HANDLE_VALUE) return 0;
// test validity of file pointer
size = GetFileSize(hptr, NULL); if (!size) goto cleanup;
// allocate space for file
*buf = (char *)calloc(size, sizeof(char)); if (!*buf) goto cleanup;
// read it in
if (!ReadFile(hptr, *buf, size, &cb, 0)) goto cleanup;
if (cb != size) goto cleanup;
success = true;
cleanup: // done
if (hptr) CloseHandle(hptr);
if (!success) { if (*buf) free(*buf); return 0; }
return size; }
// all this stuff handles PDB6 format
typedef BOOL (PDBCALL *PfnPDBOpenStream)(PDB* ppdb, const char* szStream, OUT Stream** ppstream); typedef BOOL (PDBCALL *PfnStreamReplace)(Stream* pstream, void* pvBuf, long cbBuf); typedef BOOL (PDBCALL *PfnPDBCommit)(PDB* ppdb); typedef BOOL (PDBCALL *PfnPDBClose)(PDB* ppdb);
PfnPDBOpen fnPDBOpen = NULL; PfnPDBOpenStream fnPDBOpenStream = NULL; PfnStreamReplace fnStreamReplace = NULL; PfnPDBCommit fnPDBCommit = NULL; PfnPDBClose fnPDBClose = NULL;
int ProcessPDB6(int argc, char **argv, char **env) { BOOL rc; int fnc = fncNone; char pdbname[MAX_PATH]; char input[MAX_PATH]; char streamname[MAX_PATH]; PDB *pdb; EC ec; char errormsg[cbErrMax]; Stream* pstream; char *buf = NULL; long size; long cb; bool success = false;
HINSTANCE hmspdb;
fnc = parseargs(argc, argv, pdbname, input, streamname, MAX_PATH); if (fnc == fncNone) return success;
hmspdb = LoadLibrary("mspdb60.dll"); if (!hmspdb) { printf("error 0x%x loading mspdb60.dll\n", GetLastError()); return success; } fnPDBOpen = (PfnPDBOpen)GetProcAddress(hmspdb, "PDBOpen"); fnPDBOpenStream = (PfnPDBOpenStream)GetProcAddress(hmspdb, "PDBOpenStream"); fnStreamReplace = (PfnStreamReplace)GetProcAddress(hmspdb, "StreamReplace"); fnPDBCommit = (PfnPDBCommit)GetProcAddress(hmspdb, "PDBCommit"); fnPDBClose = (PfnPDBClose)GetProcAddress(hmspdb, "PDBClose"); if (!fnPDBOpen || !fnPDBOpenStream || !fnStreamReplace || !fnPDBCommit || !fnPDBClose) { printf("error 0x%x searching for exports in mspdb60.dll\n", GetLastError()); return success; }
*errormsg = 0; rc = fnPDBOpen(pdbname, (fnc == fncRead) ? "r" : "w", 0, &ec, errormsg, &pdb); if (!rc) { printf("error 0x%x opening %s\n", ec, pdbname); return success; }
rc = fnPDBOpenStream(pdb, streamname, &pstream); if (!rc) { printf( "Could not open stream %s in %s.\n", streamname, pdbname); goto cleanup; }
if (fnc == fncWrite) { size = getcontent(input, &buf); if (!size) goto cleanup;
rc = fnStreamReplace(pstream, (void *)buf, (DWORD)size); if ( !rc ) { printf( "StreamReplace failed for %s(%s).\n", pdbname, streamname); goto cleanup; }
rc = fnPDBCommit( pdb ); if ( !rc ) { printf( "PDBCommit failed for %s.\n", pdbname); goto cleanup; } success = true; } else if (fnc == fncRead) { size = StreamQueryCb(pstream); if (!size) goto cleanup;
buf = (char *)calloc(size + 1, sizeof(char)); if (!buf) goto cleanup;
cb = size; rc = StreamRead(pstream, 0, buf, &cb); if (!rc) goto cleanup; if (cb != size) goto cleanup; printf(buf); success = true; }
cleanup: if (buf) free(buf);
if (pdb) rc = fnPDBClose(pdb);
return success ? 0 : -1; }
|