ReactOS  0.4.15-dev-3287-gfec35dc
fxiotarget.cpp
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7  FxIoTarget.cpp
8 
9 Abstract:
10 
11  This module implements the IO Target APIs
12 
13 Author:
14 
15 Environment:
16 
17  Both kernel and user mode
18 
19 Revision History:
20 
21 --*/
22 
23 
24 #include "../fxtargetsshared.hpp"
25 
26 extern "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 
53 VOID
55  VOID
56  )
57 {
60 
61  m_InStack = TRUE;
62 
64 
66  m_Removing = FALSE;
68 
69  m_Driver = NULL;
72  m_TargetPdo = 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 
98 VOID
100  VOID
101  )
102 /*++
103 
104 Routine 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 
109 Arguments:
110  None
111 
112 Return Value:
113  None
114 
115  --*/
116 
117 {
119  "WDFIOTARGET %p, setting Dispose event %p",
121 }
122 
123 VOID
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 
144  if (InterlockedDecrement(&m_IoCount) > 0) {
145  event->EnterCRAndWaitAndLeave();
146  }
147 
149  ASSERT(m_IoCount == 0);
150 }
151 
152 
153 BOOLEAN
155  VOID
156  )
157 /*++
158 
159 Routine 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 
167 Arguments:
168  None
169 
170 Return Value:
171  FALSE, indicating to the FxObject state machine *NOT* to call
172 
173  --*/
174 
175 {
177 
178  if (m_AddedToDeviceList) {
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 
205 VOID
208  )
209 {
210  ULONG action;
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  //
239  irp->SetInformation(0);
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 
267 VOID
269  __in PLIST_ENTRY RequestListHead
270  )
271 {
273 
274  while (!IsListEmpty(RequestListHead)) {
275  ple = RemoveHeadList(RequestListHead);
277  }
278 }
279 
281 NTSTATUS
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 
305 NTSTATUS
307  __in PLIST_ENTRY RequestListHead,
309  )
310 {
312  KIRQL irql;
313 
315 
316  ADDREF(START_TAG);
317 
318  if (Lock) {
320  }
321 
322 CheckState:
323  if (m_State == WdfIoTargetDeleted) {
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.",
337  GetObjectHandle());
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  //
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 
394 VOID
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();
431  pFxIrp->SkipCurrentIrpStackLocation();
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 
507 VOID
510  )
511 {
512  //
513  // This will attempt to claim cancelation ownership and call the
514  // request's completion routine.
515  //
517 }
518 
519 VOID
521  __in PLIST_ENTRY RequestListHead
522  )
523 {
525 
526  while (!IsListEmpty(RequestListHead)) {
527  ple = RemoveHeadList(RequestListHead);
530  }
531 }
532 
533 VOID
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 
549 VOID
551  __in PSINGLE_LIST_ENTRY RequestListHead
552  )
553 /*++
554 
555 Routine Description:
556  Cancels all FxRequestBases in RequestListHead
557 
558 Arguments:
559  RequestListHead - List head containing the requests
560 
561 Return 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 
581 VOID
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 
616 VOID
619  __in PSINGLE_LIST_ENTRY SentRequestListHead,
621  __in BOOLEAN LockSelf
622  )
623 /*++
624 
625 Routine Description:
626  Accumulates all pending I/O for cancelling out of this function if
627  RequestListHead != NULL.
628 
629 Arguments:
630 
631 
632 Return 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.",
698  GetObjectHandle());
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  //
739  m_SentIoEvent.Set();
740  }
741 
742  if (LockSelf) {
743  Unlock(irql);
744  }
745 }
746 
747 VOID
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 
789 VOID
792  __in PLIST_ENTRY PendedRequestListHead,
793  __in PSINGLE_LIST_ENTRY SentRequestListHead,
795  __in BOOLEAN LockSelf
796  )
797 /*++
798 
799 Routine Description:
800  Accumulates all pending and sent I/O. The I/O target is moved into
801  the 'purged' state.
802 
803 Arguments:
804 
805 
806 Return 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.",
877  GetObjectHandle());
878 
880  }
881  }
882  else {
883  wait = TRUE;
884  }
885  break;
886 
887  case WdfIoTargetPurgeIo:
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  //
909  m_SentIoEvent.Set();
910  }
911 
912  if (LockSelf) {
913  Unlock(irql);
914  }
915 }
916 
917 VOID
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 
963 VOID
965  __in WDF_IO_TARGET_STATE NewState,
966  __in PLIST_ENTRY PendedRequestListHead,
967  __in PSINGLE_LIST_ENTRY SentRequestListHead,
968  __in BOOLEAN Lock,
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.",
987  GetObjectHandle());
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  //
1044  m_SentIoEvent.Clear();
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  //
1054  m_SentIoEvent.Set();
1055  }
1056  }
1057 
1058  if (Lock) {
1059  Unlock(irql);
1060  }
1061 
1062  return;
1063 }
1064 
1065 VOID
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 
1101 NTSTATUS
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 
1118 NTSTATUS
1121  )
1122 {
1123  NTSTATUS status;
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 ||
1146  m_TargetDevice == NULL || m_TargetPdo == 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 
1184 NTSTATUS
1185 FX_VF_METHOD(FxIoTarget, VerifySubmitLocked) (
1186  _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
1188  )
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 
1243 ULONG
1247  __in ULONG Flags
1248  )
1249 /*++
1250 
1251 Routine 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 
1273 Arguments:
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 
1280 Return Value:
1281  A bit field whose flags are defined by SubmitActionFlags
1282 
1283  --*/
1284 {
1286  NTSTATUS status;
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 {
1412  action |= SubmitQueued;
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 
1440 Done:
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  //
1457  IncrementIoCount();
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  //
1511  action |= SubmitQueued;
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) {
1528  InsertTailList(&m_IgnoredIoListHead, &Request->m_ListEntry);
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 
1609 CheckError:
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)) {
1615  irp->SetStatus(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);
1629  DecrementIoCount();
1630  }
1631 
1632  return action;
1633 }
1634 
1635 ULONG
1640  )
1641 {
1642  ULONG result;
1643  KIRQL irql;
1644 
1645  Lock(&irql);
1647  Unlock(irql);
1648 
1649  return result;
1650 }
1651 
1653 NTSTATUS
1658  )
1659 {
1661  LONGLONG timeout;
1662  ULONG action;
1663  NTSTATUS status;
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;
1709  action |= SubmitTimeout;
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  //
1822  action |= (SubmitSent | SubmitWait);
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(
1838  (action & SubmitTimeout) ? &timeout : NULL
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);
1848  Request->SetTargetFlags(FX_REQUEST_CANCELLED_FROM_TIMER);
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 
1876 VOID
1880  )
1881 /*++
1882 
1883 Routine Description:
1884  Completes a request that has failed due to timer expiration or cancellation.
1885 
1886 Assumes:
1887  Assumes that the caller has undone the effects of the
1888  IoSetNextIrpStackLocation made when we enqueued the request.
1889 
1890 Arguments:
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 
1897 Return Value:
1898  None.
1899 
1900  --*/
1901 {
1902  FxIrp* irp;
1903 
1904  irp = Request->GetSubmitFxIrp();
1905 
1906  //
1907  // Simulate failure in the IRP
1908  //
1909  irp->SetStatus(Status);
1910  irp->SetInformation(0);
1911 
1912  //
1913  // Manaully process the irp as if it has completed back from the target.
1914  //
1916 }
1917 
1918 BOOLEAN
1921  )
1922 /*++
1923 
1924 Routine Description:
1925  Removes a previously sent request from the bookkeeping structures
1926 
1927 Arguments:
1928  Request - The request being completed
1929 
1930 Assumes:
1931  This object's Lock is being held by the caller.
1932 
1933 Return 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 
2016 NTSTATUS
2019  )
2020 {
2021  NTSTATUS status;
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 
2042  status = m_PendedQueue.InsertTailRequest(irp->GetIrp(), &Request->m_CsqContext, NULL);
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 
2060 VOID
2063  )
2064 /*++
2065 
2066 Routine 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 
2070 Arguments:
2071  Request - The request that has timed out
2072 
2073 Return 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  //
2112  Request->SetTargetFlags(FX_REQUEST_CANCELLED_FROM_TIMER);
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 
2174  m_SentIoEvent.Set();
2175  }
2176 
2177  if (completeRequest) {
2178  DecrementIoCount();
2179  }
2180 }
2181 
2182 VOID
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 
2219  m_SentIoEvent.Set();
2220  }
2221 
2222  DecrementIoCount();
2223 }
2224 
2225 VOID
2228  )
2229 /*++
2230 
2231 Routine 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 
2236 Arguments:
2237  Request - The request being completed.
2238 
2239 Return 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",
2297  m_SentIoEvent.Set();
2298  }
2299 
2300  DecrementIoCount();
2301 }
2302 
2303 VOID
2306  )
2307 /*++
2308 
2309 Routine 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 
2315 Arguments:
2316  Request - The request being completed.
2317 
2318 Return 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",
2395  m_SentIoEvent.Set();
2396  }
2397 
2398  if (completeRequest) {
2399  DecrementIoCount();
2400  }
2401 }
2402 
2404 NTSTATUS
2405 STDCALL
2408  MdIrp Irp,
2409  PVOID Context
2410  )
2411 /*++
2412 
2413 Routine Description:
2414  Generic I/O completion routine for all submitted requests.
2415 
2416 Arguments:
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 
2422 Return 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 
2453 NTSTATUS
2456  __in ULONG Ioctl,
2458  )
2459 {
2460  FxInternalIoctlOthersContext *pContext;
2462  NTSTATUS status;
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 {
2475  pContext = new(GetDriverGlobals()) FxInternalIoctlOthersContext();
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 
2531 VOID
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);
2575  pFxIrp.SkipCurrentIrpStackLocation();
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 
2591 VOID
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) {
2605  pParams->OrigTargetCompletionRoutine(
2606  Request,
2607  Target,
2608  Params,
2610  );
2611  }
2612 
2613  pParams->SynchEvent.Set();
2614 }
2615 
2616 
2617 VOID
2619  VOID
2620  )
2621 /*++
2622 
2623 Routine 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 
2658 NTSTATUS
2662  )
2663 /*++
2664 
2665 Routine 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 
2698 VOID
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 }
__in MdIrp __in PMdIoCsqIrpContext __in KIRQL CallerIrql
Definition: fxirpqueue.hpp:74
__inline ULONG ClearTargetFlags(__in UCHAR Flags)
static __inline FxRequestBase * _FromDrainEntry(__in PSINGLE_LIST_ENTRY Entry)
__drv_restoresIRQL KIRQL __in BOOLEAN Unlock
Definition: fxobject.hpp:1474
FORCEINLINE VOID WDF_REQUEST_SEND_OPTIONS_INIT(_Out_ PWDF_REQUEST_SEND_OPTIONS Options, _In_ ULONG Flags)
Definition: wdfrequest.h:409
MdDeviceObject m_TargetDevice
Definition: fxiotarget.hpp:910
WDFCONTEXT OrigTargetCompletionContext
Definition: fxiotarget.hpp:198
#define GetHandle(h)
Definition: treelist.c:116
enum _WDF_IO_TARGET_PURGE_IO_ACTION WDF_IO_TARGET_PURGE_IO_ACTION
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
SHORT flags
VOID SetMajorFunction(__in UCHAR MajorFunction)
Definition: fxirpum.cpp:905
CHECK_RETURN_IF_USER_MODE NTSTATUS Initialize(__in BOOLEAN InitialState=FALSE)
Definition: fxwaitlock.hpp:51
BOOLEAN FxVerifierOn
Definition: fxglobals.h:420
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
VOID CompletePendedRequestList(__in PLIST_ENTRY RequestListHead)
Definition: fxiotarget.cpp:520
LONG m_IoCount
Definition: fxiotarget.hpp:935
FxTransactionedEntry m_TransactionedEntry
Definition: fxiotarget.hpp:853
VOID PrintDisposeMessage(VOID)
Definition: fxiotarget.cpp:99
CCHAR GetStackSize(VOID)
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:306
GLint x0
Definition: linetemp.h:95
VOID SetStatus(__in NTSTATUS Status)
Definition: fxirpum.cpp:457
GLuint64EXT * result
Definition: glext.h:11304
const GLenum * bufs
Definition: glext.h:6026
_Must_inspect_result_ NTSTATUS PendRequestLocked(__in FxRequestBase *Request)
CCHAR GetCurrentIrpStackLocationIndex()
Definition: fxirpum.cpp:521
FxIoTarget * m_Target
Definition: ntbasedef.h:628
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
MdIrp GetNextRequest(__out PMdIoCsqIrpContext *pCsqContext)
Definition: fxirpqueue.cpp:219
struct outqueuenode * head
Definition: adnsresfilter.c:66
PVOID GetEvent(VOID)
Definition: fxwaitlock.hpp:172
#define __in_opt
Definition: dbghelp.h:38
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
virtual BOOLEAN Dispose(VOID)
Definition: fxiotarget.cpp:154
_Must_inspect_result_ NTSTATUS FX_VF_METHOD(FxIoTarget, VerifySubmitLocked)(_In_ PFX_DRIVER_GLOBALS FxDriverGlobals
_Must_inspect_result_ _In_ WDFDEVICE _In_ PIRP _In_ WDFQUEUE Queue
Definition: wdfdevice.h:2221
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:167
#define WDF_REQUEST_SEND_INTERNAL_OPTION_FAIL_ON_PEND
_Must_inspect_result_ NTSTATUS FormatInternalIoctlOthersRequest(__in FxRequestBase *Request, __in ULONG Ioctl, __in FxRequestBuffer *Buffers)
PVOID Buffers[0x100]
static EVT_WDF_REQUEST_COMPLETION_ROUTINE _SyncCompletionRoutine
Definition: fxiotarget.hpp:662
#define CheckState(OldState, NewState)
LONG NTSTATUS
Definition: precomp.h:26
__inline VOID CopyFileObjectAndFlags(__in FxRequestBase *Request)
Definition: fxiotarget.hpp:743
VOID MarkPassiveDispose(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:944
BOOLEAN m_WaitingForSentIo
Definition: fxiotarget.hpp:953
BOOLEAN IsCurrentIrpStackLocationValid(VOID)
Definition: fxirpum.cpp:1761
VOID DrainPendedRequestsLocked(__in PLIST_ENTRY RequestListHead, __in BOOLEAN RequestWillBeResent)
Definition: fxiotarget.cpp:395
_Must_inspect_result_ BOOLEAN CancelTimer(VOID)
FxRequest * pRequest
__inline FxIrp * GetSubmitFxIrp(VOID)
#define FX_REQUEST_NUM_OTHER_PARAMS
Definition: fxirp.hpp:28
#define STATUS_REQUEST_NOT_ACCEPTED
Definition: ntstatus.h:444
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
_Must_inspect_result_ NTSTATUS SubmitSync(__in FxRequestBase *Request, __in_opt PWDF_REQUEST_SEND_OPTIONS Options=NULL, __out_opt PULONG Action=NULL)
VOID SetTransactionedObject(__in FxObject *Object)
VOID SetDeviceBase(__in CfxDeviceBase *DeviceBase)
Definition: fxobject.hpp:797
Definition: dhcpd.h:245
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
FxIrp * pIrp
#define RELEASE(_tag)
Definition: fxobject.hpp:50
VOID CompletePendedRequest(__in FxRequestBase *Request)
Definition: fxiotarget.cpp:508
#define InsertTailList(ListHead, Entry)
VOID FailPendedRequest(__in FxRequestBase *Request, __in NTSTATUS Status)
VOID Set(VOID)
Definition: fxwaitlock.hpp:144
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
_Must_inspect_result_ NTSTATUS InitModeSpecific(__in CfxDeviceBase *Device)
GLbitfield GLuint64 timeout
Definition: glext.h:7164
virtual VOID RemoveIoTarget(__inout FxIoTarget *IoTarget)
Definition: fxdevice.hpp:261
FxCREvent m_SentIoEvent
Definition: fxiotarget.hpp:878
WDF_IO_TARGET_STATE m_State
Definition: fxiotarget.hpp:928
FxCREvent * GetSelfPointer(VOID)
Definition: fxwaitlock.hpp:180
#define FxVerifierBugCheck(FxDriverGlobals, Error,...)
Definition: fxverifier.h:58
LIST_ENTRY m_ListEntry
ULONG Submit(__in FxRequestBase *Request, __in_opt PWDF_REQUEST_SEND_OPTIONS Options, __in_opt ULONG Flags)
VOID PropagatePendingReturned(VOID)
Definition: fxirpum.cpp:443
PSINGLE_LIST_ENTRY ple
MdDeviceObject m_InStackDevice
Definition: fxiotarget.hpp:905
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define STATUS_INVALID_DEVICE_STATE
Definition: udferr_usr.h:178
__inline VOID IncrementIoCount(VOID)
Definition: fxiotarget.hpp:767
_Must_inspect_result_ __in WDFIOTARGET __in_opt WDFREQUEST __in ULONG Ioctl
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define START_TAG
Definition: fxiotarget.cpp:302
enum _WDF_IO_TARGET_SENT_IO_ACTION WDF_IO_TARGET_SENT_IO_ACTION
FxDriver * m_Driver
Definition: fxiotarget.hpp:900
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
static VOID _CancelSentRequest(__in FxRequestBase *Request)
Definition: fxiotarget.cpp:534
UCHAR KIRQL
Definition: env_spec_w32.h:591
WDFIOTARGET GetHandle(VOID)
Definition: fxiotarget.hpp:307
FxCREvent m_DisposeEventUm
Definition: fxiotarget.hpp:892
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ NTSTATUS SubmitSyncRequestIgnoreTargetState(__in FxRequestBase *Request, __in_opt PWDF_REQUEST_SEND_OPTIONS RequestOptions)
static void startTimer(void)
Definition: xmllint.c:469
__inline UCHAR GetTargetFlags(VOID)
#define __out_opt
Definition: dbghelp.h:65
#define FALSE
Definition: types.h:117
VOID SetNextIrpStackLocation(VOID)
Definition: fxirpum.cpp:1235
GLenum const GLfloat * params
Definition: glext.h:5645
_In_ PIRP Irp
Definition: csq.h:116
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
#define STATUS_WDF_DEVICE_REMOVED_NOT_SENT
Definition: wdfstatus.h:144
long LONG
Definition: pedump.c:60
short SHORT
Definition: pedump.c:59
#define ADDREF(_tag)
Definition: fxobject.hpp:49
VOID UpdateTargetIoType(VOID)
BOOLEAN m_AddedToDeviceList
Definition: fxiotarget.hpp:860
VOID MarkDisposeOverride(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:1101
PVOID __inline GetObjectHandle(VOID)
Definition: fxobject.hpp:603
#define __out
Definition: dbghelp.h:62
PVOID * GetNextStackParameterOthersArgument4Pointer()
Definition: fxirpum.cpp:1447
VOID SkipCurrentIrpStackLocation(VOID)
Definition: fxirpum.cpp:400
unsigned char BOOLEAN
VOID CancelSentIo(VOID)
FxIoTarget(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in USHORT ObjectSize)
Definition: fxiotarget.cpp:34
MdFileObject m_TargetFileObject
Definition: fxiotarget.hpp:923
#define _In_
Definition: ms_sal.h:308
__inline PVOID GetTraceObjectHandle(VOID)
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
IWudfIrp * MdIrp
Definition: mxum.h:103
VOID ClearNextStackLocation(VOID)
Definition: fxirpum.cpp:1581
void * PVOID
Definition: retypes.h:9
MdDeviceObject m_TargetPdo
Definition: fxiotarget.hpp:918
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
FORCEINLINE PSINGLE_LIST_ENTRY PopEntryList(_Inout_ PSINGLE_LIST_ENTRY ListHead)
Definition: rtlfuncs.h:240
VOID Construct(VOID)
Definition: fxiotarget.cpp:54
virtual VOID Remove(VOID)
VOID RequestCompletionRoutine(__in FxRequestBase *Request)
Status
Definition: gdiplustypes.h:24
int64_t LONGLONG
Definition: typedefs.h:68
_Must_inspect_result_ NTSTATUS InsertTailRequest(__inout MdIrp Irp, __in_opt PMdIoCsqIrpContext CsqContext, __out_opt ULONG *pRequestCount)
Definition: fxirpqueue.cpp:115
UCHAR GetTargetIoType(VOID)
Definition: fxiotarget.hpp:631
_In_ PWDFDEVICE_INIT _In_ PWDF_REMOVE_LOCK_OPTIONS Options
Definition: wdfdevice.h:3531
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
PFX_DRIVER_GLOBALS pFxDriverGlobals
BOOLEAN m_InStack
Definition: fxiotarget.hpp:855
#define STDCALL
Definition: wdf.h:45
#define ASSERT(a)
Definition: mode.c:44
WDF_EXTERN_C_START enum _WDF_IO_TARGET_STATE WDF_IO_TARGET_STATE
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
VOID Clear(VOID)
Definition: fxwaitlock.hpp:152
__inline VOID CompleteRequest(__in FxRequestBase *Request)
Definition: fxiotarget.hpp:580
PFN_WDF_REQUEST_COMPLETION_ROUTINE OrigTargetCompletionRoutine
Definition: fxiotarget.hpp:193
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
BOOLEAN m_Removing
Definition: fxiotarget.hpp:955
VOID SetInformation(__in ULONG_PTR Information)
Definition: fxirpum.cpp:504
HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] STATPROPSETSTG *rgelt, [out] ULONG *pceltFetched)
VOID TimerCallback(__in FxRequestBase *Request)
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
_Must_inspect_result_ BOOLEAN IsVerificationEnabled(__in ULONG Major, __in ULONG Minor, __in FxVerifierDownlevelOption DownLevel)
Definition: fxglobals.h:286
static __inline KIRQL MxGetCurrentIrql()
Definition: mxgeneralkm.h:86
#define IRP_MJ_INTERNAL_DEVICE_CONTROL
VOID CompleteCanceledRequest(__in FxRequestBase *Request)
BOOLEAN RemoveCompletedRequestLocked(__in FxRequestBase *Request)
GLbitfield flags
Definition: glext.h:7161
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
static const PVOID m_SentRequestTag
Definition: fxiotarget.hpp:862
unsigned char UCHAR
Definition: xmlstorage.h:181
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:629
char * PBOOLEAN
Definition: retypes.h:11
#define InterlockedDecrement
Definition: armddk.h:52
_Must_inspect_result_ NTSTATUS _In_ FxRequestBase * Request
UCHAR m_TargetIoType
Definition: fxiotarget.hpp:947
VOID HandleFailedResubmit(__in FxRequestBase *Request)
CfxDeviceBase * m_DeviceBase
Definition: fxobject.hpp:328
void CheckError(HRESULT hr)
Definition: shellclasses.h:167
LIST_ENTRY m_SentIoListHead
Definition: fxiotarget.hpp:868
virtual VOID Purge(__in WDF_IO_TARGET_PURGE_IO_ACTION Action)
Definition: fxiotarget.cpp:918
virtual _Must_inspect_result_ NTSTATUS Start(VOID)
Definition: fxiotarget.cpp:282
#define __inout
Definition: dbghelp.h:50
Definition: typedefs.h:119
__inline BOOLEAN CanComplete(VOID)
struct _cl_event * event
Definition: glext.h:7739
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define _Must_inspect_result_
Definition: ms_sal.h:558
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
FxCREvent * m_DisposeEvent
Definition: fxiotarget.hpp:885
virtual VOID ClearTargetPointers(VOID)
Definition: fxiotarget.hpp:618
static MdCompletionRoutineType _RequestCompletionRoutine
Definition: fxiotarget.hpp:609
MxDeviceObject deviceObject
NTSTATUS _Must_inspect_result_ QueryInterface(__inout FxQueryInterfaceParams *Params)
_Must_inspect_result_ NTSTATUS Init(__in CfxDeviceBase *Device)
static __inline FxRequestBase * _FromCsqContext(__in PMdIoCsqIrpContext Context)
static VOID _RequestCancelled(__in FxIrpQueue *Queue, __in MdIrp Irp, __in PMdIoCsqIrpContext pCsqContext, __in KIRQL CallerIrql)
virtual VOID WaitForSentIoToComplete(VOID)
Definition: fxiotarget.hpp:676
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
virtual _Must_inspect_result_ MdDeviceObject GetTargetDeviceObject(_In_ CfxDeviceBase *Device)
Definition: fxiotarget.hpp:326
PVOID * GetNextStackParameterOthersArgument2Pointer()
Definition: fxirpum.cpp:1434
virtual _Must_inspect_result_ NTSTATUS GotoStartState(__in PLIST_ENTRY RequestListHead, __in BOOLEAN Lock=TRUE)
Definition: fxiotarget.cpp:306
ULONG SubmitLocked(__in FxRequestBase *Request, __in_opt PWDF_REQUEST_SEND_OPTIONS Options, __in ULONG Flags)
BOOLEAN FxVerifierIO
Definition: fxglobals.h:446
FxRequestCompletionCallback m_CompletionRoutine
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
const WCHAR * action
Definition: action.c:7783
__inline LONG FxInterlockedIncrementGTZero(__inout LONG volatile *Target)
Definition: fxglobals.h:1045
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
MdIrp GetIrp(VOID)
Definition: fxirpum.cpp:15
SINGLE_LIST_ENTRY m_DrainSingleEntry
unsigned short USHORT
Definition: pedump.c:61
_In_ WDFIOTARGET _In_ _Strict_type_match_ WDF_IO_TARGET_SENT_IO_ACTION Action
Definition: wdfiotarget.h:506
CCHAR m_TargetStackSize
Definition: fxiotarget.hpp:941
PFN_WDF_REQUEST_COMPLETION_ROUTINE m_Completion
virtual VOID WaitForDisposeEvent(VOID)
Definition: fxiotarget.cpp:124
__inline VOID CallCleanup(VOID)
Definition: fxobject.hpp:815
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
return status
__inline VOID SetObject(__in_opt MdDeviceObject DeviceObject)
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
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 SetTargetFlags(__in UCHAR Flags)
#define STATUS_IO_TIMEOUT
Definition: udferr_usr.h:163
PVOID * GetNextStackParameterOthersArgument1Pointer()
Definition: fxirpum.cpp:1421
static VOID _CancelSentRequests(__in PSINGLE_LIST_ENTRY RequestListHead)
Definition: fxiotarget.cpp:550
VOID SubmitPendedRequest(__in FxRequestBase *Request)
Definition: fxiotarget.cpp:206
_In_ WDFIOTARGET Target
Definition: wdfrequest.h:306
VOID StoreAndReferenceOtherMemories(__in FxRequestBuffer *Buffer1, __in FxRequestBuffer *Buffer2, __in FxRequestBuffer *Buffer4)
Definition: fxiotarget.hpp:129
VOID SetCompletionRoutine(__in FxRequestBase *Request)
Definition: fxiotarget.hpp:834
VOID Initialize(__in FxNonPagedObject *LockObject, __in PFN_IRP_QUEUE_CANCEL Callback)
Definition: fxirpqueue.cpp:61
LIST_ENTRY m_IgnoredIoListHead
Definition: fxiotarget.hpp:873
VOID SetParameterIoctlCode(__in ULONG DeviceIoControlCode)
Definition: fxirpum.cpp:1157
_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:859
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:124
unsigned int ULONG
Definition: retypes.h:1
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
static __inline FxRequestBase * _FromListEntry(__in PLIST_ENTRY Entry)
PAGED_CODE_LOCKED()
virtual _Must_inspect_result_ NTSTATUS QueryInterface(__in FxQueryInterfaceParams *Params)
Definition: fxobject.cpp:255
#define STATUS_SUCCESS
Definition: shellext.h:65
virtual VOID Send(_In_ MdIrp Irp)
FxIrpQueue m_PendedQueue
Definition: fxiotarget.hpp:895
MdIrp SetIrp(MdIrp irp)
Definition: fxirpkm.hpp:71
#define STATUS_WDF_QUEUED
Definition: wdfstatus.h:81
__inline VOID DecrementIoCount(VOID)
Definition: fxiotarget.hpp:785
#define __in
Definition: dbghelp.h:35
VOID SubmitPendedRequests(__in PLIST_ENTRY RequestListHeadHead)
Definition: fxiotarget.cpp:268
#define TRACINGIOTARGET
Definition: dbgtrace.h:72
FxIrp * irp
FxVerifierDbgBreakPoint(pFxDriverGlobals)
virtual VOID Stop(__in WDF_IO_TARGET_SENT_IO_ACTION Action)
Definition: fxiotarget.cpp:748
KIRQL irql
#define DO_NOTHING()
Definition: mxgeneral.h:32
NTSTATUS GetStatus()
Definition: fxirpum.cpp:466
Definition: ps.c:97