Leaked source code of windows server 2003
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.
 
 
 
 
 
 

476 lines
13 KiB

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <dbgeng.h>
#include "debug.h"
#include "output.h"
typedef HRESULT (CALLBACK* PDEBUG_EXTENSION_SET_CLIENT)(LPCSTR RemoteArgs);
#if DBG
CHAR szDefaultExtPath[] = "\\\\JasonHa\\DbgExts\\gdikdxd";
#else
CHAR szDefaultExtPath[] = "\\\\JasonHa\\DbgExts\\gdikdxr";
#endif
HMODULE ghGDIExt = NULL;
PDEBUG_CONTROL Control = NULL;
BOOL Continue = TRUE;
PCSTR gRemoteSpec = NULL;
PCSTR gMainExtPath = szDefaultExtPath;
HMODULE LoadExtension(PDEBUG_CLIENT Client, PCSTR ExtPath);
BOOL FreeExtension(PDEBUG_CLIENT, HMODULE hExt);
VOID ProcessCommands(PDEBUG_CLIENT Client, OutputMonitor *Monitor);
VOID SetOutputCmd(OutputMonitor *Monitor, const char *Args);
BOOL CtrlHandler(DWORD fdwCtrlType);
int __cdecl main(int argc, char** argv)
{
HRESULT hr;
BOOL CtrlHandlerSet;
PDEBUG_CLIENT Client = NULL;
OutputMonitor Monitor;
if (argc < 2)
{
printf("Missing remote specification.\n");
return 1;
}
if (argc > 3)
{
printf("Too many arguments.\n");
return 1;
}
gRemoteSpec = argv[1];
if ((hr = DebugConnect(gRemoteSpec, __uuidof(IDebugClient), (void **)&Client)) != S_OK ||
Client == NULL)
{
printf("Couldn't connect to client: %s, HRESULT: 0x%lx\n", argv[1], hr);
return 2;
}
if ((hr = Client->QueryInterface(__uuidof(IDebugControl), (void **)&Control)) != S_OK ||
Control == NULL)
{
printf("Couldn't connect to IDebugControl, HRESULT: 0x%lx\n", hr);
Client->Release();
return 3;
}
if ((hr = Monitor.Monitor(Client,
DEBUG_OUTPUT_NORMAL |
DEBUG_OUTPUT_ERROR |
DEBUG_OUTPUT_WARNING// | DEBUG_OUTPUT_VERBOSE
)) != S_OK)
{
printf("Output monitor setup failed, HRESULT: 0x%lx\n", hr);
Control->Release();
Client->Release();
return 4;
}
CtrlHandlerSet = SetConsoleCtrlHandler(
(PHANDLER_ROUTINE) CtrlHandler, // handler function
TRUE); // add to list
if ((hr = Client->ConnectSession(DEBUG_CONNECT_SESSION_NO_VERSION, 0)) != S_OK)
{
printf("Couldn't finalize connection. HRESULT 0x%lx\n", hr);
}
else
{
if (argc > 2)
{
gMainExtPath = argv[2];
}
ghGDIExt = LoadExtension(Client, gMainExtPath);
if (ghGDIExt != NULL)
{
ProcessCommands(Client, &Monitor);
FreeExtension(Client, ghGDIExt);
}
Control->Output(DEBUG_OUTPUT_NORMAL, "GDIView disconnecting.\n");
}
if (CtrlHandlerSet)
{
SetConsoleCtrlHandler(
(PHANDLER_ROUTINE) CtrlHandler, // handler function
FALSE); // remove from list
}
Control->Release();
Client->Release();
return 0;
}
HMODULE
LoadExtension(
PDEBUG_CLIENT Client,
PCSTR ExtPath
)
{
HMODULE hExt = NULL;
BOOL bInitComplete = FALSE;
PDEBUG_CONTROL2 Control2;
ULONG Status = DEBUG_STATUS_BREAK;
if (Client->QueryInterface(__uuidof(IDebugControl2),
(void **)&Control2) == S_OK)
{
Control2->GetExecutionStatus(&Status);
Control2->Release();
}
if (Status != DEBUG_STATUS_NO_DEBUGGEE)
{
if ((hExt = LoadLibraryA(ExtPath)) != NULL)
{
PDEBUG_EXTENSION_SET_CLIENT pfnDbgExtSetClient;
PDEBUG_EXTENSION_INITIALIZE pfnDbgExtInit;
PDEBUG_EXTENSION_NOTIFY pfnDbgExtNotify;
PDEBUG_EXTENSION_UNINITIALIZE pfnDbgExtUninit;
pfnDbgExtSetClient = (PDEBUG_EXTENSION_SET_CLIENT)
GetProcAddress(hExt, "DebugExtensionSetClient");
pfnDbgExtInit = (PDEBUG_EXTENSION_INITIALIZE)
GetProcAddress(hExt, "DebugExtensionInitialize");
pfnDbgExtNotify = (PDEBUG_EXTENSION_NOTIFY)
GetProcAddress(hExt, "DebugExtensionNotify");
pfnDbgExtUninit = (PDEBUG_EXTENSION_UNINITIALIZE)
GetProcAddress(hExt, "DebugExtensionUninitialize");
if ((pfnDbgExtSetClient != NULL) &&
(pfnDbgExtInit != NULL) &&
(pfnDbgExtNotify != NULL) &&
(pfnDbgExtUninit != NULL))
{
HRESULT hr;
ULONG Version, Flags;
if ((hr = pfnDbgExtSetClient(gRemoteSpec) == S_OK) &&
(hr = pfnDbgExtInit(&Version, &Flags)) == S_OK)
{
pfnDbgExtNotify(DEBUG_NOTIFY_SESSION_ACTIVE, 0);
if (Status == DEBUG_STATUS_BREAK)
{
pfnDbgExtNotify(DEBUG_NOTIFY_SESSION_ACCESSIBLE, 0);
}
bInitComplete = TRUE;
}
else
{
printf("Extension init failed: 0x%lx\n", hr);
}
}
else
{
printf("Couldn't get all required proc addresses.\n");
}
if (!bInitComplete)
{
FreeExtension(Client, hExt);
hExt = NULL;
}
}
else
{
printf("LoadLibrary for %s failed with 0x%lx.\n",
ExtPath, GetLastError());
}
}
else
{
printf("Extension was not loaded since there is no debuggee.\n");
}
return hExt;
}
BOOL
FreeExtension(
PDEBUG_CLIENT Client,
HMODULE hExt
)
{
PDEBUG_EXTENSION_UNINITIALIZE pfnDbgExtUninit;
if (hExt == NULL) return FALSE;
pfnDbgExtUninit = (PDEBUG_EXTENSION_UNINITIALIZE)
GetProcAddress(ghGDIExt, "DebugExtensionUninitialize");
if (pfnDbgExtUninit != NULL)
{
pfnDbgExtUninit();
}
return FreeLibrary(hExt);
}
VOID
ProcessCommands(
PDEBUG_CLIENT Client,
OutputMonitor *Monitor)
{
PDEBUG_CONTROL DbgControl;
CHAR CmdLine[MAX_PATH];
CHAR *pCmd;
CHAR *pArgs;
PDEBUG_EXTENSION_CALL pfnDbgExt;
if (Client == NULL ||
Client->QueryInterface(__uuidof(IDebugControl), (void **)&DbgControl) != S_OK)
{
return;
}
while (Continue)
{
printf("GDIView> ");
if (gets(CmdLine))
{
pCmd = CmdLine;
while (*pCmd && isspace(*pCmd)) pCmd++;
if (! *pCmd) continue;
if (*pCmd == '.')
{
BOOL FoundCmd = FALSE;
pCmd++;
switch (tolower(*pCmd))
{
case 'h':
if (_strnicmp(pCmd, "help", strlen(pCmd)) == 0)
{
printf("GDIView Help:\n"
" .help This help\n"
" .output Display/toggle output filtering\n"
" .quit Exit GDIView\n"
"\n"
" <GDIKDX Extension> Execute GDIKDX Extension\n"
" help GDIKDX help information\n");
FoundCmd = TRUE;
}
break;
case 'q':
if (_strnicmp(pCmd, "quit", strlen(pCmd)) == 0)
{
Continue = FALSE;
FoundCmd = TRUE;
}
break;
case 'o':
{
ULONG CmdLen;
pArgs = pCmd;
do
{
pArgs++;
} while (*pArgs != '\0' && !isspace(*pArgs));
if (_strnicmp(pCmd, "output", pArgs - pCmd) == 0)
{
SetOutputCmd(Monitor, pArgs);
FoundCmd = TRUE;
}
break;
}
default:
break;
}
if (!FoundCmd)
{
printf("Unknown internal command: .%s\n", pCmd);
}
}
else
{
pArgs = pCmd;
while (*pArgs && !isspace(*pArgs)) pArgs++;
if (*pArgs)
{
*pArgs++ = '\0';
while (*pArgs && isspace(*pArgs)) pArgs++;
}
pfnDbgExt = (PDEBUG_EXTENSION_CALL)GetProcAddress(ghGDIExt, pCmd);
if (pfnDbgExt != NULL)
{
DbgControl->ControlledOutput(DEBUG_OUTCTL_ALL_OTHER_CLIENTS,
DEBUG_OUTPUT_NORMAL,
"GDIView> !%s.%s %s\n",
gMainExtPath,
pCmd,
pArgs);
pfnDbgExt(Client, pArgs);
}
else
{
printf("Couldn't find extension: %s\n", pCmd);
}
}
}
}
DbgControl->Release();
}
VOID
SetOutputCmd(
OutputMonitor *Monitor,
const char *Args
)
{
HRESULT hr;
ULONG OutputMask;
ULONG NewMask;
ULONG ToggleMask;
BOOL Clear = FALSE;
if (Monitor == NULL) return;
hr = Monitor->GetOutputMask(&OutputMask);
if (hr != S_OK)
{
printf("Failed to retrieve Monitor's output mask.\n");
return;
}
NewMask = OutputMask;
while (isspace(*Args)) Args++;
while (hr == S_OK && *Args != '\0')
{
switch (tolower(*Args))
{
case '+': Clear = FALSE; ToggleMask = 0; break;
case '-': Clear = TRUE; ToggleMask = 0; break;
case 'n': ToggleMask |= DEBUG_OUTPUT_NORMAL; break;
case 'e': ToggleMask |= DEBUG_OUTPUT_ERROR; break;
case 'w': ToggleMask |= DEBUG_OUTPUT_WARNING; break;
case 'v': ToggleMask |= DEBUG_OUTPUT_VERBOSE; break;
case '?':
printf("Usage: .output [+-][newv]\n");
return;
default: hr = E_INVALIDARG; break;
}
Args++;
if (*Args == '\0' || isspace(*Args))
{
if (Clear)
{
NewMask &= ~ToggleMask;
}
else
{
NewMask |= ToggleMask;
}
while (isspace(*Args)) Args++;
}
}
if (hr != S_OK)
{
printf("Invalid arguments to .output.\n");
}
else if (NewMask != OutputMask)
{
hr = Monitor->SetOutputMask(NewMask);
if (hr == S_OK)
{
OutputMask = NewMask;
}
else
{
printf("Error while trying to set new monitor mask.\n");
}
}
printf("Monitoring:");
if (OutputMask & DEBUG_OUTPUT_NORMAL) printf(" Normal");
if (OutputMask & DEBUG_OUTPUT_ERROR) printf(" Error");
if (OutputMask & DEBUG_OUTPUT_WARNING) printf(" Warning");
if (OutputMask & DEBUG_OUTPUT_VERBOSE) printf(" Verbose");
OutputMask &= ~(DEBUG_OUTPUT_NORMAL | DEBUG_OUTPUT_ERROR |
DEBUG_OUTPUT_WARNING | DEBUG_OUTPUT_VERBOSE);
if (OutputMask) printf(" Other: 0x%lx", OutputMask);
printf("\n");
}
// CtrlHandler - process Console Control signals
//
// Note: Global Control must be available whenever
// CtrlHandler is registered.
BOOL CtrlHandler(DWORD fdwCtrlType)
{
switch (fdwCtrlType)
{
// Handle the CTRL+C and CTRL+Break signals.
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
Control->SetInterrupt(DEBUG_INTERRUPT_PASSIVE);
return TRUE;
// User wants to exit.
case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
Continue = FALSE;
Control->SetInterrupt(DEBUG_INTERRUPT_EXIT);
return TRUE;
// Pass other signals to the next handler.
default:
return FALSE;
}
}