[FASTFAT] Fix size checking in VfatGetFileNameInformation()
[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 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 #ifndef __REACTOS__
32 _In_ _Unreferenced_parameter_ PDRIVER_OBJECT DriverObject
33 #else
34 _In_ PDRIVER_OBJECT DriverObject
35 #endif
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 #ifndef __REACTOS__
268 FatData.ZeroPage = ExAllocatePoolWithTag( NonPagedPoolNx, PAGE_SIZE, 'ZtaF' );
269 #else
270 FatData.ZeroPage = ExAllocatePoolWithTag( NonPagedPool, PAGE_SIZE, 'ZtaF' );
271 #endif
272 if (FatData.ZeroPage == NULL) {
273 IoDeleteDevice (FatDiskFileSystemDeviceObject);
274 IoDeleteDevice (FatCdromFileSystemDeviceObject);
275 return STATUS_INSUFFICIENT_RESOURCES;
276 }
277 RtlZeroMemory( FatData.ZeroPage, PAGE_SIZE );
278
279
280 //
281 // Now initialize our general purpose spinlock (gag) and figure out how
282 // deep and wide we want our delayed lists (along with fooling ourselves
283 // about the lookaside depths).
284 //
285
286 KeInitializeSpinLock( &FatData.GeneralSpinLock );
287
288 switch ( MmQuerySystemSize() ) {
289
290 case MmSmallSystem:
291
292 MaxDepth = 4;
293 FatMaxDelayedCloseCount = FAT_MAX_DELAYED_CLOSES;
294 break;
295
296 case MmMediumSystem:
297
298 MaxDepth = 8;
299 FatMaxDelayedCloseCount = 4 * FAT_MAX_DELAYED_CLOSES;
300 break;
301
302 case MmLargeSystem:
303 default:
304
305 MaxDepth = 16;
306 FatMaxDelayedCloseCount = 16 * FAT_MAX_DELAYED_CLOSES;
307 break;
308 }
309
310
311 //
312 // Initialize the cache manager callback routines
313 //
314
315 FatData.CacheManagerCallbacks.AcquireForLazyWrite = &FatAcquireFcbForLazyWrite;
316 FatData.CacheManagerCallbacks.ReleaseFromLazyWrite = &FatReleaseFcbFromLazyWrite;
317 FatData.CacheManagerCallbacks.AcquireForReadAhead = &FatAcquireFcbForReadAhead;
318 FatData.CacheManagerCallbacks.ReleaseFromReadAhead = &FatReleaseFcbFromReadAhead;
319
320 FatData.CacheManagerNoOpCallbacks.AcquireForLazyWrite = &FatNoOpAcquire;
321 FatData.CacheManagerNoOpCallbacks.ReleaseFromLazyWrite = &FatNoOpRelease;
322 FatData.CacheManagerNoOpCallbacks.AcquireForReadAhead = &FatNoOpAcquire;
323 FatData.CacheManagerNoOpCallbacks.ReleaseFromReadAhead = &FatNoOpRelease;
324
325 //
326 // Set up global pointer to our process.
327 //
328
329 FatData.OurProcess = PsGetCurrentProcess();
330
331 //
332 // Setup the number of processors we support for statistics as the current number
333 // running.
334 //
335
336 #if (NTDDI_VERSION >= NTDDI_VISTA)
337 FatData.NumberProcessors = KeQueryActiveProcessorCount( NULL );
338 #else
339 FatData.NumberProcessors = KeNumberProcessors;
340 #endif
341
342
343 //
344 // Read the registry to determine if we are in ChicagoMode.
345 //
346
347 ValueName.Buffer = COMPATIBILITY_MODE_VALUE_NAME;
348 ValueName.Length = sizeof(COMPATIBILITY_MODE_VALUE_NAME) - sizeof(WCHAR);
349 ValueName.MaximumLength = sizeof(COMPATIBILITY_MODE_VALUE_NAME);
350
351 Status = FatGetCompatibilityModeValue( &ValueName, &Value );
352
353 if (NT_SUCCESS(Status) && FlagOn(Value, 1)) {
354
355 FatData.ChicagoMode = FALSE;
356
357 } else {
358
359 FatData.ChicagoMode = TRUE;
360 }
361
362 //
363 // Read the registry to determine if we are going to generate LFNs
364 // for valid 8.3 names with extended characters.
365 //
366
367 ValueName.Buffer = CODE_PAGE_INVARIANCE_VALUE_NAME;
368 ValueName.Length = sizeof(CODE_PAGE_INVARIANCE_VALUE_NAME) - sizeof(WCHAR);
369 ValueName.MaximumLength = sizeof(CODE_PAGE_INVARIANCE_VALUE_NAME);
370
371 Status = FatGetCompatibilityModeValue( &ValueName, &Value );
372
373 if (NT_SUCCESS(Status) && FlagOn(Value, 1)) {
374
375 FatData.CodePageInvariant = FALSE;
376
377 } else {
378
379 FatData.CodePageInvariant = TRUE;
380 }
381
382 //
383 // Initialize our global resource and fire up the lookaside lists.
384 //
385
386 ExInitializeResourceLite( &FatData.Resource );
387
388 ExInitializeNPagedLookasideList( &FatIrpContextLookasideList,
389 NULL,
390 NULL,
391 #ifndef __REACTOS__
392 POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE,
393 #else
394 POOL_RAISE_IF_ALLOCATION_FAILURE,
395 #endif
396 sizeof(IRP_CONTEXT),
397 TAG_IRP_CONTEXT,
398 MaxDepth );
399
400 ExInitializeNPagedLookasideList( &FatNonPagedFcbLookasideList,
401 NULL,
402 NULL,
403 #ifndef __REACTOS__
404 POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE,
405 #else
406 POOL_RAISE_IF_ALLOCATION_FAILURE,
407 #endif
408 sizeof(NON_PAGED_FCB),
409 TAG_FCB_NONPAGED,
410 MaxDepth );
411
412 ExInitializeNPagedLookasideList( &FatEResourceLookasideList,
413 NULL,
414 NULL,
415 #ifndef __REACTOS__
416 POOL_NX_ALLOCATION | POOL_RAISE_IF_ALLOCATION_FAILURE,
417 #else
418 POOL_RAISE_IF_ALLOCATION_FAILURE,
419 #endif
420 sizeof(ERESOURCE),
421 TAG_ERESOURCE,
422 MaxDepth );
423
424 ExInitializeSListHead( &FatCloseContextSList );
425 ExInitializeFastMutex( &FatCloseQueueMutex );
426 KeInitializeEvent( &FatReserveEvent, SynchronizationEvent, TRUE );
427
428 //
429 // Register the file system with the I/O system
430 //
431
432 IoRegisterFileSystem(FatDiskFileSystemDeviceObject);
433 ObReferenceObject (FatDiskFileSystemDeviceObject);
434 IoRegisterFileSystem(FatCdromFileSystemDeviceObject);
435 ObReferenceObject (FatCdromFileSystemDeviceObject);
436
437 //
438 // Find out if we are running an a FujitsuFMR machine.
439 //
440
441 FatData.FujitsuFMR = FatIsFujitsuFMR();
442
443 #if (NTDDI_VERSION >= NTDDI_WIN8)
444
445 //
446 // Find out global disk accounting state, cache the result
447 //
448
449 FatDiskAccountingEnabled = PsIsDiskCountersEnabled();
450
451 #endif
452
453 //
454 // And return to our caller
455 //
456
457 return( STATUS_SUCCESS );
458 }
459
460
461 _Function_class_(DRIVER_UNLOAD)\f
462 VOID
463 NTAPI
464 FatUnload(
465 #ifndef __REACTOS__
466 _In_ _Unreferenced_parameter_ PDRIVER_OBJECT DriverObject
467 #else
468 _In_ PDRIVER_OBJECT DriverObject
469 #endif
470 )
471
472 /*++
473
474 Routine Description:
475
476 This is the unload routine for the filesystem
477
478 Arguments:
479
480 DriverObject - Pointer to driver object created by the system.
481
482 Return Value:
483
484 None
485
486 --*/
487
488 {
489 UNREFERENCED_PARAMETER( DriverObject );
490
491
492 ExDeleteNPagedLookasideList (&FatEResourceLookasideList);
493 ExDeleteNPagedLookasideList (&FatNonPagedFcbLookasideList);
494 ExDeleteNPagedLookasideList (&FatIrpContextLookasideList);
495 ExDeleteResourceLite( &FatData.Resource );
496 IoFreeWorkItem (FatData.FatCloseItem);
497 ObDereferenceObject( FatDiskFileSystemDeviceObject);
498 ObDereferenceObject( FatCdromFileSystemDeviceObject);
499 }
500
501 \f
502 //
503 // Local Support routine
504 //
505
506 NTSTATUS
507 FatGetCompatibilityModeValue (
508 IN PUNICODE_STRING ValueName,
509 IN OUT PULONG Value
510 )
511
512 /*++
513
514 Routine Description:
515
516 Given a unicode value name this routine will go into the registry
517 location for the Chicago compatibilitymode information and get the
518 value.
519
520 Arguments:
521
522 ValueName - the unicode name for the registry value located in the registry.
523 Value - a pointer to the ULONG for the result.
524
525 Return Value:
526
527 NTSTATUS
528
529 If STATUS_SUCCESSFUL is returned, the location *Value will be
530 updated with the DWORD value from the registry. If any failing
531 status is returned, this value is untouched.
532
533 --*/
534
535 {
536 HANDLE Handle;
537 NTSTATUS Status;
538 ULONG RequestLength;
539 ULONG ResultLength;
540 UCHAR Buffer[KEY_WORK_AREA];
541 UNICODE_STRING KeyName;
542 OBJECT_ATTRIBUTES ObjectAttributes;
543 PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
544
545 KeyName.Buffer = COMPATIBILITY_MODE_KEY_NAME;
546 KeyName.Length = sizeof(COMPATIBILITY_MODE_KEY_NAME) - sizeof(WCHAR);
547 KeyName.MaximumLength = sizeof(COMPATIBILITY_MODE_KEY_NAME);
548
549 InitializeObjectAttributes(&ObjectAttributes,
550 &KeyName,
551 OBJ_CASE_INSENSITIVE,
552 NULL,
553 NULL);
554
555 Status = ZwOpenKey(&Handle,
556 KEY_READ,
557 &ObjectAttributes);
558
559 if (!NT_SUCCESS(Status)) {
560
561 return Status;
562 }
563
564 RequestLength = KEY_WORK_AREA;
565
566 KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buffer;
567
568 while (1) {
569
570 Status = ZwQueryValueKey(Handle,
571 ValueName,
572 KeyValueFullInformation,
573 KeyValueInformation,
574 RequestLength,
575 &ResultLength);
576
577 NT_ASSERT( Status != STATUS_BUFFER_OVERFLOW );
578
579 if (Status == STATUS_BUFFER_OVERFLOW) {
580
581 //
582 // Try to get a buffer big enough.
583 //
584
585 if (KeyValueInformation != (PKEY_VALUE_FULL_INFORMATION)Buffer) {
586
587 ExFreePool(KeyValueInformation);
588 }
589
590 RequestLength += 256;
591
592 KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)
593 ExAllocatePoolWithTag(PagedPool,
594 RequestLength,
595 ' taF');
596
597 if (!KeyValueInformation) {
598
599 ZwClose(Handle);
600 return STATUS_NO_MEMORY;
601 }
602
603 } else {
604
605 break;
606 }
607 }
608
609 ZwClose(Handle);
610
611 if (NT_SUCCESS(Status)) {
612
613 if (KeyValueInformation->DataLength != 0) {
614
615 PULONG DataPtr;
616
617 //
618 // Return contents to the caller.
619 //
620
621 DataPtr = (PULONG)
622 ((PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset);
623 *Value = *DataPtr;
624
625 } else {
626
627 //
628 // Treat as if no value was found
629 //
630
631 Status = STATUS_OBJECT_NAME_NOT_FOUND;
632 }
633 }
634
635 if (KeyValueInformation != (PKEY_VALUE_FULL_INFORMATION)Buffer) {
636
637 ExFreePool(KeyValueInformation);
638 }
639
640 return Status;
641 }
642 \f
643 //
644 // Local Support routine
645 //
646
647 BOOLEAN
648 FatIsFujitsuFMR (
649 )
650
651 /*++
652
653 Routine Description:
654
655 This routine tells if is we running on a FujitsuFMR machine.
656
657 Arguments:
658
659
660 Return Value:
661
662 BOOLEAN - TRUE is we are and FALSE otherwise
663
664 --*/
665
666 {
667 BOOLEAN Result;
668 HANDLE Handle;
669 NTSTATUS Status;
670 ULONG RequestLength;
671 ULONG ResultLength;
672 UCHAR Buffer[KEY_WORK_AREA];
673 UNICODE_STRING KeyName;
674 UNICODE_STRING ValueName;
675 OBJECT_ATTRIBUTES ObjectAttributes;
676 PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
677
678 //
679 // Set default as PC/AT
680 //
681
682 KeyName.Buffer = REGISTRY_HARDWARE_DESCRIPTION_W;
683 KeyName.Length = sizeof(REGISTRY_HARDWARE_DESCRIPTION_W) - sizeof(WCHAR);
684 KeyName.MaximumLength = sizeof(REGISTRY_HARDWARE_DESCRIPTION_W);
685
686 InitializeObjectAttributes(&ObjectAttributes,
687 &KeyName,
688 OBJ_CASE_INSENSITIVE,
689 NULL,
690 NULL);
691
692 Status = ZwOpenKey(&Handle,
693 KEY_READ,
694 &ObjectAttributes);
695
696 if (!NT_SUCCESS(Status)) {
697
698 return FALSE;
699 }
700
701 ValueName.Buffer = REGISTRY_MACHINE_IDENTIFIER_W;
702 ValueName.Length = sizeof(REGISTRY_MACHINE_IDENTIFIER_W) - sizeof(WCHAR);
703 ValueName.MaximumLength = sizeof(REGISTRY_MACHINE_IDENTIFIER_W);
704
705 RequestLength = KEY_WORK_AREA;
706
707 KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)Buffer;
708
709 while (1) {
710
711 Status = ZwQueryValueKey(Handle,
712 &ValueName,
713 KeyValueFullInformation,
714 KeyValueInformation,
715 RequestLength,
716 &ResultLength);
717
718 // NT_ASSERT( Status != STATUS_BUFFER_OVERFLOW );
719
720 if (Status == STATUS_BUFFER_OVERFLOW) {
721
722 //
723 // Try to get a buffer big enough.
724 //
725
726 if (KeyValueInformation != (PKEY_VALUE_FULL_INFORMATION)Buffer) {
727
728 ExFreePool(KeyValueInformation);
729 }
730
731 RequestLength += 256;
732
733 KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION)
734 ExAllocatePoolWithTag(PagedPool, RequestLength, ' taF');
735
736 if (!KeyValueInformation) {
737
738 ZwClose(Handle);
739 return FALSE;
740 }
741
742 } else {
743
744 break;
745 }
746 }
747
748 ZwClose(Handle);
749
750 if (NT_SUCCESS(Status) &&
751 (KeyValueInformation->DataLength >= sizeof(FUJITSU_FMR_NAME_W)) &&
752 (RtlCompareMemory((PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset,
753 FUJITSU_FMR_NAME_W,
754 sizeof(FUJITSU_FMR_NAME_W) - sizeof(WCHAR)) ==
755 sizeof(FUJITSU_FMR_NAME_W) - sizeof(WCHAR))) {
756
757 Result = TRUE;
758
759 } else {
760
761 Result = FALSE;
762 }
763
764 if (KeyValueInformation != (PKEY_VALUE_FULL_INFORMATION)Buffer) {
765
766 ExFreePool(KeyValueInformation);
767 }
768
769 return Result;
770 }
771