You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
368 lines
8.6 KiB
368 lines
8.6 KiB
#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;
|
|
}
|