2020-09-24 20:51:15 +00:00
|
|
|
/*++
|
|
|
|
|
|
|
|
Copyright (c) Microsoft Corporation
|
|
|
|
|
|
|
|
Module Name:
|
|
|
|
|
|
|
|
FxDriver.cpp
|
|
|
|
|
|
|
|
Abstract:
|
|
|
|
|
|
|
|
This is the main driver framework.
|
|
|
|
|
|
|
|
Author:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Environment:
|
|
|
|
|
|
|
|
Both kernel and user mode
|
|
|
|
|
|
|
|
Revision History:
|
|
|
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
#include "coreprivshared.hpp"
|
|
|
|
#include "fxiotarget.hpp"
|
|
|
|
|
|
|
|
// Tracing support
|
|
|
|
extern "C" {
|
2020-10-16 03:30:51 +00:00
|
|
|
// #include "FxDriver.tmh"
|
2020-09-24 20:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
FxDriver::FxDriver(
|
|
|
|
__in MdDriverObject ArgDriverObject,
|
|
|
|
__in PWDF_DRIVER_CONFIG DriverConfig,
|
|
|
|
__in PFX_DRIVER_GLOBALS FxDriverGlobals
|
|
|
|
) :
|
|
|
|
FxNonPagedObject(FX_TYPE_DRIVER, sizeof(FxDriver), FxDriverGlobals),
|
|
|
|
m_DriverObject(ArgDriverObject),
|
|
|
|
m_CallbackMutexLock(FxDriverGlobals)
|
|
|
|
{
|
|
|
|
RtlInitUnicodeString(&m_RegistryPath, NULL);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
|
|
|
|
m_ExecutionLevel = WdfExecutionLevelDispatch;
|
|
|
|
#else
|
|
|
|
m_ExecutionLevel = WdfExecutionLevelPassive;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
m_SynchronizationScope = WdfSynchronizationScopeNone;
|
|
|
|
|
|
|
|
m_CallbackLockPtr = NULL;
|
|
|
|
m_CallbackLockObjectPtr = NULL;
|
|
|
|
|
|
|
|
m_DisposeList = NULL;
|
|
|
|
|
|
|
|
//
|
|
|
|
// These are initialized up front so that sub objects
|
|
|
|
// can have the right configuration
|
|
|
|
//
|
|
|
|
WDF_DRIVER_CONFIG_INIT(&m_Config, NULL);
|
|
|
|
|
|
|
|
// Only copy the smallest of what is specified and our size
|
|
|
|
RtlCopyMemory(&m_Config, DriverConfig, min(sizeof(m_Config), DriverConfig->Size) );
|
|
|
|
|
|
|
|
m_DebuggerConnected = FALSE;
|
|
|
|
|
|
|
|
#if FX_IS_USER_MODE
|
|
|
|
m_DriverParametersKey = NULL;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
FxDriver::~FxDriver()
|
|
|
|
{
|
|
|
|
// Make it always present right now even on free builds
|
|
|
|
if (IsDisposed() == FALSE) {
|
|
|
|
DoTraceLevelMessage(
|
|
|
|
GetDriverGlobals(), TRACE_LEVEL_FATAL, TRACINGDRIVER,
|
|
|
|
"FxDriver 0x%p not disposed: this maybe a driver reference count "
|
|
|
|
"problem with WDFDRIVER 0x%p", this, GetObjectHandleUnchecked());
|
|
|
|
|
|
|
|
FxVerifierBugCheck(GetDriverGlobals(),
|
|
|
|
WDF_OBJECT_ERROR,
|
|
|
|
(ULONG_PTR) GetObjectHandleUnchecked(),
|
|
|
|
(ULONG_PTR) this);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Free the memory for the registry path if required.
|
|
|
|
//
|
|
|
|
if (m_RegistryPath.Buffer) {
|
|
|
|
FxPoolFree(m_RegistryPath.Buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_DisposeList != NULL) {
|
|
|
|
m_DisposeList->DeleteObject();
|
|
|
|
}
|
|
|
|
|
|
|
|
#if FX_IS_USER_MODE
|
|
|
|
//
|
|
|
|
// Close the R/W handle to the driver's service parameters key
|
|
|
|
// that we opened during Initialize.
|
|
|
|
//
|
|
|
|
if (m_DriverParametersKey != NULL) {
|
|
|
|
NTSTATUS status = FxRegKey::_Close(m_DriverParametersKey);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDRIVER,
|
|
|
|
"Cannot close Driver Parameters key %!STATUS!",
|
|
|
|
status);
|
|
|
|
}
|
|
|
|
m_DriverParametersKey = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// The host-created driver object holds a reference to this
|
|
|
|
// FxDriver object. Clear it, since this object was deleted.
|
|
|
|
//
|
|
|
|
ClearDriverObjectFxDriver();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
|
|
FxDriver::Dispose(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (m_DisposeList != NULL) {
|
|
|
|
m_DisposeList->WaitForEmpty();
|
|
|
|
}
|
|
|
|
|
2020-10-16 03:30:51 +00:00
|
|
|
return FxNonPagedObject::Dispose(); // __super call
|
2020-09-24 20:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FxDriver::Unload(
|
|
|
|
__in MdDriverObject DriverObject
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
|
|
|
FxDriver *pDriver;
|
|
|
|
|
|
|
|
pDriver = FxDriver::GetFxDriver(DriverObject);
|
|
|
|
if (pDriver == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pFxDriverGlobals = pDriver->GetDriverGlobals();
|
|
|
|
|
|
|
|
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGDRIVER,
|
|
|
|
"Unloading WDFDRIVER %p, PDRIVER_OBJECT_UM %p",
|
|
|
|
pDriver->GetHandle(), DriverObject);
|
|
|
|
//
|
|
|
|
// Invoke the driver if they specified an unload routine.
|
|
|
|
//
|
|
|
|
if (pDriver->m_DriverUnload.Method) {
|
|
|
|
pDriver->m_DriverUnload.Invoke(pDriver->GetHandle());
|
|
|
|
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGDRIVER,
|
|
|
|
"Driver unload routine Exit WDFDRIVER %p, PDRIVER_OBJECT_UM %p",
|
|
|
|
pDriver->GetHandle(), DriverObject);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Delete the FxDriver object.
|
|
|
|
//
|
|
|
|
// This releases the FxDriver reference. Must be called at PASSIVE
|
|
|
|
//
|
|
|
|
pDriver->DeleteObject();
|
|
|
|
|
|
|
|
pFxDriverGlobals->Driver = NULL;
|
|
|
|
|
|
|
|
FxDestroy(pFxDriverGlobals);
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FxDriver::_InitializeDriverName(
|
|
|
|
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
|
|
|
__in PCUNICODE_STRING RegistryPath
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
Create a CHAR version of the service name contained in RegistryPath.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
RegistryPath - the path to the service name in the registry.
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PWCHAR pCur, pBegin, pEnd;
|
|
|
|
|
|
|
|
RtlZeroMemory(&FxDriverGlobals->Public.DriverName[0],
|
|
|
|
sizeof(FxDriverGlobals->Public.DriverName) );
|
|
|
|
|
|
|
|
if (RegistryPath == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pBegin = RegistryPath->Buffer;
|
|
|
|
|
|
|
|
//
|
|
|
|
// pEnd is one past the end of the string, while pCur is a pointer to the
|
|
|
|
// last character of the string. We will decrement pCur down towards the
|
|
|
|
// beginning of the string.
|
|
|
|
//
|
|
|
|
pEnd = pBegin + (RegistryPath->Length / sizeof(WCHAR));
|
|
|
|
pCur = pEnd - 1;
|
|
|
|
|
|
|
|
for ( ; *pCur != L'\\' && pCur != pBegin; pCur--) {
|
|
|
|
DO_NOTHING();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pCur != pBegin && *pCur == L'\\') {
|
|
|
|
size_t regLen;
|
|
|
|
ULONG i;
|
|
|
|
|
|
|
|
pCur++;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Can't use wcslen becuase this is a UNICODE_STRING which means that it
|
|
|
|
// does not necessarily have a terminating NULL in the buffer.
|
|
|
|
//
|
|
|
|
regLen = pEnd - pCur;
|
|
|
|
if (regLen > WDF_DRIVER_GLOBALS_NAME_LEN-1) {
|
|
|
|
regLen = WDF_DRIVER_GLOBALS_NAME_LEN-1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < regLen; i++) {
|
|
|
|
FxDriverGlobals->Public.DriverName[i] = (CHAR) pCur[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
#if FX_CORE_MODE==FX_CORE_KERNEL_MODE
|
|
|
|
status = RtlStringCbCopyA(FxDriverGlobals->Public.DriverName,
|
|
|
|
sizeof(FxDriverGlobals->Public.DriverName),
|
|
|
|
"WDF");
|
|
|
|
#else // USER_MODE
|
|
|
|
HRESULT hr;
|
|
|
|
hr = StringCbCopyA(FxDriverGlobals->Public.DriverName,
|
|
|
|
sizeof(FxDriverGlobals->Public.DriverName),
|
|
|
|
"WDF");
|
|
|
|
if (HRESULT_FACILITY(hr) == FACILITY_WIN32) {
|
|
|
|
status = WinErrorToNtStatus(HRESULT_CODE(hr));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
status = SUCCEEDED(hr) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
UNREFERENCED_PARAMETER(status);
|
|
|
|
ASSERT(NT_SUCCESS(status));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FxDriver::_InitializeTag(
|
|
|
|
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
|
|
|
__in PWDF_DRIVER_CONFIG Config
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
Tries to create a tag for the driver based off of its name. This tag is
|
|
|
|
used for allocations made on behalf of the driver so that it is easier to
|
|
|
|
track which allocations belong to which image.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
Config - driver writer provided config. in the future, may contain a tag
|
|
|
|
value in it
|
|
|
|
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PCHAR pBegin;
|
|
|
|
size_t length;
|
|
|
|
|
|
|
|
UNREFERENCED_PARAMETER(Config);
|
|
|
|
|
|
|
|
length = strlen(FxDriverGlobals->Public.DriverName);
|
|
|
|
pBegin = &FxDriverGlobals->Public.DriverName[0];
|
|
|
|
|
|
|
|
if (length >= 3) {
|
|
|
|
//
|
|
|
|
// If the driver name begins with "WDF" (case insensitive), start after
|
|
|
|
// "WDF"
|
|
|
|
//
|
|
|
|
if ((pBegin[0] == 'w' || pBegin[0] == 'W') &&
|
|
|
|
(pBegin[1] == 'd' || pBegin[1] == 'D') &&
|
|
|
|
(pBegin[2] == 'f' || pBegin[2] == 'F')) {
|
|
|
|
length -=3;
|
|
|
|
pBegin += 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (length <= 2) {
|
|
|
|
//
|
|
|
|
// 2 or less characters is not a unique enough tag, just use the default
|
|
|
|
// tag.
|
|
|
|
//
|
|
|
|
FxDriverGlobals->Tag = FX_TAG;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
if (length > sizeof(ULONG)) {
|
|
|
|
length = sizeof(ULONG);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// This copies the bytes in the right order (so that they appear correct
|
|
|
|
// when dumped as a sequence of chars)
|
|
|
|
//
|
|
|
|
RtlCopyMemory(&FxDriverGlobals->Tag,
|
|
|
|
pBegin,
|
|
|
|
length);
|
|
|
|
|
|
|
|
FxDriverGlobals->Public.DriverTag = FxDriverGlobals->Tag;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_Must_inspect_result_
|
|
|
|
NTSTATUS
|
|
|
|
FxDriver::Initialize(
|
|
|
|
__in PCUNICODE_STRING ArgRegistryPath,
|
|
|
|
__in PWDF_DRIVER_CONFIG Config,
|
|
|
|
__in_opt PWDF_OBJECT_ATTRIBUTES DriverAttributes
|
|
|
|
)
|
|
|
|
{
|
|
|
|
PFX_DRIVER_GLOBALS FxDriverGlobals = GetDriverGlobals();
|
|
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
// WDFDRIVER can not be deleted by the device driver
|
|
|
|
MarkNoDeleteDDI();
|
|
|
|
|
|
|
|
MarkDisposeOverride(ObjectDoNotLock);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Configure Constraints
|
|
|
|
//
|
|
|
|
ConfigureConstraints(DriverAttributes);
|
|
|
|
|
|
|
|
if (m_DriverObject.GetObject() == NULL) {
|
|
|
|
return STATUS_UNSUCCESSFUL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allocate FxDisposeList
|
|
|
|
status = FxDisposeList::_Create(FxDriverGlobals, m_DriverObject.GetObject(), &m_DisposeList);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Store FxDriver in Driver object extension
|
|
|
|
//
|
|
|
|
status = AllocateDriverObjectExtensionAndStoreFxDriver();
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Store away the callback functions.
|
|
|
|
//
|
|
|
|
if ((Config->DriverInitFlags & WdfDriverInitNoDispatchOverride) == 0) {
|
|
|
|
//
|
|
|
|
// Caller doesn't want to override the dispatch table. That
|
|
|
|
// means that they want to create everything and still be in
|
|
|
|
// control (or at least the port driver will take over)
|
|
|
|
//
|
|
|
|
m_DriverDeviceAdd.Method = Config->EvtDriverDeviceAdd;
|
|
|
|
m_DriverUnload.Method = Config->EvtDriverUnload;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ArgRegistryPath != NULL) {
|
|
|
|
USHORT length;
|
|
|
|
|
|
|
|
length = ArgRegistryPath->Length + sizeof(UNICODE_NULL);
|
|
|
|
|
|
|
|
m_RegistryPath.Length = ArgRegistryPath->Length;
|
|
|
|
m_RegistryPath.MaximumLength = length;
|
|
|
|
m_RegistryPath.Buffer = (PWSTR) FxPoolAllocate(
|
|
|
|
GetDriverGlobals(), PagedPool, length);
|
|
|
|
|
|
|
|
if (m_RegistryPath.Buffer != NULL) {
|
|
|
|
RtlCopyMemory(m_RegistryPath.Buffer,
|
|
|
|
ArgRegistryPath->Buffer,
|
|
|
|
ArgRegistryPath->Length);
|
|
|
|
|
|
|
|
//
|
|
|
|
// other parts of WDF assumes m_RegistryPath.Buffer is
|
|
|
|
// a null terminated string. make sure it is.
|
|
|
|
//
|
|
|
|
m_RegistryPath.Buffer[length/sizeof(WCHAR)- 1] = UNICODE_NULL;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
//
|
|
|
|
// We failed to allocate space for the registry path
|
|
|
|
// so set the length to 0.
|
|
|
|
//
|
|
|
|
m_RegistryPath.Length = 0;
|
|
|
|
m_RegistryPath.MaximumLength = 0;
|
|
|
|
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
if ((Config->DriverInitFlags & WdfDriverInitNoDispatchOverride) == 0) {
|
|
|
|
UCHAR i;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Set up dispatch routines.
|
|
|
|
//
|
|
|
|
if (Config->DriverInitFlags & WdfDriverInitNonPnpDriver) {
|
|
|
|
//
|
|
|
|
// NT4 style drivers must clear the AddDevice field in the
|
|
|
|
// driver object so that they can be unloaded while still
|
|
|
|
// having device objects around.
|
|
|
|
//
|
|
|
|
// If AddDevice is set, NT considers the driver a pnp driver
|
|
|
|
// and will not allow net stop to unload the driver.
|
|
|
|
//
|
|
|
|
m_DriverObject.SetDriverExtensionAddDevice(NULL);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Unload for an NT4 driver is still optional if the driver
|
|
|
|
// does not want to be stopped (through net stop for
|
|
|
|
// instance).
|
|
|
|
//
|
|
|
|
if (Config->EvtDriverUnload != NULL) {
|
|
|
|
m_DriverObject.SetDriverUnload(Unload);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_DriverObject.SetDriverUnload(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
//
|
|
|
|
// PnP driver, set our routines up
|
|
|
|
//
|
|
|
|
m_DriverObject.SetDriverExtensionAddDevice(AddDevice);
|
|
|
|
m_DriverObject.SetDriverUnload(Unload);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// For any major control code that we use a remove lock, the
|
|
|
|
// following locations must be updated:
|
|
|
|
//
|
|
|
|
// 1) FxDevice::_RequiresRemLock() which decides if the remlock
|
|
|
|
// is required
|
|
|
|
// 2) FxDefaultIrpHandler::Dispatch might need to be changed if
|
|
|
|
// there is catchall generic post processing that must be done
|
|
|
|
// 3) Whereever the major code irp handler completes the irp or
|
|
|
|
// sends it down the stack. A good design would have all
|
|
|
|
// spots in the irp handler where this is done to call a
|
|
|
|
// common function.
|
|
|
|
//
|
|
|
|
WDFCASSERT(IRP_MN_REMOVE_DEVICE != 0x0);
|
|
|
|
|
|
|
|
#if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE))
|
|
|
|
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
|
|
|
|
if (FxDevice::_RequiresRemLock(i, 0x0) == FxDeviceRemLockNotRequired) {
|
|
|
|
m_DriverObject.SetMajorFunction(i, FxDevice::Dispatch);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_DriverObject.SetMajorFunction(i, FxDevice::DispatchWithLock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else // USER_MODE
|
|
|
|
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
|
|
|
|
if (FxDevice::_RequiresRemLock(i, 0x0) == FxDeviceRemLockNotRequired) {
|
|
|
|
m_DriverObject.SetMajorFunction(i, FxDevice::DispatchUm);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_DriverObject.SetMajorFunction(i, FxDevice::DispatchWithLockUm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Determine if the debugger is connected.
|
|
|
|
//
|
|
|
|
#if ((FX_CORE_MODE)==(FX_CORE_KERNEL_MODE))
|
|
|
|
if (KD_DEBUGGER_ENABLED == TRUE && KD_DEBUGGER_NOT_PRESENT == FALSE) {
|
|
|
|
m_DebuggerConnected = TRUE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//
|
|
|
|
// Log this notable event after tracing has been initialized.
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ((Config->DriverInitFlags & WdfDriverInitNonPnpDriver) &&
|
|
|
|
Config->EvtDriverUnload == NULL) {
|
|
|
|
|
|
|
|
DoTraceLevelMessage(
|
|
|
|
FxDriverGlobals, TRACE_LEVEL_INFORMATION, TRACINGDRIVER,
|
|
|
|
"Driver Object %p, reg path %wZ cannot be "
|
|
|
|
"unloaded, no DriverUnload routine specified",
|
|
|
|
m_DriverObject.GetObject(), &m_RegistryPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if FX_IS_USER_MODE
|
|
|
|
//
|
|
|
|
// Open a R/W handle to the driver's service parameters key
|
|
|
|
//
|
|
|
|
status = OpenParametersKey();
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
DoTraceLevelMessage(
|
|
|
|
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDRIVER,
|
|
|
|
"Cannot open Driver Parameters key %!STATUS!",
|
|
|
|
status);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
_Must_inspect_result_
|
|
|
|
FxString *
|
|
|
|
FxDriver::GetRegistryPath(
|
|
|
|
VOID
|
|
|
|
)
|
|
|
|
{
|
|
|
|
FxString *pString;
|
|
|
|
|
|
|
|
pString = new(GetDriverGlobals(), WDF_NO_OBJECT_ATTRIBUTES)
|
|
|
|
FxString(GetDriverGlobals());
|
|
|
|
|
|
|
|
if (pString != NULL) {
|
|
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
status = pString->Assign(m_RegistryPath.Buffer);
|
|
|
|
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
pString->Release();
|
|
|
|
pString = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return pString;
|
|
|
|
}
|
|
|
|
|
2021-06-11 12:29:21 +00:00
|
|
|
|
2020-09-24 20:51:15 +00:00
|
|
|
VOID
|
|
|
|
FxDriver::ConfigureConstraints(
|
|
|
|
__in_opt PWDF_OBJECT_ATTRIBUTES DriverAttributes
|
|
|
|
)
|
|
|
|
/*++
|
|
|
|
|
|
|
|
Routine Description:
|
|
|
|
|
|
|
|
Determine the pointer to the proper lock to acquire
|
|
|
|
for event callbacks from the FxDriver to the device driver
|
|
|
|
depending on the configured locking model.
|
|
|
|
|
|
|
|
Arguments:
|
|
|
|
DriverAttributes - caller supplied scope and level, used only if they
|
|
|
|
are not InheritFromParent.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
BOOLEAN automaticLockingRequired;
|
|
|
|
|
|
|
|
automaticLockingRequired = FALSE;
|
|
|
|
|
|
|
|
// Initialize the mutex lock
|
|
|
|
m_CallbackMutexLock.Initialize(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MarkPassiveCallbacks(ObjectDoNotLock);
|
|
|
|
|
|
|
|
m_CallbackLockPtr = &m_CallbackMutexLock;
|
|
|
|
m_CallbackLockObjectPtr = this;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Use the caller supplied scope and level only if they are not
|
|
|
|
// InheritFromParent.
|
|
|
|
//
|
|
|
|
if (DriverAttributes != NULL) {
|
|
|
|
|
|
|
|
if (DriverAttributes->ExecutionLevel !=
|
|
|
|
WdfExecutionLevelInheritFromParent) {
|
|
|
|
m_ExecutionLevel = DriverAttributes->ExecutionLevel;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DriverAttributes->SynchronizationScope !=
|
|
|
|
WdfSynchronizationScopeInheritFromParent) {
|
|
|
|
m_SynchronizationScope = DriverAttributes->SynchronizationScope;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// If the driver asks for any synchronization, we synchronize the
|
|
|
|
// WDFDRIVER object's own callbacks as well.
|
|
|
|
//
|
|
|
|
// (No option to extend synchronization for regular operations
|
|
|
|
// across all WDFDEVICE objects)
|
|
|
|
//
|
|
|
|
if (m_SynchronizationScope == WdfSynchronizationScopeDevice ||
|
|
|
|
m_SynchronizationScope == WdfSynchronizationScopeQueue) {
|
|
|
|
|
|
|
|
automaticLockingRequired = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// No FxDriver events are delivered from a thread that is
|
|
|
|
// not already at PASSIVE_LEVEL, so we don't need to
|
|
|
|
// allocate an FxSystemWorkItem if the execution level
|
|
|
|
// constraint is WdfExecutionLevelPassive.
|
|
|
|
//
|
|
|
|
// If any events are added FxDriver that could occur on a thread
|
|
|
|
// that is above PASSIVE_LEVEL, then an FxSystemWorkItem would
|
|
|
|
// need to be allocated to deliver those events similar to the
|
|
|
|
// code in FxIoQueue.
|
|
|
|
//
|
|
|
|
|
|
|
|
//
|
|
|
|
// Configure FxDriver event callback locks
|
|
|
|
//
|
|
|
|
if (automaticLockingRequired) {
|
|
|
|
m_DriverDeviceAdd.SetCallbackLockPtr(m_CallbackLockPtr);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
m_DriverDeviceAdd.SetCallbackLockPtr(NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|