ReactOS  0.4.15-dev-3441-g67ad4e7
fxpkggeneral.cpp
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7  FxPkgGeneral.cpp
8 
9 Abstract:
10 
11  This module implements the wmi package for the driver frameworks.
12 
13 Author:
14 
15 
16 
17 
18 Environment:
19 
20  Both kernel and user mode
21 
22 Revision History:
23 
24 --*/
25 
26 #if ((FX_CORE_MODE)==(FX_CORE_USER_MODE))
27 #define FX_IS_USER_MODE (TRUE)
28 #define FX_IS_KERNEL_MODE (FALSE)
29 #elif ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE))
30 #define FX_IS_USER_MODE (FALSE)
31 #define FX_IS_KERNEL_MODE (TRUE)
32 #endif
33 
34 extern "C" {
35 #include "mx.h"
36 }
37 #include "fxmin.hpp"
38 
39 extern "C" {
40 // #include "FxPkgGeneral.tmh"
41 }
42 
43 
45  __in PFX_DRIVER_GLOBALS FxDriverGlobals,
47  ) :
48  FxPackage(FxDriverGlobals, Device, FX_TYPE_PACKAGE_GENERAL)
49 {
50  //
51  // The count is biased to one and not zero for control device objects. When
52  // a control devobj is deleted, we will decrement this bias out so that we
53  // know when the last handle has been closed and it is now safe to free the
54  // FxDevice.
55  //
57 
58  //
59  // List of file object info.
60  //
62 
63  m_Flags = 0;
70 }
71 
73 {
75 
77 
78  //
79  // Delete the file object info list if present.
80  //
86  delete info;
87  }
88 }
89 
94  )
95 /*++
96 
97 Routine Description:
98  Initiliazes how the driver will handle fileobjects and their associated
99  event callbacks (create, close, cleanup).
100 
101  Assumes that FileObjectAttributes has been validated by the caller.
102 
103 Arguments:
104  DeviceInit - Chain of device_init and cx_device_init with file object config.
105 
106 Return Value:
107  STATUS_SUCCESS or other NTSTATUS values.
108 
109  --*/
110 {
113  FxFileObjectInfo* fileObjInfo;
115 
117 
118  //
119  // Init file object info.
120  //
121  if (DeviceInit->FileObject.Set) {
122  fileObjInfo = new(fxDriverGlobals) FxFileObjectInfo();
123  if (fileObjInfo == NULL) {
127  "Couldn't create object FileObjectInfo, "
128  "%!STATUS!", status);
129  goto Done;
130  }
131 
132  fileObjInfo->ClassExtension = FALSE;
133  fileObjInfo->FileObjectClass = DeviceInit->FileObject.Class;
134  fileObjInfo->Attributes = DeviceInit->FileObject.Attributes;
135 
136  fileObjInfo->AutoForwardCleanupClose =
137  DeviceInit->FileObject.AutoForwardCleanupClose;
138 
139  fileObjInfo->EvtFileCreate.Method =
140  DeviceInit->FileObject.Callbacks.EvtDeviceFileCreate;
141 
142  fileObjInfo->EvtFileCleanup.Method =
143  DeviceInit->FileObject.Callbacks.EvtFileCleanup;
144 
145  fileObjInfo->EvtFileClose.Method =
146  DeviceInit->FileObject.Callbacks.EvtFileClose;
147 
149 
151 
152  if (fileObjInfo->EvtFileCreate.Method != NULL) {
154  }
155  }
156 
157  //
158  // Build file object info chain for any class extension.
159  //
160  for (next = DeviceInit->CxDeviceInitListHead.Flink;
161  next != &DeviceInit->CxDeviceInitListHead;
162  next = next->Flink) {
163 
164  PWDFCXDEVICE_INIT cxInit;
165 
166  cxInit = CONTAINING_RECORD(next, WDFCXDEVICE_INIT, ListEntry);
167 
168  if (cxInit->FileObject.Set == FALSE) {
169  continue;
170  }
171 
172  fileObjInfo = new(fxDriverGlobals) FxFileObjectInfo();
173  if (fileObjInfo == NULL) {
177  "Couldn't create object FileObjectInfo, "
178  "%!STATUS!", status);
179  goto Done;
180  }
181 
182  fileObjInfo->ClassExtension = TRUE;
183  fileObjInfo->FileObjectClass = cxInit->FileObject.Class;
184  fileObjInfo->Attributes = cxInit->FileObject.Attributes;
185 
186  fileObjInfo->AutoForwardCleanupClose =
188 
189  fileObjInfo->EvtCxFileCreate.Method =
191 
192  fileObjInfo->EvtFileCleanup.Method =
194 
195  fileObjInfo->EvtFileClose.Method =
197 
198  fileObjInfo->CxDeviceInfo = cxInit->CxDeviceInfo;
199 
201 
203 
204  if (fileObjInfo->EvtCxFileCreate.Method != NULL) {
206  }
207  }
208 
209  //
210  // Nothing to do if list if empty.
211  //
214  goto Done;
215  }
216 
217  //
218  // We will enable this once the unlocking model is figured out.
219  // It's not okay to sent request downstack with the presentation lock held.
220  //
222  if(!NT_SUCCESS(status)) {
223  goto Done;
224  }
225 
226  //
227  // Configure file object class.
228  //
230  if (!NT_SUCCESS(status)) {
231  goto Done;
232  }
233 
235 
236 Done:
237  return status;
238 }
239 
241 NTSTATUS
243  __in PLIST_ENTRY FileObjInfoList
244  )
245 /*++
246 
247 Routine Description:
248 
249  Configure the callback synchronization according to the configuration supplied by the
250  client and class extension device driver.
251  It is a requirement for this driver chain (CXs and client driver) to use the same settings.
252 
253 Arguments:
254  FileObjInfoList - List of FxFileObjectInfo structs.
255 
256 Returns:
257  NTSTATUS
258 
259 --*/
260 {
261  WDF_EXECUTION_LEVEL execLevel, parentExecLevel;
262  WDF_SYNCHRONIZATION_SCOPE synchScope, parentSynchScope;
263  BOOLEAN automaticLockingRequired;
265  FxFileObjectInfo *fileObjInfo;
268 
269  automaticLockingRequired = FALSE;
271 
272  ASSERT(!IsListEmpty(FileObjInfoList));
273 
274  //
275  // Get parent values.
276  //
277  m_Device->GetConstraints(&parentExecLevel, &parentSynchScope);
278 
279  //
280  // Default constraints settings when driver uses WDF_NO_OBJECT_ATTRIBUTES:
281  //
282  // v1.9 and below:
283  // WdfExecutionLevelDispatch and WdfSynchronizationScopeNone
284  //
285  // v1.11 and above:
286  // WdfExecutionLevelPassive and WdfSynchronizationScopeNone
287  //
288  // In v1.9 and below if driver used WDF_NO_OBJECT_ATTRIBUTES for
289  // the file object's attributes, the synchronization scope and execution
290  // level were left uninitialized (i.e., zero), which means that WDF
291  // defaulted to WdfSynchronizationScopeInvalid and WdfExecutionLevelInvalid,
292  // WDF interpreted these values as no_passive and no_synchronization.
293  //
294  // This default execution level is used when disposing the device's
295  // general package object and file object object.
296  // Independently of these settings WDF guarantees that Create,
297  // Cleanup and Close callbacks are always called at passive level.
298  //
302 
304 
305  //
306  // Make sure file object info chain follow these constrains:
307  // Cx's synch scope: none
308  //
309  for (next = FileObjInfoList->Blink;
310  next != FileObjInfoList;
311  next = next->Blink) {
312 
313  fileObjInfo = CONTAINING_RECORD(next, FxFileObjectInfo, ListEntry);
314 
315  //
316  // Size is zero if driver didn't specify any attributes.
317  //
318  if (0 == fileObjInfo->Attributes.Size) {
319  continue;
320  }
321 
322  //
323  // Execution level checks.
324  //
325  execLevel = fileObjInfo->Attributes.ExecutionLevel;
326  if (WdfExecutionLevelInheritFromParent == execLevel) {
327  execLevel = parentExecLevel;
328  }
329 
330  //
331  // Passive level wins over DPC level.
332  //
333  if (WdfExecutionLevelPassive == execLevel) {
335  }
336 
337  //
338  // Synchronization scope checks.
339  //
340  synchScope = fileObjInfo->Attributes.SynchronizationScope;
341  if (WdfSynchronizationScopeInheritFromParent == synchScope) {
342  synchScope = parentSynchScope;
343  }
344 
345  //
346  // Make sure the Cx's synch scope is none.
347  //
348  if (fileObjInfo->ClassExtension) {
349  if (synchScope != WdfSynchronizationScopeNone) {
353  "Driver 0x%p - Device 0x%p - synchronization scope: "
354  "%!WDF_SYNCHRONIZATION_SCOPE! should be"
355  "WdfSynchronizationScopeNone, %!STATUS!",
356  m_Device->GetCxDriver(fileObjInfo->CxDeviceInfo)->GetHandle(),
357  m_Device->GetHandle(),
358  synchScope,
359  status
360  );
361 
363  goto Done;
364  }
365  }
366  else {
367  //
368  // Always use client's synch scope for file object.
369  //
370  m_SynchronizationScope = synchScope;
371  }
372  }
373 
378  "WdfSynchronizationScopeQueue is not allowed on "
379  "FileObject, %!STATUS!",
380  status);
381  goto Done;
382  }
383 
385 
386  //
387  // Mark FxObject as passive level to ensure that Dispose and Destroy
388  // callbacks are passive to the driver
389  //
391  //
392  // We aren't going to use a workitem to defer the invocation of fileevents
393  // to passive-level if the caller is at DISPATCH_LEVEL because we wouldn't
394  // be able to guarantee the caller's context for fileevents. It's up to the
395  // driver writer to ensure that the layer above doesn't send create requests
396  // at dispatch-level.
397  //
398  }
399 
402  goto Done;
403  }
404 
406  //
407  // Since FileEvents can be invoked only at passive-level, we check the
408  // parent executionlevel to see if it's set to passive. If not, we return an error
409  // because we can't use the presentation lock of the device.
410  //
411  if(parentExecLevel != WdfExecutionLevelPassive) {
415  "WdfSynchronizationScopeDevice or "
416  "WdfSynchronizationScopeInheritFromParent "
417  "allowed only if the parent WDFDEVICE 0x%p, "
418  "ExecutionLevel is passive, %!STATUS!",
420  goto Done;
421  }
422 
424  automaticLockingRequired = TRUE;
425  }
426 
427  //
428  // Set lock constraint in client's callbacks object only.
429  //
430  if (automaticLockingRequired) {
431  if (!IsListEmpty(FileObjInfoList)) {
432  fileObjInfo = CONTAINING_RECORD(FileObjInfoList->Flink,
434  ListEntry);
435 
436  if (FALSE == fileObjInfo->ClassExtension) {
440  }
441  }
442  }
443 
445 
446 Done:
447  return status;
448 }
449 
451 NTSTATUS
453  __in PLIST_ENTRY FileObjInfoList
454  )
455 /*++
456 
457 Routine Description:
458 
459  Configure the file object class for this device.
460 
461  These are the possible class settings:
462 
463  WdfFileObjectNotRequired
464  WdfFileObjectWdfCanUseFsContext*
465  WdfFileObjectWdfCanUseFsContext2*,
466  WdfFileObjectWdfCannotUseFsContexts*
467 
468  * these can also be combined with WdfFileObjectCanBeOptional flag.
469 
470  Logic:
471 
472  - default: not_required.
473  - if cx/driver selects not_required, skip it.
474  - if cx/driver selects !not_required, than
475  . if everyone agrees on the setting, use that setting.
476  . else use cannot_use_fs_contexts.
477 
478 Arguments:
479  FileObjInfoList - List of FxFileObjectInfo structs.
480 
481 Returns:
482  NTSTATUS
483 
484 --*/
485 {
487  FxFileObjectInfo* fileObjInfo;
490  WDF_FILEOBJECT_CLASS fileObjClass;
491  FxCxDeviceInfo* previousCxInfo;
492 
494  fileObjClass = WdfFileObjectNotRequired;
495  previousCxInfo = NULL;
496 
497  ASSERT(!IsListEmpty(FileObjInfoList));
498 
499  //
500  // Compute the execution level and synchronization scope for all the chain.
501  //
502  for (next = FileObjInfoList->Blink;
503  next != FileObjInfoList;
504  next = next->Blink) {
505 
506  fileObjInfo = CONTAINING_RECORD(next, FxFileObjectInfo, ListEntry);
507 
508  //
509  // If not required, skip it.
510  //
511  if (WdfFileObjectNotRequired == fileObjInfo->FileObjectClass) {
512  continue;
513  }
514 
515  //
516  // If the same, skip it.
517  //
518  if (fileObjClass == fileObjInfo->FileObjectClass) {
519  continue;
520  }
521 
522  //
523  // If not set yet, use new value.
524  //
525  if (WdfFileObjectNotRequired == fileObjClass) {
526  fileObjClass = fileObjInfo->FileObjectClass;
527  previousCxInfo = fileObjInfo->CxDeviceInfo;
528  continue;
529  }
530 
531  //
532  // Make sure optional flag is compatible.
533  //
534  if (FxIsFileObjectOptional(fileObjClass) !=
535  FxIsFileObjectOptional(fileObjInfo->FileObjectClass)) {
536 
541  "Device 0x%p - "
542  "Driver 0x%p - WdfFileObjectCanBeOptional (%d) is not "
543  "compatible with wdf extension "
544  "Driver 0x%p - WdfFileObjectCanBeOptional (%d), %!STATUS!",
545  m_Device->GetHandle(),
546  m_Device->GetCxDriver(fileObjInfo->CxDeviceInfo)->GetHandle(),
547  FxIsFileObjectOptional(fileObjInfo->FileObjectClass) ? 1:0,
548  previousCxInfo->Driver->GetHandle(),
549  FxIsFileObjectOptional(fileObjClass) ? 1:0,
550  status
551  );
552 
554  goto Done;
555  }
556 
557  //
558  // Drivers do not agree on the location, set cannot use fx contexts.
559  //
561  if (FxIsFileObjectOptional(fileObjInfo->FileObjectClass)) {
562  fileObjClass = (WDF_FILEOBJECT_CLASS)
563  ((ULONG)fileObjClass | WdfFileObjectCanBeOptional);
564  }
565 
569  "Converting file object class for Driver 0x%p - Device 0x%p, "
570  "from 0x%x to 0x%x",
571  m_Device->GetCxDriver(fileObjInfo->CxDeviceInfo)->GetHandle(),
572  m_Device->GetHandle(),
573  fileObjInfo->FileObjectClass,
574  fileObjClass
575  );
576  }
577 
578  //
579  // Set the file object support level on the FxDevice
580  //
581  m_Device->SetFileObjectClass(fileObjClass);
582 
584 
585 Done:
586  return status;
587 }
588 
590 NTSTATUS
593  )
594 /*++
595 
596 Routine Description:
597  Optionally registers a shutdown and last chance shutdown notification on
598  behalf of the device.
599 
600 Arguments:
601  Init - Initialization structure which will indicate if registration is required
602 
603 Return Value:
604  NTSTATUS
605 
606  --*/
607 {
610  WDF_IO_QUEUE_CONFIG queueConfig;
611  WDF_OBJECT_ATTRIBUTES attributes;
613 
616 
617 
618 
619 
620 #if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE))
621  if (Init->Control.Flags != 0) {
623 
624  if (Init->Control.Flags & WdfDeviceShutdown) {
626  }
627 
628  if (NT_SUCCESS(status) &&
629  (Init->Control.Flags & WdfDeviceLastChanceShutdown)) {
631 
632  }
633 
634  if (NT_SUCCESS(status)) {
635  //
636  // IoDeleteDevice will automatically unregister the shutdown
637  // notifications if the device is deleted before the machine is
638  // shutdown, so we don't need to track registration beyond this point.
639  //
640  m_EvtDeviceShutdown.m_Method = Init->Control.ShutdownNotification;
641  }
642  else {
643  //
644  // This unregisters both the normal and last chance notifications
645  //
647  }
648  }
649 #else
652 #endif
653 
655  //
656  // Create an internal queue to track create requests presented to the driver.
657  // This special queue is used so that we can invoke the events in the context
658  // of the caller.
659  //
661 
662  //
663  // non power managed queue because we don't anticipate drivers touching
664  // hardware in the fileevent callbacks. If they do, then they should make sure
665  // to power up the device.
666  //
667  queueConfig.PowerManaged = WdfFalse;
668 
669  //
670  // Queue inherits the sync & exec level of fileobject.
671  //
672  WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
673  attributes.ExecutionLevel = m_ExecutionLevel;
675 
676  status = m_Device->m_PkgIo->CreateQueue(&queueConfig,
677  &attributes,
678  NULL,
680 
681  if (!NT_SUCCESS(status)) {
684  "Unable to create an internal queue for creates for WDFDEVICE "
685  "0x%p, %!STATUS!", m_Device->GetHandle(), status);
686  return status;
687  }
688  }
689 
690  return status;
691 }
692 
694 NTSTATUS
696  __in FxIoQueue* TargetQueue
697  )
698 /*++
699 
700 Routine Description:
701 
702  Used to register driver specified for dispatching create requests.
703 
704 Arguments:
705 
706 Return Value:
707 
708  NTSTATUS
709 
710  --*/
711 {
714  KIRQL irql;
715 
718 
719  if(TargetQueue->IsIoEventHandlerRegistered(WdfRequestTypeCreate) == FALSE){
723  "Must have EvtIoDefault registered to receive "
724  "WdfRequestTypeCreate requests for WDFQUEUE 0x%p, "
725  "%!STATUS!", TargetQueue->GetObjectHandle(), status);
727  return status;
728  }
729 
730  Lock(&irql);
731 
732  if (m_DriverCreatedQueue) {
734 
737  "Another WDFQUEUE 0x%p is already configured for auto dispatching "
738  "create request, %!STATUS!",
740 
742  }
743  else {
744  m_DriverCreatedQueue = TargetQueue;
745  }
746 
747  Unlock(irql);
748 
749  return status;
750 }
751 
753 NTSTATUS
756  )
757 /*++
758 
759 Routine Description:
760 
761  Dispatch routine for handling create, cleanup, close, and shutdown requests.
762 
763 Arguments:
764 
765 
766 Return Value:
767 
768  NTSTATUS
769 
770  --*/
771 {
774  FxIrp fxIrp(Irp);
775 
777 
779  "WDFDEVICE 0x%p !devobj 0x%p %!IRPMJ! IRP 0x%p",
782 
783  switch (fxIrp.GetMajorFunction()) {
784  case IRP_MJ_CREATE:
785  status = OnCreate(&fxIrp);
786  break;
787 
788  case IRP_MJ_CLOSE:
789  status = OnClose(&fxIrp);
790  break;
791 
792  case IRP_MJ_CLEANUP:
793  status = OnCleanup(&fxIrp);
794  break;
795 
796  case IRP_MJ_SHUTDOWN:
797  status = OnShutdown(&fxIrp);
798  break;
799 
800  default:
801  ASSERT(FALSE);
805  break;
806  }
807 
808  return status;
809 }
810 
812 NTSTATUS
815  )
816 /*++
817 
818 Routine Description:
819 
820  1) Allow only one handle to be open for exclusive device.
821  2) Create a WDFFILEOBJECT to represent the WDM fileobject. This
822  fileobject is created only if the driver registers for EvtFile events and
823  doesn't specify WdfFileObjectNotRequired. If the file-events are not
824  registered, the default FileobjectClass is WdfFileObjectNotRequired - set
825  during DeviceInit.
826  3) If the EvtFileCreate event is *not* set or any driver queue is not configured,
827  then complete or forward the request to the lower
828  driver depending on AutoForwardCleanupClose. AutoForwardCleanupClose
829  is set to TRUE by default for filter drivers.
830  4) Create a FxRequest.
831  5) First try to dispatch it to a driver specified queue.
832  6) If there is no driver specified queue, then check to see if the driver has
833  registered EvtDeviceFileCreate event.
834  7) If EvtFileCreate is set then dispatch the request to to an internal
835  manual queue, retrieve the request by fileobject and present the request to
836  the driver in the EvtFileCreate event. This allow the driver to forward the request
837  to another queue to mark the request cancelable and complete it later.
838 
839 Arguments:
840 
841 Return Value:
842 
843  NTSTATUS
844 
845  --*/
846 {
849  WDFFILEOBJECT hwdfFO;
852  MdFileObject fileObject;
853  LONG count;
854  BOOLEAN inCriticalRegion;
855  BOOLEAN inDefaultQueue;
856  FxFileObjectInfo* fileObjInfo;
857  WDF_OBJECT_ATTRIBUTES attributes;
859 
860  pFxFO = NULL;
861  hwdfFO = NULL;
862  pRequest = NULL;
863  inCriticalRegion = FALSE;
864  inDefaultQueue = FALSE;
866  fileObject = FxIrp->GetFileObject();
867  fileObjInfo = NULL;
868 
869  //
870  // Check for exclusivity.
871  //
873 
874  //
875  // The count is biased by one to help track when to delete the control
876  // device, so we need to check for 2, not 1.
877  //
878  if (m_Device->IsExclusive() && count > 2) {
881  "Exclusive WDFDEVICE 0x%p, only one open handle is allowed",
882  m_Device->GetHandle());
884  goto Error;
885  }
886 
887  // ------------------------------------------------------------------------
888  //
889  // Create WDFFILEOBJECT. By default we allocate the root driver's file obj
890  // context; then we attach the other file obj contexts.
891  //
892 
893  //
894  // Init the file obj's attributes. Use default if not present (legacy behavior).
895  //
896  WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
898  //
899  // file obj info is set, use the top most driver's info, i.e., cx if present.
900  //
903  ListEntry);
904 
905  //
906  // Use this layer's attributes if present.
907  // Size is zero if driver didn't specify file object's attributes.
908  //
909  if (0 != fileObjInfo->Attributes.Size) {
910  ASSERT(fileObjInfo->Attributes.Size == sizeof(WDF_OBJECT_ATTRIBUTES));
911  attributes = fileObjInfo->Attributes;
912  }
913 
914  //
915  // Use computed constraint settings.
916  //
917  attributes.ExecutionLevel = m_ExecutionLevel;
919  }
920 
921  //
922  // Create the file object.
923  //
925  m_Device,
926  FxIrp->GetIrp(),
928  &attributes,
929  fileObject,
930  &pFxFO
931  );
932 
933  if (!NT_SUCCESS(status) ) {
936  "Could not create WDFFILEOBJECT for WDFDEVICE 0x%p, failing "
937  "IRP_MJ_CREATE %!STATUS!", m_Device->GetHandle(), status);
938  goto Error;
939  }
940 
941  if (pFxFO != NULL) {
942  hwdfFO = pFxFO->GetHandle();
943 
944  //
945  // If any, attach the file obj's contexts of the other drivers in this chain.
946  //
947  for (next = m_FileObjectInfoHeadList.Blink->Blink; // skip one.
949  next = next->Blink) {
950 
951  fileObjInfo = CONTAINING_RECORD(next, FxFileObjectInfo, ListEntry);
952 
953  attributes = fileObjInfo->Attributes;
954 
955  //
956  // Size is zero if driver didn't specify file object's attributes.
957  //
958  if (0 == attributes.Size) {
959  continue;
960  }
961 
962  //
963  // Don't need these settings for extra contexts.
964  //
967  attributes.ParentObject = NULL;
968 
970  &attributes,
971  TRUE,
972  NULL);
973  if(!NT_SUCCESS(status)) {
976  "Couldn't allocate file object context 0x%p for "
977  "device 0x%p - driver 0x%p, %!STATUS!",
978  &fileObjInfo->Attributes,
979  m_Device->GetHandle(),
980  m_Device->GetCxDriver(fileObjInfo->CxDeviceInfo)->GetHandle(),
981  status
982  );
983 
984  goto Error;
985  }
986  }
987  }
988 
989  // ------------------------------------------------------------------------
990  //
991  // If there is no driver configured queue or m_EvtFileCreate is not registered,
992  // complete the request with status-success. The reason for making this
993  // check after creating the fileobject is to allow WdfRequestGetFileObject even
994  // if the driver hasn't registered any file-event callbacks.
995  //
996  if (m_DriverCreatedQueue == NULL &&
998 
999  //
1000  // Check to see if the driver has opted to autoforward cleanup and close.
1001  // If so, we should forward create requests also. Else, we should
1002  // complete the request with STATUS_SUCCESS. Note, if the driver is
1003  // a filter driver, the default value of m_AutoForwardCleanupClose is TRUE.
1004  //
1005  //
1008  //
1009  // _CreateCompletionRoutine will do the cleanup when the request is
1010  // completed with error status by the lower driver.
1011  //
1012  }
1013  else {
1016  FxIrp->SetInformation(0);
1018  }
1019 
1020  goto RequestIsGone;
1021  }
1022 
1023  // ------------------------------------------------------------------------
1024  //
1025  // Create a FxRequest for this IRP. By default we allocate the top most driver's request
1026  // context; then we attach the other request contexts.
1027  //
1028 
1029  //
1030  // Init the request's attributes.
1031  //
1033  //
1034  // file obj info is set, use the top most driver's info, i.e., cx if present.
1035  //
1038  ListEntry);
1039  if (fileObjInfo->ClassExtension) {
1040  attributes = fileObjInfo->CxDeviceInfo->RequestAttributes;
1041  }
1042  else {
1043  attributes = *m_Device->GetRequestAttributes();
1044  }
1045  }
1046  else {
1047  attributes = *m_Device->GetRequestAttributes();
1048  }
1049 
1050  if (m_Device->IsCxInIoPath()) {
1051  //
1052  // Apply cx's constrains for create requests:
1053  //
1056  attributes.ParentObject = NULL;
1057  }
1058 
1059  //
1060  // Create the request.
1061  //
1063  &attributes,
1064  FxIrp->GetIrp(),
1065  &pRequest);
1066  if(!NT_SUCCESS(status)) {
1068  "Could not create request for WDFDEVICE 0x%p, %!STATUS!",
1069  m_Device->GetHandle(), status);
1070  goto Error;
1071  }
1072 
1073  //
1074  // If any, attach the request's contexts of the other drivers in this chain.
1075  //
1076  for (next = m_FileObjectInfoHeadList.Blink->Blink; // skip one.
1078  next = next->Blink) {
1079 
1080  fileObjInfo = CONTAINING_RECORD(next, FxFileObjectInfo, ListEntry);
1081 
1082  if (fileObjInfo->ClassExtension) {
1083  attributes = fileObjInfo->CxDeviceInfo->RequestAttributes;
1084  }
1085  else {
1086  attributes = *m_Device->GetRequestAttributes();
1087  }
1088 
1089  //
1090  // Size is zero if driver didn't specify request's attributes.
1091  //
1092  if (0 == attributes.Size) {
1093  continue;
1094  }
1095 
1096  //
1097  // Don't need these settings for extra contexts.
1098  //
1101  attributes.ParentObject = NULL;
1102 
1104  pRequest,
1105  &attributes,
1106  TRUE,
1107  NULL);
1108 
1109  if(!NT_SUCCESS(status)) {
1112  "Couldn't allocate request context for "
1113  "device 0x%p - driver 0x%p, %!STATUS!",
1114  m_Device->GetHandle(),
1115  m_Device->GetCxDriver(fileObjInfo->CxDeviceInfo)->GetHandle(),
1116  status
1117  );
1118 
1119  goto Error;
1120  }
1121  }
1122 
1123  //
1124  // Disable thread suspension beyond this point by entering critical region.
1125  //
1127  {
1128  Mx::MxEnterCriticalRegion();
1129  inCriticalRegion = TRUE;
1130  }
1131 
1132  // ------------------------------------------------------------------------
1133  //
1134  // Queue request in default queue before invoking cx or client's create callbacks.
1135  //
1138 
1139  FxRequest* outputRequest;
1140 
1142 
1143  //
1144  // Make sure we are calling FileEvents at the right IRQL level.
1145  //
1148 
1152  "WDFDEVICE 0x%p cannot handle create request at or above "
1153  "dispatch-level, fail the Irp: 0x%p, %!STATUS!",
1155 
1156  goto Error;
1157  }
1158 
1159  //
1160  // Now queue and immediately retrieve the request by FileObject.
1161  // QueueRequest will return an error if the queue is not accepting request
1162  // or the request is already cancelled. Either way, the request is completed by
1163  // the FxIoQueue.
1164  //
1166  if (!NT_SUCCESS(status)) {
1169  "Couldn't forward request to the WDFQUEUE 0x%p, %!STATUS!",
1171  goto RequestIsGone;
1172  }
1173 
1175  NULL,
1176  &outputRequest);
1177  if (!NT_SUCCESS(status)) {
1178  //
1179  // Oops, request got cancelled and completed by another thread.
1180  //
1182  status = STATUS_PENDING; // IRP was already marked pending.
1183  goto RequestIsGone;
1184  }
1185 
1186  ASSERT(outputRequest == pRequest);
1187 
1188  inDefaultQueue = TRUE;
1189  }
1190 
1191  // ------------------------------------------------------------------------
1192  //
1193  // Invoke Cx's create callbacks. Here we add the cx's file obj and request contexts.
1194  //
1196 
1197  //
1198  // Loop through all cx's file obj info.
1199  //
1202  next = next->Blink) {
1203 
1204  //
1205  // Get ready to invoke next layer cx's create.
1206  //
1207  fileObjInfo = CONTAINING_RECORD(next, FxFileObjectInfo, ListEntry);
1208 
1209  //
1210  // Do not invoke the client driver's create callback (if any). For compatibility
1211  // we need to check first the driver 'create' queue.
1212  //
1213  if (FALSE == fileObjInfo->ClassExtension) {
1214  break;
1215  }
1216 
1217  ASSERT(fileObjInfo->EvtFileCreate.Method == NULL);
1218  ASSERT(fileObjInfo->EvtCxFileCreate.Method != NULL);
1219 
1220  //
1221  // Keep track where we stopped (end, not inclusive node).
1222  // Note that we cannot do this after the Invoke b/c File Object
1223  // may be gone by the time callback returns.
1224  //
1225  if (pFxFO) {
1227  }
1228 
1229  //
1230  // Invoke knows how to handle NULL callbacks.
1231  //
1232  if (fileObjInfo->EvtCxFileCreate.Invoke(
1233  m_Device->GetHandle(),
1234  (WDFREQUEST)pRequest->GetObjectHandle(),
1235  hwdfFO)) {
1236  //
1237  // Callback claimed the request.
1238  //
1239  status = STATUS_PENDING; // IRP was already marked pending.
1240  goto RequestIsGone;
1241  }
1242  }
1243  }
1244 
1245  //-------------------------------------------------------------------------
1246  //
1247  // First check for driver configured queue. If there is one, dispatch the request
1248  // to that queue.
1249  //
1250  if (m_DriverCreatedQueue != NULL) {
1251  if (inDefaultQueue) {
1253 
1256  pRequest);
1257 
1258  if(!NT_SUCCESS(status)) {
1261  "Couldn't forward request to the WDFQUEUE 0x%p, %!STATUS!",
1263 
1265  }
1266 
1267  status = STATUS_PENDING; // IRP was already marked pending.
1268  goto RequestIsGone;
1269  }
1270  else {
1271  ASSERT(pRequest->GetRefCnt() == 1);
1272  //
1273  // QueueRequest will return an error if the queue is not accepting request
1274  // or the request is already cancelled. Either way, the request is completed by
1275  // the FxIoQueue.
1276  //
1278  if(!NT_SUCCESS(status)) {
1281  "Couldn't forward request to the WDFQUEUE 0x%p, %!STATUS!",
1283  }
1284 
1285  goto RequestIsGone;
1286  }
1287  }
1288 
1289  //-------------------------------------------------------------------------
1290  //
1291  // At this point invoke the client driver callback if present.
1292  //
1295  ASSERT(TRUE == inDefaultQueue);
1296  ASSERT(fileObjInfo->EvtFileCreate.Method != NULL);
1297  ASSERT(fileObjInfo->EvtCxFileCreate.Method == NULL);
1298 
1299  //
1300  // Invoke the client driver create requests.
1301  //
1302  fileObjInfo->EvtFileCreate.Invoke(
1303  m_Device->GetHandle(),
1304  (WDFREQUEST)pRequest->GetObjectHandle(),
1305  hwdfFO);
1306  //
1307  // QueueRequest has already marked the request pending.
1308  //
1310  goto RequestIsGone;
1311  }
1312 
1313  //
1314  // We should be here only if CX's create returned 'continue' but client didn't have
1315  // a create callback.
1316  //
1318 
1319  //
1320  // Check to see if the driver has opted to autoforward cleanup and close.
1321  // If so, we should forward create requests to lower drivers. Else, we should
1322  // complete the request with STATUS_SUCCESS. Note, if the driver is
1323  // a filter driver, the default value of m_AutoForwardCleanupClose is TRUE.
1324  //
1327  //
1328  // _CreateCompletionRoutine2 will complete the WDF request.
1329  //
1330  }
1331  else {
1333  }
1334 
1335  //
1336  // Done processing this request.
1337  //
1338  status = STATUS_PENDING; // IRP was already marked pending.
1339  goto RequestIsGone;
1340 
1341 Error:
1342  if (pRequest != NULL) {
1344  pRequest = NULL;
1345  }
1346 
1348 
1349  if (pFxFO != NULL) {
1351  pFxFO = NULL;
1352  }
1353 
1354  //
1355  // NOTE: after this call, this object may have been deleted!
1356  //
1358 
1360  FxIrp->SetInformation(0);
1362 
1363  // fallthrough
1364 
1365 RequestIsGone:
1366 
1367  //
1368  // We have lost the ownership of the request. We have either successfully
1369  // presented the request to the driver or the queue function we called to
1370  // present the request returned error but completed the FxRequest on its own.
1371  // Either way we don't need to worry about cleaning up the resources
1372  // (fileobject, handle-count, etc) because the FxRequest:Completion routine
1373  // will call FxPkgGeneral::CreateCompleted to post process IRP upon completion.
1374  //
1375  if (inCriticalRegion) {
1376  Mx::MxLeaveCriticalRegion();
1377  }
1378 
1379  return status;
1380 }
1381 
1383 NTSTATUS
1385  __in FxIrp* Irp,
1388  )
1389 {
1390  NTSTATUS status;
1391 
1392  Irp->CopyCurrentIrpStackLocationToNext();
1393  Irp->SetCompletionRoutineEx(m_Device->GetDeviceObject(),
1395  Context);
1396  status = Irp->CallDriver(m_Device->GetAttachedDevice());
1397 
1398  return status;
1399 }
1400 
1401 VOID
1403  __in FxIrp *Irp
1404  )
1405 /*++
1406 
1407 Routine Description:
1408 
1409  This method is called when the WDFREQUEST for Irp
1410  is completed either by the driver or framework.
1411 
1412  Here, we check the completion status of the IRP and if
1413  it's not success, we destroy the fileobject and decrement
1414  the openhandle count on the device.
1415 
1416 Arguments:
1417 
1418 Return Value:
1419 
1420  VOID
1421 
1422  --*/
1423 {
1424  NTSTATUS status = Irp->GetStatus();
1425 
1426  //
1427  // If the create is completed with error status,
1428  // we destroy the WDFFILEOBJECT since the IoMgr will destroy
1429  // the PFILE_OBJECT if the IRP_MJ_CREATE fails and wouldn't send
1430  // Cleanup or Close IRP.
1431  //
1432  if (!NT_SUCCESS(status)) {
1433 
1434  // Now destroy the WDFFILEOBJECT
1436  m_Device,
1438  Irp->GetFileObject()
1439  );
1440 
1442  }
1443 }
1444 
1446 NTSTATUS
1447 STDCALL
1452  )
1453 /*++
1454 
1455 Routine Description:
1456 
1457  This completion routine is set only when the IRP is forwarded
1458  directly by the framework to the lower driver. Framework forwards
1459  the IRP request if:
1460  1) The driver happens to be a filter and hasn't registered any
1461  callbacks to handle create request.
1462  2) The driver is not a filter but has explicitly requested the
1463  framework to autoforward create/cleanup/close requests down.
1464 
1465  We need to intercept the create in the completion path to find
1466  out whether the lower driver has succeeded or failed the request.
1467  If the request is failed, we should inform the package so that
1468  it can cleanup the state because I/O manager wouldn't send
1469  cleanup & close requests if the create is failed.
1470 
1471 Arguments:
1472 
1473 Return Value:
1474 
1475  NTSTATUS
1476 
1477  --*/
1478 {
1479  FxPkgGeneral* pFxPkgGeneral;
1481 
1483 
1484  pFxPkgGeneral = (FxPkgGeneral*) Context;
1485 
1486  ASSERT(pFxPkgGeneral != NULL);
1487 
1488  //
1489  // Let the package know that create is completed
1490  // so that it can cleanup the state.
1491  //
1492  pFxPkgGeneral->CreateCompleted(&irp);
1493 
1494  //
1495  // Let the irp continue on its way.
1496  //
1498 
1499  return irp.GetStatus();
1500 }
1501 
1503 NTSTATUS
1504 STDCALL
1509  )
1510 /*++
1511 
1512 Routine Description:
1513 
1514  Routine Description:
1515 
1516  This completion routine is set only when the create request is forwarded by the
1517  framework to the lower driver. Framework forwards the create request using this
1518  completion routine if:
1519 
1520  1) Class extension's create callback is set by did not claim the request.
1521  2) Client driver did not register for a create callback or a create queue.
1522 
1523 Arguments:
1524 
1525 Return Value:
1526 
1527  STATUS_MORE_PROCESSING_REQUIRED
1528 
1529  --*/
1530 {
1531  FxRequest* request;
1533 
1535 
1536  request = (FxRequest*) Context;
1537 
1538  ASSERT(request != NULL);
1539 
1541 
1542  request->Complete(irp.GetStatus());
1543 
1545 }
1546 
1548 NTSTATUS
1551  )
1552 /*++
1553 
1554 Routine Description:
1555 
1556  Called in response to IRP_MJ_CLEANUP. This means an handle to
1557  the device is closed. After invoking the driver registered callback
1558  event, flush all the queues to cancel requests that belong to the
1559  file handle being closed. There is however a possibility for
1560  new requests to come in with the same fileobject.
1561 
1562 
1563 
1564 
1565 
1566 Arguments:
1567 
1568 Return Value:
1569 
1570  NTSTATUS
1571 
1572  --*/
1573 {
1574  NTSTATUS status;
1575  FxFileObject* pFxFO = NULL;
1576  WDFFILEOBJECT hwdfFO = NULL;
1577  PLIST_ENTRY next;
1578  FxFileObjectInfo* fileObjInfo;
1579  MxFileObject fileObject;
1580 
1581 
1582 
1583 
1584 
1585 
1586  //
1587  // Check to see if the fileobject represents a stream fileobject
1588  // created using IoCreateStreamFileObjectLite.
1589  //
1590  fileObject.SetFileObject(FxIrp->GetFileObject());
1591  if (FxIrp->GetFileObject() &&
1592  (fileObject.GetFlags() & FO_STREAM_FILE)){
1594  goto Passthru;
1595  }
1596 
1598  m_Device,
1600  FxIrp->GetFileObject(),
1601  &pFxFO
1602  );
1603 
1605 
1606  if (pFxFO != NULL && NT_SUCCESS(status)) {
1607  hwdfFO = pFxFO->GetHandle();
1608  }
1609 
1610  //
1611  // Invoke cleanup callbacks.
1612  //
1613  if (NULL == pFxFO) {
1614  //
1615  // Invoke cleanup callbacks of next layer (cx or client driver) based on the
1616  // autoforward setting of previous layer. (top to bottom).
1617  // AutoforwardCleanupClose set to FALSE with a not null create callback
1618  // means that create request was never forwarded to lower layer.
1619  //
1622  next = next->Blink) {
1623 
1624  fileObjInfo = CONTAINING_RECORD(next, FxFileObjectInfo, ListEntry);
1625 
1626  if (WdfFalse == fileObjInfo->AutoForwardCleanupClose &&
1627  fileObjInfo->EvtCxFileCreate.Method != NULL) {
1628  next = next->Blink; // one before the real start entry.
1629  break;
1630  }
1631  }
1632  }
1633  else {
1634  //
1635  // 'OnCreate' sets this package context.
1636  //
1638  if (NULL == next) {
1640  }
1641  }
1642 
1643  //
1644  // Invoke cleanup callbacks only if this layer (cx or client driver) had the
1645  // opprtunity to see the create request.
1646  //
1647  for (next = next->Flink;
1649  next = next->Flink) {
1650 
1651  fileObjInfo = CONTAINING_RECORD(next, FxFileObjectInfo, ListEntry);
1652  fileObjInfo->EvtFileCleanup.Invoke(hwdfFO);
1653  }
1654 
1655  //
1656  // hwdfFO could be NULL depending on the FileObjectClass
1657  //
1658 
1659  //
1660  // Scan all the I/O queues associated with this device
1661  // and cancel the requests that matches with the handle
1662  // being closed. We will be able to cancel only requests that
1663  // are waiting to be dispatched. If the requests are already
1664  // presented to the driver then it's the responsibility of the
1665  // driver to complete them when the cleanup callback is invoked.
1666  //
1667  if(FxIrp->GetFileObject() != NULL ) {
1668  FxPkgIo* pPkgIo;
1669 
1672  }
1673 
1674 Passthru:
1678  } else {
1680  FxIrp->SetInformation(0);
1682  }
1683 
1684  return status;
1685 
1686 }
1687 
1689 NTSTATUS
1692  )
1693 /*++
1694 
1695 Routine Description:
1696 
1697  Called in response to IRP_MJ_CLOSE. Invoke EvtFileClose event
1698  if registered and destroy the WDFFILEOBJECT.
1699 
1700 Arguments:
1701 
1702 Return Value:
1703 
1704  NTSTATUS
1705 
1706  --*/
1707 {
1708  NTSTATUS status;
1709  FxFileObject* pFxFO = NULL;
1710  WDFFILEOBJECT hwdfFO = NULL;
1711  BOOLEAN isStreamFileObject = FALSE;
1712  BOOLEAN acquiredRemLock = FALSE;
1713  PLIST_ENTRY next;
1714  FxFileObjectInfo* fileObjInfo;
1715  MxFileObject fileObject;
1716  MdIrp irp;
1717 
1718  //
1719  // FxIrp.CompleteRequest NULLs the m_Irp so store m_Irp separately
1720  // for use in ReleaseRemoveLock.
1721  //
1722  irp = FxIrp->GetIrp();
1723 
1724  //
1725  // Check to see if the fileobject represents a stream fileobject
1726  // created using IoCreateStreamFileObjectLite. If so, this is a
1727  // is spurious close sent by the I/O manager when it invalidates
1728  // the volumes (IopInvalidateVolumesForDevice).
1729  //
1730  fileObject.SetFileObject(FxIrp->GetFileObject());
1731  if (FxIrp->GetFileObject() &&
1732  (fileObject.GetFlags() & FO_STREAM_FILE)){
1733  isStreamFileObject = TRUE;
1735  goto Passthru;
1736  }
1737 
1739  m_Device,
1741  FxIrp->GetFileObject(),
1742  &pFxFO
1743  );
1744 
1746 
1747  if (pFxFO != NULL && NT_SUCCESS(status)) {
1748  hwdfFO = pFxFO->GetHandle();
1749  }
1750 
1751  //
1752  // Invoke close callbacks.
1753  //
1754  if (NULL == pFxFO) {
1755  //
1756  // Invoke close callbacks of next layer (cx or client driver) based on the autoforward
1757  // setting of previous layer. (top to bottom).
1758  // AutoforwardCleanupClose set to FALSE with a not null create callback
1759  // means that create request was never forwarded to lower layer.
1760  //
1763  next = next->Blink) {
1764 
1765  fileObjInfo = CONTAINING_RECORD(next, FxFileObjectInfo, ListEntry);
1766 
1767  if (WdfFalse == fileObjInfo->AutoForwardCleanupClose &&
1768  fileObjInfo->EvtCxFileCreate.Method != NULL) {
1769  next = next->Blink; // one before the real start entry.
1770  break;
1771  }
1772  }
1773  }
1774  else {
1775  //
1776  // 'OnCreate' sets this package context.
1777  //
1779  if (NULL == next) {
1781  }
1782  }
1783 
1784  //
1785  // Invoke close callbacks only if this layer (cx or client driver) had the opprtunity
1786  // to see the create request.
1787  //
1788  for (next = next->Flink;
1790  next = next->Flink) {
1791 
1792  fileObjInfo = CONTAINING_RECORD(next, FxFileObjectInfo, ListEntry);
1793  fileObjInfo->EvtFileClose.Invoke(hwdfFO);
1794  }
1795 
1796  //
1797  // Destroy the WDFFILEOBJECT. This will result in
1798  // fileobject EvtCleanup and EvtDestroy event.
1799  //
1801  m_Device,
1803  FxIrp->GetFileObject()
1804  );
1805 
1806 Passthru:
1807 
1811  } else {
1812  //
1813  // We're about to complete the request, but we need to decrement the
1814  // open handle count after we complete the request. However, completing
1815  // the request immediately opens the gate for the remove IRP to arrive
1816  // and run down the device. Hence we'll acquire the remove lock in order
1817  // to ensure that the device is not removed before we've decremented the
1818  // open handle count.
1819  //
1820 #if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
1821  acquiredRemLock = AcquireRemoveLockForClose(FxIrp);
1822 #endif
1824  FxIrp->SetInformation(0);
1826  }
1827 
1828  if (isStreamFileObject == FALSE) {
1829  //
1830  // Note that after this call returns, this object may have been deleted!
1831 
1832 
1833 
1834 
1835 
1836 
1837 
1838 
1840  }
1841 
1842  if (acquiredRemLock) {
1844  irp);
1845  }
1846 
1847  return status;
1848 
1849 }
1850 
1851 BOOLEAN
1853  __in FxIrp* FxIrp
1854  )
1855 /*++
1856 
1857 Routine Description:
1858 
1859  For PNP devices, this routine acquires the remove lock when handling the
1860  close IRP.
1861 
1862 Arguments:
1863  Irp - Pointer to the close IRP
1864 
1865 Return Value:
1866 
1867  A BOOLEAN value that indicates whether or not the function actually acquired
1868  the remove lock
1869 
1870  --*/
1871 {
1872  NTSTATUS status;
1873  BOOLEAN lockAcquired;
1876 
1877  //
1878  // Initialization
1879  //
1880  lockAcquired = FALSE;
1881 
1882  //
1883  // We attempt to acquire the remove lock only for PNP device objects
1884  //
1885  if (m_Device->IsPnp() == FALSE) {
1886  goto Done;
1887  }
1888 
1889  //
1890  // If driver has opted in for remove lock for I/O operations we have
1891  // already acquired remove lock for Close so no need to do it again.
1892  //
1893  if (wdmExtension->RemoveLockOptionFlags &
1895  goto Done;
1896  }
1897 
1900  FxIrp->GetIrp());
1901  if (NT_SUCCESS(status)) {
1902  //
1903  // Successfully acquired the remove lock
1904  //
1905  lockAcquired = TRUE;
1906  } else {
1907  //
1908  // This is likely to have failed because we got the remove IRP and
1909  // called IoReleaseRemoveLockAndWait on another thread. This would
1910  // happen if there's a bug in the driver above us in the stack that
1911  // caused it to forward us the remove IRP before we completed the close
1912  // IRP.
1913  //
1914  // There's not much we can do now, since we're already racing against
1915  // the remove IRP.
1916  //
1918 
1920 
1924  TRACINGIO,
1925  "Unable to acquire remove lock while handling the close IRP"
1926  " 0x%p, %!STATUS!",
1927  FxIrp->GetIrp(), status);
1928 
1931  }
1932  }
1933 
1934 Done:
1935  return lockAcquired;
1936 }
1937 
1938 
1940 NTSTATUS
1943  )
1944 /*++
1945 
1946 Routine Description:
1947 
1948  Called in response to IRP_MJ_SHUTDOWN.
1949 
1950 Arguments:
1951 
1952 Return Value:
1953 
1954  NTSTATUS
1955 
1956  --*/
1957 {
1958  NTSTATUS status;
1959 
1961 
1962  if(m_Device->IsFilter()) {
1965  }
1966  else {
1969  FxIrp->SetInformation(0);
1971  }
1972 
1973  return status;
1974 
1975 }
1976 
1977 VOID
1979  VOID
1980  )
1981 {
1984  }
1985 }
1986 
1987 BOOLEAN
1989  VOID
1990  )
1991 {
1992  //
1993  // Remove the bias of one that we use to track if a control device should be
1994  // deleted.
1995  //
1997  return TRUE;
1998  }
1999  else {
2000  return FALSE;
2001  }
2002 
2003 }
2004 
2005 VOID
2007  __out_opt WDF_EXECUTION_LEVEL* ExecutionLevel,
2008  __out_opt WDF_SYNCHRONIZATION_SCOPE* SynchronizationScope
2009  )
2010 /*++
2011 
2012 Routine Description:
2013  This routine is the helper routine and is used by FxFileObject to get the
2014  ExecutionLevel and SynchronizationScope.
2015 
2016 Arguments:
2017 
2018 Return Value:
2019  VOID
2020 
2021 --*/
2022 
2023 {
2024  if (ExecutionLevel != NULL) {
2025  *ExecutionLevel = m_ExecutionLevel;
2026  }
2027 
2028  if (SynchronizationScope != NULL) {
2029  *SynchronizationScope = m_SynchronizationScope;
2030  }
2031 }
2032 
2036  )
2037 /*++
2038 
2039 Routine Description:
2040  This routine is the helper routine and is used by FxFileObject to get the
2041  LockObject.
2042 
2043 
2044 Arguments:
2045 
2046 Return Value:
2047  FxCallbackLock *
2048 
2049 --*/
2050 
2051 {
2052  if (LockObject != NULL) {
2054  }
2055 
2056  return m_CallbackLockPtr;
2057 }
2058 
2059 
struct _LIST_ENTRY * PLIST_ENTRY
static __inline NTSTATUS MxAcquireRemoveLock(__in MdRemoveLock RemoveLock, __in_opt PVOID Tag)
Definition: mxgeneralkm.h:268
__drv_restoresIRQL KIRQL __in BOOLEAN Unlock
Definition: fxobject.hpp:1474
CfxDevice * m_Device
Definition: fxobject.hpp:329
FxFileObjectFileClose EvtFileClose
VOID Invoke(__in WDFDEVICE Device)
FxFileObjectFileCleanup EvtFileCleanup
static _Must_inspect_result_ NTSTATUS _CreateFileObject(__in FxDevice *pDevice, __in MdIrp Irp, __in WDF_FILEOBJECT_CLASS FileObjectClass, __in_opt PWDF_OBJECT_ATTRIBUTES pObjectAttributes, __in_opt MdFileObject pWdmFileObject, __deref_out_opt FxFileObject **ppFxFileObject)
return STATUS_NOT_SUPPORTED
MdFileObject GetFileObject(VOID)
Definition: fxirpum.cpp:1460
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define FX_PKG_GENERAL_FLAG_CX_INFO
MdRemoveLock GetRemoveLock(VOID)
Definition: fxdevicekm.hpp:47
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
__inline NTSTATUS Complete(__in NTSTATUS Status)
Definition: fxrequest.hpp:770
MdDeviceObject __inline GetDeviceObject(VOID)
Definition: fxdevice.hpp:174
VOID SetStatus(__in NTSTATUS Status)
Definition: fxirpum.cpp:457
BOOLEAN Invoke(__in WDFDEVICE Device, __in WDFREQUEST Request, __in_opt WDFFILEOBJECT FileObject)
FxCxDeviceInfo * CxDeviceInfo
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
ULONG GetFlags(VOID)
#define IRP_MJ_SHUTDOWN
#define __in_opt
Definition: dbghelp.h:38
__inline VOID SetFileObject(_In_ MdFileObject FileObject)
Definition: mxfileobject.h:36
#define TRUE
Definition: types.h:120
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
PFN_WDFCX_DEVICE_FILE_CREATE Method
WDFDEVICE __inline GetHandle(VOID)
Definition: fxdevice.hpp:237
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
GLuint GLuint GLsizei count
Definition: gl.h:1545
_Must_inspect_result_ NTSTATUS ForwardRequest(__in FxIoQueue *pDestQueue, __in FxRequest *pRequest)
Definition: fxioqueue.cpp:1712
void Invoke(__in_opt WDFFILEOBJECT FileObject)
LONG NTSTATUS
Definition: precomp.h:26
__inline BOOLEAN IsPnp(VOID)
Definition: fxdevice.hpp:1200
_Must_inspect_result_ NTSTATUS PostCreateDeviceInitialize(__in PWDFDEVICE_INIT Init)
_Must_inspect_result_ NTSTATUS Initialize(__in PWDFDEVICE_INIT DeviceInit)
FxRequest * pRequest
FxIoQueue * m_DriverCreatedQueue
Definition: fxirp.hpp:28
WDFCX_FILEOBJECT_CONFIG Callbacks
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
FxFileObjectFileCreate EvtFileCreate
static _Must_inspect_result_ NTSTATUS _CreateForPackage(__in CfxDevice *Device, __in PWDF_OBJECT_ATTRIBUTES RequestAttributes, __in MdIrp Irp, __deref_out FxRequest **Request)
Definition: fxrequest.cpp:75
KIRQL irql
Definition: wave.h:1
PFILE_OBJECT MdFileObject
Definition: mxgeneralkm.h:32
CxFileObjectInit FileObject
#define InsertTailList(ListHead, Entry)
__inline BOOLEAN IsLegacy(VOID)
Definition: fxdevice.hpp:1209
#define TRACE_LEVEL_INFORMATION
Definition: storswtr.h:29
_Must_inspect_result_ NTSTATUS QueueRequest(__in FxRequest *pRequest)
Definition: fxioqueue.cpp:2245
FxFileObject * pFxFO
_Must_inspect_result_ NTSTATUS ForwardCreateRequest(__in FxIrp *FxIrp, __in MdCompletionRoutine CompletionRoutine, __in PVOID Context)
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
VOID CreateCompleted(__in FxIrp *Irp)
PFN_WDF_DEVICE_SHUTDOWN_NOTIFICATION m_Method
LONG m_OpenHandleCount
VOID PropagatePendingReturned(VOID)
Definition: fxirpum.cpp:443
WDF_EXECUTION_LEVEL ExecutionLevel
Definition: wdfobject.h:120
FxDriver * Driver
UCHAR KIRQL
Definition: env_spec_w32.h:591
FxRequest * request
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
#define __out_opt
Definition: dbghelp.h:65
FxPkgGeneral(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in CfxDevice *Device)
PFN_WDFCX_DEVICE_FILE_CREATE EvtCxDeviceFileCreate
Definition: wdfcx.h:28
#define FALSE
Definition: types.h:117
_In_ PIRP Irp
Definition: csq.h:116
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
VOID Invoke(__in WDFDEVICE Device, __in WDFREQUEST Request, __in_opt WDFFILEOBJECT FileObject)
long LONG
Definition: pedump.c:60
_Must_inspect_result_ NTSTATUS GetRequest(__in_opt MdFileObject FileObject, __in_opt FxRequest *TagRequest, __deref_out FxRequest **pOutRequest)
Definition: fxioqueue.cpp:962
#define FX_PKG_GENERAL_FLAG_CLIENT_CREATE
enum _WDF_FILEOBJECT_CLASS WDF_FILEOBJECT_CLASS
PVOID __inline GetObjectHandle(VOID)
Definition: fxobject.hpp:603
__inline WDF_FILEOBJECT_CLASS GetFileObjectClass(VOID)
Definition: fxdevice.hpp:1123
_Must_inspect_result_ NTSTATUS OnCleanup(__inout FxIrp *FxIrp)
FxCxDeviceInfo * CxDeviceInfo
VOID SkipCurrentIrpStackLocation(VOID)
Definition: fxirpum.cpp:400
unsigned char BOOLEAN
FxCxFileObjectFileCreate EvtCxFileCreate
VOID ControlDeviceDelete(VOID)
Definition: fxdevice.hpp:1465
_Must_inspect_result_ BOOLEAN IsVersionGreaterThanOrEqualTo(__in ULONG Major, __in ULONG Minor)
Definition: globalskm.cpp:92
NTSTATUS CallDriver(__in MdDeviceObject DeviceObject)
Definition: fxirpum.cpp:36
MdDeviceObject __inline GetAttachedDevice(VOID)
Definition: fxdevice.hpp:210
WDF_FILEOBJECT_CLASS FileObjectClass
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
IWudfIrp * MdIrp
Definition: mxum.h:103
#define FX_PKG_GENERAL_FLAG_CLIENT_INFO
PFN_WDF_DEVICE_FILE_CREATE Method
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
static MdCompletionRoutineType _CreateCompletionRoutine2
_Must_inspect_result_ NTSTATUS ConfigureForwarding(__in FxIoQueue *FxQueue)
PFN_WDF_FILE_CLOSE EvtFileClose
Definition: wdfcx.h:33
VOID MarkPassiveCallbacks(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:972
_Must_inspect_result_ NTSTATUS OnClose(__inout FxIrp *FxIrp)
WDF_TRI_STATE AutoForwardCleanupClose
FxDevice * pDevice
__inline PVOID GetPkgCleanupCloseContext(VOID)
enum _WDF_SYNCHRONIZATION_SCOPE WDF_SYNCHRONIZATION_SCOPE
__inline WDFDRIVER GetHandle(VOID)
Definition: fxdriver.hpp:202
FxIoQueue * m_DefaultQueueForCreates
#define TRACINGDEVICE
Definition: dbgtrace.h:58
__inline FxDriver * GetCxDriver(__in FxCxDeviceInfo *CxDeviceInfo)
Definition: fxdevice.hpp:1654
PFX_DRIVER_GLOBALS pFxDriverGlobals
BOOLEAN __inline FxIsFileObjectOptional(__in WDF_FILEOBJECT_CLASS FileObjectClass)
Definition: fxdevice.hpp:112
#define STDCALL
Definition: wdf.h:45
#define ASSERT(a)
Definition: mode.c:44
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
__inline VOID SetFileObjectClass(__in WDF_FILEOBJECT_CLASS FileObjectClass)
Definition: fxdevice.hpp:1135
__inline BOOLEAN IsFilter()
Definition: fxdevice.hpp:1408
VOID CompleteRequest(__in_opt CCHAR PriorityBoost=IO_NO_INCREMENT)
Definition: fxirpum.cpp:24
BOOLEAN m_AutoForwardCleanupClose
Definition: fxdevice.hpp:605
_Must_inspect_result_ NTSTATUS FxObjectAllocateContext(__in FxObject *Object, __in PWDF_OBJECT_ATTRIBUTES Attributes, __in BOOLEAN AllowCallbacksOnly, __deref_opt_out PVOID *Context)
Definition: handleapi.cpp:397
VOID SetInformation(__in ULONG_PTR Information)
Definition: fxirpum.cpp:504
NTSTATUS NTAPI IoRegisterLastChanceShutdownNotification(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1663
VOID NTAPI IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1725
BOOL Error
Definition: chkdsk.c:66
_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 STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
static _Must_inspect_result_ NTSTATUS _GetFileObjectFromWdm(__in FxDevice *pDevice, __in WDF_FILEOBJECT_CLASS FileObjectClass, __in_opt MdFileObject pWdmFileObject, __deref_out_opt FxFileObject **ppFxFileObject)
void Invoke(__in_opt WDFFILEOBJECT FileObject)
struct _test_info info[]
Definition: SetCursorPos.c:19
void SetCallbackLockPtr(FxCallbackLock *Lock)
Definition: fxcallback.hpp:105
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
#define InterlockedDecrement
Definition: armddk.h:52
FxCallbackLock * GetCallbackLockPtrHelper(__deref_out_opt FxObject **LockObject)
FxCallbackLock * m_CallbackLockPtr
FxPkgIo * m_PkgIo
Definition: fxdevice.hpp:669
LIST_ENTRY m_FileObjectInfoHeadList
FxObject * m_CallbackLockObjectPtr
#define __inout
Definition: dbghelp.h:50
Definition: typedefs.h:119
_In_ PTRANSFER_PACKET _In_ ULONG _In_ PIRP OriginalIrp
Definition: classp.h:1757
#define FX_PKG_GENERAL_FLAG_CREATE
#define _Must_inspect_result_
Definition: ms_sal.h:558
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_Must_inspect_result_ NTSTATUS ConfigureConstraints(__in PLIST_ENTRY FileObjInfoList)
_Must_inspect_result_ NTSTATUS OnCreate(__inout FxIrp *FxIrp)
static VOID _DestroyFileObject(__in FxDevice *pDevice, __in WDF_FILEOBJECT_CLASS FileObjectClass, __in_opt MdFileObject pWdmFileObject)
FxPkgIo * pPkgIo
#define FX_PKG_GENERAL_FLAG_CX_CREATE
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
WDF_TRI_STATE AutoForwardCleanupClose
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
static FxWdmDeviceExtension * _GetFxWdmExtension(__in MdDeviceObject DeviceObject)
Definition: fxdevicekm.hpp:30
FORCEINLINE VOID WDF_OBJECT_ATTRIBUTES_INIT(_Out_ PWDF_OBJECT_ATTRIBUTES Attributes)
Definition: wdfobject.h:147
static __inline VOID MxReleaseRemoveLock(__in MdRemoveLock RemoveLock, __in PVOID Tag)
Definition: mxgeneralkm.h:278
LONG GetRefCnt(VOID)
Definition: fxobject.hpp:758
__inline BOOLEAN IsCxInIoPath(VOID)
Definition: fxdevice.hpp:1594
WDF_SYNCHRONIZATION_SCOPE m_SynchronizationScope
static unsigned __int64 next
Definition: rand_nt.c:6
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
#define InterlockedIncrement
Definition: armddk.h:53
_Must_inspect_result_ NTSTATUS CreateQueue(__in PWDF_IO_QUEUE_CONFIG Config, __in PWDF_OBJECT_ATTRIBUTES QueueAttributes, __in_opt FxDriver *Caller, __deref_out FxIoQueue **ppQueue)
Definition: fxpkgio.cpp:981
WDF_TRI_STATE PowerManaged
Definition: wdfio.h:393
MdIrp GetIrp(VOID)
Definition: fxirpum.cpp:15
_Must_inspect_result_ NTSTATUS FlushAllQueuesByFileObject(__in MdFileObject FileObject)
Definition: fxpkgio.cpp:1393
_Must_inspect_result_ NTSTATUS OnShutdown(__inout FxIrp *FxIrp)
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
FxCallbackLock * GetCallbackLockPtr(__out_opt FxObject **LockObject)
PFX_DRIVER_GLOBALS fxDriverGlobals
WDF_OBJECT_ATTRIBUTES RequestAttributes
_In_ WDFREQUEST _In_opt_ PFN_WDF_REQUEST_COMPLETION_ROUTINE CompletionRoutine
Definition: wdfrequest.h:893
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
WDFOBJECT ParentObject
Definition: wdfobject.h:130
FxShutDown m_EvtDeviceShutdown
static MdCompletionRoutineType _CreateCompletionRoutine
__inline WDFFILEOBJECT GetHandle(VOID)
ULONG RemoveLockOptionFlags
Definition: fxdevice.hpp:38
FxIrp fxIrp(Irp)
#define NULL
Definition: types.h:112
Definition: tftpd.h:85
#define __deref_out_opt
Definition: dbghelp.h:29
NTSTATUS NTAPI IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1694
virtual _Must_inspect_result_ NTSTATUS Dispatch(__inout MdIrp Irp)
VOID DeleteFromFailedCreate(VOID)
Definition: fxobject.cpp:391
#define IRP_MJ_CLEANUP
WUDF_IO_COMPLETION_ROUTINE * MdCompletionRoutine
Definition: mxum.h:142
struct tagContext Context
Definition: acpixf.h:1034
FX_TRACK_DRIVER(fxDriverGlobals)
VOID GetConstraints(__out_opt WDF_EXECUTION_LEVEL *ExecutionLevel, __out_opt WDF_SYNCHRONIZATION_SCOPE *SynchronizationScope)
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFWAITLOCK * Lock
Definition: wdfsync.h:124
__inline PWDF_OBJECT_ATTRIBUTES GetRequestAttributes(VOID)
Definition: fxdevice.hpp:1315
VOID DeleteFileObjectFromFailedCreate(VOID)
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
WDF_EXTERN_C_START enum _WDF_EXECUTION_LEVEL WDF_EXECUTION_LEVEL
FORCEINLINE VOID WDF_IO_QUEUE_CONFIG_INIT(_Out_ PWDF_IO_QUEUE_CONFIG Config, _In_ WDF_IO_QUEUE_DISPATCH_TYPE DispatchType)
Definition: wdfio.h:426
WDF_SYNCHRONIZATION_SCOPE SynchronizationScope
Definition: wdfobject.h:125
_In_ PWDFDEVICE_INIT DeviceInit
Definition: wdfcontrol.h:113
_Must_inspect_result_ NTSTATUS ConfigureFileObjectClass(__in PLIST_ENTRY FileObjInfoList)
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACINGIO
Definition: dbgtrace.h:66
__inline BOOLEAN IsExclusive(VOID)
Definition: fxdevice.hpp:1218
UCHAR GetMajorFunction(VOID)
Definition: fxirpum.cpp:217
VOID GetConstraintsHelper(__out_opt WDF_EXECUTION_LEVEL *ExecutionLevel, __out_opt WDF_SYNCHRONIZATION_SCOPE *SynchronizationScope)
WDF_FILEOBJECT_CLASS Class
#define __in
Definition: dbghelp.h:35
static SERVICE_STATUS status
Definition: service.c:31
BOOLEAN CanDestroyControlDevice(VOID)
#define APC_LEVEL
Definition: env_spec_w32.h:695
WDF_OBJECT_ATTRIBUTES Attributes
BOOLEAN AcquireRemoveLockForClose(__inout FxIrp *FxIrp)
FxIrp * irp
__inline VOID SetPkgCleanupCloseContext(PVOID Context)
VOID DecrementOpenHandleCount(VOID)
#define FO_STREAM_FILE
Definition: iotypes.h:1783
FxVerifierDbgBreakPoint(pFxDriverGlobals)
WDF_OBJECT_ATTRIBUTES Attributes
WDF_EXECUTION_LEVEL m_ExecutionLevel
NTSTATUS GetStatus()
Definition: fxirpum.cpp:466
Definition: ps.c:97
#define LockObject(Object)
Definition: titypes.h:34
PFN_WDF_FILE_CLEANUP EvtFileCleanup
Definition: wdfcx.h:38