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

296 lines
7.2 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Module Name:
FxRegKey.cpp
Abstract:
Author:
Environment:
kernel mode only
Revision History:
--*/
#include "fxsupportpch.hpp"
extern "C" {
// #include "FxRegKeyKM.tmh"
}
#define AT_PASSIVE() ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL)
FxRegKey::FxRegKey(
PFX_DRIVER_GLOBALS FxDriverGlobals
) :
FxPagedObject(FX_TYPE_REG_KEY, sizeof(FxRegKey), FxDriverGlobals),
m_Key(NULL),
m_Globals(FxDriverGlobals)
{
}
__drv_maxIRQL(PASSIVE_LEVEL)
FxRegKey::~FxRegKey()
{
if (m_Key != NULL) {
ZwClose(m_Key);
m_Key = NULL;
}
}
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
FxRegKey::_Close(
__in HANDLE Key
)
{
return ZwClose(Key);
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
FxRegKey::_Create(
__in_opt HANDLE ParentKey,
__in PCUNICODE_STRING KeyName,
__out HANDLE* NewKey,
__in ACCESS_MASK DesiredAccess,
__in ULONG CreateOptions,
__out_opt PULONG CreateDisposition
)
{
OBJECT_ATTRIBUTES oa;
AT_PASSIVE();
//
// Force OBJ_KERNEL_HANDLE because we are never passing the handle back
// up to a process and we don't want to create a handle in an arbitrary
// process from which that process can close the handle out from underneath
// us.
//
InitializeObjectAttributes(
&oa,
(PUNICODE_STRING) KeyName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
ParentKey,
NULL);
return ZwCreateKey(NewKey,
DesiredAccess,
&oa,
0,
0,
CreateOptions,
CreateDisposition);
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
FxRegKey::_OpenKey(
__in_opt HANDLE ParentKey,
__in PCUNICODE_STRING KeyName,
__out HANDLE* Key,
__in ACCESS_MASK DesiredAccess
)
{
OBJECT_ATTRIBUTES oa;
AT_PASSIVE();
//
// Force OBJ_KERNEL_HANDLE because we are never passing the handle back
// up to a process and we don't want to create a handle in an arbitrary
// process from which that process can close the handle out from underneath
// us.
//
InitializeObjectAttributes(
&oa,
(PUNICODE_STRING)KeyName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
ParentKey,
NULL);
return ZwOpenKey(Key, DesiredAccess, &oa);
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
FxRegKey::_SetValue(
_In_ HANDLE Key,
__in PCUNICODE_STRING ValueName,
__in ULONG ValueType,
__in_bcount(ValueLength) PVOID Value,
__in ULONG ValueLength
)
{
AT_PASSIVE();
return ZwSetValueKey(Key,
(PUNICODE_STRING)ValueName,
0,
ValueType,
Value,
ValueLength);
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
FxRegKey::_QueryValue(
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
__in HANDLE Key,
__in PCUNICODE_STRING ValueName,
__in ULONG ValueLength,
__out_bcount_opt(ValueLength) PVOID Value,
__out_opt PULONG ValueLengthQueried,
__out_opt PULONG ValueType
)
{
KEY_VALUE_PARTIAL_INFORMATION *pPartial, partial;
NTSTATUS status;
ULONG length;
if (Value == NULL) {
//
// Caller wants just the length
//
pPartial = &partial;
length = _ComputePartialSize(0);
RtlZeroMemory(&partial, length);
}
else {
length = _ComputePartialSize(ValueLength);
pPartial = (PKEY_VALUE_PARTIAL_INFORMATION)
MxMemory::MxAllocatePoolWithTag(PagedPool, length, FxDriverGlobals->Tag);
if (pPartial == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
}
//
// We always pass a buffer of at least sizeof(KEY_VALUE_PARTIAL_INFORMATION)
// to ZwQueryValueKey. This means that ZwQueryValueKey will write at least
// some information to the buffer it receives, even if the user-supplied data
// buffer is NULL or too small.
//
// According to ZwQueryValueKey's contract, this means that it will never return
// STATUS_BUFFER_TOO_SMALL (returned when no data is written). Therefore, if the
// user passes a NULL or insufficient buffer and the value exists in the registry,
// ZwQueryValueKey will return STATUS_BUFFER_OVERFLOW.
//
status = ZwQueryValueKey(Key,
(PUNICODE_STRING)ValueName,
KeyValuePartialInformation,
pPartial,
length,
&length);
if (NT_SUCCESS(status) && Value != NULL && (ValueLength >= pPartial->DataLength)) {
RtlCopyMemory(Value, &pPartial->Data[0], pPartial->DataLength);
}
if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) {
if (ValueLengthQueried != NULL) {
*ValueLengthQueried = pPartial->DataLength;
}
if (ValueType != NULL) {
*ValueType = pPartial->Type;
}
}
if (pPartial != &partial) {
MxMemory::MxFreePool(pPartial);
}
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
FxRegKey::_QueryULong(
__in HANDLE Key,
__in PCUNICODE_STRING ValueName,
__out PULONG Value
)
{
NTSTATUS status;
ULONG length;
PKEY_VALUE_PARTIAL_INFORMATION pPartial;
UCHAR buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data)+(sizeof(ULONG))];
length = sizeof(buffer);
pPartial = (PKEY_VALUE_PARTIAL_INFORMATION) &buffer[0];
status = ZwQueryValueKey(Key,
(PUNICODE_STRING)ValueName,
KeyValuePartialInformation,
pPartial,
length,
&length);
if ((NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) &&
pPartial->Type != REG_DWORD) {
status = STATUS_OBJECT_TYPE_MISMATCH;
}
if (NT_SUCCESS(status)) {
ASSERT(sizeof(ULONG) == pPartial->DataLength);
RtlCopyMemory(Value, &pPartial->Data[0], sizeof(ULONG));
}
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
FxRegKey::_QueryQuadWord(
__in HANDLE Key,
__in PCUNICODE_STRING ValueName,
__out PLARGE_INTEGER Value
)
{
NTSTATUS status;
ULONG length;
PKEY_VALUE_PARTIAL_INFORMATION pPartial;
UCHAR buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data)+(sizeof(LARGE_INTEGER))];
length = sizeof(buffer);
pPartial = (PKEY_VALUE_PARTIAL_INFORMATION) &buffer[0];
status = ZwQueryValueKey(Key,
(PUNICODE_STRING)ValueName,
KeyValuePartialInformation,
pPartial,
length,
&length);
if ((NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) &&
pPartial->Type != REG_QWORD) {
status = STATUS_OBJECT_TYPE_MISMATCH;
}
if (NT_SUCCESS(status)) {
ASSERT(sizeof(LARGE_INTEGER) == pPartial->DataLength);
RtlCopyMemory(Value, &pPartial->Data[0], sizeof(LARGE_INTEGER));
}
return status;
}