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