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.

3089 lines
85 KiB

  1. #ifndef DBG
  2. #define DBG 1
  3. #endif
  4. #define SRVDBG 1
  5. #define SRVKD 1
  6. #include "precomp.h"
  7. #include <ntverp.h>
  8. #include <windows.h>
  9. #include <wdbgexts.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. WINDBG_EXTENSION_APIS ExtensionApis;
  13. EXT_API_VERSION ApiVersion = { 5, 0, EXT_API_VERSION_NUMBER, 0 };
  14. #define ERRPRT dprintf
  15. #ifndef MIN
  16. #define MIN(a,b) ( ((a) < (b)) ? (a) : (b) )
  17. #endif
  18. #define NL 1
  19. #define NONL 0
  20. USHORT SavedMajorVersion;
  21. USHORT SavedMinorVersion;
  22. BOOL ChkTarget; // is debuggee a CHK build?
  23. /*
  24. * The help strings printed out
  25. */
  26. static LPSTR Extensions[] = {
  27. "Lan Manager Server Debugger Extensions:\n",
  28. "buffer address Dump the BUFFER structure",
  29. "client Dump the clients + CONNECTION structs",
  30. "connection address Dump the CONNECTION structure",
  31. "context address Dump the WORK_CONTEXT structure",
  32. "df address Follow an entire LIST_ENTRY to end",
  33. "endpoint [ address ] Dump the ENDPOINT structure(s)",
  34. "errcodes Dump the error log code filter",
  35. "globals Print out srv's global variables",
  36. "help",
  37. "lfcb address Dump the LFCB structure",
  38. "lock [ address ] Dump the ERESOURCE structure(s)",
  39. "mfcb address Dump the LFCB structure",
  40. "pagedconnection address Dump the PAGED_CONNECTION structure",
  41. "queue [ address ] Dump the WORK_QUEUE structure",
  42. "rfcb [ address ] Dump the RFCB structure(s)",
  43. "scavenger Dump scavenger info",
  44. "search address Dump the SEARCH structure",
  45. "session address Dump the SESSION structure",
  46. "share [ address | disk | print | comm | pipe ] Dump the SHARE structure(s)",
  47. "share =name Dump the SHARE structure for 'name'",
  48. "smb address Dump the SMB_HEADER",
  49. #if SRVDBG == 1
  50. "smbdebug [ t | f | #'s ] Get or set SMB debug flags",
  51. #endif
  52. "srv Turn target into a Server",
  53. #if SRVDBG == 1
  54. "srvdebug [ t | f | #'s ] Get or set server debug flags",
  55. #endif
  56. "statistics Dump the SrvStatistics structure",
  57. "tcon address Dump the TREE_CONNECT structure",
  58. "transaction address Dump the TRANSACTION structure",
  59. "version",
  60. "wksta Turn target into a Workstation",
  61. 0
  62. };
  63. static LPSTR BlockState[] = {
  64. "BlockStateDead",
  65. "BlockStateInitializing",
  66. "BlockStateActive",
  67. "BlockStateClosing"
  68. };
  69. static LPSTR BlockType[] = {
  70. "BlockTypeGarbage",
  71. "BlockTypeBuffer",
  72. "BlockTypeConnection",
  73. "BlockTypeEndpoint",
  74. "BlockTypeLfcb",
  75. "BlockTypeMfcb",
  76. "BlockTypeRfcb",
  77. "BlockTypeSearch",
  78. "BlockTypeSearchCore",
  79. "BlockTypeByteRangeLock",
  80. "BlockTypeSession",
  81. "BlockTypeShare",
  82. "BlockTypeTransaction",
  83. "BlockTypeTreeConnect",
  84. "BlockTypeWaitForOplockBreak",
  85. "BlockTypeCommDevice",
  86. "BlockTypeWorkContextInitial",
  87. "BlockTypeWorkContextNormal",
  88. "BlockTypeWorkContextRaw",
  89. "BlockTypeDataBuffer",
  90. "BlockTypeTable",
  91. "BlockTypeNonpagedHeader",
  92. "BlockTypePagedConnection",
  93. "BlockTypePagedRfcb",
  94. "BlockTypeNonpagedMfcb",
  95. "BlockTypeTimer",
  96. "BlockTypeAdminCheck",
  97. "BlockTypeWorkQueue",
  98. #ifdef INCLUDE_SMB_PERSISTENT
  99. "BlockTypeDfs",
  100. "BlockTypePersistentState",
  101. "BlockTypePersistentBitMap",
  102. "BlockTypePersistentShareState",
  103. #else
  104. "BlockTypeDfs"
  105. #endif
  106. };
  107. /*
  108. * The locks that we'd like to dump
  109. */
  110. static LPSTR SrvLocks[] = {
  111. "SrvConfigurationLock",
  112. "SrvEndpointLock",
  113. "SrvShareLock",
  114. "SrvOrderedListLock",
  115. "SrvOplockBreakListLock",
  116. "SrvUnlockableCodeLock",
  117. 0
  118. };
  119. /*
  120. * The globals that we'd like to dump
  121. */
  122. static LPSTR GlobalBool[] = {
  123. "SrvProductTypeServer",
  124. "SrvMultiProcessorDriver",
  125. "SrvEnableOplocks",
  126. "SrvEnableFcbOpens",
  127. "SrvEnableSoftCompatibility",
  128. "SrvEnableRawMode",
  129. "SrvSmbSecuritySignaturesRequired",
  130. "SrvSmbSecuritySignaturesEnabled",
  131. "SrvEnableW9xSecuritySignatures",
  132. "SrvRemoveDuplicateSearches",
  133. "SrvRestrictNullSessionAccess",
  134. "SrvEnableWfW311DirectIpx",
  135. "SrvEnableOplockForceClose",
  136. "SrvEnableForcedLogoff",
  137. "SrvFspActive",
  138. "SrvXsActive",
  139. "SrvPaused",
  140. "SrvCompletedPNPRegistration",
  141. "SrvFspTransitioning",
  142. "SrvResourceThreadRunning",
  143. "SrvResourceDisconnectPending",
  144. "SrvResourceFreeConnection",
  145. "SrvResourceOrphanedBlocks",
  146. 0
  147. };
  148. static LPSTR GlobalShort[] = {
  149. "SrvInitialSessionTableSize",
  150. "SrvMaxSessionTableSize",
  151. "SrvInitialTreeTableSize",
  152. "SrvInitialTreeTableSize",
  153. "SrvMaxTreeTableSize",
  154. "SrvInitialFileTableSize",
  155. "SrvMaxFileTableSize",
  156. "SrvInitialSearchTableSize",
  157. "SrvMaxSearchTableSize",
  158. "SrvMaxMpxCount",
  159. 0
  160. };
  161. static LPSTR GlobalLong[] = {
  162. "SrvServerSize",
  163. "SrvNumberOfProcessors",
  164. "SrvMinNT5Client",
  165. "SrvAbortiveDisconnects",
  166. "SrvBalanceCount",
  167. "SrvReBalanced",
  168. "SrvOtherQueueAffinity",
  169. "SrvPreferredAffinity",
  170. "SrvMaxFreeRfcbs",
  171. "SrvMaxFreeMfcbs",
  172. "SrvReceiveBufferLength",
  173. "SrvInitialReceiveWorkItemCount",
  174. "SrvMaxReceiveWorkItemCount",
  175. "SrvInitialRawModeWorkItemCount",
  176. "SrvMaxRawModeWorkItemCount",
  177. "SrvFreeConnectionMinimum",
  178. "SrvFreeConnectionMaximum",
  179. "SrvScavengerTimeoutInSeconds",
  180. "SrvMaxNumberVcs",
  181. "SrvMinReceiveQueueLength",
  182. "SrvMinFreeWorkItemsBlockingIo",
  183. "SrvIpxAutodisconnectTimeout",
  184. "SrvConnectionNoSessionsTimeout",
  185. "SrvMaxUsers",
  186. "SrvMaxPagedPoolUsage",
  187. "SrvMaxNonPagedPoolUsage",
  188. "SrvScavengerUpdateQosCount",
  189. "SrvWorkItemMaxIdleTime",
  190. "SrvAlertMinutes",
  191. "SrvFreeDiskSpaceThreshold",
  192. "SrvSharingViolationRetryCount",
  193. "SrvLockViolationDelay",
  194. "SrvLockViolationOffset",
  195. "SrvMaxOpenSearches",
  196. "SrvMaxFsctlBufferSize",
  197. "SrvMdlReadSwitchover",
  198. "SrvMpxMdlReadSwitchover",
  199. "SrvCachedOpenLimit",
  200. "SrvXsSharedMemoryReference",
  201. "SrvEndpointCount",
  202. "SrvBlockingOpsInProgress",
  203. "SrvFastWorkAllocation",
  204. "SrvSlowWorkAllocation",
  205. "SrvMinClientBufferSize",
  206. "SrvMaxFsctlBufferSize",
  207. "SrvMaxReadSize",
  208. "SrvMaxWriteChunk",
  209. "SrvNT5SecuritySigBuildNumber",
  210. 0
  211. };
  212. static LPSTR GlobalLongHex[] = {
  213. "SrvNamedPipeHandle",
  214. "SrvNamedPipeDeviceObject",
  215. "SrvNamedPipeFileObject",
  216. "SrvDfsDeviceObject",
  217. "SrvDfsFileObject",
  218. "SrvDfsFastIoDeviceControl",
  219. "SrvDiskConfiguration",
  220. "SrvSvcProcess",
  221. // "SrvWorkQueuesBase",
  222. "SrvWorkQueues",
  223. "eSrvWorkQueues",
  224. "SrvIpxSmartCard",
  225. 0
  226. };
  227. static LPSTR GlobalStringVector[] = {
  228. "SrvNullSessionPipes",
  229. "SrvNullSessionShares",
  230. "SrvPipesNeedLicense",
  231. "SrvNoRemapPipeNames",
  232. 0
  233. };
  234. static LPSTR GlobalStrings[] = {
  235. "SrvComputerName",
  236. "SrvNativeOS",
  237. "SrvNativeLanMan",
  238. "SrvSystemRoot",
  239. 0
  240. };
  241. static LPSTR ScavengerLong[] = {
  242. "LastNonPagedPoolLimitHitCount",
  243. "LastNonPagedPoolFailureCount",
  244. "LastPagedPoolLimitHitCount",
  245. "LastPagedPoolFailureCount",
  246. "SrvScavengerCheckRfcbActive",
  247. "ScavengerUpdateQosCount",
  248. "ScavengerCheckRfcbActive",
  249. "FailedWorkItemAllocations",
  250. 0
  251. };
  252. static LPSTR ScavengerBool[] = {
  253. "RunShortTermAlgorithm",
  254. "RunScavengerAlgorithm",
  255. "RunAlerterAlgorithm",
  256. "EventSwitch",
  257. 0
  258. };
  259. struct BitFields {
  260. PCSTR name;
  261. ULONGLONG value;
  262. };
  263. #if defined( SRVDBG ) && SRVDBG == 1
  264. #define DF( name ) { #name, DEBUG_ ## name }
  265. struct BitFields SrvDebugFlags[] = {
  266. DF( TRACE1 ),
  267. DF( TRACE2 ),
  268. DF( REFCNT ),
  269. DF( HEAP ),
  270. DF( WORKER1 ),
  271. DF( WORKER2 ),
  272. DF( NET1 ),
  273. DF( NET2 ),
  274. DF( FSP1 ),
  275. DF( FSP2 ),
  276. DF( FSD1 ),
  277. DF( FSD2 ),
  278. DF( SCAV1 ),
  279. DF( SCAV2 ),
  280. DF( BLOCK1 ),
  281. DF( IPX_PIPES ),
  282. DF( HANDLES ),
  283. DF( IPX ),
  284. DF( TDI ),
  285. DF( OPLOCK ),
  286. DF( NETWORK_ERRORS ),
  287. DF( FILE_CACHE ),
  288. DF( IPX2 ),
  289. DF( LOCKS ),
  290. DF( SEARCH ),
  291. DF( BRUTE_FORCE_REWIND ),
  292. DF( COMM ),
  293. DF( XACTSRV ),
  294. DF( LICENSE ),
  295. DF( API_ERRORS ),
  296. DF( STOP_ON_ERRORS ),
  297. DF( ERRORS ),
  298. DF( SMB_ERRORS ),
  299. DF( WORKITEMS ),
  300. DF( IPXNAMECLAIM ),
  301. DF( SENDS2OTHERCPU ),
  302. DF( REBALANCE ),
  303. DF( PNP ),
  304. DF( DFS ),
  305. DF( SIPX ),
  306. DF( CREATE ),
  307. DF( SECSIG ),
  308. DF( STUCK_OPLOCK ),
  309. 0
  310. };
  311. #undef DF
  312. #define DF( name ) { #name, DEBUG_SMB_ ## name }
  313. struct BitFields SmbDebugFlags[] = {
  314. DF( ERRORS ),
  315. DF( ADMIN1 ),
  316. DF( ADMIN2 ),
  317. DF( TREE1 ),
  318. DF( TREE2 ),
  319. DF( DIRECTORY1 ),
  320. DF( DIRECTORY2 ),
  321. DF( OPEN_CLOSE1 ),
  322. DF( OPEN_CLOSE2 ),
  323. DF( FILE_CONTROL1 ),
  324. DF( FILE_CONTROL2 ),
  325. DF( READ_WRITE1 ),
  326. DF( READ_WRITE2 ),
  327. DF( LOCK1 ),
  328. DF( LOCK2 ),
  329. DF( RAW1 ),
  330. DF( RAW2 ),
  331. DF( MPX1 ),
  332. DF( MPX2 ),
  333. DF( SEARCH1 ),
  334. DF( SEARCH2 ),
  335. DF( TRANSACTION1 ),
  336. DF( TRANSACTION2 ),
  337. DF( PRINT1 ),
  338. DF( PRINT2 ),
  339. DF( MESSAGE1 ),
  340. DF( MESSAGE2 ),
  341. DF( MISC1 ),
  342. DF( MISC2 ),
  343. DF( QUERY_SET1 ),
  344. DF( QUERY_SET2 ),
  345. DF( TRACE ),
  346. 0
  347. };
  348. #endif // SRVDBG
  349. /*
  350. * The MEMBERLIST structure, and the macros that follow, give an easy way to declare
  351. * the members of a structure to be printed. Once you set up a MEMBERLIST[] for a
  352. * particular structure, you call PrintMemberList() to do a formatted dump of the struct
  353. */
  354. typedef struct _MEMBERLIST {
  355. LPSTR name; // The name of the field
  356. ULONG offset; // The offset of the field in the structure
  357. UCHAR type; // The type of variable to be printed
  358. LONG extra; // Any other extra info needed for this type
  359. } MEMBERLIST;
  360. // BE -> BOOL
  361. // HE -> HEX ULONG
  362. // PE -> POINTER
  363. // UE -> Unsigned ULONG
  364. // HC -> Unsigned char as hex
  365. // DE -> Decimal Long
  366. // SE -> Decimal Short
  367. // WE -> UNICODE_STRING
  368. // AE -> ANSI_STRING
  369. // IE -> Symbol Address
  370. // CE -> Character
  371. // TE -> TABLE_HEADER structure, and follow the table
  372. // LE -> LIST_ENTRY list
  373. // BT -> BLOCK_HEADER 'Type' field
  374. // BS -> BLOCK_HEADER 'State' field
  375. // BC -> BLOCK_HEADER 'ReferenceCount' field
  376. // U64-> LONGLONG
  377. // IA -> IP Address
  378. #define ROOT( StructureName ) { "@" #StructureName, 0, 'R' }
  379. #define BE( StructureName, FieldName ) { #FieldName, FIELD_OFFSET( StructureName, FieldName ), 'B' }
  380. #define CE( StructureName, FieldName ) { #FieldName, FIELD_OFFSET( StructureName, FieldName ), 'C' }
  381. #define HE( StructureName, FieldName) { #FieldName, FIELD_OFFSET( StructureName, FieldName ), 'H' }
  382. #define PE( StructureName, FieldName) { #FieldName, FIELD_OFFSET( StructureName, FieldName ), 'P' }
  383. #define UE( StructureName, FieldName) { #FieldName, FIELD_OFFSET( StructureName, FieldName ), 'U' }
  384. #define U64( StructureName, FieldName) { #FieldName, FIELD_OFFSET( StructureName, FieldName ), '6' }
  385. #define DE( StructureName, FieldName) { #FieldName, FIELD_OFFSET( StructureName, FieldName ), 'L' }
  386. #define SE( StructureName, FieldName) { #FieldName, FIELD_OFFSET( StructureName, FieldName ), 'S' }
  387. #define WE( StructureName, FieldName) { #FieldName, FIELD_OFFSET( StructureName, FieldName ), 'W' }
  388. #define AE( StructureName, FieldName) { #FieldName, FIELD_OFFSET( StructureName, FieldName ), 'A' }
  389. #define IE( StructureName, FieldName) { #FieldName, FIELD_OFFSET( StructureName, FieldName ), 'I' }
  390. #define TE( StructureName, FieldName) { #FieldName, FIELD_OFFSET( StructureName, FieldName ), 'T' }
  391. #define LE( StructureName, FieldName, PointedToStructure, PointedToMemberName ) \
  392. { #FieldName, FIELD_OFFSET( StructureName, FieldName##.Flink ), 'Z', \
  393. FIELD_OFFSET( PointedToStructure, PointedToMemberName ## .Flink ) }
  394. #define BT() { "BlockHeader.Type", FIELD_OFFSET( BLOCK_HEADER, Type) , 'K' }
  395. #define BS() { "BlockHeader.State", FIELD_OFFSET( BLOCK_HEADER, State), 'Q' }
  396. #define BC() { "BlockHeader.ReferenceCount", FIELD_OFFSET( BLOCK_HEADER, ReferenceCount), 'L' }
  397. #define IA( StructureName, FieldName) { #FieldName, FIELD_OFFSET( StructureName, FieldName ), 'N' }
  398. /*
  399. * The members of an SMB_HEADER
  400. */
  401. MEMBERLIST ML_SMB_HEADER[] = {
  402. CE( NT_SMB_HEADER, Command ),
  403. HE( NT_SMB_HEADER, Status.NtStatus ),
  404. CE( NT_SMB_HEADER, Flags ),
  405. SE( NT_SMB_HEADER, Flags2 ),
  406. SE( NT_SMB_HEADER, Tid ),
  407. SE( NT_SMB_HEADER, Pid ),
  408. SE( NT_SMB_HEADER, Uid ),
  409. SE( NT_SMB_HEADER, Mid ),
  410. 0
  411. };
  412. /*
  413. * The members in an MFCB
  414. */
  415. MEMBERLIST ML_MFCB[] = {
  416. PE( MFCB, NonpagedMfcb ),
  417. UE( MFCB, ActiveRfcbCount ),
  418. BE( MFCB, CompatibilityOpen ),
  419. HE( MFCB, FileNameHashValue ),
  420. WE( MFCB, FileName ),
  421. PE( MFCB, MfcbHashTableEntry.Flink ),
  422. LE( MFCB, LfcbList, LFCB, MfcbListEntry ),
  423. 0
  424. };
  425. /*
  426. * The members in the SrvStatistics structure
  427. */
  428. MEMBERLIST ML_SRV_STATISTICS[] = {
  429. U64( SRV_STATISTICS, TotalBytesReceived ),
  430. U64( SRV_STATISTICS, TotalBytesSent ),
  431. DE( SRV_STATISTICS, SessionLogonAttempts ),
  432. DE( SRV_STATISTICS, SessionsTimedOut ),
  433. DE( SRV_STATISTICS, SessionsErroredOut ),
  434. DE( SRV_STATISTICS, SessionsLoggedOff ),
  435. DE( SRV_STATISTICS, SessionsForcedLogOff ),
  436. DE( SRV_STATISTICS, LogonErrors ),
  437. DE( SRV_STATISTICS, AccessPermissionErrors ),
  438. DE( SRV_STATISTICS, GrantedAccessErrors ),
  439. DE( SRV_STATISTICS, SystemErrors ),
  440. DE( SRV_STATISTICS, BlockingSmbsRejected ),
  441. DE( SRV_STATISTICS, WorkItemShortages ),
  442. DE( SRV_STATISTICS, TotalFilesOpened ),
  443. DE( SRV_STATISTICS, CurrentNumberOfOpenFiles ),
  444. DE( SRV_STATISTICS, CurrentNumberOfSessions ),
  445. DE( SRV_STATISTICS, CurrentNumberOfOpenSearches ),
  446. DE( SRV_STATISTICS, CurrentNonPagedPoolUsage ),
  447. DE( SRV_STATISTICS, NonPagedPoolFailures ),
  448. DE( SRV_STATISTICS, PeakNonPagedPoolUsage ),
  449. DE( SRV_STATISTICS, CurrentPagedPoolUsage ),
  450. DE( SRV_STATISTICS, PagedPoolFailures ),
  451. DE( SRV_STATISTICS, PeakPagedPoolUsage ),
  452. 0
  453. };
  454. /*
  455. * The members in a NONPAGED_MFCB
  456. */
  457. MEMBERLIST ML_NONPAGED_MFCB[] = {
  458. UE( NONPAGED_MFCB, Type ),
  459. PE( NONPAGED_MFCB, PagedBlock ),
  460. PE( NONPAGED_MFCB, Lock ),
  461. HE( NONPAGED_MFCB, OpenFileAttributes ),
  462. 0
  463. };
  464. /*
  465. * The members in an LFCB
  466. */
  467. MEMBERLIST ML_LFCB[] = {
  468. UE( LFCB, HandleCount ),
  469. PE( LFCB, Mfcb ),
  470. PE( LFCB, Connection ),
  471. PE( LFCB, Session ),
  472. PE( LFCB, TreeConnect ),
  473. HE( LFCB, GrantedAccess ),
  474. HE( LFCB, FileHandle ),
  475. PE( LFCB, FileObject ),
  476. PE( LFCB, DeviceObject ),
  477. HE( LFCB, FileMode ),
  478. HE( LFCB, JobId ),
  479. IE( LFCB, FastIoRead ),
  480. IE( LFCB, FastIoWrite ),
  481. IE( LFCB, FastIoUnlockSingle ),
  482. BE( LFCB, CompatibilityOpen ),
  483. 0
  484. };
  485. /*
  486. * The members in an RFCB
  487. */
  488. MEMBERLIST ML_RFCB[] = {
  489. BE( RFCB, BlockingModePipe ),
  490. BE( RFCB, ByteModePipe ),
  491. BE( RFCB, CachedOpen ),
  492. PE( RFCB, CachedOpenListEntry ),
  493. PE( RFCB, Connection ),
  494. BE( RFCB, DeferredOplockBreak ),
  495. SE( RFCB, Fid ),
  496. HE( RFCB, FileMode ),
  497. PE( RFCB, GlobalRfcbListEntry ),
  498. HE( RFCB, GrantedAccess ),
  499. PE( RFCB, Irp ),
  500. BE( RFCB, IsActive ),
  501. BE( RFCB, IsCacheable ),
  502. PE( RFCB, Lfcb ),
  503. BE( RFCB, LockAccessGranted ),
  504. PE( RFCB, Mfcb ),
  505. BE( RFCB, MpxGlommingAllowed ),
  506. CE( RFCB, NewOplockLevel ),
  507. DE( RFCB, NumberOfLocks ),
  508. BE( RFCB, OnOplockBreaksInProgressList ),
  509. BE( RFCB, OpenResponseSent ),
  510. UE( RFCB, OplockState ),
  511. PE( RFCB, PagedRfcb ),
  512. SE( RFCB, Pid ),
  513. UE( RFCB, RawWriteCount ),
  514. LE( RFCB, RawWriteSerializationList, WORK_CONTEXT, ListEntry ),
  515. BE( RFCB, ReadAccessGranted ),
  516. PE( RFCB, RetryOplockRequest ),
  517. HE( RFCB, SavedError ),
  518. HE( RFCB, ShareAccess ),
  519. HE( RFCB, ShiftedFid ),
  520. SE( RFCB, Tid ),
  521. SE( RFCB, Uid ),
  522. BE( RFCB, UnlockAccessGranted ),
  523. BE( RFCB, WriteAccessGranted ),
  524. BE( RFCB, AppendAccessGranted ),
  525. BE( RFCB, WrittenTo ),
  526. DE( RFCB, WriteMpx.ReferenceCount ),
  527. HE( RFCB, WriteMpx.Mask ),
  528. PE( RFCB, WriteMpx.FileObject ),
  529. SE( RFCB, WriteMpx.Mid ),
  530. SE( RFCB, WriteMpx.PreviousMid ),
  531. SE( RFCB, WriteMpx.SequenceNumber ),
  532. BE( RFCB, WriteMpx.Glomming ),
  533. BE( RFCB, WriteMpx.GlomPending ),
  534. PE( RFCB, WriteMpx.GlomDelayList ),
  535. DE( RFCB, WriteMpx.StartOffset ),
  536. SE( RFCB, WriteMpx.Length ),
  537. BE( RFCB, WriteMpx.GlomComplete ),
  538. BE( RFCB, WriteMpx.MpxGlommingAllowed ),
  539. PE( RFCB, WriteMpx.MdlChain ),
  540. DE( RFCB, WriteMpx.NumberOfRuns ),
  541. 0
  542. };
  543. /*
  544. * The members in a PAGED_RFCB
  545. */
  546. MEMBERLIST ML_PAGED_RFCB[] = {
  547. UE( PAGED_RFCB, FcbOpenCount ),
  548. HE( PAGED_RFCB, IpxSmartCardContext ),
  549. PE( PAGED_RFCB, LfcbListEntry.Flink ),
  550. 0
  551. };
  552. /*
  553. * The members in an RFCB for quick display
  554. */
  555. MEMBERLIST ML_RFCB_QUICK[] = {
  556. ROOT( RFCB ),
  557. PE( RFCB, Connection ),
  558. HE( RFCB, GlobalRfcbListEntry.ResumeHandle ),
  559. 0
  560. };
  561. /*
  562. * The members in a SESSION
  563. */
  564. MEMBERLIST ML_SESSION[] = {
  565. ROOT( SESSION ),
  566. WE( SESSION, NtUserName ),
  567. WE( SESSION, NtUserDomain ),
  568. UE( SESSION, CurrentFileOpenCount ),
  569. UE( SESSION, CurrentSearchOpenCount ),
  570. //HE( SESSION, UserHandle.dwUpper ),
  571. //HE( SESSION, UserHandle.dwLower ),
  572. PE( SESSION, Connection ),
  573. PE( SESSION, GlobalSessionListEntry.ListEntry.Flink ),
  574. SE( SESSION, MaxBufferSize ),
  575. SE( SESSION, MaxMpxCount ),
  576. SE( SESSION, Uid ),
  577. BE( SESSION, UsingUppercasePaths ),
  578. BE( SESSION, GuestLogon ),
  579. BE( SESSION, EncryptedLogon ),
  580. BE( SESSION, LogoffAlertSent ),
  581. BE( SESSION, TwoMinuteWarningSent ),
  582. BE( SESSION, FiveMinuteWarningSent ),
  583. BE( SESSION, IsNullSession ),
  584. BE( SESSION, IsAdmin ),
  585. BE( SESSION, IsLSNotified ),
  586. PE( SESSION, hLicense ),
  587. BE( SESSION, LogonSequenceInProgress ),
  588. 0
  589. };
  590. /*
  591. * The members in a TRANSACTION
  592. */
  593. MEMBERLIST ML_TRANSACTION[] = {
  594. BT(),
  595. BS(),
  596. BC(),
  597. PE( TRANSACTION, NonpagedHeader ),
  598. PE( TRANSACTION, Connection ),
  599. PE( TRANSACTION, Session ),
  600. PE( TRANSACTION, TreeConnect ),
  601. UE( TRANSACTION, StartTime ),
  602. UE( TRANSACTION, Timeout ),
  603. UE( TRANSACTION, cMaxBufferSize ),
  604. PE( TRANSACTION, InSetup ),
  605. PE( TRANSACTION, OutSetup ),
  606. PE( TRANSACTION, InParameters ),
  607. PE( TRANSACTION, OutParameters ),
  608. PE( TRANSACTION, InData ),
  609. PE( TRANSACTION, OutData ),
  610. UE( TRANSACTION, SetupCount ),
  611. UE( TRANSACTION, MaxSetupCount ),
  612. UE( TRANSACTION, ParameterCount ),
  613. UE( TRANSACTION, TotalParameterCount ),
  614. UE( TRANSACTION, MaxParameterCount ),
  615. UE( TRANSACTION, DataCount ),
  616. UE( TRANSACTION, TotalDataCount ),
  617. UE( TRANSACTION, MaxDataCount ),
  618. SE( TRANSACTION, Category ),
  619. SE( TRANSACTION, Function ),
  620. BE( TRANSACTION, InputBufferCopied ),
  621. BE( TRANSACTION, OutputBufferCopied ),
  622. BE( TRANSACTION, OutDataAllocated ),
  623. SE( TRANSACTION, Flags ),
  624. SE( TRANSACTION, Tid ),
  625. SE( TRANSACTION, Pid ),
  626. SE( TRANSACTION, Uid ),
  627. SE( TRANSACTION, OtherInfo ),
  628. UE( TRANSACTION, FileHandle ),
  629. PE( TRANSACTION, FileObject ),
  630. UE( TRANSACTION, ParameterDisplacement ),
  631. UE( TRANSACTION, DataDisplacement ),
  632. BE( TRANSACTION, PipeRequest ),
  633. BE( TRANSACTION, RemoteApiRequest ),
  634. BE( TRANSACTION, Inserted ),
  635. BE( TRANSACTION, MultipieceIpxSend ),
  636. BE( TRANSACTION, Executing ),
  637. 0
  638. };
  639. /*
  640. * The members in a WORK_CONTEXT
  641. */
  642. MEMBERLIST ML_WORK_CONTEXT[] = {
  643. BT(),
  644. BS(),
  645. BC(),
  646. PE( WORK_CONTEXT, Endpoint ),
  647. PE( WORK_CONTEXT, Connection ),
  648. PE( WORK_CONTEXT, Rfcb ),
  649. PE( WORK_CONTEXT, Share ),
  650. PE( WORK_CONTEXT, Session ),
  651. PE( WORK_CONTEXT, TreeConnect ),
  652. PE( WORK_CONTEXT, Irp ),
  653. UE( WORK_CONTEXT, SpinLock ),
  654. PE( WORK_CONTEXT, RequestBuffer ),
  655. PE( WORK_CONTEXT, ResponseBuffer ),
  656. PE( WORK_CONTEXT, RequestHeader ),
  657. PE( WORK_CONTEXT, RequestParameters ),
  658. PE( WORK_CONTEXT, ResponseHeader ),
  659. PE( WORK_CONTEXT, ResponseParameters ),
  660. CE( WORK_CONTEXT, NextCommand ),
  661. UE( WORK_CONTEXT, ProcessingCount ),
  662. IE( WORK_CONTEXT, FsdRestartRoutine ),
  663. IE( WORK_CONTEXT, FspRestartRoutine ),
  664. LE( WORK_CONTEXT, InProgressListEntry, WORK_CONTEXT, InProgressListEntry ),
  665. UE( WORK_CONTEXT, PartOfInitialAllocation ),
  666. // BE( WORK_CONTEXT, BlockingOperation ),
  667. // BE( WORK_CONTEXT, UsingExtraSmbBuffer ),
  668. // BE( WORK_CONTEXT, OplockOpen ),
  669. PE( WORK_CONTEXT, ClientAddress ),
  670. PE( WORK_CONTEXT, WaitForOplockBreak ),
  671. UE( WORK_CONTEXT, BytesAvailable ),
  672. 0
  673. };
  674. /*
  675. * The members in a BUFFER
  676. */
  677. MEMBERLIST ML_BUFFER[] = {
  678. PE( BUFFER, Buffer ),
  679. UE( BUFFER, BufferLength ),
  680. PE( BUFFER, Mdl ),
  681. PE( BUFFER, PartialMdl ),
  682. UE( BUFFER, DataLength ),
  683. 0
  684. };
  685. /*
  686. * The members in an ENDPOINT
  687. */
  688. MEMBERLIST ML_ENDPOINT[] = {
  689. WE( ENDPOINT, NetworkName ),
  690. WE( ENDPOINT, TransportName ),
  691. AE( ENDPOINT, TransportAddress ),
  692. WE( ENDPOINT, ServerName ),
  693. WE( ENDPOINT, DomainName ),
  694. WE( ENDPOINT, NetworkAddress ),
  695. PE( ENDPOINT, EndpointHandle ),
  696. PE( ENDPOINT, FileObject ),
  697. PE( ENDPOINT, DeviceObject ),
  698. PE( ENDPOINT, IpxMaxPacketSizeArray ),
  699. UE( ENDPOINT, MaxAdapters ),
  700. HE( ENDPOINT, NameSocketHandle ),
  701. PE( ENDPOINT, NameSocketFileObject ),
  702. PE( ENDPOINT, NameSocketDeviceObject ),
  703. UE( ENDPOINT, FreeConnectionCount ),
  704. UE( ENDPOINT, TotalConnectionCount ),
  705. TE( ENDPOINT, ConnectionTable ),
  706. PE( ENDPOINT, FreeConnectionList ),
  707. 0
  708. };
  709. /*
  710. * The members in a SEARCH
  711. */
  712. MEMBERLIST ML_SEARCH[] = {
  713. WE( SEARCH, SearchName ),
  714. WE( SEARCH, LastFileNameReturned ),
  715. HE( SEARCH, DirectoryHandle ),
  716. PE( SEARCH, LastUseListEntry.Flink ),
  717. PE( SEARCH, HashTableEntry.Flink ),
  718. PE( SEARCH, Session ),
  719. PE( SEARCH, TreeConnect ),
  720. // UE( SEARCH, SearchStorageType ),
  721. PE( SEARCH, DirectoryCache ),
  722. SE( SEARCH, NumberOfCachedFiles ),
  723. SE( SEARCH, SearchAttributes ),
  724. SE( SEARCH, CoreSequence ),
  725. SE( SEARCH, TableIndex ),
  726. SE( SEARCH, HashTableIndex ),
  727. SE( SEARCH, Pid ),
  728. SE( SEARCH, Flags2 ),
  729. BE( SEARCH, Wildcards ),
  730. BE( SEARCH, InUse ),
  731. 0
  732. };
  733. /*
  734. * The members in a CONNECTION
  735. */
  736. MEMBERLIST ML_CONNECTION[] = {
  737. WE( CONNECTION, ClientMachineNameString ),
  738. WE( CONNECTION, ClientOSType ),
  739. WE( CONNECTION, ClientLanManType ),
  740. IA( CONNECTION, ClientIPAddress ),
  741. UE( CONNECTION, SmbDialect ),
  742. UE( CONNECTION, SpinLock ),
  743. UE( CONNECTION, Interlock ),
  744. UE( CONNECTION, BalanceCount ),
  745. UE( CONNECTION, LastRequestTime ),
  746. UE( CONNECTION, Lock ),
  747. UE( CONNECTION, LicenseLock ),
  748. PE( CONNECTION, EndpointSpinLock ),
  749. PE( CONNECTION, CachedRfcb ),
  750. UE( CONNECTION, CachedFid ),
  751. BE( CONNECTION, BreakIIToNoneJustSent ),
  752. BE( CONNECTION, EnableRawIo ),
  753. UE( CONNECTION, Sid ),
  754. PE( CONNECTION, Endpoint ),
  755. DE( CONNECTION, MaximumSendSize ),
  756. PE( CONNECTION, NegotiateHandle ),
  757. PE( CONNECTION, FileObject ),
  758. PE( CONNECTION, DeviceObject ),
  759. PE( CONNECTION, InProgressWorkItemList.Flink ),
  760. UE( CONNECTION, LatestOplockBreakResponse ),
  761. UE( CONNECTION, OplockBreaksInProgress ),
  762. PE( CONNECTION, CurrentWorkQueue ),
  763. PE( CONNECTION, PreferredWorkQueue ),
  764. UE( CONNECTION, RawReadsInProgress ),
  765. BE( CONNECTION, OplocksAlwaysDisabled ),
  766. BE( CONNECTION, EnableOplocks ),
  767. PE( CONNECTION, EndpointFreeListEntry.Flink ),
  768. PE( CONNECTION, OplockWorkList ),
  769. UE( CONNECTION, CachedOpenCount ),
  770. LE( CONNECTION, CachedOpenList, RFCB, CachedOpenListEntry ),
  771. UE( CONNECTION, CachedDirectoryCount ),
  772. LE( CONNECTION, CachedDirectoryList, CACHED_DIRECTORY, ListEntry ),
  773. HE( CONNECTION, ClientCapabilities ),
  774. UE( CONNECTION, CachedTransactionCount ),
  775. BE( CONNECTION, OnNeedResourceQueue ),
  776. BE( CONNECTION, NotReusable ),
  777. BE( CONNECTION, DisconnectPending ),
  778. BE( CONNECTION, ReceivePending ),
  779. PE( CONNECTION, PagedConnection ),
  780. UE( CONNECTION, BytesAvailable ),
  781. SE( CONNECTION, CurrentNumberOfSessions ),
  782. 0
  783. };
  784. MEMBERLIST ML_CONNECTION_IPX[] = {
  785. SE( CONNECTION, SequenceNumber ),
  786. SE( CONNECTION, LastResponseLength ),
  787. SE( CONNECTION, LastResponseBufferLength ),
  788. SE( CONNECTION, LastUid ),
  789. SE( CONNECTION, LastTid ),
  790. HE( CONNECTION, LastResponseStatus ),
  791. UE( CONNECTION, StartupTime ),
  792. PE( CONNECTION, LastResponse ),
  793. SE( CONNECTION, IpxAddress.Socket ),
  794. UE( CONNECTION, IpxDuplicateCount ),
  795. UE( CONNECTION, IpxDropDuplicateCount ),
  796. 0
  797. };
  798. MEMBERLIST ML_CONNECTION_VC[] = {
  799. BE( CONNECTION, SmbSecuritySignatureActive ),
  800. UE( CONNECTION, SmbSecuritySignatureIndex ),
  801. BE( CONNECTION, NoResponseSignatureIndex ),
  802. 0
  803. };
  804. /*
  805. * The members in a PAGED_CONNECTION
  806. */
  807. MEMBERLIST ML_PAGED_CONNECTION[] = {
  808. BE( PAGED_CONNECTION, LoggedInvalidSmb ),
  809. // BE( PAGED_CONNECTION, ClientTooOld ),
  810. UE( PAGED_CONNECTION, ClientBuildNumber ),
  811. PE( PAGED_CONNECTION, TransactionList.Flink ),
  812. PE( PAGED_CONNECTION, CoreSearchList.Flink ),
  813. HE( PAGED_CONNECTION, ConnectionHandle ),
  814. SE( PAGED_CONNECTION, CurrentNumberOfCoreSearches ),
  815. 0
  816. };
  817. /*
  818. * The members in a TREE_CONNECT
  819. */
  820. MEMBERLIST ML_TREE_CONNECT[] = {
  821. PE( TREE_CONNECT, Connection ),
  822. PE( TREE_CONNECT, Share ),
  823. WE( TREE_CONNECT, ServerName ),
  824. LE( TREE_CONNECT, GlobalTreeConnectListEntry.ListEntry, TREE_CONNECT, GlobalTreeConnectListEntry.ListEntry ),
  825. UE( TREE_CONNECT, CurrentFileOpenCount ),
  826. LE( TREE_CONNECT, ShareListEntry, SHARE, TreeConnectList ),
  827. PE( TREE_CONNECT, PrintFileList.Flink ),
  828. SE( TREE_CONNECT, Tid ),
  829. BE( TREE_CONNECT, RemapPipeNames ),
  830. 0
  831. };
  832. /*
  833. * The members in a WORK_QUEUE
  834. */
  835. MEMBERLIST ML_WORK_QUEUE[] = {
  836. UE( WORK_QUEUE, Queue.MaximumCount ),
  837. UE( WORK_QUEUE, Queue.CurrentCount ),
  838. UE( WORK_QUEUE, Queue.Header.SignalState ),
  839. UE( WORK_QUEUE, CurrentClients ),
  840. UE( WORK_QUEUE, AvgQueueDepthSum ),
  841. UE( WORK_QUEUE, Threads ),
  842. UE( WORK_QUEUE, AvailableThreads ),
  843. UE( WORK_QUEUE, MaxThreads ),
  844. UE( WORK_QUEUE, FreeWorkItems ),
  845. UE( WORK_QUEUE, AllocatedWorkItems ),
  846. UE( WORK_QUEUE, MaximumWorkItems ),
  847. UE( WORK_QUEUE, MinFreeWorkItems ),
  848. UE( WORK_QUEUE, NeedWorkItem ),
  849. UE( WORK_QUEUE, StolenWorkItems ),
  850. UE( WORK_QUEUE, FreeRawModeWorkItems ),
  851. UE( WORK_QUEUE, AllocatedRawModeWorkItems ),
  852. UE( WORK_QUEUE, PagedPoolLookAsideList.MaxSize ),
  853. UE( WORK_QUEUE, NonPagedPoolLookAsideList.MaxSize ),
  854. UE( WORK_QUEUE, PagedPoolLookAsideList.AllocHit ),
  855. UE( WORK_QUEUE, PagedPoolLookAsideList.AllocMiss ),
  856. UE( WORK_QUEUE, NonPagedPoolLookAsideList.AllocHit ),
  857. UE( WORK_QUEUE, NonPagedPoolLookAsideList.AllocMiss ),
  858. PE( WORK_QUEUE, CachedFreeRfcb ),
  859. UE( WORK_QUEUE, FreeRfcbs ),
  860. UE( WORK_QUEUE, MaxFreeRfcbs ),
  861. PE( WORK_QUEUE, CachedFreeMfcb ),
  862. UE( WORK_QUEUE, FreeMfcbs ),
  863. UE( WORK_QUEUE, MaxFreeMfcbs ),
  864. HE( WORK_QUEUE, SpinLock ),
  865. PE( WORK_QUEUE, IrpThread ),
  866. CE( WORK_QUEUE, CreateMoreWorkItems.BlockHeader.Type ),
  867. U64( WORK_QUEUE, IdleTimeOut ),
  868. U64( WORK_QUEUE, stats.BytesReceived ),
  869. U64( WORK_QUEUE, stats.BytesSent ),
  870. U64( WORK_QUEUE, stats.ReadOperations ),
  871. U64( WORK_QUEUE, stats.BytesRead ),
  872. U64( WORK_QUEUE, stats.WriteOperations ),
  873. U64( WORK_QUEUE, stats.BytesWritten ),
  874. U64( WORK_QUEUE, saved.ReadOperations ),
  875. U64( WORK_QUEUE, saved.BytesRead ),
  876. U64( WORK_QUEUE, saved.WriteOperations ),
  877. U64( WORK_QUEUE, saved.BytesWritten ),
  878. UE( WORK_QUEUE, stats.WorkItemsQueued.Count ),
  879. UE( WORK_QUEUE, stats.SystemTime ),
  880. 0
  881. };
  882. /*
  883. * The members in a TABLE_HEADER
  884. */
  885. MEMBERLIST ML_TABLE_HEADER[] = {
  886. SE( TABLE_HEADER, TableSize ),
  887. SE( TABLE_HEADER, FirstFreeEntry ),
  888. SE( TABLE_HEADER, LastFreeEntry ),
  889. BE( TABLE_HEADER, Nonpaged ),
  890. PE( TABLE_HEADER, Table ),
  891. 0
  892. };
  893. /*
  894. * The members in a TABLE_ENTRY
  895. */
  896. MEMBERLIST ML_TABLE_ENTRY[] = {
  897. PE( TABLE_ENTRY, Owner ),
  898. // SE( TABLE_ENTRY, SequenceNumber ),
  899. // SE( TABLE_ENTRY, NextFreeEntry ),
  900. 0
  901. };
  902. /*
  903. * The members in a SHARE
  904. */
  905. MEMBERLIST ML_SHARE[] = {
  906. WE( SHARE, ShareName ),
  907. WE( SHARE, NtPathName ),
  908. WE( SHARE, DosPathName ),
  909. WE( SHARE, Remark ),
  910. UE( SHARE, MaxUses ),
  911. UE( SHARE, CurrentUses ),
  912. HE( SHARE, RootDirectoryHandle ),
  913. UE( SHARE, CurrentRootHandleReferences ),
  914. DE( SHARE, QueryNamePrefixLength ),
  915. PE( SHARE, SecurityDescriptor ),
  916. PE( SHARE, FileSecurityDescriptor ),
  917. BE( SHARE, PotentialSystemFile ),
  918. BE( SHARE, Removable ),
  919. BE( SHARE, SpecialShare ),
  920. BE( SHARE, IsDfs ),
  921. BE( SHARE, IsDfsRoot ),
  922. HE( SHARE, CSCState ),
  923. LE( SHARE, TreeConnectList, TREE_CONNECT, ShareListEntry ),
  924. 0
  925. };
  926. /*
  927. * Forward References...
  928. */
  929. BOOL DumpTable( IN PTABLE_HEADER pt );
  930. /*
  931. * Print out an optional message, a UNICODE_STRING, and maybe a new-line
  932. */
  933. BOOL
  934. PrintStringW( IN LPSTR msg OPTIONAL, IN PUNICODE_STRING puStr, IN BOOL nl )
  935. {
  936. PWCHAR StringData;
  937. ULONG BytesRead;
  938. if( ARGUMENT_PRESENT(msg) )
  939. dprintf( msg );
  940. if( puStr->Length == 0 ) {
  941. dprintf( "<Length == 0>" );
  942. if( nl )
  943. dprintf( "\n" );
  944. return TRUE;
  945. }
  946. if( puStr->Buffer == NULL ) {
  947. dprintf( "<Buffer == 0>" );
  948. if( nl )
  949. dprintf( "\n" );
  950. return TRUE;
  951. }
  952. StringData = (PWCHAR)LocalAlloc( LPTR, puStr->Length + sizeof(UNICODE_NULL));
  953. if( StringData == NULL ) {
  954. dprintf( "Out of memory!\n" );
  955. return FALSE;
  956. }
  957. ReadMemory( (ULONG_PTR)puStr->Buffer,
  958. StringData,
  959. puStr->Length,
  960. &BytesRead);
  961. if (BytesRead) {
  962. StringData[ puStr->Length / sizeof( WCHAR ) ] = '\0';
  963. dprintf("%ws%s", StringData, nl ? "\n" : "" );
  964. }
  965. LocalFree( (HLOCAL)StringData );
  966. return BytesRead;
  967. }
  968. /*
  969. * Print out an optional message, an ANSI_STRING, and maybe a new-line
  970. */
  971. BOOL
  972. PrintStringA( IN LPSTR msg OPTIONAL, IN PANSI_STRING pStr, IN BOOL nl )
  973. {
  974. PCHAR StringData;
  975. ULONG BytesRead;
  976. if( msg )
  977. dprintf( msg );
  978. if( pStr->Length == 0 ) {
  979. if( nl )
  980. dprintf( "\n" );
  981. return TRUE;
  982. }
  983. StringData = (PCHAR)LocalAlloc( LPTR, pStr->Length + 1 );
  984. if( StringData == NULL ) {
  985. ERRPRT( "Out of memory!\n" );
  986. return FALSE;
  987. }
  988. ReadMemory((ULONG_PTR) pStr->Buffer,
  989. StringData,
  990. pStr->Length,
  991. &BytesRead );
  992. if ( BytesRead ) {
  993. StringData[ pStr->Length ] = '\0';
  994. dprintf("%s%s", StringData, nl ? "\n" : "" );
  995. }
  996. LocalFree((HLOCAL)StringData);
  997. return BytesRead;
  998. }
  999. /*
  1000. * Get 'size' bytes from the debuggee program at 'dwAddress' and place it
  1001. * in our address space at 'ptr'. Use 'type' in an error printout if necessary
  1002. */
  1003. BOOL
  1004. GetData( IN LPVOID ptr, IN ULONG_PTR dwAddress, IN ULONG size, IN PCSTR type )
  1005. {
  1006. BOOL b;
  1007. ULONG BytesRead;
  1008. ULONG count;
  1009. while( size > 0 ) {
  1010. count = MIN( size, 3000 );
  1011. b = ReadMemory( dwAddress, ptr, count, &BytesRead );
  1012. if (!b || BytesRead != count ) {
  1013. ERRPRT( "Unable to read %u bytes at %X, for %s\n", size, dwAddress, type );
  1014. return FALSE;
  1015. }
  1016. dwAddress += count;
  1017. size -= count;
  1018. ptr = (LPVOID)((PBYTE)ptr + count);
  1019. }
  1020. return TRUE;
  1021. }
  1022. /*
  1023. * Follow a LIST_ENTRY list beginning with a head at dwListHeadAddr in the debugee's
  1024. * address space. For each element in the list, print out the pointer value at 'offset'
  1025. */
  1026. BOOL
  1027. PrintListEntryList( IN ULONG_PTR dwListHeadAddr, IN LONG offset )
  1028. {
  1029. LIST_ENTRY ListEntry;
  1030. ULONG i=0;
  1031. BOOL retval = TRUE;
  1032. ULONG count = 20;
  1033. if( !GetData( &ListEntry, dwListHeadAddr, sizeof( ListEntry ), "LIST_ENTRY" ) )
  1034. return FALSE;
  1035. while( count-- ) {
  1036. if( (ULONG_PTR)ListEntry.Flink == dwListHeadAddr || (ULONG_PTR)ListEntry.Flink == 0 )
  1037. break;
  1038. if( !GetData( &ListEntry, (ULONG_PTR)ListEntry.Flink, sizeof( ListEntry ), "ListEntry" ) ) {
  1039. retval = FALSE;
  1040. break;
  1041. }
  1042. dprintf( "%16X%s", (ULONG_PTR)ListEntry.Flink + offset, (i && !(i&3)) ? "\n" : "" );
  1043. i++;
  1044. }
  1045. if( count == 0 && (ULONG_PTR)ListEntry.Flink != dwListHeadAddr && ListEntry.Flink ) {
  1046. dprintf( "\nTruncated list dump\n" );
  1047. } else if( ! ( i && !(i&3) ) ) {
  1048. dprintf( "\n" );
  1049. }
  1050. return retval;
  1051. }
  1052. /*
  1053. * 'ptr' points to a structure in our address space which is described by the MEMBERLIST bp.
  1054. * Print out the structure according to the MEMBERLIST
  1055. */
  1056. VOID
  1057. PrintMemberList( IN VOID *ptr, IN MEMBERLIST *bp )
  1058. {
  1059. int i;
  1060. PCSTR nl = "\n";
  1061. PCSTR sep = " ";
  1062. PCSTR nlsep = "\n ";
  1063. DWORD d;
  1064. for( i=0; bp->name; i++, bp++ ) {
  1065. if( (i&1) == 0 )
  1066. dprintf( " " );
  1067. if( bp->type == 'T' ) {
  1068. dprintf( "%s -- TABLE FOLLOWS -->\n", bp->name );
  1069. } else if( strlen( bp->name ) > 30 ) {
  1070. dprintf( "%-.17s...%s ", bp->name, bp->name+strlen(bp->name)-10 );
  1071. } else {
  1072. dprintf( "%-30s ", bp->name );
  1073. }
  1074. switch( bp->type ) {
  1075. case 'R':
  1076. // dprintf( "%-16X%s", (ULONG_PTR)ptr, i&1 ? nl : sep );
  1077. break;
  1078. case 'C':
  1079. dprintf( "%-16X%s",
  1080. (*(UCHAR *)(((char *)ptr) + bp->offset )) & 0xFF ,
  1081. i&1 ? nl : sep );
  1082. break;
  1083. case 'B':
  1084. dprintf( "%-16s%s",
  1085. *(BOOLEAN *)(((char *)ptr) + bp->offset ) ? "TRUE" : "FALSE",
  1086. i&1 ? nl : sep );
  1087. break;
  1088. case 'H':
  1089. case 'P':
  1090. dprintf( "%-16X%s",
  1091. *(ULONG *)(((char *)ptr) + bp->offset ),
  1092. i&1 ? nl : sep );
  1093. break;
  1094. case 'N':
  1095. //
  1096. // IP Address
  1097. //
  1098. d = *(ULONG *)(((char *)ptr) + bp->offset );
  1099. dprintf( "%-3.3u.%-3.3u.%-3.3u.%-3.3u %s",
  1100. (d&0xFF),
  1101. (d&0xFF00)>>8,
  1102. (d&0xFF0000)>>16,
  1103. (d&0xFF000000)>>24,
  1104. i&1 ? nl : sep );
  1105. break;
  1106. case 'U':
  1107. case 'L':
  1108. dprintf( "%-16d%s",
  1109. *(ULONG *)(((char *)ptr) + bp->offset ),
  1110. i&1 ? nl : sep );
  1111. break;
  1112. case '6':
  1113. {
  1114. ULONGLONG l;
  1115. RtlCopyMemory( &l, ((char *)ptr) + bp->offset, sizeof( l ) );
  1116. dprintf( "%I64u%s", l, i&1 ? nl : sep );
  1117. }
  1118. break;
  1119. case 'S':
  1120. dprintf( "%-16X%s",
  1121. *(SHORT *)(((char *)ptr) + bp->offset ) & 0xFFFF,
  1122. i&1 ? nl : sep );
  1123. break;
  1124. case 'W':
  1125. if( i&1 ) dprintf( nlsep );
  1126. PrintStringW( NULL, (UNICODE_STRING *)(((char *)ptr) + bp->offset ), NL );
  1127. i |= 1;
  1128. break;
  1129. case 'A':
  1130. if( i&1 ) dprintf( nlsep );
  1131. PrintStringA( NULL, (ANSI_STRING *)(((char *)ptr) + bp->offset ), NL );
  1132. i |= 1;
  1133. break;
  1134. case 'I':
  1135. {
  1136. UCHAR SymbolName[ 200 ];
  1137. ULONG_PTR Displacement;
  1138. PVOID sym = (PVOID)(*(ULONG_PTR *)(((char *)ptr) + bp->offset ));
  1139. GetSymbol( sym, SymbolName, &Displacement );
  1140. dprintf( "%-16s\n", SymbolName );
  1141. i |= 1;
  1142. }
  1143. break;
  1144. case 'T':
  1145. DumpTable( (PTABLE_HEADER)(((char *)ptr) + bp->offset) );
  1146. dprintf( " --- End Of %s Table ---\n", bp->name );
  1147. i |= 1;
  1148. break;
  1149. case 'K':
  1150. {
  1151. UCHAR Type = *(UCHAR *)(((char *)ptr) + bp->offset );
  1152. if( Type < 0 || Type >= BlockTypeMax )
  1153. dprintf( "%-16X%s", Type, i&1 ? nl : sep );
  1154. else
  1155. dprintf( "%-16s%s", BlockType[ Type ], i&1 ? nl : sep );
  1156. }
  1157. break;
  1158. case 'Q':
  1159. {
  1160. UCHAR State = *(UCHAR *)(((char *)ptr) + bp->offset );
  1161. if( State < 0 || State >= BlockStateMax )
  1162. dprintf( "%-16X%s", State, i&1 ? nl : sep );
  1163. else
  1164. dprintf( "%-16s%s", BlockState[ State ], i&1 ? nl : sep );
  1165. }
  1166. break;
  1167. case 'Z':
  1168. if( i&1 ) dprintf( nl );
  1169. PrintListEntryList( *(ULONG *)(((char *)ptr) + bp->offset ), -(bp->extra) );
  1170. i |= 1;
  1171. break;
  1172. default:
  1173. ERRPRT( "Unrecognized field type %c for %s\n", bp->type, bp->name );
  1174. break;
  1175. }
  1176. }
  1177. if( i & 1 )
  1178. dprintf( "\n" );
  1179. }
  1180. /*
  1181. * Print out a single HEX character
  1182. */
  1183. VOID
  1184. PrintHexChar( IN UCHAR c )
  1185. {
  1186. dprintf( "%c%c", "0123456789abcdef"[ (c>>4)&0xf ], "0123456789abcdef"[ c&0xf ] );
  1187. }
  1188. /*
  1189. * Print out 'buf' of 'cbuf' bytes as HEX characters
  1190. */
  1191. VOID
  1192. PrintHexBuf( IN PUCHAR buf, IN ULONG cbuf )
  1193. {
  1194. while( cbuf-- ) {
  1195. PrintHexChar( *buf++ );
  1196. dprintf( " " );
  1197. }
  1198. }
  1199. /*
  1200. * Print out the TABLE structure at TABLE_HEADER
  1201. */
  1202. BOOL
  1203. DumpTable( IN PTABLE_HEADER pt )
  1204. {
  1205. LONG i;
  1206. PTABLE_ENTRY pte;
  1207. BOOL bEmpty = TRUE;
  1208. PrintMemberList( pt, ML_TABLE_HEADER );
  1209. if( pt->TableSize < 0 ) {
  1210. ERRPRT( " ILLEGAL TABLE SIZE\n" );
  1211. return FALSE;
  1212. }
  1213. if( pt->FirstFreeEntry > pt->TableSize ) {
  1214. ERRPRT( " ILLEGAL FirstFreeEntry\n" );
  1215. return FALSE;
  1216. }
  1217. if( pt->LastFreeEntry > pt->TableSize ) {
  1218. ERRPRT( " ILLEGAL LastFreeEntry\n" );
  1219. return FALSE;
  1220. }
  1221. pte = (PTABLE_ENTRY)LocalAlloc( LPTR, pt->TableSize * sizeof( TABLE_ENTRY ) );
  1222. if( pte == NULL ) {
  1223. ERRPRT( "Out of memory!\n" );
  1224. return FALSE;
  1225. }
  1226. if( !GetData( pte, (ULONG_PTR)pt->Table, pt->TableSize * sizeof(TABLE_ENTRY), "TABLE_ENTRY" ) ) {
  1227. LocalFree( (HLOCAL)pte );
  1228. return FALSE;
  1229. }
  1230. for( i=0; i < pt->TableSize; i++ ) {
  1231. if( pte[i].Owner != NULL ) {
  1232. bEmpty = FALSE;
  1233. dprintf( "%d-%X ", i, pte[i].Owner );
  1234. }
  1235. if( pte[i].NextFreeEntry > pt->TableSize ) {
  1236. ERRPRT( " ILLEGAL NextFreeEntry %d-%d\n ", i, pte[i].NextFreeEntry );
  1237. LocalFree( (HLOCAL)pte );
  1238. return FALSE;
  1239. }
  1240. }
  1241. dprintf( "\n" );
  1242. LocalFree( (HLOCAL)pte );
  1243. if( bEmpty )
  1244. dprintf( " ** Empty Table**\n " );
  1245. return TRUE;
  1246. }
  1247. /*
  1248. * Fetch the null terminated UNICODE string at dwAddress into buf
  1249. */
  1250. BOOL
  1251. GetString( IN ULONG_PTR dwAddress, IN LPWSTR buf, IN ULONG MaxChars )
  1252. {
  1253. do {
  1254. if( !GetData( buf, dwAddress, sizeof( *buf ), "UNICODE Character" ) )
  1255. return FALSE;
  1256. dwAddress += sizeof( *buf );
  1257. } while( --MaxChars && *buf++ != '\0' );
  1258. return TRUE;
  1259. }
  1260. /*
  1261. * Check out the BLOCK_HEADER structure, ensuring its Type is 'Desired'.
  1262. * If bRefCount == TRUE, ensure the BLOCK_HEADER's reference is > 0
  1263. */
  1264. BOOL
  1265. CheckBlockHeader( IN PBLOCK_HEADER ph, IN UCHAR Desired, IN BOOL bRefCount )
  1266. {
  1267. if( ph->Type != Desired ) {
  1268. ERRPRT( "BLOCK_HEADER.Type is %X, should be %X\n",
  1269. ph->Type, Desired );
  1270. return FALSE;
  1271. }
  1272. if( ph->State < 0 || ph->State >= BlockStateMax ) {
  1273. ERRPRT( " BLOCK_HEADER.State is %X: INVALID\n", ph->State );
  1274. return FALSE;
  1275. }
  1276. if( ph->Size == 0 ) {
  1277. ERRPRT( " BLOCK_HEADER ILLEGAL SIZE!\n" );
  1278. return FALSE;
  1279. }
  1280. if( bRefCount && ph->ReferenceCount == 0 ) {
  1281. ERRPRT( " BLOCK_HEADER.ReferenceCount == 0!\n" );
  1282. return FALSE;
  1283. }
  1284. return TRUE;
  1285. }
  1286. /*
  1287. * Print out the BLOCK_HEADER, and optionally its ReferenceCount
  1288. */
  1289. BOOL
  1290. PrintBlockHeader( IN PBLOCK_HEADER ph, IN BOOL bRefCount )
  1291. {
  1292. dprintf( "BLOCK_HEADER Info: " );
  1293. if( ph->State < 0 || ph->State >= BlockStateMax ) {
  1294. ERRPRT( "State is %X: INVALID\n", ph->State );
  1295. return FALSE;
  1296. }
  1297. dprintf( "%s", BlockState[ ph->State ] );
  1298. if( ph->Type < 0 || ph->Type >= BlockTypeMax ) {
  1299. ERRPRT( "\nBlockType is %X: INVALID\n", ph->Type );
  1300. return FALSE;
  1301. }
  1302. dprintf( ", %s", BlockType[ ph->Type ] );
  1303. dprintf( ", Size %u", ph->Size );
  1304. if( ph->Size == 0 ) {
  1305. ERRPRT( " BLOCK_HEADER ILLEGAL SIZE!\n" );
  1306. return FALSE;
  1307. }
  1308. dprintf( ", ReferenceCount %u", ph->ReferenceCount );
  1309. dprintf( "\n" );
  1310. return TRUE;
  1311. }
  1312. /*
  1313. * Print out the NONPAGED_HEADER structure, ensuring its type is 'Desired', that
  1314. * it points back to its paged block at 'dwPagedBlock'.
  1315. */
  1316. BOOL
  1317. PrintNonpagedHeader(
  1318. IN PNONPAGED_HEADER ph,
  1319. IN ULONG Desired,
  1320. IN ULONG_PTR dwPagedBlock,
  1321. IN BOOL bRefCount
  1322. )
  1323. {
  1324. dprintf( "NONPAGED_HEADER Info: " );
  1325. if( ph->Type != Desired ) {
  1326. ERRPRT( "NONPAGED_HEADER.Type is %X, should be %X\n",
  1327. ph->Type, Desired );
  1328. return FALSE;
  1329. }
  1330. if( bRefCount && ph->ReferenceCount == 0 ) {
  1331. ERRPRT( " NONPAGED_HEADER.ReferenceCount == 0!\n" );
  1332. return FALSE;
  1333. }
  1334. if( (ULONG_PTR)ph->PagedBlock != dwPagedBlock ) {
  1335. ERRPRT( " NONPAGED_HEADER.PagedBlock is %X, should be %X\n", ph->PagedBlock, dwPagedBlock );
  1336. return FALSE;
  1337. }
  1338. if( bRefCount )
  1339. dprintf( "ReferenceCount %u\n", ph->ReferenceCount, ph->PagedBlock );
  1340. return TRUE;
  1341. }
  1342. BOOL
  1343. DumpShare( IN ULONG_PTR dwAddress, IN SHARE_TYPE type, IN PCSTR ShareName OPTIONAL, OUT PLIST_ENTRY *Flink OPTIONAL )
  1344. {
  1345. BOOL b;
  1346. SHARE Share;
  1347. if( !GetData( &Share, dwAddress, sizeof( Share ), "SHARE" ) ||
  1348. !CheckBlockHeader( &Share.BlockHeader, BlockTypeShare, TRUE ) ) {
  1349. return FALSE;
  1350. }
  1351. if( ARGUMENT_PRESENT( Flink ) ) {
  1352. *Flink = Share.GlobalShareList.Flink;
  1353. }
  1354. if( type != (SHARE_TYPE)-1 && type != Share.ShareType ) {
  1355. return TRUE;
  1356. }
  1357. if( ARGUMENT_PRESENT( ShareName ) ) {
  1358. //
  1359. // Only print this share structure out if the name is 'ShareName'
  1360. //
  1361. PWCHAR StringData;
  1362. ULONG BytesRead;
  1363. CHAR NameBuf[ MAX_PATH ];
  1364. if( Share.ShareName.Length == 0 ) {
  1365. return TRUE;
  1366. }
  1367. StringData = LocalAlloc(LPTR,Share.ShareName.Length + sizeof(UNICODE_NULL));
  1368. if( StringData == NULL ) {
  1369. dprintf( "Out of memory!\n" );
  1370. return FALSE;
  1371. }
  1372. ReadMemory( (ULONG_PTR)Share.ShareName.Buffer, StringData, Share.ShareName.Length, &BytesRead );
  1373. if (BytesRead == 0 ) {
  1374. LocalFree( (HLOCAL)StringData );
  1375. return FALSE;
  1376. }
  1377. StringData[ Share.ShareName.Length / sizeof( WCHAR ) ] = '\0';
  1378. wcstombs( NameBuf, StringData, sizeof( NameBuf ) );
  1379. LocalFree( (HLOCAL)StringData);
  1380. if( _strcmpi( NameBuf, ShareName ) ) {
  1381. return TRUE;
  1382. }
  1383. }
  1384. dprintf( "\nSHARE at %X: ", dwAddress );
  1385. PrintBlockHeader( &Share.BlockHeader, TRUE );
  1386. dprintf( " " );
  1387. switch( Share.ShareType ) {
  1388. case ShareTypeDisk:
  1389. dprintf( "ShareTypeDisk\n" );
  1390. break;
  1391. case ShareTypePrint:
  1392. dprintf( "ShareTypePrint, Type.hPrinter = %X ", Share.Type.hPrinter );
  1393. break;
  1394. case ShareTypePipe:
  1395. dprintf( "ShareTypePipe\n" );
  1396. break;
  1397. case ShareTypeWild:
  1398. dprintf( "ShareTypeWild\n" );
  1399. break;
  1400. default:
  1401. ERRPRT( "ShareType %X : INVALID!\n", Share.ShareType );
  1402. return FALSE;
  1403. }
  1404. PrintMemberList( &Share, ML_SHARE );
  1405. if( Share.CurrentUses > Share.MaxUses ) {
  1406. ERRPRT( " CurrentUses exceeds MaxUses!\n" );
  1407. return FALSE;
  1408. }
  1409. dprintf( "\n" );
  1410. return TRUE;
  1411. }
  1412. BOOL
  1413. DumpLock( IN ULONG_PTR dwAddress )
  1414. {
  1415. SRV_LOCK sl;
  1416. char namebuf[ 50 ];
  1417. int i;
  1418. if( !GetData( &sl, dwAddress, sizeof(sl), "ERESOURCE" ) )
  1419. return FALSE;
  1420. dprintf( " ActiveCount %u, ",dwAddress, sl.ActiveCount );
  1421. switch( sl.Flag ) {
  1422. case ResourceNeverExclusive:
  1423. dprintf( "ResourceNeverExclusive, " );
  1424. break;
  1425. case ResourceReleaseByOtherThread:
  1426. dprintf( "ResourceReleaseByOtherThread, " );
  1427. break;
  1428. case ResourceOwnedExclusive:
  1429. dprintf( "ResourceOwnedExclusive, " );
  1430. break;
  1431. default:
  1432. ERRPRT( "Flag = %X%s, ", sl.Flag, sl.Flag ? "(?)" : "" );
  1433. break;
  1434. }
  1435. dprintf( "SpinLock %d\n", sl.SpinLock );
  1436. for( i=0; i < 2; i++ ) {
  1437. if( sl.OwnerThreads[i].OwnerThread == 0 && sl.OwnerThreads[i].OwnerCount == 0 )
  1438. continue;
  1439. dprintf( " OwnerThreads[%d].OwnerThread %X, OwnerCount %d\n",
  1440. i, sl.OwnerThreads[i].OwnerThread, sl.OwnerThreads[i].OwnerCount );
  1441. }
  1442. return TRUE;
  1443. }
  1444. BOOL
  1445. DumpEndpoint( IN ULONG_PTR dwAddress, IN PLIST_ENTRY *Flink OPTIONAL )
  1446. {
  1447. ENDPOINT Endpoint;
  1448. dprintf( "\nENDPOINT at %X: ", dwAddress );
  1449. if( !GetData( &Endpoint, dwAddress, sizeof( Endpoint ), "ENDPOINT" ) ||
  1450. !CheckBlockHeader( &Endpoint.BlockHeader, BlockTypeEndpoint, TRUE ) ||
  1451. !PrintBlockHeader( &Endpoint.BlockHeader, TRUE ) ) {
  1452. return FALSE;
  1453. }
  1454. PrintMemberList( &Endpoint, ML_ENDPOINT );
  1455. dprintf( " NetworkAddressData: %ws\n", Endpoint.NetworkAddressData );
  1456. if( ARGUMENT_PRESENT( Flink ) )
  1457. *Flink = Endpoint.GlobalEndpointListEntry.ListEntry.Flink;
  1458. return TRUE;
  1459. }
  1460. BOOL
  1461. DumpSearch( IN ULONG_PTR dwAddress )
  1462. {
  1463. SEARCH s;
  1464. dprintf( "\nSEARCH at %X: ", dwAddress );
  1465. if( !GetData( &s, dwAddress, sizeof(s), "SEARCH" ) ||
  1466. !PrintBlockHeader( &s.BlockHeader, TRUE ) ) {
  1467. return FALSE;
  1468. }
  1469. PrintMemberList( &s, ML_SEARCH );
  1470. return TRUE;
  1471. }
  1472. BOOL
  1473. DumpBuffer( IN ULONG_PTR dwAddress )
  1474. {
  1475. BUFFER b;
  1476. dprintf( "\nBUFFER at %X:\n", dwAddress );
  1477. if( !GetData( &b, dwAddress, sizeof(b), "BUFFER" ) )
  1478. return FALSE;
  1479. PrintMemberList( &b, ML_BUFFER );
  1480. return TRUE;
  1481. }
  1482. BOOL
  1483. DumpSmb( IN ULONG_PTR dwAddress )
  1484. {
  1485. NT_SMB_HEADER s;
  1486. UCHAR WordCount;
  1487. dprintf( "\nSMB_HEADER at %X\n", dwAddress );
  1488. if( !GetData( &s, dwAddress, sizeof(s), "SMBHEADER" ) )
  1489. return FALSE;
  1490. PrintMemberList( &s, ML_SMB_HEADER );
  1491. if( !GetData( &WordCount, dwAddress+sizeof( NT_SMB_HEADER ), sizeof( WordCount), "WordCount" )){
  1492. ERRPRT( "Unable to retrieve WordCount at %X\n", dwAddress+sizeof(NT_SMB_HEADER) );
  1493. return FALSE;
  1494. }
  1495. dprintf( "\nWordCount @ %X = %u\n", dwAddress + sizeof( NT_SMB_HEADER), WordCount );
  1496. return TRUE;
  1497. }
  1498. BOOL
  1499. DumpTcon( IN ULONG_PTR dwAddress, IN DWORD offset, IN DWORD *value OPTIONAL )
  1500. {
  1501. TREE_CONNECT Tcon;
  1502. NONPAGED_HEADER NonpagedHeader;
  1503. dprintf( "\nTREE_CONNECT at %X: ", dwAddress );
  1504. if( !GetData( &Tcon, dwAddress, sizeof( Tcon ), "TREE_CONNECT" ) ||
  1505. !CheckBlockHeader( &Tcon.BlockHeader, BlockTypeTreeConnect, FALSE ) ||
  1506. !GetData( &NonpagedHeader, (ULONG_PTR)Tcon.NonpagedHeader, sizeof(NonpagedHeader),"NONPAGED_HEADER" ) ) {
  1507. return FALSE;
  1508. }
  1509. if( !PrintBlockHeader( &Tcon.BlockHeader, FALSE ) ||
  1510. !PrintNonpagedHeader( &NonpagedHeader, BlockTypeTreeConnect, dwAddress, TRUE ) ) {
  1511. return FALSE;
  1512. }
  1513. PrintMemberList( &Tcon, ML_TREE_CONNECT );
  1514. if( ARGUMENT_PRESENT( value ) )
  1515. *value = *(DWORD *)(((UCHAR *)&Tcon) + offset);
  1516. dprintf( "\n" );
  1517. return TRUE;
  1518. }
  1519. BOOL
  1520. DumpConnection( IN ULONG_PTR dwAddress, IN DWORD offset, OUT DWORD *value OPTIONAL )
  1521. {
  1522. CONNECTION Connection;
  1523. PAGED_CONNECTION pc;
  1524. WORK_CONTEXT wc;
  1525. ULONG_PTR wcAddr;
  1526. dprintf( "\nCONNECTION at %X: ", dwAddress );
  1527. if( !GetData( &Connection, dwAddress, sizeof( Connection ), "CONNECTION" ) ||
  1528. !CheckBlockHeader( &Connection.BlockHeader, BlockTypeConnection, TRUE ) ||
  1529. !PrintBlockHeader( &Connection.BlockHeader, TRUE ) ) {
  1530. return FALSE;
  1531. }
  1532. if( ARGUMENT_PRESENT( value ) )
  1533. *value = *(DWORD *)(((UCHAR *)&Connection) + offset);
  1534. dprintf( " OemClientMachineName: %s\n", Connection.OemClientMachineName );
  1535. PrintMemberList( &Connection, ML_CONNECTION );
  1536. if( Connection.DeviceObject != NULL ) {
  1537. //
  1538. // Assume this is a VC oriented client
  1539. //
  1540. PrintMemberList( &Connection, ML_CONNECTION_VC );
  1541. } else {
  1542. //
  1543. // Assume this is a direct host IPX client
  1544. //
  1545. PrintMemberList( &Connection, ML_CONNECTION_IPX );
  1546. }
  1547. dprintf( "\n FileTable (contains RFCBs:)\n" );
  1548. if( !DumpTable( &Connection.FileTable ) )
  1549. return FALSE;
  1550. /*
  1551. * See if we can get the PAGED_CONNECTION data
  1552. */
  1553. dprintf( "\nPagedConnection Data-> " );
  1554. if( !GetData( &pc, (ULONG_PTR)Connection.PagedConnection, sizeof(pc), "PAGED_CONNECTION" ) )
  1555. return FALSE;
  1556. PrintMemberList( &pc,ML_PAGED_CONNECTION );
  1557. dprintf( "EncryptionKey: " );
  1558. PrintHexBuf( pc.EncryptionKey, sizeof( pc.EncryptionKey ) );
  1559. dprintf( "\n\n SessionTable\n" );
  1560. if( !DumpTable( &pc.SessionTable ) )
  1561. return FALSE;
  1562. dprintf( "\n TreeConnectTable\n" );
  1563. if( !DumpTable( &pc.TreeConnectTable ) )
  1564. return FALSE;
  1565. dprintf( "\n SearchTable\n" );
  1566. if( !DumpTable( &pc.SearchTable ) )
  1567. return FALSE;
  1568. //
  1569. // Print out the in progress work item list
  1570. //
  1571. dwAddress += FIELD_OFFSET( CONNECTION, InProgressWorkItemList.Flink );
  1572. if( (ULONG_PTR)Connection.InProgressWorkItemList.Flink != dwAddress ) {
  1573. ULONG_PTR thisEntry;
  1574. LIST_ENTRY le;
  1575. dprintf( "\nIn-progress work contexts:\n" );
  1576. thisEntry = (ULONG_PTR)Connection.InProgressWorkItemList.Flink;
  1577. while( 1 ) {
  1578. if( CheckControlC() ) {
  1579. break;
  1580. }
  1581. if( thisEntry == dwAddress ) {
  1582. break;
  1583. }
  1584. wcAddr = thisEntry - FIELD_OFFSET( WORK_CONTEXT, InProgressListEntry.Flink );
  1585. RtlZeroMemory( &wc, sizeof( wc ) );
  1586. GetData( &wc, wcAddr, sizeof( wc ), "WORK_CONTEXT" );
  1587. dprintf( " %p: Rfcb %p, Session %p, Share %p, TreeConnect %p\n",
  1588. wcAddr, wc.Rfcb, wc.Session, wc.Share, wc.TreeConnect );
  1589. if( !GetData( &le, thisEntry, sizeof( le ), "LIST_ENTRY" ) )
  1590. break;
  1591. thisEntry = (ULONG_PTR)le.Flink;
  1592. }
  1593. }
  1594. dprintf( "\n" );
  1595. return TRUE;
  1596. }
  1597. BOOL
  1598. DumpLfcb( IN ULONG_PTR dwAddress )
  1599. {
  1600. LFCB l;
  1601. if( !GetData( &l, dwAddress, sizeof( l ), "LFCB" ) ||
  1602. !CheckBlockHeader( (PBLOCK_HEADER)&l.BlockHeader, BlockTypeLfcb, TRUE ) ||
  1603. !PrintBlockHeader( (PBLOCK_HEADER)&l.BlockHeader, TRUE ) ) {
  1604. return FALSE;
  1605. }
  1606. PrintMemberList( &l, ML_LFCB );
  1607. return TRUE;
  1608. }
  1609. BOOL
  1610. DumpMfcb( IN ULONG_PTR dwAddress )
  1611. {
  1612. MFCB m;
  1613. NONPAGED_MFCB npm;
  1614. if( !GetData( &m, dwAddress, sizeof( m ), "MFCB" ) ||
  1615. !CheckBlockHeader( (PBLOCK_HEADER)&m.BlockHeader, BlockTypeMfcb, FALSE ) ||
  1616. !PrintBlockHeader( (PBLOCK_HEADER)&m.BlockHeader, FALSE ) ||
  1617. !GetData( &npm, (ULONG_PTR)m.NonpagedMfcb, sizeof( npm ), "NONPAGED_MFCB" ) ) {
  1618. return FALSE;
  1619. }
  1620. PrintMemberList( &m, ML_MFCB );
  1621. PrintMemberList( &npm, ML_NONPAGED_MFCB );
  1622. return TRUE;
  1623. }
  1624. BOOL
  1625. DumpRfcb( ULONG_PTR dwAddress, PLIST_ENTRY *Flink )
  1626. {
  1627. RFCB r;
  1628. MFCB m;
  1629. PAGED_RFCB p;
  1630. BOOL PagedPresent;
  1631. if( !GetData( &r, dwAddress, sizeof( r ), "RFCB" ) ||
  1632. !CheckBlockHeader( (PBLOCK_HEADER)&r, BlockTypeRfcb, FALSE ) ) {
  1633. return FALSE;
  1634. }
  1635. PagedPresent = GetData( &p,(ULONG_PTR)r.PagedRfcb, sizeof( p ), "PAGED_RFCB" );
  1636. dprintf( "Rfcb @ %x:\n", dwAddress );
  1637. if( Flink == NULL ) {
  1638. if( !PrintBlockHeader( (PBLOCK_HEADER)&r, TRUE ) )
  1639. return FALSE;
  1640. PrintMemberList( &r, ML_RFCB );
  1641. if( PagedPresent ) PrintMemberList( &p, ML_PAGED_RFCB );
  1642. } else {
  1643. PrintMemberList( &r, ML_RFCB_QUICK );
  1644. *Flink = r.GlobalRfcbListEntry.ListEntry.Flink;
  1645. }
  1646. if( !GetData( &m, (ULONG_PTR)r.Mfcb, sizeof( m ), "MFCB" ) )
  1647. return FALSE;
  1648. PrintStringW( "File: ", &m.FileName, TRUE );
  1649. return TRUE;
  1650. }
  1651. BOOL
  1652. DumpSession( IN ULONG_PTR dwAddress, IN DWORD offset, OUT DWORD *value OPTIONAL )
  1653. {
  1654. SESSION Session;
  1655. NONPAGED_HEADER NonpagedHeader;
  1656. if( !GetData( &Session, dwAddress, sizeof( Session ), "SESSION" ) ||
  1657. !CheckBlockHeader( &Session.BlockHeader, BlockTypeSession, FALSE ) ||
  1658. !PrintBlockHeader( &Session.BlockHeader, FALSE ) ||
  1659. !GetData( &NonpagedHeader, (ULONG_PTR)Session.NonpagedHeader, sizeof(NonpagedHeader),"NONPAGED_HEADER" ) ||
  1660. !PrintNonpagedHeader( &NonpagedHeader, BlockTypeSession, dwAddress, TRUE ) ) {
  1661. return FALSE;
  1662. }
  1663. if( ARGUMENT_PRESENT( value ) )
  1664. *value = *(DWORD *)(((UCHAR *)&Session) + offset);
  1665. PrintMemberList( &Session, ML_SESSION );
  1666. dprintf( "%-30s ", "NtUserSessionKey" );
  1667. PrintHexBuf( Session.NtUserSessionKey, sizeof( Session.NtUserSessionKey ) );
  1668. dprintf( "\n %-30s ", "LanManSessionKey" );
  1669. PrintHexBuf( Session.LanManSessionKey, sizeof( Session.LanManSessionKey ) );
  1670. dprintf( "\n\n" );
  1671. return TRUE;
  1672. }
  1673. BOOL
  1674. DumpTransaction( IN ULONG_PTR dwAddress )
  1675. {
  1676. TRANSACTION t;
  1677. dprintf( "\nTRANSACTION at %X:\n", dwAddress );
  1678. if( !GetData( &t, dwAddress, sizeof(t), "TRANSACTION" ) )
  1679. return FALSE;
  1680. PrintMemberList( &t, ML_TRANSACTION );
  1681. return TRUE;
  1682. }
  1683. BOOL
  1684. DumpWorkContext( IN ULONG_PTR dwAddress )
  1685. {
  1686. WORK_CONTEXT wc;
  1687. dprintf( "\nWORK_CONTEXT at %X:\n", dwAddress );
  1688. if( !GetData( &wc, dwAddress, sizeof(wc), "WORK_CONTEXT" ) )
  1689. return FALSE;
  1690. PrintMemberList( &wc, ML_WORK_CONTEXT );
  1691. dprintf( " Parameters addr %X, Parameters2 addr %X\n",
  1692. dwAddress + FIELD_OFFSET( WORK_CONTEXT, Parameters ),
  1693. dwAddress + FIELD_OFFSET( WORK_CONTEXT, Parameters2 ));
  1694. if( wc.BlockingOperation )
  1695. dprintf( " BlockingOperation" );
  1696. if( wc.UsingExtraSmbBuffer )
  1697. dprintf( " UsingExtraSmbBuffer" );
  1698. if( wc.OplockOpen )
  1699. dprintf( " OplockOpen" );
  1700. if( wc.ShareAclFailure )
  1701. dprintf( " ShareAclFailure" );
  1702. if( wc.QueueToHead )
  1703. dprintf( " QueueToHead" );
  1704. if( wc.NoResponseSmbSecuritySignature )
  1705. dprintf( " NoResponseSmbSecuritySignature" );
  1706. if( wc.LargeIndication )
  1707. dprintf( " LargeIndication" );
  1708. dprintf( "\n" );
  1709. return TRUE;
  1710. }
  1711. VOID *
  1712. ThreadHandleToPointer( HANDLE hThread )
  1713. {
  1714. return (VOID *)hThread;
  1715. }
  1716. BOOL
  1717. DumpWorkQueue( IN ULONG_PTR dwAddress )
  1718. {
  1719. WORK_QUEUE WorkQueue;
  1720. ULONG i;
  1721. PHANDLE pHandles;
  1722. dprintf( " at %X:\n", dwAddress );
  1723. if( !GetData( &WorkQueue, dwAddress, sizeof( WorkQueue ), "WORK_QUEUE" ) )
  1724. return FALSE;
  1725. if( WorkQueue.Queue.Header.Type != QueueObject ) {
  1726. ERRPRT( "WARNING: Queue.Header.Type is %X, should be %X\n",
  1727. WorkQueue.Queue.Header.Type, QueueObject );
  1728. }
  1729. if( WorkQueue.Queue.Header.Size != sizeof( KQUEUE )/ sizeof( LONG ) ) {
  1730. ERRPRT( "WARNING: Queue.Header.Size is %d, should be %d\n",
  1731. WorkQueue.Queue.Header.Size, sizeof( KQUEUE ) );
  1732. }
  1733. PrintMemberList( &WorkQueue, ML_WORK_QUEUE );
  1734. if( WorkQueue.Queue.Header.SignalState > 0 ) {
  1735. dprintf( " Queued WORK_CONTEXTs:\n" );
  1736. if( !PrintListEntryList( dwAddress + FIELD_OFFSET(WORK_QUEUE, Queue.EntryListHead.Flink ),
  1737. FIELD_OFFSET( KWAIT_BLOCK, Thread ))) {
  1738. }
  1739. }
  1740. return TRUE;
  1741. }
  1742. VOID
  1743. PrintHelp( VOID )
  1744. {
  1745. int i;
  1746. for( i=0; Extensions[i]; i++ )
  1747. dprintf( " %s\n", Extensions[i] );
  1748. }
  1749. /*
  1750. * Print out the usage message
  1751. */
  1752. DECLARE_API( help )
  1753. {
  1754. PrintHelp();
  1755. }
  1756. /*
  1757. * Follow a LIST_ENTRY to the end
  1758. */
  1759. DECLARE_API( df )
  1760. {
  1761. LIST_ENTRY ListEntry;
  1762. ULONG_PTR headAddress, dwAddress, prevAddress;
  1763. ULONG count = 0;
  1764. if( args == NULL || *args == '\0' ) {
  1765. PrintHelp();
  1766. return;
  1767. }
  1768. headAddress = GetExpression( args );
  1769. if( !headAddress ||
  1770. !GetData( &ListEntry, headAddress, sizeof( ListEntry ), "LIST_HEAD" ) ) {
  1771. return;
  1772. }
  1773. prevAddress = headAddress;
  1774. while( !CheckControlC() ) {
  1775. dwAddress = (ULONG_PTR)ListEntry.Flink;
  1776. if( dwAddress == headAddress ) {
  1777. dprintf( " %u elements in the list\n", count );
  1778. return;
  1779. }
  1780. if( dwAddress == prevAddress ) {
  1781. dprintf( " Flink at %X points to itself. Count %u\n", dwAddress, count );
  1782. }
  1783. if( !GetData( &ListEntry, dwAddress, sizeof( ListEntry ), "LIST_ENTRY" ) ) {
  1784. dprintf( " Flink at %X is bad --", prevAddress );
  1785. dprintf( " %u elements into list\n", count );
  1786. return;
  1787. }
  1788. prevAddress = dwAddress;
  1789. count++;
  1790. }
  1791. dprintf( " CTRL-C: %u elements scanned\n", count );
  1792. }
  1793. DECLARE_API( pagedconnection )
  1794. {
  1795. ULONG_PTR dwAddress;
  1796. PAGED_CONNECTION pc;
  1797. if( args == NULL || *args == '\0' ) {
  1798. PrintHelp();
  1799. } else {
  1800. dwAddress = GetExpression( args );
  1801. if( dwAddress && GetData( &pc, dwAddress, sizeof(pc), "PAGED_CONNECTION" ) ) {
  1802. dprintf( " sizeof( PAGED_CONNECTION ) = %d bytes\n", sizeof( pc ) );
  1803. PrintMemberList( &pc, ML_PAGED_CONNECTION );
  1804. }
  1805. }
  1806. }
  1807. DECLARE_API( share )
  1808. {
  1809. ULONG_PTR dwAddress;
  1810. BOOL ShowMany = FALSE;
  1811. SHARE_TYPE ShareType = (SHARE_TYPE)-1;
  1812. LPCSTR ShareName = NULL;
  1813. LIST_ENTRY SrvShareHashTable[ NSHARE_HASH_TABLE ];
  1814. ULONG i;
  1815. if( args == NULL || *args == '\0' ) {
  1816. ShowMany = TRUE;
  1817. } else if( !_strcmpi( args, "disk" ) ) {
  1818. ShowMany = TRUE;
  1819. ShareType = ShareTypeDisk;
  1820. } else if( !_strcmpi( args, "print" ) ) {
  1821. ShowMany = TRUE;
  1822. ShareType = ShareTypePrint;
  1823. } else if( !_strcmpi( args, "pipe" ) ) {
  1824. ShowMany = TRUE;
  1825. ShareType = ShareTypePipe;
  1826. } else if( args[0] == '=' ) {
  1827. ShareName = args + 1;
  1828. ShowMany = TRUE;
  1829. } else if( !_strcmpi( args, "?" ) ) {
  1830. PrintHelp();
  1831. return;
  1832. }
  1833. if( ShowMany == FALSE ) {
  1834. //
  1835. // Get at the address that was passed to this on the command line.
  1836. //
  1837. dwAddress = GetExpression( args );
  1838. if( dwAddress == 0 )
  1839. return;
  1840. DumpShare( dwAddress, ShareType, NULL, NULL );
  1841. return;
  1842. }
  1843. //
  1844. // Dump entries from the entire server share table!
  1845. //
  1846. dwAddress = GetExpression( "srv!SrvShareHashTable" );
  1847. if( dwAddress == 0 ) {
  1848. ERRPRT( "Unable to get address for srv!SrvShareHashTable\n" );
  1849. return;
  1850. }
  1851. if( !GetData( SrvShareHashTable, dwAddress, sizeof( SrvShareHashTable ), "HASH TABLE" ) ) {
  1852. ERRPRT( "Unable to read hash table\n" );
  1853. return;
  1854. }
  1855. for( i = 0; i < NSHARE_HASH_TABLE; i++ ) {
  1856. LIST_ENTRY *NextShare;
  1857. NextShare = SrvShareHashTable[i].Flink;
  1858. while( (ULONG_PTR)NextShare != dwAddress + i*sizeof( LIST_ENTRY ) ) {
  1859. ULONG_PTR ShareEntry;
  1860. ShareEntry = (ULONG_PTR)CONTAINING_RECORD( NextShare, SHARE, GlobalShareList );
  1861. if( !DumpShare( ShareEntry, ShareType, ShareName, &NextShare ) )
  1862. break;
  1863. }
  1864. }
  1865. }
  1866. DECLARE_API( lock )
  1867. {
  1868. ULONG_PTR dwAddress;
  1869. CHAR buf[ 100 ];
  1870. int i;
  1871. if( args && *args ) {
  1872. dwAddress = GetExpression( args );
  1873. DumpLock( dwAddress );
  1874. return;
  1875. }
  1876. strcpy( buf, "srv!" );
  1877. for( i=0; SrvLocks[i]; i++ ) {
  1878. strcpy( &buf[4], SrvLocks[i] );
  1879. dwAddress = GetExpression ( buf );
  1880. if( dwAddress == 0 ) {
  1881. ERRPRT( "Unable to get address of %s\n", SrvLocks[i] );
  1882. continue;
  1883. }
  1884. dprintf( "\n%s\n", SrvLocks[i] );
  1885. if( !DumpLock( dwAddress ) )
  1886. break;
  1887. }
  1888. }
  1889. DECLARE_API( endpoint )
  1890. {
  1891. LIST_ENTRY *NextEndpoint;
  1892. ORDERED_LIST_HEAD SrvEndpointList;
  1893. ULONG_PTR dwAddress;
  1894. int i;
  1895. if( args && *args ) {
  1896. dwAddress = GetExpression( args );
  1897. DumpEndpoint( dwAddress, NULL );
  1898. return;
  1899. }
  1900. dwAddress = GetExpression ( "srv!SrvEndpointList" );
  1901. if( dwAddress == 0 ) {
  1902. ERRPRT( "Unable to get address of srv!SrvEndpointList\n" );
  1903. return;
  1904. }
  1905. if( !GetData( &SrvEndpointList, dwAddress, sizeof( SrvEndpointList ), "ORDERED_LIST_HEAD" ) ) {
  1906. ERRPRT( "Unable to read data for srv!SrvEndpointList\n" );
  1907. return;
  1908. }
  1909. if( SrvEndpointList.Initialized == 0 ) {
  1910. ERRPRT( "srv!SrvEndpointList.Initialized == 0!\n" );
  1911. return;
  1912. }
  1913. if( (ULONG_PTR)SrvEndpointList.ListHead.Flink == dwAddress ) {
  1914. ERRPRT( "srv!SrvEndpointList list is empty\n" );
  1915. return;
  1916. }
  1917. if( (ULONG_PTR)SrvEndpointList.ListHead.Flink == 0 ) {
  1918. ERRPRT( "srv!SrvEndpointList.ListHead.Flink == 0: list is empty\n" );
  1919. return;
  1920. }
  1921. NextEndpoint = SrvEndpointList.ListHead.Flink;
  1922. do {
  1923. ULONG_PTR EndpointEntry;
  1924. if( CheckControlC() ) {
  1925. dprintf( "\n" );
  1926. break;
  1927. }
  1928. EndpointEntry = (ULONG_PTR)CONTAINING_RECORD( NextEndpoint, ENDPOINT, GlobalEndpointListEntry );
  1929. if( !DumpEndpoint( EndpointEntry, &NextEndpoint ) )
  1930. break;
  1931. } while( (ULONG_PTR)NextEndpoint != dwAddress );
  1932. }
  1933. DECLARE_API( search )
  1934. {
  1935. if( !args || !*args ) {
  1936. ERRPRT( "SEARCH address required\n" );
  1937. } else {
  1938. DumpSearch( GetExpression( args ) );
  1939. }
  1940. }
  1941. DECLARE_API( buffer )
  1942. {
  1943. if( !args || !*args ) {
  1944. ERRPRT( "BUFFER address required\n" );
  1945. } else {
  1946. DumpBuffer( GetExpression( args ) );
  1947. }
  1948. }
  1949. DECLARE_API( smb )
  1950. {
  1951. if( !args || !*args ) {
  1952. ERRPRT( "BUFFER address required\n" );
  1953. } else {
  1954. DumpSmb( GetExpression( args ) );
  1955. }
  1956. }
  1957. DECLARE_API( tcon )
  1958. {
  1959. if( !args || !*args ) {
  1960. ERRPRT( "Tcon address required\n" );
  1961. } else {
  1962. DumpTcon( GetExpression(args), 0, NULL );
  1963. }
  1964. }
  1965. DECLARE_API ( connection )
  1966. {
  1967. if( !args || !*args ) {
  1968. ERRPRT( "Connection address required\n" );
  1969. } else {
  1970. DumpConnection( GetExpression(args), 0, NULL );
  1971. }
  1972. }
  1973. DECLARE_API( lfcb )
  1974. {
  1975. if( !args || !*args ) {
  1976. ERRPRT( "LFCB address required\n" );
  1977. } else {
  1978. DumpLfcb( GetExpression(args) );
  1979. }
  1980. }
  1981. DECLARE_API( mfcb )
  1982. {
  1983. if( !args || !*args ) {
  1984. ERRPRT( "MFCB address required\n" );
  1985. } else {
  1986. DumpMfcb( GetExpression(args) );
  1987. }
  1988. }
  1989. DECLARE_API( rfcb )
  1990. {
  1991. LIST_ENTRY *NextRfcb;
  1992. ORDERED_LIST_HEAD SrvRfcbList;
  1993. ULONG_PTR dwAddress;
  1994. int i;
  1995. if( args && *args ) {
  1996. DumpRfcb( GetExpression(args), NULL );
  1997. return;
  1998. }
  1999. dwAddress = GetExpression ( "srv!SrvRfcbList" );
  2000. if( dwAddress == 0 ) {
  2001. ERRPRT( "Unable to get address of srv!SrvSrvRfcbList\n" );
  2002. return;
  2003. }
  2004. if( !GetData( &SrvRfcbList, dwAddress, sizeof( SrvRfcbList ), "ORDERED_LIST_HEAD" ) ) {
  2005. ERRPRT( "Unable to read data for srv!SrvRfcbList\n" );
  2006. return;
  2007. }
  2008. if( SrvRfcbList.Initialized == 0 ) {
  2009. ERRPRT( "srv!SrvRfcbList.Initialized == 0!\n" );
  2010. return;
  2011. }
  2012. if( (ULONG_PTR)SrvRfcbList.ListHead.Flink == dwAddress ) {
  2013. ERRPRT( "srv!SrvRfcbList list is empty\n" );
  2014. return;
  2015. }
  2016. if( (ULONG_PTR)SrvRfcbList.ListHead.Flink == 0 ) {
  2017. ERRPRT( "srv!SrvRfcbList.ListHead.Flink == 0: list is empty\n" );
  2018. return;
  2019. }
  2020. NextRfcb = SrvRfcbList.ListHead.Flink;
  2021. do {
  2022. ULONG_PTR RfcbEntry;
  2023. RfcbEntry = (ULONG_PTR)CONTAINING_RECORD( NextRfcb, RFCB, GlobalRfcbListEntry );
  2024. dprintf( "\n" );
  2025. DumpRfcb( RfcbEntry, &NextRfcb );
  2026. if( CheckControlC() ) {
  2027. dprintf( "\n" );
  2028. break;
  2029. }
  2030. } while( (ULONG_PTR)NextRfcb != dwAddress );
  2031. }
  2032. DECLARE_API( session )
  2033. {
  2034. if( !args || !*args ) {
  2035. ERRPRT( "Session address required\n" );
  2036. } else {
  2037. DumpSession( GetExpression(args), 0, NULL );
  2038. }
  2039. }
  2040. DECLARE_API( globals )
  2041. {
  2042. ULONG_PTR dwAddress;
  2043. CHAR buf[ 200 ];
  2044. int i;
  2045. int c=0;
  2046. GUID guid;
  2047. strcpy( buf, "srv!" );
  2048. dprintf( "BOOLEAN Values (%u bytes):\n", sizeof( BOOLEAN ) );
  2049. for( i=0; GlobalBool[i]; i++, c++ ) {
  2050. BOOLEAN b;
  2051. strcpy( &buf[4], GlobalBool[i] );
  2052. dwAddress = GetExpression ( buf );
  2053. if( dwAddress == 0 ) {
  2054. continue;
  2055. }
  2056. if( !GetData( &b, dwAddress, sizeof(b), GlobalBool[i] ) )
  2057. return;
  2058. dprintf( "%s%-35s %10s%s",
  2059. c&1 ? " " : "",
  2060. GlobalBool[i],
  2061. b ? " TRUE" : "FALSE",
  2062. c&1 ? "\n" : "" );
  2063. }
  2064. if( CheckControlC() ) {
  2065. dprintf( "\n" );
  2066. return;
  2067. }
  2068. dprintf( "%s\nSHORT Values (%u bytes):\n", c&1 ? "\n" : "" ,sizeof( SHORT ) );
  2069. c &= ~01;
  2070. for( i=0; GlobalShort[i]; i++, c++ ) {
  2071. SHORT s;
  2072. strcpy( &buf[4], GlobalShort[i] );
  2073. dwAddress = GetExpression ( buf );
  2074. if( dwAddress == 0 ) {
  2075. continue;
  2076. }
  2077. if( !GetData( &s, dwAddress, sizeof(s), GlobalShort[i] ) )
  2078. return;
  2079. dprintf( "%s%-35s %10d%s",
  2080. c&1 ? " " : "",
  2081. GlobalShort[i],
  2082. s,
  2083. c&1 ? "\n" : "" );
  2084. }
  2085. if( CheckControlC() ) {
  2086. dprintf( "\n" );
  2087. return;
  2088. }
  2089. dprintf( "%s\nLONG Values (%u bytes):\n", c&1 ? "\n" : "", sizeof( LONG ) );
  2090. c &= ~01;
  2091. for( i=0; GlobalLong[i]; i++, c++ ) {
  2092. LONG l;
  2093. strcpy( &buf[4], GlobalLong[i] );
  2094. dwAddress = GetExpression ( buf );
  2095. if( dwAddress == 0 ) {
  2096. continue;
  2097. }
  2098. if( !GetData( &l, dwAddress, sizeof(l), GlobalLong[i] ) )
  2099. return;
  2100. dprintf( "%s%-35s %10u%s",
  2101. c&1 ? " " : "",
  2102. GlobalLong[i],
  2103. l,
  2104. c&1 ? "\n" : "" );
  2105. }
  2106. if( CheckControlC() ) {
  2107. dprintf( "\n" );
  2108. return;
  2109. }
  2110. for( i=0; GlobalLongHex[i]; i++, c++ ) {
  2111. LONG l;
  2112. strcpy( &buf[4], GlobalLongHex[i] );
  2113. dwAddress = GetExpression ( buf );
  2114. if( dwAddress == 0 ) {
  2115. continue;
  2116. }
  2117. if( !GetData( &l, dwAddress, sizeof(l), GlobalLongHex[i] ) )
  2118. return;
  2119. dprintf( "%s%-35s %10X%s",
  2120. c&1 ? " " : "",
  2121. GlobalLongHex[i],
  2122. l,
  2123. c&1 ? "\n" : "" );
  2124. }
  2125. if( CheckControlC() ) {
  2126. dprintf( "\n" );
  2127. return;
  2128. }
  2129. //
  2130. // Dump out the server GUID
  2131. //
  2132. dwAddress = GetExpression( "srv!ServerGuid" );
  2133. if( dwAddress != 0 &&
  2134. GetData( &guid, dwAddress, sizeof(guid), "ServerGuid" ) ) {
  2135. dprintf( "%s%s ", c&1 ? " " : "", "ServerGuid" );
  2136. for( i=0; i < sizeof( guid ); i++ ) {
  2137. dprintf( "%2.2X", ((CHAR *)&guid)[i] & 0xFF );
  2138. }
  2139. }
  2140. for( i = 0; GlobalStrings[i]; i++ ) {
  2141. UNICODE_STRING String;
  2142. WCHAR wszbuf[35];
  2143. dprintf( "\n%s%s:\n", c&1 ? "\n" : "", GlobalStrings[i] );
  2144. c &= ~01;
  2145. strcpy( &buf[4], GlobalStrings[i] );
  2146. dwAddress = GetExpression ( buf );
  2147. if( dwAddress == 0 ) {
  2148. continue;
  2149. }
  2150. if( GetData( &String, dwAddress, sizeof( String ), GlobalStrings[i] ) ) {
  2151. wszbuf[ sizeof(wszbuf)/sizeof(wszbuf[0]) - 1 ] = L'\0';
  2152. if( !GetString( (ULONG_PTR)String.Buffer, wszbuf, sizeof(wszbuf)/sizeof(wszbuf[0])-1) )
  2153. continue;
  2154. dprintf( " %-35ws%s", wszbuf, c&1 ? "\n" : "" );
  2155. c++;
  2156. }
  2157. }
  2158. if( CheckControlC() ) {
  2159. dprintf( "\n" );
  2160. return;
  2161. }
  2162. for( i=0; GlobalStringVector[i]; i++ ) {
  2163. ULONG_PTR StringAddress;
  2164. WCHAR wszbuf[ 35 ];
  2165. dprintf( "\n%s%s:\n", c&1 ? "\n" : "", GlobalStringVector[i] );
  2166. c &= ~01;
  2167. strcpy( &buf[4], GlobalStringVector[i] );
  2168. dwAddress = GetExpression ( buf );
  2169. if( dwAddress == 0 ) {
  2170. continue;
  2171. }
  2172. if( !GetData( &dwAddress, dwAddress, sizeof( dwAddress ), GlobalStringVector[i] ) ) {
  2173. return;
  2174. }
  2175. if( dwAddress == 0 )
  2176. continue;
  2177. wszbuf[ sizeof(wszbuf)/sizeof(wszbuf[0]) - 1 ] = L'\0';
  2178. while( 1 ) {
  2179. if( !GetData( &StringAddress, dwAddress, sizeof(StringAddress), GlobalStringVector[i] ) )
  2180. break;
  2181. if( StringAddress == 0 )
  2182. break;
  2183. if( !GetString( StringAddress, wszbuf, sizeof(wszbuf) / sizeof(wszbuf[0]) - 1 ) )
  2184. break;
  2185. dprintf( " %-35ws%s",
  2186. wszbuf,
  2187. c&1 ? "\n" : "" );
  2188. dwAddress += sizeof( LPSTR );
  2189. c++;
  2190. }
  2191. }
  2192. dprintf( "\n" );
  2193. }
  2194. DECLARE_API( context )
  2195. {
  2196. if( args == NULL || !*args ) {
  2197. ERRPRT( "WORK_CONTEXT address required\n" );
  2198. } else {
  2199. DumpWorkContext( GetExpression( args ) );
  2200. }
  2201. }
  2202. DECLARE_API( transaction )
  2203. {
  2204. if( args == NULL || !*args ) {
  2205. ERRPRT( "TRANSACTION address required\n" );
  2206. } else {
  2207. DumpTransaction( GetExpression( args ) );
  2208. }
  2209. }
  2210. DECLARE_API( queue )
  2211. {
  2212. ULONG_PTR dwAddress, dweAddress;
  2213. ULONG nProcessors;
  2214. ULONG i;
  2215. BOOLEAN mp;
  2216. if( args && *args ) {
  2217. dprintf( "WorkQueue" );
  2218. DumpWorkQueue( GetExpression( args ) );
  2219. return;
  2220. }
  2221. dwAddress = GetExpression( "srv!SrvMultiProcessorDriver" );
  2222. if( !GetData( &mp, dwAddress, sizeof( mp ), "srv!SrvMultiProcessorDriver" ) )
  2223. return;
  2224. if( mp == TRUE ) {
  2225. dwAddress = GetExpression( "srv!SrvNumberOfProcessors" );
  2226. if( !GetData( &nProcessors, dwAddress, sizeof(nProcessors), "srv!SrvNumberOfProcessors" ) )
  2227. return;
  2228. dwAddress = GetExpression( "srv!SrvWorkQueues" );
  2229. if( !GetData( &dwAddress, dwAddress, sizeof(dwAddress), "srv!SrvWorkQueues" ))
  2230. return;
  2231. dweAddress = GetExpression( "srv!eSrvWorkQueues" );
  2232. if( !GetData( &dweAddress, dweAddress, sizeof(dweAddress), "srv!eSrvWorkQueues" ))
  2233. return;
  2234. if( dwAddress + nProcessors*sizeof(WORK_QUEUE) != dweAddress ) {
  2235. ERRPRT( "eSrvWorkQueues is %X, should be %X\n",
  2236. dweAddress, dwAddress + nProcessors*sizeof(WORK_QUEUE) );
  2237. }
  2238. } else {
  2239. dwAddress = GetExpression( "srv!SrvWorkQueues" );
  2240. nProcessors = 1;
  2241. }
  2242. for( i=0; i < nProcessors; i++, dwAddress += sizeof( WORK_QUEUE ) ) {
  2243. dprintf( "%sProcessor %d ", i?"\n":"", i );
  2244. if( DumpWorkQueue( dwAddress ) == FALSE )
  2245. break;
  2246. }
  2247. dwAddress = GetExpression( "srv!SrvBlockingWorkQueue" );
  2248. dprintf( "\nBlockingWorkQueue " );
  2249. DumpWorkQueue( dwAddress );
  2250. }
  2251. char *mystrtok ( char *string, char * control )
  2252. {
  2253. static unsigned char *str;
  2254. char *p, *s;
  2255. if( string )
  2256. str = string;
  2257. if( str == NULL || *str == '\0' )
  2258. return NULL;
  2259. //
  2260. // Skip leading delimiters...
  2261. //
  2262. for( ; *str; str++ ) {
  2263. for( s=control; *s; s++ ) {
  2264. if( *str == *s )
  2265. break;
  2266. }
  2267. if( *s == '\0' )
  2268. break;
  2269. }
  2270. //
  2271. // Was it was all delimiters?
  2272. //
  2273. if( *str == '\0' ) {
  2274. str = NULL;
  2275. return NULL;
  2276. }
  2277. //
  2278. // We've got a string, terminate it at first delimeter
  2279. //
  2280. for( p = str+1; *p; p++ ) {
  2281. for( s = control; *s; s++ ) {
  2282. if( *p == *s ) {
  2283. s = str;
  2284. *p = '\0';
  2285. str = p+1;
  2286. return s;
  2287. }
  2288. }
  2289. }
  2290. //
  2291. // We've got a string that ends with the NULL
  2292. //
  2293. s = str;
  2294. str = NULL;
  2295. return s;
  2296. }
  2297. void
  2298. DoLongLongBits( PCSTR symbol, PCSTR args, struct BitFields b[] )
  2299. {
  2300. ULONGLONG value;
  2301. ULONG_PTR dwAddress;
  2302. char *p;
  2303. ULONG bytesWritten;
  2304. int i;
  2305. int bsize;
  2306. dwAddress = GetExpression( symbol );
  2307. if( !GetData( &value, dwAddress, sizeof(value), symbol ) )
  2308. return;
  2309. if( !args || !*args ) {
  2310. for( i=0; b[i].name; i++ ) {
  2311. if( i && i%3 == 0 )
  2312. dprintf( "\n" );
  2313. if( strlen( b[i].name ) > 15 ) {
  2314. dprintf( " %2u %-.7s...%s ", i, b[i].name,
  2315. b[i].name+strlen(b[i].name)-5 );
  2316. } else {
  2317. dprintf( " %2u %-15s ", i, b[i].name );
  2318. }
  2319. dprintf( " %c", value & b[i].value ? 'T' : 'F' );
  2320. }
  2321. dprintf( "\n" );
  2322. return;
  2323. }
  2324. for( bsize=0; b[ bsize ].name; bsize++ )
  2325. ;
  2326. if( !_strcmpi( args, "on" ) || !_strcmpi( args, "true" ) || !_strcmpi( args, "t" ) ) {
  2327. value = (ULONGLONG)-1;
  2328. } else if( !_strcmpi( args, "off" ) || !_strcmpi( args, "false" ) || !_strcmpi( args, "f" ) ) {
  2329. value = 0;
  2330. } else {
  2331. char argbuf[ MAX_PATH ];
  2332. strcpy( argbuf, args );
  2333. for( p = mystrtok( argbuf, " \t,;" ); p && *p; p = mystrtok( NULL, " \t,;" ) ) {
  2334. i = atoi( p );
  2335. if( i < 0 || i >= bsize ) {
  2336. dprintf( "%s: illegal index number\n", p );
  2337. continue;
  2338. }
  2339. if( value & b[i].value ) {
  2340. value &= ~b[i].value;
  2341. } else {
  2342. value |= b[i].value;
  2343. }
  2344. }
  2345. }
  2346. WriteMemory( dwAddress, &value, sizeof(value), &bytesWritten );
  2347. if( bytesWritten != sizeof( value ) )
  2348. dprintf( "Write error\n" );
  2349. }
  2350. DECLARE_API( srvdebug )
  2351. {
  2352. #if SRVDBG == 1
  2353. DoLongLongBits( "srv!SrvDebug", args, SrvDebugFlags );
  2354. #else
  2355. dprintf( "Not Available!\n" );
  2356. #endif
  2357. }
  2358. DECLARE_API( smbdebug )
  2359. {
  2360. #if SRVDBG == 1
  2361. DoLongLongBits( "srv!SmbDebug", args, SmbDebugFlags );
  2362. #else
  2363. dprintf( "Not Available!\n" );
  2364. #endif
  2365. }
  2366. DECLARE_API( statistics )
  2367. {
  2368. ULONG_PTR dwAddress;
  2369. SRV_STATISTICS s;
  2370. dwAddress = GetExpression( "srv!SrvStatistics" );
  2371. if( !GetData( &s, dwAddress, sizeof(s), "SrvStatistics" ) )
  2372. return;
  2373. PrintMemberList( &s, ML_SRV_STATISTICS );
  2374. }
  2375. DECLARE_API( scavenger )
  2376. {
  2377. ULONG_PTR dwAddress;
  2378. CHAR buf[ 100 ];
  2379. int i;
  2380. int c=0;
  2381. strcpy( buf, "srv!" );
  2382. dprintf( "BOOLEAN Values (%u bytes):\n", sizeof( BOOLEAN ) );
  2383. for( i=0; ScavengerBool[i]; i++, c++ ) {
  2384. BOOLEAN b;
  2385. strcpy( &buf[4], ScavengerBool[i] );
  2386. dwAddress = GetExpression ( buf );
  2387. if( dwAddress == 0 ) {
  2388. ERRPRT( "Unable to get address of %s\n", ScavengerBool[i] );
  2389. continue;
  2390. }
  2391. if( !GetData( &b, dwAddress, sizeof(b), ScavengerBool[i] ) )
  2392. return;
  2393. dprintf( "%s%-30s %10s%s",
  2394. c&1 ? " " : "",
  2395. ScavengerBool[i],
  2396. b ? " TRUE" : "FALSE",
  2397. c&1 ? "\n" : "" );
  2398. }
  2399. dprintf( "%s\nLONG Values (%u bytes):\n", c&1 ? "\n" : "", sizeof( LONG ) );
  2400. c &= ~01;
  2401. for( i=0; ScavengerLong[i]; i++, c++ ) {
  2402. LONG l;
  2403. strcpy( &buf[4], ScavengerLong[i] );
  2404. dwAddress = GetExpression ( buf );
  2405. if( dwAddress == 0 ) {
  2406. ERRPRT( "Unable to get address of %s\n", ScavengerLong[i] );
  2407. continue;
  2408. }
  2409. if( !GetData( &l, dwAddress, sizeof(l), ScavengerLong[i] ) )
  2410. return;
  2411. dprintf( "%s%-30s %10u%s",
  2412. c&1 ? " " : "",
  2413. ScavengerLong[i],
  2414. l,
  2415. c&1 ? "\n" : "" );
  2416. }
  2417. }
  2418. DECLARE_API( srv )
  2419. {
  2420. ULONG_PTR dwAddress;
  2421. BOOLEAN b;
  2422. ULONG ul;
  2423. ULONG bytesWritten;
  2424. dwAddress = GetExpression( "srv!SrvProductTypeServer" );
  2425. b = TRUE;
  2426. WriteMemory( dwAddress, &b, sizeof(b), &bytesWritten );
  2427. if( bytesWritten != sizeof(b) ) {
  2428. ERRPRT( "Unable to update SrvProductTypeServer\n" );
  2429. return;
  2430. }
  2431. dwAddress = GetExpression( "srv!SrvCachedOpenLimit" );
  2432. ul = 5;
  2433. WriteMemory( dwAddress, &ul, sizeof(ul), &bytesWritten );
  2434. if( bytesWritten != sizeof(ul) ) {
  2435. ERRPRT( "Unable to update SrvCachedOpenLimit\n" );
  2436. }
  2437. }
  2438. DECLARE_API( wksta )
  2439. {
  2440. ULONG_PTR dwAddress;
  2441. BOOLEAN b;
  2442. ULONG ul;
  2443. ULONG bytesWritten;
  2444. dwAddress = GetExpression( "srv!SrvProductTypeServer" );
  2445. b = FALSE;
  2446. WriteMemory( dwAddress, &b, sizeof(b), &bytesWritten );
  2447. if( bytesWritten != sizeof(b) ) {
  2448. ERRPRT( "Unable to update SrvProductTypeServer\n" );
  2449. return;
  2450. }
  2451. dwAddress = GetExpression( "srv!SrvCachedOpenLimit" );
  2452. ul = 0;
  2453. WriteMemory( dwAddress, &ul, sizeof(ul), &bytesWritten );
  2454. if( bytesWritten != sizeof(ul) ) {
  2455. ERRPRT( "Unable to update SrvCachedOpenLimit\n" );
  2456. }
  2457. }
  2458. DECLARE_API( client )
  2459. {
  2460. ULONG_PTR epListAddress;
  2461. LIST_ENTRY *NextEndpoint;
  2462. ORDERED_LIST_HEAD SrvEndpointList;
  2463. WORK_QUEUE WorkQueue;
  2464. ULONG_PTR WorkQueueAddress = 0;
  2465. LONG SrvConnectionNoSessionsTimeout = 0;
  2466. ULONG_PTR dwAddress;
  2467. epListAddress = GetExpression ( "srv!SrvEndpointList" );
  2468. if( epListAddress == 0 ) {
  2469. ERRPRT( "Unable to get address of srv!SrvEndpointList\n" );
  2470. return;
  2471. }
  2472. if( !GetData( &SrvEndpointList,epListAddress,sizeof( SrvEndpointList ),"ORDERED_LIST_HEAD" )){
  2473. ERRPRT( "Unable to read data for srv!SrvEndpointList\n" );
  2474. return;
  2475. }
  2476. if( SrvEndpointList.Initialized == 0 ) {
  2477. ERRPRT( "srv!SrvEndpointList.Initialized == 0!\n" );
  2478. return;
  2479. }
  2480. if( (ULONG_PTR)SrvEndpointList.ListHead.Flink == epListAddress ) {
  2481. ERRPRT( "srv!SrvEndpointList list is empty\n" );
  2482. return;
  2483. }
  2484. if( (ULONG_PTR)SrvEndpointList.ListHead.Flink == 0 ) {
  2485. ERRPRT( "srv!SrvEndpointList.ListHead.Flink == 0: list is empty\n" );
  2486. return;
  2487. }
  2488. if( dwAddress = GetExpression( "srv!SrvConnectionNoSessionsTimeout" ) ) {
  2489. GetData( &SrvConnectionNoSessionsTimeout, dwAddress, sizeof(ULONG_PTR), "SrvConnectionNoSessionsTimeout" );
  2490. dprintf( "Session Idle Timeout: %d ticks\n", SrvConnectionNoSessionsTimeout );
  2491. }
  2492. NextEndpoint = SrvEndpointList.ListHead.Flink;
  2493. //
  2494. // Run the endpoint list, and run the connection list for each endpoint
  2495. //
  2496. do {
  2497. ENDPOINT endpoint;
  2498. CONNECTION connection;
  2499. PTABLE_ENTRY table;
  2500. USHORT i;
  2501. LONG idleTime;
  2502. dwAddress = (ULONG_PTR)CONTAINING_RECORD( NextEndpoint, ENDPOINT, GlobalEndpointListEntry );
  2503. if( CheckControlC() ) {
  2504. dprintf( "\n" );
  2505. break;
  2506. }
  2507. if( !GetData( &endpoint, dwAddress, sizeof( endpoint ), "ENDPOINT" ) ||
  2508. !CheckBlockHeader( &endpoint.BlockHeader, BlockTypeEndpoint, TRUE ) ) {
  2509. break;
  2510. }
  2511. //
  2512. // Now, run the connection table for this endpoint and print out the client names
  2513. // and connection structure address
  2514. //
  2515. if( endpoint.ConnectionTable.Table == NULL ) {
  2516. continue;
  2517. }
  2518. table = (PTABLE_ENTRY)LocalAlloc( LPTR,
  2519. endpoint.ConnectionTable.TableSize*sizeof(TABLE_ENTRY) );
  2520. if( table == NULL ) {
  2521. continue;
  2522. }
  2523. if( !GetData( table, (ULONG_PTR)endpoint.ConnectionTable.Table,
  2524. endpoint.ConnectionTable.TableSize*sizeof(TABLE_ENTRY), "TABLE" ) ) {
  2525. LocalFree( (HLOCAL)table );
  2526. continue;
  2527. }
  2528. for( i = 0; i < endpoint.ConnectionTable.TableSize; i++ ) {
  2529. if( table[i].Owner &&
  2530. GetData( &connection,(ULONG_PTR)table[i].Owner, sizeof( connection ),"CONNECTION") &&
  2531. connection.BlockHeader.ReferenceCount != 0 &&
  2532. connection.OemClientMachineName[0] &&
  2533. connection.OemClientMachineName[0] != ' ' ) {
  2534. if( args != NULL && *args != '\0' ) {
  2535. int j;
  2536. for( j = 0; args[j] ; j++ ) {
  2537. if( connection.OemClientMachineName[j] != args[j] )
  2538. break;
  2539. }
  2540. if( args[j] ) {
  2541. continue;
  2542. }
  2543. }
  2544. if( WorkQueueAddress != (ULONG_PTR)connection.CurrentWorkQueue ) {
  2545. if( GetData( &WorkQueue, (ULONG_PTR)connection.CurrentWorkQueue, sizeof( WorkQueue ), "WORK_QUEUE" ) ) {
  2546. WorkQueueAddress = (ULONG_PTR)connection.CurrentWorkQueue;
  2547. }
  2548. }
  2549. idleTime = WorkQueue.stats.SystemTime - connection.LastRequestTime;
  2550. dprintf( "%8X %-16s, Idle %d ticks\n", table[i].Owner,connection.OemClientMachineName,idleTime);
  2551. if( idleTime > SrvConnectionNoSessionsTimeout ) {
  2552. dprintf( "*** Above client is due for idle disconnect, if no open files\n" );
  2553. }
  2554. if( CheckControlC() ) {
  2555. dprintf( "\n" );
  2556. return;
  2557. }
  2558. }
  2559. }
  2560. LocalFree( (HLOCAL)table );
  2561. NextEndpoint = endpoint.GlobalEndpointListEntry.ListEntry.Flink;
  2562. } while( (ULONG_PTR)NextEndpoint != epListAddress );
  2563. }
  2564. DECLARE_API( errcodes )
  2565. {
  2566. ULONG_PTR dwAddress;
  2567. NTSTATUS status;
  2568. int count = 0;
  2569. dwAddress = GetExpression( "srv!SrvErrorLogIgnore" );
  2570. while( 1 ) {
  2571. if( !GetData( &status, dwAddress, sizeof( status ), "NTSTATUS" ) )
  2572. return;
  2573. if( status == 0 )
  2574. break;
  2575. dprintf( " %X", status );
  2576. dwAddress += sizeof( status );
  2577. if( (++count & 7) == 0 )
  2578. dprintf( "\n" );
  2579. }
  2580. dprintf( "\n" );
  2581. }
  2582. VOID
  2583. WinDbgExtensionDllInit(
  2584. PWINDBG_EXTENSION_APIS lpExtensionApis,
  2585. USHORT MajorVersion,
  2586. USHORT MinorVersion
  2587. )
  2588. {
  2589. ExtensionApis = *lpExtensionApis;
  2590. SavedMajorVersion = MajorVersion;
  2591. SavedMinorVersion = MinorVersion;
  2592. ChkTarget = SavedMajorVersion == 0x0c ? TRUE : FALSE;
  2593. }
  2594. DECLARE_API( version )
  2595. {
  2596. #if DBG
  2597. PCSTR kind = "Checked";
  2598. #else
  2599. PCSTR kind = "Free";
  2600. #endif
  2601. dprintf(
  2602. "%s SMB Extension dll for Build %d debugging %s kernel for Build %d\n",
  2603. kind,
  2604. VER_PRODUCTBUILD,
  2605. SavedMajorVersion == 0x0c ? "Checked" : "Free",
  2606. SavedMinorVersion
  2607. );
  2608. }
  2609. VOID
  2610. CheckVersion(
  2611. VOID
  2612. )
  2613. {
  2614. #if DBG
  2615. if ((SavedMajorVersion != 0x0c) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
  2616. dprintf("\r\n*** Extension DLL(%d Checked) does not match target system(%d %s)\r\n\r\n",
  2617. VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
  2618. }
  2619. #else
  2620. if ((SavedMajorVersion != 0x0f) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
  2621. dprintf("\r\n*** Extension DLL(%d Free) does not match target system(%d %s)\r\n\r\n",
  2622. VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
  2623. }
  2624. #endif
  2625. }
  2626. LPEXT_API_VERSION
  2627. ExtensionApiVersion(
  2628. VOID
  2629. )
  2630. {
  2631. return &ApiVersion;
  2632. }