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

  1. #include <windows.h>
  2. #include <tchar.h>
  3. #include <stdio.h>
  4. #include <dbgeng.h>
  5. #include "debug.h"
  6. #include "output.h"
  7. typedef HRESULT (CALLBACK* PDEBUG_EXTENSION_SET_CLIENT)(LPCSTR RemoteArgs);
  8. #if DBG
  9. CHAR szDefaultExtPath[] = "\\\\JasonHa\\DbgExts\\gdikdxd";
  10. #else
  11. CHAR szDefaultExtPath[] = "\\\\JasonHa\\DbgExts\\gdikdxr";
  12. #endif
  13. HMODULE ghGDIExt = NULL;
  14. PDEBUG_CONTROL Control = NULL;
  15. BOOL Continue = TRUE;
  16. PCSTR gRemoteSpec = NULL;
  17. PCSTR gMainExtPath = szDefaultExtPath;
  18. HMODULE LoadExtension(PDEBUG_CLIENT Client, PCSTR ExtPath);
  19. BOOL FreeExtension(PDEBUG_CLIENT, HMODULE hExt);
  20. VOID ProcessCommands(PDEBUG_CLIENT Client, OutputMonitor *Monitor);
  21. VOID SetOutputCmd(OutputMonitor *Monitor, const char *Args);
  22. BOOL CtrlHandler(DWORD fdwCtrlType);
  23. int __cdecl main(int argc, char** argv)
  24. {
  25. HRESULT hr;
  26. BOOL CtrlHandlerSet;
  27. PDEBUG_CLIENT Client = NULL;
  28. OutputMonitor Monitor;
  29. if (argc < 2)
  30. {
  31. printf("Missing remote specification.\n");
  32. return 1;
  33. }
  34. if (argc > 3)
  35. {
  36. printf("Too many arguments.\n");
  37. return 1;
  38. }
  39. gRemoteSpec = argv[1];
  40. if ((hr = DebugConnect(gRemoteSpec, __uuidof(IDebugClient), (void **)&Client)) != S_OK ||
  41. Client == NULL)
  42. {
  43. printf("Couldn't connect to client: %s, HRESULT: 0x%lx\n", argv[1], hr);
  44. return 2;
  45. }
  46. if ((hr = Client->QueryInterface(__uuidof(IDebugControl), (void **)&Control)) != S_OK ||
  47. Control == NULL)
  48. {
  49. printf("Couldn't connect to IDebugControl, HRESULT: 0x%lx\n", hr);
  50. Client->Release();
  51. return 3;
  52. }
  53. if ((hr = Monitor.Monitor(Client,
  54. DEBUG_OUTPUT_NORMAL |
  55. DEBUG_OUTPUT_ERROR |
  56. DEBUG_OUTPUT_WARNING// | DEBUG_OUTPUT_VERBOSE
  57. )) != S_OK)
  58. {
  59. printf("Output monitor setup failed, HRESULT: 0x%lx\n", hr);
  60. Control->Release();
  61. Client->Release();
  62. return 4;
  63. }
  64. CtrlHandlerSet = SetConsoleCtrlHandler(
  65. (PHANDLER_ROUTINE) CtrlHandler, // handler function
  66. TRUE); // add to list
  67. if ((hr = Client->ConnectSession(DEBUG_CONNECT_SESSION_NO_VERSION, 0)) != S_OK)
  68. {
  69. printf("Couldn't finalize connection. HRESULT 0x%lx\n", hr);
  70. }
  71. else
  72. {
  73. if (argc > 2)
  74. {
  75. gMainExtPath = argv[2];
  76. }
  77. ghGDIExt = LoadExtension(Client, gMainExtPath);
  78. if (ghGDIExt != NULL)
  79. {
  80. ProcessCommands(Client, &Monitor);
  81. FreeExtension(Client, ghGDIExt);
  82. }
  83. Control->Output(DEBUG_OUTPUT_NORMAL, "GDIView disconnecting.\n");
  84. }
  85. if (CtrlHandlerSet)
  86. {
  87. SetConsoleCtrlHandler(
  88. (PHANDLER_ROUTINE) CtrlHandler, // handler function
  89. FALSE); // remove from list
  90. }
  91. Control->Release();
  92. Client->Release();
  93. return 0;
  94. }
  95. HMODULE
  96. LoadExtension(
  97. PDEBUG_CLIENT Client,
  98. PCSTR ExtPath
  99. )
  100. {
  101. HMODULE hExt = NULL;
  102. BOOL bInitComplete = FALSE;
  103. PDEBUG_CONTROL2 Control2;
  104. ULONG Status = DEBUG_STATUS_BREAK;
  105. if (Client->QueryInterface(__uuidof(IDebugControl2),
  106. (void **)&Control2) == S_OK)
  107. {
  108. Control2->GetExecutionStatus(&Status);
  109. Control2->Release();
  110. }
  111. if (Status != DEBUG_STATUS_NO_DEBUGGEE)
  112. {
  113. if ((hExt = LoadLibraryA(ExtPath)) != NULL)
  114. {
  115. PDEBUG_EXTENSION_SET_CLIENT pfnDbgExtSetClient;
  116. PDEBUG_EXTENSION_INITIALIZE pfnDbgExtInit;
  117. PDEBUG_EXTENSION_NOTIFY pfnDbgExtNotify;
  118. PDEBUG_EXTENSION_UNINITIALIZE pfnDbgExtUninit;
  119. pfnDbgExtSetClient = (PDEBUG_EXTENSION_SET_CLIENT)
  120. GetProcAddress(hExt, "DebugExtensionSetClient");
  121. pfnDbgExtInit = (PDEBUG_EXTENSION_INITIALIZE)
  122. GetProcAddress(hExt, "DebugExtensionInitialize");
  123. pfnDbgExtNotify = (PDEBUG_EXTENSION_NOTIFY)
  124. GetProcAddress(hExt, "DebugExtensionNotify");
  125. pfnDbgExtUninit = (PDEBUG_EXTENSION_UNINITIALIZE)
  126. GetProcAddress(hExt, "DebugExtensionUninitialize");
  127. if ((pfnDbgExtSetClient != NULL) &&
  128. (pfnDbgExtInit != NULL) &&
  129. (pfnDbgExtNotify != NULL) &&
  130. (pfnDbgExtUninit != NULL))
  131. {
  132. HRESULT hr;
  133. ULONG Version, Flags;
  134. if ((hr = pfnDbgExtSetClient(gRemoteSpec) == S_OK) &&
  135. (hr = pfnDbgExtInit(&Version, &Flags)) == S_OK)
  136. {
  137. pfnDbgExtNotify(DEBUG_NOTIFY_SESSION_ACTIVE, 0);
  138. if (Status == DEBUG_STATUS_BREAK)
  139. {
  140. pfnDbgExtNotify(DEBUG_NOTIFY_SESSION_ACCESSIBLE, 0);
  141. }
  142. bInitComplete = TRUE;
  143. }
  144. else
  145. {
  146. printf("Extension init failed: 0x%lx\n", hr);
  147. }
  148. }
  149. else
  150. {
  151. printf("Couldn't get all required proc addresses.\n");
  152. }
  153. if (!bInitComplete)
  154. {
  155. FreeExtension(Client, hExt);
  156. hExt = NULL;
  157. }
  158. }
  159. else
  160. {
  161. printf("LoadLibrary for %s failed with 0x%lx.\n",
  162. ExtPath, GetLastError());
  163. }
  164. }
  165. else
  166. {
  167. printf("Extension was not loaded since there is no debuggee.\n");
  168. }
  169. return hExt;
  170. }
  171. BOOL
  172. FreeExtension(
  173. PDEBUG_CLIENT Client,
  174. HMODULE hExt
  175. )
  176. {
  177. PDEBUG_EXTENSION_UNINITIALIZE pfnDbgExtUninit;
  178. if (hExt == NULL) return FALSE;
  179. pfnDbgExtUninit = (PDEBUG_EXTENSION_UNINITIALIZE)
  180. GetProcAddress(ghGDIExt, "DebugExtensionUninitialize");
  181. if (pfnDbgExtUninit != NULL)
  182. {
  183. pfnDbgExtUninit();
  184. }
  185. return FreeLibrary(hExt);
  186. }
  187. VOID
  188. ProcessCommands(
  189. PDEBUG_CLIENT Client,
  190. OutputMonitor *Monitor)
  191. {
  192. PDEBUG_CONTROL DbgControl;
  193. CHAR CmdLine[MAX_PATH];
  194. CHAR *pCmd;
  195. CHAR *pArgs;
  196. PDEBUG_EXTENSION_CALL pfnDbgExt;
  197. if (Client == NULL ||
  198. Client->QueryInterface(__uuidof(IDebugControl), (void **)&DbgControl) != S_OK)
  199. {
  200. return;
  201. }
  202. while (Continue)
  203. {
  204. printf("GDIView> ");
  205. if (gets(CmdLine))
  206. {
  207. pCmd = CmdLine;
  208. while (*pCmd && isspace(*pCmd)) pCmd++;
  209. if (! *pCmd) continue;
  210. if (*pCmd == '.')
  211. {
  212. BOOL FoundCmd = FALSE;
  213. pCmd++;
  214. switch (tolower(*pCmd))
  215. {
  216. case 'h':
  217. if (_strnicmp(pCmd, "help", strlen(pCmd)) == 0)
  218. {
  219. printf("GDIView Help:\n"
  220. " .help This help\n"
  221. " .output Display/toggle output filtering\n"
  222. " .quit Exit GDIView\n"
  223. "\n"
  224. " <GDIKDX Extension> Execute GDIKDX Extension\n"
  225. " help GDIKDX help information\n");
  226. FoundCmd = TRUE;
  227. }
  228. break;
  229. case 'q':
  230. if (_strnicmp(pCmd, "quit", strlen(pCmd)) == 0)
  231. {
  232. Continue = FALSE;
  233. FoundCmd = TRUE;
  234. }
  235. break;
  236. case 'o':
  237. {
  238. ULONG CmdLen;
  239. pArgs = pCmd;
  240. do
  241. {
  242. pArgs++;
  243. } while (*pArgs != '\0' && !isspace(*pArgs));
  244. if (_strnicmp(pCmd, "output", pArgs - pCmd) == 0)
  245. {
  246. SetOutputCmd(Monitor, pArgs);
  247. FoundCmd = TRUE;
  248. }
  249. break;
  250. }
  251. default:
  252. break;
  253. }
  254. if (!FoundCmd)
  255. {
  256. printf("Unknown internal command: .%s\n", pCmd);
  257. }
  258. }
  259. else
  260. {
  261. pArgs = pCmd;
  262. while (*pArgs && !isspace(*pArgs)) pArgs++;
  263. if (*pArgs)
  264. {
  265. *pArgs++ = '\0';
  266. while (*pArgs && isspace(*pArgs)) pArgs++;
  267. }
  268. pfnDbgExt = (PDEBUG_EXTENSION_CALL)GetProcAddress(ghGDIExt, pCmd);
  269. if (pfnDbgExt != NULL)
  270. {
  271. DbgControl->ControlledOutput(DEBUG_OUTCTL_ALL_OTHER_CLIENTS,
  272. DEBUG_OUTPUT_NORMAL,
  273. "GDIView> !%s.%s %s\n",
  274. gMainExtPath,
  275. pCmd,
  276. pArgs);
  277. pfnDbgExt(Client, pArgs);
  278. }
  279. else
  280. {
  281. printf("Couldn't find extension: %s\n", pCmd);
  282. }
  283. }
  284. }
  285. }
  286. DbgControl->Release();
  287. }
  288. VOID
  289. SetOutputCmd(
  290. OutputMonitor *Monitor,
  291. const char *Args
  292. )
  293. {
  294. HRESULT hr;
  295. ULONG OutputMask;
  296. ULONG NewMask;
  297. ULONG ToggleMask;
  298. BOOL Clear = FALSE;
  299. if (Monitor == NULL) return;
  300. hr = Monitor->GetOutputMask(&OutputMask);
  301. if (hr != S_OK)
  302. {
  303. printf("Failed to retrieve Monitor's output mask.\n");
  304. return;
  305. }
  306. NewMask = OutputMask;
  307. while (isspace(*Args)) Args++;
  308. while (hr == S_OK && *Args != '\0')
  309. {
  310. switch (tolower(*Args))
  311. {
  312. case '+': Clear = FALSE; ToggleMask = 0; break;
  313. case '-': Clear = TRUE; ToggleMask = 0; break;
  314. case 'n': ToggleMask |= DEBUG_OUTPUT_NORMAL; break;
  315. case 'e': ToggleMask |= DEBUG_OUTPUT_ERROR; break;
  316. case 'w': ToggleMask |= DEBUG_OUTPUT_WARNING; break;
  317. case 'v': ToggleMask |= DEBUG_OUTPUT_VERBOSE; break;
  318. case '?':
  319. printf("Usage: .output [+-][newv]\n");
  320. return;
  321. default: hr = E_INVALIDARG; break;
  322. }
  323. Args++;
  324. if (*Args == '\0' || isspace(*Args))
  325. {
  326. if (Clear)
  327. {
  328. NewMask &= ~ToggleMask;
  329. }
  330. else
  331. {
  332. NewMask |= ToggleMask;
  333. }
  334. while (isspace(*Args)) Args++;
  335. }
  336. }
  337. if (hr != S_OK)
  338. {
  339. printf("Invalid arguments to .output.\n");
  340. }
  341. else if (NewMask != OutputMask)
  342. {
  343. hr = Monitor->SetOutputMask(NewMask);
  344. if (hr == S_OK)
  345. {
  346. OutputMask = NewMask;
  347. }
  348. else
  349. {
  350. printf("Error while trying to set new monitor mask.\n");
  351. }
  352. }
  353. printf("Monitoring:");
  354. if (OutputMask & DEBUG_OUTPUT_NORMAL) printf(" Normal");
  355. if (OutputMask & DEBUG_OUTPUT_ERROR) printf(" Error");
  356. if (OutputMask & DEBUG_OUTPUT_WARNING) printf(" Warning");
  357. if (OutputMask & DEBUG_OUTPUT_VERBOSE) printf(" Verbose");
  358. OutputMask &= ~(DEBUG_OUTPUT_NORMAL | DEBUG_OUTPUT_ERROR |
  359. DEBUG_OUTPUT_WARNING | DEBUG_OUTPUT_VERBOSE);
  360. if (OutputMask) printf(" Other: 0x%lx", OutputMask);
  361. printf("\n");
  362. }
  363. // CtrlHandler - process Console Control signals
  364. //
  365. // Note: Global Control must be available whenever
  366. // CtrlHandler is registered.
  367. BOOL CtrlHandler(DWORD fdwCtrlType)
  368. {
  369. switch (fdwCtrlType)
  370. {
  371. // Handle the CTRL+C and CTRL+Break signals.
  372. case CTRL_C_EVENT:
  373. case CTRL_BREAK_EVENT:
  374. Control->SetInterrupt(DEBUG_INTERRUPT_PASSIVE);
  375. return TRUE;
  376. // User wants to exit.
  377. case CTRL_CLOSE_EVENT:
  378. case CTRL_LOGOFF_EVENT:
  379. case CTRL_SHUTDOWN_EVENT:
  380. Continue = FALSE;
  381. Control->SetInterrupt(DEBUG_INTERRUPT_EXIT);
  382. return TRUE;
  383. // Pass other signals to the next handler.
  384. default:
  385. return FALSE;
  386. }
  387. }