mirror of
https://github.com/reactos/reactos.git
synced 2024-08-05 11:00:55 +00:00
1f377076d7
Not all files are included, but these are necessary to compile cdrom driver. So far it can only be statically linked with drivers, a proper implementation requires wdfldr helper driver
502 lines
14 KiB
C++
502 lines
14 KiB
C++
/*++
|
|
|
|
Copyright (c) Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
FxCxDeviceInitApi.cpp
|
|
|
|
Abstract:
|
|
|
|
This module exposes the "C" interface to the FxDevice object
|
|
for the class extensions.
|
|
|
|
Author:
|
|
|
|
|
|
|
|
Environment:
|
|
|
|
Both kernel and user mode
|
|
|
|
Revision History:
|
|
|
|
|
|
|
|
--*/
|
|
|
|
#include "coreprivshared.hpp"
|
|
|
|
extern "C" {
|
|
// #include "FxCxDeviceInitApi.tmh"
|
|
}
|
|
|
|
//
|
|
// Extern "C" the entire file
|
|
//
|
|
extern "C" {
|
|
|
|
__inline
|
|
static
|
|
NTSTATUS
|
|
FxValiateCx(
|
|
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
|
__in PFX_DRIVER_GLOBALS CxDriverGlobals
|
|
)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
if (FxIsClassExtension(FxDriverGlobals, CxDriverGlobals) == FALSE) {
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
|
"This function can only be called by a WDF "
|
|
"extension driver, Driver 0x%p, %!STATUS!",
|
|
CxDriverGlobals->Public.Driver, status);
|
|
FxVerifierDbgBreakPoint(FxDriverGlobals);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
_Must_inspect_result_
|
|
__drv_maxIRQL(DISPATCH_LEVEL)
|
|
WDFAPI
|
|
NTSTATUS
|
|
WDFEXPORT(WdfCxDeviceInitAssignWdmIrpPreprocessCallback)(
|
|
__in
|
|
PWDF_DRIVER_GLOBALS DriverGlobals,
|
|
__in
|
|
PWDFCXDEVICE_INIT CxDeviceInit,
|
|
__in
|
|
PFN_WDFCXDEVICE_WDM_IRP_PREPROCESS EvtCxDeviceWdmIrpPreprocess,
|
|
__in
|
|
UCHAR MajorFunction,
|
|
__drv_when(NumMinorFunctions > 0, __in_bcount(NumMinorFunctions))
|
|
__drv_when(NumMinorFunctions == 0, __in_opt)
|
|
PUCHAR MinorFunctions,
|
|
__in
|
|
ULONG NumMinorFunctions
|
|
)
|
|
{
|
|
DDI_ENTRY();
|
|
|
|
PFX_DRIVER_GLOBALS fxDriverGlobals;
|
|
PFX_DRIVER_GLOBALS cxDriverGlobals;
|
|
NTSTATUS status;
|
|
|
|
cxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
|
|
FxPointerNotNull(cxDriverGlobals, CxDeviceInit);
|
|
fxDriverGlobals = CxDeviceInit->ClientDriverGlobals;
|
|
|
|
//
|
|
// Caller must be a class extension driver.
|
|
//
|
|
status = FxValiateCx(fxDriverGlobals, cxDriverGlobals);
|
|
if (!NT_SUCCESS(status)) {
|
|
goto Done;
|
|
}
|
|
|
|
FxPointerNotNull(fxDriverGlobals, EvtCxDeviceWdmIrpPreprocess);
|
|
|
|
if (NumMinorFunctions > 0) {
|
|
FxPointerNotNull(fxDriverGlobals, MinorFunctions);
|
|
}
|
|
|
|
//
|
|
// ARRAY_SIZE(CxDeviceInit->PreprocessInfo->Dispatch) just returns a
|
|
// constant size, it does not actually deref PreprocessInfo (which could
|
|
// be NULL)
|
|
//
|
|
if (MajorFunction >= ARRAY_SIZE(CxDeviceInit->PreprocessInfo->Dispatch)) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
DoTraceLevelMessage(fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
|
"MajorFunction %x is invalid, %!STATUS!",
|
|
(ULONG)MajorFunction, status);
|
|
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// CX must call this API multiple times if it wants to register preprocess callbacks for
|
|
// multiple IRP major codes.
|
|
//
|
|
if (CxDeviceInit->PreprocessInfo == NULL) {
|
|
CxDeviceInit->PreprocessInfo = new(fxDriverGlobals) FxIrpPreprocessInfo();
|
|
if (CxDeviceInit->PreprocessInfo == NULL) {
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
DoTraceLevelMessage(fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
|
"Couldn't create object PreprocessInfo, "
|
|
"%!STATUS!", status);
|
|
|
|
goto Done;
|
|
}
|
|
CxDeviceInit->PreprocessInfo->ClassExtension = TRUE;
|
|
}
|
|
|
|
ASSERT(CxDeviceInit->PreprocessInfo->ClassExtension);
|
|
|
|
if (NumMinorFunctions > 0) {
|
|
if (CxDeviceInit->PreprocessInfo->Dispatch[MajorFunction].NumMinorFunctions != 0) {
|
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
|
DoTraceLevelMessage(fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
|
"Already assigned Minorfunctions, %!STATUS!",
|
|
status);
|
|
goto Done;
|
|
}
|
|
|
|
CxDeviceInit->PreprocessInfo->Dispatch[MajorFunction].MinorFunctions =
|
|
(PUCHAR) FxPoolAllocate(fxDriverGlobals,
|
|
NonPagedPool,
|
|
sizeof(UCHAR) * NumMinorFunctions);
|
|
|
|
if (CxDeviceInit->PreprocessInfo->Dispatch[MajorFunction].MinorFunctions == NULL) {
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
DoTraceLevelMessage(fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
|
"Couldn't create object MinorFunctions, "
|
|
"%!STATUS!", status);
|
|
goto Done;
|
|
}
|
|
|
|
RtlCopyMemory(
|
|
&CxDeviceInit->PreprocessInfo->Dispatch[MajorFunction].MinorFunctions[0],
|
|
&MinorFunctions[0],
|
|
NumMinorFunctions
|
|
);
|
|
|
|
CxDeviceInit->PreprocessInfo->Dispatch[MajorFunction].NumMinorFunctions =
|
|
NumMinorFunctions;
|
|
}
|
|
|
|
CxDeviceInit->PreprocessInfo->Dispatch[MajorFunction].EvtCxDevicePreprocess =
|
|
EvtCxDeviceWdmIrpPreprocess;
|
|
|
|
status = STATUS_SUCCESS;
|
|
|
|
Done:
|
|
return status;
|
|
}
|
|
|
|
__drv_maxIRQL(DISPATCH_LEVEL)
|
|
VOID
|
|
WDFEXPORT(WdfCxDeviceInitSetIoInCallerContextCallback)(
|
|
__in
|
|
PWDF_DRIVER_GLOBALS DriverGlobals,
|
|
__in
|
|
PWDFCXDEVICE_INIT CxDeviceInit,
|
|
__in
|
|
PFN_WDF_IO_IN_CALLER_CONTEXT EvtIoInCallerContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Registers an I/O pre-processing callback for the class extension device.
|
|
|
|
If registered, any I/O for the device is first presented to this
|
|
callback function before being placed in any I/O Queue's.
|
|
|
|
The callback is invoked in the thread and/or DPC context of the
|
|
original WDM caller as presented to the I/O package. No framework
|
|
threading, locking, synchronization, or queuing occurs, and
|
|
responsibility for synchronization is up to the device driver.
|
|
|
|
This API is intended to support METHOD_NEITHER IRP_MJ_DEVICE_CONTROL's
|
|
which must access the user buffer in the original callers context. The
|
|
driver would probe and lock the buffer pages from within this event
|
|
handler using the functions supplied on the WDFREQUEST object, storing
|
|
any required mapped buffers and/or pointers on the WDFREQUEST context
|
|
whose size is set by the RequestContextSize of the WDF_DRIVER_CONFIG structure.
|
|
|
|
It is the responsibility of this routine to either complete the request, or
|
|
pass it on to the I/O package through WdfDeviceEnqueueRequest(Device, Request).
|
|
|
|
Arguments:
|
|
|
|
CxDeviceInit - Class Extension Device initialization structure
|
|
|
|
EvtIoInCallerContext - Pointer to driver supplied callback function
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
DDI_ENTRY();
|
|
|
|
PFX_DRIVER_GLOBALS fxDriverGlobals;
|
|
PFX_DRIVER_GLOBALS cxDriverGlobals;
|
|
NTSTATUS status;
|
|
|
|
cxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
|
|
FxPointerNotNull(cxDriverGlobals, CxDeviceInit);
|
|
fxDriverGlobals = CxDeviceInit->ClientDriverGlobals;
|
|
|
|
//
|
|
// Caller must be a class extension driver.
|
|
//
|
|
status = FxValiateCx(fxDriverGlobals, cxDriverGlobals);
|
|
if (!NT_SUCCESS(status)) {
|
|
goto Done;
|
|
}
|
|
|
|
FxPointerNotNull(fxDriverGlobals, EvtIoInCallerContext);
|
|
|
|
CxDeviceInit->IoInCallerContextCallback = EvtIoInCallerContext;
|
|
|
|
Done:
|
|
return;
|
|
}
|
|
|
|
__drv_maxIRQL(DISPATCH_LEVEL)
|
|
VOID
|
|
WDFEXPORT(WdfCxDeviceInitSetRequestAttributes)(
|
|
__in
|
|
PWDF_DRIVER_GLOBALS DriverGlobals,
|
|
__in
|
|
PWDFCXDEVICE_INIT CxDeviceInit,
|
|
__in
|
|
PWDF_OBJECT_ATTRIBUTES RequestAttributes
|
|
)
|
|
{
|
|
DDI_ENTRY();
|
|
|
|
PFX_DRIVER_GLOBALS fxDriverGlobals;
|
|
PFX_DRIVER_GLOBALS cxDriverGlobals;
|
|
NTSTATUS status;
|
|
|
|
cxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
|
|
FxPointerNotNull(cxDriverGlobals, CxDeviceInit);
|
|
fxDriverGlobals = CxDeviceInit->ClientDriverGlobals;
|
|
|
|
//
|
|
// Caller must be a class extension driver.
|
|
//
|
|
status = FxValiateCx(fxDriverGlobals, cxDriverGlobals);
|
|
if (!NT_SUCCESS(status)) {
|
|
goto Done;
|
|
}
|
|
|
|
FxPointerNotNull(fxDriverGlobals, RequestAttributes);
|
|
|
|
//
|
|
// Parent of all requests created from WDFDEVICE are parented by the WDFDEVICE.
|
|
//
|
|
status = FxValidateObjectAttributes(fxDriverGlobals,
|
|
RequestAttributes,
|
|
FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
FxVerifierDbgBreakPoint(fxDriverGlobals);
|
|
return;
|
|
}
|
|
|
|
RtlCopyMemory(&CxDeviceInit->RequestAttributes,
|
|
RequestAttributes,
|
|
sizeof(WDF_OBJECT_ATTRIBUTES));
|
|
|
|
Done:
|
|
return;
|
|
}
|
|
|
|
__drv_maxIRQL(DISPATCH_LEVEL)
|
|
VOID
|
|
WDFEXPORT(WdfCxDeviceInitSetFileObjectConfig)(
|
|
__in
|
|
PWDF_DRIVER_GLOBALS DriverGlobals,
|
|
__in
|
|
PWDFCXDEVICE_INIT CxDeviceInit,
|
|
__in
|
|
PWDFCX_FILEOBJECT_CONFIG CxFileObjectConfig,
|
|
__in_opt
|
|
PWDF_OBJECT_ATTRIBUTES FileObjectAttributes
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Registers file object callbacks for class extensions.
|
|
|
|
Defaults to WdfFileObjectNotRequired if no file obj config set.
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
--*/
|
|
|
|
{
|
|
DDI_ENTRY();
|
|
|
|
PFX_DRIVER_GLOBALS fxDriverGlobals;
|
|
PFX_DRIVER_GLOBALS cxDriverGlobals;
|
|
NTSTATUS status;
|
|
WDF_FILEOBJECT_CLASS normalizedFileClass;
|
|
|
|
cxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
|
|
FxPointerNotNull(cxDriverGlobals, CxDeviceInit);
|
|
fxDriverGlobals = CxDeviceInit->ClientDriverGlobals;
|
|
|
|
//
|
|
// Caller must be a class extension driver.
|
|
//
|
|
status = FxValiateCx(fxDriverGlobals, cxDriverGlobals);
|
|
if (!NT_SUCCESS(status)) {
|
|
goto Done;
|
|
}
|
|
|
|
FxPointerNotNull(fxDriverGlobals, CxFileObjectConfig);
|
|
|
|
if (CxFileObjectConfig->Size != sizeof(WDFCX_FILEOBJECT_CONFIG)) {
|
|
DoTraceLevelMessage(
|
|
fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
|
"Invalid CxFileObjectConfig Size %d, expected %d",
|
|
CxFileObjectConfig->Size, sizeof(WDFCX_FILEOBJECT_CONFIG));
|
|
|
|
FxVerifierDbgBreakPoint(fxDriverGlobals);
|
|
goto Done;
|
|
}
|
|
|
|
status = FxValidateObjectAttributes(
|
|
fxDriverGlobals,
|
|
FileObjectAttributes,
|
|
FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED |
|
|
FX_VALIDATE_OPTION_EXECUTION_LEVEL_ALLOWED |
|
|
FX_VALIDATE_OPTION_SYNCHRONIZATION_SCOPE_ALLOWED
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
FxVerifierDbgBreakPoint(fxDriverGlobals);
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Validate AutoForwardCleanupClose.
|
|
//
|
|
switch (CxFileObjectConfig->AutoForwardCleanupClose) {
|
|
case WdfTrue:
|
|
case WdfFalse:
|
|
case WdfUseDefault:
|
|
break;
|
|
|
|
default:
|
|
DoTraceLevelMessage(
|
|
fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
|
"Invalid CxFileObjectConfig->AutoForwardCleanupClose value 0x%x, "
|
|
"expected WDF_TRI_STATE value",
|
|
CxFileObjectConfig->AutoForwardCleanupClose);
|
|
|
|
FxVerifierDbgBreakPoint(fxDriverGlobals);
|
|
goto Done;
|
|
}
|
|
|
|
CxDeviceInit->FileObject.Set = TRUE;
|
|
|
|
CxDeviceInit->FileObject.AutoForwardCleanupClose =
|
|
CxFileObjectConfig->AutoForwardCleanupClose;
|
|
|
|
//
|
|
// Remove bit flags and validate file object class value.
|
|
//
|
|
normalizedFileClass = FxFileObjectClassNormalize(
|
|
CxFileObjectConfig->FileObjectClass);
|
|
|
|
if (normalizedFileClass == WdfFileObjectInvalid ||
|
|
normalizedFileClass > WdfFileObjectWdfCannotUseFsContexts) {
|
|
DoTraceLevelMessage(
|
|
fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
|
"Out of range CxFileObjectConfig->FileObjectClass %d",
|
|
CxFileObjectConfig->FileObjectClass);
|
|
FxVerifierDbgBreakPoint(fxDriverGlobals);
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// The optional flag can only be combined with a subset of values.
|
|
//
|
|
if (FxIsFileObjectOptional(CxFileObjectConfig->FileObjectClass)) {
|
|
switch(normalizedFileClass) {
|
|
case WdfFileObjectWdfCanUseFsContext:
|
|
case WdfFileObjectWdfCanUseFsContext2:
|
|
case WdfFileObjectWdfCannotUseFsContexts:
|
|
break;
|
|
|
|
default:
|
|
DoTraceLevelMessage(
|
|
fxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
|
"Invalid CxFileObjectConfig->FileObjectClass %d",
|
|
CxFileObjectConfig->FileObjectClass);
|
|
FxVerifierDbgBreakPoint(fxDriverGlobals);
|
|
goto Done;
|
|
break; // just in case static verification tools complain.
|
|
}
|
|
}
|
|
|
|
CxDeviceInit->FileObject.Class = CxFileObjectConfig->FileObjectClass;
|
|
|
|
RtlCopyMemory(&CxDeviceInit->FileObject.Callbacks,
|
|
CxFileObjectConfig,
|
|
sizeof(CxDeviceInit->FileObject.Callbacks));
|
|
|
|
if (FileObjectAttributes != NULL) {
|
|
RtlCopyMemory(&CxDeviceInit->FileObject.Attributes,
|
|
FileObjectAttributes,
|
|
sizeof(CxDeviceInit->FileObject.Attributes));
|
|
}
|
|
|
|
Done:
|
|
return;
|
|
}
|
|
|
|
_Must_inspect_result_
|
|
__drv_maxIRQL(PASSIVE_LEVEL)
|
|
PWDFCXDEVICE_INIT
|
|
WDFEXPORT(WdfCxDeviceInitAllocate)(
|
|
__in
|
|
PWDF_DRIVER_GLOBALS DriverGlobals,
|
|
__in
|
|
PWDFDEVICE_INIT DeviceInit
|
|
)
|
|
{
|
|
DDI_ENTRY();
|
|
|
|
PFX_DRIVER_GLOBALS cxDriverGlobals;
|
|
PFX_DRIVER_GLOBALS fxDriverGlobals;
|
|
PWDFCXDEVICE_INIT cxDeviceInit;
|
|
NTSTATUS status;
|
|
|
|
cxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
|
|
FxPointerNotNull(cxDriverGlobals, DeviceInit);
|
|
fxDriverGlobals = DeviceInit->DriverGlobals;
|
|
cxDeviceInit = NULL;
|
|
|
|
//
|
|
// Caller must be a class extension driver.
|
|
//
|
|
status = FxValiateCx(fxDriverGlobals, cxDriverGlobals);
|
|
if (!NT_SUCCESS(status)) {
|
|
goto Done;
|
|
}
|
|
|
|
status = FxVerifierCheckIrqlLevel(fxDriverGlobals, PASSIVE_LEVEL);
|
|
if (!NT_SUCCESS(status)) {
|
|
goto Done;
|
|
}
|
|
|
|
cxDeviceInit = WDFCXDEVICE_INIT::_AllocateCxDeviceInit(DeviceInit);
|
|
if (NULL == cxDeviceInit) {
|
|
goto Done;
|
|
}
|
|
|
|
cxDeviceInit->ClientDriverGlobals = fxDriverGlobals;
|
|
cxDeviceInit->CxDriverGlobals = cxDriverGlobals;
|
|
|
|
Done:
|
|
return cxDeviceInit;
|
|
}
|
|
|
|
} // extern "C"
|
|
|