reactos/sdk/lib/drivers/wdf/shared/irphandlers/pnp/km/fxpkgfdokm.cpp
Victor Perevertkin 1f377076d7
[WDF] Fix KMDF so it can compile with ReactOS SDK
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
2020-11-03 00:06:27 +03:00

598 lines
16 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Module Name:
FxPkgFdo.cpp
Abstract:
This module implements the pnp/power package for the driver
framework.
Author:
Environment:
Kernel mode only
Revision History:
--*/
#include "../pnppriv.hpp"
#include <initguid.h>
#include <wdmguid.h>
#if defined(EVENT_TRACING)
// Tracing support
extern "C" {
#include "FxPkgFdoKm.tmh"
}
#endif
_Must_inspect_result_
NTSTATUS
FxPkgFdo::PnpFilterResourceRequirements(
__inout FxIrp *Irp
)
/*++
Routine Description:
This method is invoked in response to a Pnp FilterResourceRequirements IRP.
Arguments:
Device - a pointer to the FxDevice
Irp - a pointer to the FxIrp
Returns:
NTSTATUS
--*/
{
PIO_RESOURCE_REQUIREMENTS_LIST pWdmRequirementsList;
PIO_RESOURCE_REQUIREMENTS_LIST pNewWdmList;
NTSTATUS status;
FxIoResReqList *pIoResReqList;
WDFIORESREQLIST reqlist;
DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
"Entering FilterResourceRequirements handler");
if (m_DeviceFilterRemoveResourceRequirements.m_Method != NULL) {
pWdmRequirementsList = (PIO_RESOURCE_REQUIREMENTS_LIST) Irp->GetInformation();
status = STATUS_INSUFFICIENT_RESOURCES;
pIoResReqList = FxIoResReqList::_CreateFromWdmList(GetDriverGlobals(),
pWdmRequirementsList,
FxResourceAllAccessAllowed);
if (pIoResReqList != NULL) {
status = pIoResReqList->Commit(NULL, (PWDFOBJECT) &reqlist);
// Commit should never fail because we own all object state
ASSERT(NT_SUCCESS(status));
UNREFERENCED_PARAMETER(status);
status = m_DeviceFilterRemoveResourceRequirements.Invoke(
m_Device->GetHandle(), pIoResReqList->GetHandle());
if (NT_SUCCESS(status) && pIoResReqList->IsChanged()) {
pNewWdmList = pIoResReqList->CreateWdmList();
if (pNewWdmList != NULL) {
//
// List could be missing previously
//
if (pWdmRequirementsList != NULL) {
//
// Propagate BusNumber to our new list.
//
pNewWdmList->BusNumber = pWdmRequirementsList->BusNumber;
MxMemory::MxFreePool(pWdmRequirementsList);
}
Irp->SetInformation((ULONG_PTR) pNewWdmList);
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
}
//
// No matter what, free the resource requirements list object. If
// we need another one when adding resources, another one will be
// allocated.
//
pIoResReqList->DeleteObject();
pIoResReqList = NULL;
}
}
else {
//
// No filtering on the way down, set status to STATUS_SUCCESS so we
// send the irp down the stack.
//
status = STATUS_SUCCESS;
}
if (NT_SUCCESS(status)) {
status = SendIrpSynchronously(Irp);
}
//
// If we do not handle the IRP on the way down and the PDO does not handle
// the IRP, we can have a status of STATUS_NOT_SUPPORTED. We still want to
// process the irp in this state.
//
if (NT_SUCCESS(status) || status == STATUS_NOT_SUPPORTED) {
NTSTATUS filterStatus;
//
// Give the Framework objects a pass at the list.
//
filterStatus = FxPkgPnp::FilterResourceRequirements(
(PIO_RESOURCE_REQUIREMENTS_LIST*)(&Irp->GetIrp()->IoStatus.Information)
);
if (!NT_SUCCESS(filterStatus)) {
status = filterStatus;
}
else if (m_DeviceFilterAddResourceRequirements.m_Method != NULL) {
//
// Now give the driver a shot at it.
//
pWdmRequirementsList = (PIO_RESOURCE_REQUIREMENTS_LIST)
Irp->GetInformation();
pIoResReqList = FxIoResReqList::_CreateFromWdmList(
GetDriverGlobals(), pWdmRequirementsList, FxResourceAllAccessAllowed);
if (pIoResReqList != NULL) {
status = pIoResReqList->Commit(NULL, (PWDFOBJECT) &reqlist);
UNREFERENCED_PARAMETER(status);
//
// Since we absolutely control the lifetime of pIoResReqList, this
// should never fail
//
ASSERT(NT_SUCCESS(status));
status = m_DeviceFilterAddResourceRequirements.Invoke(
m_Device->GetHandle(), reqlist);
//
// It is possible the child driver modified the resource list,
// and if so we need to update the requirements list.
//
if (NT_SUCCESS(status) && pIoResReqList->IsChanged()) {
pNewWdmList = pIoResReqList->CreateWdmList();
if (pNewWdmList != NULL) {
//
// List could be missing previously
//
if (pWdmRequirementsList != NULL) {
//
// Propagate BusNumber to our new list.
//
pNewWdmList->BusNumber = pWdmRequirementsList->BusNumber;
ExFreePool(pWdmRequirementsList);
}
Irp->SetInformation((ULONG_PTR) pNewWdmList);
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
}
pIoResReqList->DeleteObject();
pIoResReqList = NULL;
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
}
}
CompletePnpRequest(Irp, status);
DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_VERBOSE, TRACINGPNP,
"Exiting FilterResourceRequirements handler, %!STATUS!",
status);
return status;
}
_Must_inspect_result_
NTSTATUS
FxPkgFdo::_PnpQueryCapabilitiesCompletionRoutine(
__in MdDeviceObject DeviceObject,
__inout MdIrp Irp,
__inout PVOID Context
)
{
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);
UNREFERENCED_PARAMETER(Context);
ASSERTMSG("Not implemented for KMDF\n", FALSE);
return STATUS_NOT_IMPLEMENTED;
}
_Must_inspect_result_
NTSTATUS
FxPkgFdo::PnpQueryCapabilities(
__inout FxIrp *Irp
)
/*++
Routine Description:
This method is invoked in response to a Pnp QueryCapabilities IRP.
Arguments:
Device - a pointer to the FxDevice
Irp - a pointer to the FxIrp
Returns:
NTSTATUS
--*/
{
NTSTATUS status;
HandleQueryCapabilities(Irp);
status = SendIrpSynchronously(Irp);
//
// Now that the IRP has returned to us, we modify what the bus driver
// set up.
//
if (NT_SUCCESS(status)) {
HandleQueryCapabilitiesCompletion(Irp);
}
CompletePnpRequest(Irp, status);
return status;
}
_Must_inspect_result_
NTSTATUS
FxPkgFdo::_PnpQueryPnpDeviceStateCompletionRoutine(
__in MdDeviceObject DeviceObject,
__inout MdIrp Irp,
__inout PVOID Context
)
{
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);
UNREFERENCED_PARAMETER(Context);
ASSERTMSG("Not implemented for KMDF\n", FALSE);
return STATUS_NOT_IMPLEMENTED;
}
_Must_inspect_result_
NTSTATUS
FxPkgFdo::_PnpQueryPnpDeviceState(
__inout FxPkgPnp* This,
__inout FxIrp *Irp
)
/*++
Routine Description:
This method is invoked in response to a Pnp QueryPnpDeviceState IRP.
Arguments:
Irp - a pointer to the FxIrp
Returns:
NTSTATUS
--*/
{
FxPkgFdo* pThis;
NTSTATUS status;
pThis = (FxPkgFdo*) This;
status = pThis->SendIrpSynchronously(Irp);
if (status == STATUS_NOT_SUPPORTED) {
//
// Morph into a successful code so that we process the request
//
status = STATUS_SUCCESS;
Irp->SetStatus(status);
}
if (NT_SUCCESS(status)) {
pThis->HandleQueryPnpDeviceStateCompletion(Irp);
}
else {
DoTraceLevelMessage(
This->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
"Lower stack returned error for query pnp device state, %!STATUS!",
status);
}
//
// Since we already sent the request down the stack, we must complete it
// now.
//
return pThis->CompletePnpRequest(Irp, status);
}
_Must_inspect_result_
NTSTATUS
FxPkgFdo::Initialize(
__in PWDFDEVICE_INIT DeviceInit
)
/*++
Routine Description:
After creating a FxPkgFdo, the driver writer will initialize it by passing
a set of driver callbacks that allow the driver writer to customize the
behavior when handling certain IRPs.
This is the place to do any initialization that might fail.
Arguments:
Device - a pointer to the FxDevice
DispatchTable - a driver supplied table of callbacks
Returns:
NTSTATUS
--*/
{
PFX_DRIVER_GLOBALS pGlobals;
WDF_CHILD_LIST_CONFIG config;
size_t totalDescriptionSize = 0;
WDFCHILDLIST hList;
NTSTATUS status;
pGlobals = GetDriverGlobals();
status = FxPkgPnp::Initialize(DeviceInit);
if (!NT_SUCCESS(status)) {
return status;
}
status = AllocateEnumInfo();
if (!NT_SUCCESS(status)) {
return status;
}
#pragma prefast(suppress: __WARNING_PASSING_FUNCTION_UNEXPECTED_NULL, "Static child lists do not use the EvtChildListCreateDevice callback")
WDF_CHILD_LIST_CONFIG_INIT(&config,
sizeof(FxStaticChildDescription),
NULL);
status = FxChildList::_ComputeTotalDescriptionSize(pGlobals,
&config,
&totalDescriptionSize);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxChildList::_CreateAndInit(&m_StaticDeviceList,
pGlobals,
WDF_NO_OBJECT_ATTRIBUTES,
totalDescriptionSize,
m_Device,
&config,
TRUE);
if (!NT_SUCCESS(status)) {
return status;
}
status = m_StaticDeviceList->Commit(WDF_NO_OBJECT_ATTRIBUTES,
(WDFOBJECT*) &hList,
m_Device);
if (!NT_SUCCESS(status)) {
m_StaticDeviceList->DeleteFromFailedCreate();
m_StaticDeviceList = NULL;
return status;
}
//
// This will be released in the destructor
//
m_StaticDeviceList->ADDREF(this);
return status;
}
_Must_inspect_result_
NTSTATUS
FxPkgFdo::QueryForDsfInterface(
VOID
)
{
// __REACTOS__ : not supported
// WDF_DSF_INTERFACE dsfInterface;
// NTSTATUS status;
// BOOLEAN derefQI = FALSE;
// RtlZeroMemory(&dsfInterface, sizeof(dsfInterface));
// //
// // Since there are some stacks that are not PnP re-entrant (like USBHUB,
// // xpsp2), we specify that the QI goes only to our attached device and
// // not to the top of the stack as a normal QI irp would.
// //
// // We also do this a preventative measure for other stacks we don't know
// // about internally and do not have access to when testing.
// //
// status = m_Device->QueryForInterface(&GUID_WDF_DSF_INTERFACE,
// (PINTERFACE) &dsfInterface,
// sizeof(dsfInterface),
// WDM_DSF_INTERFACE_V1_0,
// NULL,
// m_Device->GetAttachedDevice()
// );
// if (status == STATUS_NOT_SUPPORTED) {
// DoTraceLevelMessage(
// GetDriverGlobals(), TRACE_LEVEL_WARNING, TRACINGPNP,
// "Lower stack does not have a DSF interface");
// status = STATUS_SUCCESS;
// goto Done;
// }
// if (!NT_SUCCESS(status)) {
// DoTraceLevelMessage(
// GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
// "Lower stack returned an error for query DSF interface, %!STATUS!",
// status);
// goto Done;
// }
// derefQI = TRUE;
// //
// // Basic run time checks.
// //
// if (dsfInterface.Interface.Version != WDM_DSF_INTERFACE_V1_0) {
// status = STATUS_REVISION_MISMATCH;
// DoTraceLevelMessage(
// GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
// "Lower DSF stack supports v(%x), requested v(%x), %!STATUS!",
// dsfInterface.Interface.Version,
// WDM_DSF_INTERFACE_V1_0,
// status);
// goto Done;
// }
// //
// // Ex functions should be both set or cleared.
// // Active/Inactive functions should be both set or cleared.
// // Ex function must be present.
// // Note: !!(ptr) expression below converts ptr value to true/false value.
// // I.e., ptr==NULL to false and ptr!=NULL to true.
// //
// if (!((!!(dsfInterface.IoConnectInterruptEx) ==
// !!(dsfInterface.IoDisconnectInterruptEx)) &&
// (!!(dsfInterface.IoReportInterruptActive) ==
// !!(dsfInterface.IoReportInterruptInactive)) &&
// (dsfInterface.IoConnectInterruptEx != NULL)
// )) {
// status = STATUS_DATA_ERROR;
// DoTraceLevelMessage(
// GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
// "Function mismatch detected in DSF interface, %!STATUS!",
// status);
// goto Done;
// }
// //
// // Info is correct.
// //
// m_IoConnectInterruptEx = dsfInterface.IoConnectInterruptEx;
// m_IoDisconnectInterruptEx = dsfInterface.IoDisconnectInterruptEx;
// //
// // If DSF interface provides active/inactive functions then use them
// //
// if (dsfInterface.IoReportInterruptActive != NULL)
// {
// m_IoReportInterruptActive = dsfInterface.IoReportInterruptActive;
// m_IoReportInterruptInactive = dsfInterface.IoReportInterruptInactive;
// }
// Done:
// //
// // The contract with the DSF layer is to release the interface right away;
// // the embedded interrupt function ptrs will be valid until this driver is
// // unloaded.
// //
// if (derefQI) {
// dsfInterface.Interface.InterfaceDereference(dsfInterface.Interface.Context);
// }
// return status;
return STATUS_NOT_IMPLEMENTED;
}
_Must_inspect_result_
NTSTATUS
FxPkgFdo::AskParentToRemoveAndReenumerate(
VOID
)
/*++
Routine Description:
This routine asks the PDO to ask its parent bus driver to Surprise-Remove
and re-enumerate the PDO. This will be done only at the point of
catastrophic software failure, and occasionally after catastrophic hardware
failure.
Arguments:
None
Return Value:
status
--*/
{
PREENUMERATE_SELF_INTERFACE_STANDARD pInterface;
pInterface = &m_SurpriseRemoveAndReenumerateSelfInterface;
if (pInterface->SurpriseRemoveAndReenumerateSelf != NULL) {
pInterface->SurpriseRemoveAndReenumerateSelf(pInterface->Context);
return STATUS_SUCCESS;
}
return STATUS_NOT_SUPPORTED;
}