Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified Dmf/Documentation/Driver Module Framework.docx
Binary file not shown.
17 changes: 9 additions & 8 deletions Dmf/Framework/DmfCall.c
Original file line number Diff line number Diff line change
Expand Up @@ -2302,12 +2302,6 @@ Return Value:

ntStatus = STATUS_SUCCESS;

DMF_ModuleLock(DmfModule);

parentDmfObject->ReferenceCount = 1;

DMF_ModuleUnlock(DmfModule);

if (!DMF_IsObjectTypeOpenNotify(parentDmfObject))
{
// Dispatch callback to Child DMF Modules first.
Expand Down Expand Up @@ -2344,6 +2338,15 @@ Return Value:
goto Exit;
}

// Allow DMF_ModuleReference to succeed only after the Module is completely open.
//
DMF_ModuleLock(DmfModule);

ASSERT(parentDmfObject->ReferenceCount == 0);
parentDmfObject->ReferenceCount = 1;

DMF_ModuleUnlock(DmfModule);

Exit:

return ntStatus;
Expand Down Expand Up @@ -2606,8 +2609,6 @@ Return Value:

parentDmfObject = DMF_ModuleToObject(DmfModule);

DMF_ModuleWaitForReferenceCountToClear(DmfModule);

// Dispatch callback to this Module first.
//
ASSERT(parentDmfObject->InternalCallbacksDmf.DeviceClose != NULL);
Expand Down
6 changes: 3 additions & 3 deletions Dmf/Framework/DmfDefinitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ extern "C"
#endif // defined(DMF_USER_MODE)
#include <hidusage.h>
#include <hidpi.h>
#include <devpkey.h>

////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
Expand Down Expand Up @@ -501,7 +502,7 @@ DmfDriverContextCleanup(
_In_ WDFOBJECT DriverObject \
) \
{ \
WPP_CLEANUP(DriverObject); \
WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject)); \
} \
\

Expand Down Expand Up @@ -669,8 +670,7 @@ DmfDriverContextCleanup(
_In_ WDFOBJECT DriverObject \
) \
{ \
UNREFERENCED_PARAMETER(DriverObject); \
WPP_CLEANUP(DriverObject); \
WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject)); \
} \

#else
Expand Down
5 changes: 5 additions & 0 deletions Dmf/Framework/DmfIncludeInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1295,6 +1295,11 @@ DMF_Module_CloseOnDestroy(
_In_ DMFMODULE DmfModule
);

VOID
DMF_ModuleWaitForReferenceCountToClear(
_In_ DMFMODULE DmfModule
);

// DmfContainer.c
//

Expand Down
5 changes: 5 additions & 0 deletions Dmf/Framework/DmfInternal.c
Original file line number Diff line number Diff line change
Expand Up @@ -1640,6 +1640,11 @@ Return Value:
dmfObject->NeedToCallPreClose = FALSE;
}

// Now that PreClose is done, wait for reference count to clear and close the Module.
// This allows PreClose to access Module Methods if needed.
//
DMF_ModuleWaitForReferenceCountToClear(DmfModule);

dmfObject->ModuleState = ModuleState_Closing;

ASSERT(dmfObject->ModuleDescriptor.CallbacksDmf->DeviceClose != NULL);
Expand Down
136 changes: 136 additions & 0 deletions Dmf/Framework/Modules.Core/Dmf_IoctlHandler.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ typedef struct
// It is a collection of all the Open File Objects that are running "As Administrator".
//
WDFCOLLECTION AdministratorFileObjectsCollection;
IoctlHandler_IO_SET_DEVICE_INTERFACE_PROPERTY_DATA* IoSetDeviceInterfacePropertyData;
} DMF_CONTEXT_IoctlHandler;

// This macro declares the following function:
Expand All @@ -58,6 +59,132 @@ DMF_MODULE_DECLARE_CONFIG(IoctlHandler)
///////////////////////////////////////////////////////////////////////////////////////////////////////
//

#if !defined(DMF_USER_MODE)

