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

1550 lines
41 KiB
C++
Raw Normal View History

/*++
Copyright (c) Microsoft Corporation
Module Name:
FxRegistryAPI.cpp
Abstract:
This module implements registry access in the framework
Author:
Environment:
Both kernel and user mode
Revision History:
--*/
#include "fxsupportpch.hpp"
extern "C" {
// #include "FxRegistryAPI.tmh"
#define RtlSizeTToULong RtlULongPtrToULong
}
extern "C" {
//
// Not in a public header that we can reach, but is documented
//
NTSYSAPI
NTSTATUS
NTAPI
ZwDeleteValueKey(
__in IN HANDLE Key,
__in IN PUNICODE_STRING ValueName
);
}
//
// Extern "C" the entire file
//
extern "C" {
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfRegistryOpenKey)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in_opt
WDFKEY ParentKey,
__in
PCUNICODE_STRING KeyName,
__in
ACCESS_MASK DesiredAccess,
__in_opt
PWDF_OBJECT_ATTRIBUTES KeyAttributes,
__out
WDFKEY* Key
)
{
DDI_ENTRY();
FxRegKey* pKey;
PFX_DRIVER_GLOBALS pFxDriverGlobals;
NTSTATUS status;
WDFKEY keyHandle;
HANDLE parentHandle;
pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
keyHandle = NULL;
if (ParentKey != NULL) {
FxRegKey* pParent;
FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals,
ParentKey,
FX_TYPE_REG_KEY,
(PVOID*) &pParent,
&pFxDriverGlobals);
parentHandle = pParent->GetHandle();
}
else {
parentHandle = NULL;
//
// Get the parent's globals if it is present
//
if (NT_SUCCESS(FxValidateObjectAttributesForParentHandle(pFxDriverGlobals,
KeyAttributes))) {
FxObject* pParent;
FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals,
KeyAttributes->ParentObject,
FX_TYPE_OBJECT,
(PVOID*)&pParent,
&pFxDriverGlobals);
}
}
FxPointerNotNull(pFxDriverGlobals, KeyName);
FxPointerNotNull(pFxDriverGlobals, Key);
*Key = NULL;
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateObjectAttributes(pFxDriverGlobals, KeyAttributes);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateUnicodeString(pFxDriverGlobals, KeyName);
if (!NT_SUCCESS(status)) {
return status;
}
pKey = new (pFxDriverGlobals, KeyAttributes) FxRegKey(pFxDriverGlobals);
if (pKey == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"Could not allocate memory for a WDFKEY, %!STATUS!", status);
return status;
}
status = pKey->Commit(KeyAttributes, (WDFOBJECT*)&keyHandle);
if (NT_SUCCESS(status)) {
status = pKey->Open(parentHandle, KeyName, DesiredAccess);
if (NT_SUCCESS(status)) {
*Key = keyHandle;
}
else {
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"new WDFKEY object open failed, %!STATUS!", status);
}
}
if (!NT_SUCCESS(status)) {
pKey->DeleteFromFailedCreate();
pKey = NULL;
}
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfRegistryCreateKey)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in_opt
WDFKEY ParentKey,
__in
PCUNICODE_STRING KeyName,
__in
ACCESS_MASK DesiredAccess,
__in
ULONG CreateOptions,
__out_opt
PULONG CreateDisposition,
__in_opt
PWDF_OBJECT_ATTRIBUTES KeyAttributes,
__out
WDFKEY* Key
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxRegKey* pKey;
NTSTATUS status;
WDFKEY keyHandle;
HANDLE parentHandle;
pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
if (ParentKey != NULL) {
FxRegKey* pParent;
FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals,
ParentKey,
FX_TYPE_REG_KEY,
(PVOID*) &pParent,
&pFxDriverGlobals);
parentHandle = pParent->GetHandle();
}
else {
parentHandle = NULL;
//
// Get the parent's globals if it is present
//
if (NT_SUCCESS(FxValidateObjectAttributesForParentHandle(pFxDriverGlobals,
KeyAttributes))) {
FxObject* pParent;
FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals,
KeyAttributes->ParentObject,
FX_TYPE_OBJECT,
(PVOID*)&pParent,
&pFxDriverGlobals);
}
}
FxPointerNotNull(pFxDriverGlobals, KeyName);
FxPointerNotNull(pFxDriverGlobals, Key);
*Key = NULL;
keyHandle = NULL;
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateObjectAttributes(pFxDriverGlobals, KeyAttributes);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateUnicodeString(pFxDriverGlobals, KeyName);
if (!NT_SUCCESS(status)) {
return status;
}
pKey = new (pFxDriverGlobals, KeyAttributes) FxRegKey(pFxDriverGlobals);
if (pKey == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"Could not allocate memory for WDFKEY, %!STATUS!", status);
return status;
}
status = pKey->Commit(KeyAttributes, (WDFOBJECT*)&keyHandle);
if (NT_SUCCESS(status)) {
status = pKey->Create(parentHandle,
KeyName,
DesiredAccess,
CreateOptions,
CreateDisposition);
if (NT_SUCCESS(status)) {
*Key = keyHandle;
}
else {
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"Registry key creation failed, %!STATUS!", status);
}
}
if (!NT_SUCCESS(status)) {
pKey->DeleteFromFailedCreate();
pKey = NULL;
}
return status;
}
__drv_maxIRQL(PASSIVE_LEVEL)
VOID
STDCALL
WDFEXPORT(WdfRegistryClose)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFKEY Key
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxRegKey* pKey;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Key,
FX_TYPE_REG_KEY,
(PVOID*) &pKey,
&pFxDriverGlobals);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
FxVerifierDbgBreakPoint(pFxDriverGlobals);
return;
}
pKey->Close();
pKey->DeleteObject();
}
__drv_maxIRQL(PASSIVE_LEVEL)
HANDLE
STDCALL
WDFEXPORT(WdfRegistryWdmGetHandle)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFKEY Key
)
{
DDI_ENTRY();
FxRegKey* pKey;
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
Key,
FX_TYPE_REG_KEY,
(PVOID*) &pKey);
return pKey->GetHandle();
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfRegistryRemoveKey)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFKEY Key
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxRegKey* pKey;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Key,
FX_TYPE_REG_KEY,
(PVOID*) &pKey,
&pFxDriverGlobals);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = Mx::MxDeleteKey(pKey->GetHandle());
if (NT_SUCCESS(status)) {
//
// pKey->GetHandle() is now useless, delete the Fx object
//
pKey->DeleteObject();
}
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfRegistryRemoveValue)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFKEY Key,
__in
PCUNICODE_STRING ValueName
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxRegKey* pKey;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Key,
FX_TYPE_REG_KEY,
(PVOID*) &pKey,
&pFxDriverGlobals);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
if (!NT_SUCCESS(status)) {
return status;
}
FxPointerNotNull(pFxDriverGlobals, ValueName);
status = ZwDeleteValueKey(pKey->GetHandle(), (PUNICODE_STRING) ValueName);
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfRegistryQueryValue)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFKEY Key,
__in
PCUNICODE_STRING ValueName,
__in
ULONG ValueLength,
__out_bcount_opt( ValueLength)
PVOID Value,
__out_opt
PULONG ValueLengthQueried,
__out_opt
PULONG ValueType
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxRegKey* pKey;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Key,
FX_TYPE_REG_KEY,
(PVOID*) &pKey,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, ValueName);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxRegKey::_QueryValue(pFxDriverGlobals,
pKey->GetHandle(),
ValueName,
ValueLength,
Value,
ValueLengthQueried,
ValueType);
if (!NT_SUCCESS(status)) {
UCHAR traceLevel = TRACE_LEVEL_ERROR;
//
// Label message as Verbose if this is the known pattern of
// passing a 0-length NULL buffer to query the required buffer size.
//
if (status == STATUS_BUFFER_OVERFLOW && Value == NULL && ValueLength == 0) {
traceLevel = TRACE_LEVEL_VERBOSE;
}
DoTraceLevelMessage(pFxDriverGlobals, traceLevel, TRACINGERROR,
"WDFKEY %p QueryValue failed, %!STATUS!",
Key, status);
}
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfRegistryQueryMemory)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFKEY Key,
__in
PCUNICODE_STRING ValueName,
__in
__drv_strictTypeMatch( 1)
POOL_TYPE PoolType,
__in_opt
PWDF_OBJECT_ATTRIBUTES MemoryAttributes,
__out
WDFMEMORY* Memory,
__out_opt
PULONG ValueType
)
{
DDI_ENTRY();
FxRegKey* pKey;
PFX_DRIVER_GLOBALS pFxDriverGlobals;
NTSTATUS status;
ULONG dataLength;
PVOID dataBuffer;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Key,
FX_TYPE_REG_KEY,
(PVOID*) &pKey,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, ValueName);
FxPointerNotNull(pFxDriverGlobals, Memory);
*Memory = NULL;
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
FxVerifierCheckNxPoolType(pFxDriverGlobals, PoolType, pFxDriverGlobals->Tag);
status = FxValidateObjectAttributes(pFxDriverGlobals, MemoryAttributes);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
if (!NT_SUCCESS(status)) {
return status;
}
//
// Query the buffer length required.
//
status = pKey->QueryValue(ValueName, 0, NULL, &dataLength, NULL);
if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW) {
return status;
}
dataBuffer = FxPoolAllocate(pFxDriverGlobals, PagedPool, dataLength);
if (dataBuffer == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p KEY_VALUE_PARTIAL_INFORMATION allocation failed, %!STATUS!",
Key, status);
return status;
}
status = pKey->QueryValue(ValueName, dataLength, dataBuffer, &dataLength, ValueType);
if (NT_SUCCESS(status)) {
FxMemoryObject* pObject;
status = FxMemoryObject::_Create(pFxDriverGlobals,
MemoryAttributes,
PoolType,
pFxDriverGlobals->Tag,
dataLength,
&pObject);
if (NT_SUCCESS(status)) {
status = pObject->Commit(MemoryAttributes, (WDFOBJECT*) Memory);
if (NT_SUCCESS(status)) {
RtlCopyMemory(pObject->GetBuffer(),
dataBuffer,
dataLength);
}
else {
pObject->DeleteFromFailedCreate();
}
}
else {
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p WDFMEMORY object create failed, %!STATUS!",
Key, status);
}
}
else {
DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p QueryPartial failed, %!STATUS!",
Key, status);
}
FxPoolFree(dataBuffer);
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfRegistryQueryMultiString)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFKEY Key,
__in
PCUNICODE_STRING ValueName,
__in_opt
PWDF_OBJECT_ATTRIBUTES StringsAttributes,
__in
WDFCOLLECTION Collection
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxDeviceBase* pDeviceBase;
FxCollection* pCollection;
FxRegKey* pKey;
NTSTATUS status;
ULONG dataLength, type;
PVOID dataBuffer;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Key,
FX_TYPE_REG_KEY,
(PVOID*) &pKey,
&pFxDriverGlobals);
pDeviceBase = NULL;
FxPointerNotNull(pFxDriverGlobals, ValueName);
FxPointerNotNull(pFxDriverGlobals, Collection);
status = FxValidateObjectAttributes(pFxDriverGlobals, StringsAttributes);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
if (!NT_SUCCESS(status)) {
return status;
}
FxObjectHandleGetPtr(pFxDriverGlobals,
Collection,
FX_TYPE_COLLECTION,
(PVOID*) &pCollection);
pDeviceBase = FxDeviceBase::_SearchForDevice(pFxDriverGlobals,
StringsAttributes);
status = pKey->QueryValue(ValueName, 0, NULL, &dataLength, &type);
if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW) {
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p QueryPartial failed: %!STATUS!", Key, status);
return status;
}
if (type != REG_MULTI_SZ) {
return STATUS_OBJECT_TYPE_MISMATCH;
}
dataBuffer = FxPoolAllocate(pFxDriverGlobals, PagedPool, dataLength);
if (dataBuffer == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p KEY_VALUE_PARTIAL_INFORMATION allocation failed, %!STATUS!",
Key, status);
return status;
}
status = pKey->QueryValue(ValueName, dataLength, dataBuffer, &dataLength, &type);
if (NT_SUCCESS(status)) {
//
// Verify that the data from the registry is a valid multi-sz string.
//
status = FxRegKey::_VerifyMultiSzString(pFxDriverGlobals,
ValueName,
(PWCHAR) dataBuffer,
dataLength);
}
if (NT_SUCCESS(status)) {
ULONG initialCount;
PWCHAR pCur;
initialCount = pCollection->Count();
pCur = (PWCHAR) dataBuffer;
while (*pCur != UNICODE_NULL) {
FxString* pString;
pString = new (pFxDriverGlobals, StringsAttributes)
FxString(pFxDriverGlobals);
if (pString != NULL) {
if (pDeviceBase != NULL) {
pString->SetDeviceBase(pDeviceBase);
}
status = pString->Assign(pCur);
if (NT_SUCCESS(status)) {
WDFOBJECT dummy;
status = pString->Commit(StringsAttributes, &dummy);
}
if (NT_SUCCESS(status)) {
if (pCollection->Add(pString) == FALSE) {
status = STATUS_INSUFFICIENT_RESOURCES;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p, WDFCOLLECTION %p, collection add failed "
"%!STATUS!", Key, Collection, status);
}
}
if (!NT_SUCCESS(status)) {
//
// Delete the string we just created
//
pString->DeleteFromFailedCreate();
}
else {
//
// NT_SUCCES(status)
//
// Either the caller is responsible for freeing the
// WDFSTRING or it has been parented to another object.
//
DO_NOTHING();
}
}
else {
status = STATUS_INSUFFICIENT_RESOURCES;
}
if (!NT_SUCCESS(status)) {
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p: WDFSTRING creation failed: %!STATUS!",
Key, status);
break;
}
//
// Increment to the next string in the multi sz (length of string +
// 1 for the NULL)
//
pCur += wcslen(pCur) + 1;
}
if (!NT_SUCCESS(status)) {
//
// Clear out all the items we added to the collection
//
while (pCollection->Count() > initialCount) {
pCollection->Remove(initialCount);
}
}
}
FxPoolFree(dataBuffer);
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfRegistryQueryUnicodeString)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFKEY Key,
__in
PCUNICODE_STRING ValueName,
__out_opt
PUSHORT ValueByteLength,
__inout_opt
PUNICODE_STRING Value
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxRegKey* pKey;
NTSTATUS status;
ULONG dataLength, type;
PVOID dataBuffer;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Key,
FX_TYPE_REG_KEY,
(PVOID*) &pKey,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, ValueName);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
if (!NT_SUCCESS(status)) {
return status;
}
if (Value != NULL) {
status = FxValidateUnicodeString(pFxDriverGlobals, Value);
if (!NT_SUCCESS(status)) {
return status;
}
}
if (Value == NULL) {
//
// Caller wants to know just the length
//
dataLength = 0;
dataBuffer = NULL;
}
else {
dataLength = Value->MaximumLength;
dataBuffer = FxPoolAllocate(pFxDriverGlobals, PagedPool, dataLength);
if (dataBuffer == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p KEY_VALUE_PARTIAL_INFORMATION allocation failed, "
"%!STATUS!", Key, status);
return status;
}
}
status = pKey->QueryValue(ValueName, dataLength, dataBuffer, &dataLength, &type);
if (NT_SUCCESS(status) &&
FxRegKey::_IsValidSzType(type) == FALSE) {
status = STATUS_OBJECT_TYPE_MISMATCH;
}
//
// Set ValueByteLength before doing the copy
//
if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) {
//
// pPartial->DataLength is in bytes, convert to number of
// WCHARs
//
if (ValueByteLength != NULL) {
*ValueByteLength = (USHORT)dataLength ;
}
}
if (NT_SUCCESS(status) && Value != NULL) {
ASSERT(ValueByteLength == NULL ||
*ValueByteLength >= dataLength);
//
// pPartial->DataLength cannot be greater than Value->MaximumLength
// based on the call to _ComputePartialSize above. So it is safe to
// copy the pPartial data buffer to the Value buffer.
//
__analysis_assume(dataLength <= Value->MaximumLength);
RtlCopyMemory(Value->Buffer, dataBuffer, dataLength);
//terminating null shouldn't be included in the Length
Value->Length = (USHORT)dataLength;
if (Value->Buffer[Value->Length/sizeof(WCHAR)-1] == UNICODE_NULL) {
Value->Length -= sizeof(WCHAR);
}
}
if (dataBuffer != NULL) {
FxPoolFree(dataBuffer);
}
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfRegistryQueryString)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFKEY Key,
__in
PCUNICODE_STRING ValueName,
__in
WDFSTRING String
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxString* pString;
FxRegKey* pKey;
NTSTATUS status;
ULONG dataLength, type;
PVOID dataBuffer;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Key,
FX_TYPE_REG_KEY,
(PVOID*) &pKey,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, ValueName);
FxPointerNotNull(pFxDriverGlobals, String);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
if (!NT_SUCCESS(status)) {
return status;
}
FxObjectHandleGetPtr(pFxDriverGlobals,
String,
FX_TYPE_STRING,
(PVOID*) &pString);
status = pKey->QueryValue(ValueName, 0, NULL, &dataLength, &type);
if (NT_SUCCESS(status) &&
FxRegKey::_IsValidSzType(type) == FALSE) {
status = STATUS_OBJECT_TYPE_MISMATCH;
}
if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW) {
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p, QueryPartial failed, %!STATUS!",
Key, status);
return status;
}
dataBuffer = FxPoolAllocate(pFxDriverGlobals, PagedPool, dataLength);
if (dataBuffer == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p KEY_VALUE_PARTIAL_INFORMATION allocation failed, "
"%!STATUS!", Key, status);
return status;
}
status = pKey->QueryValue(ValueName, dataLength, dataBuffer, &dataLength, &type);
if (NT_SUCCESS(status) &&
FxRegKey::_IsValidSzType(type) == FALSE) {
status = STATUS_OBJECT_TYPE_MISMATCH;
}
if (NT_SUCCESS(status)) {
if (dataLength <= USHORT_MAX) {
UNICODE_STRING tmp;
if (dataLength == 0x0) {
//
// Empty string
//
tmp.Buffer = L"";
tmp.Length = 0;
tmp.MaximumLength = 0;
}
else {
//
// The string we read may not be NULL terminated, so put it into a
// UNICODE_STRING. If the final character is NULL, shorten the
// length of the string so that it does not include for the NULL.
//
// If there are embedded NULLs in the string previous to the final
// character, we leave them in place.
//
tmp.Buffer = (PWCHAR) dataBuffer;
tmp.Length = (USHORT) dataLength;
tmp.MaximumLength = tmp.Length;
if (tmp.Buffer[(tmp.Length/sizeof(WCHAR))-1] == UNICODE_NULL) {
//
// Do not include the UNICODE_NULL in the length
//
tmp.Length -= sizeof(WCHAR);
}
}
status = pString->Assign(&tmp);
}
else {
status = STATUS_INVALID_BUFFER_SIZE;
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p QueryPartial failed, Length %d > max %d, %!STATUS!",
Key, dataLength, USHORT_MAX, status);
}
}
else {
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p QueryPartial failed, Length %d, %!STATUS!",
Key, dataLength, status);
}
FxPoolFree(dataBuffer);
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfRegistryQueryULong)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFKEY Key,
__in
PCUNICODE_STRING ValueName,
__out
PULONG Value
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxRegKey* pKey;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Key,
FX_TYPE_REG_KEY,
(PVOID*) &pKey,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, ValueName);
FxPointerNotNull(pFxDriverGlobals, Value);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxRegKey::_QueryULong(pKey->GetHandle(), ValueName, Value);
if (!NT_SUCCESS(status)) {
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p, QueryULong, %!STATUS!", Key, status);
}
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfRegistryAssignValue)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFKEY Key,
__in
PCUNICODE_STRING ValueName,
__in
ULONG ValueType,
__in
ULONG ValueLength,
__in_ecount( ValueLength)
PVOID Value
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxRegKey* pKey;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Key,
FX_TYPE_REG_KEY,
(PVOID*) &pKey,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, ValueName);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
if (!NT_SUCCESS(status)) {
return status;
}
status = pKey->SetValue(ValueName, ValueType, Value, ValueLength);
if (!NT_SUCCESS(status)) {
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p SetValue, %!STATUS!", Key, status);
}
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfRegistryAssignMemory)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFKEY Key,
__in
PCUNICODE_STRING ValueName,
__in
ULONG ValueType,
__in
WDFMEMORY Memory,
__in_opt
PWDFMEMORY_OFFSET MemoryOffsets
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
IFxMemory* pMemory;
FxRegKey* pKey;
PVOID pBuffer;
ULONG length;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Key,
FX_TYPE_REG_KEY,
(PVOID*) &pKey,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, ValueName);
FxPointerNotNull(pFxDriverGlobals, Memory);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
if (!NT_SUCCESS(status)) {
return status;
}
FxObjectHandleGetPtr(pFxDriverGlobals,
Memory,
IFX_TYPE_MEMORY,
(PVOID*) &pMemory);
pBuffer = pMemory->GetBuffer();
length = (ULONG) pMemory->GetBufferSize();
if (MemoryOffsets != NULL) {
status = pMemory->ValidateMemoryOffsets(MemoryOffsets);
if (!NT_SUCCESS(status)) {
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p, WDFMEMORY %p Offsets overflowed, %!STATUS!",
Key, Memory, status);
return status;
}
if (MemoryOffsets->BufferLength > 0) {
status = RtlSizeTToULong(MemoryOffsets->BufferLength, &length);
if (!NT_SUCCESS(status)) {
DoTraceLevelMessage(
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p, WDFMEMORY %p BufferLength in Offsets truncated, "
"%!STATUS!", Key, Memory, status);
return status;
}
}
pBuffer = WDF_PTR_ADD_OFFSET(pBuffer, MemoryOffsets->BufferOffset);
}
status = pKey->SetValue(ValueName, ValueType, pBuffer, length);
if (!NT_SUCCESS(status)) {
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY handle %p SetValue, %!STATUS!", Key, status);
}
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfRegistryAssignULong)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFKEY Key,
__in
PCUNICODE_STRING ValueName,
__in
ULONG Value
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxRegKey* pKey;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Key,
FX_TYPE_REG_KEY,
(PVOID*) &pKey,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, ValueName);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
if (!NT_SUCCESS(status)) {
return status;
}
status = pKey->SetValue(ValueName, REG_DWORD, &Value, sizeof(Value));
if (!NT_SUCCESS(status)) {
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p SetValue, %!STATUS!",
Key, status);
}
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfRegistryAssignUnicodeString)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFKEY Key,
__in
PCUNICODE_STRING ValueName,
__in
PCUNICODE_STRING Value
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxRegKey* pKey;
NTSTATUS status;
PWCHAR tempValueBuf;
ULONG length;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Key,
FX_TYPE_REG_KEY,
(PVOID*) &pKey,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, ValueName);
FxPointerNotNull(pFxDriverGlobals, Value);
tempValueBuf = NULL;
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateUnicodeString(pFxDriverGlobals, Value);
if (!NT_SUCCESS(status)) {
return status;
}
length = Value->Length + sizeof(UNICODE_NULL);
//
// Buffer must be NULL terminated and Length of the buffer must also include the NULL
// Allocate a temporary buffer and NULL terminate it.
//
tempValueBuf = (PWCHAR) FxPoolAllocate(pFxDriverGlobals, PagedPool, length);
if (tempValueBuf == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p allocate temporary buffer failed, "
"%!STATUS!", Key, status);
return status;
}
//
// Copy over the string from the callers buffer and make sure it is
// NULL terminated.
//
RtlCopyMemory(tempValueBuf, Value->Buffer, Value->Length);
tempValueBuf[Value->Length/sizeof(WCHAR)] = UNICODE_NULL;
status = pKey->SetValue(ValueName, REG_SZ, tempValueBuf, length);
FxPoolFree(tempValueBuf);
if (!NT_SUCCESS(status)) {
DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p set value failed, %!STATUS!",
Key, status);
}
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfRegistryAssignString)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFKEY Key,
__in
PCUNICODE_STRING ValueName,
__in
WDFSTRING String
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxString* pString;
FxRegKey* pKey;
NTSTATUS status;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Key,
FX_TYPE_REG_KEY,
(PVOID*) &pKey,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, ValueName);
FxPointerNotNull(pFxDriverGlobals, String);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
if (!NT_SUCCESS(status)) {
return status;
}
FxObjectHandleGetPtr(pFxDriverGlobals,
String,
FX_TYPE_STRING,
(PVOID*) &pString);
status = pKey->SetValue(ValueName,
REG_SZ,
pString->Buffer(),
pString->ByteLength(TRUE));
if (!NT_SUCCESS(status)) {
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY handle %p SetValue, %!STATUS!",
Key, status);
}
return status;
}
_Must_inspect_result_
__drv_maxIRQL(PASSIVE_LEVEL)
NTSTATUS
STDCALL
WDFEXPORT(WdfRegistryAssignMultiString)(
__in
PWDF_DRIVER_GLOBALS DriverGlobals,
__in
WDFKEY Key,
__in
PCUNICODE_STRING ValueName,
__in
WDFCOLLECTION StringsCollection
)
{
DDI_ENTRY();
PFX_DRIVER_GLOBALS pFxDriverGlobals;
FxCollection* pCollection;
FxRegKey* pKey;
PWCHAR pValue;
NTSTATUS status;
ULONG length;
BOOLEAN valid;
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
Key,
FX_TYPE_REG_KEY,
(PVOID*) &pKey,
&pFxDriverGlobals);
FxPointerNotNull(pFxDriverGlobals, ValueName);
FxPointerNotNull(pFxDriverGlobals, StringsCollection);
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
if (!NT_SUCCESS(status)) {
return status;
}
status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
if (!NT_SUCCESS(status)) {
return status;
}
FxObjectHandleGetPtr(pFxDriverGlobals,
StringsCollection,
FX_TYPE_COLLECTION,
(PVOID *) &pCollection);
valid = FALSE;
status = RtlSizeTToULong(
FxCalculateTotalStringSize(pCollection, TRUE, &valid),
&length);
if (!NT_SUCCESS(status)) {
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFCOLLECTION %p, collection too large to fit into "
"a ULONG, %!STATUS!", StringsCollection, status);
return status;
}
if (valid == FALSE) {
status = STATUS_INVALID_PARAMETER;
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p, WDFCOLLECTION %p contains "
"non string objects, %!STATUS!",
Key, StringsCollection, status);
return status;
}
pValue = (PWCHAR) FxPoolAllocate(pFxDriverGlobals, PagedPool, length);
if (pValue == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p allocate for query buffer failed, "
"%!STATUS!", Key, status);
return status;
}
FxCopyMultiSz(pValue, pCollection);
status = pKey->SetValue(ValueName, REG_MULTI_SZ, pValue, length);
if (!NT_SUCCESS(status)) {
DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
"WDFKEY %p SetValue, %!STATUS!",
Key, status);
}
FxPoolFree(pValue);
return status;
}
} // extern "C"