reactos/sdk/lib/drivers/wdf/shared/support/fxdeviceinterfaceapi.cpp

404 lines
10 KiB
C++
Raw Normal View History

/*++
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"