Leaked source code of windows server 2003

3394 lines
106 KiB

  1. #include <assert.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. #include <memory.h>
  7. #include <ntos.h>
  8. #include <nturtl.h>
  9. #include <windows.h>
  10. #include <dbghelp.h>
  11. //
  12. // Include umdh stuff
  13. //
  14. #define _PART_OF_DH_ 1
  15. #include "..\umdh\database.c"
  16. #include "..\umdh\miscellaneous.c"
  17. #include "..\umdh\symbols.c"
  18. #include "..\umdh\umdh.c"
  19. #include "..\umdh\dhcmp.c"
  20. #include "..\umdh\heapwalk.c"
  21. #include "..\umdh\gc.c"
  22. #define MAXDWORD 0xffffffff //this is the max value for a DWORD
  23. //
  24. // the amount of memory to increase the size
  25. // of the buffer for NtQuerySystemInformation at each step
  26. //
  27. #define BUFFER_SIZE_STEP 65536
  28. //
  29. // Globals
  30. //
  31. BOOL fVerbose;
  32. BOOL fDumpModules;
  33. BOOL fDumpBackTraces;
  34. BOOL fIgnoreBackTraces;
  35. BOOL fDumpHeapSummaries;
  36. BOOL fDumpHeapTags;
  37. BOOL fDumpHeapEntries;
  38. BOOL fDumpHeapHogs;
  39. BOOL fDumpLocks;
  40. BOOL fDumpSystemObjects;
  41. BOOL fDumpSystemProcesses;
  42. BOOL fDumpKernelModeInformation;
  43. ULONG BufferSize ;
  44. BOOL fRepetitive; // Are we in repetitive mode
  45. DWORD dwTimeInterval; // what is the repetitive time interval
  46. DWORD dwCurrentIteration; // how many iterations have we done in repetitive mode
  47. //
  48. // BogdanA 02/19/2002 - in all of the below we rely on the
  49. // fact that globals are zeroed...
  50. //
  51. CHAR SavedFileName[ MAX_PATH ]; // what would the file name be if we didnt iterate
  52. HANDLE hCtrlCEvent; // The ctrl-c event - only for repetitive mode
  53. ULONG_PTR ProcessId; // -1=win32.sys, 0= kernel, +n= Process ID
  54. HANDLE OutputFile;
  55. CHAR DumpLine[512];
  56. CHAR OutputFileName[ MAX_PATH ];
  57. //
  58. // Prototypes
  59. //
  60. // (this is local even though it looks like it should be in ntos\rtl)
  61. PRTL_DEBUG_INFORMATION
  62. RtlQuerySystemDebugInformation(
  63. ULONG Flags
  64. );
  65. BOOLEAN
  66. ComputeSymbolicBackTraces(
  67. PRTL_PROCESS_BACKTRACES BackTraces1
  68. );
  69. BOOLEAN
  70. LoadSymbolsForModules(
  71. PRTL_PROCESS_MODULES Modules
  72. );
  73. VOID
  74. DumpModules(
  75. PRTL_PROCESS_MODULES Modules
  76. );
  77. VOID
  78. DumpBackTraces( VOID );
  79. VOID
  80. DumpHeaps(
  81. PRTL_PROCESS_HEAPS Heaps,
  82. BOOL fDumpSummary,
  83. BOOL fDumpHogs,
  84. BOOL fDumpTags,
  85. BOOL fDumpEntries
  86. );
  87. VOID
  88. DumpLocks(
  89. PRTL_PROCESS_LOCKS Locks
  90. );
  91. VOID
  92. DumpSystemProcesses( VOID );
  93. VOID
  94. DumpObjects( VOID );
  95. VOID
  96. DumpHandles( VOID );
  97. int
  98. GetDhSymbolicNameForAddress(
  99. IN HANDLE UniqueProcess,
  100. IN ULONG_PTR Address,
  101. OUT LPSTR Name,
  102. IN ULONG MaxNameLength
  103. );
  104. ////////////////////////////////////////////////////////////////////////////////////////////
  105. //
  106. // CtrlCHandler
  107. //
  108. // Function:
  109. //
  110. // This function is made the control-c handleris the -r option is used. This
  111. // allows a final snap to be taken when you are done without waiting for the next
  112. // iteration of the loop.
  113. BOOL
  114. CtrlCHandler(DWORD nCtrlType)
  115. {
  116. if (nCtrlType == CTRL_C_EVENT) {
  117. if (hCtrlCEvent) {
  118. SetEvent(hCtrlCEvent);
  119. return TRUE;
  120. }
  121. }
  122. return FALSE;
  123. }
  124. ////////////////////////////////////////////////////////////////////////////////////////////
  125. //
  126. // AdjustFileName
  127. //
  128. // Function:
  129. //
  130. // Adds the iteration number to the OutputFileName and increments the value
  131. // if fRepetitive has been set. Otherwise it returns
  132. //
  133. VOID
  134. AdjustFileName(VOID)
  135. {
  136. CHAR *pPeriod = NULL;
  137. if ((!fRepetitive)||(!strcmp(SavedFileName, "(stdout)"))||(dwCurrentIteration <= 0))
  138. return;
  139. pPeriod = strrchr(SavedFileName, '.');
  140. if (pPeriod) {
  141. pPeriod[0] = '\0';
  142. _snprintf(OutputFileName,
  143. sizeof(OutputFileName) - 1,
  144. "%s_%u.%s", SavedFileName, dwCurrentIteration, (pPeriod+1));
  145. pPeriod[0] = '.';
  146. }
  147. else
  148. _snprintf(OutputFileName,
  149. sizeof(OutputFileName) - 1,
  150. "%s_%u.dmp", SavedFileName, dwCurrentIteration);
  151. dwCurrentIteration++;
  152. }
  153. ////////////////////////////////////////////////////////////////////////////////////////////
  154. //
  155. // DumpOutputString
  156. //
  157. // Function:
  158. //
  159. // Writes 'DumpLine' to 'OutputFile' converting newlines to End-Of-Line sequences.
  160. // Closes OutputFile if there are any errors.
  161. //
  162. VOID
  163. DumpOutputString( VOID )
  164. {
  165. ULONG d;
  166. PCHAR s, s1;
  167. if (OutputFile == NULL) {
  168. return;
  169. }
  170. s = DumpLine;
  171. while (*s) {
  172. s1 = s;
  173. while (*s1 && *s1 != '\n') {
  174. s1 += 1;
  175. }
  176. if (s1 != s && !WriteFile( OutputFile, s, (ULONG)(s1 - s), &d, NULL )) {
  177. CloseHandle( OutputFile );
  178. OutputFile = NULL;
  179. return;
  180. }
  181. if (*s1 == '\n') {
  182. s1 += 1;
  183. if (!WriteFile( OutputFile, "\r\n", 2, &d, NULL )) {
  184. CloseHandle( OutputFile );
  185. OutputFile = NULL;
  186. return;
  187. }
  188. }
  189. s = s1;
  190. }
  191. }
  192. ////////////////////////////////////////////////////////////////////////////////////////////
  193. //
  194. // Usage
  195. //
  196. // Function: prints usage info to stderr and exits.
  197. //
  198. VOID
  199. Usage( VOID )
  200. {
  201. fputs( "Usage: DH [-p n | -p -1 | -p 0 [-k] [-o]] [-l] [-m] [-s] [-g] [-h] [-t] [r n][-f fileName]\n"
  202. "where: -p n - displays information about process with ClientId of n in DH_n.dmp\n"
  203. " -p -1 - displays information about Win32 Subsystem process in DH_WIN32.DMP.\n"
  204. " -l - displays information about locks.\n"
  205. " -m - displays information about module table.\n"
  206. " -s - displays summary information about heaps.\n"
  207. " -g - displays information about memory hogs.\n"
  208. " -h - displays information about heap entries for each heap.\n"
  209. " -t - displays information about heap tags for each heap.\n"
  210. " -b - displays information about stack back trace database.\n"
  211. " -i - ignore information about stack back trace database.\n"
  212. " -p 0 - displays information about kernel memory and objects in DH_SYS.DMP.\n"
  213. " -o - displays information about object handles (only valid with -p 0).\n"
  214. " -k - displays information about processes and threads (only valid with -p 0).\n"
  215. " -f fileName - specifies the name of the file to write the dump to.\n"
  216. " -# n - sets buffer size to n Meg\n"
  217. " -- specifies the dump output should be written to stdout.\n"
  218. " -r n - generates an log every n minutes with _# appended to filename\n"
  219. " -umdh umdh_options (use -umdh ? for help) \n"
  220. "\n"
  221. " Default flags for -p n are -s -g\n"
  222. " Default flags for -p 0 are -m -s -g -t -k -o\n"
  223. , stderr);
  224. exit( 1 );
  225. }
  226. ////////////////////////////////////////////////////////////////////////////////////////////
  227. //
  228. // InitializeSymbolPathEnvVar
  229. //
  230. //
  231. // Function: Sets _NT_SYMBOLS_PATH to point to where the symbols should be.
  232. //
  233. VOID
  234. InitializeSymbolPathEnvVar( VOID )
  235. {
  236. ULONG n;
  237. CHAR Buffer[ MAX_PATH ];
  238. n = GetEnvironmentVariable( "_NT_SYMBOL_PATH", Buffer, sizeof( Buffer ) );
  239. if (n == 0) {
  240. n = GetEnvironmentVariable( "SystemRoot", Buffer, sizeof( Buffer ) );
  241. if (n != 0) {
  242. //
  243. // Make sure the buffer is big enough for strcat
  244. //
  245. if (strlen(Buffer) + strlen("\\Symbols") >= sizeof(Buffer)) {
  246. fprintf( stderr, "DH: Huge WINDIR (%s), will exit\n", Buffer);
  247. exit( 3 );
  248. }
  249. strcat( Buffer, "\\Symbols" );
  250. SetEnvironmentVariable( "_NT_SYMBOL_PATH", Buffer );
  251. fprintf( stderr, "DH: Default _NT_SYMBOL_PATH to %s\n", Buffer );
  252. }
  253. }
  254. return;
  255. }
  256. ////////////////////////////////////////////////////////////////////////////////////////////
  257. PRTL_PROCESS_MODULES Modules;
  258. PRTL_PROCESS_BACKTRACES BackTraces;
  259. PUCHAR SymbolicInfoBase;
  260. PUCHAR SymbolicInfoCurrent;
  261. PUCHAR SymbolicInfoCommitNext;
  262. typedef struct _PROCESS_INFO {
  263. LIST_ENTRY Entry;
  264. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  265. PSYSTEM_THREAD_INFORMATION ThreadInfo[ 1 ];
  266. } PROCESS_INFO, *PPROCESS_INFO;
  267. LIST_ENTRY ProcessListHead;
  268. PSYSTEM_OBJECTTYPE_INFORMATION ObjectInformation;
  269. PSYSTEM_HANDLE_INFORMATION_EX HandleInformation;
  270. PSYSTEM_PROCESS_INFORMATION ProcessInformation;
  271. #define MAX_TYPE_NAMES 128
  272. PUNICODE_STRING *TypeNames;
  273. UNICODE_STRING UnknownTypeIndex;
  274. ////////////////////////////////////////////////////////////////////////////////////////////
  275. //
  276. // main
  277. //
  278. ////////////////////////////////////////////////////////////////////////////////////////////
  279. int __cdecl
  280. main(
  281. int argc,
  282. CHAR *argv[],
  283. CHAR *envp[]
  284. )
  285. {
  286. CHAR FileNameBuffer[ 32 ];
  287. CHAR *FilePart;
  288. CHAR *s;
  289. NTSTATUS Status;
  290. PRTL_DEBUG_INFORMATION p;
  291. ULONG QueryDebugProcessFlags;
  292. ULONG HeapNumber;
  293. PRTL_HEAP_INFORMATION HeapInfo;
  294. BOOLEAN WasEnabled;
  295. BOOL bSta;
  296. DWORD dwEventState = WAIT_TIMEOUT;
  297. SYSTEMTIME st;
  298. DWORD CompNameLength = MAX_COMPUTERNAME_LENGTH + 1;
  299. CHAR CompName[MAX_COMPUTERNAME_LENGTH + 1];
  300. //
  301. // Before anything else check if we need to dispatch the command line
  302. // to the umdh parser.
  303. //
  304. if (argc >= 2 && _stricmp (argv[1], "-umdh") == 0) {
  305. UmdhMain (argc - 1, argv + 1);
  306. }
  307. //
  308. // Boost our priority in case a service is higher than us.
  309. //
  310. //EnablePrivilege( SE_INC_BASE_PRIORITY_NAME );
  311. bSta= SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS );
  312. if( !bSta ) printf("SetPriorityClass failed: %d\n",GetLastError());
  313. bSta= SetThreadPriority( GetCurrentProcess(), THREAD_PRIORITY_HIGHEST );;
  314. if( !bSta ) printf("SetThreadPriority failed: %d\n",GetLastError());
  315. InitializeSymbolPathEnvVar();
  316. ProcessId = 0xFFFFFFFF;
  317. OutputFile = NULL;
  318. OutputFileName[ 0 ] = '\0';
  319. while (--argc) {
  320. s = *++argv;
  321. if (*s == '/' || *s == '-') {
  322. while (*++s) {
  323. switch (tolower(*s)) {
  324. case 'v':
  325. case 'V':
  326. fVerbose = TRUE;
  327. break;
  328. case 'i':
  329. case 'I':
  330. fIgnoreBackTraces = TRUE;
  331. break;
  332. case 'b':
  333. case 'B':
  334. fDumpBackTraces = TRUE;
  335. break;
  336. case 'g':
  337. case 'G':
  338. fDumpHeapHogs = TRUE;
  339. break;
  340. case 'h':
  341. case 'H':
  342. fDumpHeapEntries = TRUE;
  343. break;
  344. case 't':
  345. case 'T':
  346. fDumpHeapTags = TRUE;
  347. break;
  348. case 'l':
  349. case 'L':
  350. fDumpLocks = TRUE;
  351. break;
  352. case 'm':
  353. case 'M':
  354. fDumpModules = TRUE;
  355. break;
  356. case 'o':
  357. case 'O':
  358. fDumpSystemObjects = TRUE;
  359. break;
  360. case 'k':
  361. case 'K':
  362. fDumpSystemProcesses = TRUE;
  363. break;
  364. case 's':
  365. case 'S':
  366. fDumpHeapSummaries = TRUE;
  367. break;
  368. case 'p':
  369. case 'P':
  370. if (--argc) {
  371. ProcessId = atoi( *++argv );
  372. if (ProcessId == 0) {
  373. fDumpKernelModeInformation = TRUE;
  374. }
  375. }
  376. else {
  377. Usage();
  378. }
  379. break;
  380. case 'r':
  381. case 'R':
  382. if (--argc) {
  383. dwTimeInterval = atoi( *++argv );
  384. if (dwTimeInterval) {
  385. fRepetitive = TRUE;
  386. dwCurrentIteration = 1;
  387. if (dwTimeInterval > (MAXDWORD/60000))
  388. dwTimeInterval = (MAXDWORD/60000);
  389. hCtrlCEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  390. SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlCHandler, TRUE);
  391. }
  392. }
  393. else {
  394. Usage();
  395. }
  396. break;
  397. case '-':
  398. OutputFile = GetStdHandle( STD_OUTPUT_HANDLE );
  399. break;
  400. case 'f':
  401. case 'F':
  402. if (--argc) {
  403. strncpy( OutputFileName, *++argv, sizeof(OutputFileName) - 1 );
  404. }
  405. else {
  406. Usage();
  407. }
  408. break;
  409. case '#':
  410. if (--argc)
  411. {
  412. BufferSize = atoi( *++argv ) * 1024 * 1024 ;
  413. }
  414. else
  415. {
  416. Usage();
  417. }
  418. break;
  419. default:
  420. Usage();
  421. }
  422. }
  423. }
  424. else {
  425. Usage();
  426. }
  427. }
  428. if (!fDumpModules && !fDumpHeapSummaries &&
  429. !fDumpHeapTags && !fDumpHeapHogs && !fDumpLocks
  430. ) {
  431. if (fDumpKernelModeInformation) {
  432. if (!fDumpSystemObjects &&
  433. !fDumpSystemProcesses
  434. ) {
  435. fDumpModules = TRUE;
  436. fDumpHeapSummaries = TRUE;
  437. fDumpHeapTags = TRUE;
  438. fDumpHeapHogs = TRUE;
  439. fDumpSystemObjects = TRUE;
  440. fDumpSystemProcesses = TRUE;
  441. }
  442. }
  443. else {
  444. fDumpHeapSummaries = TRUE;
  445. fDumpHeapHogs = TRUE;
  446. }
  447. }
  448. if ((fDumpSystemObjects || fDumpSystemProcesses) && !fDumpKernelModeInformation) {
  449. Usage();
  450. }
  451. FileNameBuffer[sizeof(FileNameBuffer) - 1] = 0;
  452. if (OutputFile == NULL) {
  453. if (OutputFileName[ 0 ] == '\0') {
  454. if ( ProcessId == -1 ) {
  455. _snprintf( FileNameBuffer,
  456. sizeof(FileNameBuffer) - 1,
  457. "DH_win32.dmp" );
  458. }
  459. else if ( ProcessId == 0 ) {
  460. _snprintf( FileNameBuffer,
  461. sizeof(FileNameBuffer) - 1,
  462. "DH_sys.dmp" );
  463. }
  464. else {
  465. _snprintf( FileNameBuffer,
  466. sizeof(FileNameBuffer) - 1,
  467. "DH_%u.dmp", (USHORT)ProcessId );
  468. }
  469. GetFullPathName( FileNameBuffer,
  470. sizeof( OutputFileName ),
  471. OutputFileName,
  472. &FilePart
  473. );
  474. }
  475. }
  476. else {
  477. strncpy( OutputFileName, "(stdout)", sizeof(OutputFileName) - 1 );
  478. }
  479. if (fRepetitive) {
  480. strncpy(SavedFileName, OutputFileName, sizeof(SavedFileName) - 1);
  481. AdjustFileName();
  482. }
  483. Status= RtlAdjustPrivilege( SE_DEBUG_PRIVILEGE,
  484. TRUE, FALSE, &WasEnabled );
  485. if( !NT_SUCCESS(Status) ) {
  486. fprintf(stderr,"RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE) failed: %08x\n",Status);
  487. }
  488. //
  489. // Get the real process id for the windows sub-system
  490. //
  491. if (ProcessId == -1) {
  492. HANDLE Process;
  493. OBJECT_ATTRIBUTES ObjectAttributes;
  494. UNICODE_STRING UnicodeString;
  495. PROCESS_BASIC_INFORMATION BasicInfo;
  496. RtlInitUnicodeString( &UnicodeString, L"\\WindowsSS" );
  497. InitializeObjectAttributes( &ObjectAttributes,
  498. &UnicodeString,
  499. 0,
  500. NULL,
  501. NULL
  502. );
  503. Status = NtOpenProcess( &Process,
  504. PROCESS_ALL_ACCESS,
  505. &ObjectAttributes,
  506. NULL
  507. );
  508. if (NT_SUCCESS(Status)) {
  509. Status = NtQueryInformationProcess( Process,
  510. ProcessBasicInformation,
  511. (PVOID)&BasicInfo,
  512. sizeof(BasicInfo),
  513. NULL
  514. );
  515. NtClose( Process );
  516. }
  517. if (!NT_SUCCESS(Status)) {
  518. fprintf( stderr,"Unable to access Win32 server process - %08x", Status );
  519. if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
  520. fprintf( stderr,"\nUse GFLAGS.EXE to ""Enable debugging of Win32 Subsystem"" and reboot.\n" );
  521. }
  522. exit( 1 );
  523. }
  524. ProcessId = BasicInfo.UniqueProcessId;
  525. }
  526. //
  527. // Compute QueryDebugProcessFlags
  528. //
  529. QueryDebugProcessFlags = 0;
  530. if (fDumpModules) {
  531. QueryDebugProcessFlags |= RTL_QUERY_PROCESS_MODULES;
  532. }
  533. if (fDumpBackTraces || fDumpHeapHogs) {
  534. QueryDebugProcessFlags |= RTL_QUERY_PROCESS_BACKTRACES | RTL_QUERY_PROCESS_MODULES;
  535. }
  536. if (fDumpHeapSummaries) {
  537. QueryDebugProcessFlags |= RTL_QUERY_PROCESS_HEAP_SUMMARY;
  538. }
  539. if (fDumpHeapTags) {
  540. QueryDebugProcessFlags |= RTL_QUERY_PROCESS_HEAP_TAGS;
  541. }
  542. if (fDumpHeapEntries || fDumpHeapHogs) {
  543. QueryDebugProcessFlags |= RTL_QUERY_PROCESS_HEAP_ENTRIES;
  544. }
  545. if (fDumpLocks) {
  546. QueryDebugProcessFlags |= RTL_QUERY_PROCESS_LOCKS;
  547. }
  548. // Starting the main loop that does most of the work. This will only
  549. // execute once unless fRepetitive is set
  550. do {
  551. //
  552. // Open the output file
  553. //
  554. fprintf( stderr, "DH: Writing dump output to %s", OutputFileName );
  555. if (OutputFile == NULL) {
  556. OutputFile = CreateFile( OutputFileName,
  557. GENERIC_WRITE,
  558. FILE_SHARE_READ | FILE_SHARE_WRITE,
  559. NULL,
  560. CREATE_ALWAYS,
  561. 0,
  562. NULL
  563. );
  564. if ( OutputFile == INVALID_HANDLE_VALUE ) {
  565. fprintf( stderr, " - unable to open, error == %u\n", GetLastError() );
  566. exit( 1 );
  567. }
  568. }
  569. fprintf( stderr, "\n" );
  570. //Output a Timestamp to the first line of the file
  571. GetLocalTime(&st);
  572. GetComputerName(CompName, &CompNameLength);
  573. _snprintf( DumpLine, sizeof(DumpLine) - 1,
  574. "DH: Logtime %02u/%02u/%4u-%02u:%02u - Machine=%s - PID=%u\n", st.wMonth,
  575. st.wDay, st.wYear, (st.wHour <= 12) ? st.wHour : (st.wHour - 12), st.wMinute,
  576. CompName, ProcessId);
  577. DumpOutputString();
  578. if (fDumpKernelModeInformation) {
  579. p = RtlQuerySystemDebugInformation( QueryDebugProcessFlags );
  580. if (p == NULL) {
  581. fprintf( stderr, "DH: Unable to query kernel mode information.\n" );
  582. exit( 1 );
  583. }
  584. Status = STATUS_SUCCESS;
  585. }
  586. else {
  587. p = RtlCreateQueryDebugBuffer( BufferSize, FALSE );
  588. if (p == NULL) {
  589. //
  590. // That would be very bad...
  591. //
  592. fprintf( stderr, "DH: Unable to create query debug buffer.\n" );
  593. exit( 2 );
  594. }
  595. printf("RtlCreateQueryDebugBuffer returns: %p\n",p);
  596. Status = RtlQueryProcessDebugInformation( (HANDLE)ProcessId,
  597. QueryDebugProcessFlags,
  598. p
  599. );
  600. if (NT_SUCCESS( Status )) {
  601. printf("RtpQueryProcessDebugInformation\n");
  602. printf(" ProcessId: %d ProcessFlags: %08x Status %08x\n",
  603. ProcessId, QueryDebugProcessFlags, Status );
  604. if ((fDumpBackTraces || fDumpHeapHogs) && p->BackTraces == NULL) {
  605. printf("p->BackTraces: %p\n",p->BackTraces);
  606. fputs( "DH: Unable to query stack back trace information\n"
  607. " Be sure target process was launched with the\n"
  608. " 'Create user mode stack trace DB' enabled\n"
  609. " Use the GFLAGS.EXE application to do this.\n"
  610. , stderr);
  611. }
  612. if (fDumpHeapTags) {
  613. HeapInfo = &p->Heaps->Heaps[ 0 ];
  614. for (HeapNumber = 0; HeapNumber < p->Heaps->NumberOfHeaps; HeapNumber++) {
  615. if (HeapInfo->Tags != NULL && HeapInfo->NumberOfTags != 0) {
  616. break;
  617. }
  618. }
  619. if (HeapNumber == p->Heaps->NumberOfHeaps) {
  620. fputs( "DH: Unable to query heap tag information\n"
  621. " Be sure target process was launched with the\n"
  622. " 'Enable heap tagging' option enabled.\n"
  623. " Use the GFLAGS.EXE application to do this.\n"
  624. , stderr);
  625. }
  626. }
  627. }
  628. else {
  629. fprintf(stderr,"RtlQueryProcessDebugInformation failed: %08x\n",Status);
  630. }
  631. }
  632. if (NT_SUCCESS( Status )) {
  633. if (!fIgnoreBackTraces &&
  634. p->Modules != NULL &&
  635. LoadSymbolsForModules( p->Modules ) &&
  636. p->BackTraces != NULL
  637. ) {
  638. ComputeSymbolicBackTraces( p->BackTraces );
  639. }
  640. if (fDumpModules) {
  641. DumpModules( p->Modules );
  642. }
  643. if (!fIgnoreBackTraces && fDumpBackTraces) {
  644. DumpBackTraces();
  645. }
  646. if (p->Heaps) {
  647. DumpHeaps( p->Heaps, fDumpHeapSummaries, fDumpHeapHogs, fDumpHeapTags, fDumpHeapEntries );
  648. }
  649. if (fDumpLocks) {
  650. DumpLocks( p->Locks );
  651. }
  652. if (fDumpSystemObjects) {
  653. DumpObjects();
  654. DumpHandles();
  655. }
  656. if (fDumpSystemProcesses) {
  657. DumpSystemProcesses();
  658. }
  659. }
  660. else {
  661. fprintf( stderr, "Failed to query process, %x\n", Status );
  662. }
  663. RtlDestroyQueryDebugBuffer( p );
  664. // Are we in repetitive mode
  665. if (fRepetitive) {
  666. if (hCtrlCEvent)
  667. dwEventState = WaitForSingleObject(hCtrlCEvent,0);
  668. if (dwEventState == WAIT_OBJECT_0)
  669. fRepetitive = FALSE;
  670. else {
  671. // Lets let the user know we are not hung
  672. GetLocalTime(&st);
  673. printf("Starting at %u:%02u - Sleeping for %u Minute(s)\n",
  674. (st.wHour <= 12) ? st.wHour : (st.wHour - 12), st.wMinute, dwTimeInterval);
  675. // lets sleep for our time interval unless signaled with a ctrl-c
  676. if (hCtrlCEvent)
  677. dwEventState = WaitForSingleObject(hCtrlCEvent,(dwTimeInterval * 60000));
  678. else
  679. Sleep(dwTimeInterval * 60000);
  680. // Don't want to close our handle to stdout
  681. if (strcmp(SavedFileName, "(stdout)")){
  682. CloseHandle( OutputFile );
  683. OutputFile = NULL;
  684. }
  685. // Set up for the next iteration.
  686. AdjustFileName();
  687. //Adjust the pointers to this nasty global memory blob
  688. VirtualFree(SymbolicInfoBase, 4096*4096, MEM_DECOMMIT);
  689. SymbolicInfoCurrent = SymbolicInfoBase;
  690. SymbolicInfoCommitNext = SymbolicInfoBase;
  691. }
  692. }
  693. } while (fRepetitive); //do loop
  694. CloseHandle( OutputFile );
  695. VirtualFree(SymbolicInfoBase, 0, MEM_RELEASE);
  696. if (hCtrlCEvent)
  697. CloseHandle(hCtrlCEvent);
  698. return 0;
  699. }
  700. ////////////////////////////////////////////////////////////////////////////////////////////
  701. BOOL
  702. SymbolCallbackFunction(
  703. HANDLE hProcess,
  704. ULONG ActionCode,
  705. #ifdef _WIN64
  706. ULONG_PTR CallbackData,
  707. ULONG_PTR UserContext
  708. #else
  709. PVOID CallbackData,
  710. PVOID UserContext
  711. #endif
  712. )
  713. {
  714. PIMAGEHLP_DEFERRED_SYMBOL_LOAD idsl;
  715. idsl = (PIMAGEHLP_DEFERRED_SYMBOL_LOAD) CallbackData;
  716. switch( ActionCode ) {
  717. case CBA_DEFERRED_SYMBOL_LOAD_START:
  718. _strlwr( idsl->FileName );
  719. fprintf( stderr, "Loading symbols for 0x%08x %16s - ",
  720. idsl->BaseOfImage,
  721. idsl->FileName
  722. );
  723. fflush( stderr );
  724. return TRUE;
  725. case CBA_DEFERRED_SYMBOL_LOAD_FAILURE:
  726. fprintf( stderr, "*** Error: could not load symbols\n");
  727. fflush( stderr );
  728. return TRUE;
  729. case CBA_DEFERRED_SYMBOL_LOAD_COMPLETE:
  730. fprintf( stderr, "done\n" );
  731. fflush( stderr );
  732. return TRUE;
  733. case CBA_SYMBOLS_UNLOADED:
  734. fprintf( stderr, "Symbols unloaded for 0x%08x %s\n",
  735. idsl->BaseOfImage,
  736. idsl->FileName
  737. );
  738. fflush( stderr );
  739. return TRUE;
  740. default:
  741. return FALSE;
  742. }
  743. return FALSE;
  744. }
  745. ////////////////////////////////////////////////////////////////////////////////////////////
  746. #define MAX_SYMNAME_SIZE 1024
  747. #define SYM_BUFFER_SIZE (sizeof(IMAGEHLP_SYMBOL)+MAX_SYMNAME_SIZE)
  748. CHAR symBuffer[SYM_BUFFER_SIZE];
  749. PIMAGEHLP_SYMBOL sym;
  750. PIMAGEHLP_SYMBOL sym = (PIMAGEHLP_SYMBOL) symBuffer;
  751. BOOLEAN
  752. LoadSymbolsForModules(
  753. PRTL_PROCESS_MODULES Modules1
  754. )
  755. {
  756. PRTL_PROCESS_MODULE_INFORMATION ModuleInfo;
  757. ULONG ModuleNumber;
  758. PVOID MaxUserModeAddress;
  759. SymSetOptions( SYMOPT_CASE_INSENSITIVE | SYMOPT_UNDNAME | SYMOPT_NO_CPP );
  760. sym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
  761. sym->MaxNameLength = MAX_SYMNAME_SIZE;
  762. SymInitialize( (HANDLE)ProcessId, NULL, FALSE );
  763. SymRegisterCallback( (HANDLE)ProcessId, SymbolCallbackFunction, 0 );
  764. if (!NT_SUCCESS(NtQuerySystemInformation(SystemRangeStartInformation,
  765. &MaxUserModeAddress,
  766. sizeof(MaxUserModeAddress),
  767. NULL))) {
  768. // assume usermode is the low half of the address space
  769. MaxUserModeAddress = (PVOID)MAXLONG_PTR;
  770. }
  771. Modules = Modules1;
  772. ModuleInfo = &Modules->Modules[ 0 ];
  773. for (ModuleNumber=0; ModuleNumber<Modules->NumberOfModules; ModuleNumber++) {
  774. if (!fDumpKernelModeInformation || ModuleInfo->ImageBase >= MaxUserModeAddress) {
  775. SymLoadModule( (HANDLE)ProcessId,
  776. NULL,
  777. ModuleInfo->FullPathName,
  778. NULL,
  779. (ULONG_PTR)ModuleInfo->ImageBase,
  780. ModuleInfo->ImageSize
  781. );
  782. }
  783. ModuleInfo += 1;
  784. }
  785. return TRUE;
  786. }
  787. ////////////////////////////////////////////////////////////////////////////////////////////
  788. //
  789. // BogdanA - 02/19/02 : no one uses it ? Will comment out...
  790. //
  791. #if 0
  792. static CHAR DllNameBuffer[ MAX_PATH ];
  793. PCHAR
  794. FindDllHandleName(
  795. PVOID DllHandle
  796. )
  797. {
  798. PRTL_PROCESS_MODULE_INFORMATION ModuleInfo;
  799. LPSTR DllName;
  800. ULONG ModuleNumber;
  801. ModuleInfo = &Modules->Modules[ 0 ];
  802. for (ModuleNumber=0; ModuleNumber<Modules->NumberOfModules; ModuleNumber++) {
  803. if (ModuleInfo->ImageBase == DllHandle) {
  804. strncpy( DllNameBuffer,
  805. &ModuleInfo->FullPathName[ ModuleInfo->OffsetToFileName ],
  806. sizeof(OutputFileName) - 1 );
  807. if ((DllName = strchr( DllNameBuffer, '.' )) != NULL) {
  808. *DllName = '\0';
  809. }
  810. return DllNameBuffer;
  811. }
  812. ModuleInfo += 1;
  813. }
  814. return "UNKNOWN";
  815. }
  816. #endif
  817. ////////////////////////////////////////////////////////////////////////////////////////////
  818. PUCHAR
  819. SaveSymbolicBackTrace(
  820. IN ULONG Depth,
  821. IN PVOID BackTrace[]
  822. )
  823. {
  824. NTSTATUS Status;
  825. ULONG i, FileNameLength, SymbolOffset;
  826. PCHAR s, SymbolicBackTrace;
  827. int result;
  828. if (Depth == 0) {
  829. return NULL;
  830. }
  831. if (SymbolicInfoBase == NULL) {
  832. SymbolicInfoBase = (PUCHAR)VirtualAlloc( NULL,
  833. 4096 * 4096,
  834. MEM_RESERVE,
  835. PAGE_READWRITE
  836. );
  837. if (SymbolicInfoBase == NULL) {
  838. fprintf(stderr,"DH: VirtualAlloc(4096*4096...) failed: GetLastError()= %d\n",GetLastError());
  839. return NULL;
  840. }
  841. SymbolicInfoCurrent = SymbolicInfoBase;
  842. SymbolicInfoCommitNext = SymbolicInfoBase;
  843. }
  844. i = 4096;
  845. if ((SymbolicInfoCurrent + i - 1) > SymbolicInfoCommitNext) {
  846. if (!VirtualAlloc( SymbolicInfoCommitNext,
  847. i,
  848. MEM_COMMIT,
  849. PAGE_READWRITE
  850. )
  851. ) {
  852. fprintf( stderr, "DH: Exceeded 16MB of space for symbolic stack back traces.\n" );
  853. fprintf( stderr, "DH: virtualalloc(%p,%d...)\n",SymbolicInfoCommitNext,i);
  854. return NULL;
  855. }
  856. SymbolicInfoCommitNext += i;
  857. }
  858. s = SymbolicInfoCurrent;
  859. SymbolicBackTrace = s;
  860. for (i=0; i<Depth; i++) {
  861. if (BackTrace[ i ] == 0) {
  862. break;
  863. }
  864. //
  865. // Make sure we have MAX_PATH + 1 of storage left in the buffer
  866. // (+ 1 for the final terminator)
  867. //
  868. if (s + MAX_PATH + 1 > SymbolicInfoCommitNext) {
  869. fprintf( stderr, "DH: somehow we don't have enough commited memory for stack traces\n");
  870. break;
  871. }
  872. result = GetDhSymbolicNameForAddress( (HANDLE)ProcessId, (ULONG_PTR)BackTrace[ i ], s, MAX_PATH );
  873. if (result < 0) {
  874. //
  875. // Oops, we could not write as many characters as we wanted.
  876. // That is fine, we will have some truncated strings. Oh well...
  877. // Just skip MAX_PATH, make sure we terminate the string and move forward...
  878. //
  879. s += MAX_PATH;
  880. } else {
  881. s += result;
  882. }
  883. *s++ = '\0';
  884. }
  885. *s++ = '\0';
  886. SymbolicInfoCurrent = s;
  887. return SymbolicBackTrace;
  888. }
  889. ////////////////////////////////////////////////////////////////////////////////////////////
  890. BOOLEAN
  891. ComputeSymbolicBackTraces(
  892. PRTL_PROCESS_BACKTRACES BackTraces1
  893. )
  894. {
  895. PRTL_PROCESS_BACKTRACE_INFORMATION BackTraceInfo;
  896. ULONG BackTraceIndex, NumberOfBackTraces;
  897. BackTraces = BackTraces1;
  898. NumberOfBackTraces = BackTraces->NumberOfBackTraces;
  899. BackTraceInfo = &BackTraces->BackTraces[ 0 ];
  900. BackTraceIndex = 0;
  901. while (NumberOfBackTraces--) {
  902. if (!(BackTraceIndex++ % 50)) {
  903. printf( "Getting symbols for Stack Back Trace %05u\r", BackTraceIndex );
  904. }
  905. BackTraceInfo->SymbolicBackTrace = SaveSymbolicBackTrace( BackTraceInfo->Depth,
  906. &BackTraceInfo->BackTrace[ 0 ]
  907. );
  908. BackTraceInfo += 1;
  909. }
  910. return TRUE;
  911. }
  912. ////////////////////////////////////////////////////////////////////////////////////////////
  913. PRTL_PROCESS_BACKTRACE_INFORMATION
  914. FindBackTrace(
  915. IN ULONG BackTraceIndex
  916. )
  917. {
  918. PRTL_PROCESS_BACKTRACE_INFORMATION BackTraceInfo;
  919. if (!BackTraceIndex ||
  920. BackTraces == NULL ||
  921. BackTraceIndex >= BackTraces->NumberOfBackTraces
  922. ) {
  923. return( NULL );
  924. }
  925. return &BackTraces->BackTraces[ BackTraceIndex-1 ];
  926. }
  927. ////////////////////////////////////////////////////////////////////////////////////////////
  928. VOID
  929. FormatHeapHeader(
  930. PRTL_HEAP_INFORMATION HeapInfo,
  931. PCHAR Title
  932. )
  933. {
  934. CHAR TempBuffer[ 64 ];
  935. PCHAR s;
  936. TempBuffer[sizeof(TempBuffer) - 1] = 0;
  937. if (HeapInfo->BaseAddress == (PVOID)IntToPtr(SystemPagedPoolInformation)) {
  938. s = "Paged Pool";
  939. }
  940. else
  941. if (HeapInfo->BaseAddress == (PVOID)IntToPtr(SystemNonPagedPoolInformation)) {
  942. s = "NonPaged Pool";
  943. }
  944. else {
  945. _snprintf( TempBuffer, sizeof(TempBuffer) - 1, "Heap %p", HeapInfo->BaseAddress );
  946. s = TempBuffer;
  947. }
  948. _snprintf( DumpLine, sizeof(DumpLine) - 1,
  949. "\n\n*********** %s %s ********************\n\n", s, Title );
  950. DumpOutputString();
  951. }
  952. ////////////////////////////////////////////////////////////////////////////////////////////
  953. VOID
  954. DumpModules(
  955. PRTL_PROCESS_MODULES Modules
  956. )
  957. {
  958. PRTL_PROCESS_MODULE_INFORMATION ModuleInfo;
  959. ULONG ModuleNumber;
  960. if (fVerbose) {
  961. fprintf( stderr, "DH: Dumping module information.\n" );
  962. }
  963. ModuleInfo = &Modules->Modules[ 0 ];
  964. _snprintf( DumpLine, sizeof(DumpLine) - 1, "\n\n*********** Module Information ********************\n\n" );
  965. DumpOutputString();
  966. _snprintf( DumpLine, sizeof(DumpLine) - 1, "Number of loaded modules: %u\n", Modules->NumberOfModules );
  967. DumpOutputString();
  968. ModuleNumber = 0;
  969. while (ModuleNumber++ < Modules->NumberOfModules) {
  970. _snprintf( DumpLine, sizeof(DumpLine) - 1, "Module%02u (%02u,%02u,%02u): [%p .. %p] %s\n",
  971. ModuleNumber,
  972. (ULONG)ModuleInfo->LoadOrderIndex,
  973. (ULONG)ModuleInfo->InitOrderIndex,
  974. (ULONG)ModuleInfo->LoadCount,
  975. ModuleInfo->ImageBase,
  976. (PVOID)((ULONG_PTR)ModuleInfo->ImageBase + ModuleInfo->ImageSize - 1),
  977. ModuleInfo->FullPathName
  978. );
  979. DumpOutputString();
  980. ModuleInfo++;
  981. }
  982. return;
  983. }
  984. ////////////////////////////////////////////////////////////////////////////////////////////
  985. VOID
  986. DumpBackTraces( VOID )
  987. {
  988. PRTL_PROCESS_BACKTRACE_INFORMATION BackTraceInfo;
  989. ULONG BackTraceIndex;
  990. CHAR *s;
  991. if (BackTraces == NULL) {
  992. return;
  993. }
  994. if (fVerbose) {
  995. fprintf( stderr, "DH: Dumping back trace information.\n" );
  996. }
  997. _snprintf( DumpLine, sizeof(DumpLine) - 1, "\n\n*********** BackTrace Information ********************\n\n" );
  998. DumpOutputString();
  999. _snprintf( DumpLine, sizeof(DumpLine) - 1, "Number of back traces: %u Looked Up Count: %u\n",
  1000. BackTraces->NumberOfBackTraces - 1,
  1001. BackTraces->NumberOfBackTraceLookups
  1002. );
  1003. DumpOutputString();
  1004. _snprintf( DumpLine, sizeof(DumpLine) - 1, "Reserved Memory: %08x Committed Memory: %08x\n",
  1005. BackTraces->ReservedMemory,
  1006. BackTraces->CommittedMemory
  1007. );
  1008. DumpOutputString();
  1009. BackTraceInfo = BackTraces->BackTraces;
  1010. for (BackTraceIndex=0; BackTraceIndex<BackTraces->NumberOfBackTraces; BackTraceIndex++) {
  1011. _snprintf( DumpLine, sizeof(DumpLine) - 1, "BackTrace%05lu\n", BackTraceInfo->Index );
  1012. DumpOutputString();
  1013. if (BackTraceInfo->SymbolicBackTrace == NULL) {
  1014. BackTraceInfo->SymbolicBackTrace = SaveSymbolicBackTrace( BackTraceInfo->Depth,
  1015. &BackTraceInfo->BackTrace[ 0 ]
  1016. );
  1017. }
  1018. if (s = BackTraceInfo->SymbolicBackTrace) {
  1019. while (*s) {
  1020. _snprintf( DumpLine, sizeof(DumpLine) - 1, " %s\n", s );
  1021. DumpOutputString();
  1022. while (*s++) {
  1023. }
  1024. }
  1025. }
  1026. BackTraceInfo += 1;
  1027. }
  1028. }
  1029. ////////////////////////////////////////////////////////////////////////////////////////////
  1030. typedef struct _VA_CHUNK {
  1031. ULONG_PTR Base;
  1032. ULONG_PTR End;
  1033. ULONG_PTR Committed;
  1034. } VA_CHUNK, *PVA_CHUNK;
  1035. VOID
  1036. DumpHeapSummary(
  1037. PRTL_HEAP_INFORMATION HeapInfo
  1038. )
  1039. {
  1040. PRTL_PROCESS_BACKTRACE_INFORMATION BackTraceInfo;
  1041. PUCHAR s;
  1042. PRTL_HEAP_ENTRY p;
  1043. PCHAR HeapEntryAddress;
  1044. ULONG i, HeapEntryNumber;
  1045. SIZE_T AddressSpaceUsed;
  1046. ULONG NumberOfChunks;
  1047. ULONG MaxNumberOfChunks;
  1048. PVA_CHUNK Chunks, NewChunks;
  1049. MaxNumberOfChunks = 0;
  1050. NumberOfChunks = 0;
  1051. Chunks = NULL;
  1052. p = HeapInfo->Entries;
  1053. if (p != NULL && HeapInfo->NumberOfEntries != 0) {
  1054. HeapEntryAddress = NULL;
  1055. for (HeapEntryNumber=0; HeapEntryNumber<HeapInfo->NumberOfEntries; HeapEntryNumber++) {
  1056. if (p->Flags != 0xFF && p->Flags & RTL_HEAP_SEGMENT) {
  1057. if (NumberOfChunks == MaxNumberOfChunks) {
  1058. MaxNumberOfChunks += 16;
  1059. NewChunks = RtlAllocateHeap( RtlProcessHeap(),
  1060. HEAP_ZERO_MEMORY,
  1061. MaxNumberOfChunks * sizeof( VA_CHUNK )
  1062. );
  1063. if (Chunks != NULL) {
  1064. if (NewChunks != NULL) {
  1065. RtlMoveMemory( NewChunks, Chunks, NumberOfChunks * sizeof( VA_CHUNK ) );
  1066. }
  1067. RtlFreeHeap( RtlProcessHeap(), 0, Chunks );
  1068. }
  1069. Chunks = NewChunks;
  1070. if (Chunks == NULL) {
  1071. NumberOfChunks = 0;
  1072. break;
  1073. }
  1074. }
  1075. HeapEntryAddress = (PCHAR)p->u.s2.FirstBlock;
  1076. Chunks[ NumberOfChunks ].Base = (ULONG_PTR)HeapEntryAddress & ~(4096-1);
  1077. if (((ULONG_PTR)HeapEntryAddress - (ULONG_PTR)Chunks[ NumberOfChunks ].Base) < 32) {
  1078. HeapEntryAddress = (PCHAR)Chunks[ NumberOfChunks ].Base;
  1079. }
  1080. Chunks[ NumberOfChunks ].Committed = p->u.s2.CommittedSize;
  1081. NumberOfChunks += 1;
  1082. }
  1083. else {
  1084. HeapEntryAddress += p->Size;
  1085. if (NumberOfChunks > 0) {
  1086. Chunks[ NumberOfChunks-1 ].End = (ULONG_PTR)HeapEntryAddress;
  1087. }
  1088. }
  1089. p += 1;
  1090. }
  1091. }
  1092. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Flags: %08x\n", HeapInfo->Flags );
  1093. DumpOutputString();
  1094. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Number Of Entries: %u\n", HeapInfo->NumberOfEntries );
  1095. DumpOutputString();
  1096. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Number Of Tags: %u\n", HeapInfo->NumberOfTags );
  1097. DumpOutputString();
  1098. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Bytes Allocated: %08x\n", HeapInfo->BytesAllocated );
  1099. DumpOutputString();
  1100. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Bytes Committed: %08x\n", HeapInfo->BytesCommitted );
  1101. DumpOutputString();
  1102. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Total FreeSpace: %08x\n", HeapInfo->BytesCommitted -
  1103. HeapInfo->BytesAllocated );
  1104. DumpOutputString();
  1105. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Number of Virtual Address chunks used: %u\n", NumberOfChunks );
  1106. DumpOutputString();
  1107. AddressSpaceUsed = 0;
  1108. for (i=0; i<NumberOfChunks; i++) {
  1109. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Chunk[ %2u ]: [%08x .. %08x) %08x committed\n",
  1110. i+1,
  1111. Chunks[i].Base,
  1112. Chunks[i].End,
  1113. Chunks[i].Committed
  1114. );
  1115. DumpOutputString();
  1116. AddressSpaceUsed += (Chunks[i].End - Chunks[i].Base);
  1117. }
  1118. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Address Space Used: %08x\n", AddressSpaceUsed );
  1119. DumpOutputString();
  1120. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Entry Overhead: %u\n", HeapInfo->EntryOverhead );
  1121. DumpOutputString();
  1122. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Creator: (Backtrace%05lu)\n", HeapInfo->CreatorBackTraceIndex );
  1123. DumpOutputString();
  1124. BackTraceInfo = FindBackTrace( HeapInfo->CreatorBackTraceIndex );
  1125. if (BackTraceInfo != NULL && (s = BackTraceInfo->SymbolicBackTrace)) {
  1126. while (*s) {
  1127. _snprintf( DumpLine, sizeof(DumpLine) - 1, " %s\n", s );
  1128. DumpOutputString();
  1129. while (*s++) {
  1130. }
  1131. }
  1132. }
  1133. return;
  1134. }
  1135. ////////////////////////////////////////////////////////////////////////////////////////////
  1136. __inline int DiffSizeT(SIZE_T s1, SIZE_T s2)
  1137. {
  1138. if (s1 == s2)
  1139. return 0;
  1140. if (s1 > s2)
  1141. return -1;
  1142. else
  1143. return 1;
  1144. }
  1145. ////////////////////////////////////////////////////////////////////////////////////////////
  1146. int
  1147. __cdecl
  1148. CmpTagsRoutine(
  1149. const void *Element1,
  1150. const void *Element2
  1151. )
  1152. {
  1153. return( DiffSizeT((*(PRTL_HEAP_TAG *)Element2)->BytesAllocated,
  1154. (*(PRTL_HEAP_TAG *)Element1)->BytesAllocated)
  1155. );
  1156. }
  1157. ////////////////////////////////////////////////////////////////////////////////////////////
  1158. PRTL_HEAP_TAG
  1159. FindTagEntry(
  1160. PRTL_HEAP_INFORMATION HeapInfo,
  1161. ULONG TagIndex
  1162. )
  1163. {
  1164. if (TagIndex == 0 || (TagIndex & ~HEAP_PSEUDO_TAG_FLAG) >= HeapInfo->NumberOfTags) {
  1165. return NULL;
  1166. }
  1167. else {
  1168. if (TagIndex & HEAP_PSEUDO_TAG_FLAG) {
  1169. return HeapInfo->Tags + (TagIndex & ~HEAP_PSEUDO_TAG_FLAG);
  1170. }
  1171. else {
  1172. return HeapInfo->Tags + HeapInfo->NumberOfPseudoTags + TagIndex;
  1173. }
  1174. }
  1175. }
  1176. ////////////////////////////////////////////////////////////////////////////////////////////
  1177. VOID
  1178. DumpHeapTags(
  1179. PRTL_HEAP_INFORMATION HeapInfo
  1180. )
  1181. {
  1182. PRTL_HEAP_TAG *TagEntries, TagEntry;
  1183. ULONG TagIndex;
  1184. PUCHAR s;
  1185. UCHAR HeapName[ 64 ];
  1186. if (HeapInfo->Tags == NULL || HeapInfo->NumberOfTags == 0) {
  1187. return;
  1188. }
  1189. TagEntries = RtlAllocateHeap( RtlProcessHeap(),
  1190. HEAP_ZERO_MEMORY,
  1191. HeapInfo->NumberOfTags * sizeof( PRTL_HEAP_TAG )
  1192. );
  1193. if (TagEntries == NULL) {
  1194. fprintf(stderr,"DH: RtlAllocateHeap failed at %d\n",__LINE__ );
  1195. return;
  1196. }
  1197. for (TagIndex=1; TagIndex<HeapInfo->NumberOfTags; TagIndex++) {
  1198. TagEntries[ TagIndex-1 ] = &HeapInfo->Tags[ TagIndex ];
  1199. }
  1200. qsort( (void *)TagEntries,
  1201. HeapInfo->NumberOfTags - 1,
  1202. sizeof( PRTL_HEAP_TAG ),
  1203. CmpTagsRoutine
  1204. );
  1205. TagEntry = &HeapInfo->Tags[ HeapInfo->NumberOfPseudoTags ];
  1206. HeapName[sizeof(HeapName) - 1] = 0;
  1207. if (HeapInfo->NumberOfTags > HeapInfo->NumberOfPseudoTags &&
  1208. TagEntry->TagName[ 0 ] != UNICODE_NULL
  1209. ) {
  1210. _snprintf( HeapName,
  1211. sizeof(HeapName) - 1,
  1212. "Tags for %ws heap", TagEntry->TagName );
  1213. }
  1214. else {
  1215. _snprintf( HeapName,
  1216. sizeof(HeapName) - 1,
  1217. "Tags" );
  1218. }
  1219. FormatHeapHeader( HeapInfo, HeapName );
  1220. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Allocs Frees Diff Bytes Tag\n" );
  1221. DumpOutputString();
  1222. for (TagIndex=1; TagIndex<(HeapInfo->NumberOfTags-1); TagIndex++) {
  1223. TagEntry = TagEntries[ TagIndex ];
  1224. if (TagEntry->BytesAllocated != 0) {
  1225. _snprintf( DumpLine, sizeof(DumpLine) - 1, " %08x %08x %08x %08x %ws\n",
  1226. TagEntry->NumberOfAllocations,
  1227. TagEntry->NumberOfFrees,
  1228. TagEntry->NumberOfAllocations - TagEntry->NumberOfFrees,
  1229. TagEntry->BytesAllocated,
  1230. TagEntry->TagName
  1231. );
  1232. DumpOutputString();
  1233. }
  1234. }
  1235. RtlFreeHeap( RtlProcessHeap(), 0, TagEntries );
  1236. return;
  1237. }
  1238. ////////////////////////////////////////////////////////////////////////////////////////////
  1239. typedef struct _HEAP_CALLER {
  1240. SIZE_T TotalAllocated;
  1241. USHORT NumberOfAllocations;
  1242. USHORT CallerBackTraceIndex;
  1243. PRTL_HEAP_TAG TagEntry;
  1244. } HEAP_CALLER, *PHEAP_CALLER;
  1245. int
  1246. __cdecl
  1247. CmpCallerRoutine(
  1248. const void *Element1,
  1249. const void *Element2
  1250. )
  1251. {
  1252. return( DiffSizeT(((PHEAP_CALLER)Element2)->TotalAllocated,
  1253. ((PHEAP_CALLER)Element1)->TotalAllocated)
  1254. );
  1255. }
  1256. ////////////////////////////////////////////////////////////////////////////////////////////
  1257. VOID
  1258. DumpHeapHogs(
  1259. PRTL_HEAP_INFORMATION HeapInfo
  1260. )
  1261. {
  1262. PRTL_PROCESS_BACKTRACE_INFORMATION BackTraceInfo;
  1263. PUCHAR s;
  1264. ULONG BackTraceNumber, HeapEntryNumber;
  1265. USHORT TagIndex;
  1266. PRTL_HEAP_ENTRY p;
  1267. PHEAP_CALLER HogList;
  1268. if (BackTraces == NULL) {
  1269. return;
  1270. }
  1271. HogList = (PHEAP_CALLER)VirtualAlloc( NULL,
  1272. BackTraces->NumberOfBackTraces *
  1273. sizeof( HEAP_CALLER ),
  1274. MEM_COMMIT,
  1275. PAGE_READWRITE
  1276. );
  1277. if (HogList == NULL) {
  1278. fprintf(stderr,"DH: VirtualAlloc failed at %d size: %d\n",__LINE__,
  1279. BackTraces->NumberOfBackTraces * sizeof( HEAP_CALLER ) );
  1280. return;
  1281. }
  1282. p = HeapInfo->Entries;
  1283. if (p == NULL) {
  1284. VirtualFree( HogList, 0, MEM_RELEASE );
  1285. return;
  1286. }
  1287. for (HeapEntryNumber=0; HeapEntryNumber<HeapInfo->NumberOfEntries; HeapEntryNumber++) {
  1288. if (p->Flags & RTL_HEAP_BUSY) {
  1289. if (p->AllocatorBackTraceIndex >= BackTraces->NumberOfBackTraces) {
  1290. p->AllocatorBackTraceIndex = 0;
  1291. }
  1292. HogList[ p->AllocatorBackTraceIndex ].NumberOfAllocations++;
  1293. HogList[ p->AllocatorBackTraceIndex ].TotalAllocated += p->Size;
  1294. if (p->u.s1.Tag != 0) {
  1295. HogList[ p->AllocatorBackTraceIndex ].TagEntry = FindTagEntry( HeapInfo, p->u.s1.Tag );
  1296. }
  1297. else
  1298. if (HeapInfo->NumberOfPseudoTags != 0) {
  1299. TagIndex = HEAP_PSEUDO_TAG_FLAG;
  1300. if (p->Size < (HeapInfo->NumberOfPseudoTags * HeapInfo->PseudoTagGranularity)) {
  1301. TagIndex |= (p->Size / HeapInfo->PseudoTagGranularity);
  1302. }
  1303. HogList[ p->AllocatorBackTraceIndex ].TagEntry = FindTagEntry( HeapInfo, TagIndex );
  1304. }
  1305. }
  1306. p++;
  1307. }
  1308. for (BackTraceNumber = 1;
  1309. BackTraceNumber < BackTraces->NumberOfBackTraces;
  1310. BackTraceNumber++
  1311. ) {
  1312. HogList[ BackTraceNumber ].CallerBackTraceIndex = (USHORT)BackTraceNumber;
  1313. }
  1314. qsort( (void *)HogList,
  1315. BackTraces->NumberOfBackTraces,
  1316. sizeof( HEAP_CALLER ),
  1317. CmpCallerRoutine
  1318. );
  1319. FormatHeapHeader( HeapInfo, "Hogs" );
  1320. for (BackTraceNumber=0;
  1321. BackTraceNumber<BackTraces->NumberOfBackTraces;
  1322. BackTraceNumber++
  1323. ) {
  1324. if (HogList[ BackTraceNumber ].TotalAllocated != 0) {
  1325. BackTraceInfo = FindBackTrace( HogList[ BackTraceNumber ].CallerBackTraceIndex );
  1326. _snprintf( DumpLine, sizeof(DumpLine) - 1, "%08x bytes",
  1327. HogList[ BackTraceNumber ].TotalAllocated
  1328. );
  1329. DumpOutputString();
  1330. if (HogList[ BackTraceNumber ].NumberOfAllocations > 1) {
  1331. _snprintf( DumpLine, sizeof(DumpLine) - 1, " in %04lx allocations (@ %04lx)",
  1332. HogList[ BackTraceNumber ].NumberOfAllocations,
  1333. HogList[ BackTraceNumber ].TotalAllocated /
  1334. HogList[ BackTraceNumber ].NumberOfAllocations
  1335. );
  1336. DumpOutputString();
  1337. }
  1338. _snprintf( DumpLine, sizeof(DumpLine) - 1, " by: BackTrace%05lu",
  1339. BackTraceInfo ? BackTraceInfo->Index : 99999
  1340. );
  1341. DumpOutputString();
  1342. if (HogList[ BackTraceNumber ].TagEntry != NULL) {
  1343. _snprintf( DumpLine, sizeof(DumpLine) - 1, " (%ws)\n", HogList[ BackTraceNumber ].TagEntry->TagName );
  1344. }
  1345. else {
  1346. _snprintf( DumpLine, sizeof(DumpLine) - 1, "\n" );
  1347. }
  1348. DumpOutputString();
  1349. if (BackTraceInfo != NULL && (s = BackTraceInfo->SymbolicBackTrace)) {
  1350. while (*s) {
  1351. _snprintf( DumpLine, sizeof(DumpLine) - 1, " %s\n", s );
  1352. DumpOutputString();
  1353. while (*s++) {
  1354. }
  1355. }
  1356. }
  1357. _snprintf( DumpLine, sizeof(DumpLine) - 1, " \n" );
  1358. DumpOutputString();
  1359. }
  1360. }
  1361. VirtualFree( HogList, 0, MEM_RELEASE );
  1362. }
  1363. ////////////////////////////////////////////////////////////////////////////////////////////
  1364. VOID
  1365. DumpHeapEntries(
  1366. PRTL_HEAP_INFORMATION HeapInfo
  1367. )
  1368. {
  1369. PRTL_PROCESS_BACKTRACE_INFORMATION BackTraceInfo;
  1370. PUCHAR s;
  1371. PRTL_HEAP_ENTRY p;
  1372. PRTL_HEAP_TAG TagEntry;
  1373. PCHAR HeapEntryAddress;
  1374. SIZE_T HeapEntrySize;
  1375. ULONG HeapEntryNumber;
  1376. int result;
  1377. ULONG spaceLeft;
  1378. p = HeapInfo->Entries;
  1379. if (p == NULL || HeapInfo->NumberOfEntries == 0) {
  1380. return;
  1381. }
  1382. FormatHeapHeader( HeapInfo, "Entries" );
  1383. HeapEntryAddress = NULL;
  1384. for (HeapEntryNumber=0; HeapEntryNumber<HeapInfo->NumberOfEntries; HeapEntryNumber++) {
  1385. if (p->Flags != 0xFF && p->Flags & RTL_HEAP_SEGMENT) {
  1386. HeapEntryAddress = (PCHAR)p->u.s2.FirstBlock;
  1387. _snprintf( DumpLine, sizeof(DumpLine) - 1, "\n[%p : %p]\n",
  1388. (PVOID)((ULONG_PTR)HeapEntryAddress & ~(4096-1)),
  1389. (PVOID)p->u.s2.CommittedSize
  1390. );
  1391. DumpOutputString();
  1392. }
  1393. else {
  1394. HeapEntrySize = p->Size;
  1395. if (p->Flags == RTL_HEAP_UNCOMMITTED_RANGE) {
  1396. _snprintf( DumpLine, sizeof(DumpLine) - 1, "%p: %p - UNCOMMITTED\n",
  1397. HeapEntryAddress,
  1398. (PVOID)HeapEntrySize
  1399. );
  1400. DumpOutputString();
  1401. }
  1402. else
  1403. if (p->Flags & RTL_HEAP_BUSY) {
  1404. s = DumpLine;
  1405. spaceLeft = sizeof(DumpLine) - 1;
  1406. //
  1407. // BogdanA: 02/19/2002:
  1408. // Here and below: if we do not have space for
  1409. // what we want to to print, we print only so far and continue.
  1410. // We are guaranteed that DumpLine is terminated
  1411. //
  1412. result = _snprintf( s,
  1413. spaceLeft,
  1414. "%p: %p - BUSY [%02x]",
  1415. HeapEntryAddress,
  1416. (PVOID)HeapEntrySize,
  1417. p->Flags
  1418. );
  1419. if (result < 0) {
  1420. DumpOutputString();
  1421. continue;
  1422. } else {
  1423. s += result;
  1424. spaceLeft -= result;
  1425. }
  1426. TagEntry = FindTagEntry( HeapInfo, p->u.s1.Tag );
  1427. if (TagEntry != NULL) {
  1428. result = _snprintf( s, spaceLeft, "(%ws)", TagEntry->TagName );
  1429. if (result < 0) {
  1430. DumpOutputString();
  1431. continue;
  1432. } else {
  1433. s += result;
  1434. spaceLeft -= result;
  1435. }
  1436. }
  1437. if (BackTraces != NULL) {
  1438. result = _snprintf( s, spaceLeft, " (BackTrace%05lu)",
  1439. p->AllocatorBackTraceIndex
  1440. );
  1441. if (result < 0) {
  1442. DumpOutputString();
  1443. continue;
  1444. } else {
  1445. s += result;
  1446. spaceLeft -= result;
  1447. }
  1448. }
  1449. if (p->Flags & RTL_HEAP_SETTABLE_VALUE &&
  1450. p->Flags & RTL_HEAP_SETTABLE_FLAG1
  1451. ) {
  1452. result = _snprintf( s, spaceLeft, " (Handle: %x)", p->u.s1.Settable );
  1453. if (result < 0) {
  1454. DumpOutputString();
  1455. continue;
  1456. } else {
  1457. s += result;
  1458. spaceLeft -= result;
  1459. }
  1460. }
  1461. if (p->Flags & RTL_HEAP_SETTABLE_FLAG2) {
  1462. result = _snprintf( s, spaceLeft, " (DDESHARE)" );
  1463. if (result < 0) {
  1464. DumpOutputString();
  1465. continue;
  1466. } else {
  1467. s += result;
  1468. spaceLeft -= result;
  1469. }
  1470. }
  1471. if (p->Flags & RTL_HEAP_PROTECTED_ENTRY) {
  1472. _snprintf( s, spaceLeft, " (Protected)\n" );
  1473. } else {
  1474. _snprintf( s, spaceLeft, "\n" );
  1475. }
  1476. DumpOutputString();
  1477. }
  1478. else {
  1479. _snprintf( DumpLine, sizeof(DumpLine) - 1, "%p: %p - FREE\n",
  1480. HeapEntryAddress,
  1481. (PVOID)HeapEntrySize
  1482. );
  1483. DumpOutputString();
  1484. }
  1485. _snprintf( DumpLine, sizeof(DumpLine) - 1, "\n" );
  1486. DumpOutputString();
  1487. HeapEntryAddress += HeapEntrySize;
  1488. }
  1489. p++;
  1490. }
  1491. return;
  1492. }
  1493. ////////////////////////////////////////////////////////////////////////////////////////////
  1494. VOID
  1495. DumpHeaps(
  1496. PRTL_PROCESS_HEAPS Heaps,
  1497. BOOL fDumpSummary,
  1498. BOOL fDumpHogs,
  1499. BOOL fDumpTags,
  1500. BOOL fDumpEntries
  1501. )
  1502. {
  1503. ULONG HeapNumber;
  1504. PRTL_HEAP_INFORMATION HeapInfo;
  1505. if (fVerbose) {
  1506. fprintf( stderr, "DH: Dumping heap information.\n" );
  1507. }
  1508. HeapInfo = &Heaps->Heaps[ 0 ];
  1509. for (HeapNumber = 0; HeapNumber < Heaps->NumberOfHeaps; HeapNumber++) {
  1510. FormatHeapHeader( HeapInfo, "Information" );
  1511. if (fDumpSummary) {
  1512. DumpHeapSummary( HeapInfo );
  1513. }
  1514. if (fDumpTags) {
  1515. DumpHeapTags( HeapInfo );
  1516. }
  1517. if (fDumpHogs) {
  1518. DumpHeapHogs( HeapInfo );
  1519. }
  1520. if (fDumpEntries) {
  1521. DumpHeapEntries( HeapInfo );
  1522. }
  1523. HeapInfo += 1;
  1524. }
  1525. return;
  1526. }
  1527. ////////////////////////////////////////////////////////////////////////////////////////////
  1528. VOID
  1529. DumpLocks(
  1530. PRTL_PROCESS_LOCKS Locks
  1531. )
  1532. {
  1533. PRTL_PROCESS_LOCK_INFORMATION LockInfo;
  1534. PRTL_PROCESS_BACKTRACE_INFORMATION BackTraceInfo;
  1535. ULONG LockNumber;
  1536. PUCHAR s;
  1537. if (fVerbose) {
  1538. fprintf( stderr, "DH: Dumping lock information.\n" );
  1539. }
  1540. _snprintf( DumpLine, sizeof(DumpLine) - 1, "\n\n*********** Lock Information ********************\n\n" );
  1541. DumpOutputString();
  1542. if (Locks == NULL) {
  1543. return;
  1544. }
  1545. _snprintf( DumpLine, sizeof(DumpLine) - 1, "NumberOfLocks == %u\n", Locks->NumberOfLocks );
  1546. DumpOutputString();
  1547. LockInfo = &Locks->Locks[ 0 ];
  1548. LockNumber = 0;
  1549. while (LockNumber++ < Locks->NumberOfLocks) {
  1550. _snprintf( DumpLine, sizeof(DumpLine) - 1, "Lock%u at %p (%s)\n",
  1551. LockNumber,
  1552. LockInfo->Address,
  1553. LockInfo->Type == RTL_CRITSECT_TYPE ? "CriticalSection" : "Resource"
  1554. );
  1555. DumpOutputString();
  1556. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Contention: %u\n", LockInfo->ContentionCount );
  1557. DumpOutputString();
  1558. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Usage: %u\n", LockInfo->EntryCount );
  1559. DumpOutputString();
  1560. if (LockInfo->CreatorBackTraceIndex != 0) {
  1561. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Creator: (Backtrace%05lu)\n", LockInfo->CreatorBackTraceIndex );
  1562. DumpOutputString();
  1563. BackTraceInfo = FindBackTrace( LockInfo->CreatorBackTraceIndex );
  1564. if (BackTraceInfo != NULL && (s = BackTraceInfo->SymbolicBackTrace)) {
  1565. while (*s) {
  1566. _snprintf( DumpLine, sizeof(DumpLine) - 1, " %s\n", s );
  1567. DumpOutputString();
  1568. while (*s++) {
  1569. }
  1570. }
  1571. }
  1572. }
  1573. if (LockInfo->OwningThread) {
  1574. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Owner: (ThreadID == %p)\n", LockInfo->OwningThread );
  1575. DumpOutputString();
  1576. }
  1577. _snprintf( DumpLine, sizeof(DumpLine) - 1, "\n" );
  1578. DumpOutputString();
  1579. LockInfo++;
  1580. }
  1581. }
  1582. ////////////////////////////////////////////////////////////////////////////////////////////
  1583. #define RTL_NEW( p ) RtlAllocateHeap( RtlProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *p ) )
  1584. BOOLEAN
  1585. LoadSystemModules(
  1586. PRTL_DEBUG_INFORMATION Buffer
  1587. );
  1588. BOOLEAN
  1589. LoadSystemBackTraces(
  1590. PRTL_DEBUG_INFORMATION Buffer
  1591. );
  1592. BOOLEAN
  1593. LoadSystemPools(
  1594. PRTL_DEBUG_INFORMATION Buffer
  1595. );
  1596. BOOLEAN
  1597. LoadSystemTags(
  1598. PRTL_HEAP_INFORMATION PagedPoolInfo,
  1599. PRTL_HEAP_INFORMATION NonPagedPoolInfo
  1600. );
  1601. BOOLEAN
  1602. LoadSystemPool(
  1603. PRTL_HEAP_INFORMATION HeapInfo,
  1604. SYSTEM_INFORMATION_CLASS SystemInformationClass
  1605. );
  1606. BOOLEAN
  1607. LoadSystemLocks(
  1608. PRTL_DEBUG_INFORMATION Buffer
  1609. );
  1610. BOOLEAN
  1611. LoadSystemObjects(
  1612. PRTL_DEBUG_INFORMATION Buffer
  1613. );
  1614. BOOLEAN
  1615. LoadSystemHandles(
  1616. PRTL_DEBUG_INFORMATION Buffer
  1617. );
  1618. BOOLEAN
  1619. LoadSystemProcesses(
  1620. PRTL_DEBUG_INFORMATION Buffer
  1621. );
  1622. PSYSTEM_PROCESS_INFORMATION
  1623. FindProcessInfoForCid(
  1624. IN HANDLE UniqueProcessId
  1625. );
  1626. ////////////////////////////////////////////////////////////////////////////////////////////
  1627. PRTL_DEBUG_INFORMATION
  1628. RtlQuerySystemDebugInformation(
  1629. ULONG Flags
  1630. )
  1631. {
  1632. PRTL_DEBUG_INFORMATION Buffer;
  1633. Buffer = RTL_NEW( Buffer );
  1634. if (Buffer == NULL) {
  1635. fprintf(stderr,"DH: allocation failure for %d byte at line %d\n",sizeof(*Buffer),__LINE__);
  1636. return NULL;
  1637. }
  1638. if ((Flags & RTL_QUERY_PROCESS_MODULES) != 0 && !LoadSystemModules( Buffer )) {
  1639. fputs( "DH: Unable to query system module list.\n", stderr );
  1640. }
  1641. if ((Flags & RTL_QUERY_PROCESS_BACKTRACES) != 0 && !LoadSystemBackTraces( Buffer )) {
  1642. fputs( "DH: Unable to query system back trace information.\n"
  1643. " Be sure the system was booted with the\n"
  1644. " 'Create kernel mode stack trace DB' enabled\n"
  1645. " Use the GFLAGS.EXE application to do this.\n"
  1646. , stderr);
  1647. }
  1648. if ((Flags & (RTL_QUERY_PROCESS_HEAP_SUMMARY |
  1649. RTL_QUERY_PROCESS_HEAP_TAGS |
  1650. RTL_QUERY_PROCESS_HEAP_ENTRIES
  1651. )
  1652. ) != 0 &&
  1653. !LoadSystemPools( Buffer )
  1654. ) {
  1655. fputs( "DH: Unable to query system pool information.\n", stderr );
  1656. }
  1657. if ((Flags & RTL_QUERY_PROCESS_LOCKS) != 0 && !LoadSystemLocks( Buffer )) {
  1658. fputs( "DH: Unable to query system lock information.\n", stderr);
  1659. }
  1660. if (fDumpSystemObjects && !LoadSystemObjects( Buffer )) {
  1661. fputs( "DH: Unable to query system object information.\n", stderr );
  1662. }
  1663. if (fDumpSystemObjects && !LoadSystemHandles( Buffer )) {
  1664. fputs( "DH: Unable to query system handle information.\n", stderr );
  1665. }
  1666. if (!LoadSystemProcesses( Buffer )) {
  1667. fputs( "DH: Unable to query system process information.\n", stderr );
  1668. }
  1669. return Buffer;
  1670. }
  1671. ////////////////////////////////////////////////////////////////////////////////////////////
  1672. PVOID
  1673. BufferAlloc(
  1674. IN OUT SIZE_T *Length
  1675. )
  1676. {
  1677. PVOID Buffer;
  1678. MEMORY_BASIC_INFORMATION MemoryInformation;
  1679. Buffer = VirtualAlloc( NULL,
  1680. *Length,
  1681. MEM_COMMIT,
  1682. PAGE_READWRITE
  1683. );
  1684. if (Buffer != NULL &&
  1685. VirtualQuery( Buffer, &MemoryInformation, sizeof( MemoryInformation ) )
  1686. ) {
  1687. *Length = MemoryInformation.RegionSize;
  1688. }
  1689. if( Buffer == NULL ) {
  1690. fprintf(stderr,"DH: VirtualAlloc failed for %d bytes at line %d\n",*Length,__LINE__);
  1691. }
  1692. return Buffer;
  1693. }
  1694. ////////////////////////////////////////////////////////////////////////////////////////////
  1695. BOOLEAN
  1696. LoadSystemModules(
  1697. PRTL_DEBUG_INFORMATION Buffer
  1698. )
  1699. {
  1700. NTSTATUS Status;
  1701. PVOID BufferToFree;
  1702. RTL_PROCESS_MODULES ModulesBuffer;
  1703. PRTL_PROCESS_MODULES modules;
  1704. SIZE_T RequiredLength;
  1705. modules = &ModulesBuffer;
  1706. RequiredLength = sizeof( ModulesBuffer );
  1707. BufferToFree = NULL;
  1708. while (TRUE) {
  1709. Status = NtQuerySystemInformation( SystemModuleInformation,
  1710. modules,
  1711. (ULONG)RequiredLength,
  1712. (ULONG *)&RequiredLength
  1713. );
  1714. if (Status == STATUS_INFO_LENGTH_MISMATCH) {
  1715. if (modules != &ModulesBuffer) {
  1716. break;
  1717. }
  1718. modules = BufferAlloc( &RequiredLength );
  1719. if (modules == NULL) {
  1720. break;
  1721. }
  1722. BufferToFree = modules;
  1723. }
  1724. else
  1725. if (NT_SUCCESS( Status )) {
  1726. Buffer->Modules = modules;
  1727. return TRUE;
  1728. }
  1729. else {
  1730. fprintf(stderr,"DH: QuerySystemInformation failed ntstatus: %08x line: %d\n",
  1731. Status,__LINE__);
  1732. break;
  1733. }
  1734. }
  1735. if (modules != &ModulesBuffer) {
  1736. VirtualFree( modules, 0, MEM_RELEASE );
  1737. }
  1738. return FALSE;
  1739. }
  1740. ////////////////////////////////////////////////////////////////////////////////////////////
  1741. BOOLEAN
  1742. LoadSystemBackTraces(
  1743. PRTL_DEBUG_INFORMATION Buffer
  1744. )
  1745. {
  1746. NTSTATUS Status;
  1747. RTL_PROCESS_BACKTRACES BackTracesBuffer;
  1748. SIZE_T RequiredLength;
  1749. BackTraces = &BackTracesBuffer;
  1750. RequiredLength = sizeof( BackTracesBuffer );
  1751. while (TRUE) {
  1752. Status = NtQuerySystemInformation( SystemStackTraceInformation,
  1753. BackTraces,
  1754. (ULONG)RequiredLength,
  1755. (ULONG *)&RequiredLength
  1756. );
  1757. if (Status == STATUS_INFO_LENGTH_MISMATCH) {
  1758. if (BackTraces != &BackTracesBuffer) {
  1759. break;
  1760. }
  1761. RequiredLength += 4096; // slop, since we may trigger more allocs.
  1762. BackTraces = BufferAlloc( &RequiredLength );
  1763. if (BackTraces == NULL) {
  1764. return FALSE;
  1765. }
  1766. }
  1767. else
  1768. if (!NT_SUCCESS( Status )) {
  1769. fprintf(stderr,"DH: QuerySystemInformation failed ntstatus: %08x line: %d\n",Status,__LINE__);
  1770. break;
  1771. }
  1772. else {
  1773. Buffer->BackTraces = BackTraces;
  1774. return TRUE;
  1775. }
  1776. }
  1777. if (BackTraces != &BackTracesBuffer) {
  1778. VirtualFree( BackTraces, 0, MEM_RELEASE );
  1779. }
  1780. return FALSE;
  1781. }
  1782. ////////////////////////////////////////////////////////////////////////////////////////////
  1783. BOOLEAN
  1784. LoadSystemPools(
  1785. PRTL_DEBUG_INFORMATION Buffer
  1786. )
  1787. {
  1788. PRTL_PROCESS_HEAPS Heaps;
  1789. SIZE_T Size;
  1790. Size= FIELD_OFFSET( RTL_PROCESS_HEAPS, Heaps) + 2 * sizeof( RTL_HEAP_INFORMATION );
  1791. Heaps = RtlAllocateHeap( RtlProcessHeap(),
  1792. HEAP_ZERO_MEMORY,
  1793. Size );
  1794. if (Heaps == NULL) {
  1795. fprintf(stderr,"DH: AllocateHeap failed for %d bytes at line %d\n",Size,__LINE__);
  1796. return FALSE;
  1797. }
  1798. Buffer->Heaps = Heaps;
  1799. if (LoadSystemTags( &Heaps->Heaps[ 0 ], &Heaps->Heaps[ 1 ] )) {
  1800. if (LoadSystemPool( &Heaps->Heaps[ 0 ], SystemPagedPoolInformation )) {
  1801. Heaps->NumberOfHeaps = 1;
  1802. if (LoadSystemPool( &Heaps->Heaps[ 1 ], SystemNonPagedPoolInformation )) {
  1803. Heaps->NumberOfHeaps = 2;
  1804. return TRUE;
  1805. }
  1806. }
  1807. }
  1808. return FALSE;
  1809. }
  1810. ////////////////////////////////////////////////////////////////////////////////////////////
  1811. NTSTATUS
  1812. QueryPoolTagInformationIterative(
  1813. PVOID *CurrentBuffer,
  1814. SIZE_T *CurrentBufferSize
  1815. )
  1816. {
  1817. SIZE_T NewBufferSize;
  1818. NTSTATUS ReturnedStatus = STATUS_SUCCESS;
  1819. if( CurrentBuffer == NULL || CurrentBufferSize == NULL ) {
  1820. return STATUS_INVALID_PARAMETER;
  1821. }
  1822. if( *CurrentBufferSize == 0 || *CurrentBuffer == NULL ) {
  1823. //
  1824. // there is no buffer allocated yet
  1825. //
  1826. NewBufferSize = sizeof( UCHAR ) * BUFFER_SIZE_STEP;
  1827. *CurrentBuffer = VirtualAlloc(
  1828. NULL,
  1829. NewBufferSize,
  1830. MEM_COMMIT,
  1831. PAGE_READWRITE
  1832. );
  1833. if( *CurrentBuffer != NULL ) {
  1834. *CurrentBufferSize = NewBufferSize;
  1835. } else {
  1836. //
  1837. // insufficient memory
  1838. //
  1839. ReturnedStatus = STATUS_INSUFFICIENT_RESOURCES;
  1840. }
  1841. }
  1842. //
  1843. // iterate by buffer's size
  1844. //
  1845. while( *CurrentBuffer != NULL ) {
  1846. ReturnedStatus = NtQuerySystemInformation (
  1847. SystemPoolTagInformation,
  1848. *CurrentBuffer,
  1849. (ULONG)*CurrentBufferSize,
  1850. NULL );
  1851. if( ! NT_SUCCESS(ReturnedStatus) ) {
  1852. //
  1853. // free the current buffer
  1854. //
  1855. VirtualFree(
  1856. *CurrentBuffer,
  1857. 0,
  1858. MEM_RELEASE );
  1859. *CurrentBuffer = NULL;
  1860. if (ReturnedStatus == STATUS_INFO_LENGTH_MISMATCH) {
  1861. //
  1862. // try with a greater buffer size
  1863. //
  1864. NewBufferSize = *CurrentBufferSize + BUFFER_SIZE_STEP;
  1865. *CurrentBuffer = VirtualAlloc(
  1866. NULL,
  1867. NewBufferSize,
  1868. MEM_COMMIT,
  1869. PAGE_READWRITE
  1870. );
  1871. if( *CurrentBuffer != NULL ) {
  1872. //
  1873. // allocated new buffer
  1874. //
  1875. *CurrentBufferSize = NewBufferSize;
  1876. } else {
  1877. //
  1878. // insufficient memory
  1879. //
  1880. ReturnedStatus = STATUS_INSUFFICIENT_RESOURCES;
  1881. *CurrentBufferSize = 0;
  1882. }
  1883. } else {
  1884. *CurrentBufferSize = 0;
  1885. }
  1886. } else {
  1887. //
  1888. // NtQuerySystemInformation returned success
  1889. //
  1890. break;
  1891. }
  1892. }
  1893. return ReturnedStatus;
  1894. }
  1895. ////////////////////////////////////////////////////////////////////////////////////////////
  1896. BOOLEAN
  1897. LoadSystemTags(
  1898. PRTL_HEAP_INFORMATION PagedPoolInfo,
  1899. PRTL_HEAP_INFORMATION NonPagedPoolInfo
  1900. )
  1901. {
  1902. NTSTATUS Status;
  1903. SIZE_T RequiredLength;
  1904. PSYSTEM_POOLTAG_INFORMATION Tags;
  1905. PSYSTEM_POOLTAG TagInfo;
  1906. PRTL_HEAP_TAG pPagedPoolTag, pNonPagedPoolTag;
  1907. ULONG n, TagIndex;
  1908. PagedPoolInfo->NumberOfTags = 0;
  1909. PagedPoolInfo->Tags = NULL;
  1910. NonPagedPoolInfo->NumberOfTags = 0;
  1911. NonPagedPoolInfo->Tags = NULL;
  1912. Tags = NULL;
  1913. RequiredLength = 0;
  1914. while (TRUE) {
  1915. Status = QueryPoolTagInformationIterative(
  1916. &Tags,
  1917. &RequiredLength
  1918. );
  1919. if (!NT_SUCCESS( Status )) {
  1920. fprintf(stderr,"DH: QuerySystemInformation failed ntstatus: %08x line: %d\n",Status,__LINE__);
  1921. break;
  1922. }
  1923. else {
  1924. PagedPoolInfo->NumberOfTags = Tags->Count + 1;
  1925. NonPagedPoolInfo->NumberOfTags = Tags->Count + 1;
  1926. n = (Tags->Count + 1) * sizeof( RTL_HEAP_TAG );
  1927. PagedPoolInfo->Tags = RtlAllocateHeap( RtlProcessHeap(), HEAP_ZERO_MEMORY, n );
  1928. NonPagedPoolInfo->Tags = RtlAllocateHeap( RtlProcessHeap(), HEAP_ZERO_MEMORY, n );
  1929. TagInfo = &Tags->TagInfo[ 0 ];
  1930. pPagedPoolTag = PagedPoolInfo->Tags + 1;
  1931. pNonPagedPoolTag = NonPagedPoolInfo->Tags + 1;
  1932. for (TagIndex=1; TagIndex<=Tags->Count; TagIndex++) {
  1933. UNICODE_STRING UnicodeString;
  1934. ANSI_STRING AnsiString;
  1935. pPagedPoolTag->TagIndex = (USHORT)TagIndex;
  1936. pPagedPoolTag->NumberOfAllocations = TagInfo->PagedAllocs;
  1937. pPagedPoolTag->NumberOfFrees = TagInfo->PagedFrees;
  1938. pPagedPoolTag->BytesAllocated = TagInfo->PagedUsed;
  1939. UnicodeString.Buffer = pPagedPoolTag->TagName;
  1940. UnicodeString.MaximumLength = sizeof( pPagedPoolTag->TagName );
  1941. AnsiString.Buffer = TagInfo->Tag;
  1942. AnsiString.Length = sizeof( TagInfo->Tag );
  1943. AnsiString.MaximumLength = AnsiString.Length;
  1944. RtlAnsiStringToUnicodeString( &UnicodeString, &AnsiString, FALSE );
  1945. pNonPagedPoolTag->TagIndex = (USHORT)TagIndex;
  1946. pNonPagedPoolTag->NumberOfAllocations = TagInfo->NonPagedAllocs;
  1947. pNonPagedPoolTag->NumberOfFrees = TagInfo->NonPagedFrees;
  1948. pNonPagedPoolTag->BytesAllocated = TagInfo->NonPagedUsed;
  1949. pNonPagedPoolTag->TagName[sizeof(pNonPagedPoolTag->TagName) / sizeof(WCHAR) - 1 ] = 0;
  1950. wcsncpy( pNonPagedPoolTag->TagName,
  1951. pPagedPoolTag->TagName,
  1952. sizeof(pNonPagedPoolTag->TagName) / sizeof(WCHAR) - 1 );
  1953. pPagedPoolTag += 1;
  1954. pNonPagedPoolTag += 1;
  1955. TagInfo += 1;
  1956. }
  1957. break;
  1958. }
  1959. }
  1960. if (Tags != NULL) {
  1961. VirtualFree( Tags, 0, MEM_RELEASE );
  1962. }
  1963. return TRUE;
  1964. }
  1965. ////////////////////////////////////////////////////////////////////////////////////////////
  1966. USHORT
  1967. FindPoolTagIndex(
  1968. PRTL_HEAP_TAG Tags,
  1969. ULONG NumberOfTags,
  1970. PCHAR Tag
  1971. )
  1972. {
  1973. ULONG i;
  1974. UCHAR AnsiTagName[ 5 ];
  1975. WCHAR UnicodeTagName[ 5 ];
  1976. UNICODE_STRING UnicodeString;
  1977. ANSI_STRING AnsiString;
  1978. strncpy( AnsiTagName, Tag, 4 );
  1979. UnicodeString.Buffer = UnicodeTagName;
  1980. UnicodeString.MaximumLength = sizeof( UnicodeTagName );
  1981. AnsiString.Buffer = AnsiTagName;
  1982. AnsiString.Length = (USHORT)strlen( AnsiTagName );
  1983. AnsiString.MaximumLength = AnsiString.Length;
  1984. RtlAnsiStringToUnicodeString( &UnicodeString, &AnsiString, FALSE );
  1985. Tags += 1;
  1986. for (i=1; i<NumberOfTags; i++) {
  1987. if (!_wcsicmp( UnicodeTagName, Tags->TagName )) {
  1988. return (USHORT)i;
  1989. }
  1990. Tags += 1;
  1991. }
  1992. return 0;
  1993. }
  1994. ////////////////////////////////////////////////////////////////////////////////////////////
  1995. BOOLEAN
  1996. LoadSystemPool(
  1997. PRTL_HEAP_INFORMATION HeapInfo,
  1998. SYSTEM_INFORMATION_CLASS SystemInformationClass
  1999. )
  2000. {
  2001. NTSTATUS Status;
  2002. SIZE_T RequiredLength;
  2003. SYSTEM_POOL_INFORMATION PoolInfoBuffer;
  2004. PSYSTEM_POOL_INFORMATION PoolInfo;
  2005. PSYSTEM_POOL_ENTRY PoolEntry;
  2006. PRTL_HEAP_ENTRY p;
  2007. ULONG n;
  2008. BOOLEAN Result;
  2009. HeapInfo->BaseAddress = (PVOID)SystemInformationClass;
  2010. PoolInfo = &PoolInfoBuffer;
  2011. RequiredLength = sizeof( PoolInfoBuffer );
  2012. Result = FALSE;
  2013. while (TRUE) {
  2014. Status = NtQuerySystemInformation( SystemInformationClass,
  2015. PoolInfo,
  2016. (ULONG)RequiredLength,
  2017. (ULONG *)&RequiredLength
  2018. );
  2019. if (Status == STATUS_INFO_LENGTH_MISMATCH) {
  2020. if (PoolInfo != &PoolInfoBuffer) {
  2021. break;
  2022. }
  2023. RequiredLength += 4096; // slop, since we may trigger more allocs.
  2024. PoolInfo = BufferAlloc( &RequiredLength );
  2025. if (PoolInfo == NULL) {
  2026. return FALSE;
  2027. }
  2028. }
  2029. else
  2030. if (!NT_SUCCESS( Status )) {
  2031. fprintf(stderr,"DH: QuerySystemInformation failed ntstatus: %08x line: %d\n",Status,__LINE__);
  2032. break;
  2033. }
  2034. else {
  2035. n = PoolInfo->NumberOfEntries;
  2036. HeapInfo->NumberOfEntries = n + 1;
  2037. HeapInfo->EntryOverhead = PoolInfo->EntryOverhead;
  2038. HeapInfo->Entries = RtlAllocateHeap( RtlProcessHeap(),
  2039. HEAP_ZERO_MEMORY,
  2040. HeapInfo->NumberOfEntries * sizeof( RTL_HEAP_ENTRY )
  2041. );
  2042. if( HeapInfo->Entries == NULL ) {
  2043. fprintf(stderr,"DH: Alloc failed for %d bytes at line %d\n",
  2044. HeapInfo->NumberOfEntries * sizeof( RTL_HEAP_ENTRY),__LINE__);
  2045. break;
  2046. }
  2047. p = HeapInfo->Entries;
  2048. p->Flags = RTL_HEAP_SEGMENT;
  2049. p->u.s2.CommittedSize = PoolInfo->TotalSize;
  2050. p->u.s2.FirstBlock = PoolInfo->FirstEntry;
  2051. p += 1;
  2052. PoolEntry = &PoolInfo->Entries[ 0 ];
  2053. while (n--) {
  2054. p->Size = PoolEntry->Size;
  2055. if (PoolEntry->TagUlong & PROTECTED_POOL) {
  2056. p->Flags |= RTL_HEAP_PROTECTED_ENTRY;
  2057. PoolEntry->TagUlong &= ~PROTECTED_POOL;
  2058. }
  2059. p->u.s1.Tag = FindPoolTagIndex( HeapInfo->Tags,
  2060. HeapInfo->NumberOfTags,
  2061. PoolEntry->Tag
  2062. );
  2063. HeapInfo->BytesCommitted += p->Size;
  2064. if (PoolEntry->Allocated) {
  2065. p->Flags |= RTL_HEAP_BUSY;
  2066. p->AllocatorBackTraceIndex = PoolEntry->AllocatorBackTraceIndex;
  2067. HeapInfo->BytesAllocated += p->Size;
  2068. }
  2069. p += 1;
  2070. PoolEntry += 1;
  2071. }
  2072. Result = TRUE;
  2073. break;
  2074. }
  2075. }
  2076. if (PoolInfo != &PoolInfoBuffer) {
  2077. VirtualFree( PoolInfo, 0, MEM_RELEASE );
  2078. }
  2079. return Result;
  2080. }
  2081. ////////////////////////////////////////////////////////////////////////////////////////////
  2082. BOOLEAN
  2083. LoadSystemLocks(
  2084. PRTL_DEBUG_INFORMATION Buffer
  2085. )
  2086. {
  2087. NTSTATUS Status;
  2088. RTL_PROCESS_LOCKS LocksBuffer;
  2089. PRTL_PROCESS_LOCKS Locks;
  2090. SIZE_T RequiredLength;
  2091. Locks = &LocksBuffer;
  2092. RequiredLength = sizeof( LocksBuffer );
  2093. while (TRUE) {
  2094. Status = NtQuerySystemInformation( SystemLocksInformation,
  2095. Locks,
  2096. (ULONG)RequiredLength,
  2097. (ULONG *)&RequiredLength
  2098. );
  2099. if (Status == STATUS_INFO_LENGTH_MISMATCH) {
  2100. if (Locks != &LocksBuffer) {
  2101. break;
  2102. }
  2103. Locks = BufferAlloc( &RequiredLength );
  2104. if (Locks == NULL) {
  2105. return FALSE;
  2106. }
  2107. }
  2108. else
  2109. if (!NT_SUCCESS( Status )) {
  2110. fprintf(stderr,"DH: QuerySystemInformation failed ntstatus: %08x line: %d\n",Status,__LINE__);
  2111. break;
  2112. }
  2113. else {
  2114. Buffer->Locks = Locks;
  2115. return TRUE;
  2116. }
  2117. }
  2118. if (Locks != &LocksBuffer) {
  2119. VirtualFree( Locks, 0, MEM_RELEASE );
  2120. }
  2121. return FALSE;
  2122. }
  2123. ////////////////////////////////////////////////////////////////////////////////////////////
  2124. BOOLEAN
  2125. LoadSystemObjects(
  2126. PRTL_DEBUG_INFORMATION Buffer
  2127. )
  2128. {
  2129. NTSTATUS Status;
  2130. SYSTEM_OBJECTTYPE_INFORMATION ObjectInfoBuffer;
  2131. SIZE_T RequiredLength;
  2132. ULONG i;
  2133. PSYSTEM_OBJECTTYPE_INFORMATION TypeInfo;
  2134. ObjectInformation = &ObjectInfoBuffer;
  2135. RequiredLength = sizeof( *ObjectInformation );
  2136. while (TRUE) {
  2137. Status = NtQuerySystemInformation( SystemObjectInformation,
  2138. ObjectInformation,
  2139. (ULONG)RequiredLength,
  2140. (ULONG *)&RequiredLength
  2141. );
  2142. if (Status == STATUS_INFO_LENGTH_MISMATCH) {
  2143. if (ObjectInformation != &ObjectInfoBuffer) {
  2144. return FALSE;
  2145. }
  2146. RequiredLength += 4096; // slop, since we may trigger more object creations.
  2147. ObjectInformation = BufferAlloc( &RequiredLength );
  2148. if (ObjectInformation == NULL) {
  2149. return FALSE;
  2150. }
  2151. }
  2152. else
  2153. if (!NT_SUCCESS( Status )) {
  2154. fprintf(stderr,"DH: QuerySystemInformation failed ntstatus: %08x line: %d\n",Status,__LINE__);
  2155. return FALSE;
  2156. }
  2157. else {
  2158. break;
  2159. }
  2160. }
  2161. TypeNames = RtlAllocateHeap( RtlProcessHeap(),
  2162. HEAP_ZERO_MEMORY,
  2163. sizeof( PUNICODE_STRING ) * (MAX_TYPE_NAMES+1)
  2164. );
  2165. if (TypeNames == NULL) {
  2166. fprintf(stderr,"DH: Alloc failed for %d bytes at line %d\n",
  2167. sizeof( PUNICODE_STRING ) * (MAX_TYPE_NAMES+1) ,__LINE__);
  2168. return FALSE;
  2169. }
  2170. TypeInfo = ObjectInformation;
  2171. while (TRUE) {
  2172. if (TypeInfo->TypeIndex < MAX_TYPE_NAMES) {
  2173. TypeNames[ TypeInfo->TypeIndex ] = &TypeInfo->TypeName;
  2174. }
  2175. if (TypeInfo->NextEntryOffset == 0) {
  2176. break;
  2177. }
  2178. TypeInfo = (PSYSTEM_OBJECTTYPE_INFORMATION)
  2179. ((PCHAR)ObjectInformation + TypeInfo->NextEntryOffset);
  2180. }
  2181. RtlInitUnicodeString( &UnknownTypeIndex, L"Unknown Type Index" );
  2182. for (i=0; i<=MAX_TYPE_NAMES; i++) {
  2183. if (TypeNames[ i ] == NULL) {
  2184. TypeNames[ i ] = &UnknownTypeIndex;
  2185. }
  2186. }
  2187. return TRUE;
  2188. }
  2189. ////////////////////////////////////////////////////////////////////////////////////////////
  2190. BOOLEAN
  2191. LoadSystemHandles(
  2192. PRTL_DEBUG_INFORMATION Buffer
  2193. )
  2194. {
  2195. NTSTATUS Status;
  2196. SYSTEM_HANDLE_INFORMATION_EX HandleInfoBuffer;
  2197. SIZE_T RequiredLength;
  2198. PSYSTEM_OBJECTTYPE_INFORMATION TypeInfo;
  2199. PSYSTEM_OBJECT_INFORMATION ObjectInfo;
  2200. HandleInformation = &HandleInfoBuffer;
  2201. RequiredLength = sizeof( *HandleInformation );
  2202. while (TRUE) {
  2203. Status = NtQuerySystemInformation( SystemExtendedHandleInformation,
  2204. HandleInformation,
  2205. (ULONG)RequiredLength,
  2206. (ULONG *)&RequiredLength
  2207. );
  2208. if (Status == STATUS_INFO_LENGTH_MISMATCH) {
  2209. if (HandleInformation != &HandleInfoBuffer) {
  2210. return FALSE;
  2211. }
  2212. RequiredLength += 4096; // slop, since we may trigger more handle creations.
  2213. HandleInformation = (PSYSTEM_HANDLE_INFORMATION_EX)BufferAlloc( &RequiredLength );
  2214. if (HandleInformation == NULL) {
  2215. return FALSE;
  2216. }
  2217. }
  2218. else
  2219. if (!NT_SUCCESS( Status )) {
  2220. fprintf(stderr,"DH: QuerySystemInformation failed ntstatus: %08x line: %d\n",Status,__LINE__);
  2221. return FALSE;
  2222. }
  2223. else {
  2224. break;
  2225. }
  2226. }
  2227. TypeInfo = ObjectInformation;
  2228. while (TRUE) {
  2229. ObjectInfo = (PSYSTEM_OBJECT_INFORMATION)
  2230. ((PCHAR)TypeInfo->TypeName.Buffer + TypeInfo->TypeName.MaximumLength);
  2231. while (TRUE) {
  2232. if (ObjectInfo->HandleCount != 0) {
  2233. PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX HandleEntry;
  2234. ULONG HandleNumber;
  2235. HandleEntry = &HandleInformation->Handles[ 0 ];
  2236. HandleNumber = 0;
  2237. while (HandleNumber++ < HandleInformation->NumberOfHandles) {
  2238. if (!(HandleEntry->HandleAttributes & 0x80) &&
  2239. HandleEntry->Object == ObjectInfo->Object
  2240. ) {
  2241. HandleEntry->Object = ObjectInfo;
  2242. HandleEntry->HandleAttributes |= 0x80;
  2243. }
  2244. HandleEntry++;
  2245. }
  2246. }
  2247. if (ObjectInfo->NextEntryOffset == 0) {
  2248. break;
  2249. }
  2250. ObjectInfo = (PSYSTEM_OBJECT_INFORMATION)
  2251. ((PCHAR)ObjectInformation + ObjectInfo->NextEntryOffset);
  2252. }
  2253. if (TypeInfo->NextEntryOffset == 0) {
  2254. break;
  2255. }
  2256. TypeInfo = (PSYSTEM_OBJECTTYPE_INFORMATION)
  2257. ((PCHAR)ObjectInformation + TypeInfo->NextEntryOffset);
  2258. }
  2259. return TRUE;
  2260. }
  2261. ////////////////////////////////////////////////////////////////////////////////////////////
  2262. BOOLEAN
  2263. LoadSystemProcesses(
  2264. PRTL_DEBUG_INFORMATION Buffer
  2265. )
  2266. {
  2267. NTSTATUS Status;
  2268. SIZE_T RequiredLength;
  2269. ULONG i, TotalOffset;
  2270. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  2271. PSYSTEM_THREAD_INFORMATION ThreadInfo;
  2272. PPROCESS_INFO ProcessEntry;
  2273. UCHAR NameBuffer[ MAX_PATH ];
  2274. ANSI_STRING AnsiString;
  2275. SIZE_T Size;
  2276. RequiredLength = 64 * 1024;
  2277. ProcessInformation = BufferAlloc( &RequiredLength );
  2278. if (ProcessInformation == NULL) {
  2279. return FALSE;
  2280. }
  2281. Status = NtQuerySystemInformation( SystemProcessInformation,
  2282. ProcessInformation,
  2283. (ULONG)RequiredLength,
  2284. (ULONG *)&RequiredLength
  2285. );
  2286. if (!NT_SUCCESS( Status )) {
  2287. fprintf(stderr,"DH: QuerySystemInformation failed ntstatus: %08x line: %d\n",Status,__LINE__);
  2288. return FALSE;
  2289. }
  2290. InitializeListHead( &ProcessListHead );
  2291. ProcessInfo = ProcessInformation;
  2292. TotalOffset = 0;
  2293. NameBuffer[sizeof(NameBuffer) - 1] = 0;
  2294. while (TRUE) {
  2295. if (ProcessInfo->ImageName.Buffer == NULL) {
  2296. _snprintf( NameBuffer,
  2297. sizeof(NameBuffer) - 1,
  2298. "System Process (%p)", ProcessInfo->UniqueProcessId );
  2299. }
  2300. else {
  2301. _snprintf( NameBuffer,
  2302. sizeof(NameBuffer) - 1,
  2303. "%wZ (%p)",
  2304. &ProcessInfo->ImageName,
  2305. ProcessInfo->UniqueProcessId
  2306. );
  2307. }
  2308. RtlInitAnsiString( &AnsiString, NameBuffer );
  2309. RtlAnsiStringToUnicodeString( &ProcessInfo->ImageName, &AnsiString, TRUE );
  2310. Size = sizeof( *ProcessEntry ) + (sizeof( ThreadInfo ) * ProcessInfo->NumberOfThreads);
  2311. ProcessEntry = RtlAllocateHeap( RtlProcessHeap(),
  2312. HEAP_ZERO_MEMORY,
  2313. Size );
  2314. if (ProcessEntry == NULL) {
  2315. fprintf(stderr,"DH: Alloc failed for %d bytes at line %d\n",Size,__LINE__);
  2316. return FALSE;
  2317. }
  2318. InitializeListHead( &ProcessEntry->Entry );
  2319. ProcessEntry->ProcessInfo = ProcessInfo;
  2320. ThreadInfo = (PSYSTEM_THREAD_INFORMATION)(ProcessInfo + 1);
  2321. for (i = 0; i < ProcessInfo->NumberOfThreads; i++) {
  2322. ProcessEntry->ThreadInfo[ i ] = ThreadInfo++;
  2323. }
  2324. InsertTailList( &ProcessListHead, &ProcessEntry->Entry );
  2325. if (ProcessInfo->NextEntryOffset == 0) {
  2326. break;
  2327. }
  2328. TotalOffset += ProcessInfo->NextEntryOffset;
  2329. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)
  2330. ((PCHAR)ProcessInformation + TotalOffset);
  2331. }
  2332. return TRUE;
  2333. }
  2334. ////////////////////////////////////////////////////////////////////////////////////////////
  2335. PSYSTEM_PROCESS_INFORMATION
  2336. FindProcessInfoForCid(
  2337. IN HANDLE UniqueProcessId
  2338. )
  2339. {
  2340. PLIST_ENTRY Next, Head;
  2341. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  2342. PPROCESS_INFO ProcessEntry;
  2343. UCHAR NameBuffer[ 64 ];
  2344. ANSI_STRING AnsiString;
  2345. Head = &ProcessListHead;
  2346. Next = Head->Flink;
  2347. while (Next != Head) {
  2348. ProcessEntry = CONTAINING_RECORD( Next,
  2349. PROCESS_INFO,
  2350. Entry
  2351. );
  2352. ProcessInfo = ProcessEntry->ProcessInfo;
  2353. if (ProcessInfo->UniqueProcessId == UniqueProcessId) {
  2354. return ProcessInfo;
  2355. }
  2356. Next = Next->Flink;
  2357. }
  2358. ProcessEntry = RtlAllocateHeap( RtlProcessHeap(),
  2359. HEAP_ZERO_MEMORY,
  2360. sizeof( *ProcessEntry ) +
  2361. sizeof( *ProcessInfo )
  2362. );
  2363. ProcessInfo = (PSYSTEM_PROCESS_INFORMATION)(ProcessEntry+1);
  2364. ProcessEntry->ProcessInfo = ProcessInfo;
  2365. NameBuffer[sizeof(NameBuffer) - 1] = 0;
  2366. _snprintf( NameBuffer, sizeof(NameBuffer) - 1,
  2367. "Unknown Process (%p)", UniqueProcessId );
  2368. RtlInitAnsiString( &AnsiString, NameBuffer );
  2369. RtlAnsiStringToUnicodeString( (PUNICODE_STRING)&ProcessInfo->ImageName, &AnsiString, TRUE );
  2370. ProcessInfo->UniqueProcessId = UniqueProcessId;
  2371. InitializeListHead( &ProcessEntry->Entry );
  2372. InsertTailList( &ProcessListHead, &ProcessEntry->Entry );
  2373. return ProcessInfo;
  2374. }
  2375. ////////////////////////////////////////////////////////////////////////////////////////////
  2376. VOID
  2377. DumpSystemThread(
  2378. PSYSTEM_THREAD_INFORMATION ThreadInfo
  2379. )
  2380. {
  2381. UCHAR Buffer[ MAX_PATH ];
  2382. Buffer[ 0 ] = '\0';
  2383. GetDhSymbolicNameForAddress( NULL, (ULONG_PTR)ThreadInfo->StartAddress, Buffer, sizeof( Buffer ) );
  2384. //
  2385. // Make sure we terminate the buffer
  2386. //
  2387. Buffer[sizeof(Buffer) - 1] = 0;
  2388. _snprintf( DumpLine, sizeof(DumpLine) - 1,
  2389. " Thread Id: %p Start Address: %p (%s)\n",
  2390. ThreadInfo->ClientId.UniqueThread,
  2391. ThreadInfo->StartAddress,
  2392. Buffer
  2393. );
  2394. DumpOutputString();
  2395. return;
  2396. }
  2397. ////////////////////////////////////////////////////////////////////////////////////////////
  2398. VOID
  2399. DumpSystemProcess(
  2400. PPROCESS_INFO ProcessEntry
  2401. )
  2402. {
  2403. PSYSTEM_PROCESS_INFORMATION ProcessInfo;
  2404. ULONG ThreadNumber;
  2405. ProcessInfo = ProcessEntry->ProcessInfo;
  2406. _snprintf( DumpLine, sizeof(DumpLine) - 1,
  2407. "\n\n*********** %p (%wZ) Information ********************\n\n",
  2408. ProcessInfo->UniqueProcessId,
  2409. &ProcessInfo->ImageName
  2410. );
  2411. DumpOutputString();
  2412. if (ProcessInfo->InheritedFromUniqueProcessId) {
  2413. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Parent Process: %p (%wZ)\n",
  2414. ProcessInfo->InheritedFromUniqueProcessId,
  2415. &(FindProcessInfoForCid( ProcessInfo->InheritedFromUniqueProcessId )->ImageName)
  2416. );
  2417. DumpOutputString();
  2418. }
  2419. _snprintf( DumpLine, sizeof(DumpLine) - 1, " BasePriority: %u\n",
  2420. ProcessInfo->BasePriority
  2421. );
  2422. DumpOutputString();
  2423. _snprintf( DumpLine, sizeof(DumpLine) - 1, " VirtualSize: %08x\n",
  2424. ProcessInfo->VirtualSize
  2425. );
  2426. DumpOutputString();
  2427. _snprintf( DumpLine, sizeof(DumpLine) - 1, " PeakVirtualSize: %08x\n",
  2428. ProcessInfo->PeakVirtualSize
  2429. );
  2430. DumpOutputString();
  2431. _snprintf( DumpLine, sizeof(DumpLine) - 1, " WorkingSetSize: %08x\n",
  2432. ProcessInfo->WorkingSetSize
  2433. );
  2434. DumpOutputString();
  2435. _snprintf( DumpLine, sizeof(DumpLine) - 1, " PeakWorkingSetSize: %08x\n",
  2436. ProcessInfo->PeakWorkingSetSize
  2437. );
  2438. DumpOutputString();
  2439. _snprintf( DumpLine, sizeof(DumpLine) - 1, " PagefileUsage: %08x\n",
  2440. ProcessInfo->PagefileUsage
  2441. );
  2442. DumpOutputString();
  2443. _snprintf( DumpLine, sizeof(DumpLine) - 1, " PeakPagefileUsage: %08x\n",
  2444. ProcessInfo->PeakPagefileUsage
  2445. );
  2446. DumpOutputString();
  2447. _snprintf( DumpLine, sizeof(DumpLine) - 1, " PageFaultCount: %08x\n",
  2448. ProcessInfo->PageFaultCount
  2449. );
  2450. DumpOutputString();
  2451. _snprintf( DumpLine, sizeof(DumpLine) - 1, " PrivatePageCount: %08x\n",
  2452. ProcessInfo->PrivatePageCount
  2453. );
  2454. DumpOutputString();
  2455. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Number of Threads: %u\n",
  2456. ProcessInfo->NumberOfThreads
  2457. );
  2458. DumpOutputString();
  2459. for (ThreadNumber=0; ThreadNumber<ProcessInfo->NumberOfThreads; ThreadNumber++) {
  2460. DumpSystemThread( ProcessEntry->ThreadInfo[ ThreadNumber ] );
  2461. }
  2462. return;
  2463. }
  2464. ////////////////////////////////////////////////////////////////////////////////////////////
  2465. VOID
  2466. DumpSystemProcesses( VOID )
  2467. {
  2468. PLIST_ENTRY Next, Head;
  2469. PPROCESS_INFO ProcessEntry;
  2470. if (fVerbose) {
  2471. fprintf( stderr, "DH: Dumping object information.\n" );
  2472. }
  2473. _snprintf( DumpLine, sizeof(DumpLine) - 1, "\n\n*********** Process Information ********************\n\n" );
  2474. DumpOutputString();
  2475. Head = &ProcessListHead;
  2476. Next = Head->Flink;
  2477. while (Next != Head) {
  2478. ProcessEntry = CONTAINING_RECORD( Next,
  2479. PROCESS_INFO,
  2480. Entry
  2481. );
  2482. DumpSystemProcess( ProcessEntry );
  2483. Next = Next->Flink;
  2484. }
  2485. return;
  2486. }
  2487. ////////////////////////////////////////////////////////////////////////////////////////////
  2488. VOID
  2489. DumpObjects( VOID )
  2490. {
  2491. PSYSTEM_OBJECTTYPE_INFORMATION TypeInfo;
  2492. PSYSTEM_OBJECT_INFORMATION ObjectInfo;
  2493. PRTL_PROCESS_BACKTRACE_INFORMATION BackTraceInfo;
  2494. UNICODE_STRING ObjectName;
  2495. PUCHAR s;
  2496. ULONG spaceLeft;
  2497. int result;
  2498. if (fVerbose) {
  2499. fprintf( stderr, "DH: Dumping object information.\n" );
  2500. }
  2501. _snprintf( DumpLine, sizeof(DumpLine) - 1, "\n\n*********** Object Information ********************\n\n" );
  2502. DumpOutputString();
  2503. TypeInfo = ObjectInformation;
  2504. while (TRUE) {
  2505. _snprintf( DumpLine, sizeof(DumpLine) - 1, "\n\n*********** %wZ Object Type ********************\n\n",
  2506. &TypeInfo->TypeName
  2507. );
  2508. DumpOutputString();
  2509. _snprintf( DumpLine, sizeof(DumpLine) - 1, " NumberOfObjects: %u\n", TypeInfo->NumberOfObjects );
  2510. DumpOutputString();
  2511. ObjectInfo = (PSYSTEM_OBJECT_INFORMATION)
  2512. ((PCHAR)TypeInfo->TypeName.Buffer + TypeInfo->TypeName.MaximumLength);
  2513. while (TRUE) {
  2514. ObjectName = ObjectInfo->NameInfo.Name;
  2515. try {
  2516. if (ObjectName.Length != 0 && *ObjectName.Buffer == UNICODE_NULL) {
  2517. ObjectName.Length = 0;
  2518. }
  2519. _snprintf( DumpLine, sizeof(DumpLine) - 1,
  2520. " Object: %p Name: %wZ Creator: %wZ (Backtrace%05lu)\n",
  2521. ObjectInfo->Object,
  2522. &ObjectName,
  2523. &(FindProcessInfoForCid( ObjectInfo->CreatorUniqueProcess )->ImageName),
  2524. ObjectInfo->CreatorBackTraceIndex
  2525. );
  2526. }
  2527. except( EXCEPTION_EXECUTE_HANDLER ) {
  2528. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Object: %p Name: [%04x, %04x, %p]\n",
  2529. ObjectInfo->Object,
  2530. ObjectName.MaximumLength,
  2531. ObjectName.Length,
  2532. ObjectName.Buffer
  2533. );
  2534. }
  2535. DumpOutputString();
  2536. BackTraceInfo = FindBackTrace( ObjectInfo->CreatorBackTraceIndex );
  2537. if (BackTraceInfo != NULL && (s = BackTraceInfo->SymbolicBackTrace)) {
  2538. while (*s) {
  2539. _snprintf( DumpLine, sizeof(DumpLine) - 1, " %s\n", s );
  2540. DumpOutputString();
  2541. while (*s++) {
  2542. }
  2543. }
  2544. }
  2545. //
  2546. // BogdanA: 02/19/2002 Make sure we do not oveflow
  2547. // DumpLine. If one _snprintf cannot write all the stuff,
  2548. // we will print what we have so far and move on
  2549. // DumpLine is guaranteed to be NULL terminated
  2550. //
  2551. s = DumpLine;
  2552. spaceLeft = sizeof(DumpLine) - 1;
  2553. result = _snprintf( s,
  2554. spaceLeft,
  2555. "\n PointerCount: %u HandleCount: %u",
  2556. ObjectInfo->PointerCount,
  2557. ObjectInfo->HandleCount
  2558. );
  2559. if (result < 0) {
  2560. DumpOutputString();
  2561. continue;
  2562. } else {
  2563. s += result;
  2564. spaceLeft -= result;
  2565. }
  2566. if (ObjectInfo->SecurityDescriptor != NULL) {
  2567. result = _snprintf( s, spaceLeft,
  2568. " Security: %p", ObjectInfo->SecurityDescriptor );
  2569. if (result < 0) {
  2570. DumpOutputString();
  2571. continue;
  2572. } else {
  2573. s += result;
  2574. spaceLeft -= result;
  2575. }
  2576. }
  2577. if (ObjectInfo->ExclusiveProcessId) {
  2578. result = _snprintf( s,
  2579. spaceLeft,
  2580. " Exclusive by Process: %p", ObjectInfo->ExclusiveProcessId );
  2581. if (result < 0) {
  2582. DumpOutputString();
  2583. continue;
  2584. } else {
  2585. s += result;
  2586. spaceLeft -= result;
  2587. }
  2588. }
  2589. result = _snprintf( s, spaceLeft,
  2590. " Flags: %02x", ObjectInfo->Flags );
  2591. if (result < 0) {
  2592. DumpOutputString();
  2593. continue;
  2594. } else {
  2595. s += result;
  2596. spaceLeft -= result;
  2597. }
  2598. if (ObjectInfo->Flags & OB_FLAG_NEW_OBJECT) {
  2599. result = _snprintf( s, spaceLeft, " New" );
  2600. if (result < 0) {
  2601. DumpOutputString();
  2602. continue;
  2603. } else {
  2604. s += result;
  2605. spaceLeft -= result;
  2606. }
  2607. }
  2608. if (ObjectInfo->Flags & OB_FLAG_KERNEL_OBJECT) {
  2609. result = _snprintf( s, spaceLeft, " KernelMode" );
  2610. if (result < 0) {
  2611. DumpOutputString();
  2612. continue;
  2613. } else {
  2614. s += result;
  2615. spaceLeft -= result;
  2616. }
  2617. }
  2618. if (ObjectInfo->Flags & OB_FLAG_PERMANENT_OBJECT) {
  2619. result = _snprintf( s, spaceLeft, " Permanent" );
  2620. if (result < 0) {
  2621. DumpOutputString();
  2622. continue;
  2623. } else {
  2624. s += result;
  2625. spaceLeft -= result;
  2626. }
  2627. }
  2628. if (ObjectInfo->Flags & OB_FLAG_DEFAULT_SECURITY_QUOTA) {
  2629. result = _snprintf( s, spaceLeft, " DefaultSecurityQuota" );
  2630. if (result < 0) {
  2631. DumpOutputString();
  2632. continue;
  2633. } else {
  2634. s += result;
  2635. spaceLeft -= result;
  2636. }
  2637. }
  2638. if (ObjectInfo->Flags & OB_FLAG_SINGLE_HANDLE_ENTRY) {
  2639. _snprintf( s, spaceLeft, " Single Handle Entry\n" );
  2640. } else {
  2641. _snprintf( s, spaceLeft, "\n" );
  2642. }
  2643. DumpOutputString();
  2644. if (ObjectInfo->HandleCount != 0) {
  2645. PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX HandleEntry;
  2646. ULONG HandleNumber;
  2647. HandleEntry = &HandleInformation->Handles[ 0 ];
  2648. HandleNumber = 0;
  2649. while (HandleNumber++ < HandleInformation->NumberOfHandles) {
  2650. if (((HandleEntry->HandleAttributes & 0x80) && HandleEntry->Object == ObjectInfo) ||
  2651. (!(HandleEntry->HandleAttributes & 0x80) && HandleEntry->Object == ObjectInfo->Object)
  2652. ) {
  2653. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Handle: %08lx Access:%08lx Process: %wZ\n",
  2654. HandleEntry->HandleValue,
  2655. HandleEntry->GrantedAccess,
  2656. &(FindProcessInfoForCid( (HANDLE)HandleEntry->UniqueProcessId )->ImageName)
  2657. );
  2658. DumpOutputString();
  2659. }
  2660. HandleEntry++;
  2661. }
  2662. }
  2663. _snprintf( DumpLine, sizeof(DumpLine) - 1, "\n" );
  2664. DumpOutputString();
  2665. if (ObjectInfo->NextEntryOffset == 0) {
  2666. break;
  2667. }
  2668. ObjectInfo = (PSYSTEM_OBJECT_INFORMATION)
  2669. ((PCHAR)ObjectInformation + ObjectInfo->NextEntryOffset);
  2670. }
  2671. if (TypeInfo->NextEntryOffset == 0) {
  2672. break;
  2673. }
  2674. TypeInfo = (PSYSTEM_OBJECTTYPE_INFORMATION)
  2675. ((PCHAR)ObjectInformation + TypeInfo->NextEntryOffset);
  2676. }
  2677. return;
  2678. }
  2679. ////////////////////////////////////////////////////////////////////////////////////////////
  2680. VOID
  2681. DumpHandles( VOID )
  2682. {
  2683. PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX HandleEntry;
  2684. HANDLE PreviousUniqueProcessId;
  2685. ULONG HandleNumber;
  2686. PRTL_PROCESS_BACKTRACE_INFORMATION BackTraceInfo;
  2687. PSYSTEM_OBJECT_INFORMATION ObjectInfo;
  2688. PVOID Object;
  2689. PUCHAR s;
  2690. if (fVerbose) {
  2691. fprintf( stderr, "DH: Dumping handle information.\n" );
  2692. }
  2693. _snprintf( DumpLine, sizeof(DumpLine) - 1, "\n\n*********** Object Handle Information ********************\n\n" );
  2694. DumpOutputString();
  2695. _snprintf( DumpLine, sizeof(DumpLine) - 1, "Number of handles: %u\n", HandleInformation->NumberOfHandles );
  2696. DumpOutputString();
  2697. HandleEntry = &HandleInformation->Handles[ 0 ];
  2698. HandleNumber = 0;
  2699. PreviousUniqueProcessId = INVALID_HANDLE_VALUE;
  2700. while (HandleNumber++ < HandleInformation->NumberOfHandles) {
  2701. if (PreviousUniqueProcessId != (HANDLE)HandleEntry->UniqueProcessId) {
  2702. PreviousUniqueProcessId = (HANDLE)HandleEntry->UniqueProcessId;
  2703. _snprintf( DumpLine, sizeof(DumpLine) - 1, "\n\n*********** Handles for %wZ ********************\n\n",
  2704. &(FindProcessInfoForCid( PreviousUniqueProcessId )->ImageName)
  2705. );
  2706. DumpOutputString();
  2707. }
  2708. if (HandleEntry->HandleAttributes & 0x80) {
  2709. ObjectInfo = HandleEntry->Object;
  2710. Object = ObjectInfo->Object;
  2711. }
  2712. else {
  2713. ObjectInfo = NULL;
  2714. Object = HandleEntry->Object;
  2715. }
  2716. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Handle: %08lx%c Type: %wZ Object: %p Access: %08lx\n",
  2717. HandleEntry->HandleValue,
  2718. HandleEntry->HandleAttributes & OBJ_INHERIT ? 'i' : ' ',
  2719. TypeNames[ HandleEntry->ObjectTypeIndex < MAX_TYPE_NAMES ? HandleEntry->ObjectTypeIndex : MAX_TYPE_NAMES ],
  2720. Object,
  2721. HandleEntry->GrantedAccess
  2722. );
  2723. DumpOutputString();
  2724. if (ObjectInfo != NULL) {
  2725. UNICODE_STRING ObjectName;
  2726. ObjectName = ObjectInfo->NameInfo.Name;
  2727. try {
  2728. if (ObjectName.Length != 0 && *ObjectName.Buffer == UNICODE_NULL) {
  2729. ObjectName.Length = 0;
  2730. }
  2731. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Name: %wZ\n",
  2732. &ObjectName
  2733. );
  2734. }
  2735. except( EXCEPTION_EXECUTE_HANDLER ) {
  2736. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Name: [%04x, %04x, %p]\n",
  2737. ObjectName.MaximumLength,
  2738. ObjectName.Length,
  2739. ObjectName.Buffer
  2740. );
  2741. }
  2742. DumpOutputString();
  2743. }
  2744. if (HandleEntry->CreatorBackTraceIndex != 0) {
  2745. _snprintf( DumpLine, sizeof(DumpLine) - 1, " Creator: (Backtrace%05lu)\n", HandleEntry->CreatorBackTraceIndex );
  2746. DumpOutputString();
  2747. BackTraceInfo = FindBackTrace( HandleEntry->CreatorBackTraceIndex );
  2748. if (BackTraceInfo != NULL && (s = BackTraceInfo->SymbolicBackTrace)) {
  2749. while (*s) {
  2750. _snprintf( DumpLine, sizeof(DumpLine) - 1, " %s\n", s );
  2751. DumpOutputString();
  2752. while (*s++) {
  2753. }
  2754. }
  2755. }
  2756. }
  2757. _snprintf( DumpLine, sizeof(DumpLine) - 1, " \n" );
  2758. DumpOutputString();
  2759. HandleEntry++;
  2760. }
  2761. return;
  2762. }
  2763. ////////////////////////////////////////////////////////////////////////////////////////////
  2764. int
  2765. GetDhSymbolicNameForAddress(
  2766. IN HANDLE UniqueProcess,
  2767. IN ULONG_PTR Address,
  2768. OUT LPSTR Name,
  2769. IN ULONG MaxNameLength
  2770. )
  2771. //
  2772. // BogdanA, 02/19/2002: Name is not guaranteed to be NULL terminated by this
  2773. // function
  2774. // The function may also return a negative value. If this happens, the caller is
  2775. // required to handle it and terminate the buffer.
  2776. //
  2777. {
  2778. IMAGEHLP_MODULE ModuleInfo;
  2779. ULONG i, ModuleNameLength;
  2780. int Result;
  2781. ULONG_PTR Offset;
  2782. LPSTR s;
  2783. ModuleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE);
  2784. ModuleNameLength = 0;
  2785. if (SymGetModuleInfo( UniqueProcess, Address, &ModuleInfo )) {
  2786. ModuleNameLength = strlen( ModuleInfo.ModuleName );
  2787. }
  2788. if (SymGetSymFromAddr( UniqueProcess, Address, &Offset, sym )) {
  2789. s = sym->Name;
  2790. i = 1;
  2791. while ( sym->MaxNameLength > i &&
  2792. isdigit( s[ sym->MaxNameLength - i ] )
  2793. ) {
  2794. i += 1;
  2795. }
  2796. if (s[ sym->MaxNameLength - i ] == '@') {
  2797. sym->MaxNameLength = sym->MaxNameLength - i;
  2798. }
  2799. s = Name;
  2800. Result = _snprintf( s, MaxNameLength,
  2801. "%.*s!%s",
  2802. ModuleNameLength,
  2803. ModuleInfo.ModuleName,
  2804. sym->Name
  2805. );
  2806. //
  2807. // Make sure we do not attempt to manipulate negative values
  2808. //
  2809. if (Result < 0) {
  2810. return Result;
  2811. }
  2812. if (Offset != 0) {
  2813. Result += _snprintf( s + Result, MaxNameLength - Result, "+0x%x", Offset );
  2814. }
  2815. }
  2816. else {
  2817. if (ModuleNameLength != 0) {
  2818. Result = _snprintf( Name, MaxNameLength,
  2819. "%.*s!0x%08x",
  2820. ModuleNameLength,
  2821. ModuleInfo.ModuleName,
  2822. Address
  2823. );
  2824. }
  2825. else {
  2826. Result = _snprintf( Name, MaxNameLength, "0x%08x", Address );
  2827. }
  2828. }
  2829. return Result;
  2830. }