ReactOS 0.4.15-dev-7788-g1ad9096
fxioqueue.cpp
Go to the documentation of this file.
1/*++
2
3Copyright (c) Microsoft Corporation
4
5Module Name:
6
7 FxIoQueue.cpp
8
9Abstract:
10
11 This module implements the FxIoQueue object and C interfaces
12
13Author:
14
15
16
17
18Revision History:
19
20
21
22
23--*/
24
25#include "ioprivshared.hpp"
26#include "fxioqueue.hpp"
27
28extern "C" {
29#if defined(EVENT_TRACING)
30#include "FxIoQueue.tmh"
31#endif
32}
33
34//
35// Public constructors
36//
38 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
39 __in FxPkgIo* PkgIo
40 ) :
42 m_CallbackSpinLock(FxDriverGlobals),
43 m_CallbackMutexLock(FxDriverGlobals),
44 m_IoPkgListNode(FxIoQueueNodeTypeQueue)
45 {
54
55 // A newly created queue can not accept requests until initialized
57
58 //
59 // Set our Cancel callbacks
60 //
62
64
66
68
70
72
74
76
77 //
78 // We do not reference count the I/O package instance
79 // since it contains us. The fact we exist, the I/O
80 // package instance exists.
81 //
82 m_PkgIo = PkgIo;
84
85 m_Device = PkgIo->GetDevice();
86
89
91
94
97
99
102
105
108
111
112#if FX_IS_KERNEL_MODE
113
114 // Initialize the DPC used for deferrals
116 &m_Dpc,
118 this
119 );
120#endif
121
123
125
127
131
134
138
139 return;
140}
141
143{
145
146 if (m_PkgIo != NULL) {
147 m_PkgIo = NULL;
148 }
149
160}
161
168 __in_opt FxDriver* Caller,
169 __in FxPkgIo* PkgIo,
170 __in BOOLEAN InitialPowerStateOn,
172 )
173{
176
177 *Object = NULL;
178
180
181 if (pQueue == NULL) {
184 "Memory allocation failed: %!STATUS!", status);
185 return status;
186 }
187
188 //
189 // Initialize it, creating the handle to pass the driver
190 // and configuring its callbacks and queue type
191 //
194 Caller,
195 InitialPowerStateOn);
196 if (!NT_SUCCESS(status)) {
198 "Could not configure queue: %!STATUS!", status);
199 goto Done;
200 }
201Done:
202 if (NT_SUCCESS(status)) {
203 *Object = pQueue;
204 }
205 else {
206 //
207 // Release our newly allocated Queue object
208 //
210 }
211
212 return status;
213}
214
220 __in_opt FxDriver* Caller,
221 __in BOOLEAN InitialPowerStateOn
222 )
223
224/*++
225
226Routine Description:
227
228 Initialize the IoQueue after creating.
229
230 This creates the handle required for passing to the driver.
231
232Arguments:
233
234Returns:
235
236 NTSTATUS
237
238--*/
239
240{
242 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
243
245 if (!NT_SUCCESS(Status)) {
246 return Status;
247 }
248
250 if (!NT_SUCCESS(Status)) {
251 return Status;
252 }
253
254#if (FX_CORE_MODE==FX_CORE_USER_MODE)
256 if (!NT_SUCCESS(Status)) {
257 return Status;
258 }
259#endif
260
262
263 //
264 // Set the execution level and callback synchronization based on
265 // configuration
266 //
268 if (!NT_SUCCESS(Status)) {
269 return Status;
270 }
271
272 //
273 // Validate dispatch type.
274 //
275 if (pConfig->DispatchType <= WdfIoQueueDispatchInvalid ||
276 pConfig->DispatchType >= WdfIoQueueDispatchMax) {
278 "Invalid dispatch type "
279 "specified %d, Queue 0x%p %!STATUS!",
280 pConfig->DispatchType,
284 }
285
286 //
287 // If not a manual queue, must set at least IoStart, or one of
288 // read|write|devicecontrol
289 //
290 if ((pConfig->DispatchType != WdfIoQueueDispatchManual) &&
291 (pConfig->EvtIoDefault == NULL)) {
292
293 if ((pConfig->EvtIoDefault == NULL) &&
294 (pConfig->EvtIoRead == NULL) &&
295 (pConfig->EvtIoWrite == NULL) &&
296 (pConfig->EvtIoDeviceControl == NULL) &&
297 (pConfig->EvtIoInternalDeviceControl == NULL)) {
298
300 "At least one of EvtIoDefault|EvtIoRead|EvtIoWrite|"
301 "EvtIoDeviceControl|EvtIoInternalDeviceControl "
302 "must be set %!STATUS!", STATUS_WDF_NO_CALLBACK);
304 }
305 }
306
307 //
308 // A manual queue should not set any callback function
309 // pointers since they will not get invoked.
310 //
311 if (pConfig->DispatchType == WdfIoQueueDispatchManual) {
312
313 if ((pConfig->EvtIoDefault != NULL) ||
314 (pConfig->EvtIoRead != NULL) ||
315 (pConfig->EvtIoWrite != NULL) ||
316 (pConfig->EvtIoDeviceControl != NULL) ||
317 (pConfig->EvtIoInternalDeviceControl != NULL)) {
318
320 "Cannot set io callback events "
321 "on a manual WDFQUEUE 0x%p %!STATUS!",
325 }
326 }
327
328 //
329 // For version less than v1.9 m_MaxParallelQueuePresentedRequests is set to
330 // -1 by the FxIoQueue Constructor.
331 // By checking > below we mean v1.9 and above (public API already did the official
332 // validation).
333 //
334 if (pConfig->Size > sizeof(WDF_IO_QUEUE_CONFIG_V1_7)) {
335 if (pConfig->Settings.Parallel.NumberOfPresentedRequests != 0 &&
336 (pConfig->DispatchType == WdfIoQueueDispatchSequential ||
337 pConfig->DispatchType == WdfIoQueueDispatchManual)) {
340 "Cannot have NumberOfPresentedRequests other "
341 "than 0 on a Sequential or manual WDFQUEUE 0x%p."
342 "Make Sure you set NumberOfPresentedRequests"
343 " to 0, %!STATUS!",
345 Status
346 );
347 return Status;
348
349 }
350 else{
352 pConfig->Settings.Parallel.NumberOfPresentedRequests;
353 }
354 }
355
356 //
357 // Initialize our workitem if we have to support passive callbacks
358 //
359 if (m_PassiveLevel) {
360
361 Status = FxSystemWorkItem::_Create(FxDriverGlobals,
364 );
365
366 if (!NT_SUCCESS(Status)) {
368 "Could not allocate workitem: %!STATUS!", Status);
369 return Status;
370 }
371 }
372
373 m_Type = pConfig->DispatchType;
374
375 switch(pConfig->PowerManaged) {
376
377 case WdfUseDefault:
378 if(m_Device->IsFilter()){
380 } else {
382 }
383 break;
384
385 case WdfTrue:
387 break;
388
389 case WdfFalse:
391 break;
392 default:
393 ASSERTMSG("Invalid value in WDF_IO_QUEUE_CONFIG PowerManaged field\n", FALSE);
394 break;
395 }
396
397 //
398 // Queues for NonPnp devices can't be power managed.
399 //
400 if(m_Device->IsLegacy()) {
402 }
403
404 //
405 // If power managed queue, ensure its initial power state
406 // is same as the device.
407 //
408 if (m_PowerManaged) {
409 if (InitialPowerStateOn) {
411 }
412 else {
414 }
415 } else {
417 }
418
419 m_AllowZeroLengthRequests = pConfig->AllowZeroLengthRequests;
420
422 "EvtIoDefault 0x%p, EvtIoRead 0x%p, EvtIoWrite 0x%p, "
423 "EvtIoDeviceControl 0x%p for WDFQUEUE 0x%p",
424 pConfig->EvtIoDefault,
425 pConfig->EvtIoRead,
426 pConfig->EvtIoWrite,
427 pConfig->EvtIoDeviceControl, GetObjectHandle());
428
429 m_IoDefault.Method = pConfig->EvtIoDefault;
430 m_IoStop.Method = pConfig->EvtIoStop;
431 m_IoResume.Method = pConfig->EvtIoResume;
432 m_IoRead.Method = pConfig->EvtIoRead;
433 m_IoWrite.Method = pConfig->EvtIoWrite;
434 m_IoDeviceControl.Method = pConfig->EvtIoDeviceControl;
435 m_IoInternalDeviceControl.Method = pConfig->EvtIoInternalDeviceControl;
436 m_IoCanceledOnQueue.Method = pConfig->EvtIoCanceledOnQueue;
437
438
439 // A newly created queue can accept and dispatch requests once initialized
441
443
444 return STATUS_SUCCESS;
445}
446
449 )
450/*++
451
452Routine Description:
453
454 Should be called at PASSIVE_LEVEL because of the synchronous call
455 to drain requests, workitems, and dpcs associated with this queue.
456
457Arguments:
458
459Returns:
460
461 TRUE or FALSE
462
463--*/
464{
465 KIRQL irql;
466
467 if (IsCommitted() == FALSE) {
468 //
469 // We called DeleteFromFailedCreate because we couldn't commit the
470 // object.
471 //
472 goto End;
473 }
474
475 //
476 // If object is commited means we are added to the FxPkgIo queue list.
477 //
478 //
479 // Purge the queue asynchrnously without providing any callback. That way,
480 // we allow the driver to have an outstanding purge request while the delete
481 // is in progress.
482 //
484
485 Lock(&irql);
486
487 //
488 // Mark that this queue is disposing
489 //
490
492
494
495 //
496 // Just make sure the state hasn't changed after the purge.
497 //
499
500 //
501 // Call the FxPkgIo to remove its references to this queue
502 //
503 // Note: We are holding the queue lock to prevent races, and
504 // FxPkgIo never calls FxIoQueue methods while holding
505 // its lock.
506 //
508
509 DispatchEvents(irql);
510
511 //
512 // Wait for the finished event to be signalled. This event will
513 // be signalled when the queue is in a disposed state and there
514 // are no more pending events.
515 //
517 "waiting for the queue to be deleted, WDFQUEUE", GetHandle(),
518 GetDriverGlobals()->FxVerifierDbgWaitForSignalTimeoutInSec,
520
521
523
526
531 }
532
533 if (m_FwdProgContext != NULL) {
537 }
538
539 //
540 // Rundown the workitem.
541 //
542 if (m_SystemWorkItem != NULL) {
545 }
546
547 //
548 // Rundown the DPCs
549 //
550 if (m_DpcQueued) {
552 }
553
554 //
555 // All callbacks into the device driver acquire and release a
556 // reference on the queue. This ensures that the queue will
557 // not actually complete deleting until return from any
558 // outstanding event callbacks into the device driver.
559 //
560 // See DispatchRequestToDriver()
561 //
562End:
563
564 FxNonPagedObject::Dispose(); // __super call
565
566 return TRUE;
567}
568
573 __in_opt FxDriver* Caller
574 )
575
576/*++
577
578Routine Description:
579
580 Configures the locking and threading model for the
581 Queue according to parameters specified by the device
582 driver when it initialized.
583
584Arguments:
585
586Returns:
587
588 NTSTATUS
589
590--*/
591
592{
593 WDF_EXECUTION_LEVEL ParentLevel;
594 WDF_SYNCHRONIZATION_SCOPE ParentScope;
595 BOOLEAN AutomaticLockingRequired;
596
597 AutomaticLockingRequired = FALSE;
598 ASSERT(m_Device != NULL);
599
600 //
601 // Initialize both spin and mutex locks
602 //
605
606 //
607 // If WDF_OBJECT_ATTRIBUTES is specified, these override any
608 // default settings.
609 //
610 if (ObjectAttributes != NULL) {
611 m_ExecutionLevel = ObjectAttributes->ExecutionLevel;
612 m_SynchronizationScope = ObjectAttributes->SynchronizationScope;
613 }
614
615 //
616 // If no WDFQUEUE specific attributes are specified, we
617 // get them from WDFDEVICE, which allows WDFDEVICE to
618 // provide a default for all WDFQUEUE's created.
619 //
620 m_Device->GetConstraints(&ParentLevel, &ParentScope);
623
625 m_ExecutionLevel = ParentLevel;
626 }
627
629 m_SynchronizationScope = ParentScope;
630 }
631
632 //
633 // For backward compatibility purposes always have a lock associated with the
634 // object even for WdfSynchronizationScopeNone. This is so that we return a non-null
635 // presentation lock for the WDFQUEUE object.
636 //
638 //
639 // Mark FxObject as passive level to ensure that Dispose and Destroy
640 // callbacks are passive to the driver
641 //
644
645 //
646 // Passive Callbacks constraint has been set, we use a mutex for the
647 // callback lock.
648 //
651 }
652 else {
653 //
654 // If no passive level constraint is specified, then spinlocks
655 // are used for callbacks since they are lightweight and work with
656 // DPC's and Timer's
657 //
660 }
661
662 //
663 // Configure synchronization scope
664 //
667
668 //
669 // WDF extensions are not allowed to use this type of synchronization.
670 //
671 if (Caller != NULL && Caller != GetDriverGlobals()->Driver) {
674 "WDFQUEUE 0x%p Synchronization scope is set to "
675 "device; WDF extension drivers are not allowed "
676 "to use this type of synchronization, %!STATUS!",
678 return status;
679 }
680
681 //
682 // If we inherit the Sync. scope from parent or device
683 // and if the parent/device has Exec. Level different from Queue
684 // then disallow that case.
685 // FUTURE PROOF NOTE: Adding a new Execution Level will need reevaluation
686 // of the check below.
687 //
688 if (ParentLevel != m_ExecutionLevel) {
691 "WDFQUEUE 0x%p Synchronization scope is set to device"
692 " but the Device ExecutionLevel: 0x%x"
693 " doesn't match Queue ExecutionLevel: 0x%x, %!STATUS!",
694 GetObjectHandle(), ParentLevel,
696 return status;
697 }
698 //
699 // Per device automatic callback synchronization, so we update our
700 // callback lock ptr to point to the devices lock
701 //
702 AutomaticLockingRequired = TRUE;
703
704 //
705 // Get the callback lock and object from the device
706 //
708 }
710 //
711 // Per object automatic serialization
712 //
713 AutomaticLockingRequired = TRUE;
714
715 // m_CallbackLockPtr has been set above in execution level constraint
716 }
717
718
719 if (AutomaticLockingRequired) {
720 //
721 // If automatic locking has been configured, set the lock
722 // on the FxCallback object delegates
723 //
734
736 }
737 else {
738 //
739 // No automatic locking specified
740 //
751
753
754 }
755
756 return STATUS_SUCCESS;
757}
758
761 __out_opt PULONG pQueueCount,
762 __out_opt PULONG pDriverCount
763 )
764{
765 int stat;
767
768 // Get request counts
770
771 if (pQueueCount ) *pQueueCount = QueueCount;
772
773 if (pDriverCount ) *pDriverCount = DriverCount;
774
775 //
776 // First fill in the values that are kept up to date at runtime
777 //
779
780 //
781 // Set additional information bits from information retrieved
782 // from other sources. It's cheaper to get this info at the infrequent
783 // GetStatus time, rather than keep the bits up to date at each
784 // request and queue transition.
785 //
786 if (QueueCount == 0) {
788 }
789
790 if (DriverCount == 0) {
792 }
793
794 if(m_PowerManaged) {
795
798 }
799 }
800
801 return (WDF_IO_QUEUE_STATE)stat;
802}
803
804VOID
807 )
808{
809 int AllowedBits;
810
811 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
812
813 //
814 // Only allow setting of valid bits
815 //
816 AllowedBits = (int)(FxIoQueueSetAcceptRequests |
822 );
823
824 if ((int)NewStatus & ~AllowedBits) {
826 "Invalid WDFQUEUE 0x%p state",
828 FxVerifierDbgBreakPoint(FxDriverGlobals);
829 return;
830 }
831
832 //
833 // Clear the high bit used to prevent accidental mixing of
834 // WDF_IO_QUEUE_STATE and FX_IO_QUEUE_SET_STATE
835 //
836 NewStatus = (FX_IO_QUEUE_SET_STATE)((int)NewStatus & 0x7FFFFFFF);
837
838 if (NewStatus & (int)FxIoQueueClearShutdown) {
840 }
841
842 if (NewStatus & (int)FxIoQueueSetShutdown) {
844 }
845
846 if (NewStatus & (int)FxIoQueueSetAcceptRequests) {
849 }
850 else {
851 DoTraceLevelMessage(FxDriverGlobals,
853 "WDFQUEUE 0x%p is shut down, preventing queue "
854 "from accepting requests",
856 }
857 }
858
859 if (NewStatus & (int)FxIoQueueClearAcceptRequests) {
861 }
862
863 if (NewStatus & (int)FxIoQueueSetDispatchRequests) {
865 //
866 // If the queue is allowed to dispatch new requests, we must clear this flag.
867 // See also WdfIoQueueStopAndPurge for more info about the flag.
868 //
870 }
871
872 if (NewStatus & (int)FxIoQueueClearDispatchRequests) {
874 }
875
876 return;
877}
878
881FX_VF_METHOD(FxIoQueue, VerifyGetRequestUpdateFlags) (
882 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
884 )
885{
886 KIRQL irql;
888
890
891 if (TagRequest != NULL) {
892 //
893 // WdfIoQueueRetrieveFoundRequest is only valid on manual queues.
894 // v1.11 and above: driver is not required to find the request
895 // using WdfIoQueueFindRequest.
896 // v1.9 and below: driver is required to find the request
897 // using WdfIoQueueFindRequest.
898 //
899 if (FxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,11)) {
900 if (m_Type != WdfIoQueueDispatchManual) {
903 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIO,
904 "WdfIoQueueRetrieveFoundRequest is allowed "
905 "only on a manual queue 0x%p, %!STATUS!",
906 GetHandle(), status);
907 FxVerifierDbgBreakPoint(FxDriverGlobals);
908 return status;
909 }
910 }
911 else {
912 //
913 // Legacy validation.
914 //
915 TagRequest->Lock(&irql);
916 status = TagRequest->VerifyRequestIsTagRequest(FxDriverGlobals);
918 if (!NT_SUCCESS(status)) {
919 return status;
920 }
921 }
922 }
923
925 if ((m_Type == WdfIoQueueDispatchSequential) && (m_DriverIoCount == 0)) {
926
928 "Driver called WdfIoQueueRetrieveNextRequest on a sequential WDFQUEUE 0x%p with no "
929 "outstanding requests. This can cause a race with automatically dispatched "
930 "requests. Call WdfIoQueueRetrieveNextRequest before completing the current request(s)",
932
933 FxVerifierDbgBreakPoint(FxDriverGlobals);
934
935 // Allow them to continue, though this is a race condition in their driver
936 }
938
940}
941
942VOID
943FX_VF_METHOD(FxIoQueue, VerifyGetRequestRestoreFlags)(
944 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
946 )
947{
948 UNREFERENCED_PARAMETER(FxDriverGlobals);
949 KIRQL irql;
950
952 pRequest->Lock(&irql);
953
954 pRequest->ClearVerifierFlagsLocked(FXREQUEST_FLAG_TAG_REQUEST);
955 pRequest->SetVerifierFlagsLocked(FXREQUEST_FLAG_DRIVER_OWNED);
956
957 pRequest->Unlock(irql);
958}
959
965 __deref_out FxRequest** pOutRequest
966 )
967/*++
968
969Routine Description:
970
971 This method is called by
972
973 WdfIoQueueRetrieveNextRequest
974 WdfIoQueueRetrieveRequestByFileObject
975 WdfIoQueueRetrieveFoundRequest
976
977 to retrieve a request from the queue.
978
979Arguments:
980
981Returns:
982
983 NTSTATUS
984
985--*/
986{
991 KIRQL irql;
992
993 status = VerifyGetRequestUpdateFlags(pFxDriverGlobals, TagRequest);
994 if(!NT_SUCCESS(status)){
995 return status;
996 }
997
998 //
999 // Don't allow on parallel queues
1000 //
1005 "Cannot be called on a parallel WDFQUEUE 0x%p, %!STATUS!",
1007 return status;
1008 }
1009
1010 Lock(&irql);
1011
1012 //
1013 // Only if the queue state allows requests to be retrieved.
1014 // It's okay to retrieve requests while the queue is in a transitioning state.
1015 //
1019 "WDFQUEUE 0x%p is powered off, %!STATUS!",
1021 Unlock(irql);
1022 return status;
1023 }
1024
1025 //
1026 // See if the queue is (still) processing requests
1027 //
1031 "WDFQUEUE 0x%p is stopped, %!STATUS!",
1033 Unlock(irql);
1034 return status;
1035 }
1036
1037 #pragma warning(disable:4127)
1038 while (TRUE) {
1039
1040 #pragma warning(default:4127)
1041 //
1042 // Get the next FxRequest from the cancel safe queue
1043 //
1045 if (!NT_SUCCESS(status)) {
1046 //
1047 // This code address the following race condition:
1048 // 1) Queue has only one request (count 1).
1049 // 2) Request in queue is cancelled.
1050 // 3) Request's cancellation logic starts to run on thread 1.
1051 // 4) But before cancellation logic gets the queue's lock
1052 // thread 2 calls WdfIoQueueRetrieveNextRequest.
1053 // 5) WdfIoQueueRetrieveNextRequest returns no more requests.
1054 // Driver waits for the ReadyNotify callback. (count 1)
1055 // 6) Thread 3 adds a new request in queue. (count 1->2)
1056 // 7) Thread 1 finally runs. (count 2->1).
1057 // 8) At this point driver stops responding b/c it never receives ReadyNotify.
1058 //
1059 // This code below forces the queue logic to send a ReadyNotify
1060 // callback the next time a new request is added (in step 6 above).
1061 //
1063 NULL == FileObject && // WdfIoQueueRetrieveNextRequest
1064 NULL == TagRequest && // WdfIoQueueRetrieveNextRequest
1065 m_Queue.GetRequestCount() > 0L) {
1066
1068 }
1069
1070 Unlock(irql);
1071 return status;
1072 }
1073
1074 //
1075 // If we don't allow zero length read/write's to the driver,
1076 // complete it now with success and attempt to get another
1077 // request from the queue.
1078 //
1080
1081
1082
1083
1084
1086
1089
1090 if ((majorFunction == IRP_MJ_READ) &&
1091 (pIrp->GetParameterReadLength() == 0)) {
1092
1093 Unlock(irql);
1095 "Zero length WDFREQUEST 0x%p completed automatically by WDFQUEUE 0x%p",
1099
1100 Lock(&irql);
1101
1102 // Get another request from the queue
1103 continue;
1104 }
1105 else if ((majorFunction == IRP_MJ_WRITE) &&
1106 (pIrp->GetParameterWriteLength() == 0)) {
1107
1108 Unlock(irql);
1110 "Zero length WDFREQUEST 0x%p completed automatically by WDFQUEUE 0x%p",
1112
1115
1116 Lock(&irql);
1117
1118 // Get another request from the queue
1119 continue;
1120 }
1121 }
1122
1123 break;
1124 }
1125
1126 // Increase the driver owned request count
1128
1129 Unlock(irql);
1130
1131 //
1132 // We don't need to check for PurgeComplete since
1133 // we are giving the request to the driver
1134 //
1135
1136 // pRequest is not cancellable now
1137
1138 //
1139 // We are now going to return the request
1140 // to the driver, and it must complete it.
1141 //
1142
1143 //
1144 // Set a completion event, this takes a reference
1145 //
1148 UNREFERENCED_PARAMETER(oldState);
1149
1150 //
1151 // Track that we have given the request to the driver
1152 //
1153 VerifyGetRequestRestoreFlags(pFxDriverGlobals, pRequest);
1154
1156
1157 //
1158 // Release our original reference. The FxRequest::Complete
1159 // will release the final one since we have registered a completion
1160 // callback handler
1161 //
1162 // We now have one reference count on the FxRequest object until
1163 // its completion routine runs since the completion event made
1164 // an extra reference, and will dereference it when it fires, or
1165 // its canceled.
1166 //
1167
1168 pRequest->RELEASE(FXREQUEST_STATE_TAG);
1169
1170 // Return it to the driver
1171 *pOutRequest = pRequest;
1172
1173 return STATUS_SUCCESS;
1174}
1175
1178FX_VF_METHOD(FxIoQueue, VerifyPeekRequest) (
1179 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
1181 )
1182{
1184 KIRQL irql;
1185
1187
1188 TagRequest->Lock(&irql);
1189 status = TagRequest->VerifyRequestIsTagRequest(FxDriverGlobals);
1191
1192 return status;
1193}
1194
1201 __deref_out FxRequest** pOutRequest
1202 )
1203/*++
1204
1205Routine Description:
1206
1207 This method is called by WdfIoQueueFindRequest to
1208 look for a specific request from the queue. If tagrequest
1209 is not specified then this method will return the very
1210 first request from the queue.
1211
1212 If the fileobject is specified then fileobject is also
1213 used as one of the constrain for returing the request.
1214
1215 Important point to remember is that only request information
1216 is returned to the caller. The request is still present in
1217 the queue.
1218
1219 If the request is returned, there is an additional reference
1220 taken on the queue to prevent it from deletion while the
1221 caller is using the request handle. The caller has to
1222 explicitly drop the reference once he is done using the
1223 request handle.
1224
1225Arguments:
1226
1227Returns:
1228
1229 NTSTATUS
1230
1231--*/
1232
1233{
1237 KIRQL irql;
1238
1239 //
1240 // FindRequest is allowed only on a manual queue.
1241 //
1245 "FindRequest is allowed only on a manaul queue 0x%p, %!STATUS!",
1246 GetHandle(), status);
1248 return status;
1249 }
1250
1251 if (TagRequest != NULL) {
1252 status = VerifyPeekRequest(pFxDriverGlobals, TagRequest);
1253 if (!NT_SUCCESS(status)) {
1254 return status;
1255 }
1256 }
1257
1258 //
1259 // Get the next FxRequest from the cancel safe queue
1260 //
1261 // If success, it will return a referenced FxRequest in
1262 // which the caller must release the reference.
1263 //
1264 Lock(&irql);
1265
1267 &m_Queue,
1268 TagRequest,
1269 FileObject,
1270 Parameters,
1271 &pRequest
1272 );
1273
1274 //
1275 // This code address the following potential race condition:
1276 // 1) Queue has only one request (count 1).
1277 // 2) Request in queue is cancelled.
1278 // 3) Request's cancellation logic starts to run on thread 1.
1279 // 4) But before cancellation logic gets the queue's lock
1280 // thread 2 calls WdfIoQueueFindRequest to find any request.
1281 // 5) WdfIoQueueFindRequest returns no more requests.
1282 // Driver waits for the ReadyNotify callback. (count 1)
1283 // 6) Thread 3 adds a new request in queue. (count 1->2)
1284 // 7) Thread 1 finally runs. (count 2->1).
1285 // 8) At this point driver stops responding b/c it never receives ReadyNotify.
1286 //
1287 // This code below forces the queue logic to send a ReadyNotify
1288 // callback the next time a new request is added (in step 6 above).
1289 //
1291 NULL == FileObject && // WdfIoQueueFindRequest(any request)
1292 NULL == TagRequest && // WdfIoQueueFindRequest(any request)
1293 m_Queue.GetRequestCount() > 0L) {
1294
1296 }
1297
1298 Unlock(irql);
1299
1300 if (!NT_SUCCESS(status)) {
1301 return status;
1302 }
1303
1304 //
1305 // Mark it as a tag request to detect abuse since its not
1306 // driver owned.
1307 //
1310 }
1311
1312 // Return it to the driver
1313 *pOutRequest = pRequest;
1314
1315 return status;
1316}
1317
1318SHORT
1319FX_VF_METHOD(FxIoQueue, VerifyForwardRequestUpdateFlags) (
1320 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
1322 )
1323{
1324 UNREFERENCED_PARAMETER(FxDriverGlobals);
1326 KIRQL irql;
1327
1329
1330 Request->Lock(&irql);
1331
1332 // Save old flags to put them back if forward fails
1333 OldFlags = Request->GetVerifierFlagsLocked();
1334
1335 //
1336 // Set that the request was forwarded. This effects
1337 // cancel behavior.
1338 //
1339 Request->SetVerifierFlagsLocked(FXREQUEST_FLAG_FORWARDED);
1340
1341 ASSERT((Request->GetVerifierFlagsLocked() & FXREQUEST_FLAG_DRIVER_OWNED) != 0);
1342
1343 // Set that the request is no longer driver owned
1344 Request->ClearVerifierFlagsLocked(
1346
1347 Request->Unlock(irql);
1348
1349 return OldFlags;
1350}
1351
1357 )
1358{
1360 FxRequestCompletionState oldState;
1363 KIRQL irql;
1364
1365 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
1366
1367 OldFlags = 0;
1368
1369 //
1370 // The request has only one reference, held by the completion
1371 // callback function. We need to take another one before cancelling
1372 // this function, otherwise we will lose the request object
1373 //
1375
1376 //
1377 // Cancel its current completion event for this queue
1378 //
1379 oldState = Request->SetCompletionState(FxRequestCompletionStateNone);
1381
1382 OldFlags = VerifyForwardRequestUpdateFlags(FxDriverGlobals, Request);
1383
1384 //
1385 // Remove it from this queues driver owned list.
1386 //
1387 // This must be done before forward since new queue will
1388 // use the list entry in the FxRequest
1389 //
1390 // We can't use RemoveFromDriverOwnedList since we want the
1391 // m_DriverIoCount to be left alone in case the forward fails.
1392 // If we don't, another thread can run when we drop the lock, notice
1393 // that there are no more requests, and raise the purged and empty
1394 // events. But if the forward fails, the request will wind up back
1395 // on the queue! So m_DriverIoCount is used as a gate to prevent
1396 // these events from firing until we are really sure this queue
1397 // is done with the request.
1398 //
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410 Lock(&irql);
1411 ple = Request->GetListEntry(FxListEntryDriverOwned);
1414 Unlock(irql);
1415
1416 //
1417 // Attempt to pass the request onto the target queue
1418 //
1420 if (!NT_SUCCESS(status)) {
1421
1422 //
1423 // Target queue did not accept the request, so we
1424 // restore the original completion callback function
1425 // and flags
1426 //
1427 oldState = Request->SetCompletionState(oldState);
1429 UNREFERENCED_PARAMETER(oldState);
1430
1431 if (FxDriverGlobals->FxVerifierOn) {
1432 Request->SetVerifierFlags(OldFlags);
1433 }
1434
1435 // Release the extra reference we took
1436 Request->RELEASE(FXREQUEST_STATE_TAG);
1437
1438 Lock(&irql);
1439 // Place it back on the driver owned list
1441 Unlock(irql);
1442 }
1443 else {
1444
1445 Lock(&irql);
1446
1447 // Request is no longer part of the I/O count for this queue
1449
1450 ASSERT(m_DriverIoCount >= 0);
1451
1452 //
1453 // Don't run the event dispatcher if we are called from a
1454 // dispath routine in order to prevent stack recursion.
1455 // Since some other thread (possibly this thread higher on
1456 // the stack) is running the dispatcher, no events will get lost.
1457 //
1458 //
1459 // This returns with the IoQueue lock released
1460 //
1461 DispatchInternalEvents(irql);
1462
1463 //
1464 // We don't dereference the request object since the new IoQueue
1465 // will release it when it is done.
1466 //
1467 }
1468
1469 return status;
1470}
1471
1474FX_VF_METHOD(FxIoQueue, VerifyForwardRequestToParent) (
1475 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
1478 )
1479{
1480 KIRQL irql;
1482
1484
1485 if (m_Device->m_ParentDevice == NULL) {
1488 "No parent device for WDFQUEUE 0x%p Device, %!STATUS!",
1490 FxVerifierDbgBreakPoint(FxDriverGlobals);
1491 goto Done;
1492 }
1493
1494 Request->Lock(&irql);
1495
1496 status = Request->VerifyRequestIsDriverOwned(FxDriverGlobals);
1497
1499 status = Request->VerifyRequestIsNotCancelable(FxDriverGlobals);
1500 }
1501
1502 Request->Unlock(irql);
1503
1505 goto Done;
1506 }
1507
1508 if (DestQueue == this) {
1511 "Cannot forward a request to the same WDFQUEUE 0x%p"
1512 " %!STATUS!", GetObjectHandle(), status);
1513 FxVerifierDbgBreakPoint(FxDriverGlobals);
1514 goto Done;
1515 }
1516
1517 if (m_Device->m_ParentDevice != DestQueue->m_Device) {
1520 "Cannot forward a request to "
1521 "a different WDFDEVICE 0x%p which is not the "
1522 "parent, %!STATUS!",
1524 status);
1525 FxVerifierDbgBreakPoint(FxDriverGlobals);
1526 goto Done;
1527 }
1528
1529 if (Request->IsReserved()) {
1532 "Cannot forward reserved WDFREQUEST 0x%p to a "
1533 "parent WDFDEVICE 0x%p, %!STATUS!",
1534 Request->GetHandle(),
1536 status);
1537 FxVerifierDbgBreakPoint(FxDriverGlobals);
1538 goto Done;
1539 }
1540
1541 //
1542 // Make sure the child device is a PDO
1543 //
1544 ASSERT(m_Device->IsPdo());
1545
1546 //
1547 // Check if the WdfPdoInitSetForwardRequestToParent was called to increase
1548 // the StackSize of the child Device to include the stack size of the
1549 // parent Device
1550 //
1551 if (m_Device->IsPnp()
1552 &&
1553 m_Device->GetPdoPkg()->m_AllowForwardRequestToParent == FALSE) {
1556 "WdfPdoInitSetForwardRequestToParent not called on "
1557 "WDFDEVICE 0x%p, %!STATUS!", m_Device->GetHandle(),
1558 status);
1559 FxVerifierDbgBreakPoint(FxDriverGlobals);
1560 goto Done;
1561 }
1562
1563Done:
1564 return status;
1565}
1566
1573 )
1574
1575/*++
1576
1577Routine Description:
1578
1579 ForwardRequest is called from the drivers EvtIoDefault routine
1580 and the following conditions apply:
1581
1582 Request is not on a CSQ and not cancellable
1583
1584 Request is FXREQUEST_FLAG_DRIVER_OWNED
1585
1586 m_DriverIoCount has been incremented to reflect the request
1587
1588 Request has an I/O completion callback function pointing to
1589 FxIoQueueRequestComplete with the context for this Queue
1590
1591 The Request has one reference count from the I/O completion callback.
1592
1593 If a driver calls this API, it will not complete the request
1594 as a result of this queues EvtIoDefault, and does not own
1595 the request until it has been re-presented by the Destination
1596 Queue.
1597
1598Arguments:
1599
1600Returns:
1601
1602 NTSTATUS
1603
1604--*/
1605{
1608 BOOLEAN forwardRequestToParent;
1609 FxIrp* pIrp;
1610
1612
1614
1615 forwardRequestToParent = Request->m_ForwardRequestToParent;
1616
1617 status = VerifyForwardRequestToParent(pFxDriverGlobals,
1618 DestQueue,
1619 Request);
1620 if(!NT_SUCCESS(status)){
1621 return status;
1622 }
1623
1624 pIrp = Request->GetFxIrp();
1625
1628
1629 //
1630 // Save a pointer to the device object for this request so that it can
1631 // be used later in completion.
1632 //
1634
1635 Request->SetDeviceBase((CfxDeviceBase *)m_Device->m_ParentDevice);
1636 Request->m_ForwardRequestToParent = TRUE;
1637
1639
1640 //
1641 // Undo the actions of changing the FxDevice and
1642 // changing the deviceObject and stack location in the IRP
1643 //
1644 if (!NT_SUCCESS(status)) {
1645 Request->SetDeviceBase((CfxDeviceBase *)m_Device);
1646 pIrp = Request->GetFxIrp();
1649
1650 //
1651 // Set the value of m_ForwardRequestToParent to the previous
1652 // value so that if the Request has been forwarded to Parent
1653 // successfully but fails to be forwarded to the grandparent
1654 // from the parent then we free it back using ExFreePool
1655 // instead of the Lookaside buffer .
1656 //
1657 Request->m_ForwardRequestToParent = forwardRequestToParent;
1658 }
1659
1660 return status;
1661}
1662
1665FX_VF_METHOD(FxIoQueue, VerifyForwardRequest) (
1666 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
1669 )
1670{
1672 KIRQL irql;
1673
1675
1676 pRequest->Lock(&irql);
1677
1678 status = pRequest->VerifyRequestIsDriverOwned(FxDriverGlobals);
1679 if (NT_SUCCESS(status)) {
1680 status = pRequest->VerifyRequestIsNotCancelable(FxDriverGlobals);
1681 }
1682
1683 pRequest->Unlock(irql);
1684
1685 if (!NT_SUCCESS(status)) {
1686 return status;
1687 }
1688
1689 if (pDestQueue == this) {
1691 "Cannot forward a request to the same WDFQUEUE 0x%p"
1692 " %!STATUS!",
1695 FxVerifierDbgBreakPoint(FxDriverGlobals);
1697 }
1698
1699 if ((m_Device != pDestQueue->m_Device)) {
1701 "Cannot forward a request to a different WDFDEVICE 0x%p",
1703 FxVerifierDbgBreakPoint(FxDriverGlobals);
1705 }
1706
1707 return status;
1708}
1709
1715 )
1716/*++
1717
1718Routine Description:
1719
1720 ForwardRequest is called from the drivers EvtIoDefault routine
1721 and the following conditions apply:
1722
1723 Request is not on a CSQ and not cancellable
1724
1725 Request is FXREQUEST_FLAG_DRIVER_OWNED
1726
1727 m_DriverIoCount has been incremented to reflect the request
1728
1729 Request has an I/O completion callback function pointing to
1730 FxIoQueueRequestComplete with the context for this Queue
1731
1732 The Request has one reference count from the I/O completion callback.
1733
1734 If a driver calls this API, it will not complete the request
1735 as a result of this queues EvtIoDefault, and does not own
1736 the request until it has been re-presented by the Destination
1737 Queue.
1738
1739Arguments:
1740
1741Returns:
1742
1743 NTSTATUS
1744
1745--*/
1746{
1748
1749 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
1750
1751 status = VerifyForwardRequest(FxDriverGlobals, pDestQueue, pRequest);
1752 if (!NT_SUCCESS(status)) {
1753 return status;
1754 }
1755
1757 return status;
1758}
1759
1762FX_VF_METHOD(FxIoQueue, VerifyQueueDriverCreatedRequest) (
1763 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
1766 )
1767{
1769 KIRQL irql;
1770
1772
1773 Request->Lock(&irql);
1774
1775 *OldFlags = Request->GetVerifierFlagsLocked();
1777
1778 status = Request->VerifyRequestIsNotCancelable(FxDriverGlobals);
1779 if (NT_SUCCESS(status)) {
1780 // Clear the driver owned flag.
1782 Request->ClearVerifierFlagsLocked(FXREQUEST_FLAG_DRIVER_OWNED);
1783 }
1784
1785 Request->Unlock(irql);
1786 return status;
1787}
1788
1793 __in BOOLEAN ParentQueue
1794 )
1795/*++
1796
1797Routine Description:
1798
1799 Insert a driver-created-request into this queue.
1800 The following conditions apply:
1801
1802 Request is not on a CSQ and not cancellable.
1803
1804 Request doesn't have the FXREQUEST_FLAG_DRIVER_OWNED set yet.
1805
1806 Request doesn't have an I/O completion callback function pointing to
1807 FxIoQueueRequestComplete since the original queue is NULL.
1808
1809 The Request has one reference count from WdfRequestCreate[FromIrp].
1810
1811 On a successful return, the request is owned by the queue. Driver can complete
1812 this request only after it has been re-presented to the driver.
1813
1814Arguments:
1815
1816 Request - Driver created request (already validated by public API) to
1817 insert in queue.
1818
1819 ParentQueue - TRUE if the queue is owned by the parent device.
1820
1821Returns:
1822
1823 NTSTATUS
1824
1825--*/
1826{
1828 CfxDeviceBase * origDeviceBase;
1829 SHORT oldFlags = 0;
1830 FxIrp* fxIrp;
1831
1833 fxIrp = Request->GetFxIrp();
1834
1835 status = VerifyQueueDriverCreatedRequest(fxDriverGlobals, Request, &oldFlags);
1836 if(!NT_SUCCESS(status)) {
1837 return status;
1838 }
1839
1840 ASSERT(Request->SetCompletionState(FxRequestCompletionStateNone) ==
1842
1843 //
1844 // If this is the parent queue, we need to adjust the IRP's stack.
1845 //
1846 if (ParentQueue) {
1847
1848 //
1849 // IRP should not have a completion routine set yet.
1850 //
1851
1853
1856
1857 //
1858 // Save a pointer to the device object for this request so that it can
1859 // be used later in completion.
1860 //
1862 }
1863
1864 origDeviceBase = Request->GetDeviceBase();
1866
1867 //
1868 // Attempt to insert the request into the queue
1869 //
1871 if (!NT_SUCCESS(status)) {
1872 //
1873 // Request was not accepted, restore the original DeviceBase and flags.
1874 //
1875 ASSERT(Request->SetCompletionState(FxRequestCompletionStateNone) ==
1877
1878 //
1879 // Restore original device/info.
1880 //
1881 Request->SetDeviceBase(origDeviceBase);
1882
1884 Request->SetVerifierFlags(oldFlags);
1885 }
1886
1887 //
1888 // If this is the parent queue, we need to adjust the IRP's stack.
1889 //
1890 if (ParentQueue) {
1892 //
1893 // There is no completion routine. See above assert.
1894 //
1895 Request->m_Irp.ClearNextStack();
1896 }
1897 }
1898
1899 return status;
1900}
1901
1904FX_VF_METHOD(FxIoQueue, VerifyRequeue) (
1905 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
1907 )
1908{
1910 KIRQL irql;
1911
1913
1914 pRequest->Lock(&irql);
1915
1916 status = pRequest->VerifyRequestIsDriverOwned(FxDriverGlobals);
1917 if (NT_SUCCESS(status)) {
1918 status = pRequest->VerifyRequestIsNotCancelable(FxDriverGlobals);
1919 }
1920
1921 if (NT_SUCCESS(status)) {
1922 pRequest->ClearVerifierFlagsLocked(FXREQUEST_FLAG_DRIVER_OWNED |
1924 }
1925 pRequest->Unlock(irql);
1926
1927 return status;
1928}
1929
1930
1935 )
1936{
1938 FxRequestCompletionState oldState;
1939 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
1940 KIRQL irql;
1941
1942 status = VerifyRequeue(FxDriverGlobals, pRequest);
1943 if (!NT_SUCCESS(status)) {
1944 return status;
1945 }
1946
1947 //
1948 // Requeue is allowed only on Manual queue.
1949 //
1951
1953 "Requeue is allowed only for "
1954 "a manual queue, WDFREQUEST 0x%p "
1955 "%!STATUS!",
1956 pRequest,
1958 FxVerifierDbgBreakPoint(FxDriverGlobals);
1960 }
1961
1962 //
1963 // The request has only one reference, held by the completion
1964 // callback function. We need to take another one before cancelling
1965 // this function, otherwise we will lose the request object
1966 //
1968
1969 // Cancel the request complete callback (deletes a reference)
1972 UNREFERENCED_PARAMETER(oldState);
1973
1974 Lock(&irql);
1975
1976 //
1977 // We are going to place the request back on the queue
1978 //
1979
1980
1981 // Driver did not accept the I/O
1983
1985 "WDFREQUEST 0x%p", pRequest->GetHandle());
1986
1987 //
1988 // Check if we need to delete this request.
1989 //
1991 //
1992 // Do not requeue this request.
1993 //
1995 }
1996 else {
1997 //
1998 // Place the request back at the head of the main queue
1999 // so as not to re-order requests
2000 //
2002 }
2003
2004 if (!NT_SUCCESS(status)) {
2005
2006 // Request did not get placed in queue
2008 //
2009 // Let the caller think the request is requeued successfully
2010 // because this is no different from the request cancelling
2011 // while it's in the queue. By returning STATUS_CANCELLED
2012 // the caller can't take any recovery action anyways
2013 // because the request is gone.
2014 //
2016
2017 //
2018 // We must add a reference since the CancelForQueue path
2019 // assumes we were on the FxIrpQueue with the extra reference
2020 //
2022
2023 //
2024 // Mark the request as cancelled, place it on the cancel list,
2025 // and schedule the cancel event to the driver
2026 //
2027 CancelForQueue(pRequest, irql);
2028
2029 Lock(&irql);
2030 }
2031 else {
2032 // Check if went from no requests to have requests
2034 }
2035
2036 //
2037 // Visit the DispatchEvent so that we can deliver EvtIoReadyNotify
2038 //
2039 DispatchEvents(irql);
2040
2041 return status;
2042}
2043
2046FX_VF_METHOD(FxIoQueue, VerifyRequestCancelable) (
2047 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
2050 )
2051{
2053 KIRQL irql;
2054
2056
2057 pRequest->Lock(&irql);
2058
2059 // Make sure the driver owns the request
2060 status = pRequest->VerifyRequestIsDriverOwned(FxDriverGlobals);
2061 if (!NT_SUCCESS(status)) {
2062 goto Done;
2063 }
2064
2066 //
2067 // Make sure the request is not cancelable for it to be made
2068 // cancelable.
2069 //
2070 status = pRequest->VerifyRequestIsNotCancelable(FxDriverGlobals);
2071 if (!NT_SUCCESS(status)) {
2072 goto Done;
2073 }
2074 }
2075 else {
2076 //
2077 // Make sure the request is cancelable for it to be made
2078 // uncancelable.
2079 //
2080 status = pRequest->VerifyRequestIsCancelable(FxDriverGlobals);
2081 if (!NT_SUCCESS(status)) {
2082 goto Done;
2083 }
2084 }
2085
2086Done:
2087 pRequest->Unlock(irql);
2088 return status;
2089}
2090
2097 __in BOOLEAN FailIfIrpIsCancelled
2098 )
2099/*++
2100
2101 Routine Description:
2102
2103 This is called to mark or unmark the request cancelable.
2104
2105 Arguments:
2106
2107 FxRequest* - Request that is completing
2108
2109 Cancelable - if TRUE, mark the request cancellable
2110 if FALSE, mark the request not cancelable
2111 if it's previously marked canceelable.
2112
2113 EvtRequestCancel - points to driver provided cancel routine
2114 if the cancelable flag is TRUE.
2115
2116 FailIfIrpIsCancelled - if FALSE and the IRP is already cancelled,
2117 call the provided cancel routine and
2118 return success.
2119 if TRUE and the IRP is already cancelled,
2120 return STATUS_CANCELLED.
2121
2122 Returns:
2123
2124 NTSTATUS
2125
2126--*/
2127{
2129 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
2130 KIRQL irql;
2131
2132 status = VerifyRequestCancelable(FxDriverGlobals, pRequest, Cancelable);
2133 if(!NT_SUCCESS(status)) {
2134 return status;
2135 }
2136
2137 if (Cancelable) {
2138
2139 if (FxDriverGlobals->FxVerifierOn) {
2141 }
2142 //
2143 // Set the Request for cancel status by inserting in the driver owned
2144 // CSQ. Note: This could fire the cancel callback right away
2145 // if the IRP was already cancelled.
2146 //
2147
2149
2150 Lock(&irql);
2151
2153
2154 //
2155 // Check if we need to delete this request.
2156 //
2158 //
2159 // Purge is in progress, cancel this request.
2160 //
2162 }
2163 else {
2165 }
2166
2167 if (NT_SUCCESS(status)) {
2168 Unlock(irql);
2169 }
2170 else if (FailIfIrpIsCancelled == FALSE) {
2171
2173
2174 // This is not an error to the driver
2176
2178
2179 Unlock(irql);
2180
2181 //
2182 // We must add a reference since the CancelForDriver path
2183 // assumes we were on the FxIrpQueue with the extra reference
2184 //
2186
2187 //
2188 // Mark the request as cancelled, place it on the cancel list,
2189 // and schedule the cancel event to the driver
2190 //
2192 }
2193 else {
2194
2196
2198
2199 //
2200 // Let the caller complete the request with STATUS_CANCELLED.
2201 //
2202 Unlock(irql);
2203
2204 if (FxDriverGlobals->FxVerifierOn) {
2206 }
2207 }
2208
2209 return status;
2210 }
2211 else {
2212 //
2213 // This can return STATUS_CANCELLED if the request
2214 // has been canceled already
2215 //
2216 Lock(&irql);
2218
2219 if (NT_SUCCESS(status)) {
2221 }
2222 else {
2223 //
2224 // In the failure case, the cancel routine has won the race and will
2225 // be invoked on another thread.
2226 //
2227 DO_NOTHING();
2228 }
2229 Unlock(irql);
2230
2231 if (FxDriverGlobals->FxVerifierOn) {
2232
2233 // We got the request back, can clear the cancelable flag
2234 if (NT_SUCCESS(status)) {
2236 }
2237 }
2238
2239 return status;
2240 }
2241}
2242
2247 )
2248
2249/*++
2250
2251 Routine Description:
2252
2253 Enqueue a request to the end of the queue.
2254
2255 Note: This routine owns the final disposition of
2256 the Request object, and must handle it and
2257 dereference even if the driver does not.
2258
2259 Arguments:
2260
2261 pRequest - Pointer to Request object
2262
2263 Returns:
2264
2265 NTSTATUS
2266--*/
2267
2268{
2270 KIRQL irql;
2271 MdIrp pIrp;
2272 FxIrp* pFxIrp;
2273
2274 // Get IoQueue Object Lock
2275 Lock(&irql);
2276
2277 ASSERT(pRequest->GetRefCnt() == 1);
2278
2279 //
2280 // If the request is reserved, take an additional reference. This reference
2281 // will be released when the request is completed. This additional reference
2282 // enables us to detect 2 to 1 transition in the completion path so that
2283 // we can reclaim the reserved request for reuse.
2284 //
2285 if (pRequest->IsReserved()) {
2287 }
2288
2289 //
2290 // If queue is not taking new requests, fail now
2291 //
2293
2295 "WDFQUEUE 0x%p is not accepting requests, "
2296 "state is %!WDF_IO_QUEUE_STATE!, %s"
2297 "completing WDFREQUEST 0x%p %!STATUS!",
2300 "power stopping (Drain) in progress," : "",
2303
2304 // Must release IoQueue object Lock
2305 Unlock(irql);
2306
2308
2309 // Complete it with error
2311
2312 // Dereference request object
2314
2315 return Status;
2316 }
2317
2319 "Queuing WDFREQUEST 0x%p on WDFQUEUE 0x%p",
2321
2323
2324 pFxIrp = pRequest->GetFxIrp();
2325
2326 pFxIrp->MarkIrpPending();
2327
2328 //
2329 // If the request is reserved, we may be called to dispatch
2330 // a pending reserved IRP from within the context of the completion routine.
2331 // So to avoid recursion, we will insert the request in the queue and try
2332 // to dispatch in the return path. If the request is not reserved then we
2333 // will dispatch it directly because this path is meant for dispatching new
2334 // incoming I/O. There is no concern for running into recursion in that
2335 // scenario.
2336 //
2337 if (pRequest->IsReserved() && m_Dispatching != 0) {
2339 Unlock(irql);
2340 }
2341 else {
2342 DispatchEvents(irql, pRequest);
2343 }
2344
2345 // We always return status pending through the frameworks
2346 return STATUS_PENDING;
2347}
2348
2353 )
2354
2355/*++
2356
2357 Routine Description:
2358
2359 Enqueue a request to the end of the queue.
2360
2361 This is an internal version that does not fail
2362 the request if it can not be enqueued.
2363
2364 Arguments:
2365
2366 pRequest - Pointer to Request object
2367
2368 Returns:
2369
2370 STATUS_SUCCESS on success
2371--*/
2372
2373{
2375 KIRQL irql;
2376 BOOLEAN fromIo;
2377
2378 // Get IoQueue Object Lock
2379 Lock(&irql);
2380
2381 //
2382 // If queue is not taking new requests, fail now
2383 //
2385
2387
2389 "WDFQUEUE 0x%p is not accepting requests "
2390 "state is %!WDF_IO_QUEUE_STATE!, %s"
2391 "WDFREQUEST 0x%p %!STATUS!",
2394 "power stopping (Drain) in progress," : "",
2396
2397 Unlock(irql);
2398
2399 return status;
2400 }
2401#if FX_VERBOSE_TRACE
2403 "Queuing WDFREQUEST 0x%p on WDFQUEUE 0x%p",
2405#endif
2406 //
2407 // The Request has one reference count, and no completion
2408 // callback function. It has been completely removed from
2409 // its previous queue.
2410 //
2411
2412 //
2413 // Cache this info b/c the request can be delete and freed by the time we use it.
2414 //
2415 fromIo = pRequest->IsAllocatedFromIo();
2416
2417 //
2418 // Insert it in the Cancel Safe Queue
2419 //
2420 // This will mark the IRP pending
2421 //
2423
2424 if (!NT_SUCCESS(status)) {
2425
2427
2429
2430 //
2431 // We must add a reference since the CancelForQueue path
2432 // assumes we were on the FxIrpQueue with the extra reference
2433 //
2435
2436 //
2437 // Mark the request as cancelled, place it on the cancel list,
2438 // and schedule the cancel event to the driver
2439 //
2440 CancelForQueue(pRequest, irql);
2441
2442 Lock(&irql);
2443 }
2444 else {
2446
2447 // Check if went from no requests to have requests
2449 }
2450
2451 //
2452 // If the request is driver-created, we may be called to dispatch
2453 // a request from within the context of the completion routine.
2454 // So to avoid recursion, we will try to dispatch in the return path.
2455 // If the request is not driver-created then we will dispatch it directly because
2456 // this path is meant for dispatching new incoming I/O. There is no concern for
2457 // running into recursion in that scenario.
2458 //
2459 if (fromIo == FALSE && m_Dispatching != 0) {
2460 Unlock(irql);
2461 }
2462 else {
2463 //
2464 // Attempt to dispatch any new requests.
2465 //
2466 // This releases, and re-acquires the IoQueue lock
2467 //
2468 DispatchEvents(irql);
2469 }
2470
2471 return STATUS_SUCCESS;
2472}
2473
2474VOID
2476 )
2477
2478/*++
2479
2480 Routine Description:
2481
2482 Dispatch requests from the queue to the driver
2483 from within the m_Dpc
2484
2485 Arguments:
2486
2487 Returns:
2488
2489--*/
2490
2491{
2492 KIRQL irql;
2493
2494 Lock(&irql);
2495
2497
2499
2500 DispatchEvents(irql);
2501
2502 //
2503 // DispatchEvents drops the lock before returning. So reacquire the lock.
2504 //
2505 Lock(&irql);
2506
2509 } else {
2512 }
2513
2514 Unlock(irql);
2515
2516 return;
2517}
2518
2519VOID
2521 )
2522
2523/*++
2524
2525 Routine Description:
2526
2527 Dispatch requests from the queue to the driver
2528 from within the m_WorkItem.
2529
2530 Arguments:
2531
2532 Returns:
2533
2534--*/
2535
2536{
2537 KIRQL irql;
2538
2539 Lock(&irql);
2540
2542
2544
2545 DispatchEvents(irql);
2546
2547 //
2548 // DispatchEvents drops the lock before returning. So reacquire
2549 // the lock.
2550 //
2551 Lock(&irql);
2552
2553 if (m_Deleted == FALSE &&
2556 //
2557 // Workitem is queued.
2558 //
2559 DO_NOTHING();
2560 } else {
2563 }
2564
2565 Unlock(irql);
2566
2567 return;
2568}
2569
2573 __in KIRQL PreviousIrql
2574 )
2575/*++
2576
2577 Routine Description:
2578
2579 Purpose of this function is to insert the request that's dispatched
2580 by the IoPkg into FxIrpQueue. This function has been added to improve
2581 the performance of queueing logic. Prior to version 1.7, when a
2582 request is dispatched to a queue, it was first inserted into queue,
2583 various checks for the readiness of queue made, and then the request
2584 is removed from the queue to be presented to the driver.
2585
2586 To improve the I/O performance, dispatching logic has been changed
2587 such that the request will not be inserted into the queue if the queue
2588 is ready to dispatch the request. If the queue is not ready or if there
2589 are other events to be dispatched before dispatching the new incoming request,
2590 we will queue the request first using this function before releasing the lock
2591 so that we don't change the ordering of requests in the queue.
2592
2593--*/
2594{
2596
2597 status = (*Request)->InsertTailIrpQueue(&m_Queue, NULL);
2598
2599 if (!NT_SUCCESS(status)) {
2600 //
2601 // Request was never presented to the driver
2602 // so there is no need to call CancelForQueue
2603 // in this case.
2604 //
2606
2608
2609 (*Request)->CompleteWithInformation(status, 0);
2610
2611 (*Request)->RELEASE(FXREQUEST_COMPLETE_TAG);
2612
2614 }
2615 else {
2616 (*Request)->SetCurrentQueue(this);
2617
2618 // Check if went from no requests to have requests
2620 }
2621
2622 //
2623 // Request is either inserted into the queue or completed. Clear
2624 // the field to prevent touching the request.
2625 //
2626 *Request = NULL;
2627
2628 return status;
2629}
2630
2632BOOLEAN
2634 __in KIRQL PreviousIrql
2635 )
2636/*++
2637
2638 Routine Description:
2639
2640 Dispatch events and requests from the queue to the driver.
2641
2642 The IoQueue object lock must be held on entry. This routine
2643 should not drop and reacquire the lock to ensure the request
2644 is not queued out of order.
2645
2646 Returns:
2647
2648 TRUE - if the thread meets all the sychronization and
2649 execution contraints to dispatch the events.
2650 FALSE - if the dispatching of events to be defered to
2651 another thread - either DPC or workitem.
2652--*/
2653{
2654 //
2655 // If the current irql is not at passive-level and the queue is configured
2656 // to receive events only at passive-level then we should queue a
2657 // workitem to defer the processing.
2658 //
2662 "Current thread 0x%p is not at the passive-level"
2663 " %!irql!, posting to worker thread for WDFQUEUE"
2664 " 0x%p",
2667 GetObjectHandle());
2668 //
2669 // We only need to post this once
2670 //
2671 if (m_WorkItemQueued == FALSE) {
2672
2674
2676 ASSERT(FALSE);
2678 }
2679 }
2680
2681 return FALSE;
2682 }
2683
2684 //
2685 // If the current thread is holding the presentation lock, we
2686 // must defer to a DPC or work item.
2687 // This is the result of the device driver calling
2688 // WdfRequestForwardToIoQueue, or WdfIoQueueStart/Stop from
2689 // within I/O dispatch handler. This can also occur if a driver
2690 // attempts to forward a request among a circular series of Queues
2691 // that are configured to have locking constraints.
2692 //
2694
2696 "Presentation lock for WDFQUEUE 0x%p is "
2697 "already held, deferring to dpc or workitem",
2698 GetObjectHandle());
2699
2700 if (m_PassiveLevel) {
2701
2702 if(m_WorkItemQueued == FALSE) {
2703
2705
2707 ASSERT(FALSE);
2709 }
2710 }
2711 }
2712 else {
2713 //
2714 // We only need to post this once
2715 //
2716 if (m_DpcQueued == FALSE) {
2717
2718 m_DpcQueued = TRUE;
2719
2721 }
2722 }
2723
2724 return FALSE;
2725 }
2726
2727 return TRUE;
2728}
2729
2730_Releases_lock_(this->m_SpinLock.m_Lock)
2732BOOLEAN
2733FxIoQueue::DispatchEvents(
2734 __in __drv_restoresIRQL KIRQL PreviousIrql,
2735 __in_opt FxRequest* NewRequest
2736 )
2737/*++
2738
2739 Routine Description:
2740
2741 Dispatch events and requests from the queue to the driver.
2742
2743 The IoQueue object lock must be held on entry, but this routine can release
2744 and re-acquire the lock multiple times while processing.
2745
2746 It returns to the caller with the lock released, but queue state may have
2747 changed.
2748
2749 The main processing loop checks for various Queue state change events
2750 delivering them to the driver, and then finally any WDFREQUEST objects
2751 that are pending in the Queue.
2752
2753 The design also handles the recursive case with the m_Dispatching
2754 field so that a driver that completes requests from within the
2755 callback does not cause a stack or lock recursion.
2756
2757 All event callbacks to the device driver are provided though the
2758 FxCallback object which manages lock acquire and release as required
2759 by the locking model.
2760
2761 In addition these may be passive or dispatch level locks.
2762 If configured for passive level callbacks,
2763 must defer to a work item if current thread is DISPATCH_LEVEL
2764 when not owning the current FxIoQueue lock
2765
2766 Arguments:
2767
2768 NewRequest - This is a new incoming request from the driver above.
2769 It will be either presented to the driver or saved into
2770 a queue if the conditions are not right to dispatch.
2771
2772 Returns:
2773
2774 FALSE if the queue is in a deleted state else TRUE.
2775 Caller should check for return value only if it's waiting
2776 on the some events to be invoked by this call.
2777
2778--*/
2779{
2781 ULONG totalIoCount;
2783 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
2784
2785 if (m_Deleted) {
2786 ASSERT(NewRequest == NULL);
2787 Unlock(PreviousIrql);
2788 return FALSE;
2789 }
2790
2791 //
2792 // The design of the I/O Queue allows all "events" to notify the driver of
2793 // to be deferred until the opportune time to deliver them.
2794 // Depending on the drivers configured locking and threading
2795 // mode, this may have to be deferred to a worker thread or a DPC
2796 // to be in a compatible IRQL level, or to prevent a lock recursion
2797 // when a parent objects lock is in effect.
2798 //
2799
2800 if (CanThreadDispatchEventsLocked(PreviousIrql) == FALSE) {
2801 //
2802 // Previous workitem or Dpc might be running the DispatchEvents right now.
2803 // But it may be at a point where it might miss out to process the event
2804 // that we have been asked to dispatch. This is possible because the
2805 // DispatchEvent is reentrant as it acquires and drops lock along
2806 // the way. So we make a note of this, so that when the current Dpc or
2807 // workItem runs to completion, it will requeue itself to handle our message.
2808 //
2809 m_RequeueDeferredDispatcher = TRUE;
2810
2811 //
2812 // Queue the request in to FxIrpQueue and return.
2813 //
2814 InsertNewRequest(&NewRequest, PreviousIrql);
2815 Unlock(PreviousIrql);
2816 return TRUE;
2817 }
2818
2819 //
2820 // This must be incremented before attempting to deliver any
2821 // events to the driver. This prevents recursion on the presentation lock,
2822 // and limits the stack depth in a Start/Complete/Start/... recursion
2823 //
2824 m_Dispatching++;
2825
2827 "Thread %p is processing WDFQUEUE 0x%p",
2829
2830 //
2831 // At this point all constaints such as IRQL level, locks held,
2832 // and stack recursion protection has been satisfied, and we can
2833 // make callbacks into the device driver.
2834 //
2835 // Process events and requests until we either have an empty queue,
2836 // the driver stops taking requests, or some queue state does not
2837 // allow the driver to take new requests
2838 //
2839 #pragma warning(disable:4127)
2840 while (TRUE) {
2841 #pragma warning(default:4127)
2842 //
2843 // totoalIoCount is sum of requests pending in the queue and requests
2844 // currently owned by the driver.
2845 //
2846 totalIoCount = m_Queue.GetRequestCount() + m_DriverIoCount;
2847
2848 //
2849 // Increment the count if there is a new request to be dispatched.
2850 //
2851 totalIoCount += ((NewRequest != NULL) ? 1 : 0);
2852
2853 if (!IsListEmpty(&this->m_Cancelled)) {
2854 status = InsertNewRequest(&NewRequest, PreviousIrql);
2855 if (!NT_SUCCESS(status)) {
2856 continue; // totalIoCount may be zero now.
2857 }
2858
2859 //
2860 // This can drop and re-acquire the queue lock
2861 // ProcessCancelledRequests returns FALSE if the queue is
2862 // notifying driver about power state changes.
2863 //
2864 if(ProcessCancelledRequests(&PreviousIrql)) {
2865 continue;
2866 }
2867 }
2868
2869 if (!IsListEmpty(&this->m_CanceledOnQueueList)) {
2870 status = InsertNewRequest(&NewRequest, PreviousIrql);
2871 if (!NT_SUCCESS(status)) {
2872 continue; // totalIoCount may be zero now.
2873 }
2874
2875 //
2876 // This can drop and re-acquire the queue lock
2877 // ProcessCancelledRequests returns FALSE if the queue is
2878 // notifying driver about power state changes.
2879 //
2880 if (ProcessCancelledRequestsOnQueue(&PreviousIrql)) {
2881 continue;
2882 }
2883 }
2884
2885 if (m_IdleComplete.Method != NULL &&
2886 m_Dispatching == 1L &&
2887 m_DriverIoCount == 0L) {
2888
2889 InsertNewRequest(&NewRequest, PreviousIrql);
2890
2891 // no more driver owned requests, we can clear the following flag:
2892 m_CancelDispatchedRequests = FALSE;
2893
2894 // This can drop and re-acquire the queue lock
2895 ProcessIdleComplete(&PreviousIrql);
2896 continue;
2897 }
2898
2899 if (m_PurgeComplete.Method != NULL &&
2900 totalIoCount == 0L &&
2901 m_Dispatching == 1L) {
2902
2903 InsertNewRequest(&NewRequest, PreviousIrql);
2904
2905 // no more driver owned requests, we can clear the following flag:
2906 m_CancelDispatchedRequests = FALSE;
2907
2908 // This can drop and re-acquire the queue lock
2909 ProcessPurgeComplete(&PreviousIrql);
2910 continue;
2911 }
2912
2913 if (m_IsDevicePowerPolicyOwner &&
2914 m_PowerManaged &&
2915 m_PowerReferenced &&
2916 totalIoCount == 0L &&
2917 m_Dispatching == 1L) {
2918
2919 //
2920 // Queue has no requests, and is going idle. Notify
2921 // PNP/Power.
2922 //
2923 m_Device->m_PkgPnp->PowerDereference();
2924 m_PowerReferenced = FALSE;
2925 continue;
2926 }
2927
2928 //
2929 // Look for power state transitions
2930 //
2931 if (m_PowerState != FxIoQueuePowerOn &&
2932 m_PowerState != FxIoQueuePowerOff) {
2933
2935 "WDFQUEUE 0x%p Power Transition State "
2936 "%!FxIoQueuePowerState!", GetObjectHandle(),
2937 m_PowerState);
2938
2939 status = InsertNewRequest(&NewRequest, PreviousIrql);
2940 if (!NT_SUCCESS(status)) {
2941 continue; // totalIoCount may be zero now.
2942 }
2943
2944 // Process intermediate power state
2945 // This can drop and re-acquire the queue lock
2946 if (ProcessPowerEvents(&PreviousIrql)) {
2947 continue;
2948 }
2949 else {
2950
2951 //
2952 // Return, awaiting some response from the driver
2953 //
2954 goto Done;
2955 }
2956 }
2957 else {
2958 // Queue is either in PowerOn or PowerOff state
2959 DO_NOTHING();
2960 }
2961
2962 //
2963 // Check for queue disposing should be made after processing all
2964 // the events.
2965 //
2966 if (m_Disposing &&
2967 totalIoCount == 0L &&
2968 m_Dispatching == 1L) {
2969
2970 m_Deleted = TRUE;
2971
2972 //
2973 // After this point, no other thread will be able to dispatch
2974 // events from this queue. Also threads that are about to call
2975 // this function as soon as we drop the lock below should have
2976 // a reference on the queue to prevent queue object from being
2977 // freed when we signal the dispose thread to run through.
2978 //
2979 Unlock(PreviousIrql);
2980
2981 m_FinishDisposing.Set();
2982 return TRUE;
2983 }
2984
2985
2986 //
2987 // Return if power is off, can't deliver any request oriented events
2988 // to the driver.
2989 //
2990 if (m_PowerState == FxIoQueuePowerOff) {
2991 status = InsertNewRequest(&NewRequest, PreviousIrql);
2992 if (!NT_SUCCESS(status)) {
2993 continue; // totalIoCount may be zero now.
2994 }
2995
2996 goto Done;
2997 }
2998
2999 //
3000 // See if the queue is (still) processing requests
3001 //
3002 if (!IsState(WdfIoQueueDispatchRequests)) {
3003
3005 "WDFQUEUE 0x%p not in dispatching state, "
3006 "current state is %!WDF_IO_QUEUE_STATE!",
3007 GetObjectHandle(), m_QueueState);
3008
3009 status = InsertNewRequest(&NewRequest, PreviousIrql);
3010 if (!NT_SUCCESS(status)) {
3011 continue; // totalIoCount may be zero now.
3012 }
3013
3014 goto Done;
3015 }
3016
3017 //
3018 // A manual dispatch queue can have a request ready notification
3019 //
3020 if (m_Type == WdfIoQueueDispatchManual) {
3021
3022 status = InsertNewRequest(&NewRequest, PreviousIrql);
3023 if (!NT_SUCCESS(status)) {
3024 continue; // totalIoCount may be zero now.
3025 }
3026
3027 if (m_ReadyNotify.Method != NULL && m_TransitionFromEmpty) {
3028
3029 // This can drop and re-acquire the lock to callback to the driver
3030 ProcessReadyNotify(&PreviousIrql);
3031 continue;
3032 }
3033
3034 goto Done;
3035 }
3036
3037 if (m_Type == WdfIoQueueDispatchSequential && m_DriverIoCount > 0) {
3038 status = InsertNewRequest(&NewRequest, PreviousIrql);
3039 if (!NT_SUCCESS(status)) {
3040 continue; // totalIoCount may be zero now.
3041 }
3042
3043 goto Done;
3044 }
3045
3046 //
3047 // For counted Queue's dont dispatch request to driver if the
3048 // m_DriverIoCount exceeds the one set by the driver writer.
3049 //
3050 if (m_Type == WdfIoQueueDispatchParallel &&
3051 (ULONG)m_DriverIoCount >= m_MaxParallelQueuePresentedRequests) {
3052 status = InsertNewRequest(&NewRequest, PreviousIrql);
3053 if (!NT_SUCCESS(status)) {
3054 continue; // totalIoCount may be zero now.
3055 }
3056
3057 goto Done;
3058 }
3059
3060 //
3061 // If there is a request in the queue, then retrieve that.
3062 //
3063 pRequest = NULL;
3064 if (m_Queue.GetRequestCount() > 0L) {
3066 }
3067
3068 //
3069 // The request from the queue should be dispatched first
3070 // to preserve the ordering.
3071 //
3072 if (pRequest != NULL) {
3073 InsertNewRequest(&NewRequest, PreviousIrql);
3074 }
3075 else {
3076 //
3077 // If there is no request in the queue then dispatch
3078 // the incoming one.
3079 //
3080 pRequest = NewRequest;
3081 if (pRequest != NULL) {
3082 pRequest->SetCurrentQueue(this);
3083 SetTransitionFromEmpty();
3084 NewRequest = NULL;
3085 }
3086 else {
3087 goto Done;
3088 }
3089 }
3090
3091 //
3092 // pRequest is not cancellable now
3093 //
3094 InsertInDriverOwnedList(pRequest);
3095
3096 Unlock(PreviousIrql);
3097
3098 DispatchRequestToDriver(pRequest);
3099
3100 Lock(&PreviousIrql);
3101 }
3102
3103Done:
3104 m_Dispatching--;
3105 Unlock(PreviousIrql);
3106 return TRUE;
3107}
3108
3109VOID
3112 )
3113
3114/*++
3115
3116 Routine Description:
3117
3118 Dispatch the next request to the driver.
3119
3120 The IoQueue object lock is *not* held.
3121
3122 It returns to the caller with the lock *not* held.
3123
3124 This is called by DispatchRequests(), and should not be
3125 called directly in order to maintain queue processing model.
3126
3127 Arguments:
3128
3129 Returns:
3130
3131--*/
3132
3133{
3134 PFX_DRIVER_GLOBALS FxDriverGlobals;
3136 FxRequestCompletionState oldState;
3137 WDFREQUEST hRequest;
3138 FxIrp* pIrp;
3139
3140 FxDriverGlobals = GetDriverGlobals();
3141
3142
3143
3144
3145
3147
3148 pIrp = pRequest->GetFxIrp();
3149
3150 // The Irp does not have a cancel function right now
3151#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
3153#endif
3154
3155 //
3156 // Set our completion callback on the request now before
3157 // calling the driver since the driver can complete the
3158 // request in the callback handler, and to avoid races with
3159 // the drivers completion thread.
3160 //
3161 // This takes a reference on the request object.
3162 //
3165 UNREFERENCED_PARAMETER(oldState);
3166
3167 if (FxDriverGlobals->FxVerifierOn) {
3168 //
3169 // If the verifier is on, we do not release the extra
3170 // reference so we can mark the request as no longer
3171 // being dispatched to the driver on return from the
3172 // event callback to the driver
3173 //
3174
3176
3177 // Mark the request as being "owned" by the driver
3180 }
3181 else {
3182
3183 //
3184 // Release our original reference. The FxRequest::Complete
3185 // will release the final one since we have registered a completion
3186 // callback handler
3187 //
3188 // We now have one reference count on the FxRequest object until
3189 // its completion routine runs since the completion event made
3190 // an extra reference, and will dereference it when it fires, or
3191 // its canceled.
3192 //
3193
3194 pRequest->RELEASE(FXREQUEST_STATE_TAG);
3195 }
3196
3197 //
3198 // Attempt to dispatch it to the driver
3199 //
3200
3201 //
3202 // Note: A driver that changes its callback pointers at runtime
3203 // could run into a race here since we released the queue
3204 // lock. Currently, changing parameters on a processing
3205 // queue is undefined.
3206 //
3207 // The C DDI's force the callbacks to be registered at
3208 // queue creation time and avoid this race.
3209 //
3210
3211 hRequest = pRequest->GetHandle();
3212
3214
3216 ULONG readLength = pIrp->GetParameterReadLength();
3217
3218 //
3219 // Complete zero length reads with STATUS_SUCCESS unless the
3220 // driver specified it wants them delivered.
3221 //
3222 if ((readLength == 0) &&
3224
3226 FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIO,
3227 "Zero length WDFREQUEST 0x%p completed automatically "
3228 "by WDFQUEUE 0x%p", hRequest, GetObjectHandle());
3229
3231 if (FxDriverGlobals->FxVerifierOn) {
3232 //
3233 // Release the reference taken in the call to SetCompletionState
3234 // at the top of the function.
3235 //
3236 pRequest->RELEASE(FXREQUEST_STATE_TAG);
3237 }
3238 return;
3239 }
3240
3242
3244 "Calling driver EvtIoRead for WDFREQUEST 0x%p",
3245 hRequest);
3246
3248 GetHandle(),
3249 hRequest,
3250 readLength
3251 );
3252 }
3253 else if ((majorFunction == IRP_MJ_WRITE) && m_IoWrite.Method) {
3254 ULONG writeLength = pIrp->GetParameterWriteLength();
3255
3256 //
3257 // Complete zero length writes with STATUS_SUCCESS unless the
3258 // driver specified it wants them delivered.
3259 //
3260 if ((writeLength == 0) &&
3262
3264 FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIO,
3265 "Zero length WDFREQUEST 0x%p completed automatically "
3266 "by WDFQUEUE 0x%p", hRequest, GetObjectHandle());
3267
3269
3270 if (FxDriverGlobals->FxVerifierOn) {
3271 //
3272 // Release the reference taken in the call to SetCompletionState
3273 // at the top of the function.
3274 //
3275 pRequest->RELEASE(FXREQUEST_STATE_TAG);
3276 }
3277 return;
3278 }
3279
3281
3283 "Calling driver EvtIoWrite for WDFREQUEST 0x%p",
3285
3287 GetHandle(),
3288 hRequest,
3289 writeLength
3290 );
3291 }
3293
3295
3297 "Calling driver EvtIoDeviceControl for "
3298 "WDFREQUEST 0x%p", hRequest);
3299
3301 GetHandle(),
3302 hRequest,
3306 );
3307 }
3308
3310
3312
3314 FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIO,
3315 "Calling driver EvtIoInternalDeviceControl for WDFREQUEST 0x%p",
3316 hRequest);
3317
3319 GetHandle(),
3320 hRequest,
3324 );
3325 }
3326 else {
3327
3328 //
3329 // If we have an IoStart registered, call it
3330 //
3331 if (m_IoDefault.Method) {
3332
3334 FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIO,
3335 "Calling driver EvtIoDefault for WDFREQUEST 0x%p", hRequest);
3336
3337
3338 //
3339 // If we don't allow zero length requests, we must dig in whether
3340 // its a read or a write
3341 //
3343
3344 if (majorFunction == IRP_MJ_READ) {
3345
3346 if (pIrp->GetParameterReadLength() == 0) {
3347
3349 FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIO,
3350 "Zero length WDFREQUEST 0x%p completed automatically "
3351 "by WDFQUEUE 0x%p", hRequest, GetObjectHandle());
3352
3354 if (FxDriverGlobals->FxVerifierOn) {
3355 //
3356 // Release the reference taken in the call to SetCompletionState
3357 // at the top of the function.
3358 //
3359 pRequest->RELEASE(FXREQUEST_STATE_TAG);
3360 }
3361 return;
3362 }
3363 }
3364 else if (majorFunction == IRP_MJ_WRITE) {
3365
3366 if (pIrp->GetParameterWriteLength() == 0) {
3367
3369
3371 FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIO,
3372 "Zero length WDFREQUEST 0x%p completed automatically "
3373 "by WDFQUEUE 0x%p", hRequest, GetObjectHandle());
3374
3375 if (FxDriverGlobals->FxVerifierOn) {
3376 //
3377 // Release the reference taken in the call to SetCompletionState
3378 // at the top of the function.
3379 //
3380 pRequest->RELEASE(FXREQUEST_STATE_TAG);
3381 }
3382 return;
3383 }
3384 }
3385 }
3386
3388
3389 m_IoDefault.Invoke(GetHandle(), hRequest);
3390 }
3391 else {
3393
3395 "Driver has no event callback "
3396 "for %!WDF_REQUEST_TYPE!, completing WDFREQUEST 0x%p with "
3397 "%!STATUS!",
3399 pRequest,
3400 Status);
3401
3403
3404 if (FxDriverGlobals->FxVerifierOn) {
3405 //
3406 // Release our extra verifier reference now
3407 //
3408 // Release the reference taken in the call to SetCompletionState
3409 // at the top of the function.
3410 //
3411 pRequest->RELEASE(FXREQUEST_STATE_TAG);
3412 }
3413
3414 return;
3415 }
3416 }
3417
3418 // ******************************
3419 // Request may now be a freed object unless verifier is on. Only touch
3420 // request if verifier is on.
3421 // ******************************
3422
3423 if (FxDriverGlobals->FxVerifierOn) {
3424
3425 //
3426 // If the request has been forwarded, don't clear this
3427 // since the new queue may already be dispatching in a new thread or DPC
3428 //
3431 }
3432
3433 //
3434 // Release our extra verifier reference now
3435 //
3436 // Release the reference taken in the call to SetCompletionState
3437
3438 // at the top of the function.
3439 //
3440 pRequest->RELEASE(FXREQUEST_STATE_TAG);
3441 }
3442
3443 // Driver accepted a request
3444 return;
3445}
3446
3447
3448//
3449// Register a callback when the Queue has a request.
3450//
3451// Only valid for a manual Queue.
3452//
3458 )
3459{
3460 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
3461 KIRQL irql;
3463
3464 // Only valid for a manually dispatched Queue
3468 "WDFQUEUE 0x%p is "
3469 "not a Manual queue, ReadyNotify is only valid "
3470 "on a manual Queue, %!STATUS!",
3472 FxVerifierDbgBreakPoint(FxDriverGlobals);
3473 return status;
3474 }
3475
3476 Lock(&irql);
3477
3478 // If the queue is deleted, requests will not be serviced anymore
3479 if (m_Deleted) {
3480 Unlock(irql);
3481 return STATUS_DELETE_PENDING;
3482 }
3483
3484 if (QueueReady != NULL) {
3485
3486 //
3487 // Only one ReadyNotify registration per Queue is allowed
3488 //
3489 if (m_ReadyNotify.Method != NULL) {
3492 "WDFQUEUE 0x%p "
3493 "already has a ReadyNotify callback 0x%p"
3494 "registered, %!STATUS!",GetObjectHandle(),
3496 FxVerifierDbgBreakPoint(FxDriverGlobals);
3497 Unlock(irql);
3498 return status;
3499 }
3500
3503 }
3504 else {
3505
3506 //
3507 // A request to cancel ready notifications
3508 //
3509
3510 // If already cancelled, the driver is confused, notify it
3511 if (m_ReadyNotify.Method == NULL) {
3514 "WDFQUEUE 0x%p "
3515 "does not have a ReadyNotify to cancel, %!STATUS!",
3517 FxVerifierDbgBreakPoint(FxDriverGlobals);
3518 Unlock(irql);
3519 return status;
3520 }
3521
3522 //
3523 // The queue should be stopped from dispatching requests to
3524 // avoid missing state transistions between clear and set.
3525 //
3529 "WDFQUEUE 0x%p "
3530 "should be stopped before clearing ReadyNotify callback "
3531 "0x%p registered, %!STATUS!",GetObjectHandle(),
3533 FxVerifierDbgBreakPoint(FxDriverGlobals);
3534 Unlock(irql);
3535 return status;
3536
3537 }
3538
3541 }
3542
3543 //
3544 // Check for ready notification since there may already be an event
3545 //
3546 DispatchEvents(irql);
3547
3548 return STATUS_SUCCESS;
3549}
3550
3551VOID
3553 )
3554{
3555 KIRQL irql;
3556
3557 Lock(&irql);
3558
3560
3561 //
3562 // We should set the flag to notify the driver on queue start in case
3563 // the driver stops the queue while the ReadyNotify callback is executing.
3564 // If that happens, the request will be left in the manual queue with
3565 // m_TransitionFromEmpty cleared.
3566 //
3567 if (m_Queue.GetRequestCount() > 0L) {
3570 }
3571
3572 //
3573 // We may have transitioned to a status that resumes
3574 // processing, so call dispatch function.
3575 //
3576
3577 DispatchEvents(irql);
3578
3579 return;
3580}
3581
3585 __in BOOLEAN CancelRequests,
3586 __in_opt PFN_WDF_IO_QUEUE_STATE IdleComplete,
3588 )
3589
3590/*++
3591
3592Routine Description:
3593
3594 Idle (stop) the Queue.
3595
3596 If CancelRequests == TRUE,
3597 1) any requests in the Queue that have not been presented to the device driver are
3598 completed with STATUS_CANCELLED.
3599 2) any requests that the driver is operating on that are cancelable will have an
3600 I/O Cancel done on them.
3601 3) any forward progress queued IRPs are completed with STATUS_CANCELLED.
3602
3603Arguments:
3604
3605Returns:
3606
3607--*/
3608
3609{
3611 KIRQL irql;
3613 LIST_ENTRY fwrIrpList = {0};
3615
3616
3617 Lock(&irql);
3618
3619 // If the queue is deleted, requests will not be serviced anymore
3620 if (m_Deleted) {
3623 "WDFQUEUE 0x%p is already deleted, %!STATUS!",
3625 Unlock(irql);
3626
3627 return status;
3628 }
3629
3630 //
3631 // If a IdleComplete callback is supplied, we must register it up
3632 // front since a transition empty could occur in another thread.
3633 //
3634 if (IdleComplete != NULL) {
3635
3636 //
3637 // Only one Idle or Purge Complete callback can be outstanding
3638 // at a time per Queue
3639 //
3640 if (m_IdleComplete.Method != NULL) {
3643 "WDFQUEUE 0x%p already has a "
3644 "IdleComplete callback registered 0x%p, "
3645 "%!STATUS!", GetObjectHandle(),
3647 status);
3648 Unlock(irql);
3649
3650 return status;
3651 }
3652
3653 m_IdleComplete.Method = IdleComplete;
3655 }
3656
3657 // Set Accept request and Clear dispatch requests
3659
3660 //
3661 // Get ready to cancel current queued requests. Note that we don't want to
3662 // prevent new requests from being queue, i.e., it is legal for an upper
3663 // driver can resend another request in its completion routine.
3664 //
3665 if (CancelRequests) {
3666 //
3667 // Driver wants to abort/complete all queued request and cancel or
3668 // wait for all requests the driver is currently handling. Thus we must
3669 // prevent the driver from requeuing stale requests.
3670 // The 'cancel driver requests' field gives us this ability.
3671 // It is set here, and cleared when:
3672 // (a) Driver doesn't own any more requests, or
3673 // (b) the driver calls WdfIoQueueStart again (dispatch gate is opened).
3674 // When set, the framework automatically deletes any request that the
3675 // driver requeues.
3676 //
3678
3679 request = NULL; // Initial tag used by PeekRequest.
3680 #pragma warning(disable:4127)
3681 while (TRUE) {
3682 #pragma warning(default:4127)
3683 status = FxRequest::PeekRequest(&m_Queue, // in:queue
3684 request, // in:tag.
3685 NULL, // in:file_obj
3686 NULL, // out:parameters
3687 &request); // out:request.
3688 if (status != STATUS_SUCCESS) {
3690 break;
3691 }
3692
3693 //
3694 // Tag this request and release the extra ref that Peek() takes.
3695 //
3696 request->m_Canceled = TRUE;
3697
3698#pragma prefast(suppress:__WARNING_PASSING_FUNCTION_UNEXPECTED_NULL, "This is the tag value used in the ADDREF of Peek()")
3699 request->RELEASE(NULL);
3700 }
3701
3702 //
3703 // Move forward progress IRPs to a temp list; we use this logic to
3704 // allow new IRPs to be pended to the original list.
3705 //
3706 if (IsForwardProgressQueue()) {
3707 InitializeListHead(&fwrIrpList);
3708 GetForwardProgressIrps(&fwrIrpList, NULL);
3709 }
3710 }
3711
3712 // Unlock queue lock
3713 Unlock(irql);
3714
3715 if (CancelRequests) {
3716 #pragma warning(disable:4127)
3717 while (TRUE) {
3718 #pragma warning(default:4127)
3719 //
3720 // Get the next FxRequest from the cancel safe queue
3721 //
3722 Lock(&irql);
3724 if (request == NULL) {
3727 "All WDFQUEUE 0x%p requests cancelled",
3728 GetObjectHandle());
3729 Unlock(irql);
3730 break;
3731 }
3732
3733 // Irp is not cancellable now
3734
3735 //
3736 // Make sure to purged requests only if:
3737 // (a) the request was present when we started this operation.
3738 // (b) any following request that is marked as cancelled.
3739 //
3740 if (request->IsCancelled() == FALSE) {
3741 status = request->InsertHeadIrpQueue(&m_Queue, NULL);
3742 if (NT_SUCCESS(status)) {
3743 Unlock(irql);
3744 break;
3745 }
3746
3748 }
3751 "Cancelling WDFREQUEST 0x%p, WDFQUEUE 0x%p",
3752 request->GetHandle(),GetObjectHandle());
3753
3754 //
3755 // We must add a reference since the CancelForQueue path
3756 // assumes we were on the FxIrpQueue with the extra reference
3757 //
3759
3760 //
3761 // Mark the request as cancelled, place it on the cancel list,
3762 // and schedule the cancel event to the driver
3763 //
3764 CancelForQueue(request, irql);
3765 }
3766
3767 //
3768 // Walk the driver cancelable list cancelling the requests.
3769 //
3770 #pragma warning(disable:4127)
3771 while (TRUE) {
3772 #pragma warning(default:4127)
3773 //
3774 // Get the next request of driver cancelable requests
3775 //
3776 Lock(&irql);
3778 if (request == NULL) {
3781 "All driver cancellable requests cancelled "
3782 " in WDFQUEUE 0x%p",
3783 GetObjectHandle());
3784 Unlock(irql);
3785 break;
3786 }
3787
3788 request->m_Canceled = TRUE;
3789
3790 Unlock(irql);
3791
3792 //
3793 // If the driver follows the pattern of removing cancel status
3794 // from the request before completion, then there is no race
3795 // with this routine since we will not be able to retrieve any
3796 // requests the driver has made non-cancellable in preparation
3797 // for completion.
3798 //
3800
3802
3803 // The request could have been completed and released by the driver
3804 }
3805
3806 //
3807 // Cleanup forward progress IRP list.
3808 //
3809 if (IsForwardProgressQueue()) {
3810 CancelIrps(&fwrIrpList);
3811 }
3812 }
3813
3814 //
3815 // Since we set that no new requests may be dispatched,
3816 // if both m_Queue.GetRequestCount(), m_DriverIoCount == 0, and
3817 // m_Dispatch == 0, right now the queue is completely idle.
3818 //
3819
3820 //
3821 // We check if our m_PurgeComplete callback is still set
3822 // since it may have been called by another thread when
3823 // we dropped the lock above
3824 //
3825 Lock(&irql);
3826 DispatchEvents(irql);
3827
3828 //
3829 // If the driver registered an IdleComplete callback, and it was
3830 // not idle in the above check, it will be called when the final
3831 // callback handler from the device driver returns.
3832 //
3833 return STATUS_SUCCESS;
3834}
3835
3839 __in BOOLEAN CancelRequests
3840 )
3841/*++
3842
3843Routine Description:
3844
3845 Idle the Queue and wait for the driver-owned requests to complete.
3846
3847Arguments:
3848
3849 CancelRequests - If TRUE, functions tries to cancel outstanding requests.
3850
3851Returns:
3852
3853--*/
3854{
3856#if (FX_CORE_MODE==FX_CORE_USER_MODE)
3858#else
3859 MxEvent eventOnStack;
3860 //
3861 // Note that initialize always succeeds in KM so return is not checked.
3862 //
3863 eventOnStack.Initialize(NotificationEvent, FALSE);
3864 MxEvent* event = eventOnStack.GetSelfPointer();
3865#endif
3866
3867 status = QueueIdle(CancelRequests, _IdleComplete, event->GetSelfPointer());
3868
3869 if(NT_SUCCESS(status)) {
3870
3872 "Waiting for %d requests to complete "
3873 "on WDFQUEUE 0x%p",
3875 GetObjectHandle());
3876
3877 Mx::MxEnterCriticalRegion();
3878
3879 GetDriverGlobals()->WaitForSignal(event->GetSelfPointer(),
3880 "waiting for queue to stop, WDFQUEUE", GetHandle(),
3881 GetDriverGlobals()->FxVerifierDbgWaitForSignalTimeoutInSec,
3883
3884
3885 Mx::MxLeaveCriticalRegion();
3886 }
3887
3888 return status;
3889
3890}
3891
3895 __in BOOLEAN CancelQueueRequests,
3896 __in BOOLEAN CancelDriverRequests,
3899 )
3900/*++
3901
3902Routine Description:
3903
3904 Purge the Queue.
3905
3906 If CancelQueueRequests == TRUE, any requests in the
3907 Queue that have not been presented to the device driver are
3908 completed with STATUS_CANCELLED.
3909
3910 If CancelDriverRequests == TRUE, any requests that the
3911 driver is operating on that are cancelable will have an
3912 I/O Cancel done on them.
3913
3914Arguments:
3915
3916Returns:
3917
3918--*/
3919{
3921 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
3922 KIRQL irql;
3924
3925 Lock(&irql);
3926
3927 //
3928 // If the Queue is deleted, there can't be any requests
3929 // to purge, and the queue is no longer executing its
3930 // event dispatch loop, so we would stop responding if we
3931 // registered now.
3932 //
3933 // We could try and silently succeed this, but if we do, we
3934 // must invoke the PurgeComplete callback, and without our
3935 // queue state machine excuting, we can not ensure any
3936 // callback constraints are handled such as locking, queueing
3937 // to passive level, etc. So we just fail to indicate to the
3938 // driver we *will not* be invoking its PurgeComplete function.
3939 //
3940 if (m_Deleted) {
3943 "WDFQUEUE 0x%p is already deleted %!STATUS!",
3945 Unlock(irql);
3946
3947 return status;
3948 }
3949
3950 //
3951 // If a PurgeComplete callback is supplied, we must register it up
3952 // front since a transition empty could occur in another thread.
3953 //
3954 if (PurgeComplete != NULL) {
3955
3956 //
3957 // Only one PurgeComplete callback can be outstanding
3958 // at a time per Queue
3959 //
3960 if (m_PurgeComplete.Method != NULL) {
3963 "WDFQUEUE 0x%p already has a "
3964 "PurgeComplete callback registered 0x%p "
3965 "%!STATUS!", GetObjectHandle(),
3967 Unlock(irql);
3968
3969 return status;
3970 }
3971
3974 }
3975
3976 // Clear accept requests
3978
3979 if (CancelQueueRequests && CancelDriverRequests &&
3980 FxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,11)) {
3981 //
3982 // Driver wants to abort/complete all queued request and cancel or
3983 // wait for all requests the driver is currently handling. Thus we must
3984 // prevent the driver from requeuing stale requests.
3985 // This flag is set here, and cleared when:
3986 // (a) Driver doesn't own any more requests, or
3987 // (b) the driver calls WdfIoQueueStart again (dispatch gate is opened).
3988 // When set, the framework automatically deletes any request that the
3989 // driver requeues.
3990 // For compatibility we do this only for drivers v1.11 and above.
3991 //
3993 }
3994
3995 // Unlock queue lock
3996 Unlock(irql);
3997
3998 if (CancelQueueRequests) {
3999 #pragma warning(disable:4127)
4000 while (TRUE) {
4001 #pragma warning(default:4127)
4002 //
4003 // Get the next FxRequest from the cancel safe queue
4004 //
4005 Lock(&irql);
4007 if (pRequest == NULL) {
4009 "All WDFQUEUE 0x%p requests cancelled",
4010 GetObjectHandle());
4011 Unlock(irql);
4012 break;
4013 }
4014
4015 // Irp is not cancellable now
4016
4018 "Cancelling WDFREQUEST 0x%p, WDFQUEUE 0x%p",
4020
4021 //
4022 // We must add a reference since the CancelForQueue path
4023 // assumes we were on the FxIrpQueue with the extra reference
4025
4026 //
4027 // Mark the request as cancelled, place it on the cancel list,
4028 // and schedule the cancel event to the driver
4029 //
4030 CancelForQueue(pRequest, irql);
4031
4032 }
4033 }
4034
4035 if (CancelDriverRequests) {
4036
4037 //
4038 // Walk the driver cancelable list cancelling
4039 // the requests.
4040 //
4041 #pragma warning(disable:4127)
4042 while (TRUE) {
4043 #pragma warning(default:4127)
4044 //
4045 // Get the next request of driver cancelable requests
4046 //
4047 Lock(&irql);
4049 if (pRequest == NULL) {
4051 "All driver cancellable requests cancelled "
4052 " in WDFQUEUE 0x%p",
4053 GetObjectHandle());
4054 Unlock(irql);
4055 break;
4056 }
4057
4059
4060 Unlock(irql);
4061
4062 //
4063 // If the driver follows the pattern of removing cancel status
4064 // from the request before completion, then there is no race
4065 // with this routine since we will not be able to retrieve any
4066 // requests the driver has made non-cancellable in preparation
4067 // for completion.
4068 //
4070
4072
4073 // The request could have been completed and released by the driver
4074 }
4075 }
4076
4077 if (IsForwardProgressQueue()) {
4079 }
4080
4081 //
4082 // Since we set that no new requests may be enqueued,
4083 // if both m_Queue.GetRequestCount() and m_DriverIoCount == 0 right
4084 // now the queue is completely purged.
4085 //
4086
4087 //
4088 // We check if our m_PurgeComplete callback is still set
4089 // since it may have been called by another thread when
4090 // we dropped the lock above
4091 //
4092 Lock(&irql);
4093
4094 DispatchEvents(irql);
4095
4096 //
4097 // If the driver registered a PurgeComplete callback, and it was
4098 // not empty in the above check, it will be called when a
4099 // request complete from the device driver completes the
4100 // final request.
4101 //
4102 return STATUS_SUCCESS;
4103}
4104
4108 )
4109/*++
4110
4111Routine Description:
4112
4113 Purge the queue and wait for it to complete.
4114 When this call returns, there are no requests in the queue or device
4115 driver and the queue state is set to reject new requests.
4116
4117--*/
4118{
4120
4121#if (FX_CORE_MODE==FX_CORE_USER_MODE)
4123#else
4124 MxEvent eventOnStack;
4125 //
4126 // Note that initialize always succeeds in KM so return is not checked.
4127 //
4128 eventOnStack.Initialize(NotificationEvent, FALSE);
4129 MxEvent* event = eventOnStack.GetSelfPointer();
4130#endif
4131
4132 status = QueuePurge(TRUE, TRUE, _PurgeComplete, event->GetSelfPointer());
4133
4134 if(NT_SUCCESS(status)) {
4135
4137 "Waiting for %d requests to complete "
4138 "on WDFQUEUE 0x%p",
4140 GetObjectHandle());
4141
4142 Mx::MxEnterCriticalRegion();
4143
4144 GetDriverGlobals()->WaitForSignal(event->GetSelfPointer(),
4145 "waiting for queue to purge, WDFQUEUE", GetHandle(),
4146 GetDriverGlobals()->FxVerifierDbgWaitForSignalTimeoutInSec,
4148
4149 Mx::MxLeaveCriticalRegion();
4150 }
4151
4152 return status;
4153
4154}
4155
4161 )
4162{
4163 //
4164 // We drain the queue by calling QueuePurge with CancelQueueRequests
4165 // and CancelDriverRequests == FALSE. The Queue will reject new
4166 // requests, but allow the device driver to continue processing
4167 // requests currently on the Queue. The DrainComplete callback is
4168 // invoked when there are no requests in Queue or device driver.
4169 //
4170
4172
4173}
4174
4178 )
4179/*++
4180
4181Routine Description:
4182
4183 Drain the queue and wait for it to complete.
4184 When this call returns, there are no requests in the queue or device
4185 driver and the queue state is set to reject new requests.
4186
4187--*/
4188{
4190#if (FX_CORE_MODE==FX_CORE_USER_MODE)
4192#else
4193 MxEvent eventOnStack;
4194 //
4195 // Note that initialize always succeeds in KM so return is not checked.
4196 //
4197 eventOnStack.Initialize(NotificationEvent, FALSE);
4198 MxEvent* event = eventOnStack.GetSelfPointer();
4199#endif
4200
4201 status = QueueDrain(_PurgeComplete, event->GetSelfPointer());
4202
4203 if(NT_SUCCESS(status)) {
4204
4206 "Waiting for %d requests to complete "
4207 "on WDFQUEUE 0x%p",
4209 GetObjectHandle());
4210
4211 Mx::MxEnterCriticalRegion();
4212
4213 GetDriverGlobals()->WaitForSignal(event->GetSelfPointer(),
4214 "waiting for queue to drain, WDFQUEUE", GetHandle(),
4215 GetDriverGlobals()->FxVerifierDbgWaitForSignalTimeoutInSec,
4217
4218 Mx::MxLeaveCriticalRegion();
4219 }
4220
4221 return status;
4222
4223}
4224
4225
4226VOID
4228 __out_opt PULONG pQueuedRequests,
4229 __out_opt PULONG pDriverPendingRequests
4230 )
4231/*++
4232
4233Routine Description:
4234
4235 Return the count of requests currently on the queue
4236 and owned by the driver.
4237
4238Arguments:
4239
4240Returns:
4241
4242--*/
4243{
4244 if (pQueuedRequests != NULL) {
4245 *pQueuedRequests = m_Queue.GetRequestCount();
4246 }
4247
4248 if (pDriverPendingRequests != NULL) {
4249 *pDriverPendingRequests = m_DriverIoCount;
4250 }
4251
4252 return;
4253}
4254
4255VOID
4258 )
4259/*++
4260
4261Routine Description:
4262
4263 Scan the queue and cancel all the requests that have
4264 the same fileobject as the input argument.
4265
4266 This function is called when the IoPkg receives a
4267 IRP_MJ_CLEANUP requests.
4268
4269 Additional reference is already taken on the object by the caller
4270 to prevent the queue from being deleted.
4271
4272Return Value:
4273
4274--*/
4275{
4278 KIRQL irql;
4279
4280 if (IsForwardProgressQueue()) {
4282 }
4283
4284 Lock(&irql);
4285
4286 #pragma warning(disable:4127)
4287 while (TRUE) {
4288 #pragma warning(default:4127)
4289
4290 //
4291 // Get the next FxRequest from the cancel safe queue
4292 //
4295 break;
4296 }
4297 if(!NT_SUCCESS(status)) {
4298 ASSERTMSG("GetNextRequest failed\n", FALSE);
4299 break;
4300 }
4301
4302 //
4303 // We must add a reference since the CancelForQueue path
4304 // assumes we were on the FxIrpQueue with the extra reference
4305 //
4307
4308 //
4309 // Mark the request as cancelled, place it on the cancel list,
4310 // and schedule the cancel event to the driver
4311 //
4312 CancelForQueue(pRequest, irql);
4313
4314 //
4315 // Reacquire the lock because CancelForQueue visits the dispatch-loop
4316 // and releases the lock.
4317 //
4318 Lock(&irql);
4319 }
4320
4321 DispatchEvents(irql);
4322
4323 return;
4324
4325}
4326
4327_Releases_lock_(this->m_SpinLock.m_Lock)
4328VOID
4329FxIoQueue::CancelForQueue(
4331 __in __drv_restoresIRQL KIRQL PreviousIrql
4332 )
4333/*++
4334
4335 Routine Description:
4336
4337 This routine performs the actions when notified of a cancel
4338 on a request that has not been presented to the driver
4339
4340 Return Value:
4341
4342 NTSTATUS
4343
4344--*/
4345{
4346 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
4347 FxRequestCompletionState oldState;
4348
4349 // This is not an error, but want to make sure cancel testing works
4350 if (FxDriverGlobals->FxVerifierOn) {
4351
4352 // Clear cancellable status, otherwise verifier in FxRequest::Complete will complain
4353 pRequest->ClearVerifierFlags(FXREQUEST_FLAG_DRIVER_CANCELABLE);
4354
4356 "WDFREQUEST 0x%p "
4357 "was cancelled while on WDFQUEUE 0x%p",
4358 pRequest->GetHandle(),GetObjectHandle());
4359 }
4360
4361 pRequest->m_Canceled = TRUE;
4362
4363 pRequest->MarkRemovedFromIrpQueue();
4364
4365 //
4366 // Drop the extra reference taken when it was added to the queue
4367 // because the request is now leaving the queue.
4368 //
4369 pRequest->RELEASE(FXREQUEST_QUEUE_TAG);
4370
4371 //
4372 // If the driver has registered m_CanceledOnQueue callback, and if
4373 // the request was ever presented to the driver then we need to
4374 // notify the driver
4375 //
4376 if(m_IoCanceledOnQueue.Method && pRequest->m_Presented) {
4377
4378 //
4379 // Set the state to indicate the request has come from a queue.
4380 //
4381 oldState = pRequest->SetCompletionState(FxRequestCompletionStateQueue);
4383 UNREFERENCED_PARAMETER(oldState);
4384
4385 // Insert it on the driver owned list
4386 InsertInDriverOwnedList(pRequest);
4387
4388 if (FxDriverGlobals->FxVerifierOn) {
4389 ASSERT((pRequest->GetVerifierFlags() & FXREQUEST_FLAG_DRIVER_OWNED) == 0);
4390 pRequest->SetVerifierFlags(FXREQUEST_FLAG_DRIVER_OWNED);
4391 }
4392
4393 //
4394 // Also insert the request in to m_CanceledOnQueueList so
4395 // that we can notify the driver when we visit the DispatchEvents
4396 //
4397 InsertTailList(&m_CanceledOnQueueList, pRequest->GetListEntry(FxListEntryQueueOwned));
4398
4399 //
4400 // Release the reference taken in the call to SetCompletionState.
4401 //
4402 pRequest->RELEASE(FXREQUEST_STATE_TAG);
4403 } else {
4404
4405 Unlock(PreviousIrql);
4406
4407 // Its gone from our list, so complete it cancelled
4408 pRequest->CompleteWithInformation(STATUS_CANCELLED, 0);
4409
4410 // Dereference the request objects final reference
4412
4413 Lock(&PreviousIrql);
4414 }
4415
4416 // This may have caused the queue to be emptied
4417 DispatchInternalEvents(PreviousIrql);
4418
4419 return;
4420}
4421
4422VOID
4425 __in MdIrp Irp,
4426 __in PMdIoCsqIrpContext CsqContext,
4428 )
4429/*++
4430
4431Routine Description:
4432 This is our Cancel Safe Queue Callback from FxIrpQueue notifying us of an
4433 I/O cancellation on the main (pre driver) Queue.
4434
4435 Note this callback is called with the queue lock held.
4436
4437Arguments:
4438 IrpQueue - Queue the request was on
4439
4440 Irp - the irp being cancelled
4441
4442 CsqContext - the context associated with the irp
4443
4444Return Value:
4445 None
4446
4447 --*/
4448{
4449 FxIoQueue* ioQueue;
4451
4454
4455 //
4456 // Must reference the queue since this could be the final
4457 // request on a deleting queue
4458 //
4459 ioQueue->ADDREF(Irp);
4460
4461 //
4462 // We cannot drop the lock here because we may have to insert the
4463 // request in the driver owned list if the driver has registered
4464 // for canceled-on-queue callback. If we drop the lock and if the request
4465 // happens to be last request, the delete will run thru and put
4466 // the state of the queue to deleted state and prevent further dispatching
4467 // of requests.
4468 //
4469 ioQueue->CancelForQueue(pRequest, Irql);
4470
4471 ioQueue->RELEASE(Irp);
4472}
4473
4474VOID
4475FX_VF_METHOD(FxIoQueue, VerifyValidateCompletedRequest)(
4476 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
4478 )
4479{
4480 UNREFERENCED_PARAMETER(FxDriverGlobals);
4481
4483
4485 KIRQL irql;
4486
4487 Request->Lock(&irql);
4488
4489 (VOID) Request->VerifyRequestIsDriverOwned(FxDriverGlobals);
4490 Request->ClearVerifierFlagsLocked(FXREQUEST_FLAG_DRIVER_OWNED);
4491
4492 Request->Unlock(irql);
4493
4494 // Driver no longer owns it once completed
4495
4496 // Request can't be on a cancel list
4497 pEntry = Request->GetListEntry(FxListEntryQueueOwned);
4500 GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGIO,
4501 "WDFREQUEST 0x%p is on a cancellation list for WDFQUEUE 0x%p",
4502 Request->GetHandle(), GetObjectHandle());
4503 FxVerifierDbgBreakPoint(GetDriverGlobals());
4504 }
4505}
4506
4507VOID
4508FX_VF_METHOD(FxIoQueue, VerifyCancelForDriver) (
4509 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
4511 )
4512{
4514
4516
4518 "WDFREQUEST 0x%p "
4519 "was cancelled in driver for WDFQUEUE 0x%p",
4520 Request->GetHandle(), GetObjectHandle());
4521
4522 // Verifier code assures this is available to the cancel processing
4523 pEntry = Request->GetListEntry(FxListEntryQueueOwned);
4524 if (!IsListEmpty(pEntry)) {
4526 "WDFREQUEST 0x%p is "
4527 "already on list, FxRequest::m_ListEntry is busy!, "
4528 "WDFQUEUE 0x%p",
4529 Request->GetHandle(), GetObjectHandle());
4530 FxVerifierDbgBreakPoint(FxDriverGlobals);
4531 }
4532}
4533
4534VOID
4537 )
4538/*++
4539
4540Routine Description:
4541
4542 This is called when a driver-owned cancelable request is canceled.
4543 This routine will add the request to m_Canceled list so that the
4544 dispatcher and call the driver cancel-routine to notify the driver.
4545
4546 Queue lock is not held.
4547
4548Arguments:
4549
4550 pRequest - is a driver owned cancelable request.
4551
4552Return Value:
4553
4554--*/
4555{
4556 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
4557 KIRQL irql;
4558
4559 // This is not an error, but want to make sure cancel testing works
4560 VerifyCancelForDriver(FxDriverGlobals, pRequest);
4561
4562 //
4563 // We are called with no locks held, but
4564 // can be in arbitrary thread context from
4565 // a cancel occuring from another driver within
4566 // a driver stack.
4567 //
4568
4569 //
4570 // The Csq has removed this request from the driver pending
4571 // queue, and it no longer has a cancel function if the
4572 // driver does not accept the cancel right now.
4573 //
4574 // When callside eventually goes to remove it from the queue
4575 // by CsqContext, the Csq's will return NULL.
4576 //
4577 // Irp and FxRequest is still valid until the driver calls
4578 // WdfRequestComplete either as a result of this cancel
4579 // callback, or at its leasure if it chooses to ignore it.
4580 //
4581 // The insert of FxRequest onto the FxIrpQueue took out a
4582 // reference, and when an IRP gets cancelled, we are responsible
4583 // for this final dereference after calling into the driver.
4584 //
4585
4586 //
4587 // Cancellations are dispatched as events to the device driver
4588 // using the standard DispatchEvents processing loop. In order
4589 // to support this, we must defer it by linking this request
4590 // into a list of cancelled requests.
4591 //
4592 // The requests will be removed from this list and cancel notified
4593 // to the device driver by the processing loop.
4594 //
4595
4597
4598 //
4599 // Queue it on the cancelled list
4600 //
4601 Lock(&irql);
4602
4604
4605 //
4606 // Visit the event dispatcher
4607 //
4608 DispatchInternalEvents(irql);
4609
4610 return;
4611}
4612
4613VOID
4616 __in MdIrp Irp,
4617 __in PMdIoCsqIrpContext CsqContext,
4619 )
4620/*++
4621
4622Routine Description:
4623 This is our Cancel Safe Queue Callback from FxIrpQueue notifying us of an
4624 I/O cancellation on a driver owned request (driver queue)
4625
4626 Note this callback is called with the queue lock held.
4627
4628Arguments:
4629 IrpQueue - Queue the request was on
4630
4631 Irp - the irp being cancelled
4632
4633 CsqContext - the context associated with the irp
4634
4635
4636Return Value:
4637 None
4638
4639 --*/
4640{
4641 FxIoQueue* ioQueue;
4643
4646
4648
4649 //
4650 // Must reference the queue since this could be the final
4651 // request on a deleting queue.
4652 //
4653 ioQueue->ADDREF(Irp);
4654
4655 //
4656 // We can drop the lock because this request is a driver owned request and
4657 // it is tracked by m_DriverIoCount. As a result delete will be blocked
4658 // until the request is completed.
4659 //
4660 ioQueue->Unlock(Irql);
4661
4662 ioQueue->CancelForDriver(pRequest);
4663
4664 ioQueue->RELEASE(Irp);
4665}
4666
4668VOID
4669FxIoQueue::ProcessIdleComplete(
4670 __out PKIRQL PreviousIrql
4671 )
4672/*++
4673
4674Routine Description:
4675
4676 Handle IdleComplete.
4677 Calls back the driver if conditions are met.
4678 Called with Queue lock held, but can drop and re-acquire
4679 it when delivering the event callback to the device driver.
4680
4681Arguments:
4682 IrpQueue - Queue the request was on
4683
4684 Irp - the irp being cancelled
4685
4686 CsqContext - the context associated with the irp
4687
4688Return Value:
4689 None
4690
4691 --*/
4692{
4693 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
4696
4697
4700
4703
4705
4707 "WDFQUEUE 0x%p is idle, calling driver callback",
4708 GetHandle());
4709
4710 // Notify driver by callback
4711 if (callback.Method != NULL) {
4712 callback.Invoke(GetHandle(), ctx);
4713 }
4714
4716
4717 return;
4718}
4719
4721VOID
4722FxIoQueue::ProcessPurgeComplete(
4723 __out PKIRQL PreviousIrql
4724 )
4725/*++
4726
4727Routine Description:
4728
4729
4730 Handle PurgeComplete.
4731
4732 Calls back the driver if conditions are met.
4733
4734 Called with Queue lock held, but can drop and re-acquire
4735 it when delivering the event callback to the device driver.
4736
4737
4738Arguments:
4739
4740Return Value:
4741 None
4742
4743 --*/
4744{
4745 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
4748
4751
4754
4756
4758 "WDFQUEUE 0x%p is purged, calling driver callback",
4759 GetObjectHandle());
4760
4761 // Notify driver by callback
4762 if (callback.Method != NULL) {
4763 callback.Invoke(GetHandle(), ctx);
4764 }
4765
4767
4768 return;
4769}
4770
4772VOID
4773FxIoQueue::ProcessReadyNotify(
4774 __out PKIRQL PreviousIrql
4775 )
4776/*++
4777
4778Routine Description:
4779
4780 Callback the driver for a Queue ready notify
4781 Called with the Queue lock held, and may release
4782 and re-acquire it in calling back the driver
4783
4784Arguments:
4785
4786Return Value:
4787 None
4788
4789 --*/
4790{
4791 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
4794
4795 //
4796 // A callback to the driver "consumes" the notification.
4797 // Since we drop the lock when we call the driver, there is
4798 // a chance for the queue to be stopped or powered-off before
4799 // the driver tries to retrieve the request. So make sure
4800 // to set this flag when you power-on or start the queue to
4801 // avoid abandoning the requests in the queue.
4802 //
4804
4805 //
4806 // Save a local copy since another thread could
4807 // cancel the ready notification out from under us
4808 // when we drop the lock
4809 //
4811
4813
4815
4816 if (callback.Method != NULL) {
4817 callback.Invoke(GetHandle(), ctx);
4818 }
4819 else {
4820 if (FxDriverGlobals->FxVerifierOn) {
4822 "ReadyNotify notify method is NULL "
4823 "on WDFQUEUE 0x%p", GetObjectHandle());
4824 FxVerifierDbgBreakPoint(FxDriverGlobals);
4825 }
4826 }
4827
4829
4830 return;
4831}
4832
4834BOOLEAN
4835FxIoQueue::ProcessCancelledRequests(
4836 __out PKIRQL PreviousIrql
4837 )
4838/*++
4839
4840 Routine Description:
4841
4842 Process any cancelled requests
4843 Called with the Queue lock held
4844 Can drop and re-acquire the queue lock
4845 Returns with the Queue lock held
4846
4847 Arguments:
4848
4849 Return Value:
4850 None
4851
4852 --*/
4853{
4856
4857 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
4858
4860 //
4861 // We will not process cancelled request while the driver is being
4862 // notified to stop processing request to avoid double completion
4863 // of the request.
4864 //
4865 return FALSE;
4866 }
4867
4868 while (!IsListEmpty(&m_Cancelled)) {
4870
4872
4873 // FxRequest ensures its not on any list on checked builds
4875
4877
4879 "Calling CancelRoutine routine "
4880 "for WDFREQUEST 0x%p on WDFQUEUE 0x%p",
4882
4883 if (FxDriverGlobals->FxVerifierOn) {
4884
4885 // Set cancelled status, otherwise verifier in FxRequest::Complete will complain
4887 }
4888
4890
4891 if (FxDriverGlobals->FxVerifierOn) {
4893 }
4894
4895 //
4896 // Notify the driver of cancel desire
4897 //
4901 );
4902
4903 //
4904 // Release the reference that FxRequest took out on itself
4905 // when it was placed onto the FxIrpQueue. It is now leaving
4906 // the FxIrpQueue due to cancel, and we own this final
4907 // release.
4908 //
4909 pRequest->RELEASE(FXREQUEST_QUEUE_TAG);
4910
4912 }
4913
4914 return TRUE;
4915}
4916
4918BOOLEAN
4919FxIoQueue::ProcessCancelledRequestsOnQueue(
4920 __out PKIRQL PreviousIrql
4921 )
4922/*++
4923
4924 Routine Description:
4925
4926 Process any cancelled requests
4927 Called with the Queue lock held
4928 Can drop and re-acquire the queue lock
4929 Returns with the Queue lock held
4930
4931 Arguments:
4932
4933 Return Value:
4934 None
4935
4936 --*/
4937{
4940
4941 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
4942
4944 //
4945 // We will not process cancelled request while the driver is being
4946 // notified to stop/resume processing request to avoid double
4947 // completion of the request.
4948 //
4949 return FALSE;
4950 }
4951
4954
4956
4957 // FxRequest ensures its not on any list on checked builds
4959
4961
4963 "Calling CanceledOnQueue routine "
4964 "for WDFREQUEST 0x%p on WDFQUEUE 0x%p",
4966
4967 if (FxDriverGlobals->FxVerifierOn) {
4968
4969 // Set cancelled status, otherwise verifier in FxRequest::Complete will complain
4971 }
4972
4974
4975 if (FxDriverGlobals->FxVerifierOn) {
4977 }
4978
4979 //
4980 // Notify the driver
4981 //
4983
4985 }
4986
4987 return TRUE;
4988}
4989
4991BOOLEAN
4992FxIoQueue::ProcessPowerEvents(
4993 __out PKIRQL PreviousIrql
4994 )
4995/*++
4996
4997Routine Description:
4998
4999 Processes the power state machine for I/O queues.
5000
5001 Called with Queue lock held, but can drop and re-acquire
5002 it when it has to deliver event callbacks to the device driver.
5003
5004 This can modify queue state as it transits the state machine, and
5005 is called from the main event processing loop DispatchEvents().
5006
5007 Handling "in-flight" I/O requests in the device driver due
5008 to a power state transition (stopping) is tricky, and
5009 involves a complex state machine.
5010
5011 The device driver must ensure that all in-flight I/O is stopped
5012 before it can release the thread calling into the driver to
5013 perform the power state transition, otherwise a system crash
5014 can result from accessing hardware after resources have been removed.
5015
5016 In WDF, this burden is placed on FxIoQueue, so that the device driver
5017 does not have to implement the more complex aspects of this code,
5018 but can rely on notifications from the queue serialized under the
5019 IRQL level and locking it has configured.
5020
5021
5022 Implementation of FxIoQueue Power state machine:
5023 ------------------------------------------
5024
5025 Since we must drop our lock to callback into the device
5026 driver for power notifications, the processing must occur
5027 as a state machine with three lists.
5028
5029 On entry to the power stop state, any "in-flight" I/O requests
5030 are recorded on the m_DriverOwned list using
5031 FxRequest::FxListEntryDriverOwned for linkage.
5032
5033 All of the requests on m_DriverOwned are moved to m_PowerNotify
5034 while holding the lock, with m_DriverOwned cleared. The state is changed
5035 to indicate that the driver is now being notified of requests.
5036
5037 While in the driver notification state, requests are taken from the
5038 m_PowerNotify list, and moved on to the m_PowerDriverNotified list while
5039 under the lock, and the request is notified to the device driver
5040 by the callback while dropping the lock and re-acquiring the lock.
5041
5042 As the driver acknowledges the power notification, it calls
5043 WdfRequestStopAcknowledge (FxIoQueue::StopAcknowledge) which moves the
5044 request from the m_PowerDriverNotified list back to the m_DriverOwned
5045 list.
5046
5047 The device driver could also complete requests, in which case they
5048 just dis-appear from the lists by the completion code doing
5049 a RemoveEntryList on FxRequest::FxListEntryDriverOwned.
5050
5051 This occurs until the m_PowerNotify list is empty, in which case
5052 the state is changed to driver notified.
5053
5054 While in the driver notified state, the queue event processing continues
5055 until the m_PowerDriverNotified list is empty, and when it is, the
5056 stopped state is set, and the event m_PowerIdle is set. This releases
5057 the thread waiting on the power state transition in which all of the
5058 device drivers "in-flight" I/O has been stopped and accounted for.
5059
5060 State Transitions:
5061 --------------
5062
5063 During Stop:
5064
5065 FxIoQueuePowerOn
5066 --> FxIoQueuePowerStartingTransition
5067 --> FxIoQueuePowerStopping
5068 --> FxIoQueuePowerStoppingNotifyingDriver
5069 --> FxIoQueuePowerStoppingDriverNotified
5070 --> FxIoQueuePowerOff
5071
5072 During Purge:
5073
5074 FxIoQueuePowerPurge
5075 --> FxIoQueuePowerPurgeNotifyingDriver
5076 --> FxIoQueuePowerPurgeDriverNotified
5077 --> FxIoQueuePowerOff
5078
5079
5080 During Resume:
5081
5082 FxIoQueuePowerOff
5083 --> FxIoQueuePowerRestarting
5084 --> FxIoQueuePowerRestartingNotifyingDriver
5085 --> FxIoQueuePowerRestartingDriverNotified
5086 --> FxIoQueuePowerOn
5087
5088Arguments:
5089
5090Return Value:
5091
5092 TRUE - Continue processing the event loop
5093 FALSE - Stop processing event loop
5094
5095--*/
5096{
5099
5100 PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
5101
5102 switch(m_PowerState) {
5103
5105 if (m_Dispatching == 1) {
5106
5107 //
5108 // If we are the last routine actively dispatching callbacks to
5109 // the device driver under a Power stop, then we must set the
5110 // event specifying no more callbacks are active.
5111 //
5112 m_PowerIdle.Set();
5113 }
5114
5115 return FALSE;
5116
5118 //
5119 // Set state to FxIoQueuePowerPurgeNotifyingDriver
5120 //
5122
5123 // This should be empty on entry to this state
5125
5126 if (!IsListEmpty(&m_DriverOwned)) {
5127
5129 "Power Stop: WDFQUEUE 0x%p is powering off "
5130 "with in-flight requests",
5131 GetObjectHandle());
5132
5133
5134 // Ensure the logic of m_DriverOwned is correct
5137
5138 //
5139 // Move all requests on m_DriverOwned to m_PowerNotify
5140 //
5145
5146 // This is now empty
5148 }
5149 else {
5151 "Power Stop: WDFQUEUE 0x%p is powering off without "
5152 "in-flight requests",GetObjectHandle());
5153 }
5154
5155 //
5156 // Return to main processing loop which will callback to
5157 // process notifications
5158 //
5159 return TRUE;
5160
5162 //
5163 // Set state to FxIoQueuePowerPurgeNotifyingDriver
5164 //
5166
5167 // This should be empty on entry to this state
5169
5170 if (!IsListEmpty(&m_DriverOwned)) {
5171
5173 "Power Stop: WDFQUEUE 0x%p is purging with "
5174 "in-flight requests",GetObjectHandle());
5175
5176 // Ensure the logic of m_DriverOwned is correct
5179
5180 //
5181 // Move all requests on m_DriverOwned to m_PowerNotify
5182 //
5187
5188 // This is now empty
5190 }
5191 else {
5193 "Power purge: WDFQUEUE 0x%p is purging without "
5194 "in-flight requests", GetObjectHandle());
5195 }
5196
5197 //
5198 // Return to main processing loop which will callback to
5199 // process notifications
5200 //
5201 return TRUE;
5202
5204
5205 FxIoQueueIoStop stopCallback;
5206
5207 //
5208 // If the list of requests to notify the driver about is
5209 // empty, change to the notified state.
5210 //
5211 if (IsListEmpty(&m_PowerNotify)) {
5213
5214 //
5215 // Return to main processing loop which will callback to
5216 // process the wait/signaling for the driver to acknowledge
5217 // all stops.
5218 //
5219 return TRUE;
5220 }
5221
5222 //
5223 // Notify each entry in m_PowerNotify into the driver
5224 //
5225
5226 // Remove from the notify list, place it on the driver notified list
5228
5230
5231 // Retrieve the FxRequest
5233
5234 stopCallback = m_IoStop;
5235
5236 //
5237 // Notify driver by callback.
5238 //
5239 // If no callback is registered, the power thread will in effect
5240 // wait until the driver completes or cancels all requests.
5241 //
5242 if (stopCallback.Method != NULL && pRequest->m_Canceled == FALSE) {
5244
5247 }
5248
5250 FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIO,
5251 "Power Stop Notifying Driver, WDFQUEUE 0x%p, WDFREQUEST 0x%p",
5253
5254 // Driver could be calling RequestComplete as we attempt to stop
5256
5258
5259 if (FxDriverGlobals->FxVerifierOn) {
5261 }
5262
5263 stopCallback.Invoke(GetHandle(), pRequest->GetHandle(), ActionFlags);
5264
5265 pRequest->RELEASE(FXREQUEST_HOLD_TAG);
5266
5268 }
5269
5270 //
5271 // As they are acknowledged, they will move back to m_DriverOwned.
5272 //
5273 // If the driver completes them, they go away.
5274 //
5275
5276 // Return to main processing loop and continue processing notifications
5277 return TRUE;
5278 }
5279
5281
5282 FxIoQueueIoStop stopCallback;
5283
5284 //
5285 // If the list of requests to notify the driver about is
5286 // empty, change to the notified state.
5287 //
5288 if (IsListEmpty(&m_PowerNotify)) {
5290
5291 //
5292 // Return to main processing loop which will callback to
5293 // process the wait/signaling for the driver to acknowledge
5294 // all stops.
5295 //
5296 return TRUE;
5297 }
5298
5299 //
5300 // Notify each entry in m_PowerNotify into the driver
5301 //
5302
5303 // Remove from the notify list, place it on the driver notified list
5305
5307
5308 // Retrieve the FxRequest
5310
5311 stopCallback = m_IoStop;
5312
5313 //
5314 // Make sure power stop state is cleared before invoking the stop callback.
5315 //
5317
5318 //
5319 // Notify driver by callback.
5320 //
5321 // If no callback is registered, the power thread will in effect
5322 // wait until the driver completes or cancels all requests.
5323 //
5324 if (stopCallback.Method != NULL && pRequest->m_Canceled == FALSE) {
5326
5329 }
5330
5332 "Power Purge Notifying Driver "
5333 "WDFQUEUE 0x%p, WDFREQUEST 0x%p",
5335
5336 // Driver could be calling RequestComplete as we attempt to stop
5338
5340
5341 if (FxDriverGlobals->FxVerifierOn) {
5343 }
5344
5345 stopCallback.Invoke(GetHandle(), pRequest->GetHandle(), ActionFlags);
5346
5347 pRequest->RELEASE(FXREQUEST_HOLD_TAG);
5348
5350 }
5351
5352 //
5353 // As they are acknowledged, they will move back to m_DriverOwned.
5354 //
5355 // If the driver completes them, they go away.
5356 //
5357
5358 // Return to main processing loop and continue processing notifications
5359 return TRUE;
5360 }
5361
5364
5365 PLIST_ENTRY thisEntry, nextEntry, listHead;
5366 LIST_ENTRY acknowledgedList;
5367 BOOLEAN continueProcessing = FALSE;
5368
5369 InitializeListHead(&acknowledgedList);
5370
5371 //
5372 // First move all the acknowledged requests to local list and then
5373 // process the local list. We have do that in two steps because
5374 // ProcessAcknowledgedRequests drops and reacquires the lock.
5375 //
5376 listHead = &m_PowerDriverNotified;
5377
5378 for (thisEntry = listHead->Flink;
5379 thisEntry != listHead;
5380 thisEntry = nextEntry) {
5381
5382 // Retrieve the FxRequest
5384
5385 nextEntry = thisEntry->Flink;
5386
5388 RemoveEntryList(thisEntry);
5389 InsertTailList(&acknowledgedList, thisEntry);
5390 }
5391 }
5392
5393 //
5394 // Process all the acknowledged request from the local list.
5395 //
5396 while (!IsListEmpty(&acknowledgedList))
5397 {
5398 thisEntry = RemoveHeadList(&acknowledgedList);
5400 ProcessAcknowledgedRequests(pRequest, PreviousIrql);
5401
5402 //
5403 // When this function drops the lock, other threads may attempt
5404 // to dispatch but fail since we are currently dispatching.
5405 // We need to be sure to process any pending events that other
5406 // threads initiated but could not be dispatch. The acknowledged
5407 // list will eventually be cleared out, allowing exit paths from
5408 // this function to return control to the driver.
5409 //
5410 continueProcessing = TRUE;
5411 }
5412
5413 //
5414 // Check to see if there are any unacknowledged requests.
5415 //
5417
5418 //
5419 // If there are still entries on the list, we potentially return
5420 // FALSE to tell the main event dispatching loop to return to
5421 // the device driver, since we are awaiting response from
5422 // the driver while in this state.
5423 //
5424
5426 "Power Stop: Waiting for Driver to complete or "
5427 "acknowledge in-flight requests on WDFQUEUE 0x%p",
5428 GetObjectHandle());
5429
5430 return continueProcessing;
5431 }
5432
5433 //
5434 // Check to see if there are any requests in the middle of two-phase-completion.
5435 // If so, bail out and wait.
5436 //
5437 if (m_TwoPhaseCompletions != 0) {
5438
5440 "Power Stop: Waiting for Driver to complete or "
5441 "acknowledge in-flight requests on WDFQUEUE 0x%p",
5442 GetObjectHandle());
5443
5444 return continueProcessing;
5445 }
5446
5447 //
5448 // All the requests are acknowledged. We will signal the pnp thread waiting
5449 // in StopProcessingForPower to continue if we are the last one to visit
5450 // the dispatch event loop.
5451 //
5452 //
5453 if ( m_Dispatching == 1) {
5454
5455 //
5456 // If we are the last routine actively dispatching callbacks to
5457 // the device driver under a Power stop, then we must set the
5458 // event specifying no more callbacks are active.
5459 //
5460
5462 "Power Stop: WDFQUEUE 0x%p is now powered off with no "
5463 "in-flight requests",GetObjectHandle());
5464
5466
5467 m_PowerIdle.Set();
5468
5469 return TRUE;
5470 }
5471
5472 //
5473 // The driver has acknowledged all requests, and the
5474 // notification list is empty. But, there are still outstanding
5475 // dispatch calls into the driver (m_Dispatching != 1), so we potentially
5476 // return false here to hopefully unwind to the final dispatch routine,
5477 // which will set the power off state.
5478 //
5479
5481 "Power Stop: Driver has acknowledged all in-flight "
5482 "requests, but WDFQUEUE 0x%p has outstanding callbacks",
5483 GetObjectHandle());
5484
5485 return continueProcessing;
5486 }
5488
5489 //
5490 // Power is being resumed to the device. We notify the
5491 // device driver by an event callback for all driver
5492 // owned requests that it has idled due to a previous
5493 // power stop.
5494 //
5496
5497 // This should be empty on entry to this state
5499
5500 if (!IsListEmpty(&m_DriverOwned)) {
5501
5503 "Power Resume: Driver has power paused requests "
5504 "on WDFQUEUE 0x%p",GetObjectHandle());
5505
5506 // Ensure the logic of m_DriverOwned is correct
5509
5510 //
5511 // Move all requests on m_DriverOwned to m_PowerNotify
5512 //
5517
5518 // This is now empty
5520 }
5521 else {
5523 "Power Resume: Driver has no power paused requests "
5524 "on WDFQUEUE 0x%p", GetObjectHandle());
5525 }
5526
5527 //
5528 // Return to main processing loop which will callback to
5529 // process notifications
5530 //
5531 return TRUE;
5532
5533
5535
5536 FxIoQueueIoResume resumeCallback;
5537
5538 //
5539 // If the list of requests to notify the driver about is
5540 // empty, change to the notified state.
5541 //
5542 if (IsListEmpty(&m_PowerNotify)) {
5543
5545
5546 //
5547 // Return to main processing loop which will callback to
5548 // process the next state
5549 //
5550 return TRUE;
5551 }
5552
5553 //
5554 // Notify each entry in m_PowerNotify into the driver, placing them
5555 // back on the m_DriverOwned list.
5556 //
5557
5558 // Remove from the notify list, place it on the driver owned list
5560
5562
5563 // Retrieve the FxRequest
5565
5566 resumeCallback = m_IoResume;
5567
5568 // Notify driver by callback
5569 if (resumeCallback.Method != NULL && pRequest->m_Canceled == FALSE) {
5570
5572 "Power Resume, Notifying Driver, WDFQUEUE 0x%p, "
5573 "WDFREQUEST 0x%p",
5576
5577 // Driver could be calling RequestComplete as we attempt to resume
5579
5581
5582 resumeCallback.Invoke(GetHandle(), pRequest->GetHandle());
5583
5584 pRequest->RELEASE(FXREQUEST_HOLD_TAG);
5585
5587 }
5588 else {
5590 "Power Resume: Driver has no callback for "
5591 "EvtIoResume registered on WDFQUEUE 0x%p",GetObjectHandle());
5592 }
5593
5594 // Return to main processing loop and continue processing notifications
5595 return TRUE;
5596 }
5597
5599
5601 "Power Resume: WDFQUEUE 0x%p is now powered on and "
5602 "I/O has resumed",GetObjectHandle());
5603
5604 // Power state has resumed
5606
5607 //
5608 // We will resume dispatching I/O after all the queues
5609 // are moved into PowerOn state.
5610 //
5611 return FALSE;
5612
5613
5614 default:
5615 // Called on invalid state
5616 ASSERT(FALSE);
5617 return FALSE;
5618 }
5619
5620 /* NOTREACHED*/
5621}
5622
5624VOID
5625FxIoQueue::ProcessAcknowledgedRequests(
5627 __out PKIRQL PreviousIrql
5628 )
5629/*++
5630
5631Routine Description:
5632
5633 Process requests that are acknowledged by the driver.
5634
5635 Called with the queue lock held. This function can drop
5636 and reacquire the lock if needed.
5637
5638Return Value:
5639
5640--*/
5641{
5643 BOOLEAN requeue;
5645
5647
5648 ASSERT(Request->IsPowerStopAcknowledged());
5649
5650 requeue = Request->IsPowerStopAcknowledgedWithRequeue();
5651
5653 "Acknowledging WDFREQUEST %p on WDFQUEUE %p %s requeue option",
5654 Request->GetObjectHandle(), GetObjectHandle(),
5655 (requeue ? "with" : "without"));
5656
5657 Request->ClearPowerStopState();
5658
5659 //
5660 // Remove the request from the m_PowerDriverNotified list and
5661 // place it back on the m_DriverOwned list.
5662 //
5663 // N.B. Our caller guarantees that we have already been removed, thus we
5664 // must not explicitly remove here.
5665 //
5666 Entry = Request->GetListEntry(FxListEntryDriverOwned);
5667
5669
5670 InsertTailList(&this->m_DriverOwned, Entry);
5671
5673 //
5674 // As soon as we drop the lock below the request may get completed.
5675 // So take an addition reference so that we can safely clear the
5676 // flag.
5677 //
5678 Request->ADDREF(FXREQUEST_HOLD_TAG);
5679 }
5680
5682
5685 Request->RELEASE(FXREQUEST_HOLD_TAG);
5686 }
5687
5688 if (requeue) {
5689 FxRequestCompletionState oldState;
5691
5693 Request->ClearVerifierFlags(FXREQUEST_FLAG_DRIVER_OWNED |
5695 }
5696
5697 //
5698 // If the device driver requests it back on the queue, we will place it
5699 // on the front and it will be re-delivered in the normal EvtIoDefault, ... path.
5700 //
5701 // EvtIoResume *will not* be called on power resume for this request.
5702 //
5703
5704 //
5705 // The request has only one reference, held by the completion
5706 // callback function. We need to take another one before cancelling
5707 // this function, otherwise we will lose the request object
5708 //
5710
5711 // Cancel the request complete callback (deletes a reference)
5712 oldState = Request->SetCompletionState(FxRequestCompletionStateNone);
5714 UNREFERENCED_PARAMETER(oldState);
5715
5717
5718 //
5719 // We are going to place the request back on the queue
5720 //
5721
5722 // Driver is returning I/O
5724
5725 //
5726 // Check if we need to delete this request.
5727 //
5729 //
5730 // Do not requeue this request.
5731 //
5733 }
5734 else {
5735 //
5736 // Place the request back at the head of the main queue
5737 // so as not to re-order requests
5738 //
5739 status = Request->InsertHeadIrpQueue(&m_Queue, NULL);
5740 }
5741
5742 if (!NT_SUCCESS(status)) {
5743
5744 // Request not placed in queue, cancel it
5746
5748
5749 //
5750 // We must add a reference since the CancelForQueue path
5751 // assumes we were on the FxIrpQueue with the extra reference
5752 //
5754
5755 //
5756 // Mark the request as cancelled, place it on the cancel list,
5757 // and schedule the cancel event to the driver
5758 //
5759 CancelForQueue(Request, *PreviousIrql);
5760
5761 //
5762 // Reacquire the lock because CancelForQueue visits the dispatch-loop
5763 // and releases the lock.
5764 //
5766 }
5767 else {
5768 // Check if went from no requests to have requests
5770 }
5771
5772 } else {
5774 }
5775
5776 return;
5777}
5778
5779VOID
5781 )
5782/*++
5783
5784 Routine Description:
5785
5786 Purpose of this routine is to put the queue in state that would
5787 prevent any new requests from being dispatched to the driver.
5788
5789Arguments:
5790
5791Return Value:
5792
5793 VOID
5794
5795--*/
5796{
5797 KIRQL irql;
5799
5800 if(m_PowerManaged == FALSE) {
5801 return;
5802 }
5803
5804 Lock(&irql);
5805
5806 if (m_Deleted == FALSE) {
5808 }
5809
5811
5812 // We must wait on the current thread until the queue is actually idle
5814
5815 //
5816 // Run the event dispatching loop before waiting on the event
5817 // in case this thread actually performs the transition
5818 //
5819 result = DispatchEvents(irql);
5820 if(result) {
5821 //
5822 // This is called from a kernel mode PNP thread, so we do not need
5823 // a KeEnterCriticalRegion()
5824 //
5826 "Waiting for all threads to stop dispatching requests"
5827 " so that WDFQUEUE 0x%p can be powered off",
5828 GetObjectHandle());
5829
5831 "waiting for all threads to stop dispatching requests so "
5832 "that queue can be powered off, WDFQUEUE", GetHandle(),
5833 GetDriverGlobals()->FxVerifierDbgWaitForSignalTimeoutInSec,
5835 }
5836
5837 return;
5838}
5839
5840VOID
5843 )
5844/*++
5845
5846 Routine Description:
5847
5848 Stops automatic I/O processing due to a power event that requires I/O to stop.
5849
5850 This is called on a PASSIVE_LEVEL thread that can block until
5851 I/O has been stopped, or completed/cancelled.
5852
5853 Additional reference is already taken on the object by the caller
5854 to prevent the queue from being deleted.
5855
5856
5857Arguments:
5858
5859 Action -
5860
5861 FxIoStopProcessingForPowerHold:
5862 the function returns when the driver has acknowledged that it has
5863 stopped all I/O processing, but may have outstanding "in-flight" requests
5864 that have not been completed.
5865
5866 FxIoStopProcessingForPowerPurgeManaged:
5867 the function returns when all requests from a power managed queue have
5868 been completed and/or cancelled., and there are no more in-flight requests.
5869
5870 FxIoStopProcessingForPowerPurgeNonManaged:
5871 the function returns when all requests from a non-power managed queue have
5872 been completed and/or cancelled., and there are no more in-flight requests.
5873
5874Return Value:
5875
5876 NTSTATUS
5877
5878--*/
5879{
5880 KIRQL irql;
5882
5883 switch (Action) {
5885
5886 //
5887 // If power managed, leave it alone
5888 //
5889 if(m_PowerManaged == TRUE) {
5890 // Should be powered off by now.
5892 return;
5893 }
5894
5895 //
5896 // Queue is being shut down. This flag prevents the following:
5897 // (1) a race condition where a dispatch queue handler changes the
5898 // state of the queue to accept_requests while we are in the
5899 // middle of a power stopping (purge) operation
5900
5901 // (2) another thread calling Stop or Start on a queue that is in the
5902 // middle of a power stopping (purge) operation.
5903 //
5904 Lock(&irql);
5906 Unlock(irql);
5907
5909
5910 Lock(&irql);
5911 //
5912 // Queue must be in PowerOn state.
5913 //
5915
5917
5918 break;
5919
5921
5922 //
5923 // If not power managed, leave it alone
5924 //
5925 if(m_PowerManaged == FALSE) {
5927 return;
5928 }
5929
5930 //
5931 // Queue is being shut down. This flag prevents the following:
5932 // (1) a race condition where a dispatch queue handler changes the
5933 // state of the queue to accept_requests while we are in the
5934 // middle of a power stopping (purge) operation
5935
5936 // (2) another thread calling Stop or Start on a queue that is in the
5937 // middle of a power stopping (purge) operation.
5938 //
5939 Lock(&irql);
5941 Unlock(irql);
5942
5944
5945 Lock(&irql);
5946
5948
5949 break;
5950
5952 //
5953 // If not power managed, leave it alone
5954 //
5955 if(m_PowerManaged == FALSE) {
5957 return;
5958 }
5959
5960 Lock(&irql);
5961
5963
5964 break;
5965
5966 default:
5967 ASSERT(FALSE);
5968 return;
5969 }
5970
5971 // We must wait on the current thread until the queue is actually idle
5973
5974 //
5975 // Run the event dispatching loop before waiting on the event
5976 // in case this thread actually performs the transition
5977 //
5978 result = DispatchEvents(irql);
5979 if(result) {
5980 //
5981 // This is called from a kernel mode PNP thread, so we do not need
5982 // a KeEnterCriticalRegion()
5983 //
5985 "Waiting for all inflight requests to be acknowledged "
5986 " on WDFQUEUE 0x%p",
5987 GetObjectHandle());
5988
5990 "waiting for all inflight requests "
5991 "to be acknowledged on WDFQUEUE",
5992 GetHandle(),
5993 GetDriverGlobals()->FxVerifierDbgWaitForSignalTimeoutInSec,
5995 }
5996
5997 return;
5998}
5999
6000VOID
6002 VOID
6003 )
6004/*++
6005 Routine Description: Start dispatching I/Os
6006
6007 Arguments: VOID
6008
6009 Return Value: VOID
6010--*/
6011{
6012 KIRQL irql;
6013
6014 if(m_PowerManaged == FALSE) {
6016 return;
6017 }
6018
6019 Lock(&irql);
6020
6021 if (m_Deleted == FALSE) {
6023 }
6024
6025 //
6026 // If there are requests in the queue when we power up, we
6027 // should set m_TransitionFromEmpty to trigger event-ready notify
6028 // callback on the manual queue to kick start processing of requests.
6029 // If we don't set, there is a posibility for abandoning the requests in the
6030 // the queue if the queue is powered off between the time we call
6031 // ProcessReadNotify and the call to retrieve requests made by the driver
6032 // because the retrieve call will fail and the request will be left in the
6033 // queue with m_TransitionFromEmpty state cleared.
6034 //
6035 if (m_Queue.GetRequestCount() > 0L) {
6038 }
6039
6040 DispatchEvents(irql);
6041
6042 return;
6043}
6044
6045VOID
6047 VOID
6048 )
6049/*++
6050
6051 Routine Description:
6052
6053 Resumes a PowerManaged queue for automatic I/O processing due to
6054 a power event that allows I/O to resume.
6055
6056 Does nothing if its a non-power managed queue.
6057
6058 Additional reference is already taken on the object by the caller
6059 to prevent the queue from being deleted.
6060
6061Arguments:
6062
6063Return Value:
6064
6065 NTSTATUS
6066
6067--*/
6068{
6069 KIRQL irql;
6070
6071 //
6072 // If not power managed, leave it alone
6073 //
6074 if (!m_PowerManaged) {
6076 return;
6077 }
6078
6079 Lock(&irql);
6080
6082 Unlock(irql);
6083 return;
6084 }
6085
6087
6089
6090 //
6091 // We have transitioned to a status that resumes
6092 // processing, so call dispatch function.
6093 //
6094
6095 DispatchEvents(irql);
6096
6097 return;
6098}
6099
6100VOID
6102 VOID
6103 )
6104/*++
6105
6106Routine Description:
6107 The queue is shutting down. Disable WdfQueueStart/Stop from re-enabling
6108 the AcceptRequest bit.
6109
6110Arguments:
6111 None
6112
6113Return Value:
6114 None
6115
6116 --*/
6117{
6118 //
6119 // No need to take a lock since caller is responsible for providing the
6120 // required synchronization.
6121 //
6122
6123 //
6124 // Do not allow request to be queued.
6125 //
6127}
6128
6129VOID
6131 VOID
6132 )
6133/*++
6134
6135Routine Description:
6136 This is called on a device (PDO) which has been restarted from the removed
6137 state. It will reset purged queues so that it can accept new requests
6138 when ResumeProcessingForPower is called afterwards.
6139
6140 Additional reference is already taken on the object by the caller
6141 to prevent the queue from being deleted.
6142
6143
6144Arguments:
6145 None
6146
6147Return Value:
6148 None
6149
6150 --*/
6151{
6152 KIRQL irql;
6153
6154 Lock(&irql);
6155
6156 //
6157 // For non power managed queues, let us reset the m_PowerState to On
6158 //
6159 if (!m_PowerManaged) {
6161 }
6162
6163 //
6164 // Allow requests to be queued.
6165 //
6167
6168 //
6169 // No need to visit the DispatchEvents because the PowerState
6170 // is still off.
6171 //
6172 Unlock(irql);
6173
6174 return;
6175}
6176
6177BOOLEAN
6180 )
6181/*++
6182
6183Routine Description:
6184 Given a request type, this function checks to see if the appropriate
6185 event handler is registered to receive dispatched requests.
6186
6187Return Value:
6188
6189 TRUE - yes the queue is configured to dispatch requests of given RequestType
6190 FALSE - no, the queue cannot dispatch requests of given RequestType
6191
6192--*/
6193{
6195 //
6196 // Manual queues wouldn't have any IoEvent callbacks registered.
6197 //
6198 return TRUE;
6199 }
6200
6201 //
6202 // Default handler is a catch all handler.
6203 //
6204 if(m_IoDefault.Method != NULL) {
6205 return TRUE;
6206 }
6207
6208 //
6209 // Default handle is not registered. So check to see if request specific
6210 // handler is registered.
6211 //
6212 switch(RequestType) {
6213 case WdfRequestTypeRead:
6214 if(m_IoRead.Method == NULL) {
6215 return FALSE;
6216 }
6217 break;
6219 if(m_IoWrite.Method == NULL) {
6220 return FALSE;
6221 }
6222 break;
6225 return FALSE;
6226 }
6227 break;
6230 return FALSE;
6231 }
6232 break;
6233 case WdfRequestTypeCreate: // Fall through. Must have default handler.
6234 default:
6235 return FALSE;
6236 }
6237
6238 return TRUE;
6239}
6240
6241VOID
6244 )
6245/*++
6246
6247Routine Description:
6248 Thunk used when requests must be posted to a workitem.
6249
6250--*/
6251{
6253
6254 PFX_DRIVER_GLOBALS FxDriverGlobals = pQueue->GetDriverGlobals();
6255
6257 "Dispatching requests from worker thread");
6258
6260
6261 return;
6262}
6263
6264
6265VOID
6267 __in PKDPC Dpc,
6271 )
6272/*++
6273
6274Routine Description:
6275 Thunk used when requests must be posted to a DPC.
6276
6277--*/
6278{
6280
6281 PFX_DRIVER_GLOBALS FxDriverGlobals = pQueue->GetDriverGlobals();
6282
6286
6288 "Dispatching requests from DPC");
6289
6291
6292 return;
6293}
6294
6295VOID
6297 __in WDFQUEUE Queue,
6299 )
6300/*++
6301
6302Routine Description:
6303 Callback function when a queue purge completes
6304
6305--*/
6306{
6307 MxEvent* event = (MxEvent*)Context;
6308
6310
6311 event->SetWithIncrement(EVENT_INCREMENT);
6312
6313 return;
6314}
6315
6316VOID
6318 __in WDFQUEUE Queue,
6320 )
6321/*++
6322
6323Routine Description:
6324 Callback function when a stop completes
6325
6326--*/
6327{
6328 MxEvent* event = (MxEvent*)Context;
6329
6331
6332 event->SetWithIncrement(EVENT_INCREMENT);
6333
6334 return;
6335}
6336
6338VOID
6341 )
6342{
6344
6345 RtlZeroMemory(&data, sizeof(data));
6346
6347 data.Queue = GetHandle();
6348 data.Request = NULL;
6349 data.Status = Status;
6350
6353 (ULONG_PTR) &data);
6354}
6355
6356
6361 )
6362/*++
6363
6364Routine Description:
6365 Called by Fxpkgio::Dispatch to allocate a reserved request if one is
6366 avaialble.
6367
6368--*/
6369
6370{
6374 PWDF_OBJECT_ATTRIBUTES reqAttribs;
6375
6377 *Request = NULL;
6378 reqAttribs = NULL;
6379
6380 //
6381 // Get the right context for this request object.
6382 //
6383 if (GetCxDeviceInfo() != NULL) {
6384 reqAttribs = &GetCxDeviceInfo()->RequestAttributes;
6385 }
6386 else {
6387 reqAttribs = m_Device->GetRequestAttributes();
6388 }
6389
6390 //
6391 // FxRequest::_Create doesn't create a Request from the Device lookaside
6392 // hence we can't use that as the Request Context doesn't get associated
6393 // if the Request is not created from the lookaside.
6394 //
6396 if (!NT_SUCCESS(status)) {
6398 "Failure to allocate request %!STATUS!", status);
6399 return status;
6400 }
6401
6404
6405 //
6406 // This is used to return the request to the correct queue if it was
6407 // forwarded
6408 //
6411
6413
6415
6417 GetHandle(),
6418 pRequest->GetHandle());
6419 if (!NT_SUCCESS(status)) {
6421 "Failure from m_IoReservedResourcesAllocate callback %!STATUS!",
6422 status);
6424 }
6425 }
6426
6427 if (NT_SUCCESS(status)) {
6428 *Request = pRequest;
6429 }
6430
6431 return status;
6432}
6433
6434
6435VOID
6437 __in PLIST_ENTRY IrpListHead
6438 )
6439/*++
6440
6441Routine Description:
6442
6443 This function is called to purge (cancel) the specified list of IRPs.
6444 The IRP's Tail.Overlay.ListEntry field must be used to link these structs together.
6445
6446--*/
6447{
6448 MdIrp irp;
6449 FxIrp fxIrp;
6451
6452 while(!IsListEmpty(IrpListHead)) {
6453
6454 entry = RemoveHeadList(IrpListHead);
6455
6457
6458 fxIrp.SetIrp(irp);
6459
6463 }
6464}
6465
6466VOID
6469 )
6470/*++
6471
6472Routine Description:
6473
6474 This function is called when the queue is purged.
6475
6476--*/
6477{
6478 LIST_ENTRY cleanupList;
6479
6480 InitializeListHead(&cleanupList);
6481 GetForwardProgressIrps(&cleanupList, FileObject);
6482 CancelIrps(&cleanupList);
6483}
6484
6485VOID
6487 VOID
6488 )
6489/*++
6490
6491Routine Description:
6492 Called from dispose to Free all the reserved requests.
6493
6494--*/
6495{
6496 ULONG countOfInUseRequests;
6497 ULONG countOfFreeRequests;
6498 PLIST_ENTRY thisEntry, nextEntry, listHead;
6499
6500 countOfInUseRequests = 0;
6501
6503
6504 for(thisEntry = listHead->Flink;
6505 thisEntry != listHead;
6506 thisEntry = nextEntry)
6507 {
6508 nextEntry = thisEntry->Flink;
6509 countOfInUseRequests++;
6510 }
6511
6512 countOfFreeRequests = 0;
6513
6515
6516 for(thisEntry = listHead->Flink;
6517 thisEntry != listHead;
6518 thisEntry = nextEntry)
6519 {
6520 nextEntry = thisEntry->Flink;
6521 countOfFreeRequests++;
6522 }
6523
6524 ASSERT(countOfFreeRequests + countOfInUseRequests ==
6526 return;
6527}
unsigned char BOOLEAN
#define VOID
Definition: acefi.h:82
#define stat
Definition: acwin.h:99
LONG NTSTATUS
Definition: precomp.h:26
virtual _Must_inspect_result_ BOOLEAN IsOwner(VOID)=0
virtual void Initialize(FxObject *ParentObject)
virtual void Initialize(FxObject *ParentObject)
WDFDEVICE __inline GetHandle(VOID)
Definition: fxdevice.hpp:237
FxCallbackLock * GetCallbackLockPtr(__out_opt FxObject **LockObject)
VOID GetConstraints(__out_opt WDF_EXECUTION_LEVEL *ExecutionLevel, __out_opt WDF_SYNCHRONIZATION_SCOPE *SynchronizationScope)
MdDeviceObject __inline GetDeviceObject(VOID)
Definition: fxdevice.hpp:174
__inline BOOLEAN IsPnp(VOID)
Definition: fxdevice.hpp:1200
CfxDevice * m_ParentDevice
Definition: fxdevice.hpp:569
__inline PWDF_OBJECT_ATTRIBUTES GetRequestAttributes(VOID)
Definition: fxdevice.hpp:1315
FxPkgPnp * m_PkgPnp
Definition: fxdevice.hpp:670
__inline BOOLEAN IsLegacy(VOID)
Definition: fxdevice.hpp:1209
__inline BOOLEAN IsFilter()
Definition: fxdevice.hpp:1408
PFN_WDF_IO_ALLOCATE_RESOURCES_FOR_RESERVED_REQUEST Method
_Must_inspect_result_ NTSTATUS Invoke(__in WDFQUEUE Queue, __in WDFREQUEST Request)
PFN_WDF_IO_QUEUE_IO_CANCELED_ON_QUEUE Method
void Invoke(__in WDFQUEUE Queue, __in WDFREQUEST Request)
PFN_WDF_IO_QUEUE_IO_DEFAULT Method
void Invoke(__in WDFQUEUE Queue, __in WDFREQUEST Request)
PFN_WDF_IO_QUEUE_IO_DEVICE_CONTROL Method
void Invoke(__in WDFQUEUE Queue, __in WDFREQUEST Request, __in ULONG OutputBufferLength, __in ULONG InputBufferLength, __in ULONG IoControlCode)
PFN_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL Method
void Invoke(__in WDFQUEUE Queue, __in WDFREQUEST Request, __in ULONG OutputBufferLength, __in ULONG InputBufferLength, __in ULONG IoInternalControlCode)
void Invoke(__in WDFQUEUE Queue, __in WDFREQUEST Request, __in ULONG Length)
PFN_WDF_IO_QUEUE_IO_READ Method
void Invoke(__in WDFQUEUE Queue, __in WDFREQUEST Request)
PFN_WDF_IO_QUEUE_IO_RESUME Method
PFN_WDF_IO_QUEUE_STATE Method
PFN_WDF_IO_QUEUE_IO_STOP Method
void Invoke(__in WDFQUEUE Queue, __in WDFREQUEST Request, __in ULONG ActionFlags)
void Invoke(__in WDFQUEUE Queue, __in WDFREQUEST Request, __in ULONG Length)
PFN_WDF_IO_QUEUE_IO_WRITE Method
DECLSPEC_NORETURN VOID FatalError(__in NTSTATUS Status)
Definition: fxioqueue.cpp:6339
__inline VOID InsertInDriverOwnedList(__in FxRequest *Request)
Definition: fxioqueue.hpp:1451
BOOLEAN m_PassiveLevel
Definition: fxioqueue.hpp:280
__inline FxCxDeviceInfo * GetCxDeviceInfo(VOID)
Definition: fxioqueue.hpp:1360
_Must_inspect_result_ NTSTATUS QueueIdle(__in BOOLEAN CancelQueueRequests, __in_opt PFN_WDF_IO_QUEUE_STATE IdleComplete, __in_opt WDFCONTEXT Context)
Definition: fxioqueue.cpp:3584
FxObject * m_CallbackLockObjectPtr
Definition: fxioqueue.hpp:529
_Must_inspect_result_ NTSTATUS ForwardRequest(__in FxIoQueue *pDestQueue, __in FxRequest *pRequest)
Definition: fxioqueue.cpp:1712
FxSystemWorkItem * m_SystemWorkItem
Definition: fxioqueue.hpp:557
_Must_inspect_result_ NTSTATUS QueueDrainSynchronously(VOID)
Definition: fxioqueue.cpp:4177
__inline BOOLEAN IsForwardProgressQueue(VOID)
Definition: fxioqueue.hpp:1264
BOOLEAN m_PowerManaged
Definition: fxioqueue.hpp:261
WDFCONTEXT m_ReadyNotifyContext
Definition: fxioqueue.hpp:508
FxIoQueueIoDefault m_IoDefault
Definition: fxioqueue.hpp:487
BOOLEAN m_RequeueDeferredDispatcher
Definition: fxioqueue.hpp:568
MxEvent m_RequestWaitEventUm
Definition: fxioqueue.hpp:578
WDF_SYNCHRONIZATION_SCOPE m_SynchronizationScope
Definition: fxioqueue.hpp:515
__inline BOOLEAN IsState(__in WDF_IO_QUEUE_STATE State)
Definition: fxioqueue.hpp:843
BOOLEAN m_IsDevicePowerPolicyOwner
Definition: fxioqueue.hpp:463
static EVT_WDF_IO_QUEUE_STATE _IdleComplete
Definition: fxioqueue.hpp:1699
virtual ~FxIoQueue()
Definition: fxioqueue.cpp:142
__inline VOID RemoveFromDriverOwnedList(__in FxRequest *Request)
Definition: fxioqueue.hpp:1472
MxEvent m_PowerIdle
Definition: fxioqueue.hpp:571
PFXIO_FORWARD_PROGRESS_CONTEXT m_FwdProgContext
Definition: fxioqueue.hpp:241
volatile BOOLEAN m_CancelDispatchedRequests
Definition: fxioqueue.hpp:461
static _Must_inspect_result_ NTSTATUS _Create(__in PFX_DRIVER_GLOBALS DriverGlobals, __in_opt PWDF_OBJECT_ATTRIBUTES Attributes, __in PWDF_IO_QUEUE_CONFIG Config, __in_opt FxDriver *Caller, __in FxPkgIo *PkgIo, __in BOOLEAN InitialPowerStateOn, __deref_out FxIoQueue **Object)
Definition: fxioqueue.cpp:164
FxCallbackSpinLock m_CallbackSpinLock
Definition: fxioqueue.hpp:520
VOID VerifierVerifyFwdProgListsLocked(VOID)
Definition: fxioqueue.cpp:6486
_Must_inspect_result_ NTSTATUS RequestCancelable(__in FxRequest *pRequest, __in BOOLEAN Cancelable, __in_opt PFN_WDF_REQUEST_CANCEL EvtRequestCancel, __in BOOLEAN FailIfIrpIsCancelled)
Definition: fxioqueue.cpp:2093
volatile LONG m_TwoPhaseCompletions
Definition: fxioqueue.hpp:481
FxCallbackMutexLock m_CallbackMutexLock
Definition: fxioqueue.hpp:521
FxIoQueueIoDeviceControl m_IoDeviceControl
Definition: fxioqueue.hpp:492
LIST_ENTRY m_DriverOwned
Definition: fxioqueue.hpp:397
_Must_inspect_result_ NTSTATUS QueueRequest(__in FxRequest *pRequest)
Definition: fxioqueue.cpp:2245
WDF_EXECUTION_LEVEL m_ExecutionLevel
Definition: fxioqueue.hpp:514
_Must_inspect_result_ NTSTATUS QueueRequestFromForward(__in FxRequest *pRequest)
Definition: fxioqueue.cpp:2351
FxIoQueueIoState m_PurgeComplete
Definition: fxioqueue.hpp:504
static EVT_SYSTEMWORKITEM _DeferredDispatchThreadThunk
Definition: fxioqueue.hpp:1687
volatile LONG m_DriverIoCount
Definition: fxioqueue.hpp:475
FxIoQueueIoCanceledOnQueue m_IoCanceledOnQueue
Definition: fxioqueue.hpp:494
_Must_inspect_result_ NTSTATUS ForwardRequestToParent(__in FxIoQueue *DestQueue, __in FxRequest *Request, __in PWDF_REQUEST_FORWARD_OPTIONS ForwardOptions)
Definition: fxioqueue.cpp:1569
VOID GetRequestCount(__out_opt PULONG pQueuedRequests, __out_opt PULONG pDriverPendingRequests)
Definition: fxioqueue.cpp:4227
volatile BOOLEAN m_Disposing
Definition: fxioqueue.hpp:296
volatile ULONG m_Dispatching
Definition: fxioqueue.hpp:435
_Must_inspect_result_ BOOLEAN CanThreadDispatchEventsLocked(__in KIRQL PreviousIrql)
Definition: fxioqueue.cpp:2633
_Must_inspect_result_ NTSTATUS ReadyNotify(__in PFN_WDF_IO_QUEUE_STATE QueueReady, __in_opt WDFCONTEXT Context)
Definition: fxioqueue.cpp:3455
_Must_inspect_result_ NTSTATUS QueueIdleSynchronously(__in BOOLEAN CancelRequests)
Definition: fxioqueue.cpp:3838
BOOLEAN IsIoEventHandlerRegistered(__in WDF_REQUEST_TYPE RequestType)
Definition: fxioqueue.cpp:6178
static EVT_IRP_QUEUE_CANCEL _IrpCancelForDriver
Definition: fxioqueue.hpp:1683
FxIrpQueue m_DriverCancelable
Definition: fxioqueue.hpp:372
VOID FlushByFileObject(__in MdFileObject FileObject)
Definition: fxioqueue.cpp:4256
FxIoQueueIoInternalDeviceControl m_IoInternalDeviceControl
Definition: fxioqueue.hpp:493
volatile BOOLEAN m_ForceTransitionFromEmptyWhenAddingNewRequest
Definition: fxioqueue.hpp:452
FxIoQueueIoStop m_IoStop
Definition: fxioqueue.hpp:488
BOOLEAN m_Configured
Definition: fxioqueue.hpp:252
WDF_IO_QUEUE_DISPATCH_TYPE m_Type
Definition: fxioqueue.hpp:308
VOID DeferredDispatchRequestsFromDpc(VOID)
Definition: fxioqueue.cpp:2475
VOID QueueStart(VOID)
Definition: fxioqueue.cpp:3552
LIST_ENTRY m_PowerNotify
Definition: fxioqueue.hpp:405
__inline VOID CheckTransitionFromEmpty(VOID)
Definition: fxioqueue.hpp:1541
BOOLEAN m_SupportForwardProgress
Definition: fxioqueue.hpp:246
FX_IO_QUEUE_STATE m_QueueState
Definition: fxioqueue.hpp:318
FxCallbackLock * m_IoCancelCallbackLockPtr
Definition: fxioqueue.hpp:496
FxCxDeviceInfo * m_CxDeviceInfo
Definition: fxioqueue.hpp:425
NTSTATUS InsertNewRequestLocked(__deref_in FxRequest **Request, __in KIRQL PreviousIrql)
Definition: fxioqueue.cpp:2571
ULONG m_MaxParallelQueuePresentedRequests
Definition: fxioqueue.hpp:313
VOID CancelIrps(__in PLIST_ENTRY IrpListHead)
Definition: fxioqueue.cpp:6436
__in __drv_restoresIRQL KIRQL PreviousIrql
Definition: fxioqueue.hpp:631
_Must_inspect_result_ NTSTATUS GetRequest(__in_opt MdFileObject FileObject, __in_opt FxRequest *TagRequest, __deref_out FxRequest **pOutRequest)
Definition: fxioqueue.cpp:962
MxEvent m_FinishDisposing
Definition: fxioqueue.hpp:297
_Must_inspect_result_ NTSTATUS PeekRequest(__in_opt FxRequest *TagRequest, __in_opt MdFileObject FileObject, __out_opt PWDF_REQUEST_PARAMETERS Parameters, __deref_out FxRequest **pOutRequest)
Definition: fxioqueue.cpp:1197
FxIoQueueIoState m_ReadyNotify
Definition: fxioqueue.hpp:507
WDF_IO_QUEUE_STATE GetState(__out_opt PULONG pQueueCount, __out_opt PULONG pDriverCount)
Definition: fxioqueue.cpp:760
FxIoQueue(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in FxPkgIo *PkgIo)
Definition: fxioqueue.cpp:37
VOID CancelForDriver(__in FxRequest *pRequest)
Definition: fxioqueue.cpp:4535
FxIrpQueue m_Queue
Definition: fxioqueue.hpp:366
WDFCONTEXT m_PurgeCompleteContext
Definition: fxioqueue.hpp:505
VOID StartPowerTransitionOff(VOID)
Definition: fxioqueue.cpp:5780
BOOLEAN m_WorkItemQueued
Definition: fxioqueue.hpp:563
VOID FreeAllReservedRequests(__in BOOLEAN Verify)
Definition: fxioqueueum.hpp:81
SINGLE_LIST_ENTRY m_PowerSListEntry
Definition: fxioqueue.hpp:591
VOID SetStateForShutdown(VOID)
Definition: fxioqueue.cpp:6101
_Must_inspect_result_ NTSTATUS QueuePurge(__in BOOLEAN CancelQueueRequests, __in BOOLEAN CancelDriverRequests, __in_opt PFN_WDF_IO_QUEUE_STATE PurgeComplete, __in_opt WDFCONTEXT Context)
Definition: fxioqueue.cpp:3894
_Must_inspect_result_ NTSTATUS Requeue(__in FxRequest *pRequest)
Definition: fxioqueue.cpp:1933
_Must_inspect_result_ NTSTATUS QueuePurgeSynchronously(VOID)
Definition: fxioqueue.cpp:4107
FxIoQueueIoState m_IdleComplete
Definition: fxioqueue.hpp:501
__inline BOOLEAN IsPowerStateNotifyingDriver(VOID)
Definition: fxioqueue.hpp:1429
_Must_inspect_result_ NTSTATUS AllocateReservedRequest(__deref_out FxRequest **Request)
Definition: fxioqueue.cpp:6359
VOID ResetStateForRestart(VOID)
Definition: fxioqueue.cpp:6130
BOOLEAN m_DpcQueued
Definition: fxioqueue.hpp:562
VOID PurgeForwardProgressIrps(__in_opt MdFileObject FileObject)
Definition: fxioqueue.cpp:6467
_Must_inspect_result_ NTSTATUS Initialize(__in PWDF_IO_QUEUE_CONFIG pConfig, __in_opt PWDF_OBJECT_ATTRIBUTES QueueAttributes, __in_opt FxDriver *Caller, __in BOOLEAN InitialPowerStateOn)
Definition: fxioqueue.cpp:217
LIST_ENTRY m_PowerDriverNotified
Definition: fxioqueue.hpp:414
FxIoQueueIoWrite m_IoWrite
Definition: fxioqueue.hpp:491
BOOLEAN m_AllowZeroLengthRequests
Definition: fxioqueue.hpp:273
static MdDeferredRoutineType _DeferredDispatchDpcThunk
Definition: fxioqueue.hpp:1691
_Must_inspect_result_ NTSTATUS QueueDriverCreatedRequest(__in FxRequest *Request, __in BOOLEAN ParentQueue)
Definition: fxioqueue.cpp:1791
VOID FlushQueuedDpcs(VOID)
_Must_inspect_result_ NTSTATUS ConfigureConstraints(__in_opt PWDF_OBJECT_ATTRIBUTES ObjectAttributes, __in_opt FxDriver *Caller)
Definition: fxioqueue.cpp:571
VOID ResumeProcessingForPower(VOID)
Definition: fxioqueue.cpp:6046
LIST_ENTRY m_CanceledOnQueueList
Definition: fxioqueue.hpp:387
FxIoQueueIoResume m_IoResume
Definition: fxioqueue.hpp:489
KDPC m_Dpc
Definition: fxioqueue.hpp:554
VOID GetForwardProgressIrps(__in PLIST_ENTRY IrpListHead, __in_opt MdFileObject FileObject)
_Must_inspect_result_ NTSTATUS QueueDrain(__in_opt PFN_WDF_IO_QUEUE_STATE DrainComplete, __in_opt WDFCONTEXT Context)
Definition: fxioqueue.cpp:4158
volatile BOOLEAN m_TransitionFromEmpty
Definition: fxioqueue.hpp:442
WDFCONTEXT m_IdleCompleteContext
Definition: fxioqueue.hpp:502
volatile BOOLEAN m_Deleted
Definition: fxioqueue.hpp:288
VOID InsertQueueDpc(VOID)
FXIOQUEUE_POWER_STATE m_PowerState
Definition: fxioqueue.hpp:302
FxCallbackLock * m_CallbackLockPtr
Definition: fxioqueue.hpp:528
volatile BOOLEAN m_PowerReferenced
Definition: fxioqueue.hpp:267
FxPkgIo * m_PkgIo
Definition: fxioqueue.hpp:420
LIST_ENTRY m_Cancelled
Definition: fxioqueue.hpp:379
VOID StopProcessingForPower(__in FxIoStopProcessingForPowerAction Action)
Definition: fxioqueue.cpp:5841
virtual BOOLEAN Dispose(VOID)
Definition: fxioqueue.cpp:448
_Must_inspect_result_ NTSTATUS ForwardRequestWorker(__in FxRequest *Request, __in FxIoQueue *DestQueue)
Definition: fxioqueue.cpp:1354
FxIoQueueIoRead m_IoRead
Definition: fxioqueue.hpp:490
VOID SetState(__in FX_IO_QUEUE_SET_STATE NewStatus)
Definition: fxioqueue.cpp:805
VOID StartPowerTransitionOn(VOID)
Definition: fxioqueue.cpp:6001
VOID DeferredDispatchRequestsFromWorkerThread(VOID)
Definition: fxioqueue.cpp:2520
VOID DispatchRequestToDriver(__in FxRequest *pRequest)
Definition: fxioqueue.cpp:3110
static EVT_IRP_QUEUE_CANCEL _IrpCancelForQueue
Definition: fxioqueue.hpp:1674
static EVT_WDF_IO_QUEUE_STATE _PurgeComplete
Definition: fxioqueue.hpp:1695
VOID Initialize(__in FxNonPagedObject *LockObject, __in PFN_IRP_QUEUE_CANCEL Callback)
Definition: fxirpqueue.cpp:61
LONG GetRequestCount()
Definition: fxirpqueue.hpp:193
Definition: fxirp.hpp:28
UCHAR GetMajorFunction(VOID)
Definition: fxirpum.cpp:217
ULONG GetParameterWriteLength(VOID)
Definition: fxirpum.cpp:1601
VOID CompleteRequest(__in_opt CCHAR PriorityBoost=IO_NO_INCREMENT)
Definition: fxirpum.cpp:24
MdDeviceObject GetDeviceObject(VOID)
Definition: fxirpum.cpp:1352
ULONG GetParameterIoctlCode(VOID)
Definition: fxirpum.cpp:1474
MdCompletionRoutine GetNextCompletionRoutine(VOID)
Definition: fxirpum.cpp:1206
ULONG GetParameterIoctlOutputBufferLength(VOID)
Definition: fxirpum.cpp:1504
VOID SetNextIrpStackLocation(VOID)
Definition: fxirpum.cpp:1235
VOID MarkIrpPending()
Definition: fxirpum.cpp:415
VOID SkipCurrentIrpStackLocation(VOID)
Definition: fxirpum.cpp:400
VOID SetStatus(__in NTSTATUS Status)
Definition: fxirpum.cpp:457
PIO_STACK_LOCATION GetCurrentIrpStackLocation(VOID)
Definition: fxirpum.cpp:370
static MdIrp GetIrpFromListEntry(__in PLIST_ENTRY Ple)
Definition: fxirpum.cpp:1190
VOID CopyCurrentIrpStackLocationToNext(VOID)
Definition: fxirpum.cpp:209
VOID SetInformation(__in ULONG_PTR Information)
Definition: fxirpum.cpp:504
MdIrp SetIrp(MdIrp irp)
Definition: fxirpkm.hpp:71
ULONG GetParameterIoctlInputBufferLength(VOID)
Definition: fxirpum.cpp:1518
VOID SetCurrentDeviceObject(__in MdDeviceObject DeviceObject)
Definition: fxirpum.cpp:1362
ULONG GetParameterReadLength(VOID)
Definition: fxirpum.cpp:1589
void SetCallbackLockPtr(FxCallbackLock *Lock)
Definition: fxcallback.hpp:105
PVOID __inline GetObjectHandle(VOID)
Definition: fxobject.hpp:603
VOID MarkPassiveDispose(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:944
VOID SetDeviceBase(__in CfxDeviceBase *DeviceBase)
Definition: fxobject.hpp:797
virtual VOID DeleteObject(VOID)
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
CfxDevice * m_Device
Definition: fxobject.hpp:329
__drv_restoresIRQL KIRQL __in BOOLEAN Unlock
Definition: fxobject.hpp:1474
LONG GetRefCnt(VOID)
Definition: fxobject.hpp:758
CfxDeviceBase * GetDeviceBase(VOID)
Definition: fxobject.hpp:789
CfxDevice * GetDevice(VOID)
Definition: fxobject.hpp:781
virtual BOOLEAN Dispose(VOID)
VOID DeleteFromFailedCreate(VOID)
Definition: fxobject.cpp:391
VOID MarkPassiveCallbacks(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:972
VOID MarkDisposeOverride(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:1101
BOOLEAN IsCommitted(VOID)
Definition: fxobject.hpp:1087
VOID RemoveQueueReferences(__inout FxIoQueue *pQueue)
Definition: fxpkgio.cpp:1091
BOOLEAN IsPowerPolicyOwner(VOID)
Definition: fxpkgpnp.hpp:3612
__inline VOID SetVerifierFlags(__in SHORT Flags)
__inline VOID ClearVerifierFlags(__in SHORT Flags)
__inline WDFREQUEST GetHandle(VOID)
BOOLEAN __inline IsAllocatedFromIo(VOID)
__inline VOID SetCompleted(__in BOOLEAN Value)
__inline SHORT GetVerifierFlags(VOID)
FxRequestCancelCallback m_CancelRoutine
void InvokeCancel(__in FxCallbackLock *Lock, __in WDFREQUEST Request)
PFN_WDF_REQUEST_CANCEL m_Cancel
__inline NTSTATUS CompleteWithInformation(__in NTSTATUS Status, __in ULONG_PTR Information)
Definition: fxrequest.hpp:810
_Must_inspect_result_ FxIoQueue * GetCurrentQueue(VOID)
Definition: fxrequest.hpp:728
FxIrp * GetFxIrp(VOID)
Definition: fxrequest.hpp:957
_Must_inspect_result_ NTSTATUS InsertHeadIrpQueue(__in FxIrpQueue *IrpQueue, __out_opt ULONG *pRequestCount)
Definition: fxrequest.cpp:1908
static _Must_inspect_result_ FxRequest * GetNextRequest(__in FxIrpQueue *IrpQueue)
Definition: fxrequest.cpp:2025
__inline PLIST_ENTRY GetListEntry(__in FxListEntryNames Index)
Definition: fxrequest.hpp:475
VOID ClearPowerStopState(VOID)
Definition: fxrequest.hpp:1214
VOID __inline SetPresented(VOID)
Definition: fxrequest.hpp:558
static __inline FxRequest * RetrieveFromCsqContext(__in PMdIoCsqIrpContext pCsqContext)
Definition: fxrequest.hpp:1163
__inline BOOLEAN IsInIrpQueue(__in FxIrpQueue *pIrpQueue)
Definition: fxrequest.hpp:1173
FxRequestCompletionState SetCompletionState(__in FxRequestCompletionState NewState)
Definition: fxrequest.cpp:1760
_Must_inspect_result_ NTSTATUS InsertTailIrpQueue(__in FxIrpQueue *IrpQueue, __out_opt ULONG *pRequestCount)
Definition: fxrequest.cpp:1858
__inline VOID SetCurrentQueue(__in FxIoQueue *Queue)
Definition: fxrequest.hpp:649
__inline NTSTATUS Complete(__in NTSTATUS Status)
Definition: fxrequest.hpp:770
__inline VOID SetReserved()
Definition: fxrequest.hpp:617
__inline VOID MarkRemovedFromIrpQueue(VOID)
Definition: fxrequest.hpp:1100
__inline BOOLEAN IsPowerStopAcknowledged(VOID)
Definition: fxrequest.hpp:1195
__inline VOID SetForwardProgressQueue(__in FxIoQueue *Queue)
Definition: fxrequest.hpp:625
static _Must_inspect_result_ NTSTATUS _CreateForPackage(__in CfxDevice *Device, __in PWDF_OBJECT_ATTRIBUTES RequestAttributes, __in MdIrp Irp, __deref_out FxRequest **Request)
Definition: fxrequest.cpp:75
PIO_STACK_LOCATION GetCurrentIrpStackLocation(VOID)
Definition: fxrequest.hpp:1026
_Must_inspect_result_ NTSTATUS GetIrp(__deref_out MdIrp *ppIrp)
Definition: fxrequest.hpp:975
__inline BOOLEAN IsReserved()
Definition: fxrequest.hpp:609
VOID FreeRequest(VOID)
Definition: fxrequest.cpp:1022
static _Must_inspect_result_ NTSTATUS PeekRequest(__in FxIrpQueue *IrpQueue, __in_opt FxRequest *TagRequest, __in_opt MdFileObject FileObject, __out_opt PWDF_REQUEST_PARAMETERS Parameters, __deref_out FxRequest **ppOutRequest)
Definition: fxrequest.cpp:2098
_Must_inspect_result_ NTSTATUS RemoveFromIrpQueue(__in FxIrpQueue *IrpQueue)
Definition: fxrequest.cpp:1961
static FxRequest * _FromOwnerListEntry(__in FxListEntryNames Index, __in PLIST_ENTRY OwnerListEntry)
Definition: fxrequest.hpp:489
static _Must_inspect_result_ NTSTATUS _Create(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PVOID WdmObject, __out FxSystemWorkItem **pObject)
__inline BOOLEAN Enqueue(__in PFN_WDF_SYSTEMWORKITEM CallbackFunc, __in PVOID Parameter)
__inline VOID Clear()
Definition: mxeventkm.h:102
__inline VOID Set()
Definition: mxeventkm.h:91
CHECK_RETURN_IF_USER_MODE __inline NTSTATUS Initialize(__in EVENT_TYPE Type, __in BOOLEAN InitialState)
Definition: mxeventkm.h:55
MxEvent * GetSelfPointer(VOID)
Definition: mxevent.h:110
__inline VOID Uninitialize()
Definition: mxlockkm.h:104
static __inline MxThread MxGetCurrentThread()
Definition: mxgeneralkm.h:61
#define _Releases_lock_(lock)
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
_In_ PIRP Irp
Definition: csq.h:116
_Out_ PKIRQL Irql
Definition: csq.h:179
LIST_ENTRY IrpQueue
Definition: csqrtns.c:49
#define __out_opt
Definition: dbghelp.h:65
#define __in
Definition: dbghelp.h:35
#define __deref_out
Definition: dbghelp.h:26
#define __in_opt
Definition: dbghelp.h:38
#define __out
Definition: dbghelp.h:62
#define TRACINGIO
Definition: dbgtrace.h:66
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
VOID NTAPI KeInitializeDpc(IN PKDPC Dpc, IN PKDEFERRED_ROUTINE DeferredRoutine, IN PVOID DeferredContext)
Definition: dpc.c:712
static LONG QueueCount
Definition: dispatch.c:34
KIRQL irql
Definition: wave.h:1
#define __drv_restoresIRQL
Definition: driverspecs.h:322
#define __drv_requiresIRQL(irql)
Definition: driverspecs.h:321
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
UCHAR KIRQL
Definition: env_spec_w32.h:591
KIRQL * PKIRQL
Definition: env_spec_w32.h:592
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
PFX_DRIVER_GLOBALS pFxDriverGlobals
return pObject GetObjectHandle()
PFX_DRIVER_GLOBALS fxDriverGlobals
FxIrp fxIrp(Irp)
FxIoQueue * pQueue
PSINGLE_LIST_ENTRY ple
FxVerifierDbgBreakPoint(pFxDriverGlobals)
FxRequest * pRequest
DriverGlobals
@ WaitSignalBreakUnderVerifier
Definition: fxglobals.h:84
_Must_inspect_result_ NTSTATUS _In_ FxRequest * TagRequest
Definition: fxioqueue.cpp:885
_Must_inspect_result_ NTSTATUS _In_ FxRequest _In_ BOOLEAN Cancelable
Definition: fxioqueue.cpp:2051
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGIO, "WDFREQUEST 0x%p " "was cancelled in driver for WDFQUEUE 0x%p", Request->GetHandle(), GetObjectHandle())
PAGED_CODE_LOCKED()
Lock & irql
Definition: fxioqueue.cpp:924
PLIST_ENTRY pEntry
Definition: fxioqueue.cpp:4484
return STATUS_SUCCESS
Definition: fxioqueue.cpp:939
NTSTATUS status
Definition: fxioqueue.cpp:887
_Must_inspect_result_ NTSTATUS _In_ FxIoQueue * DestQueue
Definition: fxioqueue.cpp:1476
SHORT OldFlags
Definition: fxioqueue.cpp:1325
VOID _In_ FxRequest * pRequest
Definition: fxioqueue.cpp:947
_Must_inspect_result_ NTSTATUS _In_ FxIoQueue * pDestQueue
Definition: fxioqueue.cpp:1667
SHORT _In_ FxRequest * Request
Definition: fxioqueue.cpp:1323
@ FxIoQueueClearShutdown
Definition: fxioqueue.hpp:201
@ FxIoQueueSetAcceptRequests
Definition: fxioqueue.hpp:196
@ FxIoQueueSetShutdown
Definition: fxioqueue.hpp:200
@ FxIoQueueClearDispatchRequests
Definition: fxioqueue.hpp:199
@ FxIoQueueSetDispatchRequests
Definition: fxioqueue.hpp:198
@ FxIoQueueClearAcceptRequests
Definition: fxioqueue.hpp:197
@ FxIoQueueNodeTypeQueue
Definition: fxioqueue.hpp:46
@ FxIoQueueShutdown
Definition: fxioqueue.hpp:229
@ FxIoQueuePowerStartingTransition
Definition: fxioqueue.hpp:134
@ FxIoQueuePowerPurgeDriverNotified
Definition: fxioqueue.hpp:140
@ FxIoQueuePowerRestarting
Definition: fxioqueue.hpp:141
@ FxIoQueuePowerStoppingDriverNotified
Definition: fxioqueue.hpp:137
@ FxIoQueuePowerRestartingNotifyingDriver
Definition: fxioqueue.hpp:142
@ FxIoQueuePowerStopping
Definition: fxioqueue.hpp:135
@ FxIoQueuePowerStoppingNotifyingDriver
Definition: fxioqueue.hpp:136
@ FxIoQueuePowerPurgeNotifyingDriver
Definition: fxioqueue.hpp:139
@ FxIoQueuePowerOn
Definition: fxioqueue.hpp:132
@ FxIoQueuePowerPurge
Definition: fxioqueue.hpp:138
@ FxIoQueuePowerOff
Definition: fxioqueue.hpp:133
@ FxIoQueuePowerRestartingDriverNotified
Definition: fxioqueue.hpp:143
enum _FX_IO_QUEUE_STATE FX_IO_QUEUE_STATE
enum _FX_IO_QUEUE_SET_STATE FX_IO_QUEUE_SET_STATE
__in WDFQUEUE __out_opt PULONG __out_opt PULONG DriverCount
#define FX_VF_METHOD(classname, fnName)
Definition: fxmacros.hpp:43
@ ObjectDoNotLock
Definition: fxobject.hpp:128
FxIoStopProcessingForPowerAction
@ FxIoStopProcessingForPowerHold
@ FxIoStopProcessingForPowerPurgeNonManaged
@ FxIoStopProcessingForPowerPurgeManaged
void FxPoolFree(__in_xcount(ptr is at an offset from AllocationStart) PVOID ptr)
Definition: wdfpool.cpp:361
#define FXREQUEST_STATE_TAG
Definition: fxrequest.hpp:42
#define FXREQUEST_HOLD_TAG
Definition: fxrequest.hpp:58
#define FXREQUEST_COMPLETE_TAG
Definition: fxrequest.hpp:52
@ FxListEntryDriverOwned
Definition: fxrequest.hpp:378
@ FxListEntryQueueOwned
Definition: fxrequest.hpp:375
#define FXREQUEST_FWDPRG_TAG
Definition: fxrequest.hpp:63
#define FXREQUEST_QUEUE_TAG
Definition: fxrequest.hpp:47
FxIrp * pIrp
UCHAR majorFunction
FxIrp * irp
@ FXREQUEST_FLAG_TAG_REQUEST
@ FXREQUEST_FLAG_CANCELLED
@ FXREQUEST_FLAG_DRIVER_CANCELABLE
@ FXREQUEST_FLAG_DRIVER_IN_EVTIOSTOP_CONTEXT
@ FXREQUEST_FLAG_FORWARDED
@ FXREQUEST_FLAG_DRIVER_DISPATCH
@ FXREQUEST_FLAG_DRIVER_OWNED
FxRequestCompletionState
@ FxRequestCompletionStateQueue
@ FxRequestCompletionStateNone
@ FX_TYPE_QUEUE
Definition: fxtypes.h:48
#define FxVerifierBugCheck(FxDriverGlobals, Error,...)
Definition: fxverifier.h:58
Status
Definition: gdiplustypes.h:25
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
struct _cl_event * event
Definition: glext.h:7739
GLuint64EXT * result
Definition: glext.h:11304
uint32_t entry
Definition: isohybrid.c:63
#define ASSERT(a)
Definition: mode.c:44
static IPrintDialogCallback callback
Definition: printdlg.c:326
#define _Inout_
Definition: ms_sal.h:378
#define _Must_inspect_result_
Definition: ms_sal.h:558
#define _In_
Definition: ms_sal.h:308
#define DO_NOTHING()
Definition: mxgeneral.h:32
PFILE_OBJECT MdFileObject
Definition: mxgeneralkm.h:32
IWudfIrp * MdIrp
Definition: mxum.h:103
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
#define DECLSPEC_NORETURN
Definition: ntbasedef.h:176
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
@ NotificationEvent
@ SynchronizationEvent
@ Unlock
Definition: ntsecapi.h:294
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:322
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
#define L(x)
Definition: ntvdm.h:50
short SHORT
Definition: pedump.c:59
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define __deref_in
Definition: specstrings.h:137
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
base of all file and directory entries
Definition: entries.h:83
WDF_OBJECT_ATTRIBUTES RequestAttributes
FxIoQueueForwardProgressAllocateResourcesReserved m_IoReservedResourcesAllocate
Definition: fxioqueue.hpp:156
BOOLEAN FxVerifierOn
Definition: fxglobals.h:420
_Must_inspect_result_ BOOLEAN IsVersionGreaterThanOrEqualTo(__in ULONG Major, __in ULONG Minor)
Definition: globalskm.cpp:92
VOID WaitForSignal(__in MxEvent *Event, __in PCSTR ReasonForWaiting, __in PVOID Handle, __in ULONG WarningTimeoutInSec, __in ULONG WaitSignalFlags)
Definition: globals.cpp:1705
Definition: ketypes.h:699
Definition: typedefs.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:629
Definition: tftpd.h:86
Definition: stat.h:55
Definition: ps.c:97
#define GetHandle(h)
Definition: treelist.c:116
uint32_t * PULONG
Definition: typedefs.h:59
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INVALID_DEVICE_STATE
Definition: udferr_usr.h:178
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
@ WDF_QUEUE_FATAL_ERROR
Definition: wdfbugcodes.h:67
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_CHILD_LIST_CONFIG Config
Definition: wdfchildlist.h:476
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
_Must_inspect_result_ _In_ WDFDMAENABLER _In_ _In_opt_ PWDF_OBJECT_ATTRIBUTES Attributes
_Must_inspect_result_ _In_ WDFDRIVER Driver
Definition: wdfcontrol.h:83
enum _WDF_REQUEST_TYPE WDF_REQUEST_TYPE
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_Must_inspect_result_ _In_ WDFDEVICE _In_ PIRP _In_ WDFQUEUE Queue
Definition: wdfdevice.h:2225
@ WdfRequestTypeDeviceControlInternal
Definition: wdfdevice.h:518
@ WdfRequestTypeCreate
Definition: wdfdevice.h:503
@ WdfRequestTypeWrite
Definition: wdfdevice.h:507
@ WdfRequestTypeRead
Definition: wdfdevice.h:506
@ WdfRequestTypeDeviceControl
Definition: wdfdevice.h:517
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFQUEUE _In_ _Strict_type_match_ WDF_REQUEST_TYPE RequestType
Definition: wdfdevice.h:4233
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
_Must_inspect_result_ _In_ PWDF_DPC_CONFIG _In_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFDPC * Dpc
Definition: wdfdpc.h:112
EVT_WDF_IO_QUEUE_STATE * PFN_WDF_IO_QUEUE_STATE
Definition: wdfio.h:380
_In_ WDFQUEUE _In_opt_ PFN_WDF_IO_QUEUE_STATE PurgeComplete
Definition: wdfio.h:1030
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ WDFREQUEST _In_opt_ WDFFILEOBJECT _Inout_opt_ PWDF_REQUEST_PARAMETERS Parameters
Definition: wdfio.h:869
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_IO_QUEUE_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES QueueAttributes
Definition: wdfio.h:617
@ WdfIoQueueDriverNoRequests
Definition: wdfio.h:128
@ WdfIoQueueAcceptRequests
Definition: wdfio.h:125
@ WdfIoQueueDispatchRequests
Definition: wdfio.h:126
@ WdfIoQueueNoRequests
Definition: wdfio.h:127
@ WdfIoQueuePnpHeld
Definition: wdfio.h:129
_In_ WDFREQUEST _In_ ULONG ActionFlags
Definition: wdfio.h:255
@ WdfIoQueueDispatchSequential
Definition: wdfio.h:78
@ WdfIoQueueDispatchMax
Definition: wdfio.h:81
@ WdfIoQueueDispatchInvalid
Definition: wdfio.h:77
@ WdfIoQueueDispatchParallel
Definition: wdfio.h:79
@ WdfIoQueueDispatchManual
Definition: wdfio.h:80
_Must_inspect_result_ _In_ WDFQUEUE _In_opt_ PFN_WDF_IO_QUEUE_STATE QueueReady
Definition: wdfio.h:1067
enum _WDF_IO_QUEUE_STATE WDF_IO_QUEUE_STATE
_In_ WDFIOTARGET _In_ _Strict_type_match_ WDF_IO_TARGET_SENT_IO_ACTION Action
Definition: wdfiotarget.h:510
@ WdfSynchronizationScopeInheritFromParent
Definition: wdfobject.h:63
@ WdfSynchronizationScopeQueue
Definition: wdfobject.h:65
@ WdfSynchronizationScopeDevice
Definition: wdfobject.h:64
@ WdfExecutionLevelPassive
Definition: wdfobject.h:54
@ WdfExecutionLevelInheritFromParent
Definition: wdfobject.h:53
WDF_EXTERN_C_START enum _WDF_EXECUTION_LEVEL WDF_EXECUTION_LEVEL
enum _WDF_SYNCHRONIZATION_SCOPE WDF_SYNCHRONIZATION_SCOPE
_Must_inspect_result_ _In_ WDFREQUEST _In_ WDFQUEUE _In_ PWDF_REQUEST_FORWARD_OPTIONS ForwardOptions
Definition: wdfrequest.h:1736
@ WdfRequestStopRequestCancelable
Definition: wdfrequest.h:104
@ WdfRequestStopActionSuspend
Definition: wdfrequest.h:102
@ WdfRequestStopActionPurge
Definition: wdfrequest.h:103
EVT_WDF_REQUEST_CANCEL * PFN_WDF_REQUEST_CANCEL
Definition: wdfrequest.h:130
_In_ WDFREQUEST _In_ PFN_WDF_REQUEST_CANCEL EvtRequestCancel
Definition: wdfrequest.h:730
#define STATUS_WDF_PAUSED
Definition: wdfstatus.h:117
#define STATUS_WDF_NO_CALLBACK
Definition: wdfstatus.h:189
#define STATUS_WDF_BUSY
Definition: wdfstatus.h:126
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127
@ WdfTrue
Definition: wdftypes.h:88
@ WdfUseDefault
Definition: wdftypes.h:89
@ WdfFalse
Definition: wdftypes.h:87
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
_In_ BOOLEAN Cancelable
Definition: iofuncs.h:1258
#define EVENT_INCREMENT
Definition: iotypes.h:597
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IRP_MJ_INTERNAL_DEVICE_CONTROL
_In_opt_ PVOID _In_opt_ PVOID SystemArgument1
Definition: ketypes.h:688
_In_opt_ PVOID DeferredContext
Definition: ketypes.h:687
_In_opt_ PVOID _In_opt_ PVOID _In_opt_ PVOID SystemArgument2
Definition: ketypes.h:689
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:323
unsigned char UCHAR
Definition: xmlstorage.h:181