1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/io/iomgr/driver.c 5 * PURPOSE: Driver Object Management 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 * Filip Navara (navaraf@reactos.org) 8 * Herv� Poussineau (hpoussin@reactos.org) 9 */ 10 11 /* INCLUDES *******************************************************************/ 12 13 #include <ntoskrnl.h> 14 #define NDEBUG 15 #include <debug.h> 16 17 /* GLOBALS ********************************************************************/ 18 19 ERESOURCE IopDriverLoadResource; 20 21 LIST_ENTRY DriverReinitListHead; 22 KSPIN_LOCK DriverReinitListLock; 23 PLIST_ENTRY DriverReinitTailEntry; 24 25 PLIST_ENTRY DriverBootReinitTailEntry; 26 LIST_ENTRY DriverBootReinitListHead; 27 KSPIN_LOCK DriverBootReinitListLock; 28 29 UNICODE_STRING IopHardwareDatabaseKey = 30 RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM"); 31 32 POBJECT_TYPE IoDriverObjectType = NULL; 33 34 #define TAG_RTLREGISTRY 'vrqR' 35 36 extern BOOLEAN ExpInTextModeSetup; 37 extern BOOLEAN PnpSystemInit; 38 extern BOOLEAN PnPBootDriversLoaded; 39 extern KEVENT PiEnumerationFinished; 40 41 USHORT IopGroupIndex; 42 PLIST_ENTRY IopGroupTable; 43 44 /* PRIVATE FUNCTIONS **********************************************************/ 45 46 NTSTATUS 47 NTAPI 48 IopInvalidDeviceRequest( 49 PDEVICE_OBJECT DeviceObject, 50 PIRP Irp) 51 { 52 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; 53 Irp->IoStatus.Information = 0; 54 IoCompleteRequest(Irp, IO_NO_INCREMENT); 55 return STATUS_INVALID_DEVICE_REQUEST; 56 } 57 58 VOID 59 NTAPI 60 IopDeleteDriver(IN PVOID ObjectBody) 61 { 62 PDRIVER_OBJECT DriverObject = ObjectBody; 63 PIO_CLIENT_EXTENSION DriverExtension, NextDriverExtension; 64 PAGED_CODE(); 65 66 DPRINT1("Deleting driver object '%wZ'\n", &DriverObject->DriverName); 67 68 /* There must be no device objects remaining at this point */ 69 ASSERT(!DriverObject->DeviceObject); 70 71 /* Get the extension and loop them */ 72 DriverExtension = IoGetDrvObjExtension(DriverObject)->ClientDriverExtension; 73 while (DriverExtension) 74 { 75 /* Get the next one */ 76 NextDriverExtension = DriverExtension->NextExtension; 77 ExFreePoolWithTag(DriverExtension, TAG_DRIVER_EXTENSION); 78 79 /* Move on */ 80 DriverExtension = NextDriverExtension; 81 } 82 83 /* Check if the driver image is still loaded */ 84 if (DriverObject->DriverSection) 85 { 86 /* Unload it */ 87 MmUnloadSystemImage(DriverObject->DriverSection); 88 } 89 90 /* Check if it has a name */ 91 if (DriverObject->DriverName.Buffer) 92 { 93 /* Free it */ 94 ExFreePool(DriverObject->DriverName.Buffer); 95 } 96 97 /* Check if it has a service key name */ 98 if (DriverObject->DriverExtension->ServiceKeyName.Buffer) 99 { 100 /* Free it */ 101 ExFreePool(DriverObject->DriverExtension->ServiceKeyName.Buffer); 102 } 103 } 104 105 NTSTATUS 106 FASTCALL 107 IopGetDriverObject( 108 PDRIVER_OBJECT *DriverObject, 109 PUNICODE_STRING ServiceName, 110 BOOLEAN FileSystem) 111 { 112 PDRIVER_OBJECT Object; 113 UNICODE_STRING Prefix; 114 UNICODE_STRING DriverName; 115 NTSTATUS Status; 116 117 DPRINT("IopGetDriverObject(%p '%wZ' %x)\n", 118 DriverObject, ServiceName, FileSystem); 119 120 ASSERT(ExIsResourceAcquiredExclusiveLite(&IopDriverLoadResource)); 121 *DriverObject = NULL; 122 123 /* Create ModuleName string */ 124 if (ServiceName == NULL || ServiceName->Buffer == NULL) 125 /* We don't know which DriverObject we have to open */ 126 return STATUS_INVALID_PARAMETER_2; 127 128 if (FileSystem != FALSE) 129 RtlInitUnicodeString(&Prefix, FILESYSTEM_ROOT_NAME); 130 else 131 RtlInitUnicodeString(&Prefix, DRIVER_ROOT_NAME); 132 133 DriverName.Length = 0; 134 DriverName.MaximumLength = Prefix.Length + ServiceName->Length + sizeof(UNICODE_NULL); 135 ASSERT(DriverName.MaximumLength > ServiceName->Length); 136 DriverName.Buffer = ExAllocatePoolWithTag(PagedPool, DriverName.MaximumLength, TAG_IO); 137 if (DriverName.Buffer == NULL) 138 { 139 return STATUS_INSUFFICIENT_RESOURCES; 140 } 141 RtlAppendUnicodeStringToString(&DriverName, &Prefix); 142 RtlAppendUnicodeStringToString(&DriverName, ServiceName); 143 144 DPRINT("Driver name: '%wZ'\n", &DriverName); 145 146 /* Open driver object */ 147 Status = ObReferenceObjectByName(&DriverName, 148 OBJ_OPENIF | OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, /* Attributes */ 149 NULL, /* PassedAccessState */ 150 0, /* DesiredAccess */ 151 IoDriverObjectType, 152 KernelMode, 153 NULL, /* ParseContext */ 154 (PVOID*)&Object); 155 ExFreePoolWithTag(DriverName.Buffer, TAG_IO); 156 if (!NT_SUCCESS(Status)) 157 { 158 DPRINT("Failed to reference driver object, status=0x%08x\n", Status); 159 return Status; 160 } 161 162 *DriverObject = Object; 163 164 DPRINT("Driver Object: %p\n", Object); 165 166 return STATUS_SUCCESS; 167 } 168 169 /* 170 * RETURNS 171 * TRUE if String2 contains String1 as a suffix. 172 */ 173 BOOLEAN 174 NTAPI 175 IopSuffixUnicodeString( 176 IN PCUNICODE_STRING String1, 177 IN PCUNICODE_STRING String2) 178 { 179 PWCHAR pc1; 180 PWCHAR pc2; 181 ULONG Length; 182 183 if (String2->Length < String1->Length) 184 return FALSE; 185 186 Length = String1->Length / 2; 187 pc1 = String1->Buffer; 188 pc2 = &String2->Buffer[String2->Length / sizeof(WCHAR) - Length]; 189 190 if (pc1 && pc2) 191 { 192 while (Length--) 193 { 194 if( *pc1++ != *pc2++ ) 195 return FALSE; 196 } 197 return TRUE; 198 } 199 return FALSE; 200 } 201 202 /* 203 * IopDisplayLoadingMessage 204 * 205 * Display 'Loading XXX...' message. 206 */ 207 VOID 208 FASTCALL 209 IopDisplayLoadingMessage(PUNICODE_STRING ServiceName) 210 { 211 CHAR TextBuffer[256]; 212 UNICODE_STRING DotSys = RTL_CONSTANT_STRING(L".SYS"); 213 214 if (ExpInTextModeSetup) return; 215 if (!KeLoaderBlock) return; 216 RtlUpcaseUnicodeString(ServiceName, ServiceName, FALSE); 217 snprintf(TextBuffer, sizeof(TextBuffer), 218 "%s%sSystem32\\Drivers\\%wZ%s\r\n", 219 KeLoaderBlock->ArcBootDeviceName, 220 KeLoaderBlock->NtBootPathName, 221 ServiceName, 222 IopSuffixUnicodeString(&DotSys, ServiceName) ? "" : ".SYS"); 223 HalDisplayString(TextBuffer); 224 } 225 226 /* 227 * IopNormalizeImagePath 228 * 229 * Normalize an image path to contain complete path. 230 * 231 * Parameters 232 * ImagePath 233 * The input path and on exit the result path. ImagePath.Buffer 234 * must be allocated by ExAllocatePool on input. Caller is responsible 235 * for freeing the buffer when it's no longer needed. 236 * 237 * ServiceName 238 * Name of the service that ImagePath belongs to. 239 * 240 * Return Value 241 * Status 242 * 243 * Remarks 244 * The input image path isn't freed on error. 245 */ 246 NTSTATUS 247 FASTCALL 248 IopNormalizeImagePath( 249 _Inout_ _When_(return>=0, _At_(ImagePath->Buffer, _Post_notnull_ __drv_allocatesMem(Mem))) 250 PUNICODE_STRING ImagePath, 251 _In_ PUNICODE_STRING ServiceName) 252 { 253 UNICODE_STRING SystemRootString = RTL_CONSTANT_STRING(L"\\SystemRoot\\"); 254 UNICODE_STRING DriversPathString = RTL_CONSTANT_STRING(L"\\SystemRoot\\System32\\drivers\\"); 255 UNICODE_STRING DotSysString = RTL_CONSTANT_STRING(L".sys"); 256 UNICODE_STRING InputImagePath; 257 258 DPRINT("Normalizing image path '%wZ' for service '%wZ'\n", ImagePath, ServiceName); 259 260 InputImagePath = *ImagePath; 261 if (InputImagePath.Length == 0) 262 { 263 ImagePath->Length = 0; 264 ImagePath->MaximumLength = DriversPathString.Length + 265 ServiceName->Length + 266 DotSysString.Length + 267 sizeof(UNICODE_NULL); 268 ImagePath->Buffer = ExAllocatePoolWithTag(NonPagedPool, 269 ImagePath->MaximumLength, 270 TAG_IO); 271 if (ImagePath->Buffer == NULL) 272 return STATUS_NO_MEMORY; 273 274 RtlCopyUnicodeString(ImagePath, &DriversPathString); 275 RtlAppendUnicodeStringToString(ImagePath, ServiceName); 276 RtlAppendUnicodeStringToString(ImagePath, &DotSysString); 277 } 278 else if (InputImagePath.Buffer[0] != L'\\') 279 { 280 ImagePath->Length = 0; 281 ImagePath->MaximumLength = SystemRootString.Length + 282 InputImagePath.Length + 283 sizeof(UNICODE_NULL); 284 ImagePath->Buffer = ExAllocatePoolWithTag(NonPagedPool, 285 ImagePath->MaximumLength, 286 TAG_IO); 287 if (ImagePath->Buffer == NULL) 288 return STATUS_NO_MEMORY; 289 290 RtlCopyUnicodeString(ImagePath, &SystemRootString); 291 RtlAppendUnicodeStringToString(ImagePath, &InputImagePath); 292 293 /* Free caller's string */ 294 ExFreePoolWithTag(InputImagePath.Buffer, TAG_RTLREGISTRY); 295 } 296 297 DPRINT("Normalized image path is '%wZ' for service '%wZ'\n", ImagePath, ServiceName); 298 299 return STATUS_SUCCESS; 300 } 301 302 /* 303 * IopLoadServiceModule 304 * 305 * Load a module specified by registry settings for service. 306 * 307 * Parameters 308 * ServiceName 309 * Name of the service to load. 310 * 311 * Return Value 312 * Status 313 */ 314 NTSTATUS 315 FASTCALL 316 IopLoadServiceModule( 317 IN PUNICODE_STRING ServiceName, 318 OUT PLDR_DATA_TABLE_ENTRY *ModuleObject) 319 { 320 RTL_QUERY_REGISTRY_TABLE QueryTable[3]; 321 ULONG ServiceStart; 322 UNICODE_STRING ServiceImagePath, CCSName; 323 NTSTATUS Status; 324 HANDLE CCSKey, ServiceKey; 325 PVOID BaseAddress; 326 327 ASSERT(ExIsResourceAcquiredExclusiveLite(&IopDriverLoadResource)); 328 ASSERT(ServiceName->Length); 329 DPRINT("IopLoadServiceModule(%wZ, 0x%p)\n", ServiceName, ModuleObject); 330 331 if (ExpInTextModeSetup) 332 { 333 /* We have no registry, but luckily we know where all the drivers are */ 334 DPRINT1("IopLoadServiceModule(%wZ, 0x%p) called in ExpInTextModeSetup mode...\n", ServiceName, ModuleObject); 335 336 /* ServiceStart < 4 is all that matters */ 337 ServiceStart = 0; 338 339 /* IopNormalizeImagePath will do all of the work for us if we give it an empty string */ 340 RtlInitEmptyUnicodeString(&ServiceImagePath, NULL, 0); 341 } 342 else 343 { 344 /* Open CurrentControlSet */ 345 RtlInitUnicodeString(&CCSName, 346 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services"); 347 Status = IopOpenRegistryKeyEx(&CCSKey, NULL, &CCSName, KEY_READ); 348 if (!NT_SUCCESS(Status)) 349 { 350 DPRINT1("IopOpenRegistryKeyEx() failed for '%wZ' with status 0x%lx\n", 351 &CCSName, Status); 352 return Status; 353 } 354 355 /* Open service key */ 356 Status = IopOpenRegistryKeyEx(&ServiceKey, CCSKey, ServiceName, KEY_READ); 357 if (!NT_SUCCESS(Status)) 358 { 359 DPRINT1("IopOpenRegistryKeyEx() failed for '%wZ' with status 0x%lx\n", 360 ServiceName, Status); 361 ZwClose(CCSKey); 362 return Status; 363 } 364 365 /* 366 * Get information about the service. 367 */ 368 RtlZeroMemory(QueryTable, sizeof(QueryTable)); 369 370 RtlInitUnicodeString(&ServiceImagePath, NULL); 371 372 QueryTable[0].Name = L"Start"; 373 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; 374 QueryTable[0].EntryContext = &ServiceStart; 375 376 QueryTable[1].Name = L"ImagePath"; 377 QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; 378 QueryTable[1].EntryContext = &ServiceImagePath; 379 380 Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, 381 (PWSTR)ServiceKey, 382 QueryTable, 383 NULL, 384 NULL); 385 386 ZwClose(ServiceKey); 387 ZwClose(CCSKey); 388 389 if (!NT_SUCCESS(Status)) 390 { 391 DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status); 392 return Status; 393 } 394 } 395 396 /* 397 * Normalize the image path for all later processing. 398 */ 399 Status = IopNormalizeImagePath(&ServiceImagePath, ServiceName); 400 401 if (!NT_SUCCESS(Status)) 402 { 403 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status); 404 return Status; 405 } 406 407 /* 408 * Case for disabled drivers 409 */ 410 if (ServiceStart >= 4) 411 { 412 /* We can't load this */ 413 Status = STATUS_DRIVER_UNABLE_TO_LOAD; 414 } 415 else 416 { 417 DPRINT("Loading module from %wZ\n", &ServiceImagePath); 418 Status = MmLoadSystemImage(&ServiceImagePath, NULL, NULL, 0, (PVOID)ModuleObject, &BaseAddress); 419 if (NT_SUCCESS(Status)) 420 { 421 IopDisplayLoadingMessage(ServiceName); 422 } 423 } 424 425 ExFreePool(ServiceImagePath.Buffer); 426 427 /* 428 * Now check if the module was loaded successfully. 429 */ 430 if (!NT_SUCCESS(Status)) 431 { 432 DPRINT("Module loading failed (Status %x)\n", Status); 433 } 434 435 DPRINT("Module loading (Status %x)\n", Status); 436 437 return Status; 438 } 439 440 VOID 441 NTAPI 442 MmFreeDriverInitialization(IN PLDR_DATA_TABLE_ENTRY LdrEntry); 443 444 /* 445 * IopInitializeDriverModule 446 * 447 * Initialize a loaded driver. 448 * 449 * Parameters 450 * DeviceNode 451 * Pointer to device node. 452 * 453 * ModuleObject 454 * Module object representing the driver. It can be retrieve by 455 * IopLoadServiceModule. 456 * 457 * ServiceName 458 * Name of the service (as in registry). 459 * 460 * FileSystemDriver 461 * Set to TRUE for file system drivers. 462 * 463 * DriverObject 464 * On successful return this contains the driver object representing 465 * the loaded driver. 466 */ 467 NTSTATUS 468 FASTCALL 469 IopInitializeDriverModule( 470 IN PDEVICE_NODE DeviceNode, 471 IN PLDR_DATA_TABLE_ENTRY ModuleObject, 472 IN PUNICODE_STRING ServiceName, 473 IN BOOLEAN FileSystemDriver, 474 OUT PDRIVER_OBJECT *DriverObject) 475 { 476 static const WCHAR ServicesKeyName[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"; 477 UNICODE_STRING DriverName; 478 UNICODE_STRING RegistryKey; 479 PDRIVER_INITIALIZE DriverEntry; 480 PDRIVER_OBJECT Driver; 481 NTSTATUS Status; 482 483 DriverEntry = ModuleObject->EntryPoint; 484 485 if (ServiceName != NULL && ServiceName->Length != 0) 486 { 487 RegistryKey.Length = 0; 488 RegistryKey.MaximumLength = sizeof(ServicesKeyName) + ServiceName->Length; 489 RegistryKey.Buffer = ExAllocatePoolWithTag(PagedPool, 490 RegistryKey.MaximumLength, 491 TAG_IO); 492 if (RegistryKey.Buffer == NULL) 493 { 494 return STATUS_INSUFFICIENT_RESOURCES; 495 } 496 RtlAppendUnicodeToString(&RegistryKey, ServicesKeyName); 497 RtlAppendUnicodeStringToString(&RegistryKey, ServiceName); 498 } 499 else 500 { 501 RtlInitEmptyUnicodeString(&RegistryKey, NULL, 0); 502 } 503 504 /* Create ModuleName string */ 505 if (ServiceName && ServiceName->Length > 0) 506 { 507 DriverName.Length = 0; 508 DriverName.MaximumLength = sizeof(FILESYSTEM_ROOT_NAME) + ServiceName->Length; 509 DriverName.Buffer = ExAllocatePoolWithTag(PagedPool, 510 DriverName.MaximumLength, 511 TAG_IO); 512 if (DriverName.Buffer == NULL) 513 { 514 RtlFreeUnicodeString(&RegistryKey); 515 return STATUS_INSUFFICIENT_RESOURCES; 516 } 517 518 if (FileSystemDriver != FALSE) 519 RtlAppendUnicodeToString(&DriverName, FILESYSTEM_ROOT_NAME); 520 else 521 RtlAppendUnicodeToString(&DriverName, DRIVER_ROOT_NAME); 522 RtlAppendUnicodeStringToString(&DriverName, ServiceName); 523 524 DPRINT("Driver name: '%wZ'\n", &DriverName); 525 } 526 else 527 { 528 RtlInitEmptyUnicodeString(&DriverName, NULL, 0); 529 } 530 531 Status = IopCreateDriver(DriverName.Length > 0 ? &DriverName : NULL, 532 DriverEntry, 533 &RegistryKey, 534 ServiceName, 535 ModuleObject, 536 &Driver); 537 RtlFreeUnicodeString(&RegistryKey); 538 RtlFreeUnicodeString(&DriverName); 539 540 if (!NT_SUCCESS(Status)) 541 { 542 DPRINT("IopCreateDriver() failed (Status 0x%08lx)\n", Status); 543 return Status; 544 } 545 546 *DriverObject = Driver; 547 548 MmFreeDriverInitialization((PLDR_DATA_TABLE_ENTRY)Driver->DriverSection); 549 550 /* Set the driver as initialized */ 551 IopReadyDeviceObjects(Driver); 552 553 if (PnpSystemInit) IopReinitializeDrivers(); 554 555 return STATUS_SUCCESS; 556 } 557 558 /* 559 * IopAttachFilterDriversCallback 560 * 561 * Internal routine used by IopAttachFilterDrivers. 562 */ 563 NTSTATUS 564 NTAPI 565 IopAttachFilterDriversCallback( 566 PWSTR ValueName, 567 ULONG ValueType, 568 PVOID ValueData, 569 ULONG ValueLength, 570 PVOID Context, 571 PVOID EntryContext) 572 { 573 PDEVICE_NODE DeviceNode = Context; 574 UNICODE_STRING ServiceName; 575 PWCHAR Filters; 576 PLDR_DATA_TABLE_ENTRY ModuleObject; 577 PDRIVER_OBJECT DriverObject; 578 NTSTATUS Status; 579 580 /* No filter value present */ 581 if (ValueType == REG_NONE) 582 return STATUS_SUCCESS; 583 584 for (Filters = ValueData; 585 ((ULONG_PTR)Filters - (ULONG_PTR)ValueData) < ValueLength && 586 *Filters != 0; 587 Filters += (ServiceName.Length / sizeof(WCHAR)) + 1) 588 { 589 DPRINT("Filter Driver: %S (%wZ)\n", Filters, &DeviceNode->InstancePath); 590 591 ServiceName.Buffer = Filters; 592 ServiceName.MaximumLength = 593 ServiceName.Length = (USHORT)wcslen(Filters) * sizeof(WCHAR); 594 595 KeEnterCriticalRegion(); 596 ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE); 597 Status = IopGetDriverObject(&DriverObject, 598 &ServiceName, 599 FALSE); 600 if (!NT_SUCCESS(Status)) 601 { 602 /* Load and initialize the filter driver */ 603 Status = IopLoadServiceModule(&ServiceName, &ModuleObject); 604 if (!NT_SUCCESS(Status)) 605 { 606 ExReleaseResourceLite(&IopDriverLoadResource); 607 KeLeaveCriticalRegion(); 608 return Status; 609 } 610 611 Status = IopInitializeDriverModule(DeviceNode, 612 ModuleObject, 613 &ServiceName, 614 FALSE, 615 &DriverObject); 616 if (!NT_SUCCESS(Status)) 617 { 618 ExReleaseResourceLite(&IopDriverLoadResource); 619 KeLeaveCriticalRegion(); 620 return Status; 621 } 622 } 623 624 ExReleaseResourceLite(&IopDriverLoadResource); 625 KeLeaveCriticalRegion(); 626 627 Status = IopInitializeDevice(DeviceNode, DriverObject); 628 629 /* Remove extra reference */ 630 ObDereferenceObject(DriverObject); 631 632 if (!NT_SUCCESS(Status)) 633 return Status; 634 } 635 636 return STATUS_SUCCESS; 637 } 638 639 /* 640 * IopAttachFilterDrivers 641 * 642 * Load filter drivers for specified device node. 643 * 644 * Parameters 645 * Lower 646 * Set to TRUE for loading lower level filters or FALSE for upper 647 * level filters. 648 */ 649 NTSTATUS 650 FASTCALL 651 IopAttachFilterDrivers( 652 PDEVICE_NODE DeviceNode, 653 HANDLE EnumSubKey, 654 HANDLE ClassKey, 655 BOOLEAN Lower) 656 { 657 RTL_QUERY_REGISTRY_TABLE QueryTable[2] = { { NULL, 0, NULL, NULL, 0, NULL, 0 }, }; 658 NTSTATUS Status; 659 660 /* 661 * First load the device filters 662 */ 663 QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback; 664 if (Lower) 665 QueryTable[0].Name = L"LowerFilters"; 666 else 667 QueryTable[0].Name = L"UpperFilters"; 668 QueryTable[0].Flags = 0; 669 QueryTable[0].DefaultType = REG_NONE; 670 671 Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, 672 (PWSTR)EnumSubKey, 673 QueryTable, 674 DeviceNode, 675 NULL); 676 if (!NT_SUCCESS(Status)) 677 { 678 DPRINT1("Failed to load device %s filters: %08X\n", 679 Lower ? "lower" : "upper", Status); 680 return Status; 681 } 682 683 QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback; 684 if (Lower) 685 QueryTable[0].Name = L"LowerFilters"; 686 else 687 QueryTable[0].Name = L"UpperFilters"; 688 QueryTable[0].EntryContext = NULL; 689 QueryTable[0].Flags = 0; 690 QueryTable[0].DefaultType = REG_NONE; 691 692 if (ClassKey == NULL) 693 { 694 return STATUS_SUCCESS; 695 } 696 697 Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, 698 (PWSTR)ClassKey, 699 QueryTable, 700 DeviceNode, 701 NULL); 702 703 if (!NT_SUCCESS(Status)) 704 { 705 DPRINT1("Failed to load class %s filters: %08X\n", 706 Lower ? "lower" : "upper", Status); 707 return Status; 708 } 709 710 return STATUS_SUCCESS; 711 } 712 713 NTSTATUS 714 NTAPI 715 MiResolveImageReferences(IN PVOID ImageBase, 716 IN PUNICODE_STRING ImageFileDirectory, 717 IN PUNICODE_STRING NamePrefix OPTIONAL, 718 OUT PCHAR *MissingApi, 719 OUT PWCHAR *MissingDriver, 720 OUT PLOAD_IMPORTS *LoadImports); 721 722 // 723 // Used for images already loaded (boot drivers) 724 // 725 INIT_FUNCTION 726 NTSTATUS 727 NTAPI 728 LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry, 729 PUNICODE_STRING FileName, 730 PLDR_DATA_TABLE_ENTRY *ModuleObject) 731 { 732 NTSTATUS Status; 733 UNICODE_STRING BaseName, BaseDirectory; 734 PLOAD_IMPORTS LoadedImports = (PVOID)-2; 735 PCHAR MissingApiName, Buffer; 736 PWCHAR MissingDriverName; 737 PVOID DriverBase = LdrEntry->DllBase; 738 739 /* Allocate a buffer we'll use for names */ 740 Buffer = ExAllocatePoolWithTag(NonPagedPool, 741 MAXIMUM_FILENAME_LENGTH, 742 TAG_LDR_WSTR); 743 if (!Buffer) 744 { 745 /* Fail */ 746 return STATUS_INSUFFICIENT_RESOURCES; 747 } 748 749 /* Check for a separator */ 750 if (FileName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR) 751 { 752 PWCHAR p; 753 ULONG BaseLength; 754 755 /* Loop the path until we get to the base name */ 756 p = &FileName->Buffer[FileName->Length / sizeof(WCHAR)]; 757 while (*(p - 1) != OBJ_NAME_PATH_SEPARATOR) p--; 758 759 /* Get the length */ 760 BaseLength = (ULONG)(&FileName->Buffer[FileName->Length / sizeof(WCHAR)] - p); 761 BaseLength *= sizeof(WCHAR); 762 763 /* Setup the string */ 764 BaseName.Length = (USHORT)BaseLength; 765 BaseName.Buffer = p; 766 } 767 else 768 { 769 /* Otherwise, we already have a base name */ 770 BaseName.Length = FileName->Length; 771 BaseName.Buffer = FileName->Buffer; 772 } 773 774 /* Setup the maximum length */ 775 BaseName.MaximumLength = BaseName.Length; 776 777 /* Now compute the base directory */ 778 BaseDirectory = *FileName; 779 BaseDirectory.Length -= BaseName.Length; 780 BaseDirectory.MaximumLength = BaseDirectory.Length; 781 782 /* Resolve imports */ 783 MissingApiName = Buffer; 784 Status = MiResolveImageReferences(DriverBase, 785 &BaseDirectory, 786 NULL, 787 &MissingApiName, 788 &MissingDriverName, 789 &LoadedImports); 790 791 /* Free the temporary buffer */ 792 ExFreePoolWithTag(Buffer, TAG_LDR_WSTR); 793 794 /* Check the result of the imports resolution */ 795 if (!NT_SUCCESS(Status)) return Status; 796 797 /* Return */ 798 *ModuleObject = LdrEntry; 799 return STATUS_SUCCESS; 800 } 801 802 /* 803 * IopInitializeBuiltinDriver 804 * 805 * Initialize a driver that is already loaded in memory. 806 */ 807 INIT_FUNCTION 808 NTSTATUS 809 NTAPI 810 IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY BootLdrEntry) 811 { 812 PDEVICE_NODE DeviceNode; 813 PDRIVER_OBJECT DriverObject; 814 NTSTATUS Status; 815 PWCHAR Buffer, FileNameWithoutPath; 816 PWSTR FileExtension; 817 PUNICODE_STRING ModuleName = &BootLdrEntry->BaseDllName; 818 PLDR_DATA_TABLE_ENTRY LdrEntry; 819 PLIST_ENTRY NextEntry; 820 UNICODE_STRING ServiceName; 821 BOOLEAN Success; 822 823 /* 824 * Display 'Loading XXX...' message 825 */ 826 IopDisplayLoadingMessage(ModuleName); 827 InbvIndicateProgress(); 828 829 Buffer = ExAllocatePoolWithTag(PagedPool, 830 ModuleName->Length + sizeof(UNICODE_NULL), 831 TAG_IO); 832 if (Buffer == NULL) 833 { 834 return STATUS_INSUFFICIENT_RESOURCES; 835 } 836 837 RtlCopyMemory(Buffer, ModuleName->Buffer, ModuleName->Length); 838 Buffer[ModuleName->Length / sizeof(WCHAR)] = UNICODE_NULL; 839 840 /* 841 * Generate filename without path (not needed by freeldr) 842 */ 843 FileNameWithoutPath = wcsrchr(Buffer, L'\\'); 844 if (FileNameWithoutPath == NULL) 845 { 846 FileNameWithoutPath = Buffer; 847 } 848 else 849 { 850 FileNameWithoutPath++; 851 } 852 853 /* 854 * Strip the file extension from ServiceName 855 */ 856 Success = RtlCreateUnicodeString(&ServiceName, FileNameWithoutPath); 857 ExFreePoolWithTag(Buffer, TAG_IO); 858 if (!Success) 859 { 860 return STATUS_INSUFFICIENT_RESOURCES; 861 } 862 863 FileExtension = wcsrchr(ServiceName.Buffer, L'.'); 864 if (FileExtension != NULL) 865 { 866 ServiceName.Length -= (USHORT)wcslen(FileExtension) * sizeof(WCHAR); 867 FileExtension[0] = UNICODE_NULL; 868 } 869 870 /* 871 * Determine the right device object 872 */ 873 /* Use IopRootDeviceNode for now */ 874 Status = IopCreateDeviceNode(IopRootDeviceNode, 875 NULL, 876 &ServiceName, 877 &DeviceNode); 878 RtlFreeUnicodeString(&ServiceName); 879 if (!NT_SUCCESS(Status)) 880 { 881 DPRINT1("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status); 882 return Status; 883 } 884 885 /* Lookup the new Ldr entry in PsLoadedModuleList */ 886 NextEntry = PsLoadedModuleList.Flink; 887 while (NextEntry != &PsLoadedModuleList) 888 { 889 LdrEntry = CONTAINING_RECORD(NextEntry, 890 LDR_DATA_TABLE_ENTRY, 891 InLoadOrderLinks); 892 if (RtlEqualUnicodeString(ModuleName, &LdrEntry->BaseDllName, TRUE)) 893 { 894 break; 895 } 896 897 NextEntry = NextEntry->Flink; 898 } 899 ASSERT(NextEntry != &PsLoadedModuleList); 900 901 /* 902 * Initialize the driver 903 */ 904 Status = IopInitializeDriverModule(DeviceNode, 905 LdrEntry, 906 &DeviceNode->ServiceName, 907 FALSE, 908 &DriverObject); 909 910 if (!NT_SUCCESS(Status)) 911 { 912 return Status; 913 } 914 915 Status = IopInitializeDevice(DeviceNode, DriverObject); 916 if (NT_SUCCESS(Status)) 917 { 918 Status = IopStartDevice(DeviceNode); 919 } 920 921 /* Remove extra reference from IopInitializeDriverModule */ 922 ObDereferenceObject(DriverObject); 923 924 return Status; 925 } 926 927 /* 928 * IopInitializeBootDrivers 929 * 930 * Initialize boot drivers and free memory for boot files. 931 * 932 * Parameters 933 * None 934 * 935 * Return Value 936 * None 937 */ 938 INIT_FUNCTION 939 VOID 940 FASTCALL 941 IopInitializeBootDrivers(VOID) 942 { 943 PLIST_ENTRY ListHead, NextEntry, NextEntry2; 944 PLDR_DATA_TABLE_ENTRY LdrEntry; 945 PDEVICE_NODE DeviceNode; 946 PDRIVER_OBJECT DriverObject; 947 LDR_DATA_TABLE_ENTRY ModuleObject; 948 NTSTATUS Status; 949 UNICODE_STRING DriverName; 950 ULONG i, Index; 951 PDRIVER_INFORMATION DriverInfo, DriverInfoTag; 952 HANDLE KeyHandle; 953 PBOOT_DRIVER_LIST_ENTRY BootEntry; 954 DPRINT("IopInitializeBootDrivers()\n"); 955 956 /* Use IopRootDeviceNode for now */ 957 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, NULL, &DeviceNode); 958 if (!NT_SUCCESS(Status)) return; 959 960 /* Setup the module object for the RAW FS Driver */ 961 ModuleObject.DllBase = NULL; 962 ModuleObject.SizeOfImage = 0; 963 ModuleObject.EntryPoint = RawFsDriverEntry; 964 RtlInitUnicodeString(&DriverName, L"RAW"); 965 966 /* Initialize it */ 967 Status = IopInitializeDriverModule(DeviceNode, 968 &ModuleObject, 969 &DriverName, 970 TRUE, 971 &DriverObject); 972 if (!NT_SUCCESS(Status)) 973 { 974 /* Fail */ 975 return; 976 } 977 978 /* Now initialize the associated device */ 979 Status = IopInitializeDevice(DeviceNode, DriverObject); 980 if (!NT_SUCCESS(Status)) 981 { 982 /* Fail */ 983 ObDereferenceObject(DriverObject); 984 return; 985 } 986 987 /* Start it up */ 988 Status = IopStartDevice(DeviceNode); 989 if (!NT_SUCCESS(Status)) 990 { 991 /* Fail */ 992 ObDereferenceObject(DriverObject); 993 return; 994 } 995 996 /* Get highest group order index */ 997 IopGroupIndex = PpInitGetGroupOrderIndex(NULL); 998 if (IopGroupIndex == 0xFFFF) ASSERT(FALSE); 999 1000 /* Allocate the group table */ 1001 IopGroupTable = ExAllocatePoolWithTag(PagedPool, 1002 IopGroupIndex * sizeof(LIST_ENTRY), 1003 TAG_IO); 1004 if (IopGroupTable == NULL) ASSERT(FALSE); 1005 1006 /* Initialize the group table lists */ 1007 for (i = 0; i < IopGroupIndex; i++) InitializeListHead(&IopGroupTable[i]); 1008 1009 /* Loop the boot modules */ 1010 ListHead = &KeLoaderBlock->LoadOrderListHead; 1011 NextEntry = ListHead->Flink; 1012 while (ListHead != NextEntry) 1013 { 1014 /* Get the entry */ 1015 LdrEntry = CONTAINING_RECORD(NextEntry, 1016 LDR_DATA_TABLE_ENTRY, 1017 InLoadOrderLinks); 1018 1019 /* Check if the DLL needs to be initialized */ 1020 if (LdrEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL) 1021 { 1022 /* Call its entrypoint */ 1023 MmCallDllInitialize(LdrEntry, NULL); 1024 } 1025 1026 /* Go to the next driver */ 1027 NextEntry = NextEntry->Flink; 1028 } 1029 1030 /* Loop the boot drivers */ 1031 ListHead = &KeLoaderBlock->BootDriverListHead; 1032 NextEntry = ListHead->Flink; 1033 while (ListHead != NextEntry) 1034 { 1035 /* Get the entry */ 1036 BootEntry = CONTAINING_RECORD(NextEntry, 1037 BOOT_DRIVER_LIST_ENTRY, 1038 Link); 1039 1040 /* Get the driver loader entry */ 1041 LdrEntry = BootEntry->LdrEntry; 1042 1043 /* Allocate our internal accounting structure */ 1044 DriverInfo = ExAllocatePoolWithTag(PagedPool, 1045 sizeof(DRIVER_INFORMATION), 1046 TAG_IO); 1047 if (DriverInfo) 1048 { 1049 /* Zero it and initialize it */ 1050 RtlZeroMemory(DriverInfo, sizeof(DRIVER_INFORMATION)); 1051 InitializeListHead(&DriverInfo->Link); 1052 DriverInfo->DataTableEntry = BootEntry; 1053 1054 /* Open the registry key */ 1055 Status = IopOpenRegistryKeyEx(&KeyHandle, 1056 NULL, 1057 &BootEntry->RegistryPath, 1058 KEY_READ); 1059 DPRINT("IopOpenRegistryKeyEx(%wZ) returned 0x%08lx\n", &BootEntry->RegistryPath, Status); 1060 #if 0 1061 if (NT_SUCCESS(Status)) 1062 #else // Hack still needed... 1063 if ((NT_SUCCESS(Status)) || /* ReactOS HACK for SETUPLDR */ 1064 ((KeLoaderBlock->SetupLdrBlock) && ((KeyHandle = (PVOID)1)))) // yes, it's an assignment! 1065 #endif 1066 { 1067 /* Save the handle */ 1068 DriverInfo->ServiceHandle = KeyHandle; 1069 1070 /* Get the group oder index */ 1071 Index = PpInitGetGroupOrderIndex(KeyHandle); 1072 1073 /* Get the tag position */ 1074 DriverInfo->TagPosition = PipGetDriverTagPriority(KeyHandle); 1075 1076 /* Insert it into the list, at the right place */ 1077 ASSERT(Index < IopGroupIndex); 1078 NextEntry2 = IopGroupTable[Index].Flink; 1079 while (NextEntry2 != &IopGroupTable[Index]) 1080 { 1081 /* Get the driver info */ 1082 DriverInfoTag = CONTAINING_RECORD(NextEntry2, 1083 DRIVER_INFORMATION, 1084 Link); 1085 1086 /* Check if we found the right tag position */ 1087 if (DriverInfoTag->TagPosition > DriverInfo->TagPosition) 1088 { 1089 /* We're done */ 1090 break; 1091 } 1092 1093 /* Next entry */ 1094 NextEntry2 = NextEntry2->Flink; 1095 } 1096 1097 /* Insert us right before the next entry */ 1098 NextEntry2 = NextEntry2->Blink; 1099 InsertHeadList(NextEntry2, &DriverInfo->Link); 1100 } 1101 } 1102 1103 /* Go to the next driver */ 1104 NextEntry = NextEntry->Flink; 1105 } 1106 1107 /* Loop each group index */ 1108 for (i = 0; i < IopGroupIndex; i++) 1109 { 1110 /* Loop each group table */ 1111 NextEntry = IopGroupTable[i].Flink; 1112 while (NextEntry != &IopGroupTable[i]) 1113 { 1114 /* Get the entry */ 1115 DriverInfo = CONTAINING_RECORD(NextEntry, 1116 DRIVER_INFORMATION, 1117 Link); 1118 1119 /* Get the driver loader entry */ 1120 LdrEntry = DriverInfo->DataTableEntry->LdrEntry; 1121 1122 /* Initialize it */ 1123 IopInitializeBuiltinDriver(LdrEntry); 1124 1125 /* Next entry */ 1126 NextEntry = NextEntry->Flink; 1127 } 1128 } 1129 1130 /* HAL Root Bus is being initialized before loading the boot drivers so this may cause issues 1131 * when some devices are not being initialized with their drivers. This flag is used to delay 1132 * all actions with devices (except PnP root device) until boot drivers are loaded. 1133 * See PiQueueDeviceAction function 1134 */ 1135 PnPBootDriversLoaded = TRUE; 1136 } 1137 1138 INIT_FUNCTION 1139 VOID 1140 FASTCALL 1141 IopInitializeSystemDrivers(VOID) 1142 { 1143 PUNICODE_STRING *DriverList, *SavedList; 1144 1145 /* No system drivers on the boot cd */ 1146 if (KeLoaderBlock->SetupLdrBlock) return; // ExpInTextModeSetup 1147 1148 /* Get the driver list */ 1149 SavedList = DriverList = CmGetSystemDriverList(); 1150 ASSERT(DriverList); 1151 1152 /* Loop it */ 1153 while (*DriverList) 1154 { 1155 /* Load the driver */ 1156 ZwLoadDriver(*DriverList); 1157 1158 /* Free the entry */ 1159 RtlFreeUnicodeString(*DriverList); 1160 ExFreePool(*DriverList); 1161 1162 /* Next entry */ 1163 InbvIndicateProgress(); 1164 DriverList++; 1165 } 1166 1167 /* Free the list */ 1168 ExFreePool(SavedList); 1169 } 1170 1171 /* 1172 * IopUnloadDriver 1173 * 1174 * Unloads a device driver. 1175 * 1176 * Parameters 1177 * DriverServiceName 1178 * Name of the service to unload (registry key). 1179 * 1180 * UnloadPnpDrivers 1181 * Whether to unload Plug & Plug or only legacy drivers. If this 1182 * parameter is set to FALSE, the routine will unload only legacy 1183 * drivers. 1184 * 1185 * Return Value 1186 * Status 1187 * 1188 * To do 1189 * Guard the whole function by SEH. 1190 */ 1191 1192 NTSTATUS NTAPI 1193 IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers) 1194 { 1195 UNICODE_STRING Backslash = RTL_CONSTANT_STRING(L"\\"); 1196 RTL_QUERY_REGISTRY_TABLE QueryTable[2]; 1197 UNICODE_STRING ImagePath; 1198 UNICODE_STRING ServiceName; 1199 UNICODE_STRING ObjectName; 1200 PDRIVER_OBJECT DriverObject; 1201 PDEVICE_OBJECT DeviceObject; 1202 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; 1203 NTSTATUS Status; 1204 USHORT LastBackslash; 1205 BOOLEAN SafeToUnload = TRUE; 1206 KPROCESSOR_MODE PreviousMode; 1207 UNICODE_STRING CapturedServiceName; 1208 1209 PAGED_CODE(); 1210 1211 PreviousMode = ExGetPreviousMode(); 1212 1213 /* Need the appropriate priviliege */ 1214 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode)) 1215 { 1216 DPRINT1("No unload privilege!\n"); 1217 return STATUS_PRIVILEGE_NOT_HELD; 1218 } 1219 1220 /* Capture the service name */ 1221 Status = ProbeAndCaptureUnicodeString(&CapturedServiceName, PreviousMode, DriverServiceName); 1222 if (!NT_SUCCESS(Status)) 1223 { 1224 return Status; 1225 } 1226 1227 DPRINT("IopUnloadDriver('%wZ', %u)\n", &CapturedServiceName, UnloadPnpDrivers); 1228 1229 1230 /* We need a service name */ 1231 if (CapturedServiceName.Length == 0) 1232 { 1233 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1234 return STATUS_INVALID_PARAMETER; 1235 } 1236 1237 /* 1238 * Get the service name from the registry key name 1239 */ 1240 Status = RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END, 1241 &CapturedServiceName, 1242 &Backslash, 1243 &LastBackslash); 1244 if (NT_SUCCESS(Status)) 1245 { 1246 NT_ASSERT(CapturedServiceName.Length >= LastBackslash + sizeof(WCHAR)); 1247 ServiceName.Buffer = &CapturedServiceName.Buffer[LastBackslash / sizeof(WCHAR) + 1]; 1248 ServiceName.Length = CapturedServiceName.Length - LastBackslash - sizeof(WCHAR); 1249 ServiceName.MaximumLength = CapturedServiceName.MaximumLength - LastBackslash - sizeof(WCHAR); 1250 } 1251 else 1252 { 1253 ServiceName = CapturedServiceName; 1254 } 1255 1256 /* 1257 * Construct the driver object name 1258 */ 1259 Status = RtlUShortAdd(sizeof(DRIVER_ROOT_NAME), 1260 ServiceName.Length, 1261 &ObjectName.MaximumLength); 1262 if (!NT_SUCCESS(Status)) 1263 { 1264 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1265 return Status; 1266 } 1267 ObjectName.Length = 0; 1268 ObjectName.Buffer = ExAllocatePoolWithTag(PagedPool, 1269 ObjectName.MaximumLength, 1270 TAG_IO); 1271 if (!ObjectName.Buffer) 1272 { 1273 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1274 return STATUS_INSUFFICIENT_RESOURCES; 1275 } 1276 NT_VERIFY(NT_SUCCESS(RtlAppendUnicodeToString(&ObjectName, DRIVER_ROOT_NAME))); 1277 NT_VERIFY(NT_SUCCESS(RtlAppendUnicodeStringToString(&ObjectName, &ServiceName))); 1278 1279 /* 1280 * Find the driver object 1281 */ 1282 Status = ObReferenceObjectByName(&ObjectName, 1283 0, 1284 0, 1285 0, 1286 IoDriverObjectType, 1287 KernelMode, 1288 0, 1289 (PVOID*)&DriverObject); 1290 1291 if (!NT_SUCCESS(Status)) 1292 { 1293 DPRINT1("Can't locate driver object for %wZ\n", &ObjectName); 1294 ExFreePoolWithTag(ObjectName.Buffer, TAG_IO); 1295 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1296 return Status; 1297 } 1298 1299 /* Free the buffer for driver object name */ 1300 ExFreePoolWithTag(ObjectName.Buffer, TAG_IO); 1301 1302 /* Check that driver is not already unloading */ 1303 if (DriverObject->Flags & DRVO_UNLOAD_INVOKED) 1304 { 1305 DPRINT1("Driver deletion pending\n"); 1306 ObDereferenceObject(DriverObject); 1307 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1308 return STATUS_DELETE_PENDING; 1309 } 1310 1311 /* 1312 * Get path of service... 1313 */ 1314 RtlZeroMemory(QueryTable, sizeof(QueryTable)); 1315 1316 RtlInitUnicodeString(&ImagePath, NULL); 1317 1318 QueryTable[0].Name = L"ImagePath"; 1319 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; 1320 QueryTable[0].EntryContext = &ImagePath; 1321 1322 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, 1323 CapturedServiceName.Buffer, 1324 QueryTable, 1325 NULL, 1326 NULL); 1327 1328 /* We no longer need service name */ 1329 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1330 1331 if (!NT_SUCCESS(Status)) 1332 { 1333 DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status); 1334 ObDereferenceObject(DriverObject); 1335 return Status; 1336 } 1337 1338 /* 1339 * Normalize the image path for all later processing. 1340 */ 1341 Status = IopNormalizeImagePath(&ImagePath, &ServiceName); 1342 1343 if (!NT_SUCCESS(Status)) 1344 { 1345 DPRINT1("IopNormalizeImagePath() failed (Status %x)\n", Status); 1346 ObDereferenceObject(DriverObject); 1347 return Status; 1348 } 1349 1350 /* Free the service path */ 1351 ExFreePool(ImagePath.Buffer); 1352 1353 /* 1354 * Unload the module and release the references to the device object 1355 */ 1356 1357 /* Call the load/unload routine, depending on current process */ 1358 if (DriverObject->DriverUnload && DriverObject->DriverSection && 1359 (UnloadPnpDrivers || (DriverObject->Flags & DRVO_LEGACY_DRIVER))) 1360 { 1361 /* Loop through each device object of the driver 1362 and set DOE_UNLOAD_PENDING flag */ 1363 DeviceObject = DriverObject->DeviceObject; 1364 while (DeviceObject) 1365 { 1366 /* Set the unload pending flag for the device */ 1367 DeviceExtension = IoGetDevObjExtension(DeviceObject); 1368 DeviceExtension->ExtensionFlags |= DOE_UNLOAD_PENDING; 1369 1370 /* Make sure there are no attached devices or no reference counts */ 1371 if ((DeviceObject->ReferenceCount) || (DeviceObject->AttachedDevice)) 1372 { 1373 /* Not safe to unload */ 1374 DPRINT1("Drivers device object is referenced or has attached devices\n"); 1375 1376 SafeToUnload = FALSE; 1377 } 1378 1379 DeviceObject = DeviceObject->NextDevice; 1380 } 1381 1382 /* If not safe to unload, then return success */ 1383 if (!SafeToUnload) 1384 { 1385 ObDereferenceObject(DriverObject); 1386 return STATUS_SUCCESS; 1387 } 1388 1389 DPRINT1("Unloading driver '%wZ' (manual)\n", &DriverObject->DriverName); 1390 1391 /* Set the unload invoked flag and call the unload routine */ 1392 DriverObject->Flags |= DRVO_UNLOAD_INVOKED; 1393 Status = IopLoadUnloadDriver(NULL, &DriverObject); 1394 ASSERT(Status == STATUS_SUCCESS); 1395 1396 /* Mark the driver object temporary, so it could be deleted later */ 1397 ObMakeTemporaryObject(DriverObject); 1398 1399 /* Dereference it 2 times */ 1400 ObDereferenceObject(DriverObject); 1401 ObDereferenceObject(DriverObject); 1402 1403 return Status; 1404 } 1405 else 1406 { 1407 DPRINT1("No DriverUnload function! '%wZ' will not be unloaded!\n", &DriverObject->DriverName); 1408 1409 /* Dereference one time (refd inside this function) */ 1410 ObDereferenceObject(DriverObject); 1411 1412 /* Return unloading failure */ 1413 return STATUS_INVALID_DEVICE_REQUEST; 1414 } 1415 } 1416 1417 VOID 1418 NTAPI 1419 IopReinitializeDrivers(VOID) 1420 { 1421 PDRIVER_REINIT_ITEM ReinitItem; 1422 PLIST_ENTRY Entry; 1423 1424 /* Get the first entry and start looping */ 1425 Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead, 1426 &DriverReinitListLock); 1427 while (Entry) 1428 { 1429 /* Get the item */ 1430 ReinitItem = CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry); 1431 1432 /* Increment reinitialization counter */ 1433 ReinitItem->DriverObject->DriverExtension->Count++; 1434 1435 /* Remove the device object flag */ 1436 ReinitItem->DriverObject->Flags &= ~DRVO_REINIT_REGISTERED; 1437 1438 /* Call the routine */ 1439 ReinitItem->ReinitRoutine(ReinitItem->DriverObject, 1440 ReinitItem->Context, 1441 ReinitItem->DriverObject-> 1442 DriverExtension->Count); 1443 1444 /* Free the entry */ 1445 ExFreePool(Entry); 1446 1447 /* Move to the next one */ 1448 Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead, 1449 &DriverReinitListLock); 1450 } 1451 } 1452 1453 VOID 1454 NTAPI 1455 IopReinitializeBootDrivers(VOID) 1456 { 1457 PDRIVER_REINIT_ITEM ReinitItem; 1458 PLIST_ENTRY Entry; 1459 1460 /* Get the first entry and start looping */ 1461 Entry = ExInterlockedRemoveHeadList(&DriverBootReinitListHead, 1462 &DriverBootReinitListLock); 1463 while (Entry) 1464 { 1465 /* Get the item */ 1466 ReinitItem = CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry); 1467 1468 /* Increment reinitialization counter */ 1469 ReinitItem->DriverObject->DriverExtension->Count++; 1470 1471 /* Remove the device object flag */ 1472 ReinitItem->DriverObject->Flags &= ~DRVO_BOOTREINIT_REGISTERED; 1473 1474 /* Call the routine */ 1475 ReinitItem->ReinitRoutine(ReinitItem->DriverObject, 1476 ReinitItem->Context, 1477 ReinitItem->DriverObject-> 1478 DriverExtension->Count); 1479 1480 /* Free the entry */ 1481 ExFreePool(Entry); 1482 1483 /* Move to the next one */ 1484 Entry = ExInterlockedRemoveHeadList(&DriverBootReinitListHead, 1485 &DriverBootReinitListLock); 1486 } 1487 1488 /* Wait for all device actions being finished*/ 1489 KeWaitForSingleObject(&PiEnumerationFinished, Executive, KernelMode, FALSE, NULL); 1490 } 1491 1492 NTSTATUS 1493 NTAPI 1494 IopCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL, 1495 IN PDRIVER_INITIALIZE InitializationFunction, 1496 IN PUNICODE_STRING RegistryPath OPTIONAL, 1497 IN PCUNICODE_STRING ServiceName, 1498 IN PLDR_DATA_TABLE_ENTRY ModuleObject OPTIONAL, 1499 OUT PDRIVER_OBJECT *pDriverObject) 1500 { 1501 WCHAR NameBuffer[100]; 1502 USHORT NameLength; 1503 UNICODE_STRING LocalDriverName; 1504 NTSTATUS Status; 1505 OBJECT_ATTRIBUTES ObjectAttributes; 1506 ULONG ObjectSize; 1507 PDRIVER_OBJECT DriverObject; 1508 UNICODE_STRING ServiceKeyName; 1509 HANDLE hDriver; 1510 ULONG i, RetryCount = 0; 1511 1512 try_again: 1513 /* First, create a unique name for the driver if we don't have one */ 1514 if (!DriverName) 1515 { 1516 /* Create a random name and set up the string */ 1517 NameLength = (USHORT)swprintf(NameBuffer, 1518 DRIVER_ROOT_NAME L"%08u", 1519 KeTickCount.LowPart); 1520 LocalDriverName.Length = NameLength * sizeof(WCHAR); 1521 LocalDriverName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL); 1522 LocalDriverName.Buffer = NameBuffer; 1523 } 1524 else 1525 { 1526 /* So we can avoid another code path, use a local var */ 1527 LocalDriverName = *DriverName; 1528 } 1529 1530 /* Initialize the Attributes */ 1531 ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(EXTENDED_DRIVER_EXTENSION); 1532 InitializeObjectAttributes(&ObjectAttributes, 1533 &LocalDriverName, 1534 OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 1535 NULL, 1536 NULL); 1537 1538 /* Create the Object */ 1539 Status = ObCreateObject(KernelMode, 1540 IoDriverObjectType, 1541 &ObjectAttributes, 1542 KernelMode, 1543 NULL, 1544 ObjectSize, 1545 0, 1546 0, 1547 (PVOID*)&DriverObject); 1548 if (!NT_SUCCESS(Status)) return Status; 1549 1550 DPRINT("IopCreateDriver(): created DO %p\n", DriverObject); 1551 1552 /* Set up the Object */ 1553 RtlZeroMemory(DriverObject, ObjectSize); 1554 DriverObject->Type = IO_TYPE_DRIVER; 1555 DriverObject->Size = sizeof(DRIVER_OBJECT); 1556 1557 /* 1558 * Check whether RegistryPath and ModuleObject are both NULL because 1559 * IoCreateDriver() was called to initialize a built-in driver. 1560 */ 1561 if ((RegistryPath != NULL) || (ModuleObject != NULL)) 1562 DriverObject->Flags = DRVO_LEGACY_DRIVER; 1563 else 1564 DriverObject->Flags = DRVO_BUILTIN_DRIVER; 1565 1566 DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1); 1567 DriverObject->DriverExtension->DriverObject = DriverObject; 1568 DriverObject->DriverInit = InitializationFunction; 1569 DriverObject->DriverSection = ModuleObject; 1570 /* Loop all Major Functions */ 1571 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) 1572 { 1573 /* Invalidate each function */ 1574 DriverObject->MajorFunction[i] = IopInvalidDeviceRequest; 1575 } 1576 1577 /* Set up the service key name buffer */ 1578 ServiceKeyName.MaximumLength = ServiceName->Length + sizeof(UNICODE_NULL); 1579 ServiceKeyName.Buffer = ExAllocatePoolWithTag(NonPagedPool, 1580 ServiceKeyName.MaximumLength, 1581 TAG_IO); 1582 if (!ServiceKeyName.Buffer) 1583 { 1584 /* Fail */ 1585 ObMakeTemporaryObject(DriverObject); 1586 ObDereferenceObject(DriverObject); 1587 return STATUS_INSUFFICIENT_RESOURCES; 1588 } 1589 1590 /* Copy the name and set it in the driver extension */ 1591 RtlCopyUnicodeString(&ServiceKeyName, 1592 ServiceName); 1593 DriverObject->DriverExtension->ServiceKeyName = ServiceKeyName; 1594 1595 /* Make a copy of the driver name to store in the driver object */ 1596 DriverObject->DriverName.MaximumLength = LocalDriverName.Length; 1597 DriverObject->DriverName.Buffer = ExAllocatePoolWithTag(PagedPool, 1598 DriverObject->DriverName.MaximumLength, 1599 TAG_IO); 1600 if (!DriverObject->DriverName.Buffer) 1601 { 1602 /* Fail */ 1603 ObMakeTemporaryObject(DriverObject); 1604 ObDereferenceObject(DriverObject); 1605 return STATUS_INSUFFICIENT_RESOURCES; 1606 } 1607 1608 RtlCopyUnicodeString(&DriverObject->DriverName, 1609 &LocalDriverName); 1610 1611 /* Add the Object and get its handle */ 1612 Status = ObInsertObject(DriverObject, 1613 NULL, 1614 FILE_READ_DATA, 1615 0, 1616 NULL, 1617 &hDriver); 1618 1619 /* Eliminate small possibility when this function is called more than 1620 once in a row, and KeTickCount doesn't get enough time to change */ 1621 if (!DriverName && (Status == STATUS_OBJECT_NAME_COLLISION) && (RetryCount < 100)) 1622 { 1623 RetryCount++; 1624 goto try_again; 1625 } 1626 1627 if (!NT_SUCCESS(Status)) return Status; 1628 1629 /* Now reference it */ 1630 Status = ObReferenceObjectByHandle(hDriver, 1631 0, 1632 IoDriverObjectType, 1633 KernelMode, 1634 (PVOID*)&DriverObject, 1635 NULL); 1636 1637 /* Close the extra handle */ 1638 ZwClose(hDriver); 1639 1640 if (!NT_SUCCESS(Status)) 1641 { 1642 /* Fail */ 1643 ObMakeTemporaryObject(DriverObject); 1644 ObDereferenceObject(DriverObject); 1645 return Status; 1646 } 1647 1648 DriverObject->HardwareDatabase = &IopHardwareDatabaseKey; 1649 DriverObject->DriverStart = ModuleObject ? ModuleObject->DllBase : 0; 1650 DriverObject->DriverSize = ModuleObject ? ModuleObject->SizeOfImage : 0; 1651 1652 /* Finally, call its init function */ 1653 DPRINT("RegistryKey: %wZ\n", RegistryPath); 1654 DPRINT("Calling driver entrypoint at %p\n", InitializationFunction); 1655 Status = (*InitializationFunction)(DriverObject, RegistryPath); 1656 if (!NT_SUCCESS(Status)) 1657 { 1658 /* If it didn't work, then kill the object */ 1659 DPRINT1("'%wZ' initialization failed, status (0x%08lx)\n", DriverName, Status); 1660 DriverObject->DriverSection = NULL; 1661 ObMakeTemporaryObject(DriverObject); 1662 ObDereferenceObject(DriverObject); 1663 return Status; 1664 } 1665 else 1666 { 1667 /* Returns to caller the object */ 1668 *pDriverObject = DriverObject; 1669 } 1670 1671 /* We're going to say if we don't have any DOs from DriverEntry, then we're not legacy. 1672 * Other parts of the I/O manager depend on this behavior */ 1673 if (!DriverObject->DeviceObject) DriverObject->Flags &= ~DRVO_LEGACY_DRIVER; 1674 1675 /* Loop all Major Functions */ 1676 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) 1677 { 1678 /* 1679 * Make sure the driver didn't set any dispatch entry point to NULL! 1680 * Doing so is illegal; drivers shouldn't touch entry points they 1681 * do not implement. 1682 */ 1683 1684 /* Check if it did so anyway */ 1685 if (!DriverObject->MajorFunction[i]) 1686 { 1687 /* Print a warning in the debug log */ 1688 DPRINT1("Driver <%wZ> set DriverObject->MajorFunction[%lu] to NULL!\n", 1689 &DriverObject->DriverName, i); 1690 1691 /* Fix it up */ 1692 DriverObject->MajorFunction[i] = IopInvalidDeviceRequest; 1693 } 1694 } 1695 1696 /* Return the Status */ 1697 return Status; 1698 } 1699 1700 /* PUBLIC FUNCTIONS ***********************************************************/ 1701 1702 /* 1703 * @implemented 1704 */ 1705 NTSTATUS 1706 NTAPI 1707 IoCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL, 1708 IN PDRIVER_INITIALIZE InitializationFunction) 1709 { 1710 PDRIVER_OBJECT DriverObject; 1711 return IopCreateDriver(DriverName, InitializationFunction, NULL, DriverName, NULL, &DriverObject); 1712 } 1713 1714 /* 1715 * @implemented 1716 */ 1717 VOID 1718 NTAPI 1719 IoDeleteDriver(IN PDRIVER_OBJECT DriverObject) 1720 { 1721 /* Simply dereference the Object */ 1722 ObDereferenceObject(DriverObject); 1723 } 1724 1725 /* 1726 * @implemented 1727 */ 1728 VOID 1729 NTAPI 1730 IoRegisterBootDriverReinitialization(IN PDRIVER_OBJECT DriverObject, 1731 IN PDRIVER_REINITIALIZE ReinitRoutine, 1732 IN PVOID Context) 1733 { 1734 PDRIVER_REINIT_ITEM ReinitItem; 1735 1736 /* Allocate the entry */ 1737 ReinitItem = ExAllocatePoolWithTag(NonPagedPool, 1738 sizeof(DRIVER_REINIT_ITEM), 1739 TAG_REINIT); 1740 if (!ReinitItem) return; 1741 1742 /* Fill it out */ 1743 ReinitItem->DriverObject = DriverObject; 1744 ReinitItem->ReinitRoutine = ReinitRoutine; 1745 ReinitItem->Context = Context; 1746 1747 /* Set the Driver Object flag and insert the entry into the list */ 1748 DriverObject->Flags |= DRVO_BOOTREINIT_REGISTERED; 1749 ExInterlockedInsertTailList(&DriverBootReinitListHead, 1750 &ReinitItem->ItemEntry, 1751 &DriverBootReinitListLock); 1752 } 1753 1754 /* 1755 * @implemented 1756 */ 1757 VOID 1758 NTAPI 1759 IoRegisterDriverReinitialization(IN PDRIVER_OBJECT DriverObject, 1760 IN PDRIVER_REINITIALIZE ReinitRoutine, 1761 IN PVOID Context) 1762 { 1763 PDRIVER_REINIT_ITEM ReinitItem; 1764 1765 /* Allocate the entry */ 1766 ReinitItem = ExAllocatePoolWithTag(NonPagedPool, 1767 sizeof(DRIVER_REINIT_ITEM), 1768 TAG_REINIT); 1769 if (!ReinitItem) return; 1770 1771 /* Fill it out */ 1772 ReinitItem->DriverObject = DriverObject; 1773 ReinitItem->ReinitRoutine = ReinitRoutine; 1774 ReinitItem->Context = Context; 1775 1776 /* Set the Driver Object flag and insert the entry into the list */ 1777 DriverObject->Flags |= DRVO_REINIT_REGISTERED; 1778 ExInterlockedInsertTailList(&DriverReinitListHead, 1779 &ReinitItem->ItemEntry, 1780 &DriverReinitListLock); 1781 } 1782 1783 /* 1784 * @implemented 1785 */ 1786 NTSTATUS 1787 NTAPI 1788 IoAllocateDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, 1789 IN PVOID ClientIdentificationAddress, 1790 IN ULONG DriverObjectExtensionSize, 1791 OUT PVOID *DriverObjectExtension) 1792 { 1793 KIRQL OldIrql; 1794 PIO_CLIENT_EXTENSION DriverExtensions, NewDriverExtension; 1795 BOOLEAN Inserted = FALSE; 1796 1797 /* Assume failure */ 1798 *DriverObjectExtension = NULL; 1799 1800 /* Allocate the extension */ 1801 NewDriverExtension = ExAllocatePoolWithTag(NonPagedPool, 1802 sizeof(IO_CLIENT_EXTENSION) + 1803 DriverObjectExtensionSize, 1804 TAG_DRIVER_EXTENSION); 1805 if (!NewDriverExtension) return STATUS_INSUFFICIENT_RESOURCES; 1806 1807 /* Clear the extension for teh caller */ 1808 RtlZeroMemory(NewDriverExtension, 1809 sizeof(IO_CLIENT_EXTENSION) + DriverObjectExtensionSize); 1810 1811 /* Acqure lock */ 1812 OldIrql = KeRaiseIrqlToDpcLevel(); 1813 1814 /* Fill out the extension */ 1815 NewDriverExtension->ClientIdentificationAddress = ClientIdentificationAddress; 1816 1817 /* Loop the current extensions */ 1818 DriverExtensions = IoGetDrvObjExtension(DriverObject)-> 1819 ClientDriverExtension; 1820 while (DriverExtensions) 1821 { 1822 /* Check if the identifier matches */ 1823 if (DriverExtensions->ClientIdentificationAddress == 1824 ClientIdentificationAddress) 1825 { 1826 /* We have a collision, break out */ 1827 break; 1828 } 1829 1830 /* Go to the next one */ 1831 DriverExtensions = DriverExtensions->NextExtension; 1832 } 1833 1834 /* Check if we didn't collide */ 1835 if (!DriverExtensions) 1836 { 1837 /* Link this one in */ 1838 NewDriverExtension->NextExtension = 1839 IoGetDrvObjExtension(DriverObject)->ClientDriverExtension; 1840 IoGetDrvObjExtension(DriverObject)->ClientDriverExtension = 1841 NewDriverExtension; 1842 Inserted = TRUE; 1843 } 1844 1845 /* Release the lock */ 1846 KeLowerIrql(OldIrql); 1847 1848 /* Check if insertion failed */ 1849 if (!Inserted) 1850 { 1851 /* Free the entry and fail */ 1852 ExFreePoolWithTag(NewDriverExtension, TAG_DRIVER_EXTENSION); 1853 return STATUS_OBJECT_NAME_COLLISION; 1854 } 1855 1856 /* Otherwise, return the pointer */ 1857 *DriverObjectExtension = NewDriverExtension + 1; 1858 return STATUS_SUCCESS; 1859 } 1860 1861 /* 1862 * @implemented 1863 */ 1864 PVOID 1865 NTAPI 1866 IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, 1867 IN PVOID ClientIdentificationAddress) 1868 { 1869 KIRQL OldIrql; 1870 PIO_CLIENT_EXTENSION DriverExtensions; 1871 1872 /* Acquire lock */ 1873 OldIrql = KeRaiseIrqlToDpcLevel(); 1874 1875 /* Loop the list until we find the right one */ 1876 DriverExtensions = IoGetDrvObjExtension(DriverObject)->ClientDriverExtension; 1877 while (DriverExtensions) 1878 { 1879 /* Check for a match */ 1880 if (DriverExtensions->ClientIdentificationAddress == 1881 ClientIdentificationAddress) 1882 { 1883 /* Break out */ 1884 break; 1885 } 1886 1887 /* Keep looping */ 1888 DriverExtensions = DriverExtensions->NextExtension; 1889 } 1890 1891 /* Release lock */ 1892 KeLowerIrql(OldIrql); 1893 1894 /* Return nothing or the extension */ 1895 if (!DriverExtensions) return NULL; 1896 return DriverExtensions + 1; 1897 } 1898 1899 VOID 1900 NTAPI 1901 IopLoadUnloadDriverWorker( 1902 _Inout_ PVOID Parameter) 1903 { 1904 PLOAD_UNLOAD_PARAMS LoadParams = Parameter; 1905 1906 ASSERT(PsGetCurrentProcess() == PsInitialSystemProcess); 1907 LoadParams->Status = IopLoadUnloadDriver(LoadParams->RegistryPath, 1908 &LoadParams->DriverObject); 1909 KeSetEvent(&LoadParams->Event, 0, FALSE); 1910 } 1911 1912 NTSTATUS 1913 NTAPI 1914 IopLoadUnloadDriver( 1915 _In_opt_ PCUNICODE_STRING RegistryPath, 1916 _Inout_ PDRIVER_OBJECT *DriverObject) 1917 { 1918 RTL_QUERY_REGISTRY_TABLE QueryTable[3]; 1919 UNICODE_STRING ImagePath; 1920 UNICODE_STRING ServiceName; 1921 NTSTATUS Status; 1922 ULONG Type; 1923 PDEVICE_NODE DeviceNode; 1924 PLDR_DATA_TABLE_ENTRY ModuleObject; 1925 PVOID BaseAddress; 1926 WCHAR *cur; 1927 1928 /* Load/Unload must be called from system process */ 1929 if (PsGetCurrentProcess() != PsInitialSystemProcess) 1930 { 1931 LOAD_UNLOAD_PARAMS LoadParams; 1932 1933 /* Prepare parameters block */ 1934 LoadParams.RegistryPath = RegistryPath; 1935 LoadParams.DriverObject = *DriverObject; 1936 KeInitializeEvent(&LoadParams.Event, NotificationEvent, FALSE); 1937 1938 /* Initialize and queue a work item */ 1939 ExInitializeWorkItem(&LoadParams.WorkItem, 1940 IopLoadUnloadDriverWorker, 1941 &LoadParams); 1942 ExQueueWorkItem(&LoadParams.WorkItem, DelayedWorkQueue); 1943 1944 /* And wait till it completes */ 1945 KeWaitForSingleObject(&LoadParams.Event, 1946 UserRequest, 1947 KernelMode, 1948 FALSE, 1949 NULL); 1950 return LoadParams.Status; 1951 } 1952 1953 /* Check if it's an unload request */ 1954 if (*DriverObject) 1955 { 1956 (*DriverObject)->DriverUnload(*DriverObject); 1957 return STATUS_SUCCESS; 1958 } 1959 1960 RtlInitUnicodeString(&ImagePath, NULL); 1961 1962 /* 1963 * Get the service name from the registry key name. 1964 */ 1965 ASSERT(RegistryPath->Length >= sizeof(WCHAR)); 1966 1967 ServiceName = *RegistryPath; 1968 cur = RegistryPath->Buffer + RegistryPath->Length / sizeof(WCHAR) - 1; 1969 while (RegistryPath->Buffer != cur) 1970 { 1971 if (*cur == L'\\') 1972 { 1973 ServiceName.Buffer = cur + 1; 1974 ServiceName.Length = RegistryPath->Length - 1975 (USHORT)((ULONG_PTR)ServiceName.Buffer - 1976 (ULONG_PTR)RegistryPath->Buffer); 1977 break; 1978 } 1979 cur--; 1980 } 1981 1982 /* 1983 * Get service type. 1984 */ 1985 RtlZeroMemory(&QueryTable, sizeof(QueryTable)); 1986 1987 RtlInitUnicodeString(&ImagePath, NULL); 1988 1989 QueryTable[0].Name = L"Type"; 1990 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; 1991 QueryTable[0].EntryContext = &Type; 1992 1993 QueryTable[1].Name = L"ImagePath"; 1994 QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; 1995 QueryTable[1].EntryContext = &ImagePath; 1996 1997 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, 1998 RegistryPath->Buffer, 1999 QueryTable, NULL, NULL); 2000 if (!NT_SUCCESS(Status)) 2001 { 2002 DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status); 2003 if (ImagePath.Buffer) ExFreePool(ImagePath.Buffer); 2004 return Status; 2005 } 2006 2007 /* 2008 * Normalize the image path for all later processing. 2009 */ 2010 Status = IopNormalizeImagePath(&ImagePath, &ServiceName); 2011 if (!NT_SUCCESS(Status)) 2012 { 2013 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status); 2014 return Status; 2015 } 2016 2017 DPRINT("FullImagePath: '%wZ'\n", &ImagePath); 2018 DPRINT("Type: %lx\n", Type); 2019 2020 KeEnterCriticalRegion(); 2021 ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE); 2022 /* 2023 * Get existing DriverObject pointer (in case the driver 2024 * has already been loaded and initialized). 2025 */ 2026 Status = IopGetDriverObject(DriverObject, 2027 &ServiceName, 2028 (Type == SERVICE_FILE_SYSTEM_DRIVER || 2029 Type == SERVICE_RECOGNIZER_DRIVER)); 2030 2031 if (!NT_SUCCESS(Status)) 2032 { 2033 /* 2034 * Load the driver module 2035 */ 2036 DPRINT("Loading module from %wZ\n", &ImagePath); 2037 Status = MmLoadSystemImage(&ImagePath, NULL, NULL, 0, (PVOID)&ModuleObject, &BaseAddress); 2038 if (!NT_SUCCESS(Status)) 2039 { 2040 DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status); 2041 ExReleaseResourceLite(&IopDriverLoadResource); 2042 KeLeaveCriticalRegion(); 2043 return Status; 2044 } 2045 2046 /* 2047 * Initialize the driver module if it's loaded for the first time 2048 */ 2049 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &ServiceName, &DeviceNode); 2050 if (!NT_SUCCESS(Status)) 2051 { 2052 DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status); 2053 ExReleaseResourceLite(&IopDriverLoadResource); 2054 KeLeaveCriticalRegion(); 2055 MmUnloadSystemImage(ModuleObject); 2056 return Status; 2057 } 2058 2059 IopDisplayLoadingMessage(&DeviceNode->ServiceName); 2060 2061 Status = IopInitializeDriverModule(DeviceNode, 2062 ModuleObject, 2063 &DeviceNode->ServiceName, 2064 (Type == SERVICE_FILE_SYSTEM_DRIVER || 2065 Type == SERVICE_RECOGNIZER_DRIVER), 2066 DriverObject); 2067 if (!NT_SUCCESS(Status)) 2068 { 2069 DPRINT1("IopInitializeDriverModule() failed (Status %lx)\n", Status); 2070 ExReleaseResourceLite(&IopDriverLoadResource); 2071 KeLeaveCriticalRegion(); 2072 MmUnloadSystemImage(ModuleObject); 2073 return Status; 2074 } 2075 2076 ExReleaseResourceLite(&IopDriverLoadResource); 2077 KeLeaveCriticalRegion(); 2078 2079 /* Initialize and start device */ 2080 IopInitializeDevice(DeviceNode, *DriverObject); 2081 Status = IopStartDevice(DeviceNode); 2082 } 2083 else 2084 { 2085 ExReleaseResourceLite(&IopDriverLoadResource); 2086 KeLeaveCriticalRegion(); 2087 2088 DPRINT("DriverObject already exist in ObjectManager\n"); 2089 Status = STATUS_IMAGE_ALREADY_LOADED; 2090 2091 /* IopGetDriverObject references the DriverObject, so dereference it */ 2092 ObDereferenceObject(*DriverObject); 2093 } 2094 2095 return Status; 2096 } 2097 2098 /* 2099 * NtLoadDriver 2100 * 2101 * Loads a device driver. 2102 * 2103 * Parameters 2104 * DriverServiceName 2105 * Name of the service to load (registry key). 2106 * 2107 * Return Value 2108 * Status 2109 * 2110 * Status 2111 * implemented 2112 */ 2113 NTSTATUS NTAPI 2114 NtLoadDriver(IN PUNICODE_STRING DriverServiceName) 2115 { 2116 UNICODE_STRING CapturedDriverServiceName = { 0, 0, NULL }; 2117 KPROCESSOR_MODE PreviousMode; 2118 PDRIVER_OBJECT DriverObject; 2119 NTSTATUS Status; 2120 2121 PAGED_CODE(); 2122 2123 PreviousMode = KeGetPreviousMode(); 2124 2125 /* 2126 * Check security privileges 2127 */ 2128 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode)) 2129 { 2130 DPRINT("Privilege not held\n"); 2131 return STATUS_PRIVILEGE_NOT_HELD; 2132 } 2133 2134 Status = ProbeAndCaptureUnicodeString(&CapturedDriverServiceName, 2135 PreviousMode, 2136 DriverServiceName); 2137 if (!NT_SUCCESS(Status)) 2138 { 2139 return Status; 2140 } 2141 2142 DPRINT("NtLoadDriver('%wZ')\n", &CapturedDriverServiceName); 2143 2144 /* Load driver and call its entry point */ 2145 DriverObject = NULL; 2146 Status = IopLoadUnloadDriver(&CapturedDriverServiceName, &DriverObject); 2147 2148 ReleaseCapturedUnicodeString(&CapturedDriverServiceName, 2149 PreviousMode); 2150 2151 return Status; 2152 } 2153 2154 /* 2155 * NtUnloadDriver 2156 * 2157 * Unloads a legacy device driver. 2158 * 2159 * Parameters 2160 * DriverServiceName 2161 * Name of the service to unload (registry key). 2162 * 2163 * Return Value 2164 * Status 2165 * 2166 * Status 2167 * implemented 2168 */ 2169 2170 NTSTATUS NTAPI 2171 NtUnloadDriver(IN PUNICODE_STRING DriverServiceName) 2172 { 2173 return IopUnloadDriver(DriverServiceName, FALSE); 2174 } 2175 2176 /* EOF */ 2177