reactos/sdk/lib/drivers/wdf/shared/support/fxdeviceinterfaceapi.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

404 lines
10 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Module Name:
FxDeviceInterfaceAPI.cpp
Abstract:
This module implements the device interface object external APIs
Author:
Environment:
kernel and user mode
Revision History:
--*/
#include "fxsupportpch.hpp"
extern "C" {
// #include "FxDeviceInterfaceAPI.tmh"
}
//
// extern "C" the entire file
//
extern "C" {
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfDeviceCreateDeviceInterface)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFDEVICE Device,
__in
CONST GUID *InterfaceClassGUID,
__in_opt
PCUNICODE_STRING ReferenceString
)
/*++
Routine Description:
Creates a device interface associated with the passed in device object
Arguments:
Device - Handle which represents the device exposing the interface
InterfaceGUID - GUID describing the interface being exposed
ReferenceString - OPTIONAL string which allows the driver writer to
distinguish between different exposed interfaces
Return Value:
STATUS_SUCCESS or appropriate NTSTATUS code
--*/
{
DDI_ENTRY();
SINGLE_LIST_ENTRY **ppPrev, *pCur;
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxDeviceInterface *pDeviceInterface;
FxDevice *pDevice;
FxPkgPnp* pPkgPnp;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Device,
FX_TYPE_DEVICE,
(PVOID*) &pDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, InterfaceClassGUID);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
if (ReferenceString != NULL) {
status = FxValidateUnicodeString(pFxDriverGlobals, ReferenceString);
if (!NT_SUCCESS(status)) {
return status;
}
}
if (pDevice->IsLegacy()) {
status = STATUS_INVALID_DEVICE_REQUEST;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFDEVICE %p is not a PNP device, device interface creation not "
"allowed %!STATUS!", Device, status);
return status;
}
pDeviceInterface = new(pFxDriverGlobals, PagedPool) FxDeviceInterface();
if (pDeviceInterface == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFDEVICE %p DeviceInterface object creation failed, %!STATUS!",
Device, status);
return status;
}
status = pDeviceInterface->Initialize(pFxDriverGlobals,
InterfaceClassGUID,
ReferenceString);
if (!NT_SUCCESS(status)) {
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFDEVICE %p, DeviceInterface object initialization failed, %!STATUS!",
Device, status );
goto Done;
}
pPkgPnp = pDevice->m_PkgPnp;
pPkgPnp->m_DeviceInterfaceLock.AcquireLock(pFxDriverGlobals);
status = pDeviceInterface->Register(pDevice);
if (NT_SUCCESS(status)) {
//
// Insert into the end of the list
//
ppPrev = &pPkgPnp->m_DeviceInterfaceHead.Next;
pCur = pPkgPnp->m_DeviceInterfaceHead.Next;
while (pCur != NULL) {
ppPrev = &pCur->Next;
pCur = pCur->Next;
}
*ppPrev = &pDeviceInterface->m_Entry;
}
pPkgPnp->m_DeviceInterfaceLock.ReleaseLock(pFxDriverGlobals);
Done:
if (!NT_SUCCESS(status)) {
delete pDeviceInterface;
pDeviceInterface = NULL;
}
return status;
}
__drv_maxIRQL(PASSIVE_LEVEL)
VOID
STDCALL
WDFEXPORT(WdfDeviceSetDeviceInterfaceState)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFDEVICE Device,
__in
CONST GUID *InterfaceClassGUID,
__in_opt
PCUNICODE_STRING RefString,
__in
BOOLEAN State
)
{
DDI_ENTRY();
PSINGLE_LIST_ENTRY ple;
PFX_DRIVER_GLOBALS pFxDriverGlobals;
NTSTATUS status;
FxDevice* pDevice;
FxPkgPnp* pPkgPnp;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Device,
FX_TYPE_DEVICE,
(PVOID*) &pDevice,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, InterfaceClassGUID);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
FxVerifierDbgBreakPoint(pFxDriverGlobals);
return;
}
if (RefString != NULL) {
status = FxValidateUnicodeString(pFxDriverGlobals, RefString);
if (!NT_SUCCESS(status)) {
FxVerifierDbgBreakPoint(pFxDriverGlobals);
return;
}
}
if (pDevice->IsLegacy()) {
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFDEVICE %p is not a PNP device, device interfaces not allowed",
Device);
FxVerifierDbgBreakPoint(pFxDriverGlobals);
return;
}
pPkgPnp = pDevice->m_PkgPnp;
pPkgPnp->m_DeviceInterfaceLock.AcquireLock(pFxDriverGlobals);
//
// Iterate over the interfaces and see if we have a match
//
for (ple = pPkgPnp->m_DeviceInterfaceHead.Next; ple != NULL; ple = ple->Next) {
FxDeviceInterface *pDI;
pDI = FxDeviceInterface::_FromEntry(ple);
if (FxIsEqualGuid(&pDI->m_InterfaceClassGUID, InterfaceClassGUID)) {
if (RefString != NULL) {
if ((RefString->Length == pDI->m_ReferenceString.Length)
&&
(RtlCompareMemory(RefString->Buffer,
pDI->m_ReferenceString.Buffer,
RefString->Length) == RefString->Length)) {
//
// They match, carry on
//
DO_NOTHING();
}
else {
//
// The ref strings do not match, continue on in the search
// of the collection.
//
continue;
}
}
else if (pDI->m_ReferenceString.Length > 0) {
//
// Caller didn't specify a ref string but this interface has
// one, continue on in the search through the collection.
//
continue;
}
//
// Set the state and break out of the loop because we found our
// interface.
//
pDI->SetState(State);
break;
}
}
pPkgPnp->m_DeviceInterfaceLock.ReleaseLock(pFxDriverGlobals);
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfDeviceRetrieveDeviceInterfaceString)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFDEVICE Device,
__in
CONST GUID* InterfaceClassGUID,
__in_opt
PCUNICODE_STRING RefString,
__in
WDFSTRING String
)
/*++
Routine Description:
Returns the symbolic link value of the registered device interface.
Arguments:
Return Value:
--*/
{
DDI_ENTRY();
PSINGLE_LIST_ENTRY ple;
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxDevice* pDevice;
FxPkgPnp* pPkgPnp;
FxString* pString;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Device,
FX_TYPE_DEVICE,
(PVOID*) &pDevice,
&pFxDriverGlobals );
FxPointerNotNull(pFxDriverGlobals, InterfaceClassGUID);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
if (RefString != NULL) {
status = FxValidateUnicodeString(pFxDriverGlobals, RefString);
if (!NT_SUCCESS(status)) {
return status;
}
}
if (pDevice->IsLegacy()) {
status = STATUS_INVALID_DEVICE_REQUEST;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFDEVICE %p is not a PNP device, device interface creation not "
"allowed %!STATUS!", Device, status);
return status;
}
FxObjectHandleGetPtr(pFxDriverGlobals,
String,
FX_TYPE_STRING,
(PVOID*) &pString);
pPkgPnp = pDevice->m_PkgPnp;
status = STATUS_OBJECT_NAME_NOT_FOUND;
pPkgPnp->m_DeviceInterfaceLock.AcquireLock(pFxDriverGlobals);
//
// Iterate over the interfaces and see if we have a match
//
for (ple = pPkgPnp->m_DeviceInterfaceHead.Next;
ple != NULL;
ple = ple->Next) {
FxDeviceInterface *pDI;
pDI = FxDeviceInterface::_FromEntry(ple);
if (FxIsEqualGuid(&pDI->m_InterfaceClassGUID, InterfaceClassGUID)) {
if (RefString != NULL) {
if ((RefString->Length == pDI->m_ReferenceString.Length)
&&
(RtlCompareMemory(RefString->Buffer,
pDI->m_ReferenceString.Buffer,
RefString->Length) == RefString->Length)) {
//
// They match, carry on
//
DO_NOTHING();
}
else {
//
// The ref strings do not match, continue on in the search
// of the collection.
//
continue;
}
}
else if (pDI->m_ReferenceString.Length > 0) {
//
// Caller didn't specify a ref string but this interface has
// one, continue on in the search through the collection.
//
continue;
}
status = pDI->GetSymbolicLinkName(pString);
break;
}
}
pPkgPnp->m_DeviceInterfaceLock.ReleaseLock(pFxDriverGlobals);
return status;
}
} // extern "C"