472 lines
14 KiB
C
472 lines
14 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
FsRtlP.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module declares the global data used by the FsRtl Module
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Gary Kimura [GaryKi] 30-Jul-1990
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "FsRtlP.h"
|
|||
|
|
|||
|
#define COMPATIBILITY_MODE_KEY_NAME L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\FileSystem"
|
|||
|
#define COMPATIBILITY_MODE_VALUE_NAME L"Win95TruncatedExtensions"
|
|||
|
|
|||
|
#define KEY_WORK_AREA ((sizeof(KEY_VALUE_FULL_INFORMATION) + \
|
|||
|
sizeof(ULONG)) + 64)
|
|||
|
|
|||
|
#ifdef FSRTLDBG
|
|||
|
|
|||
|
LONG FsRtlDebugTraceLevel = 0x0000000f;
|
|||
|
LONG FsRtlDebugTraceIndent = 0;
|
|||
|
|
|||
|
#endif // FSRTLDBG
|
|||
|
|
|||
|
//
|
|||
|
// Local Support routine
|
|||
|
//
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
FsRtlGetCompatibilityModeValue (
|
|||
|
IN PUNICODE_STRING ValueName,
|
|||
|
IN OUT PULONG Value
|
|||
|
);
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, FsRtlAllocateResource)
|
|||
|
#pragma alloc_text(INIT, FsRtlInitSystem)
|
|||
|
#pragma alloc_text(INIT, FsRtlGetCompatibilityModeValue)
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Define the number of resources, a pointer to them and a counter for
|
|||
|
// resource selection.
|
|||
|
//
|
|||
|
|
|||
|
#define FSRTL_NUMBER_OF_RESOURCES (16)
|
|||
|
|
|||
|
PERESOURCE FsRtlPagingIoResources;
|
|||
|
|
|||
|
#ifdef ALLOC_DATA_PRAGMA
|
|||
|
#pragma data_seg("PAGEDATA")
|
|||
|
#endif
|
|||
|
ULONG FsRtlPagingIoResourceSelector = 0;
|
|||
|
BOOLEAN FsRtlSafeExtensions = TRUE;
|
|||
|
#ifdef ALLOC_DATA_PRAGMA
|
|||
|
#pragma data_seg()
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// The global static legal ANSI character array. Wild characters
|
|||
|
// are not considered legal, they should be checked seperately if
|
|||
|
// allowed.
|
|||
|
//
|
|||
|
|
|||
|
#define _FAT_ FSRTL_FAT_LEGAL
|
|||
|
#define _HPFS_ FSRTL_HPFS_LEGAL
|
|||
|
#define _NTFS_ FSRTL_NTFS_LEGAL
|
|||
|
#define _OLE_ FSRTL_OLE_LEGAL
|
|||
|
#define _WILD_ FSRTL_WILD_CHARACTER
|
|||
|
|
|||
|
static const UCHAR LocalLegalAnsiCharacterArray[128] = {
|
|||
|
|
|||
|
0 , // 0x00 ^@
|
|||
|
_OLE_, // 0x01 ^A
|
|||
|
_OLE_, // 0x02 ^B
|
|||
|
_OLE_, // 0x03 ^C
|
|||
|
_OLE_, // 0x04 ^D
|
|||
|
_OLE_, // 0x05 ^E
|
|||
|
_OLE_, // 0x06 ^F
|
|||
|
_OLE_, // 0x07 ^G
|
|||
|
_OLE_, // 0x08 ^H
|
|||
|
_OLE_, // 0x09 ^I
|
|||
|
_OLE_, // 0x0A ^J
|
|||
|
_OLE_, // 0x0B ^K
|
|||
|
_OLE_, // 0x0C ^L
|
|||
|
_OLE_, // 0x0D ^M
|
|||
|
_OLE_, // 0x0E ^N
|
|||
|
_OLE_, // 0x0F ^O
|
|||
|
_OLE_, // 0x10 ^P
|
|||
|
_OLE_, // 0x11 ^Q
|
|||
|
_OLE_, // 0x12 ^R
|
|||
|
_OLE_, // 0x13 ^S
|
|||
|
_OLE_, // 0x14 ^T
|
|||
|
_OLE_, // 0x15 ^U
|
|||
|
_OLE_, // 0x16 ^V
|
|||
|
_OLE_, // 0x17 ^W
|
|||
|
_OLE_, // 0x18 ^X
|
|||
|
_OLE_, // 0x19 ^Y
|
|||
|
_OLE_, // 0x1A ^Z
|
|||
|
_OLE_, // 0x1B ESC
|
|||
|
_OLE_, // 0x1C FS
|
|||
|
_OLE_, // 0x1D GS
|
|||
|
_OLE_, // 0x1E RS
|
|||
|
_OLE_, // 0x1F US
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x20 space
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ , // 0x21 !
|
|||
|
_WILD_| _OLE_, // 0x22 "
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x23 #
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x24 $
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x25 %
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x26 &
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x27 '
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x28 (
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x29 )
|
|||
|
_WILD_| _OLE_, // 0x2A *
|
|||
|
_HPFS_ | _NTFS_ | _OLE_, // 0x2B +
|
|||
|
_HPFS_ | _NTFS_ | _OLE_, // 0x2C ,
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x2D -
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ , // 0x2E .
|
|||
|
0 , // 0x2F /
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x30 0
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x31 1
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x32 2
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x33 3
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x34 4
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x35 5
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x36 6
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x37 7
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x38 8
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x39 9
|
|||
|
_NTFS_ , // 0x3A :
|
|||
|
_HPFS_ | _NTFS_ | _OLE_, // 0x3B ;
|
|||
|
_WILD_| _OLE_, // 0x3C <
|
|||
|
_HPFS_ | _NTFS_ | _OLE_, // 0x3D =
|
|||
|
_WILD_| _OLE_, // 0x3E >
|
|||
|
_WILD_| _OLE_, // 0x3F ?
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x40 @
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x41 A
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x42 B
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x43 C
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x44 D
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x45 E
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x46 F
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x47 G
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x48 H
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x49 I
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x4A J
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x4B K
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x4C L
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x4D M
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x4E N
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x4F O
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x50 P
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x51 Q
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x52 R
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x53 S
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x54 T
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x55 U
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x56 V
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x57 W
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x58 X
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x59 Y
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x5A Z
|
|||
|
_HPFS_ | _NTFS_ | _OLE_, // 0x5B [
|
|||
|
0 , // 0x5C backslash
|
|||
|
_HPFS_ | _NTFS_ | _OLE_, // 0x5D ]
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x5E ^
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x5F _
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x60 `
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x61 a
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x62 b
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x63 c
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x64 d
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x65 e
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x66 f
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x67 g
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x68 h
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x69 i
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x6A j
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x6B k
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x6C l
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x6D m
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x6E n
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x6F o
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x70 p
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x71 q
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x72 r
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x73 s
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x74 t
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x75 u
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x76 v
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x77 w
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x78 x
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x79 y
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x7A z
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x7B {
|
|||
|
0 | _OLE_, // 0x7C |
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x7D }
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x7E ~
|
|||
|
_FAT_ | _HPFS_ | _NTFS_ | _OLE_, // 0x7F
|
|||
|
};
|
|||
|
|
|||
|
UCHAR const* const FsRtlLegalAnsiCharacterArray = &LocalLegalAnsiCharacterArray[0];
|
|||
|
|
|||
|
//
|
|||
|
// This routine is called during phase one initialization.
|
|||
|
//
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
FsRtlInitSystem (
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG i;
|
|||
|
|
|||
|
ULONG Value;
|
|||
|
UNICODE_STRING ValueName;
|
|||
|
|
|||
|
extern KSEMAPHORE FsRtlpUncSemaphore;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Allocate and initialize all the paging Io resources
|
|||
|
//
|
|||
|
|
|||
|
FsRtlPagingIoResources = FsRtlAllocatePool( NonPagedPool,
|
|||
|
FSRTL_NUMBER_OF_RESOURCES *
|
|||
|
sizeof(ERESOURCE) );
|
|||
|
|
|||
|
for (i=0; i < FSRTL_NUMBER_OF_RESOURCES; i++) {
|
|||
|
|
|||
|
ExInitializeResourceLite( &FsRtlPagingIoResources[i] );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the global tunneling structures.
|
|||
|
//
|
|||
|
|
|||
|
FsRtlInitializeTunnels();
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the global filelock structures.
|
|||
|
//
|
|||
|
|
|||
|
FsRtlInitializeFileLocks();
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the global largemcb structures.
|
|||
|
//
|
|||
|
|
|||
|
FsRtlInitializeLargeMcbs();
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the semaphore used to guard loading of the MUP
|
|||
|
//
|
|||
|
|
|||
|
KeInitializeSemaphore( &FsRtlpUncSemaphore, 1, MAXLONG );
|
|||
|
|
|||
|
//
|
|||
|
// Pull the bit from the registry telling us whether to do a safe
|
|||
|
// or dangerous extension truncation.
|
|||
|
//
|
|||
|
|
|||
|
ValueName.Buffer = COMPATIBILITY_MODE_VALUE_NAME;
|
|||
|
ValueName.Length = sizeof(COMPATIBILITY_MODE_VALUE_NAME) - sizeof(WCHAR);
|
|||
|
ValueName.MaximumLength = sizeof(COMPATIBILITY_MODE_VALUE_NAME);
|
|||
|
|
|||
|
if (NT_SUCCESS(FsRtlGetCompatibilityModeValue( &ValueName, &Value )) &&
|
|||
|
(Value != 0)) {
|
|||
|
|
|||
|
FsRtlSafeExtensions = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the FsRtl stack overflow work QueueObject and thread.
|
|||
|
//
|
|||
|
|
|||
|
if (!NT_SUCCESS(FsRtlInitializeWorkerThread())) {
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the FsFilter component of FsRtl.
|
|||
|
//
|
|||
|
|
|||
|
if (!NT_SUCCESS(FsFilterInit())) {
|
|||
|
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
PERESOURCE
|
|||
|
FsRtlAllocateResource (
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is used to allocate a resource from the FsRtl pool.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
PERESOURCE - A pointer to the provided resource.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
return &FsRtlPagingIoResources[ FsRtlPagingIoResourceSelector++ %
|
|||
|
FSRTL_NUMBER_OF_RESOURCES];
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Local Support routine
|
|||
|
//
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
FsRtlGetCompatibilityModeValue (
|
|||
|
IN PUNICODE_STRING ValueName,
|
|||
|
IN OUT PULONG Value
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Given a unicode value name this routine will go into the registry
|
|||
|
location for the Chicago compatibilitymode information and get the
|
|||
|
value.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ValueName - the unicode name for the registry value located in the
|
|||
|
double space configuration location of the registry.
|
|||
|
Value - a pointer to the ULONG for the result.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
|
|||
|
If STATUS_SUCCESSFUL is returned, the location *Value will be
|
|||
|
updated with the DWORD value from the registry. If any failing
|
|||
|
status is returned, this value is untouched.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
HANDLE Handle;
|
|||
|
NTSTATUS Status;
|
|||
|
ULONG RequestLength;
|
|||
|
ULONG ResultLength;
|
|||
|
UCHAR Buffer[KEY_WORK_AREA];
|
|||
|
UNICODE_STRING KeyName;
|
|||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
|
|||
|
|
|||
|
KeyName.Buffer = COMPATIBILITY_MODE_KEY_NAME;
|
|||
|
KeyName.Length = sizeof(COMPATIBILITY_MODE_KEY_NAME) - sizeof(WCHAR);
|
|||
|
KeyName.MaximumLength = sizeof(COMPATIBILITY_MODE_KEY_NAME);
|
|||
|
|
|||
|
InitializeObjectAttributes(&ObjectAttributes,
|
|||
|
&KeyName,
|
|||
|
OBJ_CASE_INSENSITIVE,
|
|||
|
NULL,
|
|||
|
NULL);
|
|||
|
|
|||
|
Status = ZwOpenKey(&Handle,
|
|||
|
KEY_READ,
|
|||
|
&ObjectAttributes);
|
|||
|
|
|||
|
if (!NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
RequestLength = KEY_WORK_AREA;
|
|||
|
|
|||
|
KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buffer;
|
|||
|
|
|||
|
while (1) {
|
|||
|
|
|||
|
Status = ZwQueryValueKey(Handle,
|
|||
|
ValueName,
|
|||
|
KeyValueFullInformation,
|
|||
|
KeyValueInformation,
|
|||
|
RequestLength,
|
|||
|
&ResultLength);
|
|||
|
|
|||
|
ASSERT( Status != STATUS_BUFFER_OVERFLOW );
|
|||
|
|
|||
|
if (Status == STATUS_BUFFER_OVERFLOW) {
|
|||
|
|
|||
|
//
|
|||
|
// Try to get a buffer big enough.
|
|||
|
//
|
|||
|
|
|||
|
if (KeyValueInformation != (PKEY_VALUE_FULL_INFORMATION)Buffer) {
|
|||
|
|
|||
|
ExFreePool(KeyValueInformation);
|
|||
|
}
|
|||
|
|
|||
|
RequestLength += 256;
|
|||
|
|
|||
|
KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)
|
|||
|
ExAllocatePoolWithTag(PagedPool,
|
|||
|
RequestLength,
|
|||
|
' taF');
|
|||
|
|
|||
|
if (!KeyValueInformation) {
|
|||
|
return STATUS_NO_MEMORY;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ZwClose(Handle);
|
|||
|
|
|||
|
if (NT_SUCCESS(Status)) {
|
|||
|
|
|||
|
if (KeyValueInformation->DataLength != 0) {
|
|||
|
|
|||
|
PULONG DataPtr;
|
|||
|
|
|||
|
//
|
|||
|
// Return contents to the caller.
|
|||
|
//
|
|||
|
|
|||
|
DataPtr = (PULONG)
|
|||
|
((PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset);
|
|||
|
*Value = *DataPtr;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Treat as if no value was found
|
|||
|
//
|
|||
|
|
|||
|
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (KeyValueInformation != (PKEY_VALUE_FULL_INFORMATION)Buffer) {
|
|||
|
|
|||
|
ExFreePool(KeyValueInformation);
|
|||
|
}
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|