Something went wrong. Try again.
Reactos
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177/*++
Copyright (c) Microsoft Corporation
Module Name:
FxDevice.cpp
Abstract:
This is the class implementation for the base Device class.
Author:
Environment:
Both kernel and user mode
Revision History:
--*/
#include "coreprivshared.hpp"
extern "C" {// #include "FxDevice.tmh"}
//// This table contains the mapping between device type and the// default priority boost used by the the framework when// an I/O request is completed. The DeviceObject->DeviceType// is used as an index into this table.//const CHAR FxDevice::m_PriorityBoosts[] = { IO_NO_INCREMENT, // FILE_DEVICE_UNDEFINED 0x00000000 IO_NO_INCREMENT, // FILE_DEVICE_BEEP 0x00000001 IO_CD_ROM_INCREMENT, // FILE_DEVICE_CD_ROM 0x00000002 IO_CD_ROM_INCREMENT, // FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 IO_NO_INCREMENT, // FILE_DEVICE_CONTROLLER 0x00000004 IO_NO_INCREMENT, // FILE_DEVICE_DATALINK 0x00000005 IO_NO_INCREMENT, // FILE_DEVICE_DFS 0x00000006 IO_DISK_INCREMENT, // FILE_DEVICE_DISK 0x00000007 IO_DISK_INCREMENT, // FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 IO_NO_INCREMENT, // FILE_DEVICE_FILE_SYSTEM 0x00000009 IO_NO_INCREMENT, // FILE_DEVICE_INPORT_PORT 0x0000000a IO_KEYBOARD_INCREMENT, // FILE_DEVICE_KEYBOARD 0x0000000b IO_MAILSLOT_INCREMENT, // FILE_DEVICE_MAILSLOT 0x0000000c IO_SOUND_INCREMENT, // FILE_DEVICE_MIDI_IN 0x0000000d IO_SOUND_INCREMENT, // FILE_DEVICE_MIDI_OUT 0x0000000e IO_MOUSE_INCREMENT, // FILE_DEVICE_MOUSE 0x0000000f IO_NO_INCREMENT, // FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010 IO_NAMED_PIPE_INCREMENT,// FILE_DEVICE_NAMED_PIPE 0x00000011 IO_NETWORK_INCREMENT, // FILE_DEVICE_NETWORK 0x00000012 IO_NETWORK_INCREMENT, // FILE_DEVICE_NETWORK_BROWSER 0x00000013 IO_NETWORK_INCREMENT, // FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 IO_NO_INCREMENT, // FILE_DEVICE_NULL 0x00000015 IO_PARALLEL_INCREMENT, // FILE_DEVICE_PARALLEL_PORT 0x00000016 IO_NETWORK_INCREMENT, // FILE_DEVICE_PHYSICAL_NETCARD 0x00000017 IO_NO_INCREMENT, // FILE_DEVICE_PRINTER 0x00000018 IO_NO_INCREMENT, // FILE_DEVICE_SCANNER 0x00000019 IO_SERIAL_INCREMENT, // FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a IO_SERIAL_INCREMENT, // FILE_DEVICE_SERIAL_PORT 0x0000001b IO_VIDEO_INCREMENT, // FILE_DEVICE_SCREEN 0x0000001c IO_SOUND_INCREMENT, // FILE_DEVICE_SOUND 0x0000001d IO_SOUND_INCREMENT, // FILE_DEVICE_STREAMS 0x0000001e IO_NO_INCREMENT, // FILE_DEVICE_TAPE 0x0000001f IO_NO_INCREMENT, // FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 IO_NO_INCREMENT, // FILE_DEVICE_TRANSPORT 0x00000021 IO_NO_INCREMENT, // FILE_DEVICE_UNKNOWN 0x00000022 IO_VIDEO_INCREMENT, // FILE_DEVICE_VIDEO 0x00000023 IO_DISK_INCREMENT, // FILE_DEVICE_VIRTUAL_DISK 0x00000024 IO_SOUND_INCREMENT, // FILE_DEVICE_WAVE_IN 0x00000025 IO_SOUND_INCREMENT, // FILE_DEVICE_WAVE_OUT 0x00000026 IO_KEYBOARD_INCREMENT, // FILE_DEVICE_8042_PORT 0x00000027 IO_NETWORK_INCREMENT, // FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 IO_NO_INCREMENT, // FILE_DEVICE_BATTERY 0x00000029 IO_NO_INCREMENT, // FILE_DEVICE_BUS_EXTENDER 0x0000002a IO_SERIAL_INCREMENT, // FILE_DEVICE_MODEM 0x0000002b IO_NO_INCREMENT, // FILE_DEVICE_VDM 0x0000002c IO_DISK_INCREMENT, // FILE_DEVICE_MASS_STORAGE 0x0000002d IO_NETWORK_INCREMENT, // FILE_DEVICE_SMB 0x0000002e IO_SOUND_INCREMENT, // FILE_DEVICE_KS 0x0000002f IO_NO_INCREMENT, // FILE_DEVICE_CHANGER 0x00000030 IO_NO_INCREMENT, // FILE_DEVICE_SMARTCARD 0x00000031 IO_NO_INCREMENT, // FILE_DEVICE_ACPI 0x00000032 IO_NO_INCREMENT, // FILE_DEVICE_DVD 0x00000033 IO_VIDEO_INCREMENT, // FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034 IO_NO_INCREMENT, // FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035 IO_NO_INCREMENT, // FILE_DEVICE_DFS_VOLUME 0x00000036 IO_SERIAL_INCREMENT, // FILE_DEVICE_SERENUM 0x00000037 IO_NO_INCREMENT, // FILE_DEVICE_TERMSRV 0x00000038 IO_NO_INCREMENT, // FILE_DEVICE_KSEC 0x00000039 IO_NO_INCREMENT, // FILE_DEVICE_FIPS 0x0000003A IO_NO_INCREMENT, // FILE_DEVICE_INFINIBAND 0x0000003B};
NTSTATUSFxDevice::_CompletionRoutineForRemlockMaintenance( __in MdDeviceObject DeviceObject, __in MdIrp Irp, __in PVOID Context )/*++
Routine Description:
A completion routine for the IRPs for which we acquired opt-in remove lock.
Arguments: DeviceObject - Pointer to deviceobject Irp - Pointer to the Irp for which we acquired opt-in remove lock. Context - NULLReturn Value:
NT Status is returned.
--*/
{ FxIrp irp(Irp);
UNREFERENCED_PARAMETER(Context);
// // Let the irp continue on its way. // irp.PropagatePendingReturned();
#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) Mx::MxReleaseRemoveLock(&((FxDevice::_GetFxWdmExtension( DeviceObject))->IoRemoveLock), Irp);#else UNREFERENCED_PARAMETER(DeviceObject);#endif
return STATUS_CONTINUE_COMPLETION;}
FxDevice::FxDevice( __in FxDriver *ArgDriver ) : FxDeviceBase(ArgDriver->GetDriverGlobals(), ArgDriver, FX_TYPE_DEVICE, sizeof(FxDevice)), m_ParentDevice(NULL){ SetInitialState();}
VOIDFxDevice::SetInitialState( VOID ){ // // Set the initial device state // m_CurrentPnpState = WdfDevStatePnpObjectCreated; m_CurrentPowerState = WdfDevStatePowerObjectCreated; m_CurrentPowerPolicyState = WdfDevStatePwrPolObjectCreated;
// // Set the default IO type to "buffered" // m_ReadWriteIoType = WdfDeviceIoBuffered;
RtlZeroMemory(&m_DeviceName, sizeof(m_DeviceName)); RtlZeroMemory(&m_SymbolicLinkName, sizeof(m_SymbolicLinkName)); RtlZeroMemory(&m_MofResourceName, sizeof(m_MofResourceName));
m_Filter = FALSE; m_Exclusive = FALSE; m_PowerPageableCapable = FALSE; m_ParentWaitingOnChild = FALSE; m_Legacy = FALSE; m_DeviceObjectDeleted = FALSE; m_PdoKnown = FALSE; m_Legacy = FALSE; m_AutoForwardCleanupClose = FALSE; m_SelfIoTargetNeeded = FALSE; m_DeviceTelemetryInfoFlags = 0;
// // Clear all packages by default //
m_PkgIo = NULL; m_PkgPnp = NULL; m_PkgGeneral = NULL; m_PkgWmi = NULL; m_PkgDefault = NULL;
InitializeListHead(&m_PreprocessInfoListHead); InitializeListHead(&m_CxDeviceInfoListHead);
#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) m_FileObjectClass = WdfFileObjectNotRequired;#else // UMDF // // In UMDF file object is always required. So indicate that now. // m_FileObjectClass = WdfFileObjectWdfCannotUseFsContexts;#endif
m_DefaultPriorityBoost = IO_NO_INCREMENT;
InitializeListHead(&m_FileObjectListHead);
m_RequestLookasideListElementSize = 0; RtlZeroMemory(&m_RequestLookasideList, sizeof(m_RequestLookasideList)); RtlZeroMemory(&m_RequestAttributes, sizeof(m_RequestAttributes));
#if (FX_CORE_MODE == FX_CORE_USER_MODE) // // Init UMDF specific members // m_CleanupFromFailedCreate = FALSE; m_Dispatcher = NULL; m_DevStack = NULL; m_PdoDevKey = NULL; m_DeviceKeyPath = NULL; m_KernelDeviceName = NULL; m_DeviceInstanceId = NULL;
m_RetrievalMode = UMINT::WdfDeviceIoBufferRetrievalDeferred; m_IoctlIoType = WdfDeviceIoBuffered; m_DirectTransferThreshold = 0;
m_DirectHardwareAccess = FX_DIRECT_HARDWARE_ACCESS_DEFAULT; m_RegisterAccessMode = FX_REGISTER_ACCESS_MODE_DEFAULT; m_FileObjectPolicy = FX_FILE_OBJECT_POLICY_DEFAULT; m_FsContextUsePolicy = FX_FS_CONTEXT_USE_POLICY_DEFAULT; m_InteruptThreadpool = NULL;#endif}
FxDevice::~FxDevice(){ PLIST_ENTRY next;
// Make it always present right now even on free builds if (IsDisposed() == FALSE) { DoTraceLevelMessage( GetDriverGlobals(), TRACE_LEVEL_FATAL, TRACINGDEVICE, "FxDevice 0x%p not disposed: this maybe a driver reference count " "problem with WDFDEVICE %p", this, GetObjectHandleUnchecked());
FxVerifierBugCheck(GetDriverGlobals(), WDF_OBJECT_ERROR, (ULONG_PTR) GetObjectHandleUnchecked(), (ULONG_PTR) this); }
// // Execute mode-specific destructor. Noop for KMDF, but does // does detach and delete of UM device object for UMDF. Therefore // can be done before other cleanup. // DestructorInternal();
// // If the device has been initialized but hasn't yet been // destroyed, destroy it now. //
ASSERT(m_DeviceObject.GetObject() == NULL);
ASSERT(m_DeviceName.Buffer == NULL);
#if FX_CORE_MODE == FX_CORE_KERNEL_MODE // // Assert only applicable to KM because FxDevice can get destroyed in UMDF // without going through normal pnp remove path, for example, when an // AddDevice failure is done in reflector, after all um drivers have // succeeded AddDevice. KMDF and host use fake remove irp to handle // AddDevice failure in KMDF and host respectively, but reflector does not // do that for AddDevice failure that happens in reflector. // Note that symbolicName buffer will anyway be deleted in this destructor // later on so the symbolic link buffer doesn't leak out. // ASSERT(m_SymbolicLinkName.Buffer == NULL);#endif
ASSERT(m_MofResourceName.Buffer == NULL);
if (m_PkgIo != NULL) { m_PkgIo->RELEASE(NULL); m_PkgIo = NULL; }
if (m_PkgPnp != NULL) { m_PkgPnp->RELEASE(NULL); m_PkgPnp = NULL; }
if (m_PkgGeneral != NULL) { m_PkgGeneral->RELEASE(NULL); m_PkgGeneral = NULL; }
if (m_PkgWmi != NULL) { m_PkgWmi->RELEASE(NULL); m_PkgWmi = NULL; }
if (m_PkgDefault != NULL) { m_PkgDefault->RELEASE(NULL); m_PkgDefault = NULL; }
while (!IsListEmpty(&m_PreprocessInfoListHead)) { next = RemoveHeadList(&m_PreprocessInfoListHead); FxIrpPreprocessInfo* info; info = CONTAINING_RECORD(next, FxIrpPreprocessInfo, ListEntry); InitializeListHead(next); delete info; }
while (!IsListEmpty(&m_CxDeviceInfoListHead)) { next = RemoveHeadList(&m_CxDeviceInfoListHead); FxCxDeviceInfo* info; info = CONTAINING_RECORD(next, FxCxDeviceInfo, ListEntry); InitializeListHead(next); delete info; }
// // Clean up any referenced objects // if (m_DeviceName.Buffer != NULL) { FxPoolFree(m_DeviceName.Buffer); RtlZeroMemory(&m_DeviceName, sizeof(m_DeviceName)); }
DeleteSymbolicLink();
if (m_MofResourceName.Buffer != NULL) { FxPoolFree(m_MofResourceName.Buffer); RtlZeroMemory(&m_MofResourceName, sizeof(m_DeviceName)); }
// // m_RequestLookasideListElementSize will be set to non zero if we have // initialized the request lookaside list. // if (m_RequestLookasideListElementSize != 0) { Mx::MxDeleteNPagedLookasideList(&m_RequestLookasideList); m_RequestLookasideListElementSize = 0; }
if (m_ParentDevice != NULL) { m_ParentDevice->RELEASE(this); }}
_Must_inspect_result_NTSTATUSFxDevice::_Create( __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PWDFDEVICE_INIT* DeviceInit, __in_opt PWDF_OBJECT_ATTRIBUTES DeviceAttributes, __out FxDevice** Device ){ PWDFDEVICE_INIT pInit; FxDevice* pDevice; NTSTATUS status; WDFOBJECT object; PLIST_ENTRY pNext; PWDFCXDEVICE_INIT pCxInit; FxWdmDeviceExtension* wdmDeviceExtension;
*Device = NULL; pInit = *DeviceInit;
pDevice = new (FxDriverGlobals, DeviceAttributes) FxDevice(pInit->Driver);
if (pDevice == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Done; }
status = pDevice->Initialize(pInit, DeviceAttributes); if (!NT_SUCCESS(status)) { goto Done; }
switch (pInit->InitType) { case FxDeviceInitTypeFdo: status = pDevice->FdoInitialize(pInit); break;
case FxDeviceInitTypePdo: status = pDevice->PdoInitialize(pInit); break;
case FxDeviceInitTypeControlDevice: status = pDevice->ControlDeviceInitialize(pInit); break;
default: // // Should not drop here // ASSERT(FALSE); break; } if (!NT_SUCCESS(status)) { goto Done; }
// // Ok, we have created the device. Now lets create a handle for it. // status = pDevice->PostInitialize(); if (!NT_SUCCESS(status)) { goto Done; }
// // Can't use the PDO's FxDevice m_Parent as the object hierarchy parent // because the Fx object hierarchy lifetime rules do not match the // rules for a pnp PDO lifetime vs its FDO. // status = pDevice->Commit(DeviceAttributes, &object, pDevice->GetDriver()); if (!NT_SUCCESS(status)) { goto Done; }
// // NOTE: ---> DO NOT FAIL FROM HERE FORWARD <--- //
// // Up until now we have not reassigned any of the allocations in pInit // and assigned them to the underlying objects. We are now at the point // of "no return", ie we cannot fail. If we reassigned the allocations // before this point and the driver retried to create the device (let's // say with a different name), we would have freed those allocations // and the driver writer would have thought that particular settings // we valid, but were not b/c we freed them on error. So, to avoid a // huge tracking mess, we only grab the allocations once we know for // *sure* we are going to return success. // if (pInit->DeviceName != NULL) { pInit->DeviceName->ReleaseString(&pDevice->m_DeviceName); }
// // Check for driver preprocess requirements. // if (pInit->PreprocessInfo != NULL) { ASSERT( pInit->PreprocessInfo->ClassExtension == FALSE); ASSERT(IsListEmpty(&pDevice->m_PreprocessInfoListHead)); InsertTailList(&pDevice->m_PreprocessInfoListHead, &pInit->PreprocessInfo->ListEntry); pInit->PreprocessInfo = NULL;
// // If the driver is preprocessing requests on this device, they need // their own stack location so that they can set their own completion // routine. // pDevice->SetStackSize(pDevice->GetStackSize()+1); }
#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE) wdmDeviceExtension = _GetFxWdmExtension(pDevice->GetDeviceObject()); if (wdmDeviceExtension->RemoveLockOptionFlags & WDF_REMOVE_LOCK_OPTION_ACQUIRE_FOR_IO) { // // We will use a completion routine for remlock maintenance // pDevice->SetStackSize(pDevice->GetStackSize()+1); }
// // Note: In case of UMDF StackSize is incremented prior to attaching // the device to stack. See the comment in FxDeviceUm.cpp // if (pDevice->m_SelfIoTargetNeeded) { pDevice->SetStackSize(pDevice->GetStackSize()+1); }
#else UNREFERENCED_PARAMETER(wdmDeviceExtension);#endif
// // Check for any class-extensions' preprocess requirements. // for (pNext = pInit->CxDeviceInitListHead.Flink; pNext != &pInit->CxDeviceInitListHead; pNext = pNext->Flink) {
pCxInit = CONTAINING_RECORD(pNext, WDFCXDEVICE_INIT, ListEntry);
if (pCxInit->PreprocessInfo != NULL) { ASSERT(pCxInit->PreprocessInfo->ClassExtension); InsertTailList(&pDevice->m_PreprocessInfoListHead, &pCxInit->PreprocessInfo->ListEntry); pCxInit->PreprocessInfo = NULL;
// // If the class extension is preprocessing requests on this // device, it needs its own stack location so that it can // set its own completion routine. // pDevice->SetStackSize(pDevice->GetStackSize()+1); } }
if (pDevice->IsPnp()) { // // Take all of the allocations out of pInit related to pnp. This // will also transition the pnp state machine into the added state. // pDevice->m_PkgPnp->FinishInitialize(pInit); }
pInit->CreatedDevice = pDevice;
// // Clear out the pointer, we freed it on behalf of the caller // *DeviceInit = NULL;
if (pInit->CreatedOnStack == FALSE) { delete pInit; }
Done: if (!NT_SUCCESS(status) && pDevice != NULL) { // // We want to propagate the original error code // (void) pDevice->DeleteDeviceFromFailedCreate(status, FALSE); pDevice = NULL; }
*Device = pDevice;
return status;}
_Must_inspect_result_NTSTATUSFxDevice::DeleteDeviceFromFailedCreateNoDelete( __in NTSTATUS FailedStatus, __in BOOLEAN UseStateMachine ){ // // Cleanup the device, the driver may have allocated resources // associated with the WDFDEVICE // DoTraceLevelMessage( GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP, "WDFDEVICE %p !devobj %p created, but EvtDriverDeviceAdd returned " "status %!STATUS! or failure in creation", GetObjectHandleUnchecked(), GetDeviceObject(), FailedStatus);
// // We do not let filters affect the building of the rest of the stack. // If they return error, we convert it to STATUS_SUCCESS, remove the // attached device from the stack, and cleanup. // if (IsFilter()) { DoTraceLevelMessage( GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNP, "WDFDEVICE %p, !devobj %p is a filter, converting %!STATUS! to" " STATUS_SUCCESS", GetObjectHandleUnchecked(), GetDeviceObject(), FailedStatus); FailedStatus = STATUS_SUCCESS; }
if (UseStateMachine) { MxEvent waitEvent;
// // See comments for m_CleanupFromFailedCreate in class definition file // for use of this statement. // SetCleanupFromFailedCreate(TRUE);
waitEvent.Initialize(SynchronizationEvent, FALSE); m_PkgPnp->CleanupDeviceFromFailedCreate(waitEvent.GetSelfPointer()); } else { // // Upon certain types of failure, like STATUS_OBJECT_NAME_COLLISION, we // could keep the pDevice around and the caller retry after changing // a property, but the simpler route for now is to just recreate // everything from scratch on the retry. // // Usually the pnp state machine will do this and the FxDevice destructor // relies on it running b/c it does some cleanup. // EarlyDispose(); DestroyChildren();
// // Wait for all children to drain out and cleanup. // if (m_DisposeList != NULL) { m_DisposeList->WaitForEmpty(); }
// // We keep a reference on m_PkgPnp which is released in the destructor // so we can safely touch m_PkgPnp after destroying all of the child // objects. // if (m_PkgPnp != NULL) { m_PkgPnp->CleanupStateMachines(TRUE); } }
// // This will detach and delete the device object // Destroy();
return FailedStatus;}
_Must_inspect_result_NTSTATUSFxDevice::DeleteDeviceFromFailedCreate( __in NTSTATUS FailedStatus, __in BOOLEAN UseStateMachine ){ NTSTATUS status;
status = DeleteDeviceFromFailedCreateNoDelete(FailedStatus, UseStateMachine);
// // Delete the Fx object now // DeleteObject();
return status;}
_Must_inspect_result_NTSTATUSFxDevice::Initialize( __in PWDFDEVICE_INIT DeviceInit, __in_opt PWDF_OBJECT_ATTRIBUTES DeviceAttributes )/*++
Routine Description: Generic initialization for an FxDevice regardless of role (pdo, fdo, control).
Arguments:
Return Value:
--*/
{ PFX_DRIVER_GLOBALS pGlobals; PLIST_ENTRY next; NTSTATUS status; size_t reqCtxSize; PWDFCXDEVICE_INIT cxInit; CCHAR cxIndex; FxCxDeviceInfo* cxDeviceInfo;
pGlobals = GetDriverGlobals(); m_Exclusive = DeviceInit->Exclusive; cxIndex = 0;
MarkDisposeOverride(ObjectDoNotLock);
// // Configure device constraints. // status = ConfigureConstraints(DeviceAttributes); if (!NT_SUCCESS(status)) { return status; }
// // Generic catch all // m_PkgDefault = new (pGlobals) FxDefaultIrpHandler(pGlobals, (CfxDevice*)this); if (m_PkgDefault == NULL) { return STATUS_INSUFFICIENT_RESOURCES; }
InstallPackage(m_PkgDefault);
if (DeviceInit->InitType == FxDeviceInitTypeControlDevice) { m_Legacy = TRUE; }
// // Size will be set to a non zero if the driver wants request attributes // associated with each created request. // if (DeviceInit->RequestAttributes.Size != 0) { ASSERT(DeviceInit->RequestAttributes.Size == sizeof(WDF_OBJECT_ATTRIBUTES)); RtlCopyMemory(&m_RequestAttributes, &DeviceInit->RequestAttributes, sizeof(DeviceInit->RequestAttributes)); }
reqCtxSize = FxGetContextSize(&m_RequestAttributes);
// // If present, setup a I/O class extensions info chain. // for (next = DeviceInit->CxDeviceInitListHead.Flink; next != &DeviceInit->CxDeviceInitListHead; next = next->Flink) {
cxInit = CONTAINING_RECORD(next, WDFCXDEVICE_INIT, ListEntry);
cxDeviceInfo = new(pGlobals) FxCxDeviceInfo(pGlobals); if (NULL == cxDeviceInfo) { return STATUS_INSUFFICIENT_RESOURCES; }
cxDeviceInfo->Index = ++cxIndex; // 1-based. cxDeviceInfo->Driver = cxInit->CxDriverGlobals->Driver; cxDeviceInfo->IoInCallerContextCallback.m_Method = cxInit->IoInCallerContextCallback; cxDeviceInfo->RequestAttributes = cxInit->RequestAttributes;
InsertTailList(&m_CxDeviceInfoListHead, &cxDeviceInfo->ListEntry);
// // Set weak ref to this run-time cx struct to help file-object logic later on. // cxInit->CxDeviceInfo = cxDeviceInfo;
// // Find the max size for the request context. Used below. // ASSERT(cxInit->RequestAttributes.Size == 0 || cxInit->RequestAttributes.Size == sizeof(WDF_OBJECT_ATTRIBUTES));
reqCtxSize = MAX(FxGetContextSize(&cxInit->RequestAttributes), reqCtxSize); }
// // Memory layout for memory backing FxRequest which is allocated from the // lookaside list: // // If we are tracking memory, the allocation layout is // 0x0 - FX_POOL_TRACKER // 0x0 + sizeof(FX_POOL_TRACKER) - FX_POOL_HEADER // 0x0 + sizeof(FX_POOL_TRACKER) + FX_POOL_HEADER_SIZE - start of FxRequest // // if no tracking is occuring, the allocation layout is // 0x0 - FX_POOL_HEADER // 0x0 + FX_POOL_HEADER_SIZE - start of FxRequest // // NOTE: If the computation of m_RequestLookasideListElementSize changes, // FxDevice::AllocateRequestMemory and FxDevice::FreeRequestMemory will also // need to be updated to reflect the changes made. // status = FxCalculateObjectTotalSize2(pGlobals, sizeof(FxRequest), 0, reqCtxSize, &m_RequestLookasideListElementSize); if (!NT_SUCCESS(status)) { return status; }
status = FxPoolAddHeaderSize(pGlobals, m_RequestLookasideListElementSize, &m_RequestLookasideListElementSize);
if (!NT_SUCCESS(status)) { // // FxPoolAddHeaderSize will log to the IFR on error // return status; }
Mx::MxInitializeNPagedLookasideList(&m_RequestLookasideList, NULL, NULL, 0, m_RequestLookasideListElementSize, pGlobals->Tag, 0); // // Init device's auto_forward_cleanup_close. // ConfigureAutoForwardCleanupClose(DeviceInit);
// // Create, close, cleanup, shutdown // m_PkgGeneral = new(pGlobals) FxPkgGeneral(pGlobals, this); if (m_PkgGeneral == NULL) { return STATUS_INSUFFICIENT_RESOURCES; }
InstallPackage(m_PkgGeneral);
#if (FX_CORE_MODE==FX_CORE_KERNEL_MODE)
m_PkgWmi = new(pGlobals) FxWmiIrpHandler(pGlobals, this); if (m_PkgWmi == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } InstallPackage(m_PkgWmi);#endif
// // IO package handles reads, writes, internal and external IOCTLs // m_PkgIo = new(pGlobals) FxPkgIo(pGlobals, (CfxDevice*) this);
if (m_PkgIo == NULL) { return STATUS_INSUFFICIENT_RESOURCES; }
InstallPackage(m_PkgIo);
// // Configure I/O package. // m_PkgIo->SetIoInCallerContextCallback(DeviceInit->IoInCallerContextCallback);
if (DeviceInit->RequiresSelfIoTarget) { m_SelfIoTargetNeeded = TRUE; }
return STATUS_SUCCESS;}
VOIDFxDevice::ConfigureAutoForwardCleanupClose( __in PWDFDEVICE_INIT DeviceInit ){ WDF_TRI_STATE autoForwardCleanupClose; PLIST_ENTRY next; BOOLEAN checkClientDriver;
autoForwardCleanupClose = WdfUseDefault; checkClientDriver = TRUE;
// // Device-wide configuration for auto forwarding cleanup and close requests: // . Use WdfFalse if one of the devices in the chain use this setting with a create // callback (this means it will complete all create IRPs). // . Else use lowest driver's setting in the chain (order of cx chain: lower to higher). // . If no settings are present, use default. // for (next = DeviceInit->CxDeviceInitListHead.Blink; next != &DeviceInit->CxDeviceInitListHead; next = next->Blink) {
PWDFCXDEVICE_INIT cxInit;
cxInit = CONTAINING_RECORD(next, WDFCXDEVICE_INIT, ListEntry);
if (cxInit->FileObject.Set) { autoForwardCleanupClose = cxInit->FileObject.AutoForwardCleanupClose;
if (autoForwardCleanupClose == WdfFalse && cxInit->FileObject.Callbacks.EvtCxDeviceFileCreate != NULL) {
checkClientDriver = FALSE; break; } } }
if (checkClientDriver && DeviceInit->FileObject.Set) { autoForwardCleanupClose = DeviceInit->FileObject.AutoForwardCleanupClose; }
switch (autoForwardCleanupClose) { case WdfTrue:
m_AutoForwardCleanupClose = TRUE; // // If the device is legacy then set it to false because you can't forward // requests. // if(m_Legacy) { m_AutoForwardCleanupClose = FALSE; } break;
case WdfFalse: m_AutoForwardCleanupClose = FALSE; break;
case WdfUseDefault: // // For filters (which must be FDOs), we default to TRUE. All other // device roles (FDO, PDO, control) default to FALSE. We cannot check // m_Filter yet because it is set in FdoInitialize which occurs later. // if (DeviceInit->IsFdoInit() && DeviceInit->Fdo.Filter) { m_AutoForwardCleanupClose = TRUE; } else { m_AutoForwardCleanupClose = FALSE; } }}
_Must_inspect_result_NTSTATUSFxDevice::PostInitialize( VOID ){ NTSTATUS status;
status = FxDisposeList::_Create(GetDriverGlobals(), m_DeviceObject.GetObject(), &m_DisposeList);
return status;}
#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
_Must_inspect_result_NTSTATUSFxDevice::CreateDevice( __in PWDFDEVICE_INIT DeviceInit ){ MdDeviceObject pNewDeviceObject; ULONG characteristics; NTSTATUS status; DEVICE_TYPE devType;
status = m_PkgGeneral->Initialize(DeviceInit); if (!NT_SUCCESS(status)) { return status; }
devType = DeviceInit->DeviceType; if (devType < ARRAY_SIZE(m_PriorityBoosts)) { m_DefaultPriorityBoost= m_PriorityBoosts[devType]; }
characteristics = DeviceInit->Characteristics;
// // You can only create secure device objects which have a name. All other // device objects rely on the PDO's security // if (DeviceInit->ShouldCreateSecure()) { PUNICODE_STRING pName, pSddl; LPGUID pGuid;
if (DeviceInit->DeviceName != NULL) { pName = DeviceInit->DeviceName->GetUnicodeString(); } else { pName = NULL; }
if (DeviceInit->Security.DeviceClassSet) { pGuid = &DeviceInit->Security.DeviceClass; } else { pGuid = NULL; }
if (DeviceInit->Security.Sddl != NULL) { pSddl = DeviceInit->Security.Sddl->GetUnicodeString(); } else { // // Always provide an SDDL if one is not supplied. // // SDDL_DEVOBJ_SYS_ALL_ADM_ALL = "D:P(A;;GA;;;SY)(A;;GA;;;BA)" // // SDDL_DEVOBJ_SYS_ALL_ADM_ALL allows the kernel, system, and // administrator complete control over the device. No other users // may access the device. // // pSddl = (PUNICODE_STRING) &SDDL_DEVOBJ_SYS_ALL_ADM_ALL; pSddl = NULL; // __REACTOS__ : wdmsec.lib is not supported }
status = Mx::MxCreateDeviceSecure( m_Driver->m_DriverObject.GetObject(), sizeof(FxWdmDeviceExtension), pName, devType, characteristics, m_Exclusive, pSddl, pGuid, &pNewDeviceObject); } else { status = Mx::MxCreateDevice( m_Driver->m_DriverObject.GetObject(), sizeof(FxWdmDeviceExtension), NULL, devType, characteristics, m_Exclusive, &pNewDeviceObject); }
if (NT_SUCCESS(status)) { FxWdmDeviceExtension* pWdmExt;
pWdmExt = _GetFxWdmExtension(pNewDeviceObject);
// // We reassign DeviceExtension below and then use the knowledge that // we can always retrieve DeviceExtension by adding sizeof(DEVICE_OBJECT) // to pNewDeviceObject. ASSERT that this assumption is correct. // MxDeviceObject newDeviceObject(pNewDeviceObject); ASSERT(pWdmExt == newDeviceObject.GetDeviceExtension());
Mx::MxInitializeRemoveLock(&pWdmExt->IoRemoveLock, GetDriverGlobals()->Tag, 0, // max min 0 // highwater mark );
// // Option for remove lock is stored in device extension // since this option may be examined after FxDevice is destroyed // (if an Irp is sent after removal of device). // We combine the flags from DeviceInit with what's set through registry // pWdmExt->RemoveLockOptionFlags = DeviceInit->RemoveLockOptionFlags | GetDriverGlobals()->RemoveLockOptionFlags;
// // We assign the first context assigned to this object as the // DeviceExtension for compatibility reasons. This allows existing // WDM extensions to work as well as any stack which exports a known // structure for the extension (ie the FDO knows the extension of its // PDO and casts it and accesses it directly). // newDeviceObject.SetDeviceExtension(&GetContextHeader()->Context[0]); m_DeviceObject.SetObject(pNewDeviceObject);
// // Set some device object flags based on properties of DeviceInit. // // If we are a filter, we will set these flags later // (in FxDevice::FdoInitialize) based on the device we are attached to. // if (m_Filter == FALSE) { if (DeviceInit->ReadWriteIoType == WdfDeviceIoBuffered) { m_DeviceObject.SetFlags(m_DeviceObject.GetFlags() | DO_BUFFERED_IO); } else if (DeviceInit->ReadWriteIoType == WdfDeviceIoDirect) { m_DeviceObject.SetFlags(m_DeviceObject.GetFlags() | DO_DIRECT_IO); }
m_ReadWriteIoType = DeviceInit->ReadWriteIoType; m_PowerPageableCapable = DeviceInit->PowerPageable; } }
return status;}
#endif // (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
VOIDFxDevice::FinishInitializing( VOID )
/*++
Routine Description:
This routine is called when the device is completely initialized.
Arguments:
none.
Returns:
none.
--*/
{
m_DeviceObject.SetFlags( m_DeviceObject.GetFlags() & ~DO_DEVICE_INITIALIZING);}
VOIDFxDevice::DeleteObject( VOID )/*++
Routine Description: Virtual override of an FxObject::DeleteObject. For PDOs which are created statically and then deleted before being reported to WDF, we must simulate a pnp remove event to trigger cleanup.
Arguments: None
Return Value: None
--*/{ if (IsPnp() && IsPdo()) { FxPkgPdo* pPkgPdo; KIRQL irql; BOOLEAN remove;
remove = FALSE;
pPkgPdo = GetPdoPkg();
pPkgPdo->Lock(&irql);
if (pPkgPdo->m_Static && pPkgPdo->m_AddedToStaticList == FALSE) { // // Since no pnp action has been taken since the child was created, we // should be in the initial state. // if (m_CurrentPnpState == WdfDevStatePnpInit) { // // A PDO in this state should be deletable // ASSERT(IsNoDeleteDDI() == FALSE);
remove = TRUE; } else { // // If we are not in the init state, we should be in the created // state. This means we are failing from FxDevice::CreateDevice. // ASSERT(m_CurrentPnpState == WdfDevStatePnpObjectCreated); } }
pPkgPdo->Unlock(irql);
if (remove) { // // Cleanup the device and then let the super class delete the object. // (void) DeleteDeviceFromFailedCreateNoDelete( STATUS_UNSUCCESSFUL, TRUE); } } else if (IsLegacy() && m_PkgGeneral != NULL && m_DeviceObject.GetObject() != NULL) { // // We allow tracing devices to go through a normal DeleteObject() path // where we do not prematurely delete the device object. // (void) FxVerifierCheckIrqlLevel(GetDriverGlobals(), PASSIVE_LEVEL);
m_DeviceObjectDeleted = TRUE;
// // This reference will be released in Destroy(). // Mx::MxReferenceObject(m_DeviceObject.GetObject());
if (m_PkgWmi != NULL) { // // Since a legacy NT4 driver does not have an explicit WMI // deregistration DDI, we do it for them on deletion. // // This is done in DeleteObject because we need to deregister before // we delete the device object, otherwise we can bugcheck when // running under driver verifier. // m_PkgWmi->Deregister(); }
// // By deleting the device object now, we prevent any new creates from // being sent to the device (the io manager enforces this). // Mx::MxDeleteDevice(m_DeviceObject.GetObject());
if (m_PkgGeneral->CanDestroyControlDevice() == FALSE) { // // Delay the actual destruction of the device until the last open // handle has been closed. ControlDeviceDelete() will perform the // destruction later. // return; } }
FxDeviceBase::DeleteObject(); // __super call}
BOOLEANFxDevice::Dispose( VOID ){ ASSERT(Mx::MxGetCurrentIrql() == PASSIVE_LEVEL);
if (m_Legacy) { if (m_PkgWmi != NULL) { // // We deregister in Dispose() (as well as DeleteObject()) for // control devices which are implicitly destroyed when the driver // unloads and FxDriver is being deleted. // // Since a legacy NT4 driver does not have an explicit WMI // deregistration DDI, we do it for them on destruction. // // This is done in Dispose because we are guaranteed to be at // passive level here. Even though m_PkgWmi was already // Dispose()'ed (because it is a child of this object), it is still // valid to reference the pointer because there is an explicit // reference on the object that was taken when we created this object. // m_PkgWmi->Deregister(); }
// // Important that the cleanup routine be called while the PDEVICE_OBJECT // is valid! // CallCleanup();
// // Manually destroy the children now so that by the time we wait on the // dispose empty out, all of the children will have been added to it. // DestroyChildren();
if (m_DisposeList != NULL) { m_DisposeList->WaitForEmpty(); }
// // Now delete the device object // Destroy();
return FALSE; }
return FxDeviceBase::Dispose(); // __super call}
_Must_inspect_result_NTSTATUSFxDevice::_AcquireOptinRemoveLock( __in MdDeviceObject DeviceObject, __in MdIrp Irp ){ NTSTATUS status; FxIrp irp(Irp);
FxWdmDeviceExtension * wdmDeviceExtension = FxDevice::_GetFxWdmExtension(DeviceObject);
if (wdmDeviceExtension->RemoveLockOptionFlags & WDF_REMOVE_LOCK_OPTION_ACQUIRE_FOR_IO) {
status = Mx::MxAcquireRemoveLock(&(wdmDeviceExtension->IoRemoveLock), Irp);
if (!NT_SUCCESS(status)) { return status; }
irp.CopyCurrentIrpStackLocationToNext();
irp.SetCompletionRoutineEx( DeviceObject, _CompletionRoutineForRemlockMaintenance, DeviceObject, TRUE, TRUE, TRUE );
irp.SetNextIrpStackLocation(); }
return STATUS_SUCCESS;}
_Must_inspect_result_NTSTATUSNTAPIFxDevice::DispatchWithLock( __in MdDeviceObject DeviceObject, __in MdIrp Irp ){ NTSTATUS status; FxIrp irp(Irp);
switch (_RequiresRemLock(irp.GetMajorFunction(), irp.GetMinorFunction())) {
case FxDeviceRemLockRequired: status = Mx::MxAcquireRemoveLock( &_GetFxWdmExtension(DeviceObject)->IoRemoveLock, Irp );
if (!NT_SUCCESS(status)) { irp.SetStatus(status); irp.CompleteRequest(IO_NO_INCREMENT);
return status; }
break;
case FxDeviceRemLockOptIn: status = _AcquireOptinRemoveLock( DeviceObject, Irp );
if (!NT_SUCCESS(status)) { irp.SetStatus(status); irp.CompleteRequest(IO_NO_INCREMENT);
return status; }
break;
case FxDeviceRemLockTestValid: // // Try to Acquire and Release the RemLock. If acquiring the lock // fails then it is not safe to process the IRP and the IRP should // be completed immediately. // status = Mx::MxAcquireRemoveLock( &_GetFxWdmExtension(DeviceObject)->IoRemoveLock, Irp );
if (!NT_SUCCESS(status)) { irp.SetStatus(status); irp.CompleteRequest(IO_NO_INCREMENT);
return status; }
Mx::MxReleaseRemoveLock( &_GetFxWdmExtension(DeviceObject)->IoRemoveLock, Irp ); break; }
return Dispatch(DeviceObject, Irp);}
_Must_inspect_result___inlineBOOLEANIsPreprocessIrp( __in MdIrp Irp, __in FxIrpPreprocessInfo* Info ){ UCHAR major, minor; BOOLEAN preprocess; FxIrp irp(Irp);
major = irp.GetMajorFunction(); minor = irp.GetMinorFunction();
preprocess = FALSE;
if (Info->Dispatch[major].EvtDevicePreprocess != NULL) { if (Info->Dispatch[major].NumMinorFunctions == 0) { // // If the driver is not interested in particular minor codes, // just give the irp to it. // preprocess = TRUE; } else { ULONG i;
// // Try to match up to a minor code. // for (i = 0; i < Info->Dispatch[major].NumMinorFunctions; i++) { if (Info->Dispatch[major].MinorFunctions[i] == minor) { preprocess = TRUE; break; } } } }
return preprocess;}
_Must_inspect_result___inlineNTSTATUSPreprocessIrp( __in FxDevice* Device, __in MdIrp Irp, __in FxIrpPreprocessInfo* Info, __in PVOID DispatchContext ){ NTSTATUS status; UCHAR major, minor; FxIrp irp(Irp);
major = irp.GetMajorFunction(); minor = irp.GetMinorFunction();
// // If this is a pnp remove irp, this object could be deleted by the time // EvtDevicePreprocess returns. To not touch freed pool, capture all // values we will need before preprocessing. //
if (Info->ClassExtension == FALSE) { status = Info->Dispatch[major].EvtDevicePreprocess( Device->GetHandle(), Irp); } else { status = Info->Dispatch[major].EvtCxDevicePreprocess( Device->GetHandle(), Irp, DispatchContext); }
// // If we got this far, we handed the irp off to EvtDevicePreprocess, so we // must now do our remlock maintainance if necessary. // if (FxDevice::_RequiresRemLock(major, minor) == FxDeviceRemLockRequired) { // // Keep the remove lock active until after we call into the driver. // If the driver redispatches the irp to the framework, we will // reacquire the remove lock at that point in time. // // Touching pDevObj after sending the pnp remove irp to the framework // is OK b/c we have acquired the remlock previously and that will // prevent this irp's processing racing with the pnp remove irp // processing. // Mx::MxReleaseRemoveLock(Device->GetRemoveLock(), Irp); }
return status;}
_Must_inspect_result___inlineNTSTATUSDispatchWorker( __in FxDevice* Device, __in MdIrp Irp, __in WDFCONTEXT DispatchContext ){ PLIST_ENTRY next; FxIrp irp(Irp);
next = (PLIST_ENTRY)DispatchContext;
ASSERT(NULL != DispatchContext && ((UCHAR)(ULONG_PTR)DispatchContext & FX_IN_DISPATCH_CALLBACK) == 0);
// // Check for any driver/class-extensions' preprocess requirements. // while (next != &Device->m_PreprocessInfoListHead) { FxIrpPreprocessInfo* info;
info = CONTAINING_RECORD(next, FxIrpPreprocessInfo, ListEntry);
// // Advance to next node. // next = next->Flink;
if (IsPreprocessIrp(Irp, info)) { return PreprocessIrp(Device, Irp, info, next); } }
// // No preprocess requirements, directly dispatch the IRP. // return Device->GetDispatchPackage( irp.GetMajorFunction() )->Dispatch(Irp);}
_Must_inspect_result_NTSTATUSNTAPIFxDevice::Dispatch( __in MdDeviceObject DeviceObject, __in MdIrp Irp ){ FxDevice* device = FxDevice::GetFxDevice(DeviceObject); return DispatchWorker(device, Irp, device->m_PreprocessInfoListHead.Flink);}
_Must_inspect_result_NTSTATUSFxDevice::DispatchPreprocessedIrp( __in MdIrp Irp, __in WDFCONTEXT DispatchContext ){ NTSTATUS status; UCHAR major, minor; FxIrp irp(Irp);
// // The contract for this DDI is just like IoCallDriver. The caller sets up // their stack location and then the DDI advances to the next stack location. // This means that the caller either has to call IoSkipCurrentIrpStackLocation // or IoCopyCurrentIrpStackLocationToNext before calling this DDI. // irp.SetNextIrpStackLocation();
major = irp.GetMajorFunction(); minor = irp.GetMinorFunction();
// // FxPkgPnp and FxWmiIrpHandler expect that there will be a remove lock // acquired for all power irps. We release the remlock when we called // Evt(Ext)DevicePreprocessIrp. // if (_RequiresRemLock(major, minor) == FxDeviceRemLockRequired) { status = Mx::MxAcquireRemoveLock( GetRemoveLock(), Irp );
if (!NT_SUCCESS(status)) { goto Done; } }
return DispatchWorker(this, Irp, DispatchContext);
Done: irp.SetStatus(status); irp.SetInformation(0); irp.CompleteRequest(IO_NO_INCREMENT);
return status;}
VOIDFxDevice::InstallPackage( __inout FxPackage *Package )
{ // // Add this package as an association on FxDevice // so its children get Dispose notifications. // // Note: This assumes a transfer of the controlling reference // count which it will dereference on FxDevice teardown. // We need to add an extra one here since packages have // an existing reference count model. // Package->AddRef(); Package->AssignParentObject(this);}
PVOIDFxDevice::AllocateRequestMemory( __in_opt PWDF_OBJECT_ATTRIBUTES RequestAttributes )/*++
Routine Description: Allocates enough memory for an FxRequest* plus any additonal memory required for the device's specific context memory.
If we are tracking memory, the allocation layout is 0x0 - FX_POOL_TRACKER 0x0 + sizeof(FX_POOL_TRACKER) - FX_POOL_HEADER 0x0 + sizeof(FX_POOL_TRACKER) + FX_POOL_HEADER_SIZE - start of FxRequest
if no tracking is occuring, the allocation layout is 0x0 - FX_POOL_HEADER 0x0 + FX_POOL_HEADER_SIZE - start of FxRequest
the total size is precomputed in m_RequestLookasideListElementSize during FxDevice::Initialize
Arguments: RequestAttributes - Attributes setting for the request.
Return Value: valid ptr or NULL
--*/
{ PFX_DRIVER_GLOBALS pGlobals; PFX_POOL_TRACKER pTracker; PFX_POOL_HEADER pHeader; PVOID ptr, pTrueBase;
pGlobals = GetDriverGlobals(); ptr = NULL;
if (IsPdo() && GetPdoPkg()->IsForwardRequestToParentEnabled()) { pTrueBase = FxAllocateFromNPagedLookasideListNoTracking(&m_RequestLookasideList); } else { pTrueBase = FxAllocateFromNPagedLookasideList(&m_RequestLookasideList, m_RequestLookasideListElementSize); }
if (pTrueBase != NULL) { if (pGlobals->IsPoolTrackingOn()) { pTracker = (PFX_POOL_TRACKER) pTrueBase; pHeader = WDF_PTR_ADD_OFFSET_TYPE(pTrueBase, sizeof(FX_POOL_TRACKER), PFX_POOL_HEADER);
// // Format and insert the Tracker in the NonPagedHeader list. // FxPoolInsertNonPagedAllocateTracker(&pGlobals->FxPoolFrameworks, pTracker, m_RequestLookasideListElementSize, pGlobals->Tag, _ReturnAddress()); } else { pHeader = (PFX_POOL_HEADER) pTrueBase; }
// // Common init // pHeader->Base = pTrueBase; pHeader->FxDriverGlobals = pGlobals;
ptr = &pHeader->AllocationStart[0];
if (RequestAttributes == NULL) { RequestAttributes = &m_RequestAttributes; }
ptr = FxObjectAndHandleHeaderInit( pGlobals, ptr, COMPUTE_OBJECT_SIZE(sizeof(FxRequest), 0), RequestAttributes, FxObjectTypeExternal );
#if FX_VERBOSE_TRACE DoTraceLevelMessage(pGlobals, TRACE_LEVEL_VERBOSE, TRACINGREQUEST, "Allocating FxRequest* %p, WDFREQUEST %p", ptr, _ToHandle((FxObject*) ptr));#endif return ptr; }
return NULL;}
VOIDFxDevice::FreeRequestMemory( __in FxRequest* Request ){ PFX_POOL_HEADER pHeader;
#if FX_VERBOSE_TRACE DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGREQUEST, "Free FxRequest* %p memory", Request);#endif
// // Remove the request from the list of outstanding requests against this // driver. // pHeader = FxObject::_CleanupPointer(GetDriverGlobals(), Request); if (IsPdo() && GetPdoPkg()->IsForwardRequestToParentEnabled()) { FxFreeToNPagedLookasideListNoTracking(&m_RequestLookasideList, pHeader->Base); } else { FxFreeToNPagedLookasideList(&m_RequestLookasideList, pHeader->Base); }}
_Must_inspect_result_NTSTATUSFxDevice::QueryInterface( __inout FxQueryInterfaceParams* Params ){ switch (Params->Type) { case FX_TYPE_DEVICE: *Params->Object = (FxDevice*) this; break;
default: return FxDeviceBase::QueryInterface(Params); // __super call }
return STATUS_SUCCESS;}
_Must_inspect_result_NTSTATUSFxDevice::AddIoTarget( __inout FxIoTarget* IoTarget ){ NTSTATUS status;
status = m_IoTargetsList.Add(GetDriverGlobals(), &IoTarget->m_TransactionedEntry);
if (NT_SUCCESS(status)) { IoTarget->m_AddedToDeviceList = TRUE; IoTarget->ADDREF(this); }
return status;}
VOIDFxDevice::RemoveIoTarget( __inout FxIoTarget* IoTarget ){ m_IoTargetsList.Remove(GetDriverGlobals(), &IoTarget->m_TransactionedEntry);
// // Assumes that the caller has its own reference on the IoTarget // IoTarget->RELEASE(this);}
_Must_inspect_result_NTSTATUSFxDevice::AllocateEnumInfo( VOID ){ if (IsPnp()) { return m_PkgPnp->AllocateEnumInfo(); } else { return STATUS_SUCCESS; }}
FxIoTarget*FxDevice::GetDefaultIoTarget( VOID ){ if (IsPnp() && IsFdo()) { return GetFdoPkg()->m_DefaultTarget; } else { return NULL; }}
FxIoTargetSelf*FxDevice::GetSelfIoTarget( VOID )/*++Routine Description: Returns the Self IO target for this FxDevice. Currently Self IO Target is supported only for a Pnp FDO. If the Self IO Target has not been established, it returns NULL.--*/{ if (IsPnp() && IsFdo()) { return GetFdoPkg()->m_SelfTarget; } else { return NULL; }}
_Must_inspect_result_NTSTATUSFxDevice::SetFilter( __in BOOLEAN Value ){ NTSTATUS status;
ASSERT(IsFdo());
status = m_PkgIo->SetFilter(Value);
if (NT_SUCCESS(status) && m_PkgPnp != NULL) { status = GetFdoPkg()->SetFilter(Value); }
if (NT_SUCCESS(status)) { m_Filter = Value; }
return status;}
VOIDFxDevice::SetFilterIoType( VOID ){ FxIoTarget * ioTarget; FxTransactionedEntry * targetsList = NULL;
ASSERT(IsFilter());
m_DeviceObject.SetFlags( m_DeviceObject.GetFlags() & ~(DO_BUFFERED_IO | DO_DIRECT_IO));
// // m_AttachedDevice can be NULL for UMDF, so check for NULL // if (m_AttachedDevice.GetObject() != NULL) { m_DeviceObject.SetFlags(m_DeviceObject.GetFlags() | (m_AttachedDevice.GetFlags() & (DO_BUFFERED_IO | DO_DIRECT_IO))); }
if (m_DeviceObject.GetFlags() & DO_BUFFERED_IO) { m_ReadWriteIoType = WdfDeviceIoBuffered; } else if (m_DeviceObject.GetFlags() & DO_DIRECT_IO) { m_ReadWriteIoType = WdfDeviceIoDirect; } else { m_ReadWriteIoType = WdfDeviceIoNeither; }
// // We also need to propagate these settings to any io targets that // have already been created //
m_IoTargetsList.LockForEnum(GetDriverGlobals());
targetsList = m_IoTargetsList.GetNextEntry(targetsList);
while (targetsList != NULL) {
ioTarget = (FxIoTarget *) targetsList->GetTransactionedObject();
if (ioTarget->GetTargetPDO() == GetPhysicalDevice()) { ioTarget->UpdateTargetIoType(); }
targetsList = m_IoTargetsList.GetNextEntry(targetsList); }
m_IoTargetsList.UnlockFromEnum(GetDriverGlobals());}
BOOLEANFxDevice::IsInterfaceRegistered( _In_ const GUID* InterfaceClassGUID, _In_opt_ PCUNICODE_STRING RefString ){ PSINGLE_LIST_ENTRY ple; BOOLEAN found = FALSE;
m_PkgPnp->m_DeviceInterfaceLock.AcquireLock(GetDriverGlobals());
// // Iterate over the interfaces and see if we have a match // for (ple = m_PkgPnp->m_DeviceInterfaceHead.Next; ple != NULL; ple = ple->Next) { FxDeviceInterface *pDI;
pDI = FxDeviceInterface::_FromEntry(ple);
if (FxIsEqualGuid(&pDI->m_InterfaceClassGUID, InterfaceClassGUID)) { if (RefString != NULL) { if ((RefString->Length == pDI->m_ReferenceString.Length) && (RtlCompareMemory(RefString->Buffer, pDI->m_ReferenceString.Buffer, RefString->Length) == RefString->Length)) { // // They match, carry on // DO_NOTHING(); } else { // // The ref strings do not match, continue on in the search // of the collection. // continue; } } else if (pDI->m_ReferenceString.Length > 0) { // // Caller didn't specify a ref string but this interface has // one, continue on in the search through the collection. // continue; }
// // Set the state and break out of the loop because we found our // interface. // found = TRUE; break; } }
m_PkgPnp->m_DeviceInterfaceLock.ReleaseLock(GetDriverGlobals());
return found;}
_Must_inspect_result_NTSTATUSFxDevice::_AllocAndQueryProperty( _In_ PFX_DRIVER_GLOBALS Globals, _In_opt_ PWDFDEVICE_INIT DeviceInit, _In_opt_ FxDevice* Device, _In_opt_ MdDeviceObject RemotePdo, _In_ DEVICE_REGISTRY_PROPERTY DeviceProperty, _In_ POOL_TYPE PoolType, _In_opt_ PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes, _Out_ WDFMEMORY* PropertyMemory ){ FxMemoryObject* pMemory; NTSTATUS status; ULONG length = 0;
status = FxDevice::_QueryProperty(Globals, DeviceInit, Device, RemotePdo, DeviceProperty, 0, NULL, &length); if (status != STATUS_BUFFER_TOO_SMALL) { DoTraceLevelMessage(Globals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "Could not retrieve property %d length, %!STATUS!", DeviceProperty, status); _Analysis_assume_(!NT_SUCCESS(status)); return status; }
status = FxMemoryObject::_Create(Globals, PropertyMemoryAttributes, PoolType, Globals->Tag, length, &pMemory); if (!NT_SUCCESS(status)) { DoTraceLevelMessage(Globals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "Could not allocate WDFMEMORY, %!STATUS!", status); return status; }
status = FxDevice::_QueryProperty(Globals, DeviceInit, Device, RemotePdo, DeviceProperty, length, pMemory->GetBuffer(), &length); if (!NT_SUCCESS(status)) { DoTraceLevelMessage(Globals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "Could not query for full buffer, size %d, for " "property %d, %!STATUS!", length, DeviceProperty, status); pMemory->DeleteObject(); return status; }
status = pMemory->Commit(PropertyMemoryAttributes, (WDFOBJECT*)PropertyMemory);
if (!NT_SUCCESS(status)) { DoTraceLevelMessage(Globals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "Could not commit memory object, %!STATUS!", status); pMemory->DeleteObject(); }
return status;}
_Must_inspect_result_NTSTATUSFxDevice::_AllocAndQueryPropertyEx( _In_ PFX_DRIVER_GLOBALS DriverGlobals, _In_opt_ PWDFDEVICE_INIT DeviceInit, _In_opt_ FxDevice* Device, _In_ PVOID PropertyData, _In_ FxPropertyType FxPropertyType, _In_ POOL_TYPE PoolType, _In_opt_ PWDF_OBJECT_ATTRIBUTES PropertyMemoryAttributes, _Out_ WDFMEMORY* PropertyMemory, _Out_ PDEVPROPTYPE PropertyType ){ FxMemoryObject* pMemory; NTSTATUS status; ULONG length = 0; DEVPROPTYPE propType; ULONG requiredLength;
status = FxDevice::_QueryPropertyEx(DriverGlobals, DeviceInit, Device, PropertyData, FxPropertyType, 0, NULL, &requiredLength, &propType); if (status != STATUS_BUFFER_TOO_SMALL) { DoTraceLevelMessage(DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, "Could not retrieve property, %!STATUS!", status); _Analysis_assume_(!NT_SUCCESS(status)); return status; }
*PropertyMemory = NULL; *PropertyType = 0;
length = requiredLength; status = FxMemoryObject::_Create(DriverGlobals, PropertyMemoryAttributes, PoolType, DriverGlobals->Tag, length, &pMemory); if (!NT_SUCCESS(status)) { DoTraceLevelMessage(DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, "Could not allocate WDFMEMORY, %!STATUS!", status); return status; }
status = FxDevice::_QueryPropertyEx(DriverGlobals, DeviceInit, Device, PropertyData, FxPropertyType, length, pMemory->GetBuffer(), &requiredLength, &propType); if (!NT_SUCCESS(status)) { DoTraceLevelMessage(DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, "Could not query for full buffer, size %d, for " "property, %!STATUS!", length, status); pMemory->DeleteObject(); return status; }
status = pMemory->Commit(PropertyMemoryAttributes, (WDFOBJECT*)PropertyMemory);
if (!NT_SUCCESS(status)) { DoTraceLevelMessage(DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, "Could not commit memory object, %!STATUS!", status); pMemory->DeleteObject(); } else { *PropertyMemory = pMemory->GetHandle(); *PropertyType = propType; }
return status;}
_Must_inspect_result_NTSTATUSFxDevice::_ValidateOpenKeyParams( _In_ PFX_DRIVER_GLOBALS FxDriverGlobals, _In_opt_ PWDFDEVICE_INIT DeviceInit, _In_opt_ FxDevice* Device ){ NTSTATUS status = STATUS_SUCCESS;
// // This function should be called with exactly one valid WDFDEVICE_INIT // or one valid FxDevice object. Supplying neither or both is an error. // if ((DeviceInit == NULL && Device == NULL) || (DeviceInit != NULL && Device != NULL)) {
status = STATUS_INVALID_PARAMETER; DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "Device OpenKey/QueryProperty was called with invalid " "DeviceInit and Device parameters, %!STATUS!", status); FxVerifierDbgBreakPoint(FxDriverGlobals); }
return status;}