[FASTFAT_NEW] Sync to upstream 16022c5 (#2938)
[reactos.git] / drivers / filesystems / fastfat_new / fatinit.c
1 /*++
2
3 Copyright (c) 1989-2000 Microsoft Corporation
4
5 Module Name:
6
7 FatInit.c
8
9 Abstract:
10
11 This module implements the DRIVER_INITIALIZATION routine for Fat
12
13
14 --*/
15
16 #include "fatprocs.h"
17
18 #ifdef __REACTOS__
19 #define _Unreferenced_parameter_
20 #endif
21
22 DRIVER_INITIALIZE DriverEntry;
23
24 NTSTATUS
25 NTAPI
26 DriverEntry(
27 _In_ PDRIVER_OBJECT DriverObject,
28 _In_ PUNICODE_STRING RegistryPath
29 );
30
31 _Function_class_(DRIVER_UNLOAD)
32 VOID
33 NTAPI
34 FatUnload(
35 _In_ _Unreferenced_parameter_ PDRIVER_OBJECT DriverObject
36 );
37
38 NTSTATUS
39 FatGetCompatibilityModeValue(
40 IN PUNICODE_STRING ValueName,
41 IN OUT PULONG Value
42 );
43
44 BOOLEAN
45 FatIsFujitsuFMR (
46 );
47
48 #ifdef ALLOC_PRAGMA
49 #pragma alloc_text(INIT, DriverEntry)
50 #pragma alloc_text(INIT, FatGetCompatibilityModeValue)
51 #pragma alloc_text(INIT, FatIsFujitsuFMR)
52 //#pragma alloc_text(PAGE, FatUnload)
53 #endif
54
55 #define COMPATIBILITY_MODE_KEY_NAME L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\FileSystem"
56 #define COMPATIBILITY_MODE_VALUE_NAME L"Win31FileSystem"
57 #define CODE_PAGE_INVARIANCE_VALUE_NAME L"FatDisableCodePageInvariance"
58
59
60 #define KEY_WORK_AREA ((sizeof(KEY_VALUE_FULL_INFORMATION) + \
61 sizeof(ULONG)) + 64)
62
63 #define REGISTRY_HARDWARE_DESCRIPTION_W \
64 L"\\Registry\\Machine\\Hardware\\DESCRIPTION\\System"
65
66 #define REGISTRY_MACHINE_IDENTIFIER_W L"Identifier"
67
68 #define FUJITSU_FMR_NAME_W L"FUJITSU FMR-"
69
70
71 \f
72 NTSTATUS
73 NTAPI
74 DriverEntry(
75 _In_ PDRIVER_OBJECT DriverObject,
76 _In_ PUNICODE_STRING RegistryPath
77 )
78
79 /*++
80
81 Routine Description:
82
83 This is the initialization routine for the Fat file system
84 device driver. This routine creates the device object for the FileSystem
85 device and performs all other driver initialization.
86
87 Arguments:
88
89 DriverObject - Pointer to driver object created by the system.
90
91 Return Value:
92
93 NTSTATUS - The function value is the final status from the initialization
94 operation.
95
96 --*/
97
98 {
99 USHORT MaxDepth;
100 NTSTATUS Status;
101 UNICODE_STRING UnicodeString;
102 FS_FILTER_CALLBACKS FilterCallbacks;
103 UNICODE_STRING ValueName;
104 ULONG Value;
105
106 UNREFERENCED_PARAMETER( RegistryPath );
107
108 //
109 // Create the device object for disks. To avoid problems with filters who
110 // know this name, we must keep it.
111 //
112
113 RtlInitUnicodeString( &UnicodeString, L"\\Fat" );
114 Status = IoCreateDevice( DriverObject,
115 0,
116 &UnicodeString,
117 FILE_DEVICE_DISK_FILE_SYSTEM,
118 0,
119 FALSE,
120 &FatDiskFileSystemDeviceObject );
121
122 if (!NT_SUCCESS( Status )) {
123 return Status;
124 }
125
126 //
127 // Create the device object for "cdroms".
128 //
129
130 RtlInitUnicodeString( &UnicodeString, L"\\FatCdrom" );
131 Status = IoCreateDevice( DriverObject,
132 0,
133 &UnicodeString,
134 FILE_DEVICE_CD_ROM_FILE_SYSTEM,
135 0,
136 FALSE,
137 &FatCdromFileSystemDeviceObject );
138
139 if (!NT_SUCCESS( Status )) {
140 IoDeleteDevice( FatDiskFileSystemDeviceObject);
141 return Status;
142 }
143
144 #ifdef _MSC_VER
145 #pragma prefast( push )
146 #pragma prefast( disable:28155, "these are all correct" )
147 #pragma prefast( disable:28169, "these are all correct" )
148 #pragma prefast( disable:28175, "this is a filesystem, touching FastIoDispatch is allowed" )
149 #endif
150
151 DriverObject->DriverUnload = FatUnload;
152
153 //
154 // Note that because of the way data caching is done, we set neither
155 // the Direct I/O or Buffered I/O bit in DeviceObject->Flags. If
156 // data is not in the cache, or the request is not buffered, we may,
157 // set up for Direct I/O by hand.
158 //
159
160 //
161 // Initialize the driver object with this driver's entry points.
162 //
163
164 DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)FatFsdCreate;
165 DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)FatFsdClose;
166 DriverObject->MajorFunction[IRP_MJ_READ] = (PDRIVER_DISPATCH)FatFsdRead;
167 DriverObject->MajorFunction[IRP_MJ_WRITE] = (PDRIVER_DISPATCH)FatFsdWrite;
168 DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] = (PDRIVER_DISPATCH)FatFsdQueryInformation;
169 DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION] = (PDRIVER_DISPATCH)FatFsdSetInformation;
170 DriverObject->MajorFunction[IRP_MJ_QUERY_EA] = (PDRIVER_DISPATCH)FatFsdQueryEa;
171 DriverObject->MajorFunction[IRP_MJ_SET_EA] = (PDRIVER_DISPATCH)FatFsdSetEa;
172 DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = (PDRIVER_DISPATCH)FatFsdFlushBuffers;
173 DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = (PDRIVER_DISPATCH)FatFsdQueryVolumeInformation;
174 DriverObject->MajorFunction[IRP_MJ_SET_VOLUME_INFORMATION] = (PDRIVER_DISPATCH)FatFsdSetVolumeInformation;
175 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = (PDRIVER_DISPATCH)FatFsdCleanup;
176 DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = (PDRIVER_DISPATCH)FatFsdDirectoryControl;
177 DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = (PDRIVER_DISPATCH)FatFsdFileSystemControl;
178 DriverObject->MajorFunction[IRP_MJ_LOCK_CONTROL] = (PDRIVER_DISPATCH)FatFsdLockControl;
179 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)FatFsdDeviceControl;
180 DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = (PDRIVER_DISPATCH)FatFsdShutdown;
181 DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH)FatFsdPnp;
182
183 DriverObject->FastIoDispatch = &FatFastIoDispatch;
184
185 RtlZeroMemory(&FatFastIoDispatch, sizeof(FatFastIoDispatch));
186
187 FatFastIoDispatch.SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
188 FatFastIoDispatch.FastIoCheckIfPossible = FatFastIoCheckIfPossible; // CheckForFastIo
189 FatFastIoDispatch.FastIoRead = FsRtlCopyRead; // Read
190 FatFastIoDispatch.FastIoWrite = FsRtlCopyWrite; // Write
191 FatFastIoDispatch.FastIoQueryBasicInfo = FatFastQueryBasicInfo; // QueryBasicInfo
192 FatFastIoDispatch.FastIoQueryStandardInfo = FatFastQueryStdInfo; // QueryStandardInfo
193 FatFastIoDispatch.FastIoLock = FatFastLock; // Lock
194 FatFastIoDispatch.FastIoUnlockSingle = FatFastUnlockSingle; // UnlockSingle
195 FatFastIoDispatch.FastIoUnlockAll = FatFastUnlockAll; // UnlockAll
196 FatFastIoDispatch.FastIoUnlockAllByKey = FatFastUnlockAllByKey; // UnlockAllByKey
197 FatFastIoDispatch.FastIoQueryNetworkOpenInfo = FatFastQueryNetworkOpenInfo;
198 FatFastIoDispatch.AcquireForCcFlush = FatAcquireForCcFlush;
199 FatFastIoDispatch.ReleaseForCcFlush = FatReleaseForCcFlush;
200 FatFastIoDispatch.MdlRead = FsRtlMdlReadDev;
201 FatFastIoDispatch.MdlReadComplete = FsRtlMdlReadCompleteDev;
202 FatFastIoDispatch.PrepareMdlWrite = FsRtlPrepareMdlWriteDev;
203 FatFastIoDispatch.MdlWriteComplete = FsRtlMdlWriteCompleteDev;
204
205 #ifdef _MSC_VER
206 #pragma prefast( pop )
207 #endif
208
209 //
210 // Initialize the filter callbacks we use.
211 //
212
213 RtlZeroMemory( &FilterCallbacks,
214 sizeof(FS_FILTER_CALLBACKS) );
215
216 FilterCallbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS);
217 FilterCallbacks.PreAcquireForSectionSynchronization = FatFilterCallbackAcquireForCreateSection;
218
219 Status = FsRtlRegisterFileSystemFilterCallbacks( DriverObject,
220 &FilterCallbacks );
221
222 if (!NT_SUCCESS( Status )) {
223
224 IoDeleteDevice( FatDiskFileSystemDeviceObject );
225 IoDeleteDevice( FatCdromFileSystemDeviceObject );
226 return Status;
227 }
228
229 //
230 // Initialize the global data structures
231 //
232
233 //
234 // The FatData record
235 //
236
237 RtlZeroMemory( &FatData, sizeof(FAT_DATA));
238
239 FatData.NodeTypeCode = FAT_NTC_DATA_HEADER;
240 FatData.NodeByteSize = sizeof(FAT_DATA);
241
242 InitializeListHead(&FatData.VcbQueue);
243
244 FatData.DriverObject = DriverObject;
245 FatData.DiskFileSystemDeviceObject = FatDiskFileSystemDeviceObject;
246 FatData.CdromFileSystemDeviceObject = FatCdromFileSystemDeviceObject;
247
248 //
249 // This list head keeps track of closes yet to be done.
250 //
251
252 InitializeListHead( &FatData.AsyncCloseList );
253 InitializeListHead( &FatData.DelayedCloseList );
254
255 FatData.FatCloseItem = IoAllocateWorkItem( FatDiskFileSystemDeviceObject);
256
257 if (FatData.FatCloseItem == NULL) {
258 IoDeleteDevice (FatDiskFileSystemDeviceObject);
259 IoDeleteDevice (FatCdromFileSystemDeviceObject);
260 return STATUS_INSUFFICIENT_RESOURCES;
261 }
262
263 //
264 // Allocate the zero page
265 //
266
267 FatData.ZeroPage = ExAllocatePoolWithTag( NonPagedPoolNx, PAGE_SIZE, 'ZtaF' );
268 if (FatData.ZeroPage == NULL) {
269 IoDeleteDevice (FatDiskFileSystemDeviceObject);
270 IoDeleteDevice (FatCdromFileSystemDeviceObject);
271 return STATUS_INSUFFICIENT_RESOURCES;
272 }
273 RtlZeroMemory( FatData.ZeroPage, PAGE_SIZE );
274
275
276 //
277 // Now initialize our general purpose spinlock (gag) and figure out how
278 // deep and wide we want our delayed lists (along with fooling ourselves
279 // about the lookaside depths).
280 //
281
282 KeInitializeSpinLock( &FatData.GeneralSpinLock );
283
284 switch ( MmQuerySystemSize() ) {
285
286 case MmSmallSystem:
287
288 MaxDepth = 4;
289 FatMaxDelayedCloseCount = FAT_MAX_DELAYED_CLOSES;
290 break;
291
292 case MmMediumSystem:
293
294 MaxDepth = 8;
295 FatMaxDelayedCloseCount = 4 * FAT_MAX_DELAYED_CLOSES;
296 break;
297
298 case MmLargeSystem:
299 default:
300
301 MaxDepth = 16;
302 FatMaxDelayedCloseCount = 16 * FAT_MAX_DELAYED_CLOSES;
303 break;
304 }
305
306
307 //
308 // Initialize the cache manager callback routines
309 //
310
311 FatData.CacheManagerCallbacks.AcquireForLazyWrite = &FatAcquireFcbForLazyWrite;
312 FatData.CacheManagerCallbacks.ReleaseFromLazyWrite = &FatReleaseFcbFromLazyWrite;
313 FatData.CacheManagerCallbacks.AcquireForReadAhead = &FatAcquireFcbForReadAhead;
314 FatData.CacheManagerCallbacks.ReleaseFromReadAhead = &FatReleaseFcbFromReadAhead;
315
316 FatData.CacheManagerNoOpCallbacks.AcquireForLazyWrite = &FatNoOpAcquire;
317 FatData.CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = &FatNoOpRelease;
318 FatData.CacheManagerNoOpCallbacks.AcquireForReadAhead = &FatNoOpAcquire;
319 FatData.CacheManagerNoOpCallbacks.ReleaseFromReadAhead = &FatNoOpRelease;
320
321 //
322 // Set up global pointer to our process.
323 //
324
325 FatData.OurProcess = PsGetCurrentProcess();
326
327 //
328 // Setup the number of processors we support for statistics as the current number
329 // running.
330 //
331
332 #if (NTDDI_VERSION >= NTDDI_VISTA)
333 FatData.NumberProcessors = KeQueryActiveProcessorCount( NULL );
334 #else
335 FatData.NumberProcessors = KeNumberProcessors;
336 #endif
337
338
339 //
340 // Read the registry to determine if we are in ChicagoMode.
341 //
342
343 ValueName.Buffer = COMPATIBILITY_MODE_VALUE_NAME;
344 ValueName.Length = sizeof(COMPATIBILITY_MODE_VALUE_NAME) - sizeof(WCHAR);
345 ValueName.MaximumLength = sizeof(COMPATIBILITY_MODE_VALUE_NAME);
346
347 Status = FatGetCompatibilityModeValue( &ValueName, &Value );
348
349 if (NT_SUCCESS(Status) && FlagOn(Value, 1)) {
350
351 FatData.ChicagoMode = FALSE;
352
353 } else {
354
355 FatData.ChicagoMode = TRUE;
356 }
357
358 //
359 // Read the registry to determine if we are going to generate LFNs
360 // for valid 8.3 names with extended characters.
361 //
362
363 ValueName.Buffer = CODE_PAGE_INVARIANCE_VALUE_NAME;
364 ValueName.Length = sizeof(CODE_PAGE_INVARIANCE_VALUE_NAME) - sizeof(WCHAR);
365 ValueName.MaximumLength = sizeof(CODE_PAGE_INVARIANCE_VALUE_NAME);
366
367 Status = FatGetCompatibilityModeValue( &ValueName, &Value );
368
369 if (NT_SUCCESS(Status) && FlagOn(Value, 1)) {
370
371 FatData.CodePageInvariant = FALSE;
372
373 } else {
374
375 FatData.CodePageInvariant = TRUE;
376 }
377
378 //
379 // Initialize our global resource and fire up the lookaside lists.
380 //
381
382 ExInitializeResourceLite( &FatData.Resource );
383
384 ExInitializeNPagedLookasideList( &FatIrpContextLookasideList,
385 NULL,
386 NULL,
387 POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE,
388 sizeof(IRP_CONTEXT),
389 TAG_IRP_CONTEXT,
390 MaxDepth );
391
392 ExInitializeNPagedLookasideList( &FatNonPagedFcbLookasideList,
393 NULL,
394 NULL,
395 POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE,
396 sizeof(NON_PAGED_FCB),
397 TAG_FCB_NONPAGED,
398 MaxDepth );
399
400 ExInitializeNPagedLookasideList( &FatEResourceLookasideList,
401 NULL,
402 NULL,
403 POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE,
404 sizeof(ERESOURCE),
405 TAG_ERESOURCE,
406 MaxDepth );
407
408 ExInitializeSListHead( &FatCloseContextSList );
409 ExInitializeFastMutex( &FatCloseQueueMutex );
410 KeInitializeEvent( &FatReserveEvent, SynchronizationEvent, TRUE );
411
412 //
413 // Register the file system with the I/O system
414 //
415
416 IoRegisterFileSystem(FatDiskFileSystemDeviceObject);
417 ObReferenceObject (FatDiskFileSystemDeviceObject);
418 IoRegisterFileSystem(FatCdromFileSystemDeviceObject);
419 ObReferenceObject (FatCdromFileSystemDeviceObject);
420
421 //
422 // Find out if we are running an a FujitsuFMR machine.
423 //
424
425 FatData.FujitsuFMR = FatIsFujitsuFMR();
426
427 #if (NTDDI_VERSION >= NTDDI_WIN8)
428
429 //
430 // Find out global disk accounting state, cache the result
431 //
432
433 FatDiskAccountingEnabled = PsIsDiskCountersEnabled();
434
435 #endif
436
437 //
438 // And return to our caller
439 //
440
441 return( STATUS_SUCCESS );
442 }
443
444
445 _Function_class_(DRIVER_UNLOAD)\f
446 VOID
447 NTAPI
448 FatUnload(
449 _In_ _Unreferenced_parameter_ PDRIVER_OBJECT DriverObject
450 )
451
452 /*++
453
454 Routine Description:
455
456 This is the unload routine for the filesystem
457
458 Arguments:
459
460 DriverObject - Pointer to driver object created by the system.
461
462 Return Value:
463
464 None
465
466 --*/
467
468 {
469 UNREFERENCED_PARAMETER( DriverObject );
470
471
472 ExDeleteNPagedLookasideList (&FatEResourceLookasideList);
473 ExDeleteNPagedLookasideList (&FatNonPagedFcbLookasideList);
474 ExDeleteNPagedLookasideList (&FatIrpContextLookasideList);
475 ExDeleteResourceLite( &FatData.Resource );
476 IoFreeWorkItem (FatData.FatCloseItem);
477 ObDereferenceObject( FatDiskFileSystemDeviceObject);
478 ObDereferenceObject( FatCdromFileSystemDeviceObject);
479 }
480
481 \f
482 //
483 // Local Support routine
484 //
485
486 NTSTATUS
487 FatGetCompatibilityModeValue (
488 IN PUNICODE_STRING ValueName,
489 IN OUT PULONG Value
490 )
491
492 /*++
493
494 Routine Description:
495
496 Given a unicode value name this routine will go into the registry
497 location for the Chicago compatibilitymode information and get the
498 value.
499
500 Arguments:
501
502 ValueName - the unicode name for the registry value located in the registry.
503 Value - a pointer to the ULONG for the result.
504
505 Return Value:
506
507 NTSTATUS
508
509 If STATUS_SUCCESSFUL is returned, the location *Value will be
510 updated with the DWORD value from the registry. If any failing
511 status is returned, this value is untouched.
512
513 --*/
514
515 {
516 HANDLE Handle;
517 NTSTATUS Status;
518 ULONG RequestLength;
519 ULONG ResultLength;
520 UCHAR Buffer[KEY_WORK_AREA];
521 UNICODE_STRING KeyName;
522 OBJECT_ATTRIBUTES ObjectAttributes;
523 PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
524
525 KeyName.Buffer = COMPATIBILITY_MODE_KEY_NAME;
526 KeyName.Length = sizeof(COMPATIBILITY_MODE_KEY_NAME) - sizeof(WCHAR);
527 KeyName.MaximumLength = sizeof(COMPATIBILITY_MODE_KEY_NAME);
528
529 InitializeObjectAttributes(&ObjectAttributes,
530 &KeyName,
531 OBJ_CASE_INSENSITIVE,
532 NULL,
533 NULL);
534
535 Status = ZwOpenKey(&Handle,
536 KEY_READ,
537 &ObjectAttributes);
538
539 if (!NT_SUCCESS(Status)) {
540
541 return Status;
542 }
543
544 RequestLength = KEY_WORK_AREA;
545
546 KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buffer;
547
548 while (1) {
549
550 Status = ZwQueryValueKey(Handle,
551 ValueName,
552 KeyValueFullInformation,
553 KeyValueInformation,
554 RequestLength,
555 &ResultLength);
556
557 NT_ASSERT( Status != STATUS_BUFFER_OVERFLOW );
558
559 if (Status == STATUS_BUFFER_OVERFLOW) {
560
561 //
562 // Try to get a buffer big enough.
563 //
564
565 if (KeyValueInformation != (PKEY_VALUE_FULL_INFORMATION)Buffer) {
566
567 ExFreePool(KeyValueInformation);
568 }
569
570 RequestLength += 256;
571
572 KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)
573 ExAllocatePoolWithTag(PagedPool,
574 RequestLength,
575 ' taF');
576
577 if (!KeyValueInformation) {
578
579 ZwClose(Handle);
580 return STATUS_NO_MEMORY;
581 }
582
583 } else {
584
585 break;
586 }
587 }
588
589 ZwClose(Handle);
590
591 if (NT_SUCCESS(Status)) {
592
593 if (KeyValueInformation->DataLength != 0) {
594
595 PULONG DataPtr;
596
597 //
598 // Return contents to the caller.
599 //
600
601 DataPtr = (PULONG)
602 ((PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset);
603 *Value = *DataPtr;
604
605 } else {
606
607 //
608 // Treat as if no value was found
609 //
610
611 Status = STATUS_OBJECT_NAME_NOT_FOUND;
612 }
613 }
614
615 if (KeyValueInformation != (PKEY_VALUE_FULL_INFORMATION)Buffer) {
616
617 ExFreePool(KeyValueInformation);
618 }
619
620 return Status;
621 }
622 \f
623 //
624 // Local Support routine
625 //
626
627 BOOLEAN
628 FatIsFujitsuFMR (
629 )
630
631 /*++
632
633 Routine Description:
634
635 This routine tells us if we are running on a FujitsuFMR machine.
636
637 Arguments:
638
639
640 Return Value:
641
642 BOOLEAN - TRUE if we are and FALSE otherwise
643
644 --*/
645
646 {
647 BOOLEAN Result;
648 HANDLE Handle;
649 NTSTATUS Status;
650 ULONG RequestLength;
651 ULONG ResultLength;
652 UCHAR Buffer[KEY_WORK_AREA];
653 UNICODE_STRING KeyName;
654 UNICODE_STRING ValueName;
655 OBJECT_ATTRIBUTES ObjectAttributes;
656 PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
657
658 //
659 // Set default as PC/AT
660 //
661
662 KeyName.Buffer = REGISTRY_HARDWARE_DESCRIPTION_W;
663 KeyName.Length = sizeof(REGISTRY_HARDWARE_DESCRIPTION_W) - sizeof(WCHAR);
664 KeyName.MaximumLength = sizeof(REGISTRY_HARDWARE_DESCRIPTION_W);
665
666 InitializeObjectAttributes(&ObjectAttributes,
667 &KeyName,
668 OBJ_CASE_INSENSITIVE,
669 NULL,
670 NULL);
671
672 Status = ZwOpenKey(&Handle,
673 KEY_READ,
674 &ObjectAttributes);
675
676 if (!NT_SUCCESS(Status)) {
677
678 return FALSE;
679 }
680
681 ValueName.Buffer = REGISTRY_MACHINE_IDENTIFIER_W;
682 ValueName.Length = sizeof(REGISTRY_MACHINE_IDENTIFIER_W) - sizeof(WCHAR);
683 ValueName.MaximumLength = sizeof(REGISTRY_MACHINE_IDENTIFIER_W);
684
685 RequestLength = KEY_WORK_AREA;
686
687 KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buffer;
688
689 while (1) {
690
691 Status = ZwQueryValueKey(Handle,
692 &ValueName,
693 KeyValueFullInformation,
694 KeyValueInformation,
695 RequestLength,
696 &ResultLength);
697
698 // NT_ASSERT( Status != STATUS_BUFFER_OVERFLOW );
699
700 if (Status == STATUS_BUFFER_OVERFLOW) {
701
702 //
703 // Try to get a buffer big enough.
704 //
705
706 if (KeyValueInformation != (PKEY_VALUE_FULL_INFORMATION)Buffer) {
707
708 ExFreePool(KeyValueInformation);
709 }
710
711 RequestLength += 256;
712
713 KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)
714 ExAllocatePoolWithTag(PagedPool, RequestLength, ' taF');
715
716 if (!KeyValueInformation) {
717
718 ZwClose(Handle);
719 return FALSE;
720 }
721
722 } else {
723
724 break;
725 }
726 }
727
728 ZwClose(Handle);
729
730 if (NT_SUCCESS(Status) &&
731 (KeyValueInformation->DataLength >= sizeof(FUJITSU_FMR_NAME_W)) &&
732 (RtlCompareMemory((PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset,
733 FUJITSU_FMR_NAME_W,
734 sizeof(FUJITSU_FMR_NAME_W) - sizeof(WCHAR)) ==
735 sizeof(FUJITSU_FMR_NAME_W) - sizeof(WCHAR))) {
736
737 Result = TRUE;
738
739 } else {
740
741 Result = FALSE;
742 }
743
744 if (KeyValueInformation != (PKEY_VALUE_FULL_INFORMATION)Buffer) {
745
746 ExFreePool(KeyValueInformation);
747 }
748
749 return Result;
750 }
751