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 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 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 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 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