#pragma code_seg("PAGE")
static
_Must_inspect_result_
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS
IoctlHandler_PostDeviceInterfaceCreate(
_In_ DMFMODULE DmfModule
)
{
NTSTATUS ntStatus;
DMF_CONTEXT_IoctlHandler* moduleContext;
DMF_CONFIG_IoctlHandler* moduleConfig;
WDFDEVICE device;
UNICODE_STRING symbolicLinkName;
WDFSTRING symbolicLinkNameString;
DEVPROP_BOOLEAN isRestricted;
UNICODE_STRING functionName;

ntStatus = STATUS_SUCCESS;
moduleContext = DMF_CONTEXT_GET(DmfModule);
moduleConfig = DMF_CONFIG_GET(DmfModule);
device = DMF_ParentDeviceGet(DmfModule);
symbolicLinkNameString = NULL;

// If possible, get the IoSetDeviceInterfacePropertyData.
//
RtlInitUnicodeString(&functionName, L"IoSetDeviceInterfacePropertyData");
moduleContext->IoSetDeviceInterfacePropertyData = (IoctlHandler_IO_SET_DEVICE_INTERFACE_PROPERTY_DATA*)(ULONG_PTR)MmGetSystemRoutineAddress(&functionName);

// If the Client has set the IsRestricted or CustomProperty fields, try to set those properties.
//
if ((moduleContext->IoSetDeviceInterfacePropertyData != NULL) &&
((moduleConfig->IsRestricted) ||
(moduleConfig->CustomCapabilities != NULL)))
{
ntStatus = WdfStringCreate(NULL,
WDF_NO_OBJECT_ATTRIBUTES,
&symbolicLinkNameString);
if (!NT_SUCCESS(ntStatus))
{
TraceEvents(TRACE_LEVEL_ERROR, DMF_TRACE_IoctlHandler, "WdfStringCreate fails: ntStatus=%!STATUS!", ntStatus);
goto Exit;
}

ntStatus = WdfDeviceRetrieveDeviceInterfaceString(device,
&moduleConfig->DeviceInterfaceGuid,
NULL,
symbolicLinkNameString);
if (!NT_SUCCESS(ntStatus))
{
TraceEvents(TRACE_LEVEL_ERROR, DMF_TRACE_IoctlHandler, "WdfDeviceRetrieveDeviceInterfaceString fails: ntStatus=%!STATUS!", ntStatus);
goto Exit;
}

WdfStringGetUnicodeString(symbolicLinkNameString,
&symbolicLinkName);

isRestricted = moduleConfig->IsRestricted;

ntStatus = moduleContext->IoSetDeviceInterfacePropertyData(&symbolicLinkName,
&DEVPKEY_DeviceInterface_Restricted,
0,
0,
DEVPROP_TYPE_BOOLEAN,
sizeof(isRestricted),
&isRestricted );
if (!NT_SUCCESS(ntStatus))
{
TraceEvents(TRACE_LEVEL_ERROR, DMF_TRACE_IoctlHandler, "IoSetDeviceInterfacePropertyData fails: ntStatus=%!STATUS!", ntStatus);
goto Exit;
}

#if defined(NTDDI_WIN10_RS2) && (NTDDI_VERSION >= NTDDI_WIN10_RS2)
if (moduleConfig->CustomCapabilities != NULL)
{
// Adds a custom capability to device interface instance that allows a Windows
// Store device app to access this interface using Windows.Devices.Custom namespace.

// Get size of buffer. Add space for double \0 terminator.
//
ULONG stringLength = (ULONG)wcslen(moduleConfig->CustomCapabilities);
ULONG bufferSize = (stringLength * sizeof(WCHAR)) + (2 * sizeof(WCHAR));

ntStatus = moduleContext->IoSetDeviceInterfacePropertyData(&symbolicLinkName,
&DEVPKEY_DeviceInterface_UnrestrictedAppCapabilities,
0,
0,
DEVPROP_TYPE_STRING_LIST,
bufferSize,
(PVOID)moduleConfig->CustomCapabilities);
if (!NT_SUCCESS(ntStatus))
{
TraceEvents(TRACE_LEVEL_ERROR, DMF_TRACE_IoctlHandler, "IoSetDeviceInterfacePropertyData fails: ntStatus=%!STATUS!", ntStatus);
goto Exit;
}
}
#endif // defined(NTDDI_WIN10_RS2) && (NTDDI_VERSION >= NTDDI_WIN10_RS2)
}

// Optionaly, allow Client to perform other operations. Give Client access to the IoSetDeviceInterfacePropertyData function,
// but Client is responsible for checking if it is NULL and dealing with that.
//
if (moduleConfig->PostDeviceInterfaceCreate != NULL)
{
ntStatus = moduleConfig->PostDeviceInterfaceCreate(DmfModule,
moduleConfig->DeviceInterfaceGuid,
symbolicLinkNameString,
moduleContext->IoSetDeviceInterfacePropertyData);
}

Exit:

if (symbolicLinkNameString != NULL)
{
WdfObjectDelete(symbolicLinkNameString);
}

// NOTE: Module will not open if this function returns an error.
//
return ntStatus;
}

#endif

