Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566/*++
Copyright (c) Microsoft Corporation
Module Name:
FxFileObject.hpp
Abstract:
This module implements a frameworks managed FileObject
Author:
Environment:
Both kernel and user mode
Revision History:
--*/
#include "coreprivshared.hpp"
// Tracing supportextern "C" {// #include "FxFileObject.tmh"}
//// Public constructors//
FxFileObject::FxFileObject( __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in MdFileObject pWdmFileObject, __in FxDevice* pDevice ) : FxNonPagedObject(FX_TYPE_FILEOBJECT, sizeof(FxFileObject), FxDriverGlobals){ m_FileObject.SetFileObject(pWdmFileObject); m_PkgContext = NULL; m_Device = pDevice;
#if (FX_CORE_MODE == FX_CORE_USER_MODE) RtlInitUnicodeString(&m_FileName, NULL); m_RelatedFileObject = NULL;#endif
// // Cannot be deleted by the device driver // MarkNoDeleteDDI();}
FxFileObject::~FxFileObject(){#if (FX_CORE_MODE == FX_CORE_USER_MODE) SAFE_RELEASE(m_RelatedFileObject);#endif}
//// Create the WDFFILEOBJECT and associate it with the WDM PFILE_OBJECT.//_Must_inspect_result_NTSTATUSFxFileObject::_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** pFileObject ){ NTSTATUS Status; FxFileObject* pfo; KIRQL irql; WDF_FILEOBJECT_CLASS normalizedFileClass;
PFX_DRIVER_GLOBALS FxDriverGlobals = pDevice->GetDriverGlobals();
// // Create does require a WDM file obj based on the normalized file obj // class value. // normalizedFileClass = FxFileObjectClassNormalize(FileObjectClass);
// // No FileObject support // if( normalizedFileClass == WdfFileObjectNotRequired ) { if( pFileObject != NULL ) *pFileObject = NULL; return STATUS_SUCCESS; }
// // If fileobject support was specified, and a NULL // WDM PFILE_OBJECT is supplied, then it's an error // if( pWdmFileObject == NULL ) {
// // Seems like some filter driver above us sending a create without fileobject. // We support this only if the FileObjectClass class is set to // WdfFileObjectWdfCannotUseFsContexts and device is created to be // exclusive. // if ( normalizedFileClass == WdfFileObjectWdfCannotUseFsContexts && pDevice->IsExclusive() ) {
DO_NOTHING();
} else { DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIO, "WdfFileObjectWdfCanUseFsContexts is specified, but the Create " "IRP %p doesn't have a fileObject\n", Irp); FxVerifierDbgBreakPoint(pDevice->GetDriverGlobals()); return STATUS_DEVICE_CONFIGURATION_ERROR; }
}
// Allocate a new FxFileObject with context pfo = new(pDevice->GetDriverGlobals(), pObjectAttributes) FxFileObject(pDevice->GetDriverGlobals(), pWdmFileObject, pDevice);
if( pfo == NULL ) { return STATUS_INSUFFICIENT_RESOURCES; }
pfo->Initialize(Irp);
// Assign FxDevice as the parent for the file object Status = pfo->Commit(pObjectAttributes, NULL, pDevice); if( !NT_SUCCESS(Status) ) { pfo->DeleteFromFailedCreate(); return Status; }
// // Place it on the list of FxFileObject's for this FxDevice // pDevice->Lock(&irql); InsertHeadList(&pDevice->m_FileObjectListHead, &pfo->m_Link); pDevice->Unlock(irql);
// // Set file object context in mode-specific manner // pfo->SetFileObjectContext(pWdmFileObject, normalizedFileClass, Irp, pDevice);
// FxFileObject* to caller if( pFileObject != NULL ) { *pFileObject = pfo; }
return STATUS_SUCCESS;}
//// Destroy (dereference) the WDFFILEOBJECT related to the// WDM PFILE_OBJECT according to its FileObjectClass.//VOIDFxFileObject::_DestroyFileObject( __in FxDevice* pDevice, __in WDF_FILEOBJECT_CLASS FileObjectClass, __in_opt MdFileObject pWdmFileObject ){ FxFileObject* pfo = NULL; PFX_DRIVER_GLOBALS FxDriverGlobals = pDevice->GetDriverGlobals(); WDF_FILEOBJECT_CLASS normalizedFileClass;
// // Close does require a WDM file obj based on the normalized file obj // class value. // normalizedFileClass = FxFileObjectClassNormalize(FileObjectClass);
if( normalizedFileClass == WdfFileObjectNotRequired ) { return; }
// // Driver has specified file object support, and we // allocated one at Create, so they must pass one // to close, otherwise it's an error and we will leak // the file object. // MxFileObject wdmFileObject(pWdmFileObject); if( pWdmFileObject == NULL && normalizedFileClass != WdfFileObjectWdfCannotUseFsContexts) {
// // It's likely that IRP_MJ_CREATE had NULL for the Wdm FileObject as well. // // If a driver passes != NULL for Wdm FileObject to create, and NULL to // this routine, a WDF FxFileObject object leak will occur, which will // be reported at driver unload. // DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGIO, "PFILE_OBJECT in close IRP is NULL, *Possible Leak of FxFileObject*\n");
FxVerifierDbgBreakPoint(pDevice->GetDriverGlobals());
return; } else if( normalizedFileClass == WdfFileObjectWdfCanUseFsContext ) { pfo = (FxFileObject*)wdmFileObject.GetFsContext(); wdmFileObject.SetFsContext(NULL);
} else if( normalizedFileClass == WdfFileObjectWdfCanUseFsContext2 ) { pfo = (FxFileObject*)wdmFileObject.GetFsContext2(); wdmFileObject.SetFsContext2(NULL); } else { NTSTATUS status; // // We must find the associated FxFileObject from the list // on the device // status = FxFileObject::_GetFileObjectFromWdm( pDevice, WdfFileObjectWdfCannotUseFsContexts, pWdmFileObject, &pfo );
// // We should find it, unless a different one was passed to IRP_MJ_CLOSE // than to IRP_MJ_CREATE, which is an error. // if (NT_SUCCESS(status) == FALSE || pfo == NULL) { DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "Could not find WDFFILEOBJECT for PFILE_OBJECT 0x%p", pWdmFileObject);
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "Did a different PFILE_OBJECT get passed to " "IRP_MJ_CLOSE than did to IRP_MJ_CREATE?"); FxVerifierDbgBreakPoint(pDevice->GetDriverGlobals()); } }
if( pfo != NULL ) { KIRQL irql;
// // Remove it from the list of FxFileObjects on the FxDevice // pDevice->Lock(&irql); RemoveEntryList(&pfo->m_Link); pDevice->Unlock(irql);
// Delete the file object pfo->DeleteObject(); }
return;}
//// Return the FxFileObject* for the given WDM PFILE_OBJECT//_Must_inspect_result_NTSTATUSFxFileObject::_GetFileObjectFromWdm( __in FxDevice* pDevice, __in WDF_FILEOBJECT_CLASS FileObjectClass, __in_opt MdFileObject pWdmFileObject, __deref_out_opt FxFileObject** ppFxFileObject ){ FxFileObject* pfo = NULL; PFX_DRIVER_GLOBALS FxDriverGlobals = pDevice->GetDriverGlobals(); WDF_FILEOBJECT_CLASS normalizedFileClass;
// // Normalize file object class value. // normalizedFileClass = FxFileObjectClassNormalize(FileObjectClass);
// // No FileObject support // if( normalizedFileClass == WdfFileObjectNotRequired ) { *ppFxFileObject = NULL; return STATUS_SUCCESS; }
if( pWdmFileObject == NULL ) {
// // Warn if an I/O request has NULL for the WDM PFILE_OBJECT // if ( pDevice->IsExclusive() && normalizedFileClass == WdfFileObjectWdfCannotUseFsContexts ) { // // We allow a NULL file object iff the device is exclusive and // we have to look up the WDFFILEOBJECT by PFILE_OBJECT value // DO_NOTHING(); } else if ( FxIsFileObjectOptional(FileObjectClass) ) { // // Driver told us that it's able to handle this case. // *ppFxFileObject = NULL; return STATUS_SUCCESS; } else { DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "NULL passed for PFILE_OBJECT when FileObject " "support is requested in an I/O request"); FxVerifierDbgBreakPoint(pDevice->GetDriverGlobals());
return STATUS_UNSUCCESSFUL; } }
// // Depending on the drivers configuration, we can quickly // get the FxFileObject* from FxContext, or FxContext2. // // Some drivers can not touch either of the FxContext(s), and // in that case we must resort to a list or hashtable. // MxFileObject wdmFileObject(pWdmFileObject); if( normalizedFileClass == WdfFileObjectWdfCanUseFsContext ) { pfo = (FxFileObject*)wdmFileObject.GetFsContext(); } else if( normalizedFileClass == WdfFileObjectWdfCanUseFsContext2 ) { pfo = (FxFileObject*)wdmFileObject.GetFsContext2(); } else { PLIST_ENTRY next; FxFileObject* f; KIRQL irql;
// // Must look it up from the FxDevice->m_FileObjectListHead. // pfo = NULL;
pDevice->Lock(&irql);
next = pDevice->m_FileObjectListHead.Flink;
if(pWdmFileObject == NULL) { // // If the pWdmFileObject is NULL then we will pass the first entry // in the list because the device must be exclusive and there // can be only one fileobject in the list. // ASSERT(IsListEmpty(&pDevice->m_FileObjectListHead) == FALSE);
f = CONTAINING_RECORD(next, FxFileObject, m_Link); pfo = f;
} else {
while( next != &pDevice->m_FileObjectListHead ) { f = CONTAINING_RECORD(next, FxFileObject, m_Link);
if( f->m_FileObject.GetFileObject()== pWdmFileObject ) { pfo = f; break; }
next = next->Flink; } }
if(pfo == NULL && pDevice->IsExclusive() && pDevice->GetMxDeviceObject()->GetDeviceType() == FILE_DEVICE_SERIAL_PORT && !IsListEmpty(&pDevice->m_FileObjectListHead)) {
f = CONTAINING_RECORD(pDevice->m_FileObjectListHead.Flink, FxFileObject, m_Link); pfo = f;
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGDEVICE, "The PFILE_OBJECT 0x%p in this request (cleanup/close) " "is different from the one specified in " "create request 0x%p.This is bad!", pWdmFileObject, ((f != NULL) ? f->m_FileObject.GetFileObject(): NULL)); DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGDEVICE, "Since this is a serial port device, framework is " "using a workaround to allow this"); }
pDevice->Unlock(irql); }
// // This can happen if a different PFILE_OBJECT is passed to an I/O // request than was presented to IRP_MJ_CREATE // if (pfo == NULL && FxIsFileObjectOptional(FileObjectClass) == FALSE) {
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "Could not locate WDFFILEOBJECT for " "PFILE_OBJECT 0x%p",pWdmFileObject);
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "Did a different PFILE_OBJECT get passed to the " "request than was to IRP_MJ_CREATE?");
if (FxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,9)) { FxVerifierDbgBreakPoint(pDevice->GetDriverGlobals()); } }
// // We don't do an extra reference count since the file objects // lifetime is controlled by the IoMgr. When the IRP_MJ_CLOSE // occurs, the reference is released after the optional // driver event callback. //
*ppFxFileObject = pfo;
return STATUS_SUCCESS;}
VOIDFxFileObject::DeleteFileObjectFromFailedCreate( VOID ){ KIRQL irql;
// // Remove it from the list of FxFileObjects on the FxDevice // m_Device->Lock(&irql); RemoveEntryList(&m_Link); m_Device->Unlock(irql);
// Delete the file object DeleteFromFailedCreate();}
_Must_inspect_result_NTSTATUSFxFileObject::QueryInterface( __in FxQueryInterfaceParams* Params )/*++
Routine Description: This routine is used to return the pointer to the Object itself.
Arguments: Params - query interface parameters.
Return Value: NTSTATUS
--*/
{ switch (Params->Type) { case FX_TYPE_FILEOBJECT: *Params->Object = (FxFileObject*) this; break;
case FX_TYPE_IHASCALLBACKS: *Params->Object = (IFxHasCallbacks*) this; break;
default: return FxNonPagedObject::QueryInterface(Params); // __super call }
return STATUS_SUCCESS;}
VOIDFxFileObject::GetConstraints( __in WDF_EXECUTION_LEVEL* ExecutionLevel, __in WDF_SYNCHRONIZATION_SCOPE* SynchronizationScope )/*++
Routine Description: This routine implements the GetConstraints IfxCallback. The caller gets the ExecutionLevel and the SynchronizationScope of the FileObject. The FileObject's SynchronizationScope and ExecutionLevel is strored in the FxPkgGeneral object.
Arguments: ExecutionLevel - (opt) receives the execution level.
SynchronizationScope - (opt) receives the synchronization scope.
Return Value: None
--*/
{ // // Get it from FxPkgGeneral which has the File attributes passed to it at device Creation time. // return GetDevice()->m_PkgGeneral->GetConstraintsHelper(ExecutionLevel, SynchronizationScope);}
_Must_inspect_result_FxCallbackLock*FxFileObject::GetCallbackLockPtr( __deref_out_opt FxObject** LockObject )/*++
Routine Description: This routine implements the GetCallbackLockPtr IfxCallback. The caller gets the LockObject to be used before calling the driver callbacks.
Arguments: LockObject - receives the lock object.
Return Value: FxCallbackLock *
--*/
{ // // Get it from FxPkgGeneral which has the File attributes passed to it at device Creation time. // return GetDevice()->m_PkgGeneral->GetCallbackLockPtrHelper(LockObject);}