Source code of Windows XP (NT5)
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.

1894 lines
37 KiB

  1. /*++
  2. Copyright (c) 1995-1996 Microsoft Corporation
  3. Module Name:
  4. fcache.cxx
  5. Abstract:
  6. This module contains the cache-related ntsd debugger extensions for
  7. Internet Information Server
  8. Author:
  9. Keith Moore (keithmo) 12-Aug-1997
  10. Revision History:
  11. --*/
  12. #include "inetdbgp.h"
  13. //
  14. // Worker routines.
  15. //
  16. PSTR
  17. DemuxToString(
  18. IN ULONG Demux
  19. )
  20. /*++
  21. Routine Description:
  22. Converts the specified demux value to a printable string.
  23. Arguments:
  24. Demux - The demux value to map.
  25. Return Value:
  26. PSTR - The printable string.
  27. --*/
  28. {
  29. switch( Demux ) {
  30. case RESERVED_DEMUX_START :
  31. return "RESERVED_DEMUX_START";
  32. case RESERVED_DEMUX_DIRECTORY_LISTING :
  33. return "RESERVED_DEMUX_DIRECTORY_LISTING";
  34. case RESERVED_DEMUX_ATOMIC_DIRECTORY_GUARD :
  35. return "RESERVED_DEMUX_ATOMIC_DIRECTORY_GUARD";
  36. case RESERVED_DEMUX_OPEN_FILE :
  37. return "RESERVED_DEMUX_OPEN_FILE";
  38. case RESERVED_DEMUX_URI_INFO :
  39. return "RESERVED_DEMUX_URI_INFO";
  40. case RESERVED_DEMUX_PHYSICAL_OPEN_FILE :
  41. return "RESERVED_DEMUX_PHYSICAL_OPEN_FILE";
  42. default :
  43. return "Unknown";
  44. }
  45. } // DemuxToString
  46. PSTR
  47. SignatureToString(
  48. IN DWORD CurrentSignature,
  49. IN DWORD ValidSignature,
  50. IN DWORD FreedSignature
  51. )
  52. /*++
  53. Routine Description:
  54. Determines an appropriate display string for the given signature.
  55. If the current signature matches the expected valid signature,
  56. then the string "OK" is returned. If the current signature matches
  57. the freed signature, then "FREED" is returned. Otherwise, "INVALID"
  58. is returned.
  59. Arguments:
  60. CurrentSignature - The current signature as retrieved from the
  61. object/structure.
  62. ValidSignature - The expected signature for a valid, in-use
  63. object/structure.
  64. FreedSignature - The signature assigned to the object/structure
  65. just before it is freed.
  66. Return Value:
  67. PSTR - "OK", "FREED", or "INVALID" as appropriate.
  68. --*/
  69. {
  70. if( CurrentSignature == ValidSignature ) {
  71. return "OK";
  72. }
  73. if( CurrentSignature == FreedSignature ) {
  74. return "FREED";
  75. }
  76. return "INVALID";
  77. } // SignatureToString
  78. PSTR
  79. BoolToString(
  80. IN BOOL Flag
  81. )
  82. /*++
  83. Routine Description:
  84. Maps the given BOOL to a displayable string.
  85. Arguments:
  86. Flag - The BOOL flag to map.
  87. Return Value:
  88. PSTR - "TRUE", "FALSE", or "INVALID" as appropriate.
  89. --*/
  90. {
  91. //
  92. // In general, explicit testing for TRUE is a Bad Thing, but in
  93. // this case, it's useful for catching invalid data.
  94. //
  95. if( Flag == TRUE ) {
  96. return "TRUE";
  97. }
  98. if( Flag == FALSE ) {
  99. return "FALSE";
  100. }
  101. return "INVALID";
  102. } // BoolToString
  103. VOID
  104. DumpBlobHeader(
  105. IN PSTR Prefix,
  106. IN PBLOB_HEADER BlobHeader,
  107. IN ULONG ActualAddress
  108. )
  109. /*++
  110. Routine Description:
  111. Formats and dumps a specific BLOB_HEADER structure.
  112. Arguments:
  113. Prefix - The prefix to use before each printed line. This makes
  114. hierarchical object displays much prettier.
  115. BlobHeader - Points to a local copy of the structure.
  116. ActualAddress - The virtual address of the object in the debugee.
  117. Return Value:
  118. None.
  119. --*/
  120. {
  121. ULONG offset;
  122. UCHAR symbol[MAX_PATH];
  123. CHAR renderedSymbol[MAX_PATH];
  124. GetSymbol(
  125. (PVOID)BlobHeader->pfnFreeRoutine,
  126. symbol,
  127. &offset
  128. );
  129. if( symbol[0] == '\0' ) {
  130. renderedSymbol[0] = '\0';
  131. } else if( offset == 0 ) {
  132. sprintf(
  133. renderedSymbol,
  134. " (%s)",
  135. symbol
  136. );
  137. } else {
  138. sprintf(
  139. renderedSymbol,
  140. " (%s+0x%lx)",
  141. symbol,
  142. offset
  143. );
  144. }
  145. dprintf(
  146. "%sBLOB_HEADER @ %08lx\n"
  147. "%s IsCached = %s\n"
  148. "%s pCache = %08lx\n"
  149. "%s PFList @ %08lx%s\n"
  150. "%s pfnFreeRoutine = %08lx%s\n"
  151. "\n",
  152. Prefix,
  153. ActualAddress,
  154. Prefix,
  155. BoolToString( BlobHeader->IsCached ),
  156. Prefix,
  157. BlobHeader->pCache,
  158. Prefix,
  159. ActualAddress + FIELD_OFFSET( BLOB_HEADER, PFList ),
  160. IS_LIST_EMPTY( BlobHeader, ActualAddress, BLOB_HEADER, PFList )
  161. ? " (EMPTY)"
  162. : "",
  163. Prefix,
  164. BlobHeader->pfnFreeRoutine,
  165. renderedSymbol
  166. );
  167. } // DumpBlobHeader
  168. VOID
  169. DumpOpenFileInfo(
  170. IN PSTR Prefix,
  171. IN LPTS_OPEN_FILE_INFO OpenFileInfo,
  172. IN ULONG ActualAddress
  173. )
  174. /*++
  175. Routine Description:
  176. Formats and dumps a specific TS_OPEN_FILE_INFO structure.
  177. Arguments:
  178. Prefix - The prefix to use before each printed line. This makes
  179. hierarchical object displays much prettier.
  180. OpenFileInfo - Points to a local copy of the structure.
  181. ActualAddress - The virtual address of the object in the debugee.
  182. Return Value:
  183. None.
  184. --*/
  185. {
  186. dprintf(
  187. "%sTS_OPEN_FILE_INFO @ %08lx\n"
  188. "%s m_hOpeningUser = %08lx\n"
  189. "%s m_PhysFileInfo = %08lx\n"
  190. "%s m_FileInfo @ %08lx\n"
  191. "%s m_CastratedLastWriteTime @ %08lx\n",
  192. Prefix,
  193. ActualAddress,
  194. Prefix,
  195. OpenFileInfo->m_hOpeningUser,
  196. Prefix,
  197. OpenFileInfo->m_PhysFileInfo,
  198. Prefix,
  199. ActualAddress + FIELD_OFFSET( TS_OPEN_FILE_INFO, m_FileInfo ),
  200. Prefix,
  201. ActualAddress + FIELD_OFFSET( TS_OPEN_FILE_INFO, m_CastratedLastWriteTime )
  202. );
  203. dprintf(
  204. "%s m_achHttpInfo @ %08lx (%s)\n"
  205. "%s m_cchHttpInfo = %lu\n"
  206. "%s m_achETag @ %08lx (%s)\n"
  207. "%s m_cchETag = %lu\n"
  208. "%s m_ETagIsWeak = %s\n"
  209. "%s m_fIsCached = %s\n"
  210. "\n",
  211. Prefix,
  212. ActualAddress + FIELD_OFFSET( TS_OPEN_FILE_INFO, m_achHttpInfo ),
  213. OpenFileInfo->m_achHttpInfo,
  214. Prefix,
  215. OpenFileInfo->m_cchHttpInfo,
  216. Prefix,
  217. ActualAddress + FIELD_OFFSET( TS_OPEN_FILE_INFO, m_achETag ),
  218. OpenFileInfo->m_achETag,
  219. Prefix,
  220. OpenFileInfo->m_cchETag,
  221. Prefix,
  222. BoolToString( OpenFileInfo->m_ETagIsWeak ),
  223. Prefix,
  224. BoolToString( OpenFileInfo->m_fIsCached )
  225. );
  226. } // DumpOpenFileInfo
  227. VOID
  228. DumpUriInfo(
  229. IN PSTR Prefix,
  230. IN PW3_URI_INFO UriInfo,
  231. IN ULONG ActualAddress
  232. )
  233. /*++
  234. Routine Description:
  235. Formats and dumps a specific W3_URI_INFO structure.
  236. Arguments:
  237. Prefix - The prefix to use before each printed line. This makes
  238. hierarchical object displays much prettier.
  239. UriInfo - Points to a local copy of the structure.
  240. ActualAddress - The virtual address of the object in the debugee.
  241. Return Value:
  242. None.
  243. --*/
  244. {
  245. CHAR name[MAX_PATH];
  246. CHAR unmappedName[MAX_PATH];
  247. if( UriInfo->pszName == NULL ) {
  248. strcpy( name, "<null>" );
  249. } else if( !ReadMemory(
  250. (ULONG)UriInfo->pszName,
  251. name,
  252. sizeof(name),
  253. NULL
  254. ) ) {
  255. strcpy( name, "<unreadable>" );
  256. }
  257. if( UriInfo->pszUnmappedName == NULL ) {
  258. strcpy( unmappedName, "<null>" );
  259. } else if( !ReadMemory(
  260. (ULONG)UriInfo->pszUnmappedName,
  261. unmappedName,
  262. sizeof(unmappedName),
  263. NULL
  264. ) ) {
  265. strcpy( unmappedName, "<unreadable>" );
  266. }
  267. dprintf(
  268. "%sW3_URI_INFO @ %08lx\n"
  269. "%s bFileInfoValid = %lu\n"
  270. "%s bIsCached = %s\n"
  271. "%s hFileEvent = %08lx\n"
  272. "%s pOpenFileInfo = %08lx\n",
  273. Prefix,
  274. ActualAddress,
  275. Prefix,
  276. UriInfo->bFileInfoValid,
  277. Prefix,
  278. BoolToString( UriInfo->bIsCached ),
  279. Prefix,
  280. UriInfo->hFileEvent,
  281. Prefix,
  282. UriInfo->pOpenFileInfo
  283. );
  284. dprintf(
  285. "%s dwFileOpenError = %lu\n"
  286. "%s cchName = %lu\n"
  287. "%s pszName = %08lx (%s)\n"
  288. "%s pszUnmappedName = %08lx (%s)\n"
  289. "%s pMetaData = %08lx\n"
  290. "\n",
  291. Prefix,
  292. UriInfo->dwFileOpenError,
  293. Prefix,
  294. UriInfo->cchName,
  295. Prefix,
  296. UriInfo->pszName,
  297. name,
  298. Prefix,
  299. UriInfo->pszUnmappedName,
  300. unmappedName,
  301. Prefix,
  302. UriInfo->pMetaData
  303. );
  304. } // DumpUriInfo
  305. VOID
  306. DumpPhysOpenFileInfo(
  307. IN PSTR Prefix,
  308. IN PPHYS_OPEN_FILE_INFO PhysOpenFileInfo,
  309. IN ULONG ActualAddress
  310. )
  311. /*++
  312. Routine Description:
  313. Formats and dumps a specific PHYS_OPEN_FILE_INFO structure.
  314. Arguments:
  315. Prefix - The prefix to use before each printed line. This makes
  316. hierarchical object displays much prettier.
  317. PhysOpenFileInfo - Points to a local copy of the structure.
  318. ActualAddress - The virtual address of the object in the debugee.
  319. Return Value:
  320. None.
  321. --*/
  322. {
  323. dprintf(
  324. "%sPHYS_OPEN_FILE_INFO @ %08lx\n"
  325. "%s Signature = %08lx (%s)\n"
  326. "%s hOpenFile = %08lx\n"
  327. "%s hOpenEvent = %08lx\n",
  328. Prefix,
  329. ActualAddress,
  330. Prefix,
  331. PhysOpenFileInfo->Signature,
  332. SignatureToString(
  333. PhysOpenFileInfo->Signature,
  334. PHYS_OBJ_SIGNATURE,
  335. PHYS_OBJ_SIGNATURE_X
  336. ),
  337. Prefix,
  338. PhysOpenFileInfo->hOpenFile,
  339. Prefix,
  340. PhysOpenFileInfo->hOpenEvent
  341. );
  342. dprintf(
  343. "%s OpenReferenceList @ %08lx%s\n"
  344. "%s fSecurityDescriptor = %s\n"
  345. "%s fIsCached = %s\n",
  346. Prefix,
  347. ActualAddress + FIELD_OFFSET( PHYS_OPEN_FILE_INFO, OpenReferenceList ),
  348. IS_LIST_EMPTY( PhysOpenFileInfo, ActualAddress, PHYS_OPEN_FILE_INFO, OpenReferenceList )
  349. ? " (EMPTY)"
  350. : "",
  351. Prefix,
  352. BoolToString( PhysOpenFileInfo->fSecurityDescriptor ),
  353. Prefix,
  354. BoolToString( PhysOpenFileInfo->fIsCached )
  355. );
  356. dprintf(
  357. "%s dwLastError = %lu\n"
  358. "%s cbSecDescMaxSize = %lu\n"
  359. "%s abSecurityDescriptor = %08lx\n"
  360. "%s pOplock = %08lx\n"
  361. "\n",
  362. Prefix,
  363. PhysOpenFileInfo->dwLastError,
  364. Prefix,
  365. PhysOpenFileInfo->cbSecDescMaxSize,
  366. Prefix,
  367. PhysOpenFileInfo->abSecurityDescriptor,
  368. Prefix,
  369. PhysOpenFileInfo->pOplock
  370. );
  371. } // DumpPhysOpenFileInfo
  372. VOID
  373. DumpOplockObject(
  374. IN PSTR Prefix,
  375. IN POPLOCK_OBJECT OplockObject,
  376. IN ULONG ActualAddress
  377. )
  378. /*++
  379. Routine Description:
  380. Formats and dumps a specific OPLOCK_OBJECT structure.
  381. Arguments:
  382. Prefix - The prefix to use before each printed line. This makes
  383. hierarchical object displays much prettier.
  384. OplockObject - Points to a local copy of the structure.
  385. ActualAddress - The virtual address of the object in the debugee.
  386. Return Value:
  387. None.
  388. --*/
  389. {
  390. dprintf(
  391. "%sOPLOCK_OBJECT @ %08lx\n"
  392. "%s Signature = %08lx (%s)\n"
  393. "%s lpPFInfo = %08lx\n"
  394. "%s hOplockInitComplete = %08lx\n"
  395. "\n",
  396. Prefix,
  397. ActualAddress,
  398. Prefix,
  399. OplockObject->Signature,
  400. SignatureToString(
  401. OplockObject->Signature,
  402. OPLOCK_OBJ_SIGNATURE,
  403. OPLOCK_OBJ_SIGNATURE_X
  404. ),
  405. Prefix,
  406. OplockObject->lpPFInfo,
  407. Prefix,
  408. OplockObject->hOplockInitComplete
  409. );
  410. } // DumpOplockObject
  411. VOID
  412. DumpOpenFileInfoBlob(
  413. IN PSTR Prefix,
  414. IN PBLOB_HEADER BlobHeader,
  415. IN ULONG ActualAddress
  416. )
  417. /*++
  418. Routine Description:
  419. Formats and dumps a TS_OPEN_FILE_INFO blob.
  420. Arguments:
  421. Prefix - The prefix to use before each printed line. This makes
  422. hierarchical object displays much prettier.
  423. BlobHeader - Points to a local copy of the blob.
  424. ActualAddress - The virtual address of the object in the debugee.
  425. Return Value:
  426. None.
  427. --*/
  428. {
  429. TS_OPEN_FILE_INFO localOpenFileInfo;
  430. if( !ReadMemory(
  431. ActualAddress + sizeof(*BlobHeader),
  432. &localOpenFileInfo,
  433. sizeof(localOpenFileInfo),
  434. NULL
  435. ) ) {
  436. dprintf(
  437. "inetdbg: cannot read TS_OPEN_FILE_INFO @ %08lx\n",
  438. ActualAddress + sizeof(*BlobHeader)
  439. );
  440. return;
  441. }
  442. DumpBlobHeader(
  443. Prefix,
  444. BlobHeader,
  445. ActualAddress
  446. );
  447. DumpOpenFileInfo(
  448. Prefix,
  449. &localOpenFileInfo,
  450. ActualAddress + sizeof(*BlobHeader)
  451. );
  452. } // DumpOpenFileInfoBlob
  453. VOID
  454. DumpUriInfoBlob(
  455. IN PSTR Prefix,
  456. IN PBLOB_HEADER BlobHeader,
  457. IN ULONG ActualAddress
  458. )
  459. /*++
  460. Routine Description:
  461. Formats and dumps a W3_URI_INFO blob.
  462. Arguments:
  463. Prefix - The prefix to use before each printed line. This makes
  464. hierarchical object displays much prettier.
  465. BlobHeader - Points to a local copy of the blob.
  466. ActualAddress - The virtual address of the object in the debugee.
  467. Return Value:
  468. None.
  469. --*/
  470. {
  471. W3_URI_INFO localUriInfo;
  472. if( !ReadMemory(
  473. ActualAddress + sizeof(*BlobHeader),
  474. &localUriInfo,
  475. sizeof(localUriInfo),
  476. NULL
  477. ) ) {
  478. dprintf(
  479. "inetdbg: cannot read W3_URI_INFO @ %08lx\n",
  480. ActualAddress + sizeof(*BlobHeader)
  481. );
  482. return;
  483. }
  484. DumpBlobHeader(
  485. Prefix,
  486. BlobHeader,
  487. ActualAddress
  488. );
  489. DumpUriInfo(
  490. Prefix,
  491. &localUriInfo,
  492. ActualAddress + sizeof(*BlobHeader)
  493. );
  494. } // DumpUriInfoBlob
  495. VOID
  496. DumpPhysOpenFileInfoBlob(
  497. IN PSTR Prefix,
  498. IN PBLOB_HEADER BlobHeader,
  499. IN ULONG ActualAddress
  500. )
  501. /*++
  502. Routine Description:
  503. Formats and dumps a PHYS_OPEN_FILE_INFO blob.
  504. Arguments:
  505. Prefix - The prefix to use before each printed line. This makes
  506. hierarchical object displays much prettier.
  507. BlobHeader - Points to a local copy of the blob.
  508. ActualAddress - The virtual address of the object in the debugee.
  509. Return Value:
  510. None.
  511. --*/
  512. {
  513. PHYS_OPEN_FILE_INFO localPhysOpenFileInfo;
  514. if( !ReadMemory(
  515. ActualAddress + sizeof(*BlobHeader),
  516. &localPhysOpenFileInfo,
  517. sizeof(localPhysOpenFileInfo),
  518. NULL
  519. ) ) {
  520. dprintf(
  521. "inetdbg: cannot read PHYS_OPEN_FILE_INFO @ %08lx\n",
  522. ActualAddress + sizeof(*BlobHeader)
  523. );
  524. return;
  525. }
  526. DumpBlobHeader(
  527. Prefix,
  528. BlobHeader,
  529. ActualAddress
  530. );
  531. DumpPhysOpenFileInfo(
  532. Prefix,
  533. &localPhysOpenFileInfo,
  534. ActualAddress + sizeof(*BlobHeader)
  535. );
  536. } // DumpPhysOpenFileInfo
  537. VOID
  538. DumpCacheObject(
  539. IN PSTR Prefix,
  540. IN PCACHE_OBJECT CacheObject,
  541. IN ULONG ActualAddress,
  542. IN BOOLEAN Verbose
  543. )
  544. /*++
  545. Routine Description:
  546. Formats and dumps a specific CACHE_OBJECT structure.
  547. Arguments:
  548. Prefix - The prefix to use before each printed line. This makes
  549. hierarchical object displays much prettier.
  550. CacheObject - Points to a local copy of the structure.
  551. ActualAddress - The virtual address of the object in the debugee.
  552. Verbose - If TRUE, then also dumps the blob associated with the object.
  553. Return Value:
  554. None.
  555. --*/
  556. {
  557. BLOB_HEADER localBlob;
  558. CHAR path[MAX_PATH+1];
  559. path[0] = '\0';
  560. if( CacheObject->cchLength < MAX_PATH ) {
  561. ReadMemory(
  562. ActualAddress + FIELD_OFFSET( CACHE_OBJECT, szPath ),
  563. path,
  564. CacheObject->cchLength,
  565. NULL
  566. );
  567. path[CacheObject->cchLength] = '\0';
  568. }
  569. dprintf(
  570. "%sCACHE_OBJECT @ %08lx\n"
  571. "%s Signature = %08lx (%s)\n"
  572. "%s BinList @ %08lx%s\n"
  573. "%s MruList @ %08lx%s\n"
  574. "%s DirChangeList @ %08lx%s\n",
  575. Prefix,
  576. ActualAddress,
  577. Prefix,
  578. CacheObject->Signature,
  579. SignatureToString(
  580. CacheObject->Signature,
  581. CACHE_OBJ_SIGNATURE,
  582. CACHE_OBJ_SIGNATURE_X
  583. ),
  584. Prefix,
  585. ActualAddress + FIELD_OFFSET( CACHE_OBJECT, BinList ),
  586. IS_LIST_EMPTY( CacheObject, ActualAddress, CACHE_OBJECT, BinList )
  587. ? " (EMPTY)"
  588. : "",
  589. Prefix,
  590. ActualAddress + FIELD_OFFSET( CACHE_OBJECT, MruList ),
  591. IS_LIST_EMPTY( CacheObject, ActualAddress, CACHE_OBJECT, MruList )
  592. ? " (EMPTY)"
  593. : "",
  594. Prefix,
  595. ActualAddress + FIELD_OFFSET( CACHE_OBJECT, DirChangeList ),
  596. IS_LIST_EMPTY( CacheObject, ActualAddress, CACHE_OBJECT, DirChangeList )
  597. ? " (EMPTY)"
  598. : ""
  599. );
  600. dprintf(
  601. "%s pbhBlob = %08lx\n"
  602. "%s references = %lu\n"
  603. "%s TTL = %lu\n"
  604. "%s hash = %08lx\n",
  605. Prefix,
  606. CacheObject->pbhBlob,
  607. Prefix,
  608. CacheObject->references,
  609. Prefix,
  610. CacheObject->TTL,
  611. Prefix,
  612. CacheObject->hash
  613. );
  614. dprintf(
  615. "%s cchLength = %lu\n"
  616. "%s iDemux = %08lx (%s)\n"
  617. "%s dwService = %08lx\n"
  618. "%s dwInstance = %08lx\n",
  619. Prefix,
  620. CacheObject->cchLength,
  621. Prefix,
  622. CacheObject->iDemux,
  623. DemuxToString( CacheObject->iDemux ),
  624. Prefix,
  625. CacheObject->dwService,
  626. Prefix,
  627. CacheObject->dwInstance
  628. );
  629. dprintf(
  630. "%s pSecDesc = %08lx\n"
  631. "%s hLastSuccessAccessToken = %08lx\n"
  632. "%s fZombie = %s\n"
  633. "%s szPath = %s\n"
  634. "\n",
  635. Prefix,
  636. CacheObject->pSecDesc,
  637. Prefix,
  638. CacheObject->hLastSuccessAccessToken,
  639. Prefix,
  640. BoolToString( CacheObject->fZombie ),
  641. Prefix,
  642. path
  643. );
  644. if( Verbose ) {
  645. CHAR prefix[80];
  646. sprintf(
  647. prefix,
  648. " %s",
  649. Prefix
  650. );
  651. if( !ReadMemory(
  652. (ULONG)CacheObject->pbhBlob,
  653. &localBlob,
  654. sizeof(localBlob),
  655. NULL
  656. ) ) {
  657. dprintf(
  658. "inetdbg: cannot read blob header @ %08lx\n",
  659. CacheObject->pbhBlob
  660. );
  661. return;
  662. }
  663. switch( CacheObject->iDemux ) {
  664. case RESERVED_DEMUX_OPEN_FILE :
  665. DumpOpenFileInfoBlob(
  666. prefix,
  667. &localBlob,
  668. (ULONG)CacheObject->pbhBlob
  669. );
  670. break;
  671. case RESERVED_DEMUX_URI_INFO :
  672. DumpUriInfoBlob(
  673. prefix,
  674. &localBlob,
  675. (ULONG)CacheObject->pbhBlob
  676. );
  677. break;
  678. case RESERVED_DEMUX_PHYSICAL_OPEN_FILE :
  679. DumpPhysOpenFileInfoBlob(
  680. prefix,
  681. &localBlob,
  682. (ULONG)CacheObject->pbhBlob
  683. );
  684. break;
  685. }
  686. }
  687. } // DumpCacheObject
  688. VOID
  689. DumpCacheObjectList(
  690. IN PSTR ListName,
  691. IN PLIST_ENTRY LocalListHead,
  692. IN PLIST_ENTRY RemoteListHead,
  693. IN BOOLEAN MruList,
  694. IN BOOLEAN Verbose
  695. )
  696. /*++
  697. Routine Description:
  698. Formats and dumps a linked list of CACHE_OBJECTs.
  699. Arguments:
  700. Prefix - The prefix to use before each printed line. This makes
  701. hierarchical object displays much prettier.
  702. LocalListHead - Points to a local copy of the linked list head.
  703. RemoteListHead - The virtual address of the linked list head in
  704. the debugee.
  705. MruList - TRUE if we're dumping the Mru list, FALSE if we're
  706. dumping the Bin list.
  707. Verbose - If TRUE, then be verbose.
  708. Return Value:
  709. None.
  710. --*/
  711. {
  712. PLIST_ENTRY nextEntry;
  713. PCACHE_OBJECT cacheObject;
  714. CACHE_OBJECT localCacheObject;
  715. dprintf(
  716. "%s @ %08lx\n\n",
  717. ListName,
  718. RemoteListHead
  719. );
  720. nextEntry = LocalListHead->Flink;
  721. while( nextEntry != RemoteListHead ) {
  722. if( CheckControlC() ) {
  723. break;
  724. }
  725. if( MruList ) {
  726. cacheObject = CONTAINING_RECORD(
  727. nextEntry,
  728. CACHE_OBJECT,
  729. MruList
  730. );
  731. } else {
  732. cacheObject = CONTAINING_RECORD(
  733. nextEntry,
  734. CACHE_OBJECT,
  735. BinList
  736. );
  737. }
  738. if( !ReadMemory(
  739. (ULONG)cacheObject,
  740. &localCacheObject,
  741. sizeof(localCacheObject),
  742. NULL
  743. ) ) {
  744. dprintf(
  745. "inetdbg: cannot read CACHE_OBJECT @ %08lx\n",
  746. cacheObject
  747. );
  748. return;
  749. }
  750. DumpCacheObject(
  751. " ",
  752. &localCacheObject,
  753. (ULONG)cacheObject,
  754. Verbose
  755. );
  756. if( MruList ) {
  757. nextEntry = localCacheObject.MruList.Flink;
  758. } else {
  759. nextEntry = localCacheObject.BinList.Flink;
  760. }
  761. }
  762. } // DumpCacheObjectList
  763. VOID
  764. DumpCacheTable(
  765. IN PCACHE_TABLE CacheTable,
  766. IN ULONG ActualAddress,
  767. IN BOOLEAN DumpBin,
  768. IN BOOLEAN DumpMru,
  769. IN BOOLEAN Verbose
  770. )
  771. /*++
  772. Routine Description:
  773. Formats and dumps the entire cache table.
  774. Arguments:
  775. CacheTable - Points to a local copy of the cache table.
  776. ActualAddress - The virtual address of the cache table in the debugee.
  777. DumpBin - If TRUE, then dump the bin lists hanging off the cache table.
  778. DumpMru - If TRUE, then dump the Mru list hanging off the cache table.
  779. Verbose - If TRUE, then be verbose.
  780. Return Value:
  781. None.
  782. --*/
  783. {
  784. LONG i;
  785. //
  786. // Dump simple data.
  787. //
  788. dprintf(
  789. "CACHE_TABLE @ %08lx\n"
  790. " CriticalSection @ %08lx\n",
  791. ActualAddress,
  792. ActualAddress + FIELD_OFFSET( CACHE_TABLE, CriticalSection )
  793. );
  794. if( CacheTable->CriticalSection.LockCount == -1 ) {
  795. dprintf(
  796. " LockCount = NOT LOCKED\n"
  797. );
  798. } else {
  799. dprintf(
  800. " LockCount = %lu\n",
  801. CacheTable->CriticalSection.LockCount
  802. );
  803. }
  804. dprintf(
  805. " RecursionCount = %lu\n"
  806. " OwningThread = %08lx\n",
  807. CacheTable->CriticalSection.RecursionCount,
  808. CacheTable->CriticalSection.OwningThread
  809. );
  810. //
  811. // Only display the non-empty bins.
  812. //
  813. for( i = 0 ; i < MAX_BINS ; i++ ) {
  814. CHAR tmp[sizeof("Items[1234567890]")];
  815. if( !IS_LIST_EMPTY( CacheTable, ActualAddress, CACHE_TABLE, Items[i] ) ) {
  816. sprintf(
  817. tmp,
  818. "Items[%lu]",
  819. i
  820. );
  821. dprintf(
  822. " %-18s @ %08lx\n",
  823. tmp,
  824. ActualAddress + FIELD_OFFSET( CACHE_TABLE, Items[i] )
  825. );
  826. }
  827. }
  828. dprintf(
  829. " MruList @ %08lx%s\n"
  830. " OpenFileInUse = %ld\n"
  831. " MaxOpenFileInUse = %ld\n"
  832. "\n",
  833. ActualAddress + FIELD_OFFSET( CACHE_TABLE, MruList ),
  834. IS_LIST_EMPTY( CacheTable, ActualAddress, CACHE_TABLE, MruList )
  835. ? " (EMPTY)"
  836. : "",
  837. CacheTable->OpenFileInUse,
  838. CacheTable->MaxOpenFileInUse
  839. );
  840. //
  841. // If requested, dump the individual entries in the bin & mru lists.
  842. //
  843. if( DumpBin ) {
  844. for( i = 0 ; i < MAX_BINS ; i++ ) {
  845. CHAR tmp[sizeof("Items[1234567890]")];
  846. if( !IS_LIST_EMPTY( CacheTable, ActualAddress, CACHE_TABLE, Items[i] ) ) {
  847. sprintf(
  848. tmp,
  849. "Items[%lu]",
  850. i
  851. );
  852. DumpCacheObjectList(
  853. tmp,
  854. &CacheTable->Items[i],
  855. (PLIST_ENTRY)( ActualAddress + FIELD_OFFSET( CACHE_TABLE, Items[i] ) ),
  856. FALSE,
  857. Verbose
  858. );
  859. }
  860. }
  861. }
  862. if( DumpMru ) {
  863. if( !IS_LIST_EMPTY( CacheTable, ActualAddress, CACHE_TABLE, MruList ) ) {
  864. DumpCacheObjectList(
  865. "MruList",
  866. &CacheTable->MruList,
  867. (PLIST_ENTRY)( ActualAddress + FIELD_OFFSET( CACHE_TABLE, MruList ) ),
  868. TRUE,
  869. Verbose
  870. );
  871. }
  872. }
  873. } // DumpCacheTable
  874. //
  875. // NTSD extension entrypoints.
  876. //
  877. DECLARE_API( fcache )
  878. /*++
  879. Routine Description:
  880. This function is called as an NTSD extension to format and dump
  881. the entire open file cache or a single cache object.
  882. Arguments:
  883. hCurrentProcess - Supplies a handle to the current process (at the
  884. time the extension was called).
  885. hCurrentThread - Supplies a handle to the current thread (at the
  886. time the extension was called).
  887. CurrentPc - Supplies the current pc at the time the extension is
  888. called.
  889. lpExtensionApis - Supplies the address of the functions callable
  890. by this extension.
  891. lpArgumentString - Supplies the asciiz string that describes the
  892. ansi string to be dumped.
  893. Return Value:
  894. None.
  895. --*/
  896. {
  897. ULONG address;
  898. CACHE_OBJECT cacheObject;
  899. CACHE_TABLE cacheTable;
  900. BOOLEAN dumpBin;
  901. BOOLEAN dumpMru;
  902. BOOLEAN verbose;
  903. INIT_API();
  904. //
  905. // Establish defaults.
  906. //
  907. dumpBin = FALSE;
  908. dumpMru = FALSE;
  909. verbose = FALSE;
  910. //
  911. // Skip any leading blanks.
  912. //
  913. while( *lpArgumentString == ' ' ||
  914. *lpArgumentString == '\t' ) {
  915. lpArgumentString++;
  916. }
  917. //
  918. // Process switches.
  919. //
  920. while( *lpArgumentString == '-' ) {
  921. lpArgumentString++;
  922. while( *lpArgumentString != ' ' &&
  923. *lpArgumentString != '\t' &&
  924. *lpArgumentString != '\0' ) {
  925. switch( *lpArgumentString ) {
  926. case 'v' :
  927. case 'V' :
  928. verbose = !verbose;
  929. break;
  930. case 'b' :
  931. case 'B' :
  932. dumpBin = !dumpBin;
  933. break;
  934. case 'm' :
  935. case 'M' :
  936. dumpMru = !dumpMru;
  937. break;
  938. case '-' : // Set the switches the way I like them. --keithmo
  939. verbose = TRUE;
  940. dumpBin = TRUE;
  941. dumpMru = FALSE;
  942. break;
  943. default :
  944. dprintf(
  945. "use: inetdbg.fcache [options] [address]\n"
  946. );
  947. return;
  948. }
  949. lpArgumentString++;
  950. }
  951. while( *lpArgumentString == ' ' ||
  952. *lpArgumentString == '\t' ) {
  953. lpArgumentString++;
  954. }
  955. }
  956. if( *lpArgumentString != '\0' ) {
  957. //
  958. // Dump a single object.
  959. //
  960. address = GetExpression( lpArgumentString );
  961. if( address == 0 ) {
  962. dprintf(
  963. "inetdbg: cannot evaluate \"%s\"\n",
  964. lpArgumentString
  965. );
  966. return;
  967. }
  968. //
  969. // Read the cache object.
  970. //
  971. if( !ReadMemory(
  972. (ULONG)address,
  973. &cacheObject,
  974. sizeof(cacheObject),
  975. NULL
  976. ) ) {
  977. dprintf(
  978. "inetdbg: cannot read CACHE_OBJECT @ %lx\n",
  979. address
  980. );
  981. return;
  982. }
  983. DumpCacheObject(
  984. "",
  985. &cacheObject,
  986. address,
  987. verbose
  988. );
  989. return;
  990. }
  991. //
  992. // Dump the entire cache table.
  993. //
  994. address = GetExpression( "infocomm!CacheTable" );
  995. if( address == 0 ) {
  996. dprintf(
  997. "inetdbg: cannot find infocomm!CacheTable\n"
  998. );
  999. return;
  1000. }
  1001. if( !ReadMemory(
  1002. (ULONG)address,
  1003. &cacheTable,
  1004. sizeof(cacheTable),
  1005. NULL
  1006. ) ) {
  1007. dprintf(
  1008. "inetdbg: cannot read CACHE_TABLE @ %08lx\n",
  1009. address
  1010. );
  1011. return;
  1012. }
  1013. DumpCacheTable(
  1014. &cacheTable,
  1015. address,
  1016. dumpBin,
  1017. dumpMru,
  1018. verbose
  1019. );
  1020. } // DECLARE_API( fcache )
  1021. DECLARE_API( open )
  1022. /*++
  1023. Routine Description:
  1024. This function is called as an NTSD extension to format and dump
  1025. a specific TS_OPEN_FILE_INFO structure.
  1026. Arguments:
  1027. hCurrentProcess - Supplies a handle to the current process (at the
  1028. time the extension was called).
  1029. hCurrentThread - Supplies a handle to the current thread (at the
  1030. time the extension was called).
  1031. CurrentPc - Supplies the current pc at the time the extension is
  1032. called.
  1033. lpExtensionApis - Supplies the address of the functions callable
  1034. by this extension.
  1035. lpArgumentString - Supplies the asciiz string that describes the
  1036. ansi string to be dumped.
  1037. Return Value:
  1038. None.
  1039. --*/
  1040. {
  1041. ULONG address;
  1042. TS_OPEN_FILE_INFO openFileInfo;
  1043. INIT_API();
  1044. //
  1045. // Skip any leading blanks.
  1046. //
  1047. while( *lpArgumentString == ' ' ||
  1048. *lpArgumentString == '\t' ) {
  1049. lpArgumentString++;
  1050. }
  1051. if( *lpArgumentString == '\0' ) {
  1052. dprintf(
  1053. "use: inetdbg.open address\n"
  1054. );
  1055. return;
  1056. }
  1057. address = GetExpression( lpArgumentString );
  1058. if( address == 0 ) {
  1059. dprintf(
  1060. "inetdbg: cannot evaluate \"%s\"\n",
  1061. lpArgumentString
  1062. );
  1063. return;
  1064. }
  1065. //
  1066. // Read the object.
  1067. //
  1068. if( !ReadMemory(
  1069. (ULONG)address,
  1070. &openFileInfo,
  1071. sizeof(openFileInfo),
  1072. NULL
  1073. ) ) {
  1074. dprintf(
  1075. "inetdbg: cannot read TS_OPEN_FILE_INFO @ %lx\n",
  1076. address
  1077. );
  1078. return;
  1079. }
  1080. DumpOpenFileInfo(
  1081. "",
  1082. &openFileInfo,
  1083. address
  1084. );
  1085. } // DECLARE_API( open )
  1086. DECLARE_API( uri )
  1087. /*++
  1088. Routine Description:
  1089. This function is called as an NTSD extension to format and dump
  1090. a specific W3_URI_INFO structure.
  1091. Arguments:
  1092. hCurrentProcess - Supplies a handle to the current process (at the
  1093. time the extension was called).
  1094. hCurrentThread - Supplies a handle to the current thread (at the
  1095. time the extension was called).
  1096. CurrentPc - Supplies the current pc at the time the extension is
  1097. called.
  1098. lpExtensionApis - Supplies the address of the functions callable
  1099. by this extension.
  1100. lpArgumentString - Supplies the asciiz string that describes the
  1101. ansi string to be dumped.
  1102. Return Value:
  1103. None.
  1104. --*/
  1105. {
  1106. ULONG address;
  1107. W3_URI_INFO uriInfo;
  1108. INIT_API();
  1109. //
  1110. // Skip any leading blanks.
  1111. //
  1112. while( *lpArgumentString == ' ' ||
  1113. *lpArgumentString == '\t' ) {
  1114. lpArgumentString++;
  1115. }
  1116. if( *lpArgumentString == '\0' ) {
  1117. dprintf(
  1118. "use: inetdbg.uri address\n"
  1119. );
  1120. return;
  1121. }
  1122. address = GetExpression( lpArgumentString );
  1123. if( address == 0 ) {
  1124. dprintf(
  1125. "inetdbg: cannot evaluate \"%s\"\n",
  1126. lpArgumentString
  1127. );
  1128. return;
  1129. }
  1130. //
  1131. // Read the object.
  1132. //
  1133. if( !ReadMemory(
  1134. (ULONG)address,
  1135. &uriInfo,
  1136. sizeof(uriInfo),
  1137. NULL
  1138. ) ) {
  1139. dprintf(
  1140. "inetdbg: cannot read W3_URI_INFO @ %lx\n",
  1141. address
  1142. );
  1143. return;
  1144. }
  1145. DumpUriInfo(
  1146. "",
  1147. &uriInfo,
  1148. address
  1149. );
  1150. } // DECLARE_API( uri )
  1151. DECLARE_API( phys )
  1152. /*++
  1153. Routine Description:
  1154. This function is called as an NTSD extension to format and dump
  1155. a specific PHYS_OPEN_FILE_INFO structure.
  1156. Arguments:
  1157. hCurrentProcess - Supplies a handle to the current process (at the
  1158. time the extension was called).
  1159. hCurrentThread - Supplies a handle to the current thread (at the
  1160. time the extension was called).
  1161. CurrentPc - Supplies the current pc at the time the extension is
  1162. called.
  1163. lpExtensionApis - Supplies the address of the functions callable
  1164. by this extension.
  1165. lpArgumentString - Supplies the asciiz string that describes the
  1166. ansi string to be dumped.
  1167. Return Value:
  1168. None.
  1169. --*/
  1170. {
  1171. ULONG address;
  1172. PHYS_OPEN_FILE_INFO physOpenFileInfo;
  1173. INIT_API();
  1174. //
  1175. // Skip any leading blanks.
  1176. //
  1177. while( *lpArgumentString == ' ' ||
  1178. *lpArgumentString == '\t' ) {
  1179. lpArgumentString++;
  1180. }
  1181. if( *lpArgumentString == '\0' ) {
  1182. dprintf(
  1183. "use: inetdbg.phys address\n"
  1184. );
  1185. return;
  1186. }
  1187. address = GetExpression( lpArgumentString );
  1188. if( address == 0 ) {
  1189. dprintf(
  1190. "inetdbg: cannot evaluate \"%s\"\n",
  1191. lpArgumentString
  1192. );
  1193. return;
  1194. }
  1195. //
  1196. // Read the object.
  1197. //
  1198. if( !ReadMemory(
  1199. (ULONG)address,
  1200. &physOpenFileInfo,
  1201. sizeof(physOpenFileInfo),
  1202. NULL
  1203. ) ) {
  1204. dprintf(
  1205. "inetdbg: cannot read PHYS_OPEN_FILE_INFO @ %lx\n",
  1206. address
  1207. );
  1208. return;
  1209. }
  1210. DumpPhysOpenFileInfo(
  1211. "",
  1212. &physOpenFileInfo,
  1213. address
  1214. );
  1215. } // DECLARE_API( phys )
  1216. DECLARE_API( oplock )
  1217. /*++
  1218. Routine Description:
  1219. This function is called as an NTSD extension to format and dump
  1220. a specific OPLOCK_OBJECT structure.
  1221. Arguments:
  1222. hCurrentProcess - Supplies a handle to the current process (at the
  1223. time the extension was called).
  1224. hCurrentThread - Supplies a handle to the current thread (at the
  1225. time the extension was called).
  1226. CurrentPc - Supplies the current pc at the time the extension is
  1227. called.
  1228. lpExtensionApis - Supplies the address of the functions callable
  1229. by this extension.
  1230. lpArgumentString - Supplies the asciiz string that describes the
  1231. ansi string to be dumped.
  1232. Return Value:
  1233. None.
  1234. --*/
  1235. {
  1236. ULONG address;
  1237. OPLOCK_OBJECT oplockObject;
  1238. INIT_API();
  1239. //
  1240. // Skip any leading blanks.
  1241. //
  1242. while( *lpArgumentString == ' ' ||
  1243. *lpArgumentString == '\t' ) {
  1244. lpArgumentString++;
  1245. }
  1246. if( *lpArgumentString == '\0' ) {
  1247. dprintf(
  1248. "use: inetdbg.oplock address\n"
  1249. );
  1250. return;
  1251. }
  1252. address = GetExpression( lpArgumentString );
  1253. if( address == 0 ) {
  1254. dprintf(
  1255. "inetdbg: cannot evaluate \"%s\"\n",
  1256. lpArgumentString
  1257. );
  1258. return;
  1259. }
  1260. //
  1261. // Read the object.
  1262. //
  1263. if( !ReadMemory(
  1264. (ULONG)address,
  1265. &oplockObject,
  1266. sizeof(oplockObject),
  1267. NULL
  1268. ) ) {
  1269. dprintf(
  1270. "inetdbg: cannot read OPLOCK_OBJECT @ %lx\n",
  1271. address
  1272. );
  1273. return;
  1274. }
  1275. DumpOplockObject(
  1276. "",
  1277. &oplockObject,
  1278. address
  1279. );
  1280. } // DECLARE_API( oplock )
  1281. DECLARE_API( blob )
  1282. /*++
  1283. Routine Description:
  1284. This function is called as an NTSD extension to format and dump
  1285. a specific BLOB_HEADER structure.
  1286. Arguments:
  1287. hCurrentProcess - Supplies a handle to the current process (at the
  1288. time the extension was called).
  1289. hCurrentThread - Supplies a handle to the current thread (at the
  1290. time the extension was called).
  1291. CurrentPc - Supplies the current pc at the time the extension is
  1292. called.
  1293. lpExtensionApis - Supplies the address of the functions callable
  1294. by this extension.
  1295. lpArgumentString - Supplies the asciiz string that describes the
  1296. ansi string to be dumped.
  1297. Return Value:
  1298. None.
  1299. --*/
  1300. {
  1301. ULONG address;
  1302. BLOB_HEADER blobHeader;
  1303. INIT_API();
  1304. //
  1305. // Skip any leading blanks.
  1306. //
  1307. while( *lpArgumentString == ' ' ||
  1308. *lpArgumentString == '\t' ) {
  1309. lpArgumentString++;
  1310. }
  1311. if( *lpArgumentString == '\0' ) {
  1312. dprintf(
  1313. "use: inetdbg.blob address\n"
  1314. );
  1315. return;
  1316. }
  1317. address = GetExpression( lpArgumentString );
  1318. if( address == 0 ) {
  1319. dprintf(
  1320. "inetdbg: cannot evaluate \"%s\"\n",
  1321. lpArgumentString
  1322. );
  1323. return;
  1324. }
  1325. //
  1326. // Read the object.
  1327. //
  1328. if( !ReadMemory(
  1329. (ULONG)address,
  1330. &blobHeader,
  1331. sizeof(blobHeader),
  1332. NULL
  1333. ) ) {
  1334. dprintf(
  1335. "inetdbg: cannot read BLOB_HEADER @ %lx\n",
  1336. address
  1337. );
  1338. return;
  1339. }
  1340. DumpBlobHeader(
  1341. "",
  1342. &blobHeader,
  1343. address
  1344. );
  1345. } // DECLARE_API( blob )