mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 05:12:55 +00:00
[WDF] Add Windows Driver Framework files
Takern from Microsoft GitHub repo:
d9c6040fe9
Licensed under MIT
This commit is contained in:
parent
545df81502
commit
8a978a179f
475 changed files with 285099 additions and 0 deletions
650
sdk/lib/drivers/wdf/shared/enhancedverif/verifier.cpp
Normal file
650
sdk/lib/drivers/wdf/shared/enhancedverif/verifier.cpp
Normal file
|
@ -0,0 +1,650 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
Verifier.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This file has implementation of verifier support routines
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Shared (Kernel and user)
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#include "vfpriv.hpp"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
extern WDFVERSION WdfVersion;
|
||||
|
||||
// Tracing support
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "verifier.tmh"
|
||||
#endif
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(FX_ENHANCED_VERIFIER_SECTION_NAME, \
|
||||
AddEventHooksWdfDeviceCreate, \
|
||||
AddEventHooksWdfIoQueueCreate, \
|
||||
VfAddContextToHandle, \
|
||||
VfAllocateContext, \
|
||||
VfWdfObjectGetTypedContext \
|
||||
)
|
||||
#endif
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
AddEventHooksWdfDeviceCreate(
|
||||
__inout PVF_HOOK_PROCESS_INFO HookProcessInfo,
|
||||
__in PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in PWDFDEVICE_INIT* DeviceInit,
|
||||
__in PWDF_OBJECT_ATTRIBUTES DeviceAttributes,
|
||||
__out WDFDEVICE* Device
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine is called by main hook for WdfDeviceCreate.
|
||||
The routine swaps the event callbacks provided by client.
|
||||
|
||||
Arguments:
|
||||
|
||||
Return value:
|
||||
|
||||
--*/
|
||||
{
|
||||
NTSTATUS status;
|
||||
PWDFDEVICE_INIT deviceInit = *DeviceInit;
|
||||
WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerEvtsOriginal;
|
||||
WDF_PNPPOWER_EVENT_CALLBACKS *pnpPowerEvts;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
PVOID contextHeader = NULL;
|
||||
WDF_OBJECT_ATTRIBUTES attributes;
|
||||
|
||||
PAGED_CODE_LOCKED();
|
||||
|
||||
pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, DeviceInit);
|
||||
FxPointerNotNull(pFxDriverGlobals, *DeviceInit);
|
||||
FxPointerNotNull(pFxDriverGlobals, Device);
|
||||
|
||||
//
|
||||
// Check if there are any callbacks set by the client driver. If not, we
|
||||
// don't need any callback hooking.
|
||||
//
|
||||
if (deviceInit->PnpPower.PnpPowerEventCallbacks.Size !=
|
||||
sizeof(WDF_PNPPOWER_EVENT_CALLBACKS)) {
|
||||
//
|
||||
// no hooking required.
|
||||
//
|
||||
status = STATUS_SUCCESS;
|
||||
HookProcessInfo->DonotCallKmdfLib = FALSE;
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Hooking can be done only if we are able to allocate context memory.
|
||||
// Try to allocate a context
|
||||
//
|
||||
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
|
||||
&attributes,
|
||||
VF_WDFDEVICECREATE_CONTEXT
|
||||
);
|
||||
|
||||
status = VfAllocateContext(DriverGlobals, &attributes, &contextHeader);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
//
|
||||
// couldn't allocate context. hooking not possible
|
||||
//
|
||||
HookProcessInfo->DonotCallKmdfLib = FALSE;
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// store original driver callbacks to local variable
|
||||
//
|
||||
RtlCopyMemory(&pnpPowerEvtsOriginal,
|
||||
&deviceInit->PnpPower.PnpPowerEventCallbacks,
|
||||
sizeof(WDF_PNPPOWER_EVENT_CALLBACKS)
|
||||
);
|
||||
|
||||
//
|
||||
// Set callback hooks
|
||||
//
|
||||
// Normally override the hooks on local copy of stucture (not the original
|
||||
// structure itself) and then pass the local struture to DDI call and
|
||||
// copy back the original poniter when returning back to caller. In this case
|
||||
// device_init is null'ed out by fx when returning to caller so we can
|
||||
// directly override the original
|
||||
//
|
||||
pnpPowerEvts = &deviceInit->PnpPower.PnpPowerEventCallbacks;
|
||||
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceD0Entry);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceD0EntryPostInterruptsEnabled);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceD0Exit);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceD0ExitPreInterruptsDisabled);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDevicePrepareHardware);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceReleaseHardware);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceSelfManagedIoCleanup);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceSelfManagedIoFlush);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceSelfManagedIoInit);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceSelfManagedIoSuspend);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceSelfManagedIoRestart);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceSurpriseRemoval);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceQueryRemove);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceQueryStop);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceUsageNotification);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceUsageNotificationEx);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(pnpPowerEvts, pnpPowerEvts, EvtDeviceRelationsQuery);
|
||||
|
||||
//
|
||||
// Call the DDI on behalf of driver.
|
||||
//
|
||||
status = ((PFN_WDFDEVICECREATE)WdfVersion.Functions.pfnWdfDeviceCreate)(
|
||||
DriverGlobals,
|
||||
DeviceInit,
|
||||
DeviceAttributes,
|
||||
Device
|
||||
);
|
||||
//
|
||||
// Tell main hook routine not to call the DDI in kmdf lib since we
|
||||
// already called it
|
||||
//
|
||||
HookProcessInfo->DonotCallKmdfLib = TRUE;
|
||||
HookProcessInfo->DdiCallStatus = status;
|
||||
|
||||
//
|
||||
// if DDI Succeeds, add context
|
||||
//
|
||||
if (NT_SUCCESS(status)) {
|
||||
PVF_WDFDEVICECREATE_CONTEXT context = NULL;
|
||||
|
||||
//
|
||||
// add the already allocated context to the object.
|
||||
//
|
||||
status = VfAddContextToHandle(contextHeader,
|
||||
&attributes,
|
||||
*Device,
|
||||
(PVOID *)&context);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
//
|
||||
// store the DriverGlobals pointer used to associate the driver
|
||||
// with its client driver callback later in the callback hooks
|
||||
//
|
||||
context->CommonHeader.DriverGlobals = DriverGlobals;
|
||||
|
||||
//
|
||||
// store original client driver callbacks in context
|
||||
//
|
||||
RtlCopyMemory(
|
||||
&context->PnpPowerEventCallbacksOriginal,
|
||||
&pnpPowerEvtsOriginal,
|
||||
sizeof(WDF_PNPPOWER_EVENT_CALLBACKS)
|
||||
);
|
||||
}
|
||||
else {
|
||||
//
|
||||
// For some reason adding context to handle failed. This should be
|
||||
// rare failure, because context allocation was already successful,
|
||||
// only adding to handle failed.
|
||||
//
|
||||
// Hooking failed if adding context is unsuccessful. This means
|
||||
// kmdf has callbacks hooks but verifier cannot assiociate client
|
||||
// driver callbacks with callback hooks. This would be a fatal error.
|
||||
//
|
||||
ASSERTMSG("KMDF Enhanced Verifier failed to add context to object "
|
||||
"handle\n", FALSE);
|
||||
|
||||
if (contextHeader != NULL) {
|
||||
FxPoolFree(contextHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// KMDF DDI call failed. In case of failure, DeviceInit is not NULL'ed
|
||||
// so the driver could potentially call WdfDeviceCreate again with this
|
||||
// DeviceInit that contains callback hooks, and result in infinite
|
||||
// callback loop. So put original callbacks back
|
||||
//
|
||||
if ((*DeviceInit) != NULL) {
|
||||
//
|
||||
// we overwrote only the pnppower callbacks. Put the original back.
|
||||
//
|
||||
deviceInit = *DeviceInit;
|
||||
RtlCopyMemory(&deviceInit->PnpPower.PnpPowerEventCallbacks,
|
||||
&pnpPowerEvtsOriginal,
|
||||
sizeof(WDF_PNPPOWER_EVENT_CALLBACKS)
|
||||
);
|
||||
}
|
||||
|
||||
if (contextHeader != NULL) {
|
||||
FxPoolFree(contextHeader);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
AddEventHooksWdfIoQueueCreate(
|
||||
__inout PVF_HOOK_PROCESS_INFO HookProcessInfo,
|
||||
__in PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in WDFDEVICE Device,
|
||||
__in PWDF_IO_QUEUE_CONFIG Config,
|
||||
__in PWDF_OBJECT_ATTRIBUTES QueueAttributes,
|
||||
__out WDFQUEUE* Queue
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Arguments:
|
||||
|
||||
Return value:
|
||||
|
||||
--*/
|
||||
{
|
||||
NTSTATUS status;
|
||||
WDF_IO_QUEUE_CONFIG configNew;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
WDFQUEUE *pQueue;
|
||||
WDFQUEUE queue;
|
||||
PVOID contextHeader = NULL;
|
||||
WDF_OBJECT_ATTRIBUTES attributes;
|
||||
|
||||
PAGED_CODE_LOCKED();
|
||||
|
||||
pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, Config);
|
||||
|
||||
//
|
||||
// Check if there are any callbacks set by the client driver. If not, we
|
||||
// don't need any callback hooking.
|
||||
//
|
||||
if (Config->Size != sizeof(WDF_IO_QUEUE_CONFIG)) {
|
||||
//
|
||||
// no hooking required.
|
||||
//
|
||||
status = STATUS_SUCCESS;
|
||||
HookProcessInfo->DonotCallKmdfLib = FALSE;
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Hooking can be done only if we are able to allocate context memory.
|
||||
// Try to allocate a context
|
||||
//
|
||||
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes,
|
||||
VF_WDFIOQUEUECREATE_CONTEXT);
|
||||
|
||||
status = VfAllocateContext(DriverGlobals, &attributes, &contextHeader);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
//
|
||||
// couldn't allocate context. hooking not possible
|
||||
//
|
||||
HookProcessInfo->DonotCallKmdfLib = FALSE;
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// create a local copy of config
|
||||
//
|
||||
RtlCopyMemory(&configNew,
|
||||
Config,
|
||||
sizeof(configNew)
|
||||
);
|
||||
|
||||
//
|
||||
// Override local copy with event callback hooks.
|
||||
//
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(Config, &configNew, EvtIoDefault);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(Config, &configNew, EvtIoRead);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(Config, &configNew, EvtIoWrite);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(Config, &configNew, EvtIoDeviceControl);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(Config, &configNew, EvtIoInternalDeviceControl);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(Config, &configNew, EvtIoStop);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(Config, &configNew, EvtIoResume);
|
||||
SET_HOOK_IF_CALLBACK_PRESENT(Config, &configNew, EvtIoCanceledOnQueue);
|
||||
|
||||
//
|
||||
// Queue handle is an optional parameter
|
||||
//
|
||||
if (Queue == NULL) {
|
||||
pQueue = &queue;
|
||||
}
|
||||
else {
|
||||
pQueue = Queue;
|
||||
}
|
||||
|
||||
//
|
||||
// call the DDI
|
||||
//
|
||||
status = WdfVersion.Functions.pfnWdfIoQueueCreate(
|
||||
DriverGlobals,
|
||||
Device,
|
||||
&configNew,
|
||||
QueueAttributes,
|
||||
pQueue
|
||||
);
|
||||
|
||||
//
|
||||
// Tell main hook routine not to call the DDI in kmdf lib since we
|
||||
// already called it
|
||||
//
|
||||
HookProcessInfo->DonotCallKmdfLib = TRUE;
|
||||
HookProcessInfo->DdiCallStatus = status;
|
||||
|
||||
//
|
||||
// if DDI Succeeds, add context
|
||||
//
|
||||
if (NT_SUCCESS(status)) {
|
||||
PVF_WDFIOQUEUECREATE_CONTEXT context = NULL;
|
||||
|
||||
//
|
||||
// add the already allocated context to the object.
|
||||
//
|
||||
status = VfAddContextToHandle(contextHeader,
|
||||
&attributes,
|
||||
*pQueue,
|
||||
(PVOID *)&context);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
//
|
||||
// store the DriverGlobals pointer used to associate the driver
|
||||
// with its client driver callback later in the callback hooks
|
||||
//
|
||||
context->CommonHeader.DriverGlobals = DriverGlobals;
|
||||
|
||||
//
|
||||
// add stored original callbacks to context
|
||||
//
|
||||
RtlCopyMemory(
|
||||
&context->IoQueueConfigOriginal,
|
||||
Config,
|
||||
sizeof(WDF_IO_QUEUE_CONFIG)
|
||||
);
|
||||
}
|
||||
else {
|
||||
//
|
||||
// For some reason adding context to handle failed. This should be
|
||||
// rare failure, because context allocation was already successful,
|
||||
// only adding to handle failed.
|
||||
//
|
||||
// Hooking failed if adding context is unsuccessful. This means
|
||||
// kmdf has callbacks hooks but verifier cannot assiociate client
|
||||
// driver callbacks with callback hooks. This would be a fatal error.
|
||||
//
|
||||
ASSERTMSG("KMDF Enhanced Verifier failed to add context to object "
|
||||
"handle\n", FALSE);
|
||||
|
||||
if (contextHeader != NULL) {
|
||||
FxPoolFree(contextHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// DDI call to KMDF failed. Nothing to do by verifier. Just return
|
||||
// kmdf's status after freeing context header memory.
|
||||
//
|
||||
if (contextHeader != NULL) {
|
||||
FxPoolFree(contextHeader);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
PVOID
|
||||
FASTCALL
|
||||
VfWdfObjectGetTypedContext(
|
||||
__in
|
||||
WDFOBJECT Handle,
|
||||
__in
|
||||
PCWDF_OBJECT_CONTEXT_TYPE_INFO TypeInfo
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Retrieves the requested type from a handle
|
||||
|
||||
Arguments:
|
||||
Handle - the handle to retrieve the context from
|
||||
TypeInfo - global constant pointer which describes the type. Since the pointer
|
||||
value is unique in all of kernel space, we will perform a pointer compare
|
||||
instead of a deep structure compare
|
||||
|
||||
Return Value:
|
||||
A valid context pointere or NULL. NULL is not a failure, querying for a type
|
||||
not associated with the handle is a legitimate operation.
|
||||
|
||||
--*/
|
||||
{
|
||||
FxContextHeader* pHeader;
|
||||
FxObject* pObject;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
WDFOBJECT_OFFSET offset;
|
||||
|
||||
PAGED_CODE_LOCKED();
|
||||
|
||||
//
|
||||
// Do not call FxObjectHandleGetPtr( , , FX_TYPE_OBJECT) because this is a
|
||||
// hot spot / workhorse function that should be as efficient as possible.
|
||||
//
|
||||
// A call to FxObjectHandleGetPtr would :
|
||||
// 1) invoke a virtual call to QueryInterface
|
||||
//
|
||||
// 2) ASSERT that the ref count of the object is > zero. Since this is one
|
||||
// of the few functions that can be called in EvtObjectDestroy where the
|
||||
// ref count is zero, that is not a good side affect.
|
||||
//
|
||||
offset = 0;
|
||||
pObject = FxObject::_GetObjectFromHandle(Handle, &offset);
|
||||
|
||||
//
|
||||
// Use the object's globals, not the caller's
|
||||
//
|
||||
pFxDriverGlobals = pObject->GetDriverGlobals();
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, Handle);
|
||||
FxPointerNotNull(pFxDriverGlobals, TypeInfo);
|
||||
|
||||
pHeader = pObject->GetContextHeader();
|
||||
|
||||
for ( ; pHeader != NULL; pHeader = pHeader->NextHeader) {
|
||||
if (pHeader->ContextTypeInfo == TypeInfo) {
|
||||
return &pHeader->Context[0];
|
||||
}
|
||||
}
|
||||
|
||||
PCHAR pGivenName;
|
||||
|
||||
if (TypeInfo->ContextName != NULL) {
|
||||
pGivenName = TypeInfo->ContextName;
|
||||
}
|
||||
else {
|
||||
pGivenName = "<no typename given>";
|
||||
}
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGDEVICE,
|
||||
"Attempting to get context type %s from WDFOBJECT 0x%p",
|
||||
pGivenName, Handle);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
VfAllocateContext(
|
||||
__in PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in PWDF_OBJECT_ATTRIBUTES Attributes,
|
||||
__out PVOID* ContextHeader
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Allocates an additional context on the handle if the object is in the
|
||||
correct state
|
||||
|
||||
Arguments:
|
||||
Handle - handle on which to add a context
|
||||
Attributes - attributes which describe the type and size of the new context
|
||||
Context - optional pointer which will recieve the new context
|
||||
|
||||
Return Value:
|
||||
STATUS_SUCCESS upon success, STATUS_OBJECT_NAME_EXISTS if the context type
|
||||
is already attached to the handle, and !NT_SUCCESS on failure
|
||||
|
||||
--*/
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
NTSTATUS status;
|
||||
FxContextHeader *pHeader;
|
||||
size_t size;
|
||||
|
||||
PAGED_CODE_LOCKED();
|
||||
|
||||
pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
|
||||
|
||||
status = FxValidateObjectAttributes(
|
||||
pFxDriverGlobals, Attributes, FX_VALIDATE_OPTION_ATTRIBUTES_REQUIRED);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Must have a context type!
|
||||
//
|
||||
if (Attributes->ContextTypeInfo == NULL) {
|
||||
status = STATUS_OBJECT_NAME_INVALID;
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGHANDLE,
|
||||
"Attributes %p ContextTypeInfo is NULL, %!STATUS!",
|
||||
Attributes, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// By passing 0's for raw object size and extra size, we can compute the
|
||||
// size of only the header and its contents.
|
||||
//
|
||||
status = FxCalculateObjectTotalSize(pFxDriverGlobals, 0, 0, Attributes, &size);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
pHeader = (FxContextHeader*)
|
||||
FxPoolAllocate(pFxDriverGlobals, NonPagedPool, size);
|
||||
|
||||
if (pHeader != NULL) {
|
||||
*ContextHeader = pHeader;
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
VfAddContextToHandle(
|
||||
__in PVOID ContextHeader,
|
||||
__in PWDF_OBJECT_ATTRIBUTES Attributes,
|
||||
__in WDFOBJECT Handle,
|
||||
__out_opt PVOID* Context
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
FxObject* pObject;
|
||||
FxContextHeader *pHeader;
|
||||
WDFOBJECT_OFFSET offset;
|
||||
|
||||
PAGED_CODE_LOCKED();
|
||||
|
||||
pHeader = (FxContextHeader *)ContextHeader;
|
||||
|
||||
if (pHeader == NULL) {
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// No need to call FxObjectHandleGetPtr( , , FX_TYPE_OBJECT) because
|
||||
// we assume that the object handle will point back to an FxObject. (The
|
||||
// call to FxObjectHandleGetPtr will just make needless virtual call into
|
||||
// FxObject anyways).
|
||||
//
|
||||
offset = 0;
|
||||
pObject = FxObject::_GetObjectFromHandle(Handle, &offset);
|
||||
|
||||
pFxDriverGlobals = pObject->GetDriverGlobals();
|
||||
|
||||
if (offset != 0) {
|
||||
//
|
||||
// for lack of a better error code
|
||||
//
|
||||
status = STATUS_OBJECT_PATH_INVALID;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGHANDLE,
|
||||
"WDFHANDLE %p cannot have contexts added to it, %!STATUS!",
|
||||
Handle, status);
|
||||
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
pObject->ADDREF(&status);
|
||||
|
||||
FxContextHeaderInit(pHeader, pObject, Attributes);
|
||||
|
||||
status = pObject->AddContext(pHeader, Context, Attributes);
|
||||
|
||||
//
|
||||
// STATUS_OBJECT_NAME_EXISTS will not fail NT_SUCCESS, so check
|
||||
// explicitly for STATUS_SUCCESS.
|
||||
//
|
||||
if (status != STATUS_SUCCESS) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGHANDLE,
|
||||
"WDFHANDLE %p failed to add context, %!STATUS!",
|
||||
Handle, status);
|
||||
}
|
||||
|
||||
pObject->RELEASE(&status);
|
||||
|
||||
cleanup:
|
||||
|
||||
if (status != STATUS_SUCCESS && pHeader != NULL) {
|
||||
FxPoolFree(pHeader);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
} // extern "C"
|
Loading…
Add table
Add a link
Reference in a new issue