Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

824 lines
24 KiB

  1. /*++
  2. Copyright (c) 1992-2000 Microsoft Corporation
  3. Module Name:
  4. handle.c
  5. Abstract:
  6. WinDbg Extension Api
  7. Revision History:
  8. --*/
  9. #include "precomp.h"
  10. #pragma hdrstop
  11. BOOL
  12. DumpHandles (
  13. IN ULONG64 RealProcessBase,
  14. IN ULONG64 HandleToDump,
  15. IN ULONG64 pObjectType,
  16. IN ULONG Flags
  17. );
  18. BOOLEAN
  19. DumpHandle(
  20. IN ULONG64 pHandleTableEntry,
  21. IN ULONG64 Handle,
  22. IN ULONG64 pObjectType,
  23. IN ULONG Flags
  24. );
  25. DECLARE_API( handle )
  26. /*++
  27. Routine Description:
  28. Dump the active handles
  29. Arguments:
  30. args - [handle-to-dump [flags [process-to-dump [TypeName]]]]
  31. if handle-to-dump is 0 dump all, otherwise it's the handle to dump.
  32. if process-to-dump is 0 dump all. if nonzero, it can be either an
  33. EPROCESS pointer or a PID.
  34. flags bit meanings:
  35. 0x2 Dump the object
  36. 0x4 Dump free entries
  37. 0x10 Dump kernel handle table
  38. 0x20 Dump psp cid handle table
  39. Examples:
  40. !handle 0 3 ffffffff Section
  41. means dump all Section handles (using verbosity flags=3) for the current process.
  42. -----
  43. !handle 0 3 ffffffff
  44. means dump all handles (using verbosity flags=3) for the current process.
  45. -----
  46. !handle 0 3 0
  47. means dump all handles (using verbosity flags=3) for all processes.
  48. -----
  49. !handle 0 10 ffffffff Section
  50. means dump Section entries in the kernel handle table (using verbosity flags=3).
  51. Return Value:
  52. None
  53. --*/
  54. {
  55. ULONG64 ProcessToDump;
  56. ULONG64 HandleToDump;
  57. ULONG Flags;
  58. ULONG Result;
  59. ULONG nArgs;
  60. ULONG64 Next = 0;
  61. ULONG64 ProcessHead = 1;
  62. ULONG64 Process;
  63. char TypeName[ MAX_PATH ];
  64. ULONG64 pObjectType;
  65. ULONG64 UserProbeAddress;
  66. ULONG ActiveProcessLinksOffset=0;
  67. ULONG64 UniqueProcessId=0, ActiveProcessLinks_Flink=0;
  68. FIELD_INFO procLink[] = {
  69. {"ActiveProcessLinks", "", 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL},
  70. {"UniqueProcessId", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &UniqueProcessId},
  71. {"ActiveProcessLinks.Flink","", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &ActiveProcessLinks_Flink},
  72. };
  73. SYM_DUMP_PARAM EProc = {
  74. sizeof (SYM_DUMP_PARAM), "nt!_EPROCESS", DBG_DUMP_NO_PRINT, 0,
  75. NULL, NULL, NULL, 3, &procLink[0],
  76. };
  77. ULONG dwProcessor=0;
  78. CHAR Addr1[100], Addr2[100];
  79. GetCurrentProcessor(Client, &dwProcessor, NULL);
  80. HandleToDump = 0;
  81. Flags = 0x3; //by default dump bodies and objects for in use entries
  82. ProcessToDump = -1;
  83. UserProbeAddress = GetNtDebuggerDataValue(MmUserProbeAddress);
  84. dprintf("processor number %d\n", dwProcessor);
  85. Addr1[0] = 0;
  86. Addr2[0] = 0;
  87. nArgs = 0;
  88. if (GetExpressionEx(args, &HandleToDump, &args)) {
  89. ULONG64 tmp;
  90. ++nArgs;
  91. if (GetExpressionEx(args, &tmp, &args) && args) {
  92. ULONG i;
  93. Flags = (ULONG) tmp;
  94. ++nArgs;
  95. while (*args == ' ') {
  96. ++args;
  97. }
  98. // Do not use GetExpressionEx since it will search for TypeName
  99. // in symbols
  100. i=0;
  101. while (*args && (*args != ' ')) {
  102. Addr1[i++] = *args++;
  103. }
  104. Addr1[i] = 0;
  105. if (Addr1[0]) {
  106. ProcessToDump = GetExpression(Addr1);
  107. ++nArgs;
  108. while (*args == ' ') {
  109. ++args;
  110. }
  111. if (StringCchCopy(TypeName, sizeof(TypeName), args) != S_OK)
  112. {
  113. TypeName[0] = 0;
  114. }
  115. if (TypeName[0]) ++nArgs;
  116. }
  117. }
  118. }
  119. pObjectType = 0;
  120. if (nArgs > 3 && FetchObjectManagerVariables(FALSE)) {
  121. pObjectType = FindObjectType( TypeName );
  122. }
  123. if (ProcessToDump == 0) {
  124. dprintf("**** NT ACTIVE PROCESS HANDLE DUMP ****\n");
  125. if (Flags == 0xFFFFFFFF) {
  126. Flags = 1;
  127. }
  128. }
  129. else if (ProcessToDump == -1) {
  130. GetCurrentProcessAddr( dwProcessor, 0, &ProcessToDump );
  131. if (ProcessToDump == 0) {
  132. dprintf("Unable to get current process pointer.\n");
  133. return E_INVALIDARG;
  134. }
  135. }
  136. if (ProcessToDump < UserProbeAddress) {
  137. //
  138. // If a process id is specified, then search the active process list
  139. // for the specified process id.
  140. //
  141. ULONG64 List_Flink=0, List_Blink=0;
  142. FIELD_INFO listFields[] = {
  143. {"Flink", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &List_Flink},
  144. {"Blink", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &List_Blink},
  145. };
  146. SYM_DUMP_PARAM Lst = {
  147. sizeof (SYM_DUMP_PARAM), "nt!_LIST_ENTRY", DBG_DUMP_NO_PRINT,
  148. 0, NULL, NULL, NULL, 2, &listFields[0]
  149. };
  150. ProcessHead = GetNtDebuggerData( PsActiveProcessHead );
  151. if ( !ProcessHead ) {
  152. dprintf("Unable to get value of PsActiveProcessHead\n");
  153. return E_INVALIDARG;
  154. }
  155. Lst.addr = ProcessHead;
  156. if (Ioctl(IG_DUMP_SYMBOL_INFO, &Lst, Lst.size)) {
  157. dprintf("Unable to find _LIST_ENTRY type, ProcessHead: %08I64x\n", ProcessHead);
  158. return E_INVALIDARG;
  159. }
  160. if (ProcessToDump != 0) {
  161. dprintf("Searching for Process with Cid == %I64lx\n", ProcessToDump);
  162. }
  163. Next = List_Flink;
  164. if (Next == 0) {
  165. dprintf("PsActiveProcessHead is NULL!\n");
  166. return E_INVALIDARG;
  167. }
  168. }
  169. if (GetFieldOffset("nt!_EPROCESS", "ActiveProcessLinks", &ActiveProcessLinksOffset)) {
  170. dprintf("Unable to find _EPROCESS type\n");
  171. return E_INVALIDARG;
  172. }
  173. if (pObjectType != 0) {
  174. dprintf("Searching for handles of type %s\n", TypeName);
  175. }
  176. while (Next != ProcessHead) {
  177. if ( CheckControlC() ) {
  178. return E_INVALIDARG;
  179. }
  180. if (Next != 0) {
  181. Process = Next - ActiveProcessLinksOffset;
  182. } else {
  183. Process = ProcessToDump;
  184. }
  185. EProc.addr = Process;
  186. if (Ioctl(IG_DUMP_SYMBOL_INFO, &EProc, EProc.size)) {
  187. dprintf("_EPROCESS Ioctl failed at %p\n",Process);
  188. return E_INVALIDARG;
  189. }
  190. if (ProcessToDump == 0 ||
  191. ProcessToDump < UserProbeAddress && ProcessToDump == UniqueProcessId ||
  192. ProcessToDump >= UserProbeAddress && ProcessToDump == Process
  193. ) {
  194. if (DumpProcess ("", Process, 0, NULL)) {
  195. if (!DumpHandles ( Process, HandleToDump, pObjectType, Flags)) {
  196. break;
  197. }
  198. } else {
  199. break;
  200. }
  201. }
  202. if (Next == 0) {
  203. break;
  204. }
  205. Next = ActiveProcessLinks_Flink;
  206. }
  207. return S_OK;
  208. }
  209. #define KERNEL_HANDLE_MASK 0x80000000
  210. //+---------------------------------------------------------------------------
  211. //
  212. // Function: DumpHandles
  213. //
  214. // Synopsis: Dump the handle table for the given process
  215. //
  216. // Arguments: [RealProcessBase] -- base address of the process
  217. // [HandleToDump] -- handle to look for - if 0 dump all
  218. // [pObjectType] -- object type to look for
  219. // [Flags] -- flags passed thru to DumpHandle
  220. // if 0x10 is set dump the kernel handle table
  221. //
  222. // Returns: TRUE if successful
  223. //
  224. // History: 1-12-1998 benl Created
  225. //
  226. // Notes: Each segment of table has 0xFF or 8 bits worth of entries
  227. // the handle number's lowest 2 bit are application defined
  228. // so the indexes are gotten from the 3 8 bits ranges after
  229. // the first 2 bits
  230. //
  231. //----------------------------------------------------------------------------
  232. BOOL
  233. DumpHandles (
  234. IN ULONG64 RealProcessBase,
  235. IN ULONG64 HandleToDump,
  236. IN ULONG64 pObjectType,
  237. IN ULONG Flags
  238. )
  239. {
  240. ULONG64 ObjectTable=0;
  241. ULONG ulRead;
  242. ULONG64 ulTopLevel;
  243. ULONG64 ulMidLevel;
  244. ULONG ulHandleNum = ((ULONG)(HandleToDump) >> 2);
  245. ULONG iIndex1;
  246. ULONG iIndex2;
  247. ULONG iIndex3;
  248. ULONG ptrSize, hTableEntrySize, hTableEntryPointerSize;
  249. ULONG64 tablePtr;
  250. ULONG64 HandleCount = 0;
  251. ULONG64 Table = 0;
  252. ULONG64 UniqueProcessId = 0;
  253. BOOL KernelHandle = FALSE, CidHandle = FALSE;
  254. ULONG LowLevelCounts = 256;
  255. ULONG MidLevelCounts = 256;
  256. ULONG HighLevelCounts = 256;
  257. ULONG TableLevel = 2;
  258. BOOLEAN NewStyle = FALSE;
  259. //
  260. // Typeinfo parsing structures
  261. //
  262. FIELD_INFO procFields[] = {
  263. {"ObjectTable", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &ObjectTable},
  264. };
  265. FIELD_INFO handleTblFields[] = {
  266. {"HandleCount", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &HandleCount},
  267. {"UniqueProcessId", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &UniqueProcessId},
  268. };
  269. SYM_DUMP_PARAM handleSym = {
  270. sizeof (SYM_DUMP_PARAM), "nt!_EPROCESS", DBG_DUMP_NO_PRINT, RealProcessBase,
  271. NULL, NULL, NULL, 1, &procFields[0]
  272. };
  273. //
  274. // Check for kernel handle table
  275. //
  276. if ((Flags & 0x10) || ((ulHandleNum != 0) && (((ULONG_PTR)HandleToDump & KERNEL_HANDLE_MASK) == KERNEL_HANDLE_MASK))) {
  277. ULONG64 KernelTableAddr;
  278. KernelHandle = TRUE;
  279. KernelTableAddr = GetExpression( "nt!ObpKernelHandleTable" );
  280. if (!KernelTableAddr) {
  281. dprintf( "Unable to find ObpKernelHandleTable\n" );
  282. return FALSE;
  283. }
  284. if (!ReadPointer(KernelTableAddr, &ObjectTable)) {
  285. dprintf( "Unable to find ObpKernelHandleTable at %p\n", KernelTableAddr );
  286. return FALSE;
  287. }
  288. } else if (Flags & 0x20) {
  289. CidHandle = TRUE;
  290. ObjectTable = GetNtDebuggerDataValue(PspCidTable);
  291. if (!ObjectTable) {
  292. dprintf( "Unable to find PspCidTable\n" );
  293. return FALSE;
  294. }
  295. } else {
  296. if (Ioctl(IG_DUMP_SYMBOL_INFO, &handleSym, handleSym.size)) {
  297. dprintf("Unable to get ObjectTable address from process %I64x\n", RealProcessBase);
  298. return FALSE;
  299. }
  300. }
  301. ptrSize = DBG_PTR_SIZE;
  302. if (!ptrSize) {
  303. dprintf("Cannot get pointer size\n");
  304. return FALSE;
  305. }
  306. handleSym.sName = "nt!_HANDLE_TABLE"; handleSym.addr = ObjectTable;
  307. handleSym.nFields = sizeof (handleTblFields) / sizeof (FIELD_INFO);
  308. handleSym.Fields = &handleTblFields[0];
  309. if (!ObjectTable ||
  310. Ioctl(IG_DUMP_SYMBOL_INFO, &handleSym, handleSym.size)) {
  311. dprintf("%08p: Unable to read handle table\n",
  312. ObjectTable);
  313. return FALSE;
  314. }
  315. if (GetFieldValue(ObjectTable, "nt!_HANDLE_TABLE", "TableCode", Table)) {
  316. // Could be older build
  317. } else if (!IsPtr64()) {
  318. //
  319. // GetFieldValue doesn't sign extend it since TableCode is defined as dword (not pointer)
  320. //
  321. Table = (ULONG64) (LONG64) (LONG) Table;
  322. }
  323. hTableEntrySize = GetTypeSize("nt!_HANDLE_TABLE_ENTRY");
  324. hTableEntryPointerSize = IsPtr64() ? 8 : 4;
  325. if (hTableEntrySize == 0)
  326. {
  327. dprintf("Cannot get size of nt!_HANDLE_TABLE_ENTRY \n");
  328. return FALSE;
  329. }
  330. if (Table != 0) {
  331. NewStyle = TRUE;
  332. LowLevelCounts = PageSize / hTableEntrySize;
  333. MidLevelCounts = PageSize / hTableEntryPointerSize;
  334. HighLevelCounts = (1<<24) / (LowLevelCounts * MidLevelCounts);
  335. TableLevel = (ULONG)(Table & 3);
  336. Table &= ~((ULONG64)3);
  337. } else if (GetFieldValue(ObjectTable, "nt!_HANDLE_TABLE", "Table", Table) ) {
  338. dprintf("%08p: Unable to read Table field from _HANDLE_TABLE\n",
  339. ObjectTable);
  340. return FALSE;
  341. }
  342. if (KernelHandle) {
  343. dprintf( "Kernel " );
  344. }
  345. else if (CidHandle) {
  346. dprintf( "Cid " );
  347. }
  348. dprintf("%s version of handle table at %p with %I64d %s in use\n",
  349. (NewStyle ? "New" : "Old"),
  350. Table,
  351. HandleCount,
  352. ((HandleCount == 1) ? "Entry" : "Entries"));
  353. if (ulHandleNum != 0) {
  354. if (NewStyle) {
  355. ULONG64 CrtTable = Table;
  356. ULONG64 CrtHandleNum = ulHandleNum;
  357. if (TableLevel == 2) {
  358. ULONG64 HighLevelIndex = ulHandleNum / (LowLevelCounts * MidLevelCounts);
  359. CrtTable = CrtTable + HighLevelIndex * ptrSize;
  360. if (!ReadPointer(CrtTable,
  361. &CrtTable)) {
  362. dprintf("%08p: Unable to read handle table level 3\n", CrtTable );
  363. return FALSE;
  364. }
  365. CrtHandleNum = ulHandleNum - HighLevelIndex * (LowLevelCounts * MidLevelCounts);
  366. }
  367. if (TableLevel == 1) {
  368. CrtTable = CrtTable + (CrtHandleNum / LowLevelCounts) * ptrSize;
  369. if (!ReadPointer(CrtTable,
  370. &CrtTable)) {
  371. dprintf("%08p: Unable to read handle table level 2\n", CrtTable );
  372. return FALSE;
  373. }
  374. CrtHandleNum = CrtHandleNum % LowLevelCounts;
  375. }
  376. tablePtr = CrtTable + CrtHandleNum * hTableEntrySize;
  377. } else {
  378. //
  379. // Read the 3 level table stage by stage to find the specific entry
  380. //
  381. tablePtr = Table + ((ulHandleNum & 0x00FF0000) >> 16) * ptrSize;
  382. ulTopLevel = 0;
  383. if (!ReadPointer(tablePtr,
  384. &ulTopLevel)) {
  385. dprintf("%08p: Unable to read handle table level 3\n", tablePtr );
  386. return FALSE;
  387. }
  388. if (!ulTopLevel) {
  389. dprintf("Invalid handle: 0x%x\n", ulHandleNum);
  390. return FALSE;
  391. }
  392. tablePtr = ulTopLevel + ((ulHandleNum & 0x0000FF00) >> 8) * ptrSize;
  393. ulMidLevel = 0;
  394. if (!ReadPointer(tablePtr,
  395. &ulMidLevel)) {
  396. dprintf("%08p: Unable to read handle table level 2\n", tablePtr);
  397. return FALSE;
  398. }
  399. if (!ulMidLevel) {
  400. dprintf("Invalid handle: 0x%x\n", ulHandleNum);
  401. return FALSE;
  402. }
  403. //
  404. // Read the specific entry req. and dump it
  405. //
  406. tablePtr = (ulMidLevel + (0x000000ff & ulHandleNum) * hTableEntrySize);
  407. }
  408. DumpHandle(tablePtr, HandleToDump, pObjectType, Flags);
  409. } else {
  410. //
  411. // loop over all the possible parts of the table
  412. //
  413. for (iIndex1=0; iIndex1 < HighLevelCounts; iIndex1++) {
  414. //
  415. // check for ctrl-c to abort
  416. //
  417. if (CheckControlC()) {
  418. return FALSE;
  419. }
  420. if (TableLevel < 2) {
  421. tablePtr = Table;
  422. ulTopLevel = tablePtr;
  423. //
  424. // We break the loop second time if we don't have the table level 2
  425. //
  426. if (iIndex1 > 0) {
  427. break;
  428. }
  429. } else {
  430. //
  431. // Read the 3 level table stage by stage to find the specific entry
  432. //
  433. tablePtr = Table + iIndex1 * ptrSize;
  434. ulTopLevel = 0;
  435. if (!ReadPointer(tablePtr,
  436. &ulTopLevel)) {
  437. dprintf("%08p: Unable to read handle table top level\n",
  438. tablePtr);
  439. return FALSE;
  440. }
  441. if (!ulTopLevel) {
  442. continue;
  443. }
  444. }
  445. for (iIndex2=0; iIndex2 < MidLevelCounts; iIndex2++) {
  446. //
  447. // check for ctrl-c to abort
  448. //
  449. if (CheckControlC()) {
  450. return FALSE;
  451. }
  452. if (TableLevel < 1) {
  453. tablePtr = Table;
  454. ulMidLevel = tablePtr;
  455. //
  456. // We break the loop second time if we don't have the table level 1
  457. //
  458. if (iIndex2 > 0) {
  459. break;
  460. }
  461. } else {
  462. tablePtr = ulTopLevel + iIndex2 * ptrSize;
  463. ulMidLevel = 0;
  464. if (!ReadPointer(tablePtr,
  465. &ulMidLevel)) {
  466. dprintf("%08p: Unable to read handle table middle level\n",
  467. tablePtr);
  468. return FALSE;
  469. }
  470. if (!ulMidLevel) {
  471. continue;
  472. }
  473. }
  474. //
  475. // now read all the entries in this segment of the table and dump them
  476. // Note: Handle Number = 6 unused bits + 8 bits high + 8 bits mid +
  477. // 8 bits low + 2 bits user defined
  478. //
  479. for (iIndex3 = 0; iIndex3 < LowLevelCounts; iIndex3++) {
  480. //
  481. // check for ctrl-c to abort
  482. //
  483. if (CheckControlC()) {
  484. return FALSE;
  485. }
  486. DumpHandle(ulMidLevel + iIndex3*hTableEntrySize,
  487. (iIndex3 + (iIndex2 + iIndex1 * MidLevelCounts) * LowLevelCounts) * 4,
  488. pObjectType, Flags);
  489. }
  490. }
  491. } // end outermost for
  492. } // endif on a specific handle
  493. return TRUE;
  494. } // DumpHandles
  495. //+---------------------------------------------------------------------------
  496. //
  497. // Function: DumpHandle
  498. //
  499. // Synopsis: Dump a particular Handle
  500. //
  501. // Arguments: [pHandleTableEntry] -- entry to dump
  502. // [Handle] -- handle number of entry
  503. // [pObjectType] -- only dump if object type matches this
  504. // if NULL dump everything
  505. // [Flags] -- flags if 0x2 also dump the object
  506. // if 0x4 dump free entries
  507. //
  508. // Returns:
  509. //
  510. // History: 1-12-1998 benl Created
  511. //
  512. // Notes:
  513. //
  514. //----------------------------------------------------------------------------
  515. BOOLEAN
  516. DumpHandle(
  517. IN ULONG64 pHandleTableEntry,
  518. IN ULONG64 Handle,
  519. IN ULONG64 pObjectType,
  520. IN ULONG Flags
  521. )
  522. {
  523. ULONG64 ulObjectHeaderAddr;
  524. ULONG Result;
  525. ULONG HandleAttributes;
  526. // OBJECT_HEADER ObjectHeader;
  527. ULONG64 ObjectBody;
  528. ULONG GrantedAccess=0;
  529. ULONG64 Object=0, ObjType=0;
  530. FIELD_INFO hTableEntryFields[] = {
  531. {"Object", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &Object},
  532. {"GrantedAccess", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &GrantedAccess},
  533. };
  534. FIELD_INFO ObjHeaderFields[] = {
  535. {"Type", "", 0, DBG_DUMP_FIELD_COPY_FIELD_DATA, 0, (PVOID) &ObjType},
  536. {"Body", "", 0, DBG_DUMP_FIELD_RETURN_ADDRESS, 0, NULL},
  537. };
  538. SYM_DUMP_PARAM ObjSym = {
  539. sizeof (SYM_DUMP_PARAM), "nt!_HANDLE_TABLE_ENTRY", DBG_DUMP_NO_PRINT, pHandleTableEntry,
  540. NULL, NULL, NULL, sizeof (hTableEntryFields) /sizeof (FIELD_INFO), &hTableEntryFields[0],
  541. };
  542. if (Ioctl (IG_DUMP_SYMBOL_INFO, &ObjSym, ObjSym.size)) {
  543. dprintf("Unable to get _HANDLE_TABLE_ENTRY : %p\n", pHandleTableEntry);
  544. return FALSE;
  545. }
  546. if (!(Object)) {
  547. //only print if flag is set to 4
  548. if (Flags & 4)
  549. {
  550. dprintf("%04lx: free handle, Entry address %p, Next Entry %p\n",
  551. (ULONG)Handle, pHandleTableEntry, GrantedAccess);
  552. }
  553. return TRUE;
  554. }
  555. if (BuildNo > 2230) {
  556. // if (GetExpression( "nt!ObpAccessProtectCloseBit" )) {
  557. //
  558. // we have a new handle table style
  559. //
  560. //actual hdr has the lowest 3 bits cancelled out
  561. //lower 3 bits mark auditing, inheritance and lock
  562. ulObjectHeaderAddr = (Object) & ~(0x7);
  563. //
  564. // Apply the sign extension, if the highest bit is set
  565. //
  566. if ( !IsPtr64() &&
  567. (Object & 0x80000000)) {
  568. ulObjectHeaderAddr |= 0xFFFFFFFF00000000L;
  569. }
  570. } else {
  571. //actual hdr is sign extend value with the lowest 3 bits cancelled out
  572. //top bit marks whether entry is locked
  573. //lower 3 bits mark auditing, inheritance and protection
  574. if (!IsPtr64()) {
  575. ulObjectHeaderAddr = ((Object) & ~(0x7)) | 0xFFFFFFFF80000000L;
  576. } else {
  577. ulObjectHeaderAddr = ((Object) & ~(0x7)) | 0x8000000000000000L;
  578. }
  579. }
  580. ObjSym.sName = "nt!_OBJECT_HEADER"; ObjSym.addr = ulObjectHeaderAddr;
  581. ObjSym.nFields = sizeof (ObjHeaderFields) / sizeof (FIELD_INFO);
  582. ObjSym.Fields = &ObjHeaderFields[0];
  583. if (Ioctl ( IG_DUMP_SYMBOL_INFO, &ObjSym, ObjSym.size)) {
  584. dprintf("%08p: Unable to read nonpaged object header\n",
  585. ulObjectHeaderAddr);
  586. return FALSE;
  587. }
  588. if (pObjectType != 0 && ObjType != pObjectType) {
  589. return TRUE;
  590. }
  591. if (Flags & 0x20) {
  592. //
  593. // PspCidTable contains pointer to object, not object header
  594. // Compute header address based on object.
  595. //
  596. ObjectBody = ulObjectHeaderAddr;
  597. ulObjectHeaderAddr -= ObjHeaderFields[1].address-ulObjectHeaderAddr;
  598. }
  599. else {
  600. ObjectBody = ObjHeaderFields[1].address;
  601. }
  602. dprintf("%04I64lx: Object: %08p GrantedAccess: %08lx",
  603. Handle,
  604. ObjectBody,
  605. (GrantedAccess & ~MAXIMUM_ALLOWED));
  606. if (BuildNo > 2230) {
  607. // if (GetExpression( "nt!ObpAccessProtectCloseBit" )) {
  608. //
  609. // New handle table style
  610. //
  611. if (((ULONG) Object & 1) == 0) {
  612. dprintf(" (Locked)");
  613. }
  614. if (GrantedAccess & MAXIMUM_ALLOWED) {
  615. dprintf(" (Protected)");
  616. }
  617. } else {
  618. if (IsPtr64()) {
  619. if (Object & 0x8000000000000000L) {
  620. dprintf(" (Locked)");
  621. }
  622. } else if ((ULONG) Object & 0x80000000) {
  623. dprintf(" (Locked)");
  624. }
  625. if (Object & 1) {
  626. dprintf(" (Protected)");
  627. }
  628. }
  629. if (Object & 2) {
  630. dprintf(" (Inherit)");
  631. }
  632. if (Object & 4) {
  633. dprintf(" (Audit)");
  634. }
  635. dprintf("\n");
  636. if (Flags & 2) {
  637. DumpObject( " ", ObjectBody, Flags );
  638. }
  639. EXPRLastDump = ObjectBody;
  640. dprintf("\n");
  641. return TRUE;
  642. }