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.

1093 lines
32 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. irp.c
  5. Abstract:
  6. WinDbg Extension Api
  7. Environment:
  8. User Mode.
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. //#include "irpverif.h"
  13. #pragma hdrstop
  14. typedef
  15. BOOLEAN
  16. (WINAPI *IRP_FILTER_ROUTINE)(
  17. ULONG64 Irp,
  18. PVOID FilterContext
  19. );
  20. typedef struct _IRP_FILTER {
  21. IRP_FILTER_ROUTINE FilterRoutine;
  22. PVOID FilterContext;
  23. } IRP_FILTER, *PIRP_FILTER;
  24. typedef struct _SEARCH_CONTEXT {
  25. ULONG FirstTime;
  26. IRP_FILTER Filter;
  27. } SEARCH_CONTEXT, *PSEARCH_CONTEXT;
  28. #define TAG 0
  29. #define NONPAGED_ALLOC 1
  30. #define NONPAGED_FREE 2
  31. #define PAGED_ALLOC 3
  32. #define PAGED_FREE 4
  33. #define NONPAGED_USED 5
  34. #define PAGED_USED 6
  35. VOID
  36. DumpIrp(
  37. ULONG64 IrpToDump,
  38. ULONG DumpLevel
  39. );
  40. BOOLEAN
  41. IrpFilterUserEvent(
  42. ULONG64 Irp,
  43. PVOID FilterContext
  44. );
  45. BOOLEAN
  46. IrpFilterDevice(
  47. ULONG64 Irp,
  48. PVOID FilterContext
  49. );
  50. BOOLEAN
  51. IrpFilterFileObject(
  52. ULONG64 Irp,
  53. PVOID FilterContext
  54. );
  55. BOOLEAN
  56. IrpFilterThread(
  57. ULONG64 Irp,
  58. PVOID FilterContext
  59. );
  60. BOOLEAN
  61. IrpFilterMdlProcess(
  62. ULONG64 Irp,
  63. PVOID FilterContext
  64. );
  65. BOOLEAN
  66. IrpFilterArg(
  67. ULONG64 Irp,
  68. PVOID FilterContext
  69. );
  70. DECLARE_API( irp )
  71. /*++
  72. Routine Description:
  73. Dumps the specified Irp
  74. Arguments:
  75. args - Address
  76. Return Value:
  77. None
  78. --*/
  79. {
  80. ULONG64 irpToDump;
  81. ULONG dumpLevel = 0 ;
  82. char irpExprBuf[256] ;
  83. char dumpLevelBuf[256] ;
  84. if (!*args) {
  85. irpToDump = EXPRLastDump;
  86. } else {
  87. //
  88. // !Irp IrpAddress DumpLevel
  89. // where IrpAddress can be an expression
  90. // and DumpLevel is a decimal level of any non-decimal string for 1
  91. irpExprBuf[0] = '\0' ;
  92. dumpLevelBuf[0] = '\0' ;
  93. if (!sscanf(args, "%255s %255s", irpExprBuf, dumpLevelBuf)) {
  94. irpExprBuf[0] = '\0' ;
  95. dumpLevelBuf[0] = '\0' ;
  96. }
  97. if (irpExprBuf) {
  98. if (IsHexNumber(irpExprBuf)) {
  99. irpToDump = GetExpression( irpExprBuf ) ;
  100. } else {
  101. irpToDump = GetExpression( irpExprBuf ) ;
  102. if (irpToDump==0) {
  103. dprintf("An error occured trying to evaluate the expression\n") ;
  104. return E_INVALIDARG ;
  105. }
  106. }
  107. if (IsDecNumber(dumpLevelBuf)) {
  108. if (!sscanf(dumpLevelBuf, "%d", &dumpLevel) ) {
  109. dumpLevel = 0;
  110. }
  111. } else if (dumpLevelBuf[0]) {
  112. dumpLevel = 1 ;
  113. } else {
  114. dumpLevel = 0 ;
  115. }
  116. }
  117. }
  118. if (irpToDump == 0) {
  119. dprintf("Free build - use !irpfind to scan memory for any active IRPs\n") ;
  120. } else {
  121. DumpIrp(irpToDump, (ULONG) dumpLevel);
  122. }
  123. return S_OK;
  124. }
  125. DECLARE_API( irpzone )
  126. /*++
  127. Routine Description:
  128. Dumps both the small irp zone and the large irp zone. Only irps that
  129. are currently allocated are dumped. "args" controls the type of dump.
  130. If "args" is present then the Irp is sent to the DumpIrp routine to be
  131. disected. Otherwise, only the irp, its thread and the driver holding the
  132. irp (i.e. the driver of the last stack) is printed.
  133. Arguments:
  134. args - a string pointer. If anything is in the string it indicates full
  135. information (i.e. call DumpIrp).
  136. Return Value:
  137. None.
  138. --*/
  139. {
  140. ULONG listAddress;
  141. BOOLEAN fullOutput = FALSE;
  142. dprintf("irpzone is no longer supported. Use irpfind to search " \
  143. "nonpaged pool for active Irps\n");
  144. return S_OK;
  145. }
  146. VOID
  147. DumpIrp(
  148. ULONG64 IrpToDump,
  149. ULONG DumpLevel
  150. )
  151. /*++
  152. Routine Description:
  153. This routine dumps an Irp. It does not check to see that the address
  154. supplied actually locates an Irp. This is done to allow for dumping
  155. Irps post mortem, or after they have been freed or completed.
  156. Arguments:
  157. IrpToDump - the address of the irp.
  158. DumpLevel - 0 Summary
  159. 1 Extended information
  160. 2 Debug tracking info iff available
  161. Return Value:
  162. None
  163. --*/
  164. {
  165. PCHAR buffer;
  166. ULONG64 irpStackAddress;
  167. ULONG64 result64=0;
  168. ULONG result;
  169. // IRP irp;
  170. CCHAR irpStackIndex;
  171. LARGE_INTEGER runTime ;
  172. #if DBG
  173. // PIOV_REQUEST_PACKET irpTrackingData ;
  174. #endif
  175. BOOLEAN delayed ;
  176. ULONG Type=0, StackCount=0, CurrentLocation=0, Flags=0, PendingReturned=0;
  177. ULONG Io_Status=0, Cancel=0, CancelIrql=0, ApcEnvironment=0, Overlay_Alloc_High=0;
  178. ULONG Overlay_Alloc_Low=0, RequestorMode=0, IrpSize;
  179. ULONG64 Tail_Overlay_CurrStack=0, MdlAddress=0, Associated_MasterIrp=0;
  180. ULONG64 ThreadListEntry_Flink=0, ThreadListEntry_Blink=0, Io_Information=0;
  181. ULONG64 CancelRoutine=0, UserIosb=0, UserEvent=0, UserBuffer=0, Overlay_Async_UserApcRoutine=0;
  182. ULONG64 Overlay_Async_UserApcContext=0, Tail_Overlay_Thread=0, Tail_Overlay_AuxBuffer=0;
  183. ULONG64 Tail_Overlay_List_Flink=0, Tail_Overlay_List_Blink=0, Tail_Overlay_OrigFile=0;
  184. ULONG64 Tail_CompletionKey=0;
  185. ULONG Tail_Overlay_DeviceQueueEntry;
  186. BYTE Tail_Apc[100]={0};
  187. UCHAR IrpType[]= "nt!_IRP";
  188. if ( (GetFieldValue(IrpToDump, IrpType, "Type", Type)) ) {
  189. dprintf("%08p: Could not read Irp\n", IrpToDump);
  190. return;
  191. }
  192. GetFieldValue(IrpToDump, IrpType, "StackCount", StackCount);
  193. GetFieldValue(IrpToDump, IrpType, "CurrentLocation", CurrentLocation);
  194. GetFieldValue(IrpToDump, IrpType, "Tail.Overlay.CurrentStackLocation", Tail_Overlay_CurrStack);
  195. GetFieldValue(IrpToDump, IrpType, "MdlAddress", MdlAddress);
  196. GetFieldValue(IrpToDump, IrpType, "AssociatedIrp.MasterIrp", Associated_MasterIrp);
  197. GetFieldValue(IrpToDump, IrpType, "Flags", Flags);
  198. GetFieldValue(IrpToDump, IrpType, "RequestorMode", RequestorMode);
  199. GetFieldValue(IrpToDump, IrpType, "PendingReturned", PendingReturned);
  200. GetFieldValue(IrpToDump, IrpType, "ThreadListEntry.Flink", ThreadListEntry_Flink);
  201. GetFieldValue(IrpToDump, IrpType, "ThreadListEntry.Blink", ThreadListEntry_Blink);
  202. GetFieldValue(IrpToDump, IrpType, "IoStatus.Status", Io_Status);
  203. GetFieldValue(IrpToDump, IrpType, "IoStatus.Information", Io_Information);
  204. GetFieldValue(IrpToDump, IrpType, "Cancel", Cancel);
  205. GetFieldValue(IrpToDump, IrpType, "CancelIrql", CancelIrql);
  206. GetFieldValue(IrpToDump, IrpType, "CancelRoutine", CancelRoutine);
  207. GetFieldValue(IrpToDump, IrpType, "ApcEnvironment", ApcEnvironment);
  208. GetFieldValue(IrpToDump, IrpType, "UserIosb", UserIosb);
  209. GetFieldValue(IrpToDump, IrpType, "UserEvent", UserEvent);
  210. GetFieldValue(IrpToDump, IrpType, "UserBuffer", UserBuffer);
  211. GetFieldValue(IrpToDump, IrpType, "Overlay.AsynchronousParameters.UserApcRoutine", Overlay_Async_UserApcRoutine);
  212. GetFieldValue(IrpToDump, IrpType, "Overlay.AsynchronousParameters.UserApcContext", Overlay_Async_UserApcContext);
  213. GetFieldValue(IrpToDump, IrpType, "Overlay.AllocationSize.High", Overlay_Alloc_High);
  214. GetFieldValue(IrpToDump, IrpType, "Overlay.AllocationSize.Low", Overlay_Alloc_Low);
  215. GetFieldOffset(IrpType, "Tail.Overlay.DeviceQueueEntry", &Tail_Overlay_DeviceQueueEntry);
  216. GetFieldValue(IrpToDump, IrpType, "Tail.Overlay.Thread", Tail_Overlay_Thread);
  217. GetFieldValue(IrpToDump, IrpType, "Tail.Overlay.AuxiliaryBuffer", Tail_Overlay_AuxBuffer);
  218. GetFieldValue(IrpToDump, IrpType, "Tail.Overlay.ListEntry.Flink", Tail_Overlay_List_Flink);
  219. GetFieldValue(IrpToDump, IrpType, "Tail.Overlay.ListEntry.Blink", Tail_Overlay_List_Blink);
  220. GetFieldValue(IrpToDump, IrpType, "Tail.Overlay.OriginalFileObject", Tail_Overlay_OrigFile);
  221. GetFieldValue(IrpToDump, IrpType, "Tail.Apc", Tail_Apc);
  222. GetFieldValue(IrpToDump, IrpType, "Tail.CompletionKey", Tail_CompletionKey);
  223. IrpSize = GetTypeSize("nt!_IRP");
  224. if (Type != IO_TYPE_IRP) {
  225. dprintf("IRP signature does not match, probably not an IRP\n");
  226. return;
  227. }
  228. dprintf("Irp is active with %d stacks %d is current (= %#08p)\n",
  229. StackCount,
  230. CurrentLocation,
  231. Tail_Overlay_CurrStack);
  232. if ((MdlAddress != 0) && (Type == IO_TYPE_IRP)) {
  233. dprintf(" Mdl = %08p ", MdlAddress);
  234. } else {
  235. dprintf(" No Mdl ");
  236. }
  237. if (Associated_MasterIrp != 0) {
  238. dprintf("%s = %08p ",
  239. (Flags & IRP_ASSOCIATED_IRP) ? "Associated Irp" :
  240. (Flags & IRP_DEALLOCATE_BUFFER) ? "System buffer" :
  241. "Irp count",
  242. Associated_MasterIrp);
  243. }
  244. dprintf("Thread %08p: ", Tail_Overlay_Thread);
  245. if (StackCount > 30) {
  246. dprintf("Too many Irp stacks to be believed (>30)!!\n");
  247. return;
  248. } else {
  249. if (CurrentLocation > StackCount) {
  250. dprintf("Irp is completed. ");
  251. } else {
  252. dprintf("Irp stack trace. ");
  253. }
  254. }
  255. if (PendingReturned) {
  256. dprintf("Pending has been returned\n");
  257. } else {
  258. dprintf("\n");
  259. }
  260. if (DumpLevel>0) {
  261. dprintf("Flags = %08lx\n", Flags);
  262. dprintf("ThreadListEntry.Flink = %08p\n", ThreadListEntry_Flink);
  263. dprintf("ThreadListEntry.Blink = %08p\n", ThreadListEntry_Blink);
  264. dprintf("IoStatus.Status = %08lx\n", Io_Status);
  265. dprintf("IoStatus.Information = %08p\n", Io_Information);
  266. dprintf("RequestorMode = %08lx\n", RequestorMode);
  267. dprintf("Cancel = %02lx\n", Cancel);
  268. dprintf("CancelIrql = %lx\n", CancelIrql);
  269. dprintf("ApcEnvironment = %02lx\n", ApcEnvironment);
  270. dprintf("UserIosb = %08p\n", UserIosb);
  271. dprintf("UserEvent = %08p\n", UserEvent);
  272. dprintf("Overlay.AsynchronousParameters.UserApcRoutine = %08p\n", Overlay_Async_UserApcRoutine);
  273. dprintf("Overlay.AsynchronousParameters.UserApcContext = %08p\n", Overlay_Async_UserApcContext);
  274. dprintf(
  275. "Overlay.AllocationSize = %08lx - %08lx\n",
  276. Overlay_Alloc_High,
  277. Overlay_Alloc_Low);
  278. dprintf("CancelRoutine = %08p\n", CancelRoutine);
  279. dprintf("UserBuffer = %08p\n", UserBuffer);
  280. dprintf("&Tail.Overlay.DeviceQueueEntry = %08p\n", IrpToDump + Tail_Overlay_DeviceQueueEntry);
  281. dprintf("Tail.Overlay.Thread = %08p\n", Tail_Overlay_Thread);
  282. dprintf("Tail.Overlay.AuxiliaryBuffer = %08p\n", Tail_Overlay_AuxBuffer);
  283. dprintf("Tail.Overlay.ListEntry.Flink = %08p\n", Tail_Overlay_List_Flink);
  284. dprintf("Tail.Overlay.ListEntry.Blink = %08p\n", Tail_Overlay_List_Blink);
  285. dprintf("Tail.Overlay.CurrentStackLocation = %08p\n", Tail_Overlay_CurrStack);
  286. dprintf("Tail.Overlay.OriginalFileObject = %08p\n", Tail_Overlay_OrigFile);
  287. dprintf("Tail.Apc = %08lx\n", *((PULONG) Tail_Apc));
  288. dprintf("Tail.CompletionKey = %08p\n", Tail_CompletionKey);
  289. }
  290. irpStackAddress = (ULONG64) IrpToDump + GetTypeSize("nt!_IRP");
  291. buffer = LocalAlloc(LPTR, 256);
  292. if (buffer == NULL) {
  293. dprintf("Can't allocate 256 bytes\n");
  294. return;
  295. }
  296. dprintf(" cmd flg cl Device File Completion-Context\n");
  297. for (irpStackIndex = 1; (ULONG) irpStackIndex <= StackCount; irpStackIndex++) {
  298. ULONG MajorFunction=0, MinorFunction=0, Flags2=0, Control=0, irpStackSize;
  299. ULONG64 DeviceObject=0, FileObject=0, CompletionRoutine=0, Context=0;
  300. ULONG64 Others_Argument1=0, Others_Argument2=0, Others_Argument3=0, Others_Argument4=0;
  301. UCHAR IOStack[] = "nt!_IO_STACK_LOCATION";
  302. if ( GetFieldValue(irpStackAddress, IOStack, "MajorFunction", MajorFunction)) {
  303. dprintf("%p: Could not read IrpStack\n", irpStackAddress);
  304. goto exit;
  305. }
  306. irpStackSize = GetTypeSize(IOStack);
  307. GetFieldValue(irpStackAddress, IOStack, "MinorFunction", MinorFunction);
  308. GetFieldValue(irpStackAddress, IOStack, "Flags", Flags2);
  309. GetFieldValue(irpStackAddress, IOStack, "DeviceObject", DeviceObject);
  310. GetFieldValue(irpStackAddress, IOStack, "FileObject", FileObject);
  311. GetFieldValue(irpStackAddress, IOStack, "CompletionRoutine", CompletionRoutine);
  312. GetFieldValue(irpStackAddress, IOStack, "Context", Context);
  313. GetFieldValue(irpStackAddress, IOStack, "Control", Control);
  314. GetFieldValue(irpStackAddress, IOStack, "Parameters.Others.Argument1",Others_Argument1);
  315. GetFieldValue(irpStackAddress, IOStack, "Parameters.Others.Argument2",Others_Argument2);
  316. GetFieldValue(irpStackAddress, IOStack, "Parameters.Others.Argument3",Others_Argument3);
  317. GetFieldValue(irpStackAddress, IOStack, "Parameters.Others.Argument4",Others_Argument4);
  318. dprintf("%c[%3x,%2x] %2x %2x %08p %08p %08p-%08p %s %s %s %s\n",
  319. (ULONG) irpStackIndex == CurrentLocation ? '>' : ' ',
  320. MajorFunction,
  321. MinorFunction,
  322. Flags2,
  323. Control,
  324. DeviceObject,
  325. FileObject,
  326. CompletionRoutine,
  327. Context,
  328. (Control & SL_INVOKE_ON_SUCCESS) ? "Success" : "",
  329. (Control & SL_INVOKE_ON_ERROR) ? "Error" : "",
  330. (Control & SL_INVOKE_ON_CANCEL) ? "Cancel" : "",
  331. (Control & SL_PENDING_RETURNED) ? "pending" : "");
  332. if (DeviceObject != 0) {
  333. dprintf("\t ");
  334. DumpDevice(DeviceObject, 0, FALSE);
  335. }
  336. if (CompletionRoutine != 0) {
  337. GetSymbol(CompletionRoutine, buffer, &result64);
  338. dprintf("\t%s\n", buffer);
  339. } else {
  340. dprintf("\n");
  341. }
  342. dprintf("\t\t\tArgs: %08p %08p %08p %08p\n",
  343. Others_Argument1,
  344. Others_Argument2,
  345. Others_Argument3,
  346. Others_Argument4);
  347. irpStackAddress += irpStackSize;
  348. if (CheckControlC()) {
  349. goto exit;
  350. }
  351. }
  352. if (DumpLevel>=2) {
  353. dprintf("Extra information not available.\n") ;
  354. }
  355. exit:
  356. LocalFree(buffer);
  357. }
  358. //+---------------------------------------------------------------------------
  359. //
  360. // Function: CheckForIrp
  361. //
  362. // Synopsis: Matches pool chunk against an irp
  363. //
  364. // Arguments: [Tag] --
  365. // [Filter] --
  366. // [Flags] -- 0 nonpaged pool 1 paged pool 2 special pool 4 dump irp
  367. // [PoolTrackTable] --
  368. // [PoolHeader] --
  369. // [BlockSize] --
  370. // [Data] --
  371. //
  372. // Returns:
  373. //
  374. // History: 7-28-1999 benl Created
  375. //
  376. // Notes:
  377. //
  378. //----------------------------------------------------------------------------
  379. BOOLEAN WINAPI CheckForIrp(
  380. PCHAR Tag,
  381. PCHAR Filter,
  382. ULONG Flags,
  383. ULONG64 PoolHeader,
  384. ULONG64 BlockSize,
  385. ULONG64 Data,
  386. PVOID Context
  387. )
  388. {
  389. ULONG64 Irp = Data;
  390. ULONG Result;
  391. ULONG64 irpSp;
  392. // MDL Mdl;
  393. PSEARCH_CONTEXT SearchContext = (PSEARCH_CONTEXT)Context;
  394. ULONG PoolType, SizeOfIRP;
  395. // dprintf("Call Hdr %p, Data %p \n", PoolHeader, Data);
  396. if (PoolHeader) {
  397. if (GetFieldValue(PoolHeader, "nt!_POOL_HEADER", "PoolType", PoolType)) {
  398. dprintf("Unable to read nt!_POOL_HEADER type.\n");
  399. }
  400. }
  401. if (((PoolHeader == 0) ||
  402. (Flags & 0x2) ||
  403. (PoolType != 0)) &&
  404. (CheckSingleFilter (Tag, Filter))) {
  405. ULONG Type=0, CurrentLocation, StackCount, MajorFunction, MinorFunction;
  406. ULONG64 Thread, DeviceObject, MdlAddress;
  407. if (!GetFieldValue(Irp, "nt!_IRP", "Type", Type)) {
  408. if (Type == IO_TYPE_IRP) {
  409. SizeOfIRP = GetTypeSize("nt!_IRP");
  410. if (Flags & 0x8) {
  411. if (SearchContext->FirstTime) {
  412. dprintf(" Irp [ Thread ] irpStack: (Mj,Mn) DevObj [Driver]\n");
  413. SearchContext->FirstTime = FALSE;
  414. }
  415. dprintf("%08p: ", Data);
  416. DumpIrp(Data, 0);
  417. dprintf("\n");
  418. } else {
  419. if ((SearchContext->Filter.FilterRoutine == NULL) ||
  420. (SearchContext->Filter.FilterRoutine(Irp, SearchContext->Filter.FilterContext))) {
  421. if (SearchContext->FirstTime) {
  422. dprintf(" Irp [ Thread ] irpStack: (Mj,Mn) DevObj [Driver]\n");
  423. SearchContext->FirstTime = FALSE;
  424. }
  425. GetFieldValue(Irp, "nt!_IRP", "CurrentLocation", CurrentLocation);
  426. GetFieldValue(Irp, "nt!_IRP", "StackCount", StackCount);
  427. GetFieldValue(Irp, "nt!_IRP", "MdlAddress", MdlAddress);
  428. GetFieldValue(Irp, "nt!_IRP", "Tail.Overlay.Thread",
  429. Thread);
  430. irpSp = Irp + SizeOfIRP +
  431. (CurrentLocation - 1)*GetTypeSize("nt!_IO_STACK_LOCATION");
  432. dprintf("%08p [%08p] ", Data, Thread);
  433. if (CurrentLocation > StackCount) {
  434. dprintf("Irp is complete (CurrentLocation "
  435. "%d > StackCount %d)",
  436. CurrentLocation,
  437. StackCount);
  438. } else {
  439. GetFieldValue(irpSp, "nt!_IO_STACK_LOCATION", "MajorFunction", MajorFunction);
  440. GetFieldValue(irpSp, "nt!_IO_STACK_LOCATION", "MinorFunction", MinorFunction);
  441. GetFieldValue(irpSp, "nt!_IO_STACK_LOCATION", "DeviceObject", DeviceObject);
  442. dprintf("irpStack: (%2x,%2x)",
  443. MajorFunction,
  444. MinorFunction);
  445. dprintf(" %08p [", DeviceObject);
  446. DumpDevice(DeviceObject, 0, FALSE);
  447. dprintf("]");
  448. }
  449. if (MdlAddress) {
  450. ULONG64 Process;
  451. if (!GetFieldValue(MdlAddress,
  452. "nt!_MDL",
  453. "Process",
  454. Process)) {
  455. dprintf( " 0x%p", Process );
  456. }
  457. }
  458. dprintf("\n");
  459. }
  460. }
  461. } else {
  462. // dprintf("%08lx (size %04lx) uninitialized or overwritten IRP\n",
  463. // irpAddress,
  464. // PoolBlock.Header.BlockSize << POOL_BLOCK_SHIFT);
  465. }
  466. } else {
  467. dprintf("Possible IRP @ %p - unable to read addr/type\n", Data );
  468. }
  469. return TRUE;
  470. } else {
  471. #ifdef SHOW_PROGRESS
  472. dprintf("%c", turnTable[turn]);
  473. turn = (turn + 1) % 4;
  474. #endif
  475. }
  476. return FALSE;
  477. } // CheckForIrp
  478. DECLARE_API(irpfind)
  479. /*++
  480. Routine Description:
  481. finds Irps in non-paged pool
  482. Arguments:
  483. args -
  484. Return Value:
  485. None
  486. --*/
  487. {
  488. ULONG Flags = 0;
  489. ULONG64 RestartAddr = 0;
  490. ULONG TagName;
  491. UCHAR Field[20];
  492. ULONG64 Match=0;
  493. SEARCH_CONTEXT Context;
  494. BOOL Verbose = FALSE;
  495. Context.FirstTime = TRUE;
  496. Context.Filter.FilterRoutine = NULL;
  497. Field[0] = '\0';
  498. if (args) {
  499. PCHAR pc;
  500. ULONG64 tmp;
  501. while (*args)
  502. {
  503. if (*args == ' ' || *args == '\t')
  504. {
  505. ++args;
  506. continue;
  507. }
  508. if (*args=='/' || *args == '-')
  509. {
  510. ++args;
  511. switch (*args)
  512. {
  513. default:
  514. dprintf("Usage: !irpfind [-v] <poolflags> [Field] [MatchType]\n");
  515. return S_OK;
  516. case 'v':
  517. Verbose = TRUE;
  518. break;
  519. }
  520. } else
  521. {
  522. break;
  523. }
  524. ++args;
  525. }
  526. if (GetExpressionEx(args, &tmp, &args)) {
  527. Flags = (ULONG) tmp & 7;
  528. if (GetExpressionEx(args, &RestartAddr, &args)) {
  529. if (!sscanf(args, "%19s %x", Field, &Match)) {
  530. Match = 0;
  531. }
  532. }
  533. }
  534. }
  535. if (Verbose)
  536. {
  537. Flags |= 8;
  538. }
  539. //
  540. // Sign extend the address if necc.
  541. //
  542. if (RestartAddr != 0) {
  543. if (RestartAddr >= 0x80000000 && RestartAddr <= 0xFFFFFFFF) {
  544. RestartAddr += 0xFFFFFFFF00000000;
  545. }
  546. }
  547. if ((_stricmp(Field, "userevent") == 0) &&
  548. (Match != 0)) {
  549. Context.Filter.FilterRoutine = IrpFilterUserEvent;
  550. Context.Filter.FilterContext = (PVOID)&Match;
  551. dprintf("Looking for IRP with UserEvent == %08p\n",Match);
  552. } else if ((_stricmp(Field, "device") == 0) &&
  553. (Match != 0)) {
  554. Context.Filter.FilterRoutine = IrpFilterDevice;
  555. Context.Filter.FilterContext = (PVOID)&Match;
  556. dprintf("Looking for IRPs with device object == %08p\n",Match);
  557. } else if ((_stricmp(Field, "fileobject") == 0) &&
  558. (Match != 0)) {
  559. Context.Filter.FilterRoutine = IrpFilterFileObject;
  560. Context.Filter.FilterContext = (PVOID)&Match;
  561. dprintf("Looking for IRPs with file object == %08p\n",Match);
  562. } else if ((_stricmp(Field, "mdlprocess") == 0) &&
  563. (Match != 0)) {
  564. Context.Filter.FilterRoutine = IrpFilterMdlProcess;
  565. Context.Filter.FilterContext = (PVOID)&Match;
  566. dprintf("Looking for IRPs with mdl process == %08p\n",Match);
  567. } else if ((_stricmp(Field, "thread") == 0) &&
  568. (Match != 0)) {
  569. Context.Filter.FilterRoutine = IrpFilterThread;
  570. Context.Filter.FilterContext = (PVOID)&Match;
  571. dprintf("Looking for IRPs with thread == %08p\n",Match);
  572. } else if ((_stricmp(Field, "arg") == 0) &&
  573. (Match != 0)) {
  574. Context.Filter.FilterRoutine = IrpFilterArg;
  575. Context.Filter.FilterContext = (PVOID)&Match;
  576. dprintf("Looking for IRPs with arg == %08p\n",Match);
  577. }
  578. TagName = '?prI';
  579. SearchPool( TagName, Flags, RestartAddr, &CheckForIrp, &Context );
  580. return S_OK;
  581. }
  582. BOOLEAN
  583. IrpFilterUserEvent(
  584. IN ULONG64 Irp,
  585. IN PVOID FilterContext
  586. )
  587. /*++
  588. Routine Description:
  589. Checks to see if the userevent field of an IRP matches the supplied
  590. parameter
  591. Arguments:
  592. Irp - Supplies the irp to filter
  593. FilterContext - supplies the user event
  594. Return Value:
  595. TRUE if the specified irp has userevent == FilterContext
  596. FALSE otherwise
  597. --*/
  598. {
  599. ULONG64 pEvent = *((PULONG64) FilterContext);
  600. ULONG64 UserEvent;
  601. if (GetFieldValue(Irp, "nt!_IRP", "UserEvent", UserEvent)) {
  602. return FALSE;
  603. }
  604. if (UserEvent == pEvent) {
  605. return(TRUE);
  606. } else {
  607. return(FALSE);
  608. }
  609. }
  610. BOOLEAN
  611. IrpFilterDevice(
  612. IN ULONG64 Irp,
  613. IN PVOID FilterContext
  614. )
  615. /*++
  616. Routine Description:
  617. Checks to see if the specified IRP matches the supplied
  618. device object
  619. Arguments:
  620. Irp - Supplies the irp to filter
  621. FilterContext - supplies the device object
  622. Return Value:
  623. TRUE if the specified irp has a device == FilterContext
  624. FALSE otherwise
  625. --*/
  626. {
  627. ULONG64 IrpStack = (Irp+GetTypeSize("nt!_IRP"));
  628. ULONG StackCount, Stksize;
  629. ULONG64 DeviceObject;
  630. ULONG i;
  631. if (GetFieldValue(Irp, "nt!_IRP", "StackCount", StackCount)) {
  632. return FALSE;
  633. }
  634. if (StackCount > 30) {
  635. return(FALSE);
  636. }
  637. Stksize = GetTypeSize("nt!_IO_STACK_LOCATION");
  638. for (i=0; i<StackCount; i++) {
  639. if (!GetFieldValue(Irp + i*Stksize,
  640. "nt!_IO_STACK_LOCATION",
  641. "DeviceObject",
  642. DeviceObject)) {
  643. if (DeviceObject == *((PULONG64) FilterContext)) {
  644. return(TRUE);
  645. }
  646. }
  647. }
  648. return(FALSE);
  649. }
  650. BOOLEAN
  651. IrpFilterFileObject(
  652. IN ULONG64 Irp,
  653. IN PVOID FilterContext
  654. )
  655. /*++
  656. Routine Description:
  657. Checks to see if the Tail.Overlay.OriginalFileObject field of an IRP matches the
  658. supplied parameter
  659. Arguments:
  660. Irp - Supplies the irp to filter
  661. FilterContext - supplies the file object
  662. Return Value:
  663. TRUE if the specified irp has userevent == FilterContext
  664. FALSE otherwise
  665. --*/
  666. {
  667. ULONG64 pFile = *((PULONG64) FilterContext);
  668. ULONG64 OriginalFileObject;
  669. if (GetFieldValue(Irp, "nt!_IRP",
  670. "Tail.Overlay.OriginalFileObject",
  671. OriginalFileObject)) {
  672. return FALSE;
  673. }
  674. if (OriginalFileObject == pFile) {
  675. return(TRUE);
  676. } else {
  677. return(FALSE);
  678. }
  679. }
  680. BOOLEAN
  681. IrpFilterThread(
  682. IN ULONG64 Irp,
  683. IN PVOID FilterContext
  684. )
  685. /*++
  686. Routine Description:
  687. Checks to see if the Tail.Overlay.OriginalFileObject field of an IRP matches the
  688. supplied parameter
  689. Arguments:
  690. Irp - Supplies the irp to filter
  691. FilterContext - supplies the file object
  692. Return Value:
  693. TRUE if the specified irp has userevent == FilterContext
  694. FALSE otherwise
  695. --*/
  696. {
  697. ULONG64 pThread = *((PULONG64) FilterContext);
  698. ULONG64 Thread;
  699. if (GetFieldValue(Irp, "nt!_IRP",
  700. "Tail.Overlay.Thread",
  701. Thread)) {
  702. return FALSE;
  703. }
  704. if (Thread == pThread) {
  705. return(TRUE);
  706. } else {
  707. return(FALSE);
  708. }
  709. }
  710. BOOLEAN
  711. IrpFilterMdlProcess(
  712. IN ULONG64 Irp,
  713. IN PVOID FilterContext
  714. )
  715. /*++
  716. Routine Description:
  717. Checks to see if the Tail.Overlay.OriginalFileObject field of an IRP matches the
  718. supplied parameter
  719. Arguments:
  720. Irp - Supplies the irp to filter
  721. FilterContext - supplies the file object
  722. Return Value:
  723. TRUE if the specified irp has userevent == FilterContext
  724. FALSE otherwise
  725. --*/
  726. {
  727. ULONG64 pProcess = *((PULONG64) FilterContext);
  728. ULONG64 Process, MdlAddress;
  729. if (GetFieldValue(Irp, "nt!_IRP",
  730. "MdlAddress",
  731. MdlAddress)) {
  732. return FALSE;
  733. }
  734. if (MdlAddress == 0) {
  735. return(FALSE);
  736. }
  737. if (GetFieldValue(MdlAddress, "nt!_MDL", "Process", Process)) {
  738. return FALSE;
  739. }
  740. if (Process == pProcess) {
  741. return(TRUE);
  742. } else {
  743. return(FALSE);
  744. }
  745. }
  746. BOOLEAN
  747. IrpFilterArg(
  748. IN ULONG64 Irp,
  749. IN PVOID FilterContext
  750. )
  751. /*++
  752. Routine Description:
  753. Checks to see if the specified IRP matches the supplied
  754. argument
  755. Arguments:
  756. Irp - Supplies the irp to filter
  757. FilterContext - supplies the argument to match
  758. Return Value:
  759. TRUE if the specified irp has argument == FilterContext
  760. FALSE otherwise
  761. --*/
  762. {
  763. ULONG64 IrpStack = (Irp+GetTypeSize("nt!_IRP"));
  764. ULONG StackCount, Stksize;
  765. ULONG i;
  766. if (GetFieldValue(Irp, "nt!_IRP", "StackCount", StackCount)) {
  767. return FALSE;
  768. }
  769. Stksize = GetTypeSize("nt!_IO_STACK_LOCATION");
  770. if (!Stksize || (StackCount > 30)) {
  771. return(FALSE);
  772. }
  773. for (i=0; i<StackCount; i++) {
  774. ULONG64 Argument1,Argument2,Argument3,Argument4;
  775. GetFieldValue(Irp + i*Stksize, "nt!_IO_STACK_LOCATION",
  776. "Parameters.Others.Argument1",Argument1);
  777. GetFieldValue(Irp + i*Stksize, "nt!_IO_STACK_LOCATION",
  778. "Parameters.Others.Argument2",Argument2);
  779. GetFieldValue(Irp + i*Stksize, "nt!_IO_STACK_LOCATION",
  780. "Parameters.Others.Argument3",Argument3);
  781. GetFieldValue(Irp + i*Stksize, "nt!_IO_STACK_LOCATION",
  782. "Parameters.Others.Argument4",Argument4);
  783. if ((Argument1 == *((PULONG64)FilterContext)) ||
  784. (Argument2 == *((PULONG64)FilterContext)) ||
  785. (Argument3 == *((PULONG64)FilterContext)) ||
  786. (Argument4 == *((PULONG64)FilterContext))) {
  787. return(TRUE);
  788. }
  789. }
  790. return(FALSE);
  791. }
  792. HRESULT
  793. GetIrpInfo(
  794. ULONG64 Irp,
  795. PDEBUG_IRP_INFO pIrp
  796. )
  797. {
  798. ULONG Type;
  799. UCHAR TypeName[]= "nt!_IRP";
  800. ULONG irpStackIndex;
  801. ULONG64 irpStackAddress;
  802. ZeroMemory(pIrp, sizeof(DEBUG_IRP_INFO));
  803. pIrp->SizeOfStruct = sizeof(DEBUG_IRP_INFO);
  804. pIrp->IrpAddress = Irp;
  805. if ( (GetFieldValue(Irp, TypeName, "Type", Type)) ) {
  806. //dprintf("%08p: Could not read Irp\n", IrpToDump);
  807. return E_INVALIDARG;
  808. }
  809. if (Type != IO_TYPE_IRP) {
  810. return E_INVALIDARG;
  811. }
  812. GetFieldValue(Irp, TypeName, "StackCount", pIrp->StackCount);
  813. GetFieldValue(Irp, TypeName, "CurrentLocation", pIrp->CurrentLocation);
  814. GetFieldValue(Irp, TypeName, "MdlAddress", pIrp->MdlAddress);
  815. GetFieldValue(Irp, TypeName, "CancelRoutine", pIrp->CancelRoutine);
  816. GetFieldValue(Irp, TypeName, "Tail.Overlay.Thread", pIrp->Thread);
  817. for (irpStackIndex = pIrp->StackCount,
  818. irpStackAddress = Irp + GetTypeSize("nt!_IRP") + (pIrp->StackCount - 1)* GetTypeSize("nt!_IO_STACK_LOCATION");
  819. irpStackIndex >= 1;
  820. irpStackIndex++, irpStackAddress -= GetTypeSize("nt!_IO_STACK_LOCATION")) {
  821. if ( InitTypeRead(irpStackAddress, nt!_IO_STACK_LOCATION)) {
  822. return E_INVALIDARG;
  823. }
  824. pIrp->CurrentStack.DeviceObject = ReadField(DeviceObject);
  825. if (!pIrp->CurrentStack.DeviceObject) {
  826. // To be implemented later, we are only interested in current one now
  827. continue;
  828. }
  829. pIrp->CurrentStack.StackAddress = irpStackAddress;
  830. pIrp->CurrentStack.CompletionRoutine = ReadField(CompletionRoutine);
  831. pIrp->CurrentStack.FileObject = ReadField(FileObject);
  832. pIrp->CurrentStack.Major = (UCHAR) ReadField(MajorFunction);
  833. pIrp->CurrentStack.Minor = (UCHAR) ReadField(MinorFunction);
  834. break;
  835. }
  836. return S_OK;
  837. }
  838. EXTENSION_API( GetIrpInfo )(
  839. PDEBUG_CLIENT Client,
  840. ULONG64 Irp,
  841. PDEBUG_IRP_INFO pIrp
  842. )
  843. {
  844. HRESULT Hr = E_FAIL;
  845. INIT_API();
  846. if (pIrp && (pIrp->SizeOfStruct == sizeof(DEBUG_IRP_INFO))) {
  847. Hr = GetIrpInfo(Irp, pIrp);
  848. }
  849. EXIT_API();
  850. return Hr;
  851. }