mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
0daa5547d9
This implies that a sample for W10. It has been backported to NT5.2; not sure how it would work on a W2K3 (feel free to test!)
771 lines
22 KiB
C
771 lines
22 KiB
C
/*++
|
||
|
||
Copyright (c) 1989-2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
FatInit.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the DRIVER_INITIALIZATION routine for Fat
|
||
|
||
|
||
--*/
|
||
|
||
#include "fatprocs.h"
|
||
|
||
DRIVER_INITIALIZE DriverEntry;
|
||
|
||
NTSTATUS
|
||
NTAPI
|
||
DriverEntry(
|
||
_In_ PDRIVER_OBJECT DriverObject,
|
||
_In_ PUNICODE_STRING RegistryPath
|
||
);
|
||
|
||
_Function_class_(DRIVER_UNLOAD)
|
||
VOID
|
||
NTAPI
|
||
FatUnload(
|
||
#ifndef __REACTOS__
|
||
_In_ _Unreferenced_parameter_ PDRIVER_OBJECT DriverObject
|
||
#else
|
||
_In_ PDRIVER_OBJECT DriverObject
|
||
#endif
|
||
);
|
||
|
||
NTSTATUS
|
||
FatGetCompatibilityModeValue(
|
||
IN PUNICODE_STRING ValueName,
|
||
IN OUT PULONG Value
|
||
);
|
||
|
||
BOOLEAN
|
||
FatIsFujitsuFMR (
|
||
);
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(INIT, DriverEntry)
|
||
#pragma alloc_text(INIT, FatGetCompatibilityModeValue)
|
||
#pragma alloc_text(INIT, FatIsFujitsuFMR)
|
||
//#pragma alloc_text(PAGE, FatUnload)
|
||
#endif
|
||
|
||
#define COMPATIBILITY_MODE_KEY_NAME L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\FileSystem"
|
||
#define COMPATIBILITY_MODE_VALUE_NAME L"Win31FileSystem"
|
||
#define CODE_PAGE_INVARIANCE_VALUE_NAME L"FatDisableCodePageInvariance"
|
||
|
||
|
||
#define KEY_WORK_AREA ((sizeof(KEY_VALUE_FULL_INFORMATION) + \
|
||
sizeof(ULONG)) + 64)
|
||
|
||
#define REGISTRY_HARDWARE_DESCRIPTION_W \
|
||
L"\\Registry\\Machine\\Hardware\\DESCRIPTION\\System"
|
||
|
||
#define REGISTRY_MACHINE_IDENTIFIER_W L"Identifier"
|
||
|
||
#define FUJITSU_FMR_NAME_W L"FUJITSU FMR-"
|
||
|
||
|
||
|
||
NTSTATUS
|
||
NTAPI
|
||
DriverEntry(
|
||
_In_ PDRIVER_OBJECT DriverObject,
|
||
_In_ PUNICODE_STRING RegistryPath
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the initialization routine for the Fat file system
|
||
device driver. This routine creates the device object for the FileSystem
|
||
device and performs all other driver initialization.
|
||
|
||
Arguments:
|
||
|
||
DriverObject - Pointer to driver object created by the system.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS - The function value is the final status from the initialization
|
||
operation.
|
||
|
||
--*/
|
||
|
||
{
|
||
USHORT MaxDepth;
|
||
NTSTATUS Status;
|
||
UNICODE_STRING UnicodeString;
|
||
FS_FILTER_CALLBACKS FilterCallbacks;
|
||
UNICODE_STRING ValueName;
|
||
ULONG Value;
|
||
|
||
UNREFERENCED_PARAMETER( RegistryPath );
|
||
|
||
//
|
||
// Create the device object for disks. To avoid problems with filters who
|
||
// know this name, we must keep it.
|
||
//
|
||
|
||
RtlInitUnicodeString( &UnicodeString, L"\\Fat" );
|
||
Status = IoCreateDevice( DriverObject,
|
||
0,
|
||
&UnicodeString,
|
||
FILE_DEVICE_DISK_FILE_SYSTEM,
|
||
0,
|
||
FALSE,
|
||
&FatDiskFileSystemDeviceObject );
|
||
|
||
if (!NT_SUCCESS( Status )) {
|
||
return Status;
|
||
}
|
||
|
||
//
|
||
// Create the device object for "cdroms".
|
||
//
|
||
|
||
RtlInitUnicodeString( &UnicodeString, L"\\FatCdrom" );
|
||
Status = IoCreateDevice( DriverObject,
|
||
0,
|
||
&UnicodeString,
|
||
FILE_DEVICE_CD_ROM_FILE_SYSTEM,
|
||
0,
|
||
FALSE,
|
||
&FatCdromFileSystemDeviceObject );
|
||
|
||
if (!NT_SUCCESS( Status )) {
|
||
IoDeleteDevice( FatDiskFileSystemDeviceObject);
|
||
return Status;
|
||
}
|
||
|
||
#ifdef _MSC_VER
|
||
#pragma prefast( push )
|
||
#pragma prefast( disable:28155, "these are all correct" )
|
||
#pragma prefast( disable:28169, "these are all correct" )
|
||
#pragma prefast( disable:28175, "this is a filesystem, touching FastIoDispatch is allowed" )
|
||
#endif
|
||
|
||
DriverObject->DriverUnload = FatUnload;
|
||
|
||
//
|
||
// Note that because of the way data caching is done, we set neither
|
||
// the Direct I/O or Buffered I/O bit in DeviceObject->Flags. If
|
||
// data is not in the cache, or the request is not buffered, we may,
|
||
// set up for Direct I/O by hand.
|
||
//
|
||
|
||
//
|
||
// Initialize the driver object with this driver's entry points.
|
||
//
|
||
|
||
DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)FatFsdCreate;
|
||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)FatFsdClose;
|
||
DriverObject->MajorFunction[IRP_MJ_READ] = (PDRIVER_DISPATCH)FatFsdRead;
|
||
DriverObject->MajorFunction[IRP_MJ_WRITE] = (PDRIVER_DISPATCH)FatFsdWrite;
|
||
DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = (PDRIVER_DISPATCH)FatFsdQueryInformation;
|
||
DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = (PDRIVER_DISPATCH)FatFsdSetInformation;
|
||
DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = (PDRIVER_DISPATCH)FatFsdQueryEa;
|
||
DriverObject->MajorFunction[IRP_MJ_SET_EA] = (PDRIVER_DISPATCH)FatFsdSetEa;
|
||
DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = (PDRIVER_DISPATCH)FatFsdFlushBuffers;
|
||
DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = (PDRIVER_DISPATCH)FatFsdQueryVolumeInformation;
|
||
DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = (PDRIVER_DISPATCH)FatFsdSetVolumeInformation;
|
||
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = (PDRIVER_DISPATCH)FatFsdCleanup;
|
||
DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = (PDRIVER_DISPATCH)FatFsdDirectoryControl;
|
||
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = (PDRIVER_DISPATCH)FatFsdFileSystemControl;
|
||
DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = (PDRIVER_DISPATCH)FatFsdLockControl;
|
||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)FatFsdDeviceControl;
|
||
DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = (PDRIVER_DISPATCH)FatFsdShutdown;
|
||
DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH)FatFsdPnp;
|
||
|
||
DriverObject->FastIoDispatch = &FatFastIoDispatch;
|
||
|
||
RtlZeroMemory(&FatFastIoDispatch, sizeof(FatFastIoDispatch));
|
||
|
||
FatFastIoDispatch.SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
|
||
FatFastIoDispatch.FastIoCheckIfPossible = FatFastIoCheckIfPossible; // CheckForFastIo
|
||
FatFastIoDispatch.FastIoRead = FsRtlCopyRead; // Read
|
||
FatFastIoDispatch.FastIoWrite = FsRtlCopyWrite; // Write
|
||
FatFastIoDispatch.FastIoQueryBasicInfo = FatFastQueryBasicInfo; // QueryBasicInfo
|
||
FatFastIoDispatch.FastIoQueryStandardInfo = FatFastQueryStdInfo; // QueryStandardInfo
|
||
FatFastIoDispatch.FastIoLock = FatFastLock; // Lock
|
||
FatFastIoDispatch.FastIoUnlockSingle = FatFastUnlockSingle; // UnlockSingle
|
||
FatFastIoDispatch.FastIoUnlockAll = FatFastUnlockAll; // UnlockAll
|
||
FatFastIoDispatch.FastIoUnlockAllByKey = FatFastUnlockAllByKey; // UnlockAllByKey
|
||
FatFastIoDispatch.FastIoQueryNetworkOpenInfo = FatFastQueryNetworkOpenInfo;
|
||
FatFastIoDispatch.AcquireForCcFlush = FatAcquireForCcFlush;
|
||
FatFastIoDispatch.ReleaseForCcFlush = FatReleaseForCcFlush;
|
||
FatFastIoDispatch.MdlRead = FsRtlMdlReadDev;
|
||
FatFastIoDispatch.MdlReadComplete = FsRtlMdlReadCompleteDev;
|
||
FatFastIoDispatch.PrepareMdlWrite = FsRtlPrepareMdlWriteDev;
|
||
FatFastIoDispatch.MdlWriteComplete = FsRtlMdlWriteCompleteDev;
|
||
|
||
#ifdef _MSC_VER
|
||
#pragma prefast( pop )
|
||
#endif
|
||
|
||
//
|
||
// Initialize the filter callbacks we use.
|
||
//
|
||
|
||
RtlZeroMemory( &FilterCallbacks,
|
||
sizeof(FS_FILTER_CALLBACKS) );
|
||
|
||
FilterCallbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS);
|
||
FilterCallbacks.PreAcquireForSectionSynchronization = FatFilterCallbackAcquireForCreateSection;
|
||
|
||
Status = FsRtlRegisterFileSystemFilterCallbacks( DriverObject,
|
||
&FilterCallbacks );
|
||
|
||
if (!NT_SUCCESS( Status )) {
|
||
|
||
IoDeleteDevice( FatDiskFileSystemDeviceObject );
|
||
IoDeleteDevice( FatCdromFileSystemDeviceObject );
|
||
return Status;
|
||
}
|
||
|
||
//
|
||
// Initialize the global data structures
|
||
//
|
||
|
||
//
|
||
// The FatData record
|
||
//
|
||
|
||
RtlZeroMemory( &FatData, sizeof(FAT_DATA));
|
||
|
||
FatData.NodeTypeCode = FAT_NTC_DATA_HEADER;
|
||
FatData.NodeByteSize = sizeof(FAT_DATA);
|
||
|
||
InitializeListHead(&FatData.VcbQueue);
|
||
|
||
FatData.DriverObject = DriverObject;
|
||
FatData.DiskFileSystemDeviceObject = FatDiskFileSystemDeviceObject;
|
||
FatData.CdromFileSystemDeviceObject = FatCdromFileSystemDeviceObject;
|
||
|
||
//
|
||
// This list head keeps track of closes yet to be done.
|
||
//
|
||
|
||
InitializeListHead( &FatData.AsyncCloseList );
|
||
InitializeListHead( &FatData.DelayedCloseList );
|
||
|
||
FatData.FatCloseItem = IoAllocateWorkItem( FatDiskFileSystemDeviceObject);
|
||
|
||
if (FatData.FatCloseItem == NULL) {
|
||
IoDeleteDevice (FatDiskFileSystemDeviceObject);
|
||
IoDeleteDevice (FatCdromFileSystemDeviceObject);
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
//
|
||
// Allocate the zero page
|
||
//
|
||
|
||
#ifndef __REACTOS__
|
||
FatData.ZeroPage = ExAllocatePoolWithTag( NonPagedPoolNx, PAGE_SIZE, 'ZtaF' );
|
||
#else
|
||
FatData.ZeroPage = ExAllocatePoolWithTag( NonPagedPool, PAGE_SIZE, 'ZtaF' );
|
||
#endif
|
||
if (FatData.ZeroPage == NULL) {
|
||
IoDeleteDevice (FatDiskFileSystemDeviceObject);
|
||
IoDeleteDevice (FatCdromFileSystemDeviceObject);
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
RtlZeroMemory( FatData.ZeroPage, PAGE_SIZE );
|
||
|
||
|
||
//
|
||
// Now initialize our general purpose spinlock (gag) and figure out how
|
||
// deep and wide we want our delayed lists (along with fooling ourselves
|
||
// about the lookaside depths).
|
||
//
|
||
|
||
KeInitializeSpinLock( &FatData.GeneralSpinLock );
|
||
|
||
switch ( MmQuerySystemSize() ) {
|
||
|
||
case MmSmallSystem:
|
||
|
||
MaxDepth = 4;
|
||
FatMaxDelayedCloseCount = FAT_MAX_DELAYED_CLOSES;
|
||
break;
|
||
|
||
case MmMediumSystem:
|
||
|
||
MaxDepth = 8;
|
||
FatMaxDelayedCloseCount = 4 * FAT_MAX_DELAYED_CLOSES;
|
||
break;
|
||
|
||
case MmLargeSystem:
|
||
default:
|
||
|
||
MaxDepth = 16;
|
||
FatMaxDelayedCloseCount = 16 * FAT_MAX_DELAYED_CLOSES;
|
||
break;
|
||
}
|
||
|
||
|
||
//
|
||
// Initialize the cache manager callback routines
|
||
//
|
||
|
||
FatData.CacheManagerCallbacks.AcquireForLazyWrite = &FatAcquireFcbForLazyWrite;
|
||
FatData.CacheManagerCallbacks.ReleaseFromLazyWrite = &FatReleaseFcbFromLazyWrite;
|
||
FatData.CacheManagerCallbacks.AcquireForReadAhead = &FatAcquireFcbForReadAhead;
|
||
FatData.CacheManagerCallbacks.ReleaseFromReadAhead = &FatReleaseFcbFromReadAhead;
|
||
|
||
FatData.CacheManagerNoOpCallbacks.AcquireForLazyWrite = &FatNoOpAcquire;
|
||
FatData.CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = &FatNoOpRelease;
|
||
FatData.CacheManagerNoOpCallbacks.AcquireForReadAhead = &FatNoOpAcquire;
|
||
FatData.CacheManagerNoOpCallbacks.ReleaseFromReadAhead = &FatNoOpRelease;
|
||
|
||
//
|
||
// Set up global pointer to our process.
|
||
//
|
||
|
||
FatData.OurProcess = PsGetCurrentProcess();
|
||
|
||
//
|
||
// Setup the number of processors we support for statistics as the current number
|
||
// running.
|
||
//
|
||
|
||
#if (NTDDI_VERSION >= NTDDI_VISTA)
|
||
FatData.NumberProcessors = KeQueryActiveProcessorCount( NULL );
|
||
#else
|
||
FatData.NumberProcessors = KeNumberProcessors;
|
||
#endif
|
||
|
||
|
||
//
|
||
// Read the registry to determine if we are in ChicagoMode.
|
||
//
|
||
|
||
ValueName.Buffer = COMPATIBILITY_MODE_VALUE_NAME;
|
||
ValueName.Length = sizeof(COMPATIBILITY_MODE_VALUE_NAME) - sizeof(WCHAR);
|
||
ValueName.MaximumLength = sizeof(COMPATIBILITY_MODE_VALUE_NAME);
|
||
|
||
Status = FatGetCompatibilityModeValue( &ValueName, &Value );
|
||
|
||
if (NT_SUCCESS(Status) && FlagOn(Value, 1)) {
|
||
|
||
FatData.ChicagoMode = FALSE;
|
||
|
||
} else {
|
||
|
||
FatData.ChicagoMode = TRUE;
|
||
}
|
||
|
||
//
|
||
// Read the registry to determine if we are going to generate LFNs
|
||
// for valid 8.3 names with extended characters.
|
||
//
|
||
|
||
ValueName.Buffer = CODE_PAGE_INVARIANCE_VALUE_NAME;
|
||
ValueName.Length = sizeof(CODE_PAGE_INVARIANCE_VALUE_NAME) - sizeof(WCHAR);
|
||
ValueName.MaximumLength = sizeof(CODE_PAGE_INVARIANCE_VALUE_NAME);
|
||
|
||
Status = FatGetCompatibilityModeValue( &ValueName, &Value );
|
||
|
||
if (NT_SUCCESS(Status) && FlagOn(Value, 1)) {
|
||
|
||
FatData.CodePageInvariant = FALSE;
|
||
|
||
} else {
|
||
|
||
FatData.CodePageInvariant = TRUE;
|
||
}
|
||
|
||
//
|
||
// Initialize our global resource and fire up the lookaside lists.
|
||
//
|
||
|
||
ExInitializeResourceLite( &FatData.Resource );
|
||
|
||
ExInitializeNPagedLookasideList( &FatIrpContextLookasideList,
|
||
NULL,
|
||
NULL,
|
||
#ifndef __REACTOS__
|
||
POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE,
|
||
#else
|
||
POOL_RAISE_IF_ALLOCATION_FAILURE,
|
||
#endif
|
||
sizeof(IRP_CONTEXT),
|
||
TAG_IRP_CONTEXT,
|
||
MaxDepth );
|
||
|
||
ExInitializeNPagedLookasideList( &FatNonPagedFcbLookasideList,
|
||
NULL,
|
||
NULL,
|
||
#ifndef __REACTOS__
|
||
POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE,
|
||
#else
|
||
POOL_RAISE_IF_ALLOCATION_FAILURE,
|
||
#endif
|
||
sizeof(NON_PAGED_FCB),
|
||
TAG_FCB_NONPAGED,
|
||
MaxDepth );
|
||
|
||
ExInitializeNPagedLookasideList( &FatEResourceLookasideList,
|
||
NULL,
|
||
NULL,
|
||
#ifndef __REACTOS__
|
||
POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE,
|
||
#else
|
||
POOL_RAISE_IF_ALLOCATION_FAILURE,
|
||
#endif
|
||
sizeof(ERESOURCE),
|
||
TAG_ERESOURCE,
|
||
MaxDepth );
|
||
|
||
ExInitializeSListHead( &FatCloseContextSList );
|
||
ExInitializeFastMutex( &FatCloseQueueMutex );
|
||
KeInitializeEvent( &FatReserveEvent, SynchronizationEvent, TRUE );
|
||
|
||
//
|
||
// Register the file system with the I/O system
|
||
//
|
||
|
||
IoRegisterFileSystem(FatDiskFileSystemDeviceObject);
|
||
ObReferenceObject (FatDiskFileSystemDeviceObject);
|
||
IoRegisterFileSystem(FatCdromFileSystemDeviceObject);
|
||
ObReferenceObject (FatCdromFileSystemDeviceObject);
|
||
|
||
//
|
||
// Find out if we are running an a FujitsuFMR machine.
|
||
//
|
||
|
||
FatData.FujitsuFMR = FatIsFujitsuFMR();
|
||
|
||
#if (NTDDI_VERSION >= NTDDI_WIN8)
|
||
|
||
//
|
||
// Find out global disk accounting state, cache the result
|
||
//
|
||
|
||
FatDiskAccountingEnabled = PsIsDiskCountersEnabled();
|
||
|
||
#endif
|
||
|
||
//
|
||
// And return to our caller
|
||
//
|
||
|
||
return( STATUS_SUCCESS );
|
||
}
|
||
|
||
|
||
_Function_class_(DRIVER_UNLOAD)
|
||
VOID
|
||
NTAPI
|
||
FatUnload(
|
||
#ifndef __REACTOS__
|
||
_In_ _Unreferenced_parameter_ PDRIVER_OBJECT DriverObject
|
||
#else
|
||
_In_ PDRIVER_OBJECT DriverObject
|
||
#endif
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the unload routine for the filesystem
|
||
|
||
Arguments:
|
||
|
||
DriverObject - Pointer to driver object created by the system.
|
||
|
||
Return Value:
|
||
|
||
None
|
||
|
||
--*/
|
||
|
||
{
|
||
UNREFERENCED_PARAMETER( DriverObject );
|
||
|
||
|
||
ExDeleteNPagedLookasideList (&FatEResourceLookasideList);
|
||
ExDeleteNPagedLookasideList (&FatNonPagedFcbLookasideList);
|
||
ExDeleteNPagedLookasideList (&FatIrpContextLookasideList);
|
||
ExDeleteResourceLite( &FatData.Resource );
|
||
IoFreeWorkItem (FatData.FatCloseItem);
|
||
ObDereferenceObject( FatDiskFileSystemDeviceObject);
|
||
ObDereferenceObject( FatCdromFileSystemDeviceObject);
|
||
}
|
||
|
||
|
||
//
|
||
// Local Support routine
|
||
//
|
||
|
||
NTSTATUS
|
||
FatGetCompatibilityModeValue (
|
||
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 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);
|
||
|
||
NT_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) {
|
||
|
||
ZwClose(Handle);
|
||
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;
|
||
}
|
||
|
||
//
|
||
// Local Support routine
|
||
//
|
||
|
||
BOOLEAN
|
||
FatIsFujitsuFMR (
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine tells if is we running on a FujitsuFMR machine.
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
BOOLEAN - TRUE is we are and FALSE otherwise
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOLEAN Result;
|
||
HANDLE Handle;
|
||
NTSTATUS Status;
|
||
ULONG RequestLength;
|
||
ULONG ResultLength;
|
||
UCHAR Buffer[KEY_WORK_AREA];
|
||
UNICODE_STRING KeyName;
|
||
UNICODE_STRING ValueName;
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
|
||
|
||
//
|
||
// Set default as PC/AT
|
||
//
|
||
|
||
KeyName.Buffer = REGISTRY_HARDWARE_DESCRIPTION_W;
|
||
KeyName.Length = sizeof(REGISTRY_HARDWARE_DESCRIPTION_W) - sizeof(WCHAR);
|
||
KeyName.MaximumLength = sizeof(REGISTRY_HARDWARE_DESCRIPTION_W);
|
||
|
||
InitializeObjectAttributes(&ObjectAttributes,
|
||
&KeyName,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL,
|
||
NULL);
|
||
|
||
Status = ZwOpenKey(&Handle,
|
||
KEY_READ,
|
||
&ObjectAttributes);
|
||
|
||
if (!NT_SUCCESS(Status)) {
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
ValueName.Buffer = REGISTRY_MACHINE_IDENTIFIER_W;
|
||
ValueName.Length = sizeof(REGISTRY_MACHINE_IDENTIFIER_W) - sizeof(WCHAR);
|
||
ValueName.MaximumLength = sizeof(REGISTRY_MACHINE_IDENTIFIER_W);
|
||
|
||
RequestLength = KEY_WORK_AREA;
|
||
|
||
KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buffer;
|
||
|
||
while (1) {
|
||
|
||
Status = ZwQueryValueKey(Handle,
|
||
&ValueName,
|
||
KeyValueFullInformation,
|
||
KeyValueInformation,
|
||
RequestLength,
|
||
&ResultLength);
|
||
|
||
// NT_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) {
|
||
|
||
ZwClose(Handle);
|
||
return FALSE;
|
||
}
|
||
|
||
} else {
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
ZwClose(Handle);
|
||
|
||
if (NT_SUCCESS(Status) &&
|
||
(KeyValueInformation->DataLength >= sizeof(FUJITSU_FMR_NAME_W)) &&
|
||
(RtlCompareMemory((PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset,
|
||
FUJITSU_FMR_NAME_W,
|
||
sizeof(FUJITSU_FMR_NAME_W) - sizeof(WCHAR)) ==
|
||
sizeof(FUJITSU_FMR_NAME_W) - sizeof(WCHAR))) {
|
||
|
||
Result = TRUE;
|
||
|
||
} else {
|
||
|
||
Result = FALSE;
|
||
}
|
||
|
||
if (KeyValueInformation != (PKEY_VALUE_FULL_INFORMATION)Buffer) {
|
||
|
||
ExFreePool(KeyValueInformation);
|
||
}
|
||
|
||
return Result;
|
||
}
|
||
|