ReactOS  0.4.15-dev-2776-g4130f0b
fxirpqueue.cpp
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7  FxIrpQueue.cpp
8 
9 Abstract:
10 
11  This module implements a common queue structure for the
12  driver frameworks built around the Cancel Safe Queue model
13 
14 Author:
15 
16 
17 
18 
19 
20 
21 
22 Environment:
23 
24  Both kernel and user mode
25 
26 Revision History:
27 
28 
29 --*/
30 
31 #include "coreprivshared.hpp"
32 
33 // Tracing support
34 extern "C" {
35 // #include "FxIrpQueue.tmh"
36 }
37 
38 //
39 // Public constructors
40 //
41 
43  VOID
44  )
45 {
47 
49 
51 
52  m_RequestCount = 0;
53 }
54 
56 {
58 }
59 
60 VOID
64  )
65 
66 /*++
67 
68 Routine Description:
69 
70  Initialize the FxIrpQueue.
71 
72  Set the callback for when an IRP gets cancelled.
73 
74  The callback function is only called when an IRP
75  gets cancelled, and is called with no locks held.
76 
77  The cancel function that the caller registers is
78  responsible for completing the IRP with IoCompleteRequest.
79 
80  If no Cancel Callback is set, or is set to NULL, IRP's will
81  be automatically completed with STATUS_CANCELED by
82  the FxIrpQueue when they are canceled.
83 
84 
85  If the caller supplies a LockObject, this object is used
86  to synchronize cancellation access to the list, but it is
87  expected that the caller be holding the same lock for insert/remove
88  operations. This allows the caller to perform insert/remove operations
89  using its own lock in a race free manner.
90 
91  If a LockObject is not supplied, the FxIrpQueue uses its own lock.
92 
93 Arguments:
94 
95  LockObject - Object whose lock controls the queue
96 
97  Callback - Driver callback function
98 
99 Returns:
100 
101  None
102 
103 --*/
104 
105 {
106  ASSERT(LockObject != NULL);
107 
110 }
111 
112 
114 NTSTATUS
116  __inout MdIrp Irp,
118  __out_opt ULONG* pRequestCount
119  )
120 
121 /*++
122 
123 Routine Description:
124 
125  Enqueue a request to the end of the queue (FIFO) and
126  marks it as pending.
127 
128  The PMdIoCsqIrpContext is associated with the IRP.
129 
130  PIO_CSQ_IRP_CONTEXT must be in non-paged pool, and can
131  not be released until the IRP is is finally released from
132  the queue.
133 
134 Arguments:
135 
136  Irp - Pointer to IRP
137 
138  Context - Pointer to caller allocated CSQ context
139 
140  pRequestCount - Location to return new request count of queue
141  after insertion
142 
143 Returns:
144 
145  STATUS_SUCCESS - Operation completed.
146 
147  STATUS_CANCELLED - Request was cancelled, and not inserted
148  Call is responsible for completing it.
149 --*/
150 
151 {
153 
154  // Note: This marks the IRP Pending
156  Irp, // Irp to insert
157  Context, // PIO_CSQ_IRP_CONTEXT
158  FALSE, // InsertInHead
159  pRequestCount
160  );
161 
162  return Status;
163 }
164 
165 
167 NTSTATUS
169  __inout MdIrp Irp,
171  __out_opt ULONG* pRequestCount
172  )
173 
174 /*++
175 
176 Routine Description:
177 
178  Enqueue a request to the head of the queue and
179  marks it as pending.
180 
181  The PIO_CSQ_IRP_CONTEXT is associated with the IRP.
182 
183  PIO_CSQ_IRP_CONTEXT must be in non-paged pool, and can
184  not be released until the IRP is is finally released from
185  the queue.
186 
187 Arguments:
188 
189  Irp - Pointer to IRP
190 
191  Context - Pointer to caller allocated CSQ context
192 
193  pRequestCount - Location to return new request count of queue
194  after insertion
195 Returns:
196 
197  STATUS_SUCCESS - Operation completed.
198 
199  STATUS_CANCELLED - Request was cancelled, and not inserted
200  Call is responsible for completing it.
201 --*/
202 
203 {
205 
206  // Note: This marks the IRP Pending
208  Irp, // Irp to insert
209  Context, // PIO_CSQ_IRP_CONTEXT
210  TRUE, // InsertInHead
211  pRequestCount
212  );
213 
214  return Status;
215 }
216 
217 
218 MdIrp
221  )
222 
223 /*++
224 
225 Routine Description:
226 
227  Returns an IRP from the queue, and if successful
228  the IRP is no longer on the CSQ (m_Queue) and
229  is not non-cancellable.
230 
231 --*/
232 
233 {
235 }
236 
237 
239 NTSTATUS
241  __in_opt PMdIoCsqIrpContext TagContext,
243  __out FxRequest** ppOutRequest
244  )
245 
246 /*++
247 
248 Routine Description:
249 
250  Returns a request from the queue using an optional
251  FileObject or TagContext.
252 
253 --*/
254 
255 {
256  MdIrp Irp;
259 
260  if( TagContext == NULL ) {
261 
262  //
263  // Returns an IRP from the queue, and if successful
264  // the IRP is no longer on the CSQ (m_Queue) and
265  // is not non-cancellable.
266  //
268  FileObject, // PeekContext
269  &pCsqContext
270  );
271 
272  if( Irp != NULL ) {
273 
275 
276  *ppOutRequest = pRequest;
277 
278  return STATUS_SUCCESS;
279  }
280  else {
281  return STATUS_NO_MORE_ENTRIES;
282  }
283  }
284  else {
285 
286  // Handle TagRequest Case
288  TagContext
289  );
290 
291  if( Irp != NULL ) {
293 
294  *ppOutRequest = pRequest;
295 
296  return STATUS_SUCCESS;
297  }
298  else {
299  return STATUS_NOT_FOUND;
300  }
301  }
302 }
303 
305 NTSTATUS
307  __in_opt PMdIoCsqIrpContext TagContext,
309  __out FxRequest** ppOutRequest
310  )
311 
312 /*++
313 
314 Routine Description:
315 
316  PeekRequest allows a caller to enumerate through requests in
317  a queue, optionally only returning requests that match a specified
318  FileObject.
319 
320  The first call specifies TagContext == NULL, and the first request
321  in the queue that matches the FileObject is returned.
322 
323  Subsequent requests specify the previous request value as the
324  TagContext, and searching will continue at the request that follows.
325 
326  If the queue is empty, there are no requests after TagContext, or no
327  requests match the FileObject, NULL is returned.
328 
329  If FileObject == NULL, this matches any FileObject in a request.
330 
331  If a WDF_REQUEST_PARAMETERS structure is supplied, the information
332  from the request is returned to allow the driver to further examine
333  the request to decide whether to service it.
334 
335  If a TagRequest is specified, and it is not found, the return
336  status STATUS_NOT_FOUND means that the queue should
337  be re-scanned. This is because the TagRequest was cancelled from
338  the queue, or if the queue was active, delivered to the driver.
339  There may still be un-examined requests on the queue that match
340  the drivers search criteria, but the search marker has been lost.
341 
342  Re-scanning the queue starting with TagRequest == NULL and
343  continuing until STATUS_NO_MORE_ENTRIES is returned will ensure
344  all requests have been examined.
345 
346  Enumerating an active queue with this API could result in the
347  driver frequently having to re-scan.
348 
349  If a successful return of a Request object handle occurs, the driver
350  *must* call WdfObjectDereference when done with it.
351 
352  NOTE: Synchronization Details
353 
354  The driver is allowed to "peek" at requests that are still on
355  the Cancel Safe Queue without removing them. This means that
356  the peek context value used (TagRequest) could go away while
357  still holding it. This does not seem bad in itself, but the request
358  could immediately be re-used by a look aside list and be re-submitted
359  to the queue. At this point, the "tag" value means a completely different
360  request.
361 
362  This race is dealt with by reference counting the FxRequest object
363  that contains our PIO_CSQ_IRP_CONTEXT, so its memory remains valid
364  after a cancel, and the driver explicitly releases it with
365  WdfObjectDereference.
366 
367  But if this reference is not added under the CSQ's spinlock, there
368  could be a race in which the I/O gets cancelled and the cancel
369  callback completes the request, before we add our reference count.
370  This would then result in attempting to reference count invalid
371  memory. So to close this race, this routine returns the referenced
372  FxRequest object as its result.
373 
374 Arguments:
375 
376  TagRequest - If !NULL, request to begin search at
377 
378  FileObject - If !NULL, FileObject to match in the request
379 
380 
381 Returns:
382 
383  STATUS_NOT_FOUND - TagContext was specified, but not
384  found in the queue. This could be
385  because the request was cancelled,
386  or is part of an active queue and
387  the request was passed to the driver
388  or forwarded to another queue.
389 
390  STATUS_NO_MORE_ENTRYS - The queue is empty, or no more requests
391  match the selection criteria of TagRequest
392  and FileObject specified above.
393 
394  STATUS_SUCCESS - A request context was returned in
395  pOutRequest.
396 
397 --*/
398 
399 {
400  PLIST_ENTRY nextEntry;
401  FxIrp nextIrp(NULL);
403  BOOLEAN FoundTag = (TagContext == NULL) ? TRUE : FALSE;
405 
406  for( nextEntry = m_Queue.Flink; nextEntry != &this->m_Queue; nextEntry = nextEntry->Flink) {
407 
408  nextIrp.SetIrp(FxIrp::GetIrpFromListEntry(nextEntry));
409 
410  if(nextIrp.IsCanceled()) {
411  //
412  // This IRP is cancelled and the WdmCancelRoutine is about to run or waiting
413  // for us to drop the lock. So skip this one.
414  //
415  continue;
416  }
417 
419 
420  if( FoundTag ) {
421 
422  if( FileObject != NULL ) {
423 
424  if(nextIrp.GetFileObject() == FileObject ) {
425 
427 
428  //
429  // Must add the reference here under the protection
430  // of the cancel safe queues spinlock
431  //
432  pRequest->ADDREF(NULL);
433 
434  *ppOutRequest = pRequest;
435 
436  return STATUS_SUCCESS;
437  }
438  }
439  else {
440 
442 
443  //
444  // Must add the reference here under the protection
445  // of the cancel safe queues spinlock
446  //
447  pRequest->ADDREF(NULL);
448 
449  *ppOutRequest = pRequest;
450 
451  return STATUS_SUCCESS;
452  }
453  }
454  else {
455 
456  // If we found the tag, we want the *next* entry
457  if( pCsqContext == TagContext ) {
458  FoundTag = TRUE;
459  }
460  }
461 
462  }
463 
464  //
465  // If the caller supplied a tag, and it was
466  // not found, return a different code since
467  // the caller needs to re-scan the queue.
468  //
469  if( (TagContext != NULL) && !FoundTag ) {
470  return STATUS_NOT_FOUND;
471  }
472  else {
473  return STATUS_NO_MORE_ENTRIES;
474  }
475 }
476 
477 MdIrp
480  )
481 /*++
482 
483 Routine Description:
484 
485  Returns a request from the queue.
486 
487 --*/
488 {
489  MdIrp Irp;
490 
491  ASSERT(Context != NULL);
492 
493  //
494  // Returns an IRP from the queue, and if success
495  // the IRP is no longer on the CSQ (m_Queue) and
496  // is not non-cancellable.
497  //
499 
500  return Irp;
501 }
502 
504 NTSTATUS
506  __inout MdIrp Irp,
508  __in BOOLEAN InsertInHead,
509  __out_opt ULONG* pRequestCount
510  )
511 /*++
512 
513 Routine Description:
514 
515  Insert the IRP in the queue. If the IRP is already cancelled
516  it removes the IRP from the queue and returns STATUS_CANCELLED.
517 
518  If the IRP is cancelled and the CancelRoutine has already started
519  execution, then this function returns STATUS_SUCCESS.
520 
521 Arguments:
522 
523  Irp - Pointer to IRP
524 
525  Context - Pointer to caller allocated CSQ context
526 
527  InsertInHead - TRUE for head, FALSE for tail.
528 
529  pRequestCount - Location to return new request count of queue
530  after insertion
531 
532 Returns:
533 
534  STATUS_SUCCESS - Operation completed.
535 
536  STATUS_CANCELLED - if the request is already cancelled.
537 
538 --*/
539 {
540  FxIrp irp(Irp);
541  MdCancelRoutine cancelRoutine;
543 
544  //
545  // Set the association between the context and the IRP.
546  //
547 
548  if (Context) {
550  Context->Irp = Irp;
551  Context->Csq = (PIO_CSQ)this;
552 
553 
554 
555 
556 
557 
558 
559 
560 
561 
563  } else {
564 
565  //
566  // Currently always require context, but this will change when we
567  // allow queuing or low level IRP's without FxRequest headers allocated
568  //
569  ASSERT(FALSE);
570 
572  }
573 
574  // See if it's a head insertion
575  if( InsertInHead ) {
577  &m_Queue,
578  irp.ListEntry()
579  );
580  }
581  else {
583  &m_Queue,
584  irp.ListEntry()
585  );
586  }
587 
588  m_RequestCount++;
589 
590  if( pRequestCount != NULL ) {
591  *pRequestCount = m_RequestCount;
592  }
593 
595 
597 
598  ASSERT(!cancelRoutine);
599  UNREFERENCED_PARAMETER(cancelRoutine);
600 
601  if (irp.IsCanceled()) {
602 
603  cancelRoutine = irp.SetCancelRoutine(NULL);
604 
605  if (cancelRoutine) {
606 
607  // Remove the IRP from the list
609 
610  if (Context) {
611  Context->Irp = NULL;
612  }
613 
615 
616  //
617  // Caller does not want us to recurse on their lock by invoking
618  // the m_CancelCallback on the insert path. So they will complete
619  // the IRP themselves.
620  //
621  return STATUS_CANCELLED;
622  } else {
623 
624  //
625  // The cancel routine beat us to it.
626  //
627  DO_NOTHING();
628  }
629 
630  }
631 
632  return status;
633 }
634 
635 VOID
636 FX_VF_METHOD(FxIrpQueue, VerifyRemoveIrpFromQueueByContext)(
637  __in PFX_DRIVER_GLOBALS FxDriverGlobals,
639  )
640 /*++
641 
642 Routine Description:
643 
644  Makes sure that the specified Request (context) belongs to this IRP queue.
645 
646 --*/
647 {
649 
650  if (FxDriverGlobals->IsVerificationEnabled(1, 11, OkForDownLevel)) {
651  if (Context->Irp != NULL &&
653  Context->Csq != (PIO_CSQ)this)) {
654 
655  //
656  // This should never happen. Bugcheck before corrupting memory.
657  //
659  "Irp 0x%p (Context 0x%p) not on IRP queue 0x%p\n",
660  Context->Irp, Context, this);
661 
662  FxVerifierBugCheck(FxDriverGlobals,
665  (ULONG_PTR) Context);
666  }
667  }
668 }
669 
670 MdIrp
673  )
674 /*++
675 
676 Routine Description:
677 
678  Using the context it remove the associated IRP from the queue.
679 
680 --*/
681 {
682  MdIrp irp;
683  MdCancelRoutine cancelRoutine;
684 
685  if (Context->Irp ) {
686  //
687  // Make sure the Irp belongs to this queue.
688  //
689  ASSERT(Context->Csq == (PIO_CSQ)this);
690  VerifyRemoveIrpFromQueueByContext(m_LockObject->GetDriverGlobals(),
691  Context);
692 
693  irp = Context->Irp;
694 
695  FxIrp fxIrp(irp);
696 
697  cancelRoutine = fxIrp.SetCancelRoutine(NULL);
698  if (!cancelRoutine) {
699  return NULL;
700  }
701 
703 
705 
706  //
707  // Break the association.
708  //
709 
710  Context->Irp = NULL;
712 
713  ASSERT(Context->Csq == (PIO_CSQ)this);
714 
715  return irp;
716 
717  } else {
718  return NULL;
719  }
720 }
721 
722 
723 MdIrp
727  )
728 /*++
729 
730 Routine Description:
731 
732  This API look up IRP's in the queue.
733 
734  If Irp == NULL, it returns one from the head
735  of the queue.
736 
737  If Irp != NULL, it is a "peek context", and the
738  routine returns the *next* IRP in the queue.
739 
740 --*/
741 {
742  PLIST_ENTRY nextEntry;
743  PLIST_ENTRY listHead;
744  FxIrp irp(Irp);
745  FxIrp nextIrp(NULL);
746 
747  listHead = &m_Queue;
748 
749  //
750  // If the IRP is NULL, we will start peeking from the listhead, else
751  // we will start from that IRP onwards. This is done under the
752  // assumption that new IRPs are always inserted at the tail.
753  //
754 
755  if(Irp == NULL) {
756  nextEntry = listHead->Flink;
757  } else {
758  nextEntry = irp.ListEntry()->Flink;
759  }
760 
761  while(nextEntry != listHead) {
762 
763  nextIrp.SetIrp(FxIrp::GetIrpFromListEntry(nextEntry));
764 
765  //
766  // If PeekContext is supplied, it's a search for an IRP associated
767  // with a particular file object.
768  //
769  if(PeekContext) {
770 
771  if(nextIrp.GetFileObject() == (MdFileObject) PeekContext) {
772  break;
773  }
774  } else {
775  break;
776  }
777 
778  nextIrp.SetIrp(NULL);
779 
780  nextEntry = nextEntry->Flink;
781  }
782 
783  return nextIrp.GetIrp();
784 }
785 
786 MdIrp
790  )
791 /*++
792 
793 Routine Description:
794 
795  This routine will return a pointer to the next IRP in the queue adjacent to
796  the irp passed as a parameter. If the irp is NULL, it returns the IRP at the head of
797  the queue.
798 
799 --*/
800 {
802  MdCancelRoutine cancelRoutine;
803  FxIrp fxIrp(NULL);
804 
806 
807  for (;;) {
808 
809  if (!fxIrp.GetIrp()) {
810  return NULL;
811  }
812 
813  cancelRoutine = fxIrp.SetCancelRoutine(NULL);
814  if (!cancelRoutine) {
816  continue;
817  }
818 
819  RemoveIrpFromListEntry(&fxIrp); // Remove this IRP from the queue
820 
821  break;
822  }
823 
825  if (context->Type == FX_IRP_QUEUE_ENTRY_IDENTIFIER) {
826  context->Irp = NULL;
827  ASSERT(context->Csq == (PIO_CSQ)this);
828  }
829 
830  if(pCsqContext != NULL) {
831  *pCsqContext = context;
832  }
833 
835 
836  return fxIrp.GetIrp();
837 }
838 
839 
840 VOID
844  )
845 /*++
846 
847 Routine Description:
848 
849  This is the function called by WDM on the IRP when a cancel occurs
850 
851 --*/
852 {
853  PMdIoCsqIrpContext irpContext;
854  FxIrpQueue* p;
855  KIRQL irql;
856  FxIrp irp(Irp);
857 
859 
860  Mx::ReleaseCancelSpinLock(irp.GetCancelIrql());
861 
863 
864  //
865  // Decide if we have a PIO_CSQ_IRP_CONTEXT or an FxIrpQueue*
866  //
867  if (irpContext->Type == FX_IRP_QUEUE_ENTRY_IDENTIFIER) {
868  p = (FxIrpQueue*)irpContext->Csq;
869  } else {
870  ASSERT(FALSE);
871  p = (FxIrpQueue*)irpContext;
872  }
873 
874  ASSERT(p);
875 
876  p->LockFromCancel(&irql);
877 
878  // Remove the IRP from the list
879  p->RemoveIrpFromListEntry(&irp);
880 
881  //
882  // Break the association if necessary.
883  //
884 
885  if (irpContext != (PMdIoCsqIrpContext)p) {
886  irpContext->Irp = NULL;
887 
889  }
890 
891  //
892  // We are calling cancel-callback of the owning object with the lock
893  // held so that it can successfully deliver the canceled request to the driver
894  // if needed. If we don't hold the lock, we run into a race condition between
895  // thread that's deleting the queue and this routine that's trying to deliver
896  // a request to the queue being deleted. So the way it happens is that the dispose
897  // call of queue waits for the request count to go zero. When we remove the
898  // last Irp from the list above, we end up dropping the count to zero. This causes
899  // the delete thread to run thru and destroy the FxIoQueue object. So to avoid that
900  // after popping the request from the FxIrpQueue, we have to call into the FxIoQueue
901  // with the lock and insert the request back into the FxIoQueue list so that delete
902  // thread will wait until the request is delivered to the driver.
903  //
904  if( p->m_CancelCallback != NULL ) {
905  p->m_CancelCallback(p, Irp, irpContext, irql);
906  }
907  else {
908 
909  p->UnlockFromCancel(irql);
910 
911  //
912  // Dispose of the IRP ourselves
913  //
915  irp.SetInformation(0);
916 
917  DoTraceLevelMessage(p->m_LockObject->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDEVICE,
918  "Irp 0x%p on Queue 0x%p Cancelled\n", Irp, p);
919 
920  //
921  // Breakpoint for now. This usually means that someone
922  // is going to leak some driver frameworks state...
923  //
924  FxVerifierDbgBreakPoint(p->m_LockObject->GetDriverGlobals());
925 
927  }
928 }
929 
930 BOOLEAN
933  )
934 /*++
935 
936 Routine Description:
937  Enumerates the list to see if any of the IRPs there has
938  a context that matches the input one.
939 
940 --*/
941 {
942  PLIST_ENTRY nextEntry;
943  FxIrp nextIrp(NULL);
945 
946  nextEntry = m_Queue.Flink;
947 
948  while( nextEntry != &m_Queue ) {
949  nextIrp.SetIrp(FxIrp::GetIrpFromListEntry(nextEntry));
950 
952 
953  if( pCsqContext == Context ) {
954  ASSERT(Context->Irp == nextIrp.GetIrp());
955  return TRUE;
956  }
957 
958  nextEntry = nextEntry->Flink;
959  }
960 
961  return FALSE;
962 }
963 
964 
PLIST_ENTRY ListEntry()
Definition: fxirpum.cpp:535
FxNonPagedObject * m_LockObject
Definition: fxirpqueue.hpp:97
LONG m_RequestCount
Definition: fxirpqueue.hpp:107
#define _Must_inspect_result_
Definition: no_sal2.h:62
MdFileObject GetFileObject(VOID)
Definition: fxirpum.cpp:1460
PVOID GetContext(__in ULONG Index)
Definition: fxirpum.cpp:361
__in MdIrp __in PMdIoCsqIrpContext pCsqContext
Definition: fxirpqueue.hpp:74
_Must_inspect_result_ NTSTATUS InsertHeadRequest(__inout MdIrp Irp, __in_opt PMdIoCsqIrpContext CsqContext, __out_opt ULONG *pRequestCount)
Definition: fxirpqueue.cpp:168
static MdIrp GetIrpFromListEntry(__in PLIST_ENTRY Ple)
Definition: fxirpum.cpp:1190
BOOLEAN IsIrpInQueue(__in PMdIoCsqIrpContext Context)
Definition: fxirpqueue.cpp:931
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
VOID SetStatus(__in NTSTATUS Status)
Definition: fxirpum.cpp:457
Definition: http.c:7251
MdIrp GetNextRequest(__out PMdIoCsqIrpContext *pCsqContext)
Definition: fxirpqueue.cpp:219
#define __in_opt
Definition: dbghelp.h:38
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
VOID SetContext(__in ULONG Index, __in PVOID Value)
Definition: fxirpum.cpp:351
LONG NTSTATUS
Definition: precomp.h:26
FxRequest * pRequest
Definition: fxirp.hpp:28
KIRQL irql
Definition: wave.h:1
PFN_IRP_QUEUE_CANCEL m_CancelCallback
Definition: fxirpqueue.hpp:102
PFILE_OBJECT MdFileObject
Definition: mxgeneralkm.h:32
#define InsertTailList(ListHead, Entry)
~FxIrpQueue(VOID)
Definition: fxirpqueue.cpp:55
#define FX_IRP_QUEUE_CSQ_CONTEXT_ENTRY
Definition: fxirpqueue.hpp:47
#define TRACINGREQUEST
Definition: dbgtrace.h:65
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
#define FxVerifierBugCheck(FxDriverGlobals, Error,...)
Definition: fxverifier.h:58
EVT_IRP_QUEUE_CANCEL * PFN_IRP_QUEUE_CANCEL
Definition: fxirpqueue.hpp:79
uint32_t ULONG_PTR
Definition: typedefs.h:65
IO_CSQ_IRP_CONTEXT * PMdIoCsqIrpContext
LIST_ENTRY m_Queue
Definition: fxirpqueue.hpp:91
UCHAR KIRQL
Definition: env_spec_w32.h:591
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
#define __out_opt
Definition: dbghelp.h:65
VOID RemoveIrpFromListEntry(__inout FxIrp *Irp)
Definition: fxirpqueue.hpp:257
#define FALSE
Definition: types.h:117
MdIrp RemoveNextIrpFromQueue(__in_opt PVOID PeekContext, __out_opt PMdIoCsqIrpContext *pCsqContext)
Definition: fxirpqueue.cpp:787
_In_ PIRP Irp
Definition: csq.h:116
struct _IO_CSQ * PIO_CSQ
Definition: csq.h:69
#define __out
Definition: dbghelp.h:62
#define PAGED_CODE_LOCKED()
Definition: kefuncs.h:1429
unsigned char BOOLEAN
IWudfIrp * MdIrp
Definition: mxum.h:103
WUDF_DRIVER_CANCEL * MdCancelRoutine
Definition: mxum.h:143
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:547
MdIrp RemoveRequest(__in PMdIoCsqIrpContext Context)
Definition: fxirpqueue.cpp:478
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define __drv_useCancelIRQL
Definition: driverspecs.h:314
_Must_inspect_result_ NTSTATUS InsertTailRequest(__inout MdIrp Irp, __in_opt PMdIoCsqIrpContext CsqContext, __out_opt ULONG *pRequestCount)
Definition: fxirpqueue.cpp:115
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define TRACINGDEVICE
Definition: dbgtrace.h:58
#define ASSERT(a)
Definition: mode.c:44
VOID CompleteRequest(__in_opt CCHAR PriorityBoost=IO_NO_INCREMENT)
Definition: fxirpum.cpp:24
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
VOID SetInformation(__in ULONG_PTR Information)
Definition: fxirpum.cpp:504
_In_opt_ PVOID _In_ ULONG _In_ PVOID context
Definition: wdfdriver.h:113
static __inline FxRequest * RetrieveFromCsqContext(__in PMdIoCsqIrpContext pCsqContext)
Definition: fxrequest.hpp:1163
KIRQL GetCancelIrql()
Definition: fxirpum.cpp:492
BOOLEAN IsCanceled()
Definition: fxirpum.cpp:484
#define __inout
Definition: dbghelp.h:50
Definition: typedefs.h:119
VOID MarkIrpPending()
Definition: fxirpum.cpp:415
static MdCancelRoutineType _WdmCancelRoutineInternal
Definition: fxirpqueue.hpp:273
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
_In_ WDFINTERRUPT _In_ PFN_WDF_INTERRUPT_SYNCHRONIZE Callback
Definition: wdfinterrupt.h:456
MdIrp PeekNextIrpFromQueue(__in_opt MdIrp Irp, __in_opt PVOID PeekContext)
Definition: fxirpqueue.cpp:724
#define FX_IRP_QUEUE_ENTRY_IDENTIFIER
Definition: fxirpqueue.hpp:52
Definition: csq.h:222
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
MdIrp GetIrp(VOID)
Definition: fxirpum.cpp:15
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
MdIrp RemoveIrpFromQueueByContext(__in PMdIoCsqIrpContext Context)
Definition: fxirpqueue.cpp:671
FxIrp fxIrp(Irp)
#define NULL
Definition: types.h:112
VOID FX_VF_METHOD(FxIrpQueue, VerifyRemoveIrpFromQueueByContext)(__in PFX_DRIVER_GLOBALS FxDriverGlobals
_In_opt_ PIRP _In_opt_ PVOID PeekContext
Definition: csq.h:159
VOID Initialize(__in FxNonPagedObject *LockObject, __in PFN_IRP_QUEUE_CANCEL Callback)
Definition: fxirpqueue.cpp:61
FxIrpQueue(VOID)
Definition: fxirpqueue.cpp:42
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define STATUS_SUCCESS
Definition: shellext.h:65
GLfloat GLfloat p
Definition: glext.h:8902
MdIrp SetIrp(MdIrp irp)
Definition: fxirpkm.hpp:71
#define __in
Definition: dbghelp.h:35
static SERVICE_STATUS status
Definition: service.c:31
VOID __in PMdIoCsqIrpContext Context
Definition: fxirpqueue.cpp:647
_Must_inspect_result_ NTSTATUS InsertIrpInQueue(__inout MdIrp Irp, __in_opt PMdIoCsqIrpContext Context, __in BOOLEAN InsertInHead, __out_opt ULONG *pRequestCount)
Definition: fxirpqueue.cpp:505
_Must_inspect_result_ NTSTATUS PeekRequest(__in_opt PMdIoCsqIrpContext TagContext, __in_opt MdFileObject FileObject, __out FxRequest **ppOutRequest)
Definition: fxirpqueue.cpp:306
MdCancelRoutine SetCancelRoutine(__in_opt MdCancelRoutine CancelRoutine)
Definition: fxirpum.cpp:124
FxIrp * irp
FxVerifierDbgBreakPoint(pFxDriverGlobals)
#define DO_NOTHING()
Definition: mxgeneral.h:32
Definition: ps.c:97
#define LockObject(Object)
Definition: titypes.h:34