705 lines
13 KiB
C
705 lines
13 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1993 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
windbgrm.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This file implements the WinDbg remote debugger that doesn't use any
|
||
|
USER32.DLL or csrss functionality one initialized.
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Wesley Witt (wesw) 1-Nov-1993
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
User Mode
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#include "defs.h"
|
||
|
#include "mm.h"
|
||
|
#include "ll.h"
|
||
|
#include "od.h"
|
||
|
#include "emdm.h"
|
||
|
#include "tl.h"
|
||
|
#include "dbgver.h"
|
||
|
#include "resource.h"
|
||
|
#include "windbgrm.h"
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// globals
|
||
|
//
|
||
|
HANDLE hEventService;
|
||
|
HANDLE hEventLoadTl;
|
||
|
HANDLE hConnectThread;
|
||
|
BOOL fConnected;
|
||
|
BOOL fStartup;
|
||
|
BOOL fDebugger;
|
||
|
BOOL fGuiMode = TRUE;
|
||
|
DWORD dwRequest;
|
||
|
HPID hpidSvc;
|
||
|
HANDLE hout;
|
||
|
BOOL fGonOnDisconnect;
|
||
|
CHAR szTlName[256];
|
||
|
TLFUNC TLFunc;
|
||
|
HANDLE hTransportDll;
|
||
|
DBG_ACTIVE_STRUCT das;
|
||
|
DWORD nextHpid;
|
||
|
CHAR szCmdLine[512];
|
||
|
CHAR ClientId[MAX_PATH];
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// prototypes
|
||
|
//
|
||
|
DWORD
|
||
|
ConnectThread(
|
||
|
LPVOID lpv
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
GetCommandLineArgs(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
LoadTransport(
|
||
|
LPTRANSPORT_LAYER lpTl
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
UnLoadTransport(
|
||
|
LPTRANSPORT_LAYER lpTl
|
||
|
);
|
||
|
|
||
|
XOSD
|
||
|
TLCallbackFunc(
|
||
|
TLCB tlcb,
|
||
|
HPID hpid,
|
||
|
HTID htid,
|
||
|
UINT wParam,
|
||
|
LONG lParam
|
||
|
);
|
||
|
|
||
|
void
|
||
|
DebugPrint(
|
||
|
char * szFormat,
|
||
|
...
|
||
|
);
|
||
|
|
||
|
HANDLE
|
||
|
StartupDebugger(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
ConnectDebugger(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
DisConnectDebugger(
|
||
|
HPID hpid
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
AttachProcess(
|
||
|
HPID hpid,
|
||
|
DBG_ACTIVE_STRUCT *das
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
ProgramLoad(
|
||
|
HPID hpid,
|
||
|
LPSTR lpProgName
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
InitApplication(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
BOOLEAN
|
||
|
DebuggerStateChanged(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
VOID _cdecl
|
||
|
main(
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This is the entry point for WINDBGRM
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
#define append(s,n) p=p+sprintf(p,s,n)
|
||
|
HANDLE hDebugger;
|
||
|
CHAR buf[256];
|
||
|
LPSTR p;
|
||
|
LPTRANSPORT_LAYER lpTl;
|
||
|
|
||
|
|
||
|
|
||
|
// DEBUG_OUT( "WinDbgRm initializing\n" );
|
||
|
|
||
|
GetCommandLineArgs();
|
||
|
|
||
|
if (fGuiMode) {
|
||
|
InitApplication();
|
||
|
}
|
||
|
|
||
|
SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS );
|
||
|
|
||
|
hEventService = CreateEvent( NULL, TRUE, FALSE, NULL );
|
||
|
hEventLoadTl = CreateEvent( NULL, TRUE, FALSE, NULL );
|
||
|
|
||
|
if (fDebugger) {
|
||
|
ConnectDebugger();
|
||
|
if (szCmdLine[0]) {
|
||
|
nextHpid++;
|
||
|
ProgramLoad( (HPID)nextHpid, szCmdLine );
|
||
|
}
|
||
|
if (das.dwProcessId) {
|
||
|
nextHpid++;
|
||
|
AttachProcess( (HPID)nextHpid, &das );
|
||
|
}
|
||
|
DisConnectDebugger( (HPID) nextHpid );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
while( TRUE ) {
|
||
|
//
|
||
|
// get the default transport layer
|
||
|
//
|
||
|
lpTl = RegGetDefaultTransportLayer( szTlName );
|
||
|
if (!lpTl) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (!szTlName[0]) {
|
||
|
strcpy( szTlName, lpTl->szShortName );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// load the TL and DM
|
||
|
//
|
||
|
if (!LoadTransport( lpTl )) {
|
||
|
if (fGuiMode) {
|
||
|
WaitForSingleObject( hEventLoadTl, INFINITE );
|
||
|
ResetEvent( hEventLoadTl );
|
||
|
continue;
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Initialize the Transport with init string and create the transports
|
||
|
//
|
||
|
sprintf( buf, "%s %s ", DM_SIDE_L_INIT_SWITCH, lpTl->szParam );
|
||
|
|
||
|
//
|
||
|
// add the kernel debugger options
|
||
|
//
|
||
|
if (lpTl->KdParams.fEnable) {
|
||
|
p = &buf[strlen(buf)];
|
||
|
append( "baudrate=%d ", lpTl->KdParams.dwBaudRate );
|
||
|
append( "port=%d ", lpTl->KdParams.dwPort );
|
||
|
append( "cache=%d ", lpTl->KdParams.dwCache );
|
||
|
append( "verbose=%d ", lpTl->KdParams.fVerbose );
|
||
|
append( "initialbp=%d ", lpTl->KdParams.fInitialBp );
|
||
|
append( "defer=%d ", lpTl->KdParams.fDefer );
|
||
|
append( "usemodem=%d ", lpTl->KdParams.fUseModem );
|
||
|
append( "goexit=%d ", lpTl->KdParams.fGoExit );
|
||
|
append( "symbolpath=%s ", "." );
|
||
|
}
|
||
|
|
||
|
fConnected = FALSE;
|
||
|
if (TLFunc( tlfInit, hpidNull, TRUE, (LONG)buf ) != xosdNone) {
|
||
|
//
|
||
|
// we couldn't create the necessary transport objects
|
||
|
//
|
||
|
if (fGuiMode) {
|
||
|
UnLoadTransport( lpTl );
|
||
|
WaitForSingleObject( hEventLoadTl, INFINITE );
|
||
|
ResetEvent( hEventLoadTl );
|
||
|
continue;
|
||
|
}
|
||
|
return;
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fStartup) {
|
||
|
hDebugger = StartupDebugger();
|
||
|
if (!hDebugger) {
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
while ( TRUE ) {
|
||
|
if (TLFunc(tlfConnect, hpidNull, sizeof(ClientId), ClientId) == xosdNone) {
|
||
|
|
||
|
fConnected = TRUE;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
Sleep( 2000 );
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
XOSD
|
||
|
TLCallbackFunc(
|
||
|
TLCB tlcb,
|
||
|
HPID hpid,
|
||
|
HTID htid,
|
||
|
UINT wParam,
|
||
|
LONG lParam
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Provides a callback function for the TL. Currently
|
||
|
this callback is only to signal a disconnect.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
if ((tlcb != tlcbDisconnect) || (!TLFunc) || (!fConnected)) {
|
||
|
return xosdNone;
|
||
|
}
|
||
|
|
||
|
// DebugPrint("windbgrm disconnecting...\n");
|
||
|
|
||
|
fConnected = FALSE;
|
||
|
hpidSvc = hpid;
|
||
|
htidBpt = htid;
|
||
|
fGonOnDisconnect = wParam;
|
||
|
SetEvent( hEventService );
|
||
|
|
||
|
return xosdNone;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
LoadTransport(
|
||
|
LPTRANSPORT_LAYER lpTl
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Loads the named pipes transport layer and does the necessary
|
||
|
initialization of the TL.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
extern AVS Avs;
|
||
|
DBGVERSIONPROC pVerProc;
|
||
|
LPAVS pavs;
|
||
|
CHAR szDmName[16];
|
||
|
|
||
|
|
||
|
if ((hTransportDll = LoadLibrary(lpTl->szDllName)) == NULL) {
|
||
|
goto LoadTransportError;
|
||
|
}
|
||
|
|
||
|
pVerProc = (DBGVERSIONPROC)GetProcAddress(hTransportDll, DBGVERSIONPROCNAME);
|
||
|
if (!pVerProc) {
|
||
|
goto LoadTransportError;
|
||
|
}
|
||
|
|
||
|
pavs = (*pVerProc)();
|
||
|
|
||
|
if (pavs->rgchType[0] != 'T' || pavs->rgchType[1] != 'L') {
|
||
|
goto LoadTransportError;
|
||
|
}
|
||
|
|
||
|
if (Avs.rlvt != pavs->rlvt) {
|
||
|
goto LoadTransportError;
|
||
|
}
|
||
|
|
||
|
if (Avs.iRmj != pavs->iRmj) {
|
||
|
goto LoadTransportError;
|
||
|
}
|
||
|
|
||
|
if ((TLFunc = (TLFUNC)GetProcAddress(hTransportDll, "TLFunc")) == NULL) {
|
||
|
goto LoadTransportError;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Ask the TL to load the DM.
|
||
|
//
|
||
|
if (lpTl->KdParams.fEnable) {
|
||
|
switch (lpTl->KdParams.dwPlatform) {
|
||
|
case 0:
|
||
|
strcpy( szDmName, "DMKDX86.DLL " );
|
||
|
break;
|
||
|
|
||
|
case 1:
|
||
|
strcpy( szDmName, "DMKDMIP.DLL " );
|
||
|
break;
|
||
|
|
||
|
case 2:
|
||
|
strcpy( szDmName, "DMKDALP.DLL " );
|
||
|
break;
|
||
|
}
|
||
|
} else {
|
||
|
strcpy( szDmName, "DM.DLL " );
|
||
|
}
|
||
|
|
||
|
if (TLFunc(tlfLoadDM, hpidNull, wNull, (LONG)szDmName) != xosdNone) {
|
||
|
goto LoadTransportError;
|
||
|
}
|
||
|
|
||
|
if (TLFunc(tlfRegisterDBF, hpidNull, wNull, 0) != xosdNone) {
|
||
|
goto LoadTransportError;
|
||
|
}
|
||
|
|
||
|
if (TLFunc(tlfSetErrorCB, hpidNull, wNull, (LONG) &TLCallbackFunc) != xosdNone) {
|
||
|
goto LoadTransportError;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Initialize the Timer and Physical Layers of the Transport.
|
||
|
// Callback address should be NULL for now. The TL has already
|
||
|
// initialized this.
|
||
|
//
|
||
|
if (TLFunc(tlfGlobalInit, hpidNull, wNull, 0) != xosdNone) {
|
||
|
goto LoadTransportError;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
|
||
|
LoadTransportError:
|
||
|
if (hTransportDll) {
|
||
|
FreeLibrary( hTransportDll );
|
||
|
hTransportDll = NULL;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
UnLoadTransport(
|
||
|
LPTRANSPORT_LAYER lpTl
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Unloads the transport layer.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
FreeLibrary( hTransportDll );
|
||
|
hTransportDll = NULL;
|
||
|
free( lpTl );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
HANDLE
|
||
|
StartupDebugger(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
CHAR szCommandLine[MAX_PATH];
|
||
|
STARTUPINFO si;
|
||
|
PROCESS_INFORMATION pi;
|
||
|
|
||
|
|
||
|
sprintf( szCommandLine, "windbgrm -q -d -n %s ", szTlName );
|
||
|
if (das.dwProcessId) {
|
||
|
sprintf( &szCommandLine[strlen(szCommandLine)], "-p %d ", das.dwProcessId );
|
||
|
}
|
||
|
if (das.hEventGo) {
|
||
|
sprintf( &szCommandLine[strlen(szCommandLine)], "-e %d ", das.hEventGo );
|
||
|
}
|
||
|
if (szCmdLine[0]) {
|
||
|
strcat( szCommandLine, szCmdLine );
|
||
|
}
|
||
|
|
||
|
GetStartupInfo( &si );
|
||
|
si.hStdOutput = hout;
|
||
|
|
||
|
if (!CreateProcess( NULL, szCommandLine, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi )) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return pi.hProcess;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
GetCommandLineArgs(
|
||
|
VOID
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Simple command line parser.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
char *lpstrCmd = GetCommandLine();
|
||
|
UCHAR ch;
|
||
|
DWORD i = 0;
|
||
|
|
||
|
// skip over program name
|
||
|
do {
|
||
|
ch = *lpstrCmd++;
|
||
|
}
|
||
|
while (ch != ' ' && ch != '\t' && ch != '\0');
|
||
|
|
||
|
// skip over any following white space
|
||
|
while (ch == ' ' || ch == '\t') {
|
||
|
ch = *lpstrCmd++;
|
||
|
}
|
||
|
|
||
|
// process each switch character '-' as encountered
|
||
|
|
||
|
while (ch == '-' || ch == '/') {
|
||
|
ch = tolower(*lpstrCmd++);
|
||
|
// process multiple switch characters as needed
|
||
|
do {
|
||
|
switch (ch) {
|
||
|
case 'n':
|
||
|
do {
|
||
|
ch = *lpstrCmd++;
|
||
|
} while (ch == ' ' || ch == '\t');
|
||
|
i=0;
|
||
|
while (ch != ' ' && ch != '\0') {
|
||
|
szTlName[i++] = ch;
|
||
|
ch = *lpstrCmd++;
|
||
|
}
|
||
|
szTlName[i] = '\0';
|
||
|
break;
|
||
|
|
||
|
case '?':
|
||
|
//Usage();
|
||
|
ch = *lpstrCmd++;
|
||
|
break;
|
||
|
|
||
|
case 'p':
|
||
|
// skip whitespace
|
||
|
do {
|
||
|
ch = *lpstrCmd++;
|
||
|
} while (ch == ' ' || ch == '\t');
|
||
|
|
||
|
if ( ch == '-' ) {
|
||
|
ch = *lpstrCmd++;
|
||
|
if ( ch == '1' ) {
|
||
|
das.dwProcessId = 0xffffffff;
|
||
|
ch = *lpstrCmd++;
|
||
|
}
|
||
|
} else {
|
||
|
i=0;
|
||
|
while (ch >= '0' && ch <= '9') {
|
||
|
i = i * 10 + ch - '0';
|
||
|
ch = *lpstrCmd++;
|
||
|
}
|
||
|
das.dwProcessId = i;
|
||
|
}
|
||
|
fStartup = TRUE;
|
||
|
break;
|
||
|
|
||
|
case 'e':
|
||
|
// skip whitespace
|
||
|
do {
|
||
|
ch = *lpstrCmd++;
|
||
|
} while (ch == ' ' || ch == '\t');
|
||
|
|
||
|
i=0;
|
||
|
while (ch >= '0' && ch <= '9') {
|
||
|
i = i * 10 + ch - '0';
|
||
|
ch = *lpstrCmd++;
|
||
|
}
|
||
|
das.hEventGo = (HANDLE) i;
|
||
|
break;
|
||
|
|
||
|
case 'q':
|
||
|
fDebugger = TRUE;
|
||
|
ch = *lpstrCmd++;
|
||
|
break;
|
||
|
|
||
|
case 'g':
|
||
|
ch = *lpstrCmd++;
|
||
|
break;
|
||
|
|
||
|
case 'd':
|
||
|
fGuiMode = FALSE;
|
||
|
ch = *lpstrCmd++;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return;
|
||
|
}
|
||
|
} while (ch != ' ' && ch != '\t' && ch != '\0');
|
||
|
|
||
|
while (ch == ' ' || ch == '\t') {
|
||
|
ch = *lpstrCmd++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// get the command line for a debuggee
|
||
|
//
|
||
|
|
||
|
while (ch == ' ' || ch == '\t') {
|
||
|
ch = *lpstrCmd++;
|
||
|
}
|
||
|
i=0;
|
||
|
while (ch) {
|
||
|
szCmdLine[i++] = ch;
|
||
|
ch = *lpstrCmd++;
|
||
|
}
|
||
|
szCmdLine[i] = '\0';
|
||
|
if (i) {
|
||
|
fStartup = TRUE;
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
DebugPrint(
|
||
|
char * szFormat,
|
||
|
...
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Provides a printf style function for doing outputdebugstring.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
va_list marker;
|
||
|
int n;
|
||
|
char rgchDebug[4096];
|
||
|
|
||
|
va_start( marker, szFormat );
|
||
|
n = _vsnprintf(rgchDebug, sizeof(rgchDebug), szFormat, marker );
|
||
|
va_end( marker);
|
||
|
|
||
|
if (n == -1) {
|
||
|
rgchDebug[sizeof(rgchDebug)-1] = '\0';
|
||
|
}
|
||
|
|
||
|
OutputDebugString( rgchDebug );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
ShowAssert(
|
||
|
LPSTR condition,
|
||
|
UINT line,
|
||
|
LPSTR file
|
||
|
)
|
||
|
{
|
||
|
char text[4096];
|
||
|
int id;
|
||
|
|
||
|
sprintf(text, "Assertion failed - Line:%u, File:%Fs, Condition:%Fs", line, file, condition);
|
||
|
DebugPrint( "%s\r\n", text );
|
||
|
id = MessageBox( NULL, text, "WinDbgRm", MB_YESNO | MB_ICONHAND | MB_TASKMODAL | MB_SETFOREGROUND );
|
||
|
if (id != IDYES) {
|
||
|
DebugBreak();
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|