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.

448 lines
9.2 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. FileLock.c
  5. Abstract:
  6. WinDbg Extension Api
  7. Author:
  8. Dan Lovinger 12-Apr-96
  9. Environment:
  10. User Mode.
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. //
  15. // Common node type codes
  16. //
  17. #define NTFS_NTC_SCB_DATA 0x705
  18. #define FAT_NTC_FCB 0x502
  19. //
  20. // dprintf is really expensive to iteratively call to do the indenting,
  21. // so we just build up some avaliable spaces to mangle as required
  22. //
  23. #define MIN(a,b) ((a) > (b) ? (b) : (a))
  24. #define MAXINDENT 128
  25. #define INDENTSTEP 2
  26. #define MakeSpace(I) Space[MIN((I)*INDENTSTEP, MAXINDENT)] = '\0'
  27. #define RestoreSpace(I) Space[MIN((I)*INDENTSTEP, MAXINDENT)] = ' '
  28. CHAR Space[MAXINDENT*INDENTSTEP + 1];
  29. __inline VOID CheckForBreak()
  30. /*++
  31. Purpose:
  32. Encapsulate control c checking code
  33. Arguments:
  34. None
  35. Return:
  36. None, raises if break is needed
  37. --*/
  38. {
  39. if ( CheckControlC() ) {
  40. RaiseException(0, EXCEPTION_NONCONTINUABLE, 0, NULL);
  41. }
  42. }
  43. //
  44. // Helper macros for printing 64bit quantities
  45. //
  46. #define SplitLI(LI) (LI).HighPart, (LI).LowPart
  47. VOID
  48. DumpFileLockInfo(
  49. ULONG64 pFileLockInfo,
  50. ULONG Indent
  51. )
  52. /*++
  53. Purpose:
  54. Dump the local internal FILE_LOCK_INFO structure
  55. Arguments:
  56. pFileLock - debugger address of FILE_LOCK_INFO to dump
  57. Return:
  58. None
  59. --*/
  60. {
  61. MakeSpace(Indent);
  62. InitTypeRead(pFileLockInfo, FILE_LOCK_INFO);
  63. dprintf("%sStart = %08I64x Length = %08I64x End = %08I64x (%s)\n"
  64. "%sKey = %08x FileOb = %08p ProcId = %08p\n",
  65. Space,
  66. ReadField(StartingByte),
  67. ReadField(Length),
  68. ReadField(EndingByte),
  69. (ReadField(ExclusiveLock) ? "Ex":"Sh"),
  70. Space,
  71. (ULONG) ReadField(Key),
  72. ReadField(FileObject),
  73. ReadField(ProcessId));
  74. RestoreSpace(Indent);
  75. }
  76. __inline
  77. ULONG64
  78. ExLockAddress(
  79. ULONG64 ExLockSplayLinks
  80. )
  81. {
  82. static ULONG Off=0, GotOff=0;
  83. if (!GotOff) {
  84. if (!GetFieldOffset("nt!_EX_LOCK", "Links", &Off))
  85. GotOff = TRUE;
  86. }
  87. return ExLockSplayLinks ?
  88. ( ExLockSplayLinks - Off ) : 0;
  89. }
  90. VOID
  91. DumpExclusiveNode(
  92. ULONG64 ExclusiveNodeSplayLinks,
  93. ULONG Indent
  94. )
  95. /*++
  96. Purpose:
  97. Dump an exclusive lock node
  98. Arguments:
  99. ExclusiveNodeSplayLinks - splay links of an exclusive node
  100. Indent - indent level to use
  101. Return:
  102. None
  103. --*/
  104. {
  105. ULONG64 Parent, pExLock;
  106. ULONG Off;
  107. pExLock = ExLockAddress(ExclusiveNodeSplayLinks);
  108. if (GetFieldValue(pExLock, "nt!_EX_LOCK", "Links.Parent", Parent)) {
  109. dprintf("Cannot read nt!_EX_LOCK at %p.\n", pExLock);
  110. return;
  111. }
  112. MakeSpace(Indent);
  113. InitTypeRead(pExLock, EX_LOCK);
  114. dprintf("%sLock @ %08x ("
  115. "P = %08x R = %08x L = %08x)\n",
  116. Space,
  117. pExLock,
  118. ExLockAddress(Parent),
  119. ExLockAddress(ReadField(Links.RightChild)),
  120. ExLockAddress(ReadField(Links.LeftChild)));
  121. RestoreSpace(Indent);
  122. GetFieldOffset("nt!_EX_LOCK", "LockInfo", &Off);
  123. DumpFileLockInfo(pExLock + Off, Indent);
  124. }
  125. __inline
  126. ULONG64
  127. LockTreeAddress(
  128. ULONG64 LockTreeSplayLinks
  129. )
  130. {
  131. static ULONG Off=0, GotOff=0;
  132. if (!GotOff) {
  133. if (GetFieldOffset("nt!_LOCKTREE_NODE", "Links", &Off))
  134. GotOff = TRUE;
  135. }
  136. return LockTreeSplayLinks ?
  137. ( LockTreeSplayLinks - Off ) : 0;
  138. }
  139. VOID
  140. DumpSharedNode(
  141. ULONG64 SharedNodeSplayLinks,
  142. ULONG Indent
  143. )
  144. /*++
  145. Purpose:
  146. Dump a shared lock node
  147. Arguments:
  148. SharedNodeSplayLinks - splay links of an exclusive node
  149. Indent - indent level to use
  150. Return:
  151. None
  152. --*/
  153. {
  154. ULONG64 pLockTreeNode;
  155. ULONG64 pShLock;
  156. ULONG64 pLink, Next;
  157. ULONG Off, LockInfoOff;
  158. pLockTreeNode = LockTreeAddress(SharedNodeSplayLinks);
  159. if (GetFieldValue(pLockTreeNode, "nt!_LOCKTREE_NODE", "Locks.Next", Next)) {
  160. dprintf("Cannot read nt!_LOCKTREE_NODE at %p\n", pLockTreeNode);
  161. return;
  162. }
  163. MakeSpace(Indent);
  164. InitTypeRead(pLockTreeNode, nt!_LOCKTREE_NODE);
  165. dprintf("%sLockTreeNode @ %08p ("
  166. "P = %08p R = %08p L = %08p)%s\n",
  167. Space,
  168. pLockTreeNode,
  169. LockTreeAddress(ReadField(Links.Parent)),
  170. LockTreeAddress(ReadField(Links.RightChild)),
  171. LockTreeAddress(ReadField(Links.LeftChild)),
  172. (ReadField(HoleyNode) ? " (Holey)" : ""));
  173. RestoreSpace(Indent);
  174. GetFieldOffset("nt!_SH_LOCK", "Link", &Off);
  175. GetFieldOffset("nt!_SH_LOCK", "LockInfo", &LockInfoOff);
  176. for (pLink = Next;
  177. pLink;
  178. pLink = Next) {
  179. CheckForBreak();
  180. pShLock = ( pLink - Off);
  181. if (GetFieldValue(pShLock, "nt!_SH_LOCK", "Link.Next", Next)) {
  182. dprintf("Cannot read nt!_SH_LOCK AT %p.\n", pShLock);
  183. return;
  184. }
  185. MakeSpace(Indent);
  186. dprintf("%sLock @ %08p\n", Space, pShLock);
  187. RestoreSpace(Indent);
  188. DumpFileLockInfo(pShLock + LockInfoOff, Indent);
  189. }
  190. }
  191. VOID
  192. DumpFileLock(
  193. ULONG64 pFileLock
  194. )
  195. /*++
  196. Purpose:
  197. Dump the fsrtl FILE_LOCK structure at debugee
  198. Arguments:
  199. pFileLock - debugee address of FILE_LOCK
  200. Return:
  201. None
  202. --*/
  203. {
  204. ULONG64 pFileLockInfo;
  205. ULONG64 pLockInfo;
  206. ULONG Count;
  207. ULONG64 LastReturnedLock, LockInformation, LowestLockOffset;
  208. ULONG64 SharedLockTree, ExclusiveLockTree;
  209. if (GetFieldValue(pFileLock, "FILE_LOCK", "LastReturnedLock", LastReturnedLock)) {
  210. dprintf("Cannot read FILE_LOCK at %p\n", pFileLock);
  211. return;
  212. }
  213. InitTypeRead(pFileLock, FILE_LOCK);
  214. dprintf("FileLock @ %08p\n"
  215. "FastIoIsQuestionable = %c\n"
  216. "CompletionRoutine = %08p\n"
  217. "UnlockRoutine = %08p\n"
  218. "LastReturnedLock = %08p\n",
  219. pFileLock,
  220. ReadField(FastIoIsQuestionable) ? 'T':'F',
  221. ReadField(CompleteLockIrpRoutine),
  222. ReadField(UnlockRoutine),
  223. LastReturnedLock);
  224. LockInformation = ReadField(LockInformation);
  225. if (LastReturnedLock != 0) {
  226. ULONG Off;
  227. //
  228. // We never reset the enumeration info, so it can be out of date ...
  229. //
  230. GetFieldOffset("FILE_LOCK", "LastReturnedLockInfo", &Off);
  231. dprintf("LastReturnedLockInfo:\n");
  232. DumpFileLockInfo(pFileLock + Off, 0);
  233. }
  234. if (LockInformation == 0) {
  235. dprintf("No Locks\n");
  236. return;
  237. } else {
  238. if (GetFieldValue(LockInformation, "nt!_LOCK_INFO", "LowestLockOffset", LowestLockOffset)) {
  239. dprintf("Canot read nt!_LOCK_INFO at %p\n", LockInformation);
  240. return;
  241. }
  242. }
  243. dprintf("LowestLockOffset = %08p\n\n", LowestLockOffset);
  244. GetFieldValue(LockInformation, "nt!_LOCK_INFO", "LockQueue.SharedLockTree", SharedLockTree);
  245. GetFieldValue(LockInformation, "nt!_LOCK_INFO", "LockQueue.ExclusiveLockTree", ExclusiveLockTree);
  246. Count = DumpSplayTree(SharedLockTree, DumpSharedNode);
  247. if (!Count) {
  248. dprintf("No Shared Locks\n");
  249. }
  250. dprintf("\n");
  251. Count = DumpSplayTree(ExclusiveLockTree, DumpExclusiveNode);
  252. if (!Count) {
  253. dprintf("No Exclusive Locks\n");
  254. }
  255. }
  256. DECLARE_API( filelock )
  257. /*++
  258. Routine Description:
  259. Dump file locks
  260. Arguments:
  261. arg - <Address>
  262. Return Value:
  263. None
  264. --*/
  265. {
  266. ULONG64 FileLock = 0;
  267. CSHORT NodeType = 0;
  268. CSHORT FileType = 0;
  269. ULONG64 FsContext = 0;
  270. ULONG Offset;
  271. RtlFillMemory(Space, sizeof(Space), ' ');
  272. if ((FileLock = GetExpression(args)) == 0) {
  273. //
  274. // No args
  275. //
  276. return E_INVALIDARG;
  277. }
  278. //
  279. // We raise out if the user whacketh control-c
  280. //
  281. __try {
  282. //
  283. // Test for fileobject
  284. //
  285. GetFieldValue( FileLock, "nt!_FILE_OBJECT", "Type", FileType );
  286. if (FileType == IO_TYPE_FILE) {
  287. //
  288. // its really a fileobject so grab the fscontext
  289. //
  290. if (!GetFieldValue( FileLock, "nt!_FILE_OBJECT", "FsContext", FsContext )) {
  291. GetFieldValue( FsContext, "nt!_FSRTL_COMMON_FCB_HEADER", "NodeTypeCode", NodeType );
  292. dprintf( "%x\n", NodeType );
  293. if (NodeType == NTFS_NTC_SCB_DATA) {
  294. GetFieldValue( FsContext, "ntfs!_SCB", "ScbType.Data.FileLock", FileLock );
  295. } else if (NodeType == FAT_NTC_FCB) {
  296. GetFieldOffset( "fastfat!_FCB", "Specific", &Offset );
  297. dprintf( "Offset: 0x%x\n", Offset );
  298. FileLock = FsContext + Offset;
  299. } else {
  300. dprintf( "Unknown fscontext - you'll have to find the filelock within the fileobject manually\n" );
  301. return S_OK;
  302. }
  303. }
  304. if (FileLock == 0) {
  305. dprintf( "There is no filelock in this fileobject\n" );
  306. return S_OK;
  307. }
  308. }
  309. DumpFileLock(FileLock);
  310. } __except (EXCEPTION_EXECUTE_HANDLER) {
  311. NOTHING;
  312. }
  313. return S_OK;
  314. }