ReactOS  0.4.15-dev-3182-g7b62228
fxfileobject.cpp
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7  FxFileObject.hpp
8 
9 Abstract:
10 
11  This module implements a frameworks managed FileObject
12 
13 Author:
14 
15 
16 
17 Environment:
18 
19  Both kernel and user mode
20 
21 Revision History:
22 
23 
24 --*/
25 
26 #include "coreprivshared.hpp"
27 
28 // Tracing support
29 extern "C" {
30 // #include "FxFileObject.tmh"
31 }
32 
33 //
34 // Public constructors
35 //
36 
37 
39  __in PFX_DRIVER_GLOBALS FxDriverGlobals,
40  __in MdFileObject pWdmFileObject,
42  ) :
44 {
45  m_FileObject.SetFileObject(pWdmFileObject);
47  m_Device = pDevice;
48 
49 #if (FX_CORE_MODE == FX_CORE_USER_MODE)
52 #endif
53 
54  //
55  // Cannot be deleted by the device driver
56  //
58 }
59 
61 {
62 #if (FX_CORE_MODE == FX_CORE_USER_MODE)
64 #endif
65 }
66 
67 //
68 // Create the WDFFILEOBJECT and associate it with the WDM PFILE_OBJECT.
69 //
74  __in MdIrp Irp,
75  __in WDF_FILEOBJECT_CLASS FileObjectClass,
76  __in_opt PWDF_OBJECT_ATTRIBUTES pObjectAttributes,
77  __in_opt MdFileObject pWdmFileObject,
78  __deref_out_opt FxFileObject** pFileObject
79  )
80 {
83  KIRQL irql;
85 
86  PFX_DRIVER_GLOBALS FxDriverGlobals = pDevice->GetDriverGlobals();
87 
88  //
89  // Create does require a WDM file obj based on the normalized file obj
90  // class value.
91  //
93 
94  //
95  // No FileObject support
96  //
98  if( pFileObject != NULL ) *pFileObject = NULL;
99  return STATUS_SUCCESS;
100  }
101 
102  //
103  // If fileobject support was specified, and a NULL
104  // WDM PFILE_OBJECT is supplied, then it's an error
105  //
106  if( pWdmFileObject == NULL ) {
107 
108  //
109  // Seems like some filter driver above us sending a create without fileobject.
110  // We support this only if the FileObjectClass class is set to
111  // WdfFileObjectWdfCannotUseFsContexts and device is created to be
112  // exclusive.
113  //
115  pDevice->IsExclusive() ) {
116 
117  DO_NOTHING();
118 
119  } else {
121  "WdfFileObjectWdfCanUseFsContexts is specified, but the Create "
122  "IRP %p doesn't have a fileObject\n",
123  Irp);
126  }
127 
128  }
129 
130  // Allocate a new FxFileObject with context
131  pfo = new(pDevice->GetDriverGlobals(), pObjectAttributes)
132  FxFileObject(pDevice->GetDriverGlobals(), pWdmFileObject, pDevice);
133 
134  if( pfo == NULL ) {
136  }
137 
138  pfo->Initialize(Irp);
139 
140  // Assign FxDevice as the parent for the file object
141  Status = pfo->Commit(pObjectAttributes, NULL, pDevice);
142  if( !NT_SUCCESS(Status) ) {
143  pfo->DeleteFromFailedCreate();
144  return Status;
145  }
146 
147  //
148  // Place it on the list of FxFileObject's for this FxDevice
149  //
150  pDevice->Lock(&irql);
152  pDevice->Unlock(irql);
153 
154  //
155  // Set file object context in mode-specific manner
156  //
157  pfo->SetFileObjectContext(pWdmFileObject,
159  Irp,
160  pDevice);
161 
162  // FxFileObject* to caller
163  if( pFileObject != NULL ) {
164  *pFileObject = pfo;
165  }
166 
167  return STATUS_SUCCESS;
168 }
169 
170 //
171 // Destroy (dereference) the WDFFILEOBJECT related to the
172 // WDM PFILE_OBJECT according to its FileObjectClass.
173 //
174 VOID
177  __in WDF_FILEOBJECT_CLASS FileObjectClass,
178  __in_opt MdFileObject pWdmFileObject
179  )
180 {
181  FxFileObject* pfo = NULL;
182  PFX_DRIVER_GLOBALS FxDriverGlobals = pDevice->GetDriverGlobals();
184 
185  //
186  // Close does require a WDM file obj based on the normalized file obj
187  // class value.
188  //
190 
192  return;
193  }
194 
195  //
196  // Driver has specified file object support, and we
197  // allocated one at Create, so they must pass one
198  // to close, otherwise it's an error and we will leak
199  // the file object.
200  //
201  MxFileObject wdmFileObject(pWdmFileObject);
202  if( pWdmFileObject == NULL &&
204 
205  //
206  // It's likely that IRP_MJ_CREATE had NULL for the Wdm FileObject as well.
207  //
208  // If a driver passes != NULL for Wdm FileObject to create, and NULL to
209  // this routine, a WDF FxFileObject object leak will occur, which will
210  // be reported at driver unload.
211  //
213  "PFILE_OBJECT in close IRP is NULL, *Possible Leak of FxFileObject*\n");
214 
216 
217  return;
218  }
220  pfo = (FxFileObject*)wdmFileObject.GetFsContext();
221  wdmFileObject.SetFsContext(NULL);
222 
223  }
225  pfo = (FxFileObject*)wdmFileObject.GetFsContext2();
226  wdmFileObject.SetFsContext2(NULL);
227  }
228  else {
230  //
231  // We must find the associated FxFileObject from the list
232  // on the device
233  //
235  pDevice,
237  pWdmFileObject,
238  &pfo
239  );
240 
241  //
242  // We should find it, unless a different one was passed to IRP_MJ_CLOSE
243  // than to IRP_MJ_CREATE, which is an error.
244  //
245  if (NT_SUCCESS(status) == FALSE || pfo == NULL) {
247  "Could not find WDFFILEOBJECT for PFILE_OBJECT 0x%p",
248  pWdmFileObject);
249 
251  "Did a different PFILE_OBJECT get passed to "
252  "IRP_MJ_CLOSE than did to IRP_MJ_CREATE?");
254  }
255  }
256 
257  if( pfo != NULL ) {
258  KIRQL irql;
259 
260  //
261  // Remove it from the list of FxFileObjects on the FxDevice
262  //
263  pDevice->Lock(&irql);
264  RemoveEntryList(&pfo->m_Link);
265  pDevice->Unlock(irql);
266 
267  // Delete the file object
268  pfo->DeleteObject();
269  }
270 
271  return;
272 }
273 
274 //
275 // Return the FxFileObject* for the given WDM PFILE_OBJECT
276 //
278 NTSTATUS
281  __in WDF_FILEOBJECT_CLASS FileObjectClass,
282  __in_opt MdFileObject pWdmFileObject,
283  __deref_out_opt FxFileObject** ppFxFileObject
284  )
285 {
286  FxFileObject* pfo = NULL;
287  PFX_DRIVER_GLOBALS FxDriverGlobals = pDevice->GetDriverGlobals();
289 
290  //
291  // Normalize file object class value.
292  //
294 
295  //
296  // No FileObject support
297  //
299  *ppFxFileObject = NULL;
300  return STATUS_SUCCESS;
301  }
302 
303  if( pWdmFileObject == NULL ) {
304 
305  //
306  // Warn if an I/O request has NULL for the WDM PFILE_OBJECT
307  //
308  if ( pDevice->IsExclusive() &&
310  //
311  // We allow a NULL file object iff the device is exclusive and
312  // we have to look up the WDFFILEOBJECT by PFILE_OBJECT value
313  //
314  DO_NOTHING();
315  }
316  else if ( FxIsFileObjectOptional(FileObjectClass) ) {
317  //
318  // Driver told us that it's able to handle this case.
319  //
320  *ppFxFileObject = NULL;
321  return STATUS_SUCCESS;
322  }
323  else {
325  "NULL passed for PFILE_OBJECT when FileObject "
326  "support is requested in an I/O request");
328 
329  return STATUS_UNSUCCESSFUL;
330  }
331  }
332 
333  //
334  // Depending on the drivers configuration, we can quickly
335  // get the FxFileObject* from FxContext, or FxContext2.
336  //
337  // Some drivers can not touch either of the FxContext(s), and
338  // in that case we must resort to a list or hashtable.
339  //
340  MxFileObject wdmFileObject(pWdmFileObject);
342  pfo = (FxFileObject*)wdmFileObject.GetFsContext();
343  }
345  pfo = (FxFileObject*)wdmFileObject.GetFsContext2();
346  }
347  else {
349  FxFileObject* f;
350  KIRQL irql;
351 
352  //
353  // Must look it up from the FxDevice->m_FileObjectListHead.
354  //
355  pfo = NULL;
356 
357  pDevice->Lock(&irql);
358 
360 
361  if(pWdmFileObject == NULL) {
362  //
363  // If the pWdmFileObject is NULL then we will pass the first entry
364  // in the list because the device must be exclusive and there
365  // can be only one fileobject in the list.
366  //
368 
370  pfo = f;
371 
372  } else {
373 
374  while( next != &pDevice->m_FileObjectListHead ) {
376 
377  if( f->m_FileObject.GetFileObject()== pWdmFileObject ) {
378  pfo = f;
379  break;
380  }
381 
382  next = next->Flink;
383  }
384  }
385 
386 
387 
388 
389 
390 
391 
392 
393 
394 
395  if(pfo == NULL
396  && pDevice->IsExclusive()
399 
402  pfo = f;
403 
405  "The PFILE_OBJECT 0x%p in this request (cleanup/close) "
406  "is different from the one specified in "
407  "create request 0x%p.This is bad!", pWdmFileObject,
408  ((f != NULL) ? f->m_FileObject.GetFileObject(): NULL));
410  "Since this is a serial port device, framework is "
411  "using a workaround to allow this");
412  }
413 
414  pDevice->Unlock(irql);
415  }
416 
417  //
418  // This can happen if a different PFILE_OBJECT is passed to an I/O
419  // request than was presented to IRP_MJ_CREATE
420  //
421  if (pfo == NULL && FxIsFileObjectOptional(FileObjectClass) == FALSE) {
422 
424  "Could not locate WDFFILEOBJECT for "
425  "PFILE_OBJECT 0x%p",pWdmFileObject);
426 
428  "Did a different PFILE_OBJECT get passed to the "
429  "request than was to IRP_MJ_CREATE?");
430 
431 
432 
433 
434 
435 
436 
437 
438 
439 
440  if (FxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,9)) {
442  }
443  }
444 
445  //
446  // We don't do an extra reference count since the file objects
447  // lifetime is controlled by the IoMgr. When the IRP_MJ_CLOSE
448  // occurs, the reference is released after the optional
449  // driver event callback.
450  //
451 
452  *ppFxFileObject = pfo;
453 
454  return STATUS_SUCCESS;
455 }
456 
457 VOID
459  VOID
460  )
461 {
462  KIRQL irql;
463 
464  //
465  // Remove it from the list of FxFileObjects on the FxDevice
466  //
467  m_Device->Lock(&irql);
469  m_Device->Unlock(irql);
470 
471  // Delete the file object
473 }
474 
476 NTSTATUS
479  )
480 /*++
481 
482 Routine Description:
483  This routine is used to return the pointer to the Object itself.
484 
485 Arguments:
486  Params - query interface parameters.
487 
488 Return Value:
489  NTSTATUS
490 
491 --*/
492 
493 {
494  switch (Params->Type) {
495  case FX_TYPE_FILEOBJECT:
496  *Params->Object = (FxFileObject*) this;
497  break;
498 
500  *Params->Object = (IFxHasCallbacks*) this;
501  break;
502 
503  default:
504  return FxNonPagedObject::QueryInterface(Params); // __super call
505  }
506 
507  return STATUS_SUCCESS;
508 }
509 
510 VOID
512  __in WDF_EXECUTION_LEVEL* ExecutionLevel,
513  __in WDF_SYNCHRONIZATION_SCOPE* SynchronizationScope
514  )
515 /*++
516 
517 Routine Description:
518  This routine implements the GetConstraints IfxCallback. The caller gets the
519  ExecutionLevel and the SynchronizationScope of the FileObject. The FileObject's
520  SynchronizationScope and ExecutionLevel is strored in the FxPkgGeneral object.
521 
522 Arguments:
523  ExecutionLevel - (opt) receives the execution level.
524 
525  SynchronizationScope - (opt) receives the synchronization scope.
526 
527 Return Value:
528  None
529 
530 --*/
531 
532 {
533  //
534  // Get it from FxPkgGeneral which has the File attributes passed to it at device Creation time.
535  //
536  return GetDevice()->m_PkgGeneral->GetConstraintsHelper(ExecutionLevel, SynchronizationScope);
537 }
538 
543  )
544 /*++
545 
546 Routine Description:
547  This routine implements the GetCallbackLockPtr IfxCallback. The caller gets the
548  LockObject to be used before calling the driver callbacks.
549 
550 Arguments:
551  LockObject - receives the lock object.
552 
553 Return Value:
554  FxCallbackLock *
555 
556 --*/
557 
558 {
559  //
560  // Get it from FxPkgGeneral which has the File attributes passed to it at device Creation time.
561  //
563 }
564 
565 
CfxDevice * m_Device
Definition: fxobject.hpp:329
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)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
VOID SetFsContext2(_In_ PVOID Value)
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:306
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
__inline MxDeviceObject * GetMxDeviceObject(VOID)
Definition: fxdevice.hpp:183
#define __in_opt
Definition: dbghelp.h:38
__inline VOID SetFileObject(_In_ MdFileObject FileObject)
Definition: mxfileobject.h:36
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
VOID SetFsContext(_In_ PVOID Value)
LONG NTSTATUS
Definition: precomp.h:26
KIRQL irql
Definition: wave.h:1
PFILE_OBJECT MdFileObject
Definition: mxgeneralkm.h:32
PVOID GetFsContext(VOID)
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
_Must_inspect_result_ FxCallbackLock * GetCallbackLockPtr(__deref_out_opt FxObject **LockObject)
FxFileObject * m_RelatedFileObject
UNICODE_STRING m_FileName
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
UCHAR KIRQL
Definition: env_spec_w32.h:591
FxFileObject(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in MdFileObject pWdmFileObject, __in FxDevice *Device)
#define FALSE
Definition: types.h:117
_In_ PIRP Irp
Definition: csq.h:116
#define TRACE_LEVEL_VERBOSE
Definition: storswtr.h:30
enum _WDF_FILEOBJECT_CLASS WDF_FILEOBJECT_CLASS
_Must_inspect_result_ BOOLEAN IsVersionGreaterThanOrEqualTo(__in ULONG Major, __in ULONG Minor)
Definition: globalskm.cpp:92
IWudfIrp * MdIrp
Definition: mxum.h:103
#define SAFE_RELEASE(p)
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
FxDevice * pDevice
enum _WDF_SYNCHRONIZATION_SCOPE WDF_SYNCHRONIZATION_SCOPE
LIST_ENTRY m_Link
Status
Definition: gdiplustypes.h:24
_In_opt_ FONTOBJ * pfo
Definition: winddi.h:3603
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LIST_ENTRY m_FileObjectListHead
Definition: fxdevice.hpp:643
VOID GetConstraints(__in WDF_EXECUTION_LEVEL *ExecutionLevel, __in WDF_SYNCHRONIZATION_SCOPE *SynchronizationScope)
GLfloat f
Definition: glext.h:7540
#define TRACINGDEVICE
Definition: dbgtrace.h:58
BOOLEAN __inline FxIsFileObjectOptional(__in WDF_FILEOBJECT_CLASS FileObjectClass)
Definition: fxdevice.hpp:112
#define ASSERT(a)
Definition: mode.c:44
virtual ~FxFileObject()
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
WDF_FILEOBJECT_CLASS __inline FxFileObjectClassNormalize(__in WDF_FILEOBJECT_CLASS FileObjectClass)
Definition: fxdevice.hpp:103
WDF_FILEOBJECT_CLASS normalizedFileClass
static _Must_inspect_result_ NTSTATUS _GetFileObjectFromWdm(__in FxDevice *pDevice, __in WDF_FILEOBJECT_CLASS FileObjectClass, __in_opt MdFileObject pWdmFileObject, __deref_out_opt FxFileObject **ppFxFileObject)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
DEVICE_TYPE GetDeviceType(VOID)
FxCallbackLock * GetCallbackLockPtrHelper(__deref_out_opt FxObject **LockObject)
VOID MarkNoDeleteDDI(__in FxObjectLockState State=ObjectLock)
Definition: fxobject.hpp:1118
Definition: typedefs.h:119
#define _Must_inspect_result_
Definition: ms_sal.h:558
FxPkgGeneral * m_PkgGeneral
Definition: fxdevice.hpp:671
static VOID _DestroyFileObject(__in FxDevice *pDevice, __in WDF_FILEOBJECT_CLASS FileObjectClass, __in_opt MdFileObject pWdmFileObject)
MxFileObject m_FileObject
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
#define TRACE_LEVEL_WARNING
Definition: storswtr.h:28
static unsigned __int64 next
Definition: rand_nt.c:6
__inline PFX_DRIVER_GLOBALS GetDriverGlobals(VOID)
Definition: fxobject.hpp:734
#define f
Definition: ke_i.h:83
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
#define NULL
Definition: types.h:112
#define __deref_out_opt
Definition: dbghelp.h:29
VOID DeleteFromFailedCreate(VOID)
Definition: fxobject.cpp:391
VOID DeleteFileObjectFromFailedCreate(VOID)
PVOID m_PkgContext
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
WDF_EXTERN_C_START enum _WDF_EXECUTION_LEVEL WDF_EXECUTION_LEVEL
virtual _Must_inspect_result_ NTSTATUS QueryInterface(__in FxQueryInterfaceParams *Params)
Definition: fxobject.cpp:255
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACINGIO
Definition: dbgtrace.h:66
__inline BOOLEAN IsExclusive(VOID)
Definition: fxdevice.hpp:1218
#define STATUS_DEVICE_CONFIGURATION_ERROR
Definition: ntstatus.h:619
VOID GetConstraintsHelper(__out_opt WDF_EXECUTION_LEVEL *ExecutionLevel, __out_opt WDF_SYNCHRONIZATION_SCOPE *SynchronizationScope)
#define FILE_DEVICE_SERIAL_PORT
Definition: serial.c:44
#define __in
Definition: dbghelp.h:35
static SERVICE_STATUS status
Definition: service.c:31
_Must_inspect_result_ NTSTATUS QueryInterface(__in FxQueryInterfaceParams *Params)
__inline CfxDevice * GetDevice(VOID)
FxVerifierDbgBreakPoint(pFxDriverGlobals)
virtual VOID DeleteObject(VOID)
Definition: fxdevice.cpp:1135
#define DO_NOTHING()
Definition: mxgeneral.h:32
Definition: ps.c:97
#define LockObject(Object)
Definition: titypes.h:34
PVOID GetFsContext2(VOID)