reactos/sdk/lib/drivers/wdf/shared/inc/private/um/fxdeviceum.hpp

461 lines
14 KiB
C++
Raw Normal View History

/*++
Copyright (c) Microsoft Corporation
Module Name:
FxDeviceUM.hpp
Abstract:
This is the definition of the FxDevice object UM specific
Author:
Environment:
User mode only
Revision History:
--*/
#ifndef _FXDEVICEUM_H_
#define _FXDEVICEUM_H_
#define WDF_PATH_SEPARATOR L"\\"
#define WUDF_SUB_KEY L"WUDF"
#define WUDF_ADDITIONAL_SUB_KEY L"WDF"
#define FX_DIRECT_HARDWARE_ACCESS L"DirectHardwareAccess"
#define FX_DIRECT_HARDWARE_ACCESS_DEFAULT (WdfRejectDirectHardwareAccess)
#define FX_REGISTER_ACCESS_MODE L"RegisterAccessMode"
#define FX_REGISTER_ACCESS_MODE_DEFAULT (WdfRegisterAccessUsingSystemCall)
#define FX_FILE_OBJECT_POLICY L"FileObjectPolicy"
#define FX_FILE_OBJECT_POLICY_DEFAULT (WdfRejectNullAndUnknownFileObjects)
#define FX_FS_CONTEXT_USE_POLICY L"FsContextUsePolicy"
#define FX_FS_CONTEXT_USE_POLICY_DEFAULT (WdfDefaultFsContextUsePolicy)
#define FX_KERNEL_MODE_CLIENT_POLICY L"KernelModeClientPolicy"
#define FX_METHOD_NEITHER_ACTION L"MethodNeitherAction"
#define FX_PROCESS_SHARING_ENABLED L"HostProcessSharingEnabled"
#define FX_DEVICE_GROUP_ID L"DeviceGroupId"
#define FX_FILE_OBJECT_POLICY L"FileObjectPolicy"
//
// READ/WRITE_REGISTER_Xxx macros need compiler and memory barrier. Each
// platform has a different set of compiler intrinsics to support that.
// In kernel, x86 READ/WRITE macros are implemented in assembly and use
// lock prefix to force real access. For amd64, _ReadWriteBarrier
// (compiler barrier) is used for reads and __faststorefence (CPU barrier) for
// writes. For ARM, _ReadWriteBarrier (compiler barrier) is used for reads and
// both _ReadWriteBarrier and __emit(Value) for writes.
//
// Because of this variation, UMDF will use the macros directly from wdm.h
// by autogenerating those macros from wdm.h into a private UMDF header.
// For x86, there are no macros so either UMDF could directly link to the
// ntosrtl.lib (that has these macros implemented in assembly), or implement
// its own macros that use MemoryBarrier() macro from winnt.h.
//
// Below is UMDF's implementation for x86. The macros for other platforms are
// in WudfWdm_private.h.
//
#if defined(_X86_)
#define READ_REGISTER_UCHAR(x) \
(MemoryBarrier(), *(volatile UCHAR * const)(x))
#define READ_REGISTER_USHORT(x) \
(MemoryBarrier(), *(volatile USHORT * const)(x))
#define READ_REGISTER_ULONG(x) \
(MemoryBarrier(), *(volatile ULONG * const)(x))
#define READ_REGISTER_ULONG64(x) \
(MemoryBarrier(), *(volatile ULONG64 * const)(x))
#define READ_REGISTER_BUFFER_UCHAR(x, y, z) { \
PUCHAR registerBuffer = x; \
PUCHAR readBuffer = y; \
ULONG readCount; \
MemoryBarrier(); \
for (readCount = z; readCount--; readBuffer++, registerBuffer++) { \
*readBuffer = *(volatile UCHAR * const)(registerBuffer); \
} \
}
#define READ_REGISTER_BUFFER_USHORT(x, y, z) { \
PUSHORT registerBuffer = x; \
PUSHORT readBuffer = y; \
ULONG readCount; \
MemoryBarrier(); \
for (readCount = z; readCount--; readBuffer++, registerBuffer++) { \
*readBuffer = *(volatile USHORT * const)(registerBuffer); \
} \
}
#define READ_REGISTER_BUFFER_ULONG(x, y, z) { \
PULONG registerBuffer = x; \
PULONG readBuffer = y; \
ULONG readCount; \
MemoryBarrier(); \
for (readCount = z; readCount--; readBuffer++, registerBuffer++) { \
*readBuffer = *(volatile ULONG * const)(registerBuffer); \
} \
}
#define READ_REGISTER_BUFFER_ULONG64(x, y, z) { \
PULONG64 registerBuffer = x; \
PULONG64 readBuffer = y; \
ULONG readCount; \
MemoryBarrier(); \
for (readCount = z; readCount--; readBuffer++, registerBuffer++) { \
*readBuffer = *(volatile ULONG64 * const)(registerBuffer); \
} \
}
#define WRITE_REGISTER_UCHAR(x, y) { \
*(volatile UCHAR * const)(x) = y; \
MemoryBarrier(); \
}
#define WRITE_REGISTER_USHORT(x, y) { \
*(volatile USHORT * const)(x) = y; \
MemoryBarrier(); \
}
#define WRITE_REGISTER_ULONG(x, y) { \
*(volatile ULONG * const)(x) = y; \
MemoryBarrier(); \
}
#define WRITE_REGISTER_ULONG64(x, y) { \
*(volatile ULONG64 * const)(x) = y; \
MemoryBarrier(); \
}
#define WRITE_REGISTER_BUFFER_UCHAR(x, y, z) { \
PUCHAR registerBuffer = x; \
PUCHAR writeBuffer = y; \
ULONG writeCount; \
for (writeCount = z; writeCount--; writeBuffer++, registerBuffer++) { \
*(volatile UCHAR * const)(registerBuffer) = *writeBuffer; \
} \
MemoryBarrier(); \
}
#define WRITE_REGISTER_BUFFER_USHORT(x, y, z) { \
PUSHORT registerBuffer = x; \
PUSHORT writeBuffer = y; \
ULONG writeCount; \
for (writeCount = z; writeCount--; writeBuffer++, registerBuffer++) { \
*(volatile USHORT * const)(registerBuffer) = *writeBuffer; \
} \
MemoryBarrier(); \
}
#define WRITE_REGISTER_BUFFER_ULONG(x, y, z) { \
PULONG registerBuffer = x; \
PULONG writeBuffer = y; \
ULONG writeCount; \
for (writeCount = z; writeCount--; writeBuffer++, registerBuffer++) { \
*(volatile ULONG * const)(registerBuffer) = *writeBuffer; \
} \
MemoryBarrier(); \
}
#define WRITE_REGISTER_BUFFER_ULONG64(x, y, z) { \
PULONG64 registerBuffer = x; \
PULONG64 writeBuffer = y; \
ULONG writeCount; \
for (writeCount = z; writeCount--; writeBuffer++, registerBuffer++) { \
*(volatile ULONG64 * const)(registerBuffer) = *writeBuffer; \
} \
MemoryBarrier(); \
}
#endif // _X86_
__inline
SIZE_T
FxDevice::ReadRegister(
__in WDF_DEVICE_HWACCESS_TARGET_SIZE Size,
__in PVOID Register
)
{
SIZE_T value = 0;
//
// ETW start event for perf measurement
//
EventWriteEVENT_UMDF_FX_READ_FROM_HARDWARE_START(
WdfDeviceHwAccessTargetTypeRegister, Size, 0);
switch(Size) {
case WdfDeviceHwAccessTargetSizeUchar:
value = READ_REGISTER_UCHAR((PUCHAR)Register);
break;
case WdfDeviceHwAccessTargetSizeUshort:
value = READ_REGISTER_USHORT((PUSHORT)Register);
break;
case WdfDeviceHwAccessTargetSizeUlong:
value = READ_REGISTER_ULONG((PULONG)Register);
break;
case WdfDeviceHwAccessTargetSizeUlong64:
#if defined(_WIN64)
value = READ_REGISTER_ULONG64((PULONG64)Register);
#else
FX_VERIFY(DRIVER(BadArgument, TODO), CHECK("Invalid call to ULONG64 "
"hardware access function", FALSE));
#endif
break;
default:
FX_VERIFY(INTERNAL, TRAPMSG("Unexpected"));
break;
}
//
// ETW end event for perf measurement
//
EventWriteEVENT_UMDF_FX_READ_FROM_HARDWARE_END(
WdfDeviceHwAccessTargetTypeRegister, Size, 0);
return value;
}
__inline
VOID
FxDevice::ReadRegisterBuffer(
__in WDF_DEVICE_HWACCESS_TARGET_SIZE Size,
__in PVOID Register,
__out_ecount_full(Count) PVOID Buffer,
__in ULONG Count
)
{
//
// ETW start event for perf measurement
//
EventWriteEVENT_UMDF_FX_READ_FROM_HARDWARE_START(
WdfDeviceHwAccessTargetTypeRegisterBuffer, Size, Count);
switch(Size) {
case WdfDeviceHwAccessTargetSizeUchar:
READ_REGISTER_BUFFER_UCHAR(((PUCHAR)Register), (PUCHAR)Buffer, Count );
break;
case WdfDeviceHwAccessTargetSizeUshort:
#pragma prefast(suppress:26000, "The Size parameter dictates the buffer size")
READ_REGISTER_BUFFER_USHORT(((PUSHORT)Register), (PUSHORT)Buffer, Count );
break;
case WdfDeviceHwAccessTargetSizeUlong:
READ_REGISTER_BUFFER_ULONG(((PULONG)Register), (PULONG)Buffer, Count );
break;
case WdfDeviceHwAccessTargetSizeUlong64:
#if defined(_WIN64)
READ_REGISTER_BUFFER_ULONG64(((PULONG64)Register), (PULONG64)Buffer, Count );
#else
FX_VERIFY(DRIVER(BadArgument, TODO), CHECK("Invalid call to ULONG64 "
"hardware access function", FALSE));
#endif
break;
default:
FX_VERIFY(INTERNAL, TRAPMSG("Unexpected"));
break;
}
//
// ETW start event for perf measurement
//
EventWriteEVENT_UMDF_FX_READ_FROM_HARDWARE_END(
WdfDeviceHwAccessTargetTypeRegisterBuffer, Size, Count);
}
__inline
VOID
FxDevice::WriteRegister(
__in WDF_DEVICE_HWACCESS_TARGET_SIZE Size,
__in PVOID Register,
__in SIZE_T Value
)
{
//
// ETW start event for perf measurement
//
EventWriteEVENT_UMDF_FX_WRITE_TO_HARDWARE_START(
WdfDeviceHwAccessTargetTypeRegister, Size, 0);
switch(Size) {
case WdfDeviceHwAccessTargetSizeUchar:
WRITE_REGISTER_UCHAR((PUCHAR)Register, (UCHAR)Value);
break;
case WdfDeviceHwAccessTargetSizeUshort:
WRITE_REGISTER_USHORT((PUSHORT)Register, (USHORT)Value);
break;
case WdfDeviceHwAccessTargetSizeUlong:
WRITE_REGISTER_ULONG((PULONG)Register, (ULONG)Value);
break;
case WdfDeviceHwAccessTargetSizeUlong64:
#if defined(_WIN64)
WRITE_REGISTER_ULONG64((PULONG64)Register, (ULONG64)Value);
#else
FX_VERIFY(DRIVER(BadArgument, TODO), CHECK("Invalid call to ULONG64 "
"hardware access function", FALSE));
#endif
break;
default:
FX_VERIFY(INTERNAL, TRAPMSG("Unexpected"));
break;
}
//
// ETW start event for perf measurement
//
EventWriteEVENT_UMDF_FX_WRITE_TO_HARDWARE_END(
WdfDeviceHwAccessTargetTypeRegister, Size, 0);
}
__inline
VOID
FxDevice::WriteRegisterBuffer(
__in WDF_DEVICE_HWACCESS_TARGET_SIZE Size,
__in PVOID Register,
__in_ecount(Count) PVOID Buffer,
__in ULONG Count
)
{
//
// ETW start event for perf measurement
//
EventWriteEVENT_UMDF_FX_WRITE_TO_HARDWARE_START(
WdfDeviceHwAccessTargetTypeRegisterBuffer, Size, Count);
switch(Size) {
case WdfDeviceHwAccessTargetSizeUchar:
WRITE_REGISTER_BUFFER_UCHAR(((PUCHAR)Register), (PUCHAR)Buffer, Count);
break;
case WdfDeviceHwAccessTargetSizeUshort:
#pragma prefast(suppress:26000, "The Size parameter dictates the buffer size")
WRITE_REGISTER_BUFFER_USHORT(((PUSHORT)Register), (PUSHORT)Buffer, Count);
break;
case WdfDeviceHwAccessTargetSizeUlong:
WRITE_REGISTER_BUFFER_ULONG(((PULONG)Register), (PULONG)Buffer, Count);
break;
case WdfDeviceHwAccessTargetSizeUlong64:
#if defined(_WIN64)
WRITE_REGISTER_BUFFER_ULONG64(((PULONG64)Register), (PULONG64)Buffer, Count);
#else
FX_VERIFY(DRIVER(BadArgument, TODO), CHECK("Invalid call to ULONG64 "
"hardware access function", FALSE));
#endif
break;
default:
FX_VERIFY(INTERNAL, TRAPMSG("Unexpected"));
break;
}
//
// ETW start event for perf measurement
//
EventWriteEVENT_UMDF_FX_WRITE_TO_HARDWARE_END(
WdfDeviceHwAccessTargetTypeRegisterBuffer, Size, Count);
}
__inline
FxWdmDeviceExtension*
FxDevice::_GetFxWdmExtension(
__in MdDeviceObject DeviceObject
)
{
return (FxWdmDeviceExtension*)
((static_cast<IWudfDevice2*> (DeviceObject))->GetDeviceExtension());
}
__inline
BOOLEAN
FxDevice::IsRemoveLockEnabledForIo(
VOID
)
{
return FALSE;
}
__inline
MdRemoveLock
FxDevice::GetRemoveLock(
VOID
)
{
return &FxDevice::_GetFxWdmExtension(
GetDeviceObject())->IoRemoveLock;
}
__inline
NTSTATUS
FxDevice::WmiPkgRegister(
VOID
)
{
//
// WMI doesn't apply for UMDF
//
DO_NOTHING();
return STATUS_SUCCESS;
}
__inline
VOID
FxDevice::WmiPkgDeregister(
VOID
)
{
//
// WMI doesn't apply for UMDF
//
DO_NOTHING();
}
__inline
VOID
FxDevice::WmiPkgCleanup(
VOID
)
{
//
// WMI doesn't apply for UMDF
//
DO_NOTHING();
}
__inline
IWudfDeviceStack*
FxDevice::GetDeviceStack(
VOID
)
{
return m_DevStack;
}
__inline
IWudfDeviceStack2 *
FxDevice::GetDeviceStack2(
)
{
IWudfDeviceStack2 *pDeviceStack2;
HRESULT hrQI;
hrQI = m_DevStack->QueryInterface(IID_IWudfDeviceStack2,
(PVOID*)&pDeviceStack2);
FX_VERIFY(INTERNAL, CHECK_QI(hrQI, pDeviceStack2));
m_DevStack->Release();
return pDeviceStack2;
}
#endif //_FXDEVICEUM_H_