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.

513 lines
16 KiB

  1. /*-----------------------------------------------------------------------------
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module:
  4. exts.cpp
  5. Sampe file showing couple of extension examples
  6. -----------------------------------------------------------------------------*/
  7. #include "tsdbg.h"
  8. bool IsUserDbg()
  9. {
  10. /*
  11. // Specific types of kernel debuggees.
  12. #define DEBUG_KERNEL_CONNECTION 0
  13. #define DEBUG_KERNEL_LOCAL 1
  14. #define DEBUG_KERNEL_EXDI_DRIVER 2
  15. #define DEBUG_KERNEL_SMALL_DUMP DEBUG_DUMP_SMALL
  16. #define DEBUG_KERNEL_DUMP DEBUG_DUMP_DEFAULT
  17. #define DEBUG_KERNEL_FULL_DUMP DEBUG_DUMP_FULL
  18. // Specific types of Windows user debuggees.
  19. #define DEBUG_USER_WINDOWS_PROCESS 0
  20. #define DEBUG_USER_WINDOWS_PROCESS_SERVER 1
  21. #define DEBUG_USER_WINDOWS_SMALL_DUMP DEBUG_DUMP_SMALL
  22. #define DEBUG_USER_WINDOWS_DUMP DEBUG_DUMP_DEFAULT
  23. */
  24. /*
  25. #define DEBUG_CLASS_UNINITIALIZED 0
  26. #define DEBUG_CLASS_KERNEL 1
  27. #define DEBUG_CLASS_USER_WINDOWS 2
  28. */
  29. ULONG Class, Qualifier;
  30. // Figure out if this is KD or NTSD piped to KD.
  31. if (S_OK != g_ExtControl->GetDebuggeeType(&Class, &Qualifier))
  32. {
  33. dprintf("*** GetDebuggeeType failed ***\n\n");
  34. }
  35. if (Class == DEBUG_CLASS_USER_WINDOWS)
  36. return true;
  37. else
  38. return false;
  39. }
  40. /*
  41. Sample extension to demonstrace ececuting debugger command
  42. */
  43. HRESULT CALLBACK
  44. cmdsample(PDEBUG_CLIENT Client, PCSTR args)
  45. {
  46. CHAR Input[256];
  47. INIT_API();
  48. UNREFERENCED_PARAMETER(args);
  49. //
  50. // Output a 10 frame stack
  51. //
  52. g_ExtControl->OutputStackTrace(DEBUG_OUTCTL_ALL_CLIENTS | // Flags on what to do with output
  53. DEBUG_OUTCTL_OVERRIDE_MASK |
  54. DEBUG_OUTCTL_NOT_LOGGED,
  55. NULL,
  56. 10, // number of frames to display
  57. DEBUG_STACK_FUNCTION_INFO | DEBUG_STACK_COLUMN_NAMES |
  58. DEBUG_STACK_ARGUMENTS | DEBUG_STACK_FRAME_ADDRESSES);
  59. //
  60. // Engine interface for print
  61. //
  62. g_ExtControl->Output(DEBUG_OUTCTL_ALL_CLIENTS, "\n\nDebugger module list\n");
  63. //
  64. // list all the modules by executing lm command
  65. //
  66. g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
  67. DEBUG_OUTCTL_OVERRIDE_MASK |
  68. DEBUG_OUTCTL_NOT_LOGGED,
  69. "lm", // Command to be executed
  70. DEBUG_EXECUTE_DEFAULT );
  71. //
  72. // Ask for user input
  73. //
  74. g_ExtControl->Output(DEBUG_OUTCTL_ALL_CLIENTS, "\n\n***User Input sample\n\nEnter Command to run : ");
  75. GetInputLine(NULL, &Input[0], sizeof(Input));
  76. g_ExtControl->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
  77. DEBUG_OUTCTL_OVERRIDE_MASK |
  78. DEBUG_OUTCTL_NOT_LOGGED,
  79. Input, // Command to be executed
  80. DEBUG_EXECUTE_DEFAULT );
  81. EXIT_API();
  82. return S_OK;
  83. }
  84. /*
  85. Sample extension to read and dump a struct on target
  86. This reads the struct _EXCEPTION_RECORD which is defined as:
  87. typedef struct _EXCEPTION_RECORD {
  88. NTSTATUS ExceptionCode;
  89. ULONG ExceptionFlags;
  90. struct _EXCEPTION_RECORD *ExceptionRecord;
  91. PVOID ExceptionAddress;
  92. ULONG NumberParameters;
  93. ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
  94. } EXCEPTION_RECORD;
  95. */
  96. HRESULT CALLBACK
  97. structsample(PDEBUG_CLIENT /*Client*/, PCSTR /*args*/)
  98. {
  99. /*
  100. ULONG64 Address;
  101. INIT_API();
  102. Address = GetExpression(args);
  103. DWORD Buffer[4], cb;
  104. // Read and display first 4 dwords at Address
  105. if (ReadMemory(Address, &Buffer, sizeof(Buffer), &cb) && cb == sizeof(Buffer)) {
  106. dprintf("%p: %08lx %08lx %08lx %08lx\n\n", Address,
  107. Buffer[0], Buffer[1], Buffer[2], Buffer[3]);
  108. }
  109. //
  110. // Method 1 to dump a struct
  111. //
  112. dprintf("Method 1:\n");
  113. // Inititalze type read from the Address
  114. if (InitTypeRead(Address, _EXCEPTION_RECORD) != 0) {
  115. dprintf("Error in reading _EXCEPTION_RECORD at %p", // Use %p to print pointer values
  116. Address);
  117. } else {
  118. // read and dump the fields
  119. dprintf("_EXCEPTION_RECORD @ %p\n", Address);
  120. dprintf("\tExceptionCode : %lx\n", (ULONG) ReadField(ExceptionCode));
  121. dprintf("\tExceptionAddress : %p\n", ReadField(ExceptionAddress));
  122. dprintf("\tExceptionInformation[1] : %I64lx\n", ReadField(ExceptionInformation[1]));
  123. // And so on...
  124. }
  125. //
  126. // Method 2 to read a struct
  127. //
  128. ULONG64 ExceptionInformation_1, ExceptionAddress, ExceptionCode;
  129. dprintf("\n\nMethod 2:\n");
  130. // Read and dump the fields by specifying type and address individually
  131. if (GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionCode", ExceptionCode)) {
  132. dprintf("Error in reading _EXCEPTION_RECORD at %p\n",
  133. Address);
  134. } else {
  135. // Pointers are read as ULONG64 values
  136. GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionAddress", ExceptionAddress);
  137. GetFieldValue(Address, "_EXCEPTION_RECORD", "ExceptionInformation[1]", ExceptionInformation_1);
  138. // And so on..
  139. dprintf("_EXCEPTION_RECORD @ %p\n", Address);
  140. dprintf("\tExceptionCode : %lx\n", ExceptionCode);
  141. dprintf("\tExceptionAddress : %p\n", ExceptionAddress);
  142. dprintf("\tExceptionInformation[1] : %I64lx\n", ExceptionInformation_1);
  143. }
  144. ULONG64 Module;
  145. ULONG i, TypeId;
  146. CHAR Name[MAX_PATH];
  147. //
  148. // To get/list field names
  149. //
  150. g_ExtSymbols->GetSymbolTypeId("_EXCEPTION_RECORD", &TypeId, &Module);
  151. dprintf("Fields of _EXCEPTION_RECORD\n");
  152. for (i=0; ;i++) {
  153. HRESULT Hr;
  154. ULONG Offset=0;
  155. Hr = g_ExtSymbols2->GetFieldName(Module, TypeId, i, Name, MAX_PATH, NULL);
  156. if (Hr == S_OK) {
  157. g_ExtSymbols->GetFieldOffset(Module, TypeId, Name, &Offset);
  158. dprintf("%lx (+%03lx) %s\n", i, Offset, Name);
  159. } else if (Hr == E_INVALIDARG) {
  160. // All Fields done
  161. break;
  162. } else {
  163. dprintf("GetFieldName Failed %lx\n", Hr);
  164. break;
  165. }
  166. }
  167. //
  168. // Get name for an enumerate
  169. //
  170. // typedef enum {
  171. // Enum1,
  172. // Enum2,
  173. // Enum3,
  174. // } TEST_ENUM;
  175. //
  176. ULONG ValueOfEnum = 0;
  177. g_ExtSymbols->GetSymbolTypeId("TEST_ENUM", &TypeId, &Module);
  178. g_ExtSymbols2->GetConstantName(Module, TypeId, ValueOfEnum, Name, MAX_PATH, NULL);
  179. dprintf("Testenum %I64lx == %s\n", ExceptionCode, Name);
  180. // This prints out, Testenum 0 == Enum1
  181. //
  182. // Read an array
  183. //
  184. // typedef struct FOO_TYPE {
  185. // ULONG Bar;
  186. // ULONG Bar2;
  187. // } FOO_TYPE;
  188. //
  189. // FOO_TYPE sampleArray[20];
  190. ULONG Bar, Bar2;
  191. CHAR TypeName[100];
  192. for (i=0; i<20; i++) {
  193. sprintf(TypeName, "sampleArray[%lx]", i);
  194. if (GetFieldValue(0, TypeName, "Bar", Bar))
  195. break;
  196. GetFieldValue(0, TypeName, "Bar2", Bar2);
  197. dprintf("%16s - Bar %2ld Bar2 %ld\n", TypeName, Bar, Bar2);
  198. }
  199. EXIT_API();
  200. */
  201. return S_OK;
  202. }
  203. /*
  204. This gets called (by DebugExtensionNotify whentarget is halted and is accessible
  205. */
  206. HRESULT
  207. NotifyOnTargetAccessible(PDEBUG_CONTROL /* Control */)
  208. {/*
  209. dprintf("Extension dll detected a break");
  210. if (Connected) {
  211. dprintf(" connected to ");
  212. switch (TargetMachine) {
  213. case IMAGE_FILE_MACHINE_I386:
  214. dprintf("X86");
  215. break;
  216. case IMAGE_FILE_MACHINE_AMD64:
  217. dprintf("AMD64");
  218. break;
  219. case IMAGE_FILE_MACHINE_IA64:
  220. dprintf("IA64");
  221. break;
  222. default:
  223. dprintf("Other");
  224. break;
  225. }
  226. }
  227. dprintf("\n");
  228. //
  229. // show the top frame and execute dv to dump the locals here and return
  230. //
  231. Control->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
  232. DEBUG_OUTCTL_OVERRIDE_MASK |
  233. DEBUG_OUTCTL_NOT_LOGGED,
  234. ".frame", // Command to be executed
  235. DEBUG_EXECUTE_DEFAULT );
  236. Control->Execute(DEBUG_OUTCTL_ALL_CLIENTS |
  237. DEBUG_OUTCTL_OVERRIDE_MASK |
  238. DEBUG_OUTCTL_NOT_LOGGED,
  239. "dv", // Command to be executed
  240. DEBUG_EXECUTE_DEFAULT );
  241. */
  242. return S_OK;
  243. }
  244. /*
  245. A built-in help for the extension dll
  246. */
  247. HRESULT CALLBACK
  248. help(PDEBUG_CLIENT Client, PCSTR args)
  249. {
  250. INIT_API();
  251. UNREFERENCED_PARAMETER(args);
  252. dprintf("Help for tsdbg.dll\n"
  253. " qwinsta - lists winstation data structures\n"
  254. " help = Shows this help\n"
  255. // " structsample <addr> - This dumps a struct at given address\n"
  256. //" cmdsample - This does stacktrace and lists\n"
  257. );
  258. EXIT_API();
  259. return S_OK;
  260. }
  261. void PrintBuildNumber()
  262. {
  263. ULONG64 Address;
  264. Address = GetExpression("poi(nt!ntbuildnumber)");
  265. if (Address & 0xf0000000)
  266. {
  267. Address &= 0x0fffffff;
  268. dprintf("Build Number = %d Free\n", Address);
  269. }
  270. else if (Address & 0xc0000000)
  271. {
  272. Address &= 0x0fffffff;
  273. dprintf("Build Number = %d Chk\n", Address);
  274. }
  275. else
  276. {
  277. dprintf("Error getting Build Number!\n");
  278. }
  279. }
  280. HRESULT CALLBACK
  281. qwinsta(PDEBUG_CLIENT Client, PCSTR args)
  282. {
  283. ULONG64 winstationlisthead, FLink;
  284. ULONG64 TermSrvProcPerTermDD = 0;
  285. bool bDebugMode = false;
  286. INIT_API();
  287. dprintf("qwinsta 1.2\n");
  288. if (strstr(args, "debug"))
  289. bDebugMode = true;
  290. if (bDebugMode)
  291. {
  292. dprintf("*** in debug mode *** \n");
  293. }
  294. if (bDebugMode)
  295. dprintf("IsUserDebugger = %s\n", (IsUserDbg() ? "true" : "false"));
  296. dprintf("----------------------------------------------------------------------------------------------------\n");
  297. //
  298. // Find Termsrv proccess id.
  299. //
  300. if (!IsUserDbg())
  301. {
  302. TermSrvProcPerTermDD = GetExpression("poi(termdd!g_TermServProcessID)");
  303. dprintf("termsrv process = %p \n", TermSrvProcPerTermDD);
  304. if (!TermSrvProcPerTermDD)
  305. {
  306. dprintf("ERROR:tsdbg failed to retrive the value for termdd!g_TermServProcessID\n");
  307. dprintf("please make sure that the symbols are alright\n");
  308. goto doneError;
  309. }
  310. ULONG64 ImpliciteProcess;
  311. g_ExtSysObjects2->GetImplicitProcessDataOffset(&ImpliciteProcess);
  312. dprintf("Implicit Process = %p \n", ImpliciteProcess);
  313. ULONG64 CurrentProcess;
  314. g_ExtSysObjects2->GetCurrentProcessDataOffset(&CurrentProcess);
  315. dprintf("current Process = %p \n", CurrentProcess);
  316. if (ImpliciteProcess != TermSrvProcPerTermDD)
  317. {
  318. dprintf("ERROR:tsdbg for this command to work current implicite process must be termsrv.\n");
  319. dprintf("please do .process /p %p and then try again.\n", TermSrvProcPerTermDD);
  320. goto doneError;
  321. }
  322. }
  323. //
  324. // get active console session id.
  325. //
  326. LONG ActiveConsoleId = STATUS_UNSUCCESSFUL;
  327. if (GetFieldValue((ULONG64) MM_SHARED_USER_DATA_VA, "termsrv!KUSER_SHARED_DATA", "ActiveConsoleId", ActiveConsoleId))
  328. ActiveConsoleId = STATUS_UNSUCCESSFUL;
  329. dprintf("ActiveConsoleId = %d \n", ActiveConsoleId);
  330. //
  331. // winstation list head.
  332. //
  333. winstationlisthead = GetExpression("termsrv!winstationlisthead");
  334. if (!winstationlisthead)
  335. {
  336. dprintf("ERROR:tsdbg failed to retrive the value for termsrv!winstationlisthead\n");
  337. dprintf("please make sure that the symbols are alright\n");
  338. goto doneError;
  339. }
  340. dprintf("winstationlisthead = %p \n", winstationlisthead);
  341. if (GetFieldValue(winstationlisthead, "termsrv!LIST_ENTRY", "Flink", FLink))
  342. {
  343. dprintf("failed to get winstationlisthead.flink\n\n");
  344. goto doneError;
  345. }
  346. UINT uiWinstations = 0;
  347. //
  348. // print winstation list.
  349. //
  350. dprintf("----------------------------------------------------------------------------------------------------\n");
  351. dprintf("%8s", "Winsta");
  352. dprintf(" ");
  353. dprintf("%7s", "LogonId");
  354. dprintf(" ");
  355. dprintf("%-10s", "Name");
  356. dprintf(" ");
  357. dprintf("%-22s", "State");
  358. dprintf(" ");
  359. dprintf("%8s", "Flags");
  360. dprintf(" ");
  361. dprintf("%8s", "SFlags");
  362. dprintf(" ");
  363. dprintf("%-10s", "Starting");
  364. dprintf(" ");
  365. dprintf("%-10s", "Terminating");
  366. dprintf("\n");
  367. while (winstationlisthead != FLink && uiWinstations < 500)
  368. {
  369. if (CheckControlC()) goto doneError;
  370. uiWinstations++;
  371. ULONG ret = 0;
  372. ULONG LogonId, State, Flags, StateFlags;
  373. WCHAR WinStationName[33];
  374. UCHAR Starting, Terminating;
  375. // InitTypeRead(FLink, Type)
  376. ret += GetFieldValue(FLink, "termsrv!_WINSTATION", "LogonId", LogonId);
  377. ret += GetFieldValue(FLink, "termsrv!_WINSTATION", "WinStationName", WinStationName);
  378. ret += GetFieldValue(FLink, "termsrv!_WINSTATION", "State", State);
  379. ret += GetFieldValue(FLink, "termsrv!_WINSTATION", "Flags", Flags);
  380. ret += GetFieldValue(FLink, "termsrv!_WINSTATION", "Starting", Starting);
  381. ret += GetFieldValue(FLink, "termsrv!_WINSTATION", "LogonId", LogonId);
  382. ret += GetFieldValue(FLink, "termsrv!_WINSTATION", "Terminating", Terminating);
  383. ret += GetFieldValue(FLink, "termsrv!_WINSTATION", "StateFlags", StateFlags);
  384. //
  385. // get string value for the enum _WINSTATIONSTATECLASS.
  386. //
  387. ULONG64 Module;
  388. ULONG TypeId;
  389. char StateName[MAX_PATH];
  390. g_ExtSymbols->GetSymbolTypeId("_WINSTATIONSTATECLASS", &TypeId, &Module);
  391. g_ExtSymbols2->GetConstantName(Module, TypeId, State, StateName, MAX_PATH, NULL);
  392. if (ret)
  393. {
  394. dprintf("failed to get winstationlisthead.flink\n\n");
  395. goto doneError;
  396. }
  397. dprintf("%p", FLink);
  398. dprintf(" ");
  399. dprintf("%#7x", LogonId);
  400. dprintf(" ");
  401. dprintf("%-10S", WinStationName);
  402. dprintf(" ");
  403. dprintf("%1x:%-20s", State, StateName);
  404. dprintf(" ");
  405. dprintf("%08x", Flags);
  406. dprintf(" ");
  407. dprintf("%08x", StateFlags);
  408. dprintf(" ");
  409. dprintf("%-10s", (Starting ? "True" : "False"));
  410. dprintf(" ");
  411. dprintf("%-10s", (Terminating ? "True" : "False"));
  412. dprintf("\n");
  413. //dprintf("%10p %7d %-10S %5d:%-20s %5d %10d %-8s %-11s\n", FLink, LogonId, WinStationName, State, StateName, Flags, StateFlags, (Starting ? "true" : "false"), (Terminating ? "true" : "false"));
  414. if (GetFieldValue(FLink, "termsrv!LIST_ENTRY", "Flink", FLink))
  415. {
  416. dprintf("failed to get winstationlisthead.flink\n\n");
  417. goto doneError;
  418. }
  419. }
  420. dprintf("----------------------------------------------------------------------------------------------------\n");
  421. // dprintf("Total Winstations = %d\n", uiWinstations);
  422. doneError:
  423. EXIT_API();
  424. return S_OK;
  425. }