///////////////////////////////////////////////////////////////////////////////////////////////////////
// Wdf Module Callbacks
///////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -246,6 +373,7 @@ Return Value:
// Buffer is validated. Call client handler.
//
ntStatus = ioctlRecord->EvtIoctlHandlerFunction(DmfModule,
Queue,
Request,
IoControlCode,
inputBuffer,
Expand Down Expand Up @@ -632,6 +760,14 @@ Return Value:
TraceEvents(TRACE_LEVEL_ERROR, DMF_TRACE_IoctlHandler, "WdfDeviceCreateDeviceInterface fails: ntStatus=%!STATUS!", ntStatus);
goto Exit;
}
#if !defined(DMF_USER_MODE)
ntStatus = IoctlHandler_PostDeviceInterfaceCreate(DmfModule);
if (! NT_SUCCESS(ntStatus))
{
TraceEvents(TRACE_LEVEL_ERROR, DMF_TRACE_IoctlHandler, "IoctlHandler_PostDeviceInterfaceCreate fails: ntStatus=%!STATUS!", ntStatus);
goto Exit;
}
#endif
}
else
{
Expand Down
42 changes: 36 additions & 6 deletions Dmf/Framework/Modules.Core/Dmf_IoctlHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ _IRQL_requires_max_(DISPATCH_LEVEL)
_IRQL_requires_same_
NTSTATUS
EVT_DMF_IoctlHandler_Callback(_In_ DMFMODULE DmfModule,
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ ULONG IoctlCode,
_In_reads_(InputBufferSize) VOID* InputBuffer,
Expand All @@ -54,6 +55,29 @@ EVT_DMF_IoctlHandler_AccessModeFilter(_In_ DMFMODULE DmfModule,
_In_ WDFREQUEST Request,
_In_ WDFFILEOBJECT FileObject);

typedef
_Function_class_(IoctlHandler_IO_SET_DEVICE_INTERFACE_PROPERTY_DATA)
_IRQL_requires_max_(PASSIVE_LEVEL)
_IRQL_requires_same_
NTSTATUS
IoctlHandler_IO_SET_DEVICE_INTERFACE_PROPERTY_DATA(_In_ PUNICODE_STRING SymbolicLinkName,
_In_ CONST DEVPROPKEY* PropertyKey,
_In_ LCID Lcid,
_In_ ULONG Flags,
_In_ DEVPROPTYPE Type,
_In_ ULONG Size,
_In_opt_ PVOID Data);

typedef
_Function_class_(EVT_DMF_IoctlHandler_PostDeviceInterfaceCreate)
_IRQL_requires_max_(PASSIVE_LEVEL)
_IRQL_requires_same_
NTSTATUS
EVT_DMF_IoctlHandler_PostDeviceInterfaceCreate(_In_ DMFMODULE DmfModule,
_In_ GUID DeviceInterfaceGuid,
_In_ WDFSTRING SymbolicLinkNameString,
_In_ IoctlHandler_IO_SET_DEVICE_INTERFACE_PROPERTY_DATA* IoSetDeviceInterfaceProperty);

// The descriptor for each supported IOCTL.
//
typedef struct
Expand All @@ -79,22 +103,21 @@ typedef struct

typedef enum
{
IoctlHandler_AccessModeFilterInvalid = 0,
// Do what WDF would normally do (allow User-mode).
//
IoctlHandler_AccessModeDefault = 1,
IoctlHandler_AccessModeDefault,
// Call the a Client Callback function that will decide.
//
IoctlHandler_AccessModeFilterClientCallback = 2,
IoctlHandler_AccessModeFilterClientCallback,
// NOTE: This is currently not implemented.
//
IoctlHandler_AccessModeFilterDoNotAllowUserMode = 3,
IoctlHandler_AccessModeFilterDoNotAllowUserMode,
// Only allows "Run as Administrator".
//
IoctlHandler_AccessModeFilterAdministratorOnly = 4,
IoctlHandler_AccessModeFilterAdministratorOnly,
// Allow access to Administrator on a per-IOCTL basis.
//
IoctlHandler_AccessModeFilterAdministratorOnlyPerIoctl = 5,
IoctlHandler_AccessModeFilterAdministratorOnlyPerIoctl,
} IoctlHandler_AccessModeFilterType;

// Client uses this structure to configure the Module specific parameters.
Expand All @@ -116,6 +139,13 @@ typedef struct
// The number of records in the above table.
//
ULONG IoctlRecordCount;
// Windows Store App access settings.
//
WCHAR* CustomCapabilities;
DEVPROP_BOOLEAN IsRestricted;
// Allows Client to perform actions after the Device Interface is created.
//
EVT_DMF_IoctlHandler_PostDeviceInterfaceCreate* PostDeviceInterfaceCreate;
} DMF_CONFIG_IoctlHandler;

// This macro declares the following functions:
Expand Down
Loading