ReactOS 0.4.15-dev-7897-g78dc504
fxiotarget.cpp
Go to the documentation of this file.
1/*++
2
3Copyright (c) Microsoft Corporation
4
5Module Name:
6
7 FxIoTarget.cpp
8
9Abstract:
10
11 This module implements the IO Target APIs
12
13Author:
14
15Environment:
16
17 Both kernel and user mode
18
19Revision History:
20
21--*/
22
23
24#include "../fxtargetsshared.hpp"
25
26extern "C" {
27#if defined(EVENT_TRACING)
28#include "FxIoTarget.tmh"
29#endif
30}
31
33
35 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
36 __in USHORT ObjectSize
37 ) :
38 FxNonPagedObject(FX_TYPE_IO_TARGET, ObjectSize, FxDriverGlobals)
39{
40 Construct();
41}
42
44 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
45 __in USHORT ObjectSize,
46 __in USHORT WdfType
47 ) :
48 FxNonPagedObject(WdfType, ObjectSize, FxDriverGlobals)
49{
50 Construct();
51}
52
53VOID
55 VOID
56 )
57{
60
62
64
68
69 m_Driver = NULL;
76 m_IoCount = 1;
79
81
82 //
83 // We want to guarantee that the cleanup callback is called at passive level
84 // so the driver writer can override the automatic behavior the target uses
85 // when shutting down with i/o in progress.
86 //
89}
90
92{
95 ASSERT(m_IoCount == 0);
96}
97
98VOID
100 VOID
101 )
102/*++
103
104Routine Description:
105 To prevent WPP from reporting incorrect module or line number if the
106 caller is an inline function we use this function to print the message
107 to the IFR.
108
109Arguments:
110 None
111
112Return Value:
113 None
114
115 --*/
116
117{
119 "WDFIOTARGET %p, setting Dispose event %p",
121}
122
123VOID
125 VOID
126 )
127{
128#if (FX_CORE_MODE==FX_CORE_USER_MODE)
130#else
131 FxCREvent eventOnStack;
132 eventOnStack.Initialize();
133 FxCREvent * event = eventOnStack.GetSelfPointer();
134#endif
135
137
139
141 "WDFIOTARGET %p, Waiting on Dispose event %p",
143
145 event->EnterCRAndWaitAndLeave();
146 }
147
149 ASSERT(m_IoCount == 0);
150}
151
152
155 VOID
156 )
157/*++
158
159Routine Description:
160 Dispose is overridden so that the driver can have a chance to override the
161 default remove behavior for the target. By default, remove will cancel
162 all sent I/O and then wait for it to complete. For instance, if the driver
163 wants to wait for all i/o to complete rather then be canceled, a cleanup
164 callback should be registered on the target and the wait should be performed
165 there.
166
167Arguments:
168 None
169
170Return Value:
171 FALSE, indicating to the FxObject state machine *NOT* to call
172
173 --*/
174
175{
177
179 //
180 // Remove the target from the list of targets that the device keeps track
181 // of.
182 //
185 }
186
187 //
188 //
189 // Call all of the cleanup callbacks first
190 //
191 CallCleanup();
192
193 //
194 // Now cancel all sent i/o and shut the target down
195 //
196 Remove();
197
198 //
199 // By returning FALSE, the object state machine will not attempt to call
200 // cleanup again.
201 //
202 return FALSE;
203}
204
205VOID
208 )
209{
211 FxIrp* irp = NULL;
212
213 irp = Request->GetSubmitFxIrp();
214 action = Submit(Request, NULL, 0);
215 if (action & SubmitSend) {
218 "Sending Pended WDFREQUEST %p, Irp %p",
219 Request->GetTraceObjectHandle(),
220 irp->GetIrp());
221
222 Send(irp->GetIrp());
223 }
224
225 //
226 // If the request was not sent or pended (queued), complete it.
227 //
228 if ((action & (SubmitSend | SubmitQueued)) == 0) {
229 ASSERT(0 == action);
232 "Completing Pended WDFREQUEST %p, Irp %p, %!STATUS!",
233 Request->GetTraceObjectHandle(), irp->GetIrp(), irp->GetStatus());
234
235 //
236 // Fail the request.
237 //
240
241 //
242 // This function updates the outstanding 'io count' value and
243 // decrement the ref count on Request.
244 //
246 }
247 else {
248 //
249 // Submit() updated the 'io count' counter for request that got sent or
250 // queued. Note that the input request was already tracked via this
251 // counter, thus decrement its value.
252 //
254
255 //
256 // SubmitLocked will add another ref if it needs it. Release the
257 // reference taken when the request was pended.
258 //
259 // Release the reference after submitting it in case the request was deleted.
260 // If it was deleted, the reference taken by the target is the only keep
261 // it alive.
262 //
263 Request->RELEASE(this);
264 }
265}
266
267VOID
269 __in PLIST_ENTRY RequestListHead
270 )
271{
273
274 while (!IsListEmpty(RequestListHead)) {
275 ple = RemoveHeadList(RequestListHead);
277 }
278}
279
283 VOID
284 )
285{
288
290
292
294
297 "WDFIOTARGET %p started status %!STATUS!",
298 GetHandle(),status);
299 return status;
300}
301
302#define START_TAG ((PVOID) ('trtS'))
303
307 __in PLIST_ENTRY RequestListHead,
309 )
310{
312 KIRQL irql;
313
315
317
318 if (Lock) {
319 FxIoTarget::Lock(&irql);
320 }
321
325 }
326 else if (m_WaitingForSentIo) {
327
329
332 "WDFIOTARGET %p is being started while it is being stopped or "
333 "purged by another thread. WdfIoTargetStart and "
334 "WdfIoTargetStop/WdfIoTargetPurge must be called synchronously. "
335 "After the driver calls one of these functions, it must not call "
336 "the other function before the first one returns.",
338
340 (irql > PASSIVE_LEVEL)) {
341
342 //
343 // We cannont wait for a previous stop to complete if we are at
344 // dispatch level
345 //
347 }
348
349 //
350 // Wait for the stop code to complete
351 //
353
354 ASSERT(Lock);
355 Unlock(irql);
356
358
359 //
360 // Go back and check our state again since we dropped the lock.
361 //
362 FxIoTarget::Lock(&irql);
363 goto CheckState;
364 }
365 else {
367 }
368
369 //
370 // Restart all of the pended i/o.
371 //
372 if (NT_SUCCESS(status)) {
374
377
378 //
379 // TRUE - requests will be resent to the target, so attempt to claim
380 // cancelation ownership
381 //
382 DrainPendedRequestsLocked(RequestListHead, TRUE);
383 }
384
385 if (Lock) {
386 Unlock(irql);
387 }
388
390
391 return status;
392}
393
394VOID
396 __in PLIST_ENTRY RequestListHead,
397 __in BOOLEAN RequestWillBeResent
398 )
399{
400 PMdIoCsqIrpContext pContext;
401 MdIrp pIrp;
402 FxIrp* pFxIrp = NULL;
403 pContext = NULL;
404
405 while ((pIrp = m_PendedQueue.GetNextRequest(&pContext)) != NULL) {
407 BOOLEAN enqueue;
408
409 enqueue = FALSE;
410
411 //
412 // Each FxRequestBase on the pending list has a reference taken against
413 // it already. We will release the reference after we call Submit.
414 //
415 // After this call we are done with the m_CsqContext field.
416 //
418
419 //
420 // m_ListEntry and m_CsqContext are a union. Now that we are done with
421 // m_CsqContext, initialize it to be a valid list entry.
422 //
424
425 //
426 // Undo the affects of the IoSetNextIrpStackLocation made when we
427 // enqueued the request. We want to do this no matter if we can claim
428 // cancellation ownership of the request or not.
429 //
430 pFxIrp = pRequest->GetSubmitFxIrp();
432
433 //
434 // Request is not longer pended.
435 //
438
439 if (RequestWillBeResent) {
440 //
441 // Make sure timer callback is not about to run. After the call
442 // below the timer was successfully canceled or the timer callback
443 // already run.
444 //
445 if (pRequest->CancelTimer()) {
446 //
447 // Try to claim cancellation (*) ownership of the request.
448 // CanComplete() decrements the irp completion ref count and
449 // whomever decrements to zero owns the request. Ownership in
450 // this case is resubmission as well as completion (as the name
451 // of the function implies).
452 //
453 // (*) - cancellation as defined by WDF and the myriad of
454 // functions which are calling FxRequestBase::Cancel().
455 // By this point we have already removed the cancellation
456 // routine by calling m_PendedQueue.GetNextRequest()
457 //
458 if (pRequest->CanComplete()) {
459
460 enqueue = TRUE;
461 }
462 }
463
464 if (FALSE == enqueue) {
465 //
466 // Some other thread is responsible for canceling this request.
467 // We are assuming here that the other thread will complete it
468 // in that thread because we are no longer tracking this request
469 // in any of our lists.
470 //
472
473 //
474 // Mark that the request has been completed so that if the other
475 // thread is the timer DPC, it will handle the case properly and
476 // complete the request.
477 //
480
483 "WDFIOTARGET %p, WDFREQUEST %p is being canceled on another thread,"
484 " allowing other thread to complete request, not resending",
486 }
487 }
488 else {
489 //
490 // The caller is going to attempt to complete the requests. To make
491 // the caller's life easier and let it reuse RequestCompletionRoutine,
492 // to handle the completion semantics, keep the completion reference
493 // count != 0 and return the request back to the caller.
494 //
495 enqueue = TRUE;
496 }
497
498 if (enqueue) {
500 InsertTailList(RequestListHead, &pRequest->m_ListEntry);
501 }
502
503 pContext = NULL;
504 }
505}
506
507VOID
510 )
511{
512 //
513 // This will attempt to claim cancelation ownership and call the
514 // request's completion routine.
515 //
517}
518
519VOID
521 __in PLIST_ENTRY RequestListHead
522 )
523{
525
526 while (!IsListEmpty(RequestListHead)) {
527 ple = RemoveHeadList(RequestListHead);
530 }
531}
532
533VOID
536 )
537{
538 //
539 // Attempt to cancel the request
540 //
541 Request->Cancel();
542
543 //
544 // Release the reference taken by GetSentRequestsListLocked
545 //
546 Request->RELEASE(m_SentRequestTag);
547}
548
549VOID
551 __in PSINGLE_LIST_ENTRY RequestListHead
552 )
553/*++
554
555Routine Description:
556 Cancels all FxRequestBases in RequestListHead
557
558Arguments:
559 RequestListHead - List head containing the requests
560
561Return Value:
562 None.
563
564 --*/
565{
567
568 while (RequestListHead->Next != NULL) {
569 ple = PopEntryList(RequestListHead);
570
571 //
572 // Set the Next pointer back to NULL so that if it is reinserted into a
573 // cancel list, it will not point to unknown pool.
574 //
575 ple->Next = NULL;
576
578 }
579}
580
581VOID
583 __in PSINGLE_LIST_ENTRY RequestListHead,
584 __in PLIST_ENTRY SendList,
585 __out PBOOLEAN AddedToList
586 )
587{
589
590 *AddedToList = IsListEmpty(SendList) ? FALSE : TRUE;
591
592 //
593 // Since we are inserting into the head of the single list head, if we walked
594 // over the list from first to last, we would reverse the entries. By walking
595 // the list backwards, we build the single list head in the order of SendList.
596 //
597 for (ple = SendList->Blink; ple != SendList; ple = ple->Blink) {
599
601
602 //
603 // Add a reference since the request will be touched outside of the
604 // lock being held.
605 //
606 pRequest->ADDREF(m_SentRequestTag);
607
608 //
609 // Add the request at the head of the list.
610 //
611 pRequest->m_DrainSingleEntry.Next = RequestListHead->Next;
612 RequestListHead->Next = &pRequest->m_DrainSingleEntry;
613 }
614}
615
616VOID
619 __in PSINGLE_LIST_ENTRY SentRequestListHead,
621 __in BOOLEAN LockSelf
622 )
623/*++
624
625Routine Description:
626 Accumulates all pending I/O for cancelling out of this function if
627 RequestListHead != NULL.
628
629Arguments:
630
631
632Return Value:
633
634 --*/
635
636{
637 KIRQL irql;
638 BOOLEAN getSentList, wait, added;
639
640 getSentList = FALSE;
641 wait = FALSE;
643
644 if (LockSelf) {
645 Lock(&irql);
646 }
647
648 //
649 // The following transitions are allowed:
650 // (1) Started -> Stopped
651 // (2) Purged -> Stopped
652 // (3) Stopped -> Stopped
653 //
654 // A Stopped -> Stopped transition
655 // is feasible if the previous stop left all pending i/o and the current
656 // stop wants to cancel all i/o.
657 //
660 }
661 else if (m_State != WdfIoTargetStopped) {
662 //
663 // Stopping in any state other then stopped or started is not fatal,
664 // but should be logged.
665 //
666
667 //
670 "WDFIOTARGET %p stopped, but it is currently in the "
671 "%!WDF_IO_TARGET_STATE! state, not started or stopped",
672 GetHandle(), m_State);
673 }
674
675 switch (Action) {
677 getSentList = TRUE;
678 // || || Drop through || ||
679 // \/ \/ \/ \/
680
683 //
684 // By using m_WaitingForSentIo as value for wait, we can handle the
685 // case where GotoStopState is called when we are already in the
686 // stopping case (in which case we would have drained
687 // m_SendIoListHead already).
688 //
689 wait = m_WaitingForSentIo;
690
691 if (m_WaitingForSentIo) {
694 "WDFIOTARGET %p is already in the process of being stopped "
695 "or purged from another thread. Driver must wait for the "
696 "first WdfIoTargetStop or WdfIoTargetPurge to complete "
697 "before calling it again.",
699 }
700 }
701 else {
702 wait = TRUE;
703
704 if (getSentList) {
705 //
706 // Ignore the assignment to added since we have already computed
707 // if we need to wait or not.
708 //
709 GetSentRequestsListLocked(SentRequestListHead,
711 &added);
712 }
713 }
714
715 break;
716
718 wait = FALSE;
719 break;
720 }
721
722 m_WaitingForSentIo = wait;
723 *Wait = wait;
724
725 if (wait) {
726 //
727 // If Stop(leave sent io pending) was previously called, m_SentIoEvent
728 // will be in the signalled state. We need to wait for sent i/o to be
729 // completed, so make sure it is not signalled while holding the lock
730 //
732 }
733 else {
734 //
735 // Even though *Wait is set to FALSE, the caller may wait anyways
736 // if it is aggregating targets to move into the stopped state and
737 // wait on them all.
738 //
740 }
741
742 if (LockSelf) {
743 Unlock(irql);
744 }
745}
746
747VOID
750 )
751{
753 BOOLEAN wait;
754
755 head.Next = NULL;
756 wait = FALSE;
757
758 GotoStopState(Action, &head, &wait, TRUE);
759
760 if (head.Next != NULL) {
762 }
763
764 if (wait) {
765 KIRQL irql;
766
767 //
768 // Under the lock, if wait is set, m_WaitingForSentIo is true, but once
769 // we drop the lock, all pended i/o could have already been canceled
770 // and m_WaitingForSentIo is FALSE at this point.
771 //
772 // ASSERT(m_WaitingForSentIo);
773
775
776 //
777 // Mark that we are no longer stopping and waiting for i/o to complete.
778 //
779 Lock(&irql);
781 Unlock(irql);
782 }
783
786 "WDFIOTARGET %p stopped ",GetHandle());
787}
788
789VOID
792 __in PLIST_ENTRY PendedRequestListHead,
793 __in PSINGLE_LIST_ENTRY SentRequestListHead,
795 __in BOOLEAN LockSelf
796 )
797/*++
798
799Routine Description:
800 Accumulates all pending and sent I/O. The I/O target is moved into
801 the 'purged' state.
802
803Arguments:
804
805
806Return Value:
807
808 --*/
809
810{
811 KIRQL irql;
812 BOOLEAN wait, added;
813
814 wait = FALSE;
816
817 if (LockSelf) {
818 Lock(&irql);
819 }
820
821 //
822 // The following transitions are allowed:
823 // (1) Started -> Purged
824 // (2) Stop -> Purged
825 // (3) Purged -> Purged
826 //
827 // A Purged -> Purged transition is feasible if the previous purge didn't
828 // wait for pending i/o to complete and the current purge wants to wait
829 // for them.
830 //
833 }
834 else if (m_State != WdfIoTargetPurged) {
835 //
836 // Purging in any state other then purged or started is not fatal,
837 // but should be logged.
838 //
839
840 //
843 "WDFIOTARGET %p purged, but it is currently in the "
844 "%!WDF_IO_TARGET_STATE! state, not started, stopped or purged",
845 GetHandle(), m_State);
846 }
847
848 //
849 // FALSE - requests will not be resent to the target. As such,
850 // cancellation ownership will not be claimed b/c the request
851 // will subsequently be passed to FailPendedRequest.
852 //
853 DrainPendedRequestsLocked(PendedRequestListHead, FALSE);
854
855 GetSentRequestsListLocked(SentRequestListHead,
857 &added);
858
859 switch (Action) {
861 if (added == FALSE) {
862 //
863 // By using m_WaitingForSentIo as value for wait, we can handle the
864 // case where GotoPurgeState is called when we are already in the
865 // purging case (in which case we would have drained
866 // m_SendIoListHead already).
867 //
868 wait = m_WaitingForSentIo;
869
870 if (m_WaitingForSentIo) {
873 "WDFIOTARGET %p is already in the process of being purged "
874 "or stopped from another thread. Driver must wait for the "
875 "first WdfIoTargetPurge or WdfIoTargetStop to complete "
876 "before calling it again.",
878
880 }
881 }
882 else {
883 wait = TRUE;
884 }
885 break;
886
888 wait = FALSE;
889 break;
890 }
891
892 m_WaitingForSentIo = wait;
893 *Wait = wait;
894
895 if (wait) {
896 //
897 // If Stop/Purge(don't wait) was previously called, m_SentIoEvent
898 // will be in the signalled state. We need to wait for sent i/o to be
899 // completed, so make sure it is not signalled while holding the lock
900 //
902 }
903 else {
904 //
905 // Even though *Wait is set to FALSE, the caller may wait anyways
906 // if it is aggregating targets to move into the purged state and
907 // wait on them all.
908 //
910 }
911
912 if (LockSelf) {
913 Unlock(irql);
914 }
915}
916
917VOID
920 )
921{
922 LIST_ENTRY pendedHead;
923 SINGLE_LIST_ENTRY sentHead;
924 BOOLEAN wait;
925
926 InitializeListHead(&pendedHead);
927 sentHead.Next = NULL;
928 wait = FALSE;
929
930 GotoPurgeState(Action, &pendedHead, &sentHead, &wait, TRUE);
931
932 //
933 // Complete any requests we might have pulled off of our lists
934 //
935 CompletePendedRequestList(&pendedHead);
936 _CancelSentRequests(&sentHead);
937
938 if (wait) {
939 KIRQL irql;
940
941 //
942 // Under the lock, if wait is set, m_WaitingForSentIo is true, but once
943 // we drop the lock, all pended i/o could have already been canceled
944 // and m_WaitingForSentIo is FALSE at this point.
945 //
946 // ASSERT(m_WaitingForSentIo);
947
949
950 //
951 // Mark that we are no longer purging and waiting for i/o to complete.
952 //
953 Lock(&irql);
955 Unlock(irql);
956 }
957
960 "WDFIOTARGET %p purged ",GetHandle());
961}
962
963VOID
965 __in WDF_IO_TARGET_STATE NewState,
966 __in PLIST_ENTRY PendedRequestListHead,
967 __in PSINGLE_LIST_ENTRY SentRequestListHead,
970 )
971{
972 KIRQL irql;
973 BOOLEAN sentAdded, ignoredAdded;
974
976
977 if (Lock) {
978 this->Lock(&irql);
979 }
980
981 if (m_WaitingForSentIo) {
984 "WDFIOTARGET %p is being deleted while it is being stopped/purged "
985 "by another thread. Driver must wait for WdfIoTargetStop or "
986 "WdfIoTargetPurge to complete before deleting the object.",
988
989 ASSERT(Lock);
990
991 Unlock(irql);
993 this->Lock(&irql);
994
996 }
997
998 *Wait = FALSE;
999 m_State = NewState;
1000
1001 //
1002 // FALSE - requests will not be resent to the target. As such,
1003 // cancellation ownership will not be claimed b/c the request
1004 // will subsequently be passed to FailPendedRequest.
1005 //
1006 DrainPendedRequestsLocked(PendedRequestListHead, FALSE);
1007
1008 //
1009 // Now cancel all of the sent I/O since we are being removed for good.
1010 //
1011 if (NewState == WdfIoTargetDeleted || NewState == WdfIoTargetClosed ||
1012 NewState == WdfIoTargetClosedForQueryRemove) {
1013 //
1014 // If the caller is aggregating calls to GotoRemoveState among many
1015 // targets (for instance, WDFUSBDEVICE will do this over its WDFUSBPIPEs
1016 // on remove), we cannot use the state of SentRequestListHead after these
1017 // two calls as a test to see if any requests are being canceled (and the
1018 // diff between removing and removed). Instead, we rely on the added
1019 // state returned by each call.
1020 //
1021 GetSentRequestsListLocked(SentRequestListHead,
1023 &sentAdded);
1024 GetSentRequestsListLocked(SentRequestListHead,
1026 &ignoredAdded);
1027
1028 if (sentAdded || ignoredAdded) {
1029 //
1030 // We will have to wait for the i/o to come back. As such, we are
1031 // in the transition state and must wait for it to complete. In this
1032 // transitionary stage, I/O can still be sent if they are marked to
1033 // ignore the target state.
1034 //
1035 m_Removing = TRUE;
1036 *Wait = TRUE;
1037
1038 //
1039 // If Stop(leave sent io pending) or Purge(do-not-wait) was
1040 // previously called, m_SentIoEvent will be in the signalled state.
1041 // We need to wait for sent i/o to be completed, so make sure it
1042 // is not signalled while hodling the lock
1043 //
1045 }
1046 else {
1048
1049 //
1050 // Even though *Wait is set to FALSE, the caller may wait anyways
1051 // if it is aggregating targets to move into the remove state and
1052 // wait on all of them.
1053 //
1055 }
1056 }
1057
1058 if (Lock) {
1059 Unlock(irql);
1060 }
1061
1062 return;
1063}
1064
1065VOID
1067 VOID
1068 )
1069{
1070 SINGLE_LIST_ENTRY sentHead;
1071 LIST_ENTRY pendedHead;
1072 BOOLEAN wait;
1073
1074 sentHead.Next = NULL;
1075 InitializeListHead(&pendedHead);
1076
1078 &pendedHead,
1079 &sentHead,
1080 TRUE,
1081 &wait);
1082
1083 //
1084 // Complete any requests we might have pulled off of our lists
1085 //
1086 CompletePendedRequestList(&pendedHead);
1087 _CancelSentRequests(&sentHead);
1088
1089 if (wait) {
1091
1093 }
1094
1096
1097 return;
1098}
1099
1104 )
1105{
1106 switch (Params->Type) {
1107 case FX_TYPE_IO_TARGET:
1108 *Params->Object = (FxIoTarget*) this;
1109 break;
1110 default:
1111 return FxNonPagedObject::QueryInterface(Params); // __super call
1112 }
1113
1114 return STATUS_SUCCESS;
1115}
1116
1121 )
1122{
1124
1126 if (!NT_SUCCESS(status)) {
1127 return status;
1128 }
1129
1132
1133 m_InStackDevice = Device->GetDeviceObject();
1134
1135 //
1136 // Note that AttachedDevice can be NULL for UMDF for
1137 // example when there is only one device in the stack.
1138 //
1140 m_TargetPdo = Device->GetPhysicalDevice();
1141
1142 m_Driver = Device->GetDriver();
1143
1144#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
1145 if (m_InStackDevice == NULL || m_Driver == NULL ||
1149 "Init WDFIOTARGET %p, unexpected NULL, m_InStackDevice %p, "
1150 "m_TargetDevice %p, m_TargetPdo %p, m_Driver %p",
1152 m_Driver);
1153
1154 return STATUS_UNSUCCESSFUL;
1155 }
1156#else
1157 if (m_InStackDevice == NULL || m_Driver == NULL) {
1160 "Init WDFIOTARGET %p, unexpected NULL, m_InStackDevice %p, "
1161 "m_Driver %p",
1163
1164 return STATUS_UNSUCCESSFUL;
1165 }
1166#endif
1167
1168 //
1169 // For UMDF the target device can be NULL if there is only one driver in the
1170 // stack. In that case m_TargetStackSize retains its initial value (0).
1171 //
1172 if (m_TargetDevice != NULL) {
1174
1176
1178 }
1179
1180 return STATUS_SUCCESS;
1181}
1182
1185FX_VF_METHOD(FxIoTarget, VerifySubmitLocked) (
1186 _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
1188 )
1189{
1194
1196
1197 irp = Request->GetSubmitFxIrp();
1198 Request->Lock(&irql);
1199 flags = Request->GetVerifierFlagsLocked();
1200
1203
1205 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1206 "WDFREQUEST %p has not been formatted, cannot send, %!STATUS!",
1207 Request->GetTraceObjectHandle(), status);
1208 }
1210 //
1211 // Technically this is the same check as m_IrpCompletionReferenceCount
1212 // above, but we make this check in many more locations.
1213 //
1215 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1216 "WDFREQUEST %p is already pending on a WDFIOTARGET",
1217 Request->GetTraceObjectHandle());
1218
1219 FxVerifierBugCheck(FxDriverGlobals,
1222 (ULONG_PTR) Request->GetHandle());
1223 }
1224 else if (HasEnoughStackLocations(irp) == FALSE) {
1226
1227 //
1228 // For reasons why we subtract 1 from CurrentLocation, see comments
1229 // in FxIoTarget::HasEnoughStackLocations.
1230 //
1232 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGIOTARGET,
1233 "WDFREQUEST %p, PIRP %p does not have enough stack locations %d"
1234 " for this WDFIOTARGET %p (requires %d locations), %!STATUS!",
1235 Request->GetTraceObjectHandle(), irp->GetIrp(), irp->GetCurrentIrpStackLocationIndex() - 1,
1236 GetHandle(), m_TargetStackSize, status);
1237 }
1238
1239 Request->Unlock(irql);
1240 return status;
1241}
1242
1243ULONG
1248 )
1249/*++
1250
1251Routine Description:
1252 Core processing logic for submitting a request. Will return the send flag
1253 if the request can be submitted immediately. If the flag is not returned,
1254 the pended flag may be set. If neither are set, status in the Request will
1255 be set with the error.
1256
1257 NTSTATUS status;
1258 ULONG action;
1259
1260 Lock();
1261 action |= SubmitLocked(...);
1262 UnLock();
1263
1264 if (action & Send) {
1265 // IoCallDriver ....
1266 }
1267 else if (action & Pended) {
1268 // request was pended
1269 }
1270
1271 return ...;
1272
1273Arguments:
1274 Request - The request that will be submitted to the target
1275
1276 Options - send options associated with the request being sent
1277
1278 Flags - Additional flags to control how the request is being sent
1279
1280Return Value:
1281 A bit field whose flags are defined by SubmitActionFlags
1282
1283 --*/
1284{
1287 ULONG action;
1288 BOOLEAN startTimer, stateIgnored, verify;
1289 BOOLEAN addedRef;
1290 FxIrp* irp;
1291
1293
1294 action = 0;
1295 startTimer = FALSE;
1296 stateIgnored = FALSE;
1297 addedRef = FALSE;
1298
1299 //
1300 // If the reference count is not zero, the irp has not completed and the
1301 // driver is reusing it before it has returned to the driver. Not good!
1302 //
1303 ASSERT(Request->m_IrpCompletionReferenceCount == 0);
1304 if (Request->m_IrpCompletionReferenceCount != 0) {
1307 "WDFREQUEST %p already sent to a target",
1308 Request->GetTraceObjectHandle());
1309
1310 //
1311 // Last ditch assert
1312 //
1313 ASSERT((Request->GetTargetFlags() & FX_REQUEST_PENDED) == 0);
1314
1315 // no return
1319 (ULONG_PTR) Request->GetHandle());
1320 }
1321
1322 irp = Request->GetSubmitFxIrp();
1323
1326
1327 verify = TRUE;
1328 status = VerifySubmitLocked(pFxDriverGlobals, Request);
1329 if (!NT_SUCCESS(status)){
1330 goto Done;
1331 }
1332 }
1333 else {
1334 verify = FALSE;
1335 }
1336
1337 //
1338 // if WDF_REQUEST_SEND_OPTION_TIMEOUT is set, Options != NULL
1339 //
1340 if ((Flags & WDF_REQUEST_SEND_OPTION_TIMEOUT) && Options->Timeout != 0) {
1341 //
1342 // Create the timer under the lock
1343 //
1344 status = Request->CreateTimer();
1345
1346 if (!NT_SUCCESS(status)) {
1349 "WDFREQUEST %p, could not create timer, %!STATUS!",
1350 Request->GetTraceObjectHandle(), status);
1351
1352 goto Done;
1353 }
1354
1355 startTimer = TRUE;
1356 }
1357
1359 //
1360 // If we are in the deleted or closed state, we must be in the transitioning
1361 // state to allow I/O at this time. For any other state, always allow
1362 // the i/o to go through.
1363 //
1364 if ((m_State == WdfIoTargetDeleted ||
1367 m_Removing == FALSE) {
1368 //
1369 // The target is truly closed or removed, it is not in the
1370 // transitionary state. We don't allow I/O anymore.
1371 //
1373
1376 "WDFIOTARGET %p state %!WDF_IO_TARGET_STATE!, sending "
1377 "WDFREQUEST %p cannot ignore current state, %!STATUS!",
1378 GetObjectHandle(), m_State, Request->GetTraceObjectHandle(),
1379 status);
1380
1381 goto Done;
1382 }
1383 else {
1384 action |= SubmitSend;
1385
1388 "ignoring WDFIOTARGET %p state, sending WDFREQUEST %p, state "
1389 "%!WDF_IO_TARGET_STATE!",
1390 GetObjectHandle(), Request->GetTraceObjectHandle(), m_State);
1391
1392 Request->SetTargetFlags(FX_REQUEST_IGNORE_STATE);
1393
1395 stateIgnored = TRUE;
1396 }
1397 }
1398 else {
1399 switch (m_State) {
1400 case WdfIoTargetStarted:
1402 action |= SubmitSend;
1403 break;
1404
1405 case WdfIoTargetStopped:
1408 goto Done;
1409 }
1410 else {
1413 }
1414 break;
1415
1417 case WdfIoTargetClosed:
1418 case WdfIoTargetDeleted:
1419 case WdfIoTargetPurged:
1420 default:
1423 "failing WDFREQUEST %p, WDFIOTARGET %p not accepting requests, "
1424 "state %!WDF_IO_TARGET_STATE!", Request->GetTraceObjectHandle(),
1426
1428 goto Done;
1429 }
1430 }
1431
1432 //
1433 // Make sure the list entry is initialized so if we call RemoveEntryList
1434 // later, we don't corrupt whatever Flink and Blink point to.
1435 //
1436 InitializeListHead(&Request->m_ListEntry);
1437
1439
1440Done:
1441 if (NT_SUCCESS(status)) {
1442 //
1443 // Request should not be pended
1444 //
1445 ASSERT((Request->GetTargetFlags() & FX_REQUEST_PENDED) == 0);
1446
1447 //
1448 // Set m_Target before setting the reference count to one because as soon
1449 // as it is set to 1, it can be decremented to zero and then it will
1450 // assume that m_Target is valid.
1451 //
1452 Request->SetTarget(this);
1453
1454 //
1455 // Assume we are successful, we will adjust this value in case of error.
1456 //
1458
1459 //
1460 // All paths which are pulling the request off of the list must use this
1461 // specific tag. This would include the cancel, timer, and completion
1462 // routines.
1463 //
1464 // We don't add a reference in the error case because the caller
1465 // will just complete the request back to the caller (for a queue
1466 // presented request) or free it (for a driver created request).
1467 //
1468 // This released at the end of FxRequestBase::CompleteSubmitted
1469 //
1470 Request->ADDREF(this);
1471
1472 //
1473 // In case of error, we use this flag to know if the IoCount and
1474 // RequestRef need to be rolled back.
1475 //
1476 addedRef = TRUE;
1477
1478 //
1479 // Set the reference count to one. This reference count guards prevents
1480 // Request::Cancel from touching an invalid PIRP outside of any lock.
1481 //
1482 Request->m_IrpCompletionReferenceCount = 1;
1483
1484 if (Request->m_Canceled) {
1485 //
1486 // CanComplete() decrements the count that was set above. If the
1487 // count goes to zero, CanComplete() returns TRUE and
1488 // FxRequestBase::Cancel will not touch the irp. If it returns
1489 // FALSE, we indicate that the request was sent, in actuality we
1490 // don't send the request b/c FxRequestBase::Cancel will call
1491 // CompleteCanceledRequest, where the irp will complete.
1492 //
1493 if (Request->CanComplete()) {
1494 //
1495 // This thread owns the irp. Set the status to !NT_SUCCESS and
1496 // clear any actions we indicate to the caller.
1497 //
1498 action = 0;
1499 }
1500 else {
1501 //
1502 // There is still an reference count on the completion count,
1503 // let the other thread complete it.
1504 //
1505
1506 //
1507 // Make the caller think that the request was queued. By doing
1508 // this, it will not attempt to call IoCallDriver. SubmitSend
1509 // will be cleared after jump to Done: and evaluate status.
1510 //
1512 }
1513
1514 //
1515 // Either way, we want to set STATUS_CANCELLED in the PIRP when we
1516 // are done.
1517 //
1519
1520 //
1521 // Just jump to the end and avoid any more compares.
1522 //
1523 goto CheckError;
1524 }
1525
1526 if (action & SubmitSend) {
1527 if (stateIgnored) {
1529 }
1530 else {
1531 //
1532 // Keep track of the request so that we can cancel it later if needed
1533 //
1534 InsertTailList(&m_SentIoListHead, &Request->m_ListEntry);
1535 }
1536
1537 //
1538 // We know we are going to send the request, set the completion
1539 // routine now. Since IoSetCompletionRoutineEx allocates memory
1540 // which is only freed when the completion routine is called when
1541 // the request is completing, we can only set the CR when we *KNOW*
1542 // the request will be sent, ie SubmitSend is set and returned to
1543 // the caller.
1544 //
1546
1547 //
1548 // NOTE: No need to reference the file object before we drop the lock
1549 // because will not deref the file object while there is outstanding
1550 // I/O.
1551 //
1552 }
1553 else {
1557 "Pending WDFREQUEST %p, WDFIOTARGET %p is paused, %!STATUS!",
1558 Request->GetTraceObjectHandle(), GetObjectHandle(), status);
1559
1560 if (!NT_SUCCESS(status)) {
1561 //
1562 // CanComplete() decrements the count that was set above. If the
1563 // count goes to zero, CanComplete() returns TRUE and
1564 // FxRequestBase::Cancel will not touch the irp. If it returns
1565 // FALSE, we indicate that the request was sent, in actuality we
1566 // don't send the request b/c FxRequestBase::Cancel will call
1567 // CompleteCanceledRequest, where the irp will complete.
1568 //
1569 if (Request->CanComplete()) {
1570 //
1571 // This thread owns the irp.
1572 // Clear any actions we indicate to the caller.
1573 //
1574 action = 0;
1575 }
1576 else {
1577 //
1578 // The cancel/timer routine (whoever has ownership of
1579 // request) will complete the request.
1580 //
1582 DO_NOTHING();
1583 }
1584 }
1585 }
1586
1587 if (NT_SUCCESS(status)) {
1588 //
1589 // Delay starting the timer to the last possible moment where we know
1590 // there will be no error and we don't have to deal with any cancel
1591 // logic in the error case.
1592 //
1593 if (startTimer) {
1595
1596 //
1597 // Set the timer under the lock
1598 //
1601 "Starting timer on WDFREQUEST %p",
1602 Request->GetTraceObjectHandle());
1603
1604 Request->StartTimer(Options->Timeout);
1605 }
1606 }
1607 }
1608
1610 //
1611 // Not an else clause to the if (NT_SUCCESS(status)) above b/c status can
1612 // be changed within the NT_SUCCESS(status) clause.
1613 //
1614 if (!NT_SUCCESS(status)) {
1616 action &= ~SubmitSend;
1617 }
1618 else if (verify) {
1619 Request->SetVerifierFlags(FXREQUEST_FLAG_SENT_TO_TARGET);
1620 }
1621
1622 //
1623 // Keep the IoCount and Request->AddRef() only if the request is going
1624 // to be sent, or it is queued, or another thread took ownership of its
1625 // cancellation.
1626 //
1627 if (addedRef && (action & (SubmitSend | SubmitQueued)) == 0) {
1628 Request->RELEASE(this);
1630 }
1631
1632 return action;
1633}
1634
1635ULONG
1640 )
1641{
1642 ULONG result;
1643 KIRQL irql;
1644
1645 Lock(&irql);
1647 Unlock(irql);
1648
1649 return result;
1650}
1651
1658 )
1659{
1662 ULONG action;
1664 KIRQL irql;
1665 BOOLEAN clearContext;
1666
1669 "WDFIOTARGET %p, WDFREQUEST %p",
1670 GetObjectHandle(), Request->GetTraceObjectHandle());
1671
1672#if (FX_CORE_MODE == FX_CORE_USER_MODE)
1673 //
1674 // FxCREvent events needs to be initiliazed in UMDF, and failure handled
1675 // gracefully. For KMDF, it will result in double initialization which is
1676 // not a problem. Note that for KMDF, FxCREvent->Initialize will never fail.
1677 //
1678 status = params.SynchEvent.Initialize();
1679 if (!NT_SUCCESS(status)) {
1681 "Failed to initialize sync event for "
1682 "WDFIOTARGET %p, WDFREQUEST %p",
1683 GetObjectHandle(), Request->GetTraceObjectHandle());
1684 if (Action != NULL) {
1685 *Action = 0;
1686 }
1687 return status;
1688 }
1689#endif
1690
1691 clearContext = Request->ShouldClearContext();
1692
1693 if (Action != NULL) {
1694 action = *Action;
1695 }
1696 else {
1697 action = 0;
1698 }
1699
1700 if (Options != NULL &&
1702 Options->Timeout != 0) {
1703 //
1704 // If this flag is set, SubmitLocked will start a timer, which we don't
1705 // want because we will timeout the I/O using KeWaitForSingleObject.
1706 //
1707 // params.Constraints &= ~WDF_REQUEST_SEND_OPTION_TIMEOUT;
1708 timeout = Options->Timeout;
1710 }
1711
1712 //
1713 // Must set the completion routine before calling Submit() so that in the
1714 // pended or sent case, the completion routine is set in place during
1715 // cancelation or delayed completion.
1716 //
1718 params.OrigTargetCompletionContext = Request->m_TargetCompletionContext;
1719 params.OrigTargetCompletionRoutine =
1720 Request->m_CompletionRoutine.m_Completion;
1721 }
1722 else {
1723 params.OrigTargetCompletionContext = NULL;
1724 params.OrigTargetCompletionRoutine = NULL;
1725 }
1726
1727 Request->SetCompletionRoutine(_SyncCompletionRoutine, &params);
1728
1729 //
1730 // SubmitLocked will return whether the request should be sent *right now*.
1731 // If SubmitSend is clear, SubmitQueued must be checked. If set, then
1732 // the request was queued, otherwise, the request has failed and the
1733 // status was already set in the irp.
1734 //
1735 // Clear the WDF_REQUEST_SEND_OPTION_TIMEOUT flag so that SumbitLocked doesn't
1736 // try to allocate a timer
1737 //
1738 action |= Submit(
1739 Request,
1740 Options,
1741 (Options != NULL) ? (Options->Flags & ~WDF_REQUEST_SEND_OPTION_TIMEOUT) : 0);
1742
1744 "WDFREQUEST %p, Action 0x%x", Request->GetTraceObjectHandle(),
1745 action);
1746
1747 //
1748 // Add reference so that if we call Request->Cancel(), Request is still
1749 // a valid object in between the wait timeout and the cancel call if
1750 // request completes before Cancel is called.
1751 //
1752 Request->ADDREF(&status);
1753
1754 if (action & SubmitSend) {
1755 action |= SubmitSent;
1756
1759 "Sending WDFREQUEST %p, Irp %p", Request->GetTraceObjectHandle(),
1760 Request->GetSubmitIrp());
1761
1762 Send(Request->GetSubmitIrp());
1763
1764 //
1765 // We always wait, even in the synchronous case. We do this because
1766 // even though the WDM completion routine ran synchronously in this
1767 // thread, the WDF processing of the completion could have been post-
1768 // poned by another thread attempting to cancel the I/O. The postpone-
1769 // ment would occur when the canceling thread has an oustanding reference
1770 // on m_IrpCompletionReferenceCount, which would cause the call to
1771 // CanComplete() in RequestCompletionRoutine() to return FALSE and not
1772 // call _SyncCompletionRoutine in the context of the WDM completion
1773 // routine, but in the context of the canceling thread.
1774 //
1775 action |= SubmitWait;
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816 }
1817 else if (action & SubmitQueued) {
1818 //
1819 // To the caller, we say we sent the request (and all the cancel
1820 // semantics of a sent request still work).
1821 //
1823 }
1824 else if (action & SubmitSyncCallCompletion) {
1825 //
1826 // The request was not sent nor queued, reset the completion routine
1827 // since we overwrote it.
1828 //
1829 Request->m_TargetCompletionContext = params.OrigTargetCompletionContext;
1830 Request->m_CompletionRoutine.m_Completion =
1831 params.OrigTargetCompletionRoutine;
1832 ASSERT(!NT_SUCCESS(Request->GetSubmitFxIrp()->GetStatus()));
1833 }
1834
1835 if (action & SubmitSent) {
1836 if (action & SubmitWait) {
1837 status = params.SynchEvent.EnterCRAndWaitAndLeave(
1839 );
1840
1841 if (status == STATUS_TIMEOUT) {
1842 //
1843 // By setting FX_REQUEST_CANCELLED_FROM_TIMER, we match the
1844 // async timer behavior where we change the completion status
1845 // from STATUS_CANCELLED to STATUS_IO_TIMEOUT.
1846 //
1847 Lock(&irql);
1849 Unlock(irql);
1850
1851 Request->Cancel();
1852
1853 params.SynchEvent.EnterCRAndWaitAndLeave();
1854 }
1855 }
1856
1857 status = params.Status;
1858 }
1859 else {
1860 status = Request->GetSubmitFxIrp()->GetStatus();
1861 }
1862
1863 Request->RELEASE(&status);
1864
1865 if (Action != NULL) {
1866 *Action = action;
1867 }
1868
1869 if (clearContext) {
1870 Request->ContextReleaseAndRestore();
1871 }
1872
1873 return status;
1874}
1875
1876VOID
1880 )
1881/*++
1882
1883Routine Description:
1884 Completes a request that has failed due to timer expiration or cancellation.
1885
1886Assumes:
1887 Assumes that the caller has undone the effects of the
1888 IoSetNextIrpStackLocation made when we enqueued the request.
1889
1890Arguments:
1891 Request - request that failed
1892
1893 Status - the status to set in the request
1894
1895 TakeReference - add a reference before completing the request
1896
1897Return Value:
1898 None.
1899
1900 --*/
1901{
1902 FxIrp* irp;
1903
1904 irp = Request->GetSubmitFxIrp();
1905
1906 //
1907 // Simulate failure in the IRP
1908 //
1910 irp->SetInformation(0);
1911
1912 //
1913 // Manaully process the irp as if it has completed back from the target.
1914 //
1916}
1917
1918BOOLEAN
1921 )
1922/*++
1923
1924Routine Description:
1925 Removes a previously sent request from the bookkeeping structures
1926
1927Arguments:
1928 Request - The request being completed
1929
1930Assumes:
1931 This object's Lock is being held by the caller.
1932
1933Return Value:
1934 TRUE if the m_SentIoEvent should be set after the caller has released the
1935 object lock.
1936
1937 --*/
1938{
1939 ULONG oldFlags;
1940
1941 //
1942 // We will decrement the pending io count associated with this completed
1943 // request in FxIoTarget::CompleteRequest
1944 //
1945 // DecrementPendingIoCount();
1946
1948 "WDFIOTARGET %p, WDFREQUEST %p", GetObjectHandle(),
1949 Request->GetTraceObjectHandle());
1950
1951 RemoveEntryList(&Request->m_ListEntry);
1952
1953 //
1954 // The request expects not to be on a list when it is destroyed.
1955 //
1956 InitializeListHead(&Request->m_ListEntry);
1957
1958 //
1959 // By the time we get here, there should never ever be a timer set for the
1960 // request.
1961 //
1962 ASSERT((Request->GetTargetFlags() & FX_REQUEST_TIMER_SET) == 0);
1963
1964 //
1965 // Clear flags that may have been set previously.
1966 //
1967 oldFlags = Request->ClearTargetFlags(FX_REQUEST_COMPLETED |
1971
1973
1974 //
1975 // If we are removing, we must wait for *ALL* requests that were sent down
1976 // the stack.
1977 //
1978 // If we are stopping, we only wait for i/o which do not ignore state
1979 //
1980 // NOTE: if we are completing a request which was inserted onto a list
1981 // Cancel()'ed before SubmitLocked was called and the Cancel()
1982 // thread already had a completion reference taken we are going to
1983 // evaluate a state transition even though the request is not a part
1984 // in that transition. I think this is OK b/c the transition would
1985 // have already occurred if the request(s) holding up the transition
1986 // have completed and will not occur here if they are still pending.
1987 //
1988 if (m_Removing) {
1990 //
1991 // We are no longer transitioning, do not allow new I/O of any kind
1992 // to come in.
1993 //
1994 m_Removing = FALSE;
1995
1996 //
1997 // Now that all i/o has ceased, clear out our pointers with relation
1998 // to the target itself.
1999 //
2001
2002 return TRUE;
2003 }
2004 }
2005 else if (m_WaitingForSentIo &&
2006 (oldFlags & FX_REQUEST_IGNORE_STATE) == 0 &&
2009 return TRUE;
2010 }
2011
2012 return FALSE;
2013}
2014
2019 )
2020{
2022 FxIrp* irp;
2023
2024 //
2025 // Assumes this object's lock is being held
2026 //
2027 Request->SetTargetFlags(FX_REQUEST_PENDED);
2028
2029 irp = Request->GetSubmitFxIrp();
2030
2031 //
2032 // Make sure there is a valid current stack location in the irp. If we
2033 // allocated the irp ourself, then the current stack location is not valid.
2034 // Even if we didn't allocate the irp ourself, this will do no harm. In
2035 // every spot where we remove the request, we undo this call with a call to
2036 // IoSkipCurrentIrpStackLocation
2037 //
2039
2041
2043
2044 if (!NT_SUCCESS(status)) {
2045 //
2046 // Undo the affects of the IoSetNextIrpStackLocation made when we
2047 // enqueued the request.
2048 //
2050
2051 //
2052 // Request was not pended.
2053 //
2054 Request->ClearTargetFlags(FX_REQUEST_PENDED);
2055 }
2056
2057 return status;
2058}
2059
2060VOID
2063 )
2064/*++
2065
2066Routine Description:
2067 Timer routine for when a request has timed out. This routine will attempt
2068 to cancel the request if it hasn't yet completed or complete it if it has.
2069
2070Arguments:
2071 Request - The request that has timed out
2072
2073Return Value:
2074 None.
2075
2076 --*/
2077
2078{
2079 KIRQL irql;
2080 BOOLEAN completeRequest, setStopEvent;
2081 LONG completionRefCount;
2082
2083 completeRequest = FALSE;
2084 setStopEvent = FALSE;
2085
2087 "WDFIOTARGET %p, WDFREQUEST %p", GetObjectHandle(),
2088 Request->GetTraceObjectHandle());
2089
2090 Lock(&irql);
2091
2092 //
2093 // Clear the flag so that when the completion routine runs, there is no attempt
2094 // to cancel this timer.
2095 //
2096 Request->ClearTargetFlags(FX_REQUEST_TIMER_SET);
2097
2098 if (Request->GetTargetFlags() & FX_REQUEST_COMPLETED) {
2099 //
2100 // Completion routine ran on a separate processor as the same time as
2101 // the timer DPC. The completion routine will have deferred
2102 // completion to the timer DPC or the caller of Request::Cancel().
2103 //
2104 completeRequest = Request->CanComplete();
2105 }
2106 else {
2107 //
2108 // Attempt to cancel the request later outside of the lock. By setting
2109 // the cancelled from timer flag, the completion routine can morph the
2110 // status to timeout if the request is returned as cancelled.
2111 //
2113
2114 //
2115 // Make sure the completion routine does not complete the request
2116 // while the timer callback is still running, in case the completion
2117 // is invoked in the unlock/lock window below.
2118 //
2119 completionRefCount = FxInterlockedIncrementGTZero(
2120 &Request->m_IrpCompletionReferenceCount);
2121 ASSERT(completionRefCount != 0);
2122 UNREFERENCED_PARAMETER(completionRefCount);
2123
2124 Unlock(irql);
2125
2126 Request->Cancel();
2127
2128 Lock(&irql);
2129
2130 //
2131 // CanComplete() returns true if completion ownership was claimed.
2132 //
2133 completeRequest = Request->CanComplete();
2134 }
2135
2136 //
2137 // If completion ownership was claimed, complete request.
2138 //
2139 if (completeRequest) {
2140 ASSERT(Request->GetTargetFlags() & FX_REQUEST_COMPLETED);
2141
2142 setStopEvent = RemoveCompletedRequestLocked(Request);
2143
2144 if (Request->m_Irp.GetStatus() == STATUS_CANCELLED) {
2145 //
2146 // We cancelled the request in another thread and the timer
2147 // fired at the same time. Treat this as if we did the cancel
2148 // from timer directly.
2149 //
2150 // Morph the status code into a timeout status.
2151 //
2152 // Don't muck with the IoStatus.Information field.
2153 //
2154 Request->m_Irp.SetStatus(STATUS_IO_TIMEOUT);
2155 }
2156 }
2157
2158 Unlock(irql);
2159
2160 if (completeRequest) {
2163 "WDFREQUEST %p completed in timer callback",
2164 Request->GetTraceObjectHandle());
2166 }
2167
2168 if (setStopEvent) {
2171 "WDFIOTARGET %p, setting stop event %p in timer callback",
2173
2175 }
2176
2177 if (completeRequest) {
2179 }
2180}
2181
2182VOID
2185 )
2186{
2187 KIRQL irql;
2188 BOOLEAN setStopEvent;
2189
2190 Lock(&irql);
2191
2192 //
2193 // RemoveCompletedRequestLocked clears Request->m_TargetFlags, so we must
2194 // do this check before that call.
2195 //
2196 if ((Request->GetTargetFlags() & FX_REQUEST_CANCELLED_FROM_TIMER) &&
2197 Request->m_Irp.GetStatus() == STATUS_CANCELLED) {
2198 //
2199 // We cancelled the request from the timer and it has completed with
2200 // cancelled. Morph the status code into a timeout status.
2201 //
2202 // Don't muck with the IoStatus.Information field.
2203 //
2204 Request->m_Irp.SetStatus(STATUS_IO_TIMEOUT);
2205 }
2206
2207 setStopEvent = RemoveCompletedRequestLocked(Request);
2208 Unlock(irql);
2210 "WDFREQUEST %p completed in from cancel",
2211 Request->GetTraceObjectHandle());
2213
2214 if (setStopEvent) {
2216 "WDFIOTARGET %p, setting stop event %p",
2218
2220 }
2221
2223}
2224
2225VOID
2228 )
2229/*++
2230
2231Routine Description:
2232 This function handles the completion of the request when Submit() fails.
2233 Request is tracked by the 'Io Count' counter, caller is responsible for
2234 updating its value.
2235
2236Arguments:
2237 Request - The request being completed.
2238
2239Return Value:
2240 None.
2241
2242 --*/
2243{
2244 KIRQL irql;
2245 BOOLEAN setStopEvent;
2246
2248 "WDFREQUEST %p", Request->GetTraceObjectHandle());
2249
2250 setStopEvent = FALSE;
2251
2252 Lock(&irql);
2253
2254 //
2255 // Flag should be clear until we set it below
2256 //
2257 ASSERT((Request->GetTargetFlags() & FX_REQUEST_COMPLETED) == 0);
2258
2259 //
2260 // Mark that the request has been completed
2261 //
2262 Request->SetTargetFlags(FX_REQUEST_COMPLETED);
2263
2264 //
2265 // Timer should not have been started.
2266 //
2267 ASSERT((Request->GetTargetFlags() & FX_REQUEST_TIMER_SET) == 0);
2268
2269 //
2270 // RemoveCompletedRequestLocked clears Request->m_TargetFlags, so we must
2271 // do this check before that call.
2272 //
2273 if ((Request->GetTargetFlags() & FX_REQUEST_CANCELLED_FROM_TIMER) &&
2274 Request->m_Irp.GetStatus() == STATUS_CANCELLED) {
2275 //
2276 // We cancelled the request from the timer and it has completed with
2277 // cancelled. Morph the status code into a timeout status.
2278 //
2279 // Don't muck with the IoStatus.Information field.
2280 //
2281 Request->m_Irp.SetStatus(STATUS_IO_TIMEOUT);
2282 }
2283
2284 setStopEvent = RemoveCompletedRequestLocked(Request);
2285
2286 Unlock(irql);
2287
2289 "WDFREQUEST %p completed in completion routine",
2290 Request->GetTraceObjectHandle());
2292
2293 if (setStopEvent) {
2295 "WDFIOTARGET %p, setting stop event %p",
2298 }
2299
2301}
2302
2303VOID
2306 )
2307/*++
2308
2309Routine Description:
2310 The previously submitted request has been completed. This function will
2311 handle coordination with the (optional) request timer and the potential
2312 simultaneous call to FxRequest::Cancel as to which function
2313 will actually complete the request.
2314
2315Arguments:
2316 Request - The request being completed.
2317
2318Return Value:
2319 None.
2320
2321 --*/
2322{
2323 KIRQL irql;
2324 BOOLEAN completeRequest, setStopEvent;
2325
2327 "WDFREQUEST %p", Request->GetTraceObjectHandle());
2328
2329
2330 setStopEvent = FALSE;
2331 completeRequest = FALSE;
2332
2333 Lock(&irql);
2334
2335 //
2336 // Flag should be clear until we set it below
2337 //
2338 ASSERT((Request->GetTargetFlags() & FX_REQUEST_COMPLETED) == 0);
2339
2340 //
2341 // Mark that the request has been completed so that the potential timer
2342 // DPC will handle the case properly
2343 //
2344 Request->SetTargetFlags(FX_REQUEST_COMPLETED);
2345
2346 //
2347 // CancelTimer() returns TRUE if the timer was successfully canceled (if
2348 // queued) or if no timer was queued.
2349 //
2350 if (Request->CancelTimer()) {
2351 //
2352 // Sync with Request->Cancel() to make sure we can delete the request.
2353 //
2354 completeRequest = Request->CanComplete();
2355 }
2356
2357 if (completeRequest) {
2358 //
2359 // RemoveCompletedRequestLocked clears Request->m_TargetFlags, so we must
2360 // do this check before that call.
2361 //
2362 if ((Request->GetTargetFlags() & FX_REQUEST_CANCELLED_FROM_TIMER) &&
2363 Request->m_Irp.GetStatus() == STATUS_CANCELLED) {
2364 //
2365 // We cancelled the request from the timer and it has completed with
2366 // cancelled. Morph the status code into a timeout status.
2367 //
2368 // Don't muck with the IoStatus.Information field.
2369 //
2370 Request->m_Irp.SetStatus(STATUS_IO_TIMEOUT);
2371 }
2372
2373 setStopEvent = RemoveCompletedRequestLocked(Request);
2374 }
2375 else {
2378 "WDFREQUEST %p deferring completion due to outstanding completion "
2379 "references", Request->GetTraceObjectHandle());
2380 }
2381
2382 Unlock(irql);
2383
2384 if (completeRequest) {
2386 "WDFREQUEST %p completed in completion routine",
2387 Request->GetTraceObjectHandle());
2389 }
2390
2391 if (setStopEvent) {
2393 "WDFIOTARGET %p, setting stop event %p",
2396 }
2397
2398 if (completeRequest) {
2400 }
2401}
2402
2405STDCALL
2408 MdIrp Irp,
2410 )
2411/*++
2412
2413Routine Description:
2414 Generic I/O completion routine for all submitted requests.
2415
2416Arguments:
2417 DeviceObject - Our device object. Most likely NULL since we created the
2418 request and we are the top most driver with respect to it
2419 Irp - Request itself. Ignored since the context also contains this value
2420 Context - Our context, FxRequestBase*.
2421
2422Return Value:
2423 STATUS_MORE_PROCESSING_REQUIRED since the lifetime of the Irp is controlled
2424 by the lifetime of our context which may outlive this function call.
2425
2426 --*/
2427{
2428 FxIoTarget* pThis;
2430
2431 FxIrp irp(Irp);
2432
2434
2436 pThis = pRequest->m_Target;
2437
2438 //
2439 // Only propagate the the pending returned bit in the IRP if this is an
2440 // asynchronous request
2441 //
2445 }
2446
2448
2450}
2451
2458 )
2459{
2463 ULONG i;
2464 FxIrp* irp;
2465
2466 status = Request->ValidateTarget(this);
2467 if (!NT_SUCCESS(status)) {
2468 return status;
2469 }
2470
2471 if (Request->HasContextType(FX_RCT_INTERNAL_IOCTL_OTHERS)) {
2472 pContext = (FxInternalIoctlOthersContext*) Request->GetContext();
2473 }
2474 else {
2476
2477 if (pContext == NULL) {
2480 "Could not allocate context for request");
2481
2483 }
2484
2485 Request->SetContext(pContext);
2486 }
2487
2488 //
2489 // Save away any references to IFxMemory pointers that are passed.
2490 // (StoreAndReferenceMemory can only store one buffer, so it doesn't help).
2491 //
2493 &Buffers[1],
2494 &Buffers[2]);
2495
2496
2497 irp = Request->GetSubmitFxIrp();
2499
2502
2504
2505 i = 0;
2509
2510 for (i = 0; i < FX_REQUEST_NUM_OTHER_PARAMS; i++) {
2511 status = Buffers[i].GetBuffer(bufs[i]);
2512
2513 if (!NT_SUCCESS(status)) {
2516 "Could not retrieve buffer %d, status %!STATUS!", i+1, status);
2517
2518 Request->ContextReleaseAndRestore();
2519
2520 return status;
2521 }
2522 }
2523
2524 if (NT_SUCCESS(status)) {
2525 Request->VerifierSetFormatted();
2526 }
2527
2528 return status;
2529}
2530
2531VOID
2534 __in MdIrp Irp,
2535 __in PMdIoCsqIrpContext CsqContext,
2537 )
2538{
2539 FxIoTarget* pThis;
2541 KIRQL irql;
2542 FxIrp pFxIrp;
2543
2545
2546 pThis->Unlock(CallerIrql);
2547
2548 //
2549 // Grab the request out of the irp. After this call we are done with the
2550 // m_CsqContext field.
2551 //
2553
2556 "Pended WDFREQUEST %p canceled", pRequest->GetTraceObjectHandle());
2557
2558 //
2559 // m_ListEntry is union'ed with m_CsqContext. m_CsqContext was in use up
2560 // until this function was called. From this point on, we are going to
2561 // process the request as if it has been completed. The completed code path
2562 // assumes m_ListEntry is on a list head. To have a valid m_ListEntry when
2563 // we call RemoveEntryList, initialize it now. Since we have an outstanding
2564 // irp completion reference count (which is decremented in the call to
2565 // FailPendedRequest later), we can safely initialize this field without
2566 // holding any locks.
2567 //
2569
2570 //
2571 // Undo the affects of the IoSetNextIrpStackLocation made when we
2572 // enqueued the request.
2573 //
2574 pFxIrp.SetIrp(Irp);
2576
2577 //
2578 // Request is no longer pended
2579 //
2580 pThis->Lock(&irql);
2583 pThis->Unlock(irql);
2584
2585 //
2586 // Call the driver's completion routine
2587 //
2589}
2590
2591VOID
2593 __in WDFREQUEST Request,
2594 __in WDFIOTARGET Target,
2597 )
2598{
2599 FxTargetSubmitSyncParams* pParams;
2600
2601 pParams = (FxTargetSubmitSyncParams*) Context;
2602 pParams->Status = Params->IoStatus.Status;
2603
2604 if (pParams->OrigTargetCompletionRoutine != NULL) {
2606 Request,
2607 Target,
2608 Params,
2610 );
2611 }
2612
2613 pParams->SynchEvent.Set();
2614}
2615
2616
2617VOID
2619 VOID
2620 )
2621/*++
2622
2623Routine Description:
2624 This will be used whenever we send a reset request.
2625 For example if you are sending a reset request
2626 to USB target, you must cancel outstanding I/O before sending a reset
2627 or cycle port request for error recovery.
2628--*/
2629
2630{
2631 SINGLE_LIST_ENTRY sentRequestListHead;
2632 BOOLEAN sentAdded;
2633 KIRQL irql;
2635
2636
2638 sentRequestListHead.Next = NULL;
2639 Lock(&irql);
2640
2641 GetSentRequestsListLocked(&sentRequestListHead,
2643 &sentAdded);
2644
2645 Unlock(irql);
2646
2649 "Cancelling pending I/O on WDFIOTARGET %p ",
2650 GetHandle());
2651
2652 if (sentAdded) {
2653 _CancelSentRequests(&sentRequestListHead);
2654 }
2655}
2656
2662 )
2663/*++
2664
2665Routine Description:
2666 Use this for sending a request which ignores target state.
2667--*/
2668{
2670 WDF_REQUEST_SEND_OPTIONS requestOptions;
2671
2673 if (RequestOptions != NULL) {
2674
2675 //
2676 // Do a copy so that the passed in paramters is
2677 // not modified.
2678 //
2679 RtlCopyMemory(&requestOptions,
2681 sizeof(WDF_REQUEST_SEND_OPTIONS));
2682
2683 if ((requestOptions.Flags & WDF_REQUEST_SEND_OPTION_IGNORE_TARGET_STATE) == 0) {
2685 "Ignoring WDFIOTARGET %p state to send request",
2686 GetHandle());
2688 }
2689 }
2690 else{
2691 WDF_REQUEST_SEND_OPTIONS_INIT(&requestOptions,
2693 }
2694
2695 return SubmitSync(Request, &requestOptions);
2696}
2697
2698VOID
2700 VOID
2701 )
2702{
2703 UCHAR ioType = GetTargetIoType();
2704
2705 //
2706 // m_IoCount is initialized to 1
2707 //
2708 if ((ioType != m_TargetIoType) && (m_IoCount > 1)) {
2711 "WDFIOTARGET %p has changed IoType with outstanding IO",
2712 GetHandle());
2713 }
2714 m_TargetIoType = (UCHAR) ioType;
2715}
#define CheckState(OldState, NewState)
unsigned char BOOLEAN
PVOID Buffers[0x100]
struct outqueuenode * head
Definition: adnsresfilter.c:66
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
virtual VOID RemoveIoTarget(__inout FxIoTarget *IoTarget)
Definition: fxdevice.hpp:261
NTSTATUS _Must_inspect_result_ QueryInterface(__inout FxQueryInterfaceParams *Params)
virtual _Must_inspect_result_ NTSTATUS GotoStartState(__in PLIST_ENTRY RequestListHead, __in BOOLEAN Lock=TRUE)
Definition: fxiotarget.cpp:306
virtual VOID Stop(__in WDF_IO_TARGET_SENT_IO_ACTION Action)
Definition: fxiotarget.cpp:748
VOID CancelSentIo(VOID)
VOID DrainPendedRequestsLocked(__in PLIST_ENTRY RequestListHead, __in BOOLEAN RequestWillBeResent)
Definition: fxiotarget.cpp:395
VOID CompleteCanceledRequest(__in FxRequestBase *Request)
VOID SetCompletionRoutine(__in FxRequestBase *Request)
Definition: fxiotarget.hpp:834
static MdCompletionRoutineType _RequestCompletionRoutine
Definition: fxiotarget.hpp:609
virtual VOID GotoStopState(__in WDF_IO_TARGET_SENT_IO_ACTION Action, __in PSINGLE_LIST_ENTRY SentRequestListHead, __out PBOOLEAN Wait, __in BOOLEAN LockSelf)
Definition: fxiotarget.cpp:617
LIST_ENTRY m_IgnoredIoListHead
Definition: fxiotarget.hpp:873
VOID FailPendedRequest(__in FxRequestBase *Request, __in NTSTATUS Status)
static VOID _CancelSentRequest(__in FxRequestBase *Request)
Definition: fxiotarget.cpp:534
_Must_inspect_result_ NTSTATUS SubmitSync(__in FxRequestBase *Request, __in_opt PWDF_REQUEST_SEND_OPTIONS Options=NULL, __out_opt PULONG Action=NULL)
virtual VOID Remove(VOID)
VOID TimerCallback(__in FxRequestBase *Request)
VOID RequestCompletionRoutine(__in FxRequestBase *Request)
ULONG SubmitLocked(__in FxRequestBase *Request, __in_opt PWDF_REQUEST_SEND_OPTIONS Options, __in ULONG Flags)
BOOLEAN m_AddedToDeviceList
Definition: fxiotarget.hpp:860
UCHAR GetTargetIoType(VOID)
Definition: fxiotarget.hpp:631
VOID HandleFailedResubmit(__in FxRequestBase *Request)
LIST_ENTRY m_SentIoListHead
Definition: fxiotarget.hpp:868
_Must_inspect_result_ NTSTATUS SubmitSyncRequestIgnoreTargetState(__in FxRequestBase *Request, __in_opt PWDF_REQUEST_SEND_OPTIONS RequestOptions)
FxIrpQueue m_PendedQueue
Definition: fxiotarget.hpp:895
_Must_inspect_result_ NTSTATUS Init(__in CfxDeviceBase *Device)
MdDeviceObject m_TargetDevice
Definition: fxiotarget.hpp:910
MdDeviceObject m_TargetPdo
Definition: fxiotarget.hpp:918
FxTransactionedEntry m_TransactionedEntry
Definition: fxiotarget.hpp:853
virtual VOID WaitForDisposeEvent(VOID)
Definition: fxiotarget.cpp:124
BOOLEAN m_InStack
Definition: fxiotarget.hpp:855
LONG m_IoCount
Definition: fxiotarget.hpp:935
UCHAR m_TargetIoType
Definition: fxiotarget.hpp:947
VOID UpdateTargetIoType(VOID)
virtual BOOLEAN Dispose(VOID)
Definition: fxiotarget.cpp:154
__inline VOID CompleteRequest(__in FxRequestBase *Request)
Definition: fxiotarget.hpp:580
MdDeviceObject m_InStackDevice
Definition: fxiotarget.hpp:905
WDF_IO_TARGET_STATE m_State
Definition: fxiotarget.hpp:928
__inline VOID CopyFileObjectAndFlags(__in FxRequestBase *Request)
Definition: fxiotarget.hpp:743
FxCREvent m_DisposeEventUm
Definition: fxiotarget.hpp:892
VOID SubmitPendedRequests(__in PLIST_ENTRY RequestListHeadHead)
Definition: fxiotarget.cpp:268
_Must_inspect_result_ NTSTATUS PendRequestLocked(__in FxRequestBase *Request)
VOID CompletePendedRequest(__in FxRequestBase *Request)
Definition: fxiotarget.cpp:508
__inline VOID DecrementIoCount(VOID)
Definition: fxiotarget.hpp:785
VOID CompletePendedRequestList(__in PLIST_ENTRY RequestListHead)
Definition: fxiotarget.cpp:520
VOID Construct(VOID)
Definition: fxiotarget.cpp:54
virtual VOID ClearTargetPointers(VOID)
Definition: fxiotarget.hpp:618
FxDriver * m_Driver
Definition: fxiotarget.hpp:900
BOOLEAN RemoveCompletedRequestLocked(__in FxRequestBase *Request)
_Must_inspect_result_ NTSTATUS FormatInternalIoctlOthersRequest(__in FxRequestBase *Request, __in ULONG Ioctl, __in FxRequestBuffer *Buffers)
virtual _Must_inspect_result_ MdDeviceObject GetTargetDeviceObject(_In_ CfxDeviceBase *Device)
Definition: fxiotarget.hpp:326
CCHAR m_TargetStackSize
Definition: fxiotarget.hpp:941
static VOID _CancelSentRequests(__in PSINGLE_LIST_ENTRY RequestListHead)
Definition: fxiotarget.cpp:550
static VOID _RequestCancelled(__in FxIrpQueue *Queue, __in MdIrp Irp, __in PMdIoCsqIrpContext pCsqContext, __in KIRQL CallerIrql)
FxCREvent * m_DisposeEvent
Definition: fxiotarget.hpp:885
virtual VOID GotoPurgeState(__in WDF_IO_TARGET_PURGE_IO_ACTION Action, __in PLIST_ENTRY PendedRequestListHead, __in PSINGLE_LIST_ENTRY SentRequestListHead, __out PBOOLEAN Wait, __in BOOLEAN LockSelf)
Definition: fxiotarget.cpp:790
VOID SubmitPendedRequest(__in FxRequestBase *Request)
Definition: fxiotarget.cpp:206
virtual VOID Send(_In_ MdIrp Irp)
static const PVOID m_SentRequestTag
Definition: fxiotarget.hpp:862
FxCREvent m_SentIoEvent
Definition: fxiotarget.hpp:878
static EVT_WDF_REQUEST_COMPLETION_ROUTINE _SyncCompletionRoutine
Definition: fxiotarget.hpp:662
_Must_inspect_result_ NTSTATUS InitModeSpecific(__in CfxDeviceBase *Device)
BOOLEAN m_WaitingForSentIo
Definition: fxiotarget.hpp:953
virtual VOID GotoRemoveState(__in WDF_IO_TARGET_STATE NewState, __in PLIST_ENTRY PendedRequestListHead, __in PSINGLE_LIST_ENTRY SentRequestListHead, __in BOOLEAN Lock, __out PBOOLEAN Wait)
Definition: fxiotarget.cpp:964
__inline VOID IncrementIoCount(VOID)
Definition: fxiotarget.hpp:767
ULONG Submit(__in FxRequestBase *Request, __in_opt PWDF_REQUEST_SEND_OPTIONS Options, __in_opt ULONG Flags)
VOID ClearCompletedRequestVerifierFlags(__in FxRequestBase *Request)
Definition: fxiotarget.hpp:814
VOID GetSentRequestsListLocked(__in PSINGLE_LIST_ENTRY RequestListHead, __in PLIST_ENTRY SendList, __out PBOOLEAN AddedToList)
Definition: fxiotarget.cpp:582
BOOLEAN m_Removing
Definition: fxiotarget.hpp:955
VOID PrintDisposeMessage(VOID)
Definition: fxiotarget.cpp:99
virtual VOID Purge(__in WDF_IO_TARGET_PURGE_IO_ACTION Action)
Definition: fxiotarget.cpp:918
FxIoTarget(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in USHORT ObjectSize)
Definition: fxiotarget.cpp:34
virtual _Must_inspect_result_ NTSTATUS Start(VOID)
Definition: fxiotarget.cpp:282
virtual VOID WaitForSentIoToComplete(VOID)
Definition: fxiotarget.hpp:676
MdFileObject m_TargetFileObject
Definition: fxiotarget.hpp:923
_Must_inspect_result_ NTSTATUS InsertTailRequest(__inout MdIrp Irp, __in_opt PMdIoCsqIrpContext CsqContext, __out_opt ULONG *pRequestCount)
Definition: fxirpqueue.cpp:115
VOID Initialize(__in FxNonPagedObject *LockObject, __in PFN_IRP_QUEUE_CANCEL Callback)
Definition: fxirpqueue.cpp:61
MdIrp GetNextRequest(__out PMdIoCsqIrpContext *pCsqContext)
Definition: fxirpqueue.cpp:219
Definition: fxirp.hpp:28
PVOID * GetNextStackParameterOthersArgument2Pointer()
Definition: fxirpum.cpp:1434
PVOID * GetNextStackParameterOthersArgument4Pointer()
Definition: fxirpum.cpp:1447
CCHAR GetCurrentIrpStackLocationIndex()
Definition: fxirpum.cpp:521
VOID SetMajorFunction(__in UCHAR MajorFunction)
Definition: fxirpum.cpp:905
VOID SetParameterIoctlCode(__in ULONG DeviceIoControlCode)
Definition: fxirpum.cpp:1157
VOID SetNextIrpStackLocation(VOID)
Definition: fxirpum.cpp:1235
VOID SkipCurrentIrpStackLocation(VOID)
Definition: fxirpum.cpp:400
VOID PropagatePendingReturned(VOID)
Definition: fxirpum.cpp:443
VOID SetStatus(__in NTSTATUS Status)
Definition: fxirpum.cpp:457
NTSTATUS GetStatus()
Definition: fxirpum.cpp:466
PVOID * GetNextStackParameterOthersArgument1Pointer()
Definition: fxirpum.cpp:1421
MdIrp GetIrp(VOID)
Definition: fxirpum.cpp:15
VOID SetInformation(__in ULONG_PTR Information)
Definition: fxirpum.cpp:504
BOOLEAN IsCurrentIrpStackLocationValid(VOID)
Definition: fxirpum.cpp:1761
MdIrp SetIrp(MdIrp irp)
Definition: fxirpkm.hpp:71
VOID ClearNextStackLocation(VOID)
Definition: fxirpum.cpp:1581
VOID MarkPassiveDispose(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:944
VOID SetDeviceBase(__in CfxDeviceBase *DeviceBase)
Definition: fxobject.hpp:797
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
CfxDeviceBase * m_DeviceBase
Definition: fxobject.hpp:328
__drv_restoresIRQL KIRQL __in BOOLEAN Unlock
Definition: fxobject.hpp:1474
VOID MarkDisposeOverride(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:1101
virtual _Must_inspect_result_ NTSTATUS QueryInterface(__in FxQueryInterfaceParams *Params)
Definition: fxobject.cpp:255
__inline VOID CallCleanup(VOID)
Definition: fxobject.hpp:815
SINGLE_LIST_ENTRY m_DrainSingleEntry
__inline FxIrp * GetSubmitFxIrp(VOID)
__inline PVOID GetTraceObjectHandle(VOID)
__inline VOID SetTargetFlags(__in UCHAR Flags)
FxIoTarget * m_Target
__inline BOOLEAN CanComplete(VOID)
static __inline FxRequestBase * _FromListEntry(__in PLIST_ENTRY Entry)
__inline ULONG ClearTargetFlags(__in UCHAR Flags)
LIST_ENTRY m_ListEntry
static __inline FxRequestBase * _FromDrainEntry(__in PSINGLE_LIST_ENTRY Entry)
_Must_inspect_result_ BOOLEAN CancelTimer(VOID)
FxRequestCompletionCallback m_CompletionRoutine
static __inline FxRequestBase * _FromCsqContext(__in PMdIoCsqIrpContext Context)
__inline UCHAR GetTargetFlags(VOID)
PFN_WDF_REQUEST_COMPLETION_ROUTINE m_Completion
__inline VOID SetObject(__in_opt MdDeviceObject DeviceObject)
CCHAR GetStackSize(VOID)
static __inline KIRQL MxGetCurrentIrql()
Definition: mxgeneralkm.h:86
_In_ PIRP Irp
Definition: csq.h:116
#define __out_opt
Definition: dbghelp.h:65
#define __in
Definition: dbghelp.h:35
#define __inout
Definition: dbghelp.h:50
#define __in_opt
Definition: dbghelp.h:38
#define __out
Definition: dbghelp.h:62
#define TRACINGIOTARGET
Definition: dbgtrace.h:72
#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
const WCHAR * action
Definition: action.c:7479
KIRQL irql
Definition: wave.h:1
#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
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
PFX_DRIVER_GLOBALS pFxDriverGlobals
return pObject GetObjectHandle()
MxDeviceObject deviceObject
PSINGLE_LIST_ENTRY ple
FxVerifierDbgBreakPoint(pFxDriverGlobals)
FxRequest * pRequest
@ OkForDownLevel
Definition: fxglobals.h:80
__inline LONG FxInterlockedIncrementGTZero(__inout LONG volatile *Target)
Definition: fxglobals.h:1045
FxIrp * irp
PAGED_CODE_LOCKED()
KIRQL irql
return status
SHORT flags
_Must_inspect_result_ NTSTATUS _In_ FxRequestBase * Request
#define START_TAG
Definition: fxiotarget.cpp:302
@ SubmitTimeout
Definition: fxiotarget.hpp:206
@ SubmitWait
Definition: fxiotarget.hpp:205
@ SubmitSend
Definition: fxiotarget.hpp:202
@ SubmitSyncCallCompletion
Definition: fxiotarget.hpp:207
@ SubmitSent
Definition: fxiotarget.hpp:204
@ SubmitQueued
Definition: fxiotarget.hpp:203
_Must_inspect_result_ __in WDFIOTARGET __in_opt WDFREQUEST __in ULONG Ioctl
__in MdIrp __in PMdIoCsqIrpContext __in KIRQL CallerIrql
Definition: fxirpqueue.hpp:77
#define FX_VF_METHOD(classname, fnName)
Definition: fxmacros.hpp:43
@ ObjectDoNotLock
Definition: fxobject.hpp:128
#define ADDREF(_tag)
Definition: fxobject.hpp:49
#define RELEASE(_tag)
Definition: fxobject.hpp:50
FxIrp * pIrp
FxIrp * irp
#define WDF_REQUEST_SEND_INTERNAL_OPTION_FAIL_ON_PEND
@ FX_REQUEST_PENDED
@ FX_REQUEST_TIMER_SET
@ FX_REQUEST_IGNORE_STATE
@ FX_REQUEST_COMPLETED
@ FX_REQUEST_CANCELLED_FROM_TIMER
@ FXREQUEST_FLAG_FORMATTED
@ FXREQUEST_FLAG_SENT_TO_TARGET
#define FX_REQUEST_NUM_OTHER_PARAMS
@ FX_RCT_INTERNAL_IOCTL_OTHERS
@ FX_TYPE_IO_TARGET
Definition: fxtypes.h:100
#define FxVerifierBugCheck(FxDriverGlobals, Error,...)
Definition: fxverifier.h:58
Status
Definition: gdiplustypes.h:25
struct _cl_event * event
Definition: glext.h:7739
const GLenum * bufs
Definition: glext.h:6026
GLenum const GLfloat * params
Definition: glext.h:5645
GLbitfield flags
Definition: glext.h:7161
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] STATPROPSETSTG *rgelt, [out] ULONG *pceltFetched)
#define ASSERT(a)
Definition: mode.c:44
#define _Must_inspect_result_
Definition: ms_sal.h:558
#define _In_
Definition: ms_sal.h:308
#define DO_NOTHING()
Definition: mxgeneral.h:32
IWudfIrp * MdIrp
Definition: mxum.h:103
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define STATUS_REQUEST_NOT_ACCEPTED
Definition: ntstatus.h:444
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
void CheckError(HRESULT hr)
Definition: shellclasses.h:167
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
#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
FxCREvent * GetSelfPointer(VOID)
Definition: fxwaitlock.hpp:180
PVOID GetEvent(VOID)
Definition: fxwaitlock.hpp:172
VOID Set(VOID)
Definition: fxwaitlock.hpp:144
VOID Clear(VOID)
Definition: fxwaitlock.hpp:152
CHECK_RETURN_IF_USER_MODE NTSTATUS Initialize(__in BOOLEAN InitialState=FALSE)
Definition: fxwaitlock.hpp:51
VOID StoreAndReferenceOtherMemories(__in FxRequestBuffer *Buffer1, __in FxRequestBuffer *Buffer2, __in FxRequestBuffer *Buffer4)
Definition: fxiotarget.hpp:129
WDFCONTEXT OrigTargetCompletionContext
Definition: fxiotarget.hpp:198
PFN_WDF_REQUEST_COMPLETION_ROUTINE OrigTargetCompletionRoutine
Definition: fxiotarget.hpp:193
VOID SetTransactionedObject(__in FxObject *Object)
BOOLEAN FxVerifierOn
Definition: fxglobals.h:420
BOOLEAN FxVerifierIO
Definition: fxglobals.h:446
_Must_inspect_result_ BOOLEAN IsVerificationEnabled(__in ULONG Major, __in ULONG Minor, __in FxVerifierDownlevelOption DownLevel)
Definition: fxglobals.h:286
Definition: typedefs.h:120
Definition: ntbasedef.h:628
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:629
Definition: ps.c:97
Definition: dhcpd.h:245
#define GetHandle(h)
Definition: treelist.c:116
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char * PBOOLEAN
Definition: typedefs.h:53
int64_t LONGLONG
Definition: typedefs.h:68
void * PVOID
Definition: typedefs.h:50
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
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_IO_TIMEOUT
Definition: udferr_usr.h:163
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#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
#define STDCALL
Definition: wdf.h:45
@ WDF_REQUEST_FATAL_ERROR
Definition: wdfbugcodes.h:63
@ WDF_REQUEST_FATAL_ERROR_REQUEST_ALREADY_SENT
Definition: wdfbugcodes.h:78
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ WDFDEVICE _In_ PIRP _In_ WDFQUEUE Queue
Definition: wdfdevice.h:2225
_In_ PWDFDEVICE_INIT _In_ PWDF_REMOVE_LOCK_OPTIONS Options
Definition: wdfdevice.h:3534
@ WdfDeviceIoUndefined
Definition: wdfdevice.h:450
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
enum _WDF_IO_TARGET_PURGE_IO_ACTION WDF_IO_TARGET_PURGE_IO_ACTION
@ WdfIoTargetCancelSentIo
Definition: wdfiotarget.h:71
@ WdfIoTargetWaitForSentIoToComplete
Definition: wdfiotarget.h:72
@ WdfIoTargetLeaveSentIoPending
Definition: wdfiotarget.h:73
enum _WDF_IO_TARGET_SENT_IO_ACTION WDF_IO_TARGET_SENT_IO_ACTION
@ WdfIoTargetClosed
Definition: wdfiotarget.h:56
@ WdfIoTargetStarted
Definition: wdfiotarget.h:53
@ WdfIoTargetClosedForQueryRemove
Definition: wdfiotarget.h:55
@ WdfIoTargetPurged
Definition: wdfiotarget.h:58
@ WdfIoTargetDeleted
Definition: wdfiotarget.h:57
@ WdfIoTargetStopped
Definition: wdfiotarget.h:54
_In_ WDFIOTARGET _In_ _Strict_type_match_ WDF_IO_TARGET_SENT_IO_ACTION Action
Definition: wdfiotarget.h:510
@ WdfIoTargetPurgeIo
Definition: wdfiotarget.h:79
@ WdfIoTargetPurgeIoAndWait
Definition: wdfiotarget.h:78
WDF_EXTERN_C_START enum _WDF_IO_TARGET_STATE WDF_IO_TARGET_STATE
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS RequestOptions
Definition: wdfiotarget.h:867
FORCEINLINE VOID WDF_REQUEST_SEND_OPTIONS_INIT(_Out_ PWDF_REQUEST_SEND_OPTIONS Options, _In_ ULONG Flags)
Definition: wdfrequest.h:409
@ WDF_REQUEST_SEND_OPTION_TIMEOUT
Definition: wdfrequest.h:108
@ WDF_REQUEST_SEND_OPTION_IGNORE_TARGET_STATE
Definition: wdfrequest.h:110
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:308
#define STATUS_WDF_QUEUED
Definition: wdfstatus.h:81
#define STATUS_WDF_DEVICE_REMOVED_NOT_SENT
Definition: wdfstatus.h:144
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:127
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define IRP_MJ_INTERNAL_DEVICE_CONTROL
_In_ BOOLEAN Remove
Definition: psfuncs.h:110
FORCEINLINE PSINGLE_LIST_ENTRY PopEntryList(_Inout_ PSINGLE_LIST_ENTRY ListHead)
Definition: rtlfuncs.h:240
static void startTimer(void)
Definition: xmllint.c:460
unsigned char UCHAR
Definition: xmlstorage.h:181