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 /* In old ROS, the loader list became empty after this point. Simulate. */ 1138 InitializeListHead(&KeLoaderBlock->LoadOrderListHead); 1139 } 1140 1141 INIT_FUNCTION 1142 VOID 1143 FASTCALL 1144 IopInitializeSystemDrivers(VOID) 1145 { 1146 PUNICODE_STRING *DriverList, *SavedList; 1147 1148 /* No system drivers on the boot cd */ 1149 if (KeLoaderBlock->SetupLdrBlock) return; // ExpInTextModeSetup 1150 1151 /* Get the driver list */ 1152 SavedList = DriverList = CmGetSystemDriverList(); 1153 ASSERT(DriverList); 1154 1155 /* Loop it */ 1156 while (*DriverList) 1157 { 1158 /* Load the driver */ 1159 ZwLoadDriver(*DriverList); 1160 1161 /* Free the entry */ 1162 RtlFreeUnicodeString(*DriverList); 1163 ExFreePool(*DriverList); 1164 1165 /* Next entry */ 1166 InbvIndicateProgress(); 1167 DriverList++; 1168 } 1169 1170 /* Free the list */ 1171 ExFreePool(SavedList); 1172 } 1173 1174 /* 1175 * IopUnloadDriver 1176 * 1177 * Unloads a device driver. 1178 * 1179 * Parameters 1180 * DriverServiceName 1181 * Name of the service to unload (registry key). 1182 * 1183 * UnloadPnpDrivers 1184 * Whether to unload Plug & Plug or only legacy drivers. If this 1185 * parameter is set to FALSE, the routine will unload only legacy 1186 * drivers. 1187 * 1188 * Return Value 1189 * Status 1190 * 1191 * To do 1192 * Guard the whole function by SEH. 1193 */ 1194 1195 NTSTATUS NTAPI 1196 IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers) 1197 { 1198 UNICODE_STRING Backslash = RTL_CONSTANT_STRING(L"\\"); 1199 RTL_QUERY_REGISTRY_TABLE QueryTable[2]; 1200 UNICODE_STRING ImagePath; 1201 UNICODE_STRING ServiceName; 1202 UNICODE_STRING ObjectName; 1203 PDRIVER_OBJECT DriverObject; 1204 PDEVICE_OBJECT DeviceObject; 1205 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; 1206 NTSTATUS Status; 1207 USHORT LastBackslash; 1208 BOOLEAN SafeToUnload = TRUE; 1209 KPROCESSOR_MODE PreviousMode; 1210 UNICODE_STRING CapturedServiceName; 1211 1212 PAGED_CODE(); 1213 1214 PreviousMode = ExGetPreviousMode(); 1215 1216 /* Need the appropriate priviliege */ 1217 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode)) 1218 { 1219 DPRINT1("No unload privilege!\n"); 1220 return STATUS_PRIVILEGE_NOT_HELD; 1221 } 1222 1223 /* Capture the service name */ 1224 Status = ProbeAndCaptureUnicodeString(&CapturedServiceName, PreviousMode, DriverServiceName); 1225 if (!NT_SUCCESS(Status)) 1226 { 1227 return Status; 1228 } 1229 1230 DPRINT("IopUnloadDriver('%wZ', %u)\n", &CapturedServiceName, UnloadPnpDrivers); 1231 1232 1233 /* We need a service name */ 1234 if (CapturedServiceName.Length == 0) 1235 { 1236 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1237 return STATUS_INVALID_PARAMETER; 1238 } 1239 1240 /* 1241 * Get the service name from the registry key name 1242 */ 1243 Status = RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END, 1244 &CapturedServiceName, 1245 &Backslash, 1246 &LastBackslash); 1247 if (NT_SUCCESS(Status)) 1248 { 1249 NT_ASSERT(CapturedServiceName.Length >= LastBackslash + sizeof(WCHAR)); 1250 ServiceName.Buffer = &CapturedServiceName.Buffer[LastBackslash / sizeof(WCHAR) + 1]; 1251 ServiceName.Length = CapturedServiceName.Length - LastBackslash - sizeof(WCHAR); 1252 ServiceName.MaximumLength = CapturedServiceName.MaximumLength - LastBackslash - sizeof(WCHAR); 1253 } 1254 else 1255 { 1256 ServiceName = CapturedServiceName; 1257 } 1258 1259 /* 1260 * Construct the driver object name 1261 */ 1262 Status = RtlUShortAdd(sizeof(DRIVER_ROOT_NAME), 1263 ServiceName.Length, 1264 &ObjectName.MaximumLength); 1265 if (!NT_SUCCESS(Status)) 1266 { 1267 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1268 return Status; 1269 } 1270 ObjectName.Length = 0; 1271 ObjectName.Buffer = ExAllocatePoolWithTag(PagedPool, 1272 ObjectName.MaximumLength, 1273 TAG_IO); 1274 if (!ObjectName.Buffer) 1275 { 1276 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1277 return STATUS_INSUFFICIENT_RESOURCES; 1278 } 1279 NT_VERIFY(NT_SUCCESS(RtlAppendUnicodeToString(&ObjectName, DRIVER_ROOT_NAME))); 1280 NT_VERIFY(NT_SUCCESS(RtlAppendUnicodeStringToString(&ObjectName, &ServiceName))); 1281 1282 /* 1283 * Find the driver object 1284 */ 1285 Status = ObReferenceObjectByName(&ObjectName, 1286 0, 1287 0, 1288 0, 1289 IoDriverObjectType, 1290 KernelMode, 1291 0, 1292 (PVOID*)&DriverObject); 1293 1294 if (!NT_SUCCESS(Status)) 1295 { 1296 DPRINT1("Can't locate driver object for %wZ\n", &ObjectName); 1297 ExFreePoolWithTag(ObjectName.Buffer, TAG_IO); 1298 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1299 return Status; 1300 } 1301 1302 /* Free the buffer for driver object name */ 1303 ExFreePoolWithTag(ObjectName.Buffer, TAG_IO); 1304 1305 /* Check that driver is not already unloading */ 1306 if (DriverObject->Flags & DRVO_UNLOAD_INVOKED) 1307 { 1308 DPRINT1("Driver deletion pending\n"); 1309 ObDereferenceObject(DriverObject); 1310 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1311 return STATUS_DELETE_PENDING; 1312 } 1313 1314 /* 1315 * Get path of service... 1316 */ 1317 RtlZeroMemory(QueryTable, sizeof(QueryTable)); 1318 1319 RtlInitUnicodeString(&ImagePath, NULL); 1320 1321 QueryTable[0].Name = L"ImagePath"; 1322 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; 1323 QueryTable[0].EntryContext = &ImagePath; 1324 1325 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, 1326 CapturedServiceName.Buffer, 1327 QueryTable, 1328 NULL, 1329 NULL); 1330 1331 /* We no longer need service name */ 1332 ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1333 1334 if (!NT_SUCCESS(Status)) 1335 { 1336 DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status); 1337 ObDereferenceObject(DriverObject); 1338 return Status; 1339 } 1340 1341 /* 1342 * Normalize the image path for all later processing. 1343 */ 1344 Status = IopNormalizeImagePath(&ImagePath, &ServiceName); 1345 1346 if (!NT_SUCCESS(Status)) 1347 { 1348 DPRINT1("IopNormalizeImagePath() failed (Status %x)\n", Status); 1349 ObDereferenceObject(DriverObject); 1350 return Status; 1351 } 1352 1353 /* Free the service path */ 1354 ExFreePool(ImagePath.Buffer); 1355 1356 /* 1357 * Unload the module and release the references to the device object 1358 */ 1359 1360 /* Call the load/unload routine, depending on current process */ 1361 if (DriverObject->DriverUnload && DriverObject->DriverSection && 1362 (UnloadPnpDrivers || (DriverObject->Flags & DRVO_LEGACY_DRIVER))) 1363 { 1364 /* Loop through each device object of the driver 1365 and set DOE_UNLOAD_PENDING flag */ 1366 DeviceObject = DriverObject->DeviceObject; 1367 while (DeviceObject) 1368 { 1369 /* Set the unload pending flag for the device */ 1370 DeviceExtension = IoGetDevObjExtension(DeviceObject); 1371 DeviceExtension->ExtensionFlags |= DOE_UNLOAD_PENDING; 1372 1373 /* Make sure there are no attached devices or no reference counts */ 1374 if ((DeviceObject->ReferenceCount) || (DeviceObject->AttachedDevice)) 1375 { 1376 /* Not safe to unload */ 1377 DPRINT1("Drivers device object is referenced or has attached devices\n"); 1378 1379 SafeToUnload = FALSE; 1380 } 1381 1382 DeviceObject = DeviceObject->NextDevice; 1383 } 1384 1385 /* If not safe to unload, then return success */ 1386 if (!SafeToUnload) 1387 { 1388 ObDereferenceObject(DriverObject); 1389 return STATUS_SUCCESS; 1390 } 1391 1392 DPRINT1("Unloading driver '%wZ' (manual)\n", &DriverObject->DriverName); 1393 1394 /* Set the unload invoked flag and call the unload routine */ 1395 DriverObject->Flags |= DRVO_UNLOAD_INVOKED; 1396 Status = IopLoadUnloadDriver(NULL, &DriverObject); 1397 ASSERT(Status == STATUS_SUCCESS); 1398 1399 /* Mark the driver object temporary, so it could be deleted later */ 1400 ObMakeTemporaryObject(DriverObject); 1401 1402 /* Dereference it 2 times */ 1403 ObDereferenceObject(DriverObject); 1404 ObDereferenceObject(DriverObject); 1405 1406 return Status; 1407 } 1408 else 1409 { 1410 DPRINT1("No DriverUnload function! '%wZ' will not be unloaded!\n", &DriverObject->DriverName); 1411 1412 /* Dereference one time (refd inside this function) */ 1413 ObDereferenceObject(DriverObject); 1414 1415 /* Return unloading failure */ 1416 return STATUS_INVALID_DEVICE_REQUEST; 1417 } 1418 } 1419 1420 VOID 1421 NTAPI 1422 IopReinitializeDrivers(VOID) 1423 { 1424 PDRIVER_REINIT_ITEM ReinitItem; 1425 PLIST_ENTRY Entry; 1426 1427 /* Get the first entry and start looping */ 1428 Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead, 1429 &DriverReinitListLock); 1430 while (Entry) 1431 { 1432 /* Get the item */ 1433 ReinitItem = CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry); 1434 1435 /* Increment reinitialization counter */ 1436 ReinitItem->DriverObject->DriverExtension->Count++; 1437 1438 /* Remove the device object flag */ 1439 ReinitItem->DriverObject->Flags &= ~DRVO_REINIT_REGISTERED; 1440 1441 /* Call the routine */ 1442 ReinitItem->ReinitRoutine(ReinitItem->DriverObject, 1443 ReinitItem->Context, 1444 ReinitItem->DriverObject-> 1445 DriverExtension->Count); 1446 1447 /* Free the entry */ 1448 ExFreePool(Entry); 1449 1450 /* Move to the next one */ 1451 Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead, 1452 &DriverReinitListLock); 1453 } 1454 } 1455 1456 VOID 1457 NTAPI 1458 IopReinitializeBootDrivers(VOID) 1459 { 1460 PDRIVER_REINIT_ITEM ReinitItem; 1461 PLIST_ENTRY Entry; 1462 1463 /* Get the first entry and start looping */ 1464 Entry = ExInterlockedRemoveHeadList(&DriverBootReinitListHead, 1465 &DriverBootReinitListLock); 1466 while (Entry) 1467 { 1468 /* Get the item */ 1469 ReinitItem = CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry); 1470 1471 /* Increment reinitialization counter */ 1472 ReinitItem->DriverObject->DriverExtension->Count++; 1473 1474 /* Remove the device object flag */ 1475 ReinitItem->DriverObject->Flags &= ~DRVO_BOOTREINIT_REGISTERED; 1476 1477 /* Call the routine */ 1478 ReinitItem->ReinitRoutine(ReinitItem->DriverObject, 1479 ReinitItem->Context, 1480 ReinitItem->DriverObject-> 1481 DriverExtension->Count); 1482 1483 /* Free the entry */ 1484 ExFreePool(Entry); 1485 1486 /* Move to the next one */ 1487 Entry = ExInterlockedRemoveHeadList(&DriverBootReinitListHead, 1488 &DriverBootReinitListLock); 1489 } 1490 1491 /* Wait for all device actions being finished*/ 1492 KeWaitForSingleObject(&PiEnumerationFinished, Executive, KernelMode, FALSE, NULL); 1493 } 1494 1495 NTSTATUS 1496 NTAPI 1497 IopCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL, 1498 IN PDRIVER_INITIALIZE InitializationFunction, 1499 IN PUNICODE_STRING RegistryPath OPTIONAL, 1500 IN PCUNICODE_STRING ServiceName, 1501 IN PLDR_DATA_TABLE_ENTRY ModuleObject OPTIONAL, 1502 OUT PDRIVER_OBJECT *pDriverObject) 1503 { 1504 WCHAR NameBuffer[100]; 1505 USHORT NameLength; 1506 UNICODE_STRING LocalDriverName; 1507 NTSTATUS Status; 1508 OBJECT_ATTRIBUTES ObjectAttributes; 1509 ULONG ObjectSize; 1510 PDRIVER_OBJECT DriverObject; 1511 UNICODE_STRING ServiceKeyName; 1512 HANDLE hDriver; 1513 ULONG i, RetryCount = 0; 1514 1515 try_again: 1516 /* First, create a unique name for the driver if we don't have one */ 1517 if (!DriverName) 1518 { 1519 /* Create a random name and set up the string */ 1520 NameLength = (USHORT)swprintf(NameBuffer, 1521 DRIVER_ROOT_NAME L"%08u", 1522 KeTickCount.LowPart); 1523 LocalDriverName.Length = NameLength * sizeof(WCHAR); 1524 LocalDriverName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL); 1525 LocalDriverName.Buffer = NameBuffer; 1526 } 1527 else 1528 { 1529 /* So we can avoid another code path, use a local var */ 1530 LocalDriverName = *DriverName; 1531 } 1532 1533 /* Initialize the Attributes */ 1534 ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(EXTENDED_DRIVER_EXTENSION); 1535 InitializeObjectAttributes(&ObjectAttributes, 1536 &LocalDriverName, 1537 OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 1538 NULL, 1539 NULL); 1540 1541 /* Create the Object */ 1542 Status = ObCreateObject(KernelMode, 1543 IoDriverObjectType, 1544 &ObjectAttributes, 1545 KernelMode, 1546 NULL, 1547 ObjectSize, 1548 0, 1549 0, 1550 (PVOID*)&DriverObject); 1551 if (!NT_SUCCESS(Status)) return Status; 1552 1553 DPRINT("IopCreateDriver(): created DO %p\n", DriverObject); 1554 1555 /* Set up the Object */ 1556 RtlZeroMemory(DriverObject, ObjectSize); 1557 DriverObject->Type = IO_TYPE_DRIVER; 1558 DriverObject->Size = sizeof(DRIVER_OBJECT); 1559 1560 /* 1561 * Check whether RegistryPath and ModuleObject are both NULL because 1562 * IoCreateDriver() was called to initialize a built-in driver. 1563 */ 1564 if ((RegistryPath != NULL) || (ModuleObject != NULL)) 1565 DriverObject->Flags = DRVO_LEGACY_DRIVER; 1566 else 1567 DriverObject->Flags = DRVO_BUILTIN_DRIVER; 1568 1569 DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1); 1570 DriverObject->DriverExtension->DriverObject = DriverObject; 1571 DriverObject->DriverInit = InitializationFunction; 1572 DriverObject->DriverSection = ModuleObject; 1573 /* Loop all Major Functions */ 1574 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) 1575 { 1576 /* Invalidate each function */ 1577 DriverObject->MajorFunction[i] = IopInvalidDeviceRequest; 1578 } 1579 1580 /* Set up the service key name buffer */ 1581 ServiceKeyName.MaximumLength = ServiceName->Length + sizeof(UNICODE_NULL); 1582 ServiceKeyName.Buffer = ExAllocatePoolWithTag(NonPagedPool, 1583 ServiceKeyName.MaximumLength, 1584 TAG_IO); 1585 if (!ServiceKeyName.Buffer) 1586 { 1587 /* Fail */ 1588 ObMakeTemporaryObject(DriverObject); 1589 ObDereferenceObject(DriverObject); 1590 return STATUS_INSUFFICIENT_RESOURCES; 1591 } 1592 1593 /* Copy the name and set it in the driver extension */ 1594 RtlCopyUnicodeString(&ServiceKeyName, 1595 ServiceName); 1596 DriverObject->DriverExtension->ServiceKeyName = ServiceKeyName; 1597 1598 /* Make a copy of the driver name to store in the driver object */ 1599 DriverObject->DriverName.MaximumLength = LocalDriverName.Length; 1600 DriverObject->DriverName.Buffer = ExAllocatePoolWithTag(PagedPool, 1601 DriverObject->DriverName.MaximumLength, 1602 TAG_IO); 1603 if (!DriverObject->DriverName.Buffer) 1604 { 1605 /* Fail */ 1606 ObMakeTemporaryObject(DriverObject); 1607 ObDereferenceObject(DriverObject); 1608 return STATUS_INSUFFICIENT_RESOURCES; 1609 } 1610 1611 RtlCopyUnicodeString(&DriverObject->DriverName, 1612 &LocalDriverName); 1613 1614 /* Add the Object and get its handle */ 1615 Status = ObInsertObject(DriverObject, 1616 NULL, 1617 FILE_READ_DATA, 1618 0, 1619 NULL, 1620 &hDriver); 1621 1622 /* Eliminate small possibility when this function is called more than 1623 once in a row, and KeTickCount doesn't get enough time to change */ 1624 if (!DriverName && (Status == STATUS_OBJECT_NAME_COLLISION) && (RetryCount < 100)) 1625 { 1626 RetryCount++; 1627 goto try_again; 1628 } 1629 1630 if (!NT_SUCCESS(Status)) return Status; 1631 1632 /* Now reference it */ 1633 Status = ObReferenceObjectByHandle(hDriver, 1634 0, 1635 IoDriverObjectType, 1636 KernelMode, 1637 (PVOID*)&DriverObject, 1638 NULL); 1639 1640 /* Close the extra handle */ 1641 ZwClose(hDriver); 1642 1643 if (!NT_SUCCESS(Status)) 1644 { 1645 /* Fail */ 1646 ObMakeTemporaryObject(DriverObject); 1647 ObDereferenceObject(DriverObject); 1648 return Status; 1649 } 1650 1651 DriverObject->HardwareDatabase = &IopHardwareDatabaseKey; 1652 DriverObject->DriverStart = ModuleObject ? ModuleObject->DllBase : 0; 1653 DriverObject->DriverSize = ModuleObject ? ModuleObject->SizeOfImage : 0; 1654 1655 /* Finally, call its init function */ 1656 DPRINT("RegistryKey: %wZ\n", RegistryPath); 1657 DPRINT("Calling driver entrypoint at %p\n", InitializationFunction); 1658 Status = (*InitializationFunction)(DriverObject, RegistryPath); 1659 if (!NT_SUCCESS(Status)) 1660 { 1661 /* If it didn't work, then kill the object */ 1662 DPRINT1("'%wZ' initialization failed, status (0x%08lx)\n", DriverName, Status); 1663 DriverObject->DriverSection = NULL; 1664 ObMakeTemporaryObject(DriverObject); 1665 ObDereferenceObject(DriverObject); 1666 return Status; 1667 } 1668 else 1669 { 1670 /* Returns to caller the object */ 1671 *pDriverObject = DriverObject; 1672 } 1673 1674 /* We're going to say if we don't have any DOs from DriverEntry, then we're not legacy. 1675 * Other parts of the I/O manager depend on this behavior */ 1676 if (!DriverObject->DeviceObject) DriverObject->Flags &= ~DRVO_LEGACY_DRIVER; 1677 1678 /* Loop all Major Functions */ 1679 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) 1680 { 1681 /* 1682 * Make sure the driver didn't set any dispatch entry point to NULL! 1683 * Doing so is illegal; drivers shouldn't touch entry points they 1684 * do not implement. 1685 */ 1686 1687 /* Check if it did so anyway */ 1688 if (!DriverObject->MajorFunction[i]) 1689 { 1690 /* Print a warning in the debug log */ 1691 DPRINT1("Driver <%wZ> set DriverObject->MajorFunction[%lu] to NULL!\n", 1692 &DriverObject->DriverName, i); 1693 1694 /* Fix it up */ 1695 DriverObject->MajorFunction[i] = IopInvalidDeviceRequest; 1696 } 1697 } 1698 1699 /* Return the Status */ 1700 return Status; 1701 } 1702 1703 /* PUBLIC FUNCTIONS ***********************************************************/ 1704 1705 /* 1706 * @implemented 1707 */ 1708 NTSTATUS 1709 NTAPI 1710 IoCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL, 1711 IN PDRIVER_INITIALIZE InitializationFunction) 1712 { 1713 PDRIVER_OBJECT DriverObject; 1714 return IopCreateDriver(DriverName, InitializationFunction, NULL, DriverName, NULL, &DriverObject); 1715 } 1716 1717 /* 1718 * @implemented 1719 */ 1720 VOID 1721 NTAPI 1722 IoDeleteDriver(IN PDRIVER_OBJECT DriverObject) 1723 { 1724 /* Simply dereference the Object */ 1725 ObDereferenceObject(DriverObject); 1726 } 1727 1728 /* 1729 * @implemented 1730 */ 1731 VOID 1732 NTAPI 1733 IoRegisterBootDriverReinitialization(IN PDRIVER_OBJECT DriverObject, 1734 IN PDRIVER_REINITIALIZE ReinitRoutine, 1735 IN PVOID Context) 1736 { 1737 PDRIVER_REINIT_ITEM ReinitItem; 1738 1739 /* Allocate the entry */ 1740 ReinitItem = ExAllocatePoolWithTag(NonPagedPool, 1741 sizeof(DRIVER_REINIT_ITEM), 1742 TAG_REINIT); 1743 if (!ReinitItem) return; 1744 1745 /* Fill it out */ 1746 ReinitItem->DriverObject = DriverObject; 1747 ReinitItem->ReinitRoutine = ReinitRoutine; 1748 ReinitItem->Context = Context; 1749 1750 /* Set the Driver Object flag and insert the entry into the list */ 1751 DriverObject->Flags |= DRVO_BOOTREINIT_REGISTERED; 1752 ExInterlockedInsertTailList(&DriverBootReinitListHead, 1753 &ReinitItem->ItemEntry, 1754 &DriverBootReinitListLock); 1755 } 1756 1757 /* 1758 * @implemented 1759 */ 1760 VOID 1761 NTAPI 1762 IoRegisterDriverReinitialization(IN PDRIVER_OBJECT DriverObject, 1763 IN PDRIVER_REINITIALIZE ReinitRoutine, 1764 IN PVOID Context) 1765 { 1766 PDRIVER_REINIT_ITEM ReinitItem; 1767 1768 /* Allocate the entry */ 1769 ReinitItem = ExAllocatePoolWithTag(NonPagedPool, 1770 sizeof(DRIVER_REINIT_ITEM), 1771 TAG_REINIT); 1772 if (!ReinitItem) return; 1773 1774 /* Fill it out */ 1775 ReinitItem->DriverObject = DriverObject; 1776 ReinitItem->ReinitRoutine = ReinitRoutine; 1777 ReinitItem->Context = Context; 1778 1779 /* Set the Driver Object flag and insert the entry into the list */ 1780 DriverObject->Flags |= DRVO_REINIT_REGISTERED; 1781 ExInterlockedInsertTailList(&DriverReinitListHead, 1782 &ReinitItem->ItemEntry, 1783 &DriverReinitListLock); 1784 } 1785 1786 /* 1787 * @implemented 1788 */ 1789 NTSTATUS 1790 NTAPI 1791 IoAllocateDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, 1792 IN PVOID ClientIdentificationAddress, 1793 IN ULONG DriverObjectExtensionSize, 1794 OUT PVOID *DriverObjectExtension) 1795 { 1796 KIRQL OldIrql; 1797 PIO_CLIENT_EXTENSION DriverExtensions, NewDriverExtension; 1798 BOOLEAN Inserted = FALSE; 1799 1800 /* Assume failure */ 1801 *DriverObjectExtension = NULL; 1802 1803 /* Allocate the extension */ 1804 NewDriverExtension = ExAllocatePoolWithTag(NonPagedPool, 1805 sizeof(IO_CLIENT_EXTENSION) + 1806 DriverObjectExtensionSize, 1807 TAG_DRIVER_EXTENSION); 1808 if (!NewDriverExtension) return STATUS_INSUFFICIENT_RESOURCES; 1809 1810 /* Clear the extension for teh caller */ 1811 RtlZeroMemory(NewDriverExtension, 1812 sizeof(IO_CLIENT_EXTENSION) + DriverObjectExtensionSize); 1813 1814 /* Acqure lock */ 1815 OldIrql = KeRaiseIrqlToDpcLevel(); 1816 1817 /* Fill out the extension */ 1818 NewDriverExtension->ClientIdentificationAddress = ClientIdentificationAddress; 1819 1820 /* Loop the current extensions */ 1821 DriverExtensions = IoGetDrvObjExtension(DriverObject)-> 1822 ClientDriverExtension; 1823 while (DriverExtensions) 1824 { 1825 /* Check if the identifier matches */ 1826 if (DriverExtensions->ClientIdentificationAddress == 1827 ClientIdentificationAddress) 1828 { 1829 /* We have a collision, break out */ 1830 break; 1831 } 1832 1833 /* Go to the next one */ 1834 DriverExtensions = DriverExtensions->NextExtension; 1835 } 1836 1837 /* Check if we didn't collide */ 1838 if (!DriverExtensions) 1839 { 1840 /* Link this one in */ 1841 NewDriverExtension->NextExtension = 1842 IoGetDrvObjExtension(DriverObject)->ClientDriverExtension; 1843 IoGetDrvObjExtension(DriverObject)->ClientDriverExtension = 1844 NewDriverExtension; 1845 Inserted = TRUE; 1846 } 1847 1848 /* Release the lock */ 1849 KeLowerIrql(OldIrql); 1850 1851 /* Check if insertion failed */ 1852 if (!Inserted) 1853 { 1854 /* Free the entry and fail */ 1855 ExFreePoolWithTag(NewDriverExtension, TAG_DRIVER_EXTENSION); 1856 return STATUS_OBJECT_NAME_COLLISION; 1857 } 1858 1859 /* Otherwise, return the pointer */ 1860 *DriverObjectExtension = NewDriverExtension + 1; 1861 return STATUS_SUCCESS; 1862 } 1863 1864 /* 1865 * @implemented 1866 */ 1867 PVOID 1868 NTAPI 1869 IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, 1870 IN PVOID ClientIdentificationAddress) 1871 { 1872 KIRQL OldIrql; 1873 PIO_CLIENT_EXTENSION DriverExtensions; 1874 1875 /* Acquire lock */ 1876 OldIrql = KeRaiseIrqlToDpcLevel(); 1877 1878 /* Loop the list until we find the right one */ 1879 DriverExtensions = IoGetDrvObjExtension(DriverObject)->ClientDriverExtension; 1880 while (DriverExtensions) 1881 { 1882 /* Check for a match */ 1883 if (DriverExtensions->ClientIdentificationAddress == 1884 ClientIdentificationAddress) 1885 { 1886 /* Break out */ 1887 break; 1888 } 1889 1890 /* Keep looping */ 1891 DriverExtensions = DriverExtensions->NextExtension; 1892 } 1893 1894 /* Release lock */ 1895 KeLowerIrql(OldIrql); 1896 1897 /* Return nothing or the extension */ 1898 if (!DriverExtensions) return NULL; 1899 return DriverExtensions + 1; 1900 } 1901 1902 VOID 1903 NTAPI 1904 IopLoadUnloadDriverWorker( 1905 _Inout_ PVOID Parameter) 1906 { 1907 PLOAD_UNLOAD_PARAMS LoadParams = Parameter; 1908 1909 ASSERT(PsGetCurrentProcess() == PsInitialSystemProcess); 1910 LoadParams->Status = IopLoadUnloadDriver(LoadParams->RegistryPath, 1911 &LoadParams->DriverObject); 1912 KeSetEvent(&LoadParams->Event, 0, FALSE); 1913 } 1914 1915 NTSTATUS 1916 NTAPI 1917 IopLoadUnloadDriver( 1918 _In_opt_ PCUNICODE_STRING RegistryPath, 1919 _Inout_ PDRIVER_OBJECT *DriverObject) 1920 { 1921 RTL_QUERY_REGISTRY_TABLE QueryTable[3]; 1922 UNICODE_STRING ImagePath; 1923 UNICODE_STRING ServiceName; 1924 NTSTATUS Status; 1925 ULONG Type; 1926 PDEVICE_NODE DeviceNode; 1927 PLDR_DATA_TABLE_ENTRY ModuleObject; 1928 PVOID BaseAddress; 1929 WCHAR *cur; 1930 1931 /* Load/Unload must be called from system process */ 1932 if (PsGetCurrentProcess() != PsInitialSystemProcess) 1933 { 1934 LOAD_UNLOAD_PARAMS LoadParams; 1935 1936 /* Prepare parameters block */ 1937 LoadParams.RegistryPath = RegistryPath; 1938 LoadParams.DriverObject = *DriverObject; 1939 KeInitializeEvent(&LoadParams.Event, NotificationEvent, FALSE); 1940 1941 /* Initialize and queue a work item */ 1942 ExInitializeWorkItem(&LoadParams.WorkItem, 1943 IopLoadUnloadDriverWorker, 1944 &LoadParams); 1945 ExQueueWorkItem(&LoadParams.WorkItem, DelayedWorkQueue); 1946 1947 /* And wait till it completes */ 1948 KeWaitForSingleObject(&LoadParams.Event, 1949 UserRequest, 1950 KernelMode, 1951 FALSE, 1952 NULL); 1953 return LoadParams.Status; 1954 } 1955 1956 /* Check if it's an unload request */ 1957 if (*DriverObject) 1958 { 1959 (*DriverObject)->DriverUnload(*DriverObject); 1960 return STATUS_SUCCESS; 1961 } 1962 1963 RtlInitUnicodeString(&ImagePath, NULL); 1964 1965 /* 1966 * Get the service name from the registry key name. 1967 */ 1968 ASSERT(RegistryPath->Length >= sizeof(WCHAR)); 1969 1970 ServiceName = *RegistryPath; 1971 cur = RegistryPath->Buffer + RegistryPath->Length / sizeof(WCHAR) - 1; 1972 while (RegistryPath->Buffer != cur) 1973 { 1974 if (*cur == L'\\') 1975 { 1976 ServiceName.Buffer = cur + 1; 1977 ServiceName.Length = RegistryPath->Length - 1978 (USHORT)((ULONG_PTR)ServiceName.Buffer - 1979 (ULONG_PTR)RegistryPath->Buffer); 1980 break; 1981 } 1982 cur--; 1983 } 1984 1985 /* 1986 * Get service type. 1987 */ 1988 RtlZeroMemory(&QueryTable, sizeof(QueryTable)); 1989 1990 RtlInitUnicodeString(&ImagePath, NULL); 1991 1992 QueryTable[0].Name = L"Type"; 1993 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; 1994 QueryTable[0].EntryContext = &Type; 1995 1996 QueryTable[1].Name = L"ImagePath"; 1997 QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; 1998 QueryTable[1].EntryContext = &ImagePath; 1999 2000 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, 2001 RegistryPath->Buffer, 2002 QueryTable, NULL, NULL); 2003 if (!NT_SUCCESS(Status)) 2004 { 2005 DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status); 2006 if (ImagePath.Buffer) ExFreePool(ImagePath.Buffer); 2007 return Status; 2008 } 2009 2010 /* 2011 * Normalize the image path for all later processing. 2012 */ 2013 Status = IopNormalizeImagePath(&ImagePath, &ServiceName); 2014 if (!NT_SUCCESS(Status)) 2015 { 2016 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status); 2017 return Status; 2018 } 2019 2020 DPRINT("FullImagePath: '%wZ'\n", &ImagePath); 2021 DPRINT("Type: %lx\n", Type); 2022 2023 KeEnterCriticalRegion(); 2024 ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE); 2025 /* 2026 * Get existing DriverObject pointer (in case the driver 2027 * has already been loaded and initialized). 2028 */ 2029 Status = IopGetDriverObject(DriverObject, 2030 &ServiceName, 2031 (Type == SERVICE_FILE_SYSTEM_DRIVER || 2032 Type == SERVICE_RECOGNIZER_DRIVER)); 2033 2034 if (!NT_SUCCESS(Status)) 2035 { 2036 /* 2037 * Load the driver module 2038 */ 2039 DPRINT("Loading module from %wZ\n", &ImagePath); 2040 Status = MmLoadSystemImage(&ImagePath, NULL, NULL, 0, (PVOID)&ModuleObject, &BaseAddress); 2041 if (!NT_SUCCESS(Status)) 2042 { 2043 DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status); 2044 ExReleaseResourceLite(&IopDriverLoadResource); 2045 KeLeaveCriticalRegion(); 2046 return Status; 2047 } 2048 2049 /* 2050 * Initialize the driver module if it's loaded for the first time 2051 */ 2052 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &ServiceName, &DeviceNode); 2053 if (!NT_SUCCESS(Status)) 2054 { 2055 DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status); 2056 ExReleaseResourceLite(&IopDriverLoadResource); 2057 KeLeaveCriticalRegion(); 2058 MmUnloadSystemImage(ModuleObject); 2059 return Status; 2060 } 2061 2062 IopDisplayLoadingMessage(&DeviceNode->ServiceName); 2063 2064 Status = IopInitializeDriverModule(DeviceNode, 2065 ModuleObject, 2066 &DeviceNode->ServiceName, 2067 (Type == SERVICE_FILE_SYSTEM_DRIVER || 2068 Type == SERVICE_RECOGNIZER_DRIVER), 2069 DriverObject); 2070 if (!NT_SUCCESS(Status)) 2071 { 2072 DPRINT1("IopInitializeDriverModule() failed (Status %lx)\n", Status); 2073 ExReleaseResourceLite(&IopDriverLoadResource); 2074 KeLeaveCriticalRegion(); 2075 MmUnloadSystemImage(ModuleObject); 2076 return Status; 2077 } 2078 2079 ExReleaseResourceLite(&IopDriverLoadResource); 2080 KeLeaveCriticalRegion(); 2081 2082 /* Initialize and start device */ 2083 IopInitializeDevice(DeviceNode, *DriverObject); 2084 Status = IopStartDevice(DeviceNode); 2085 } 2086 else 2087 { 2088 ExReleaseResourceLite(&IopDriverLoadResource); 2089 KeLeaveCriticalRegion(); 2090 2091 DPRINT("DriverObject already exist in ObjectManager\n"); 2092 Status = STATUS_IMAGE_ALREADY_LOADED; 2093 2094 /* IopGetDriverObject references the DriverObject, so dereference it */ 2095 ObDereferenceObject(*DriverObject); 2096 } 2097 2098 return Status; 2099 } 2100 2101 /* 2102 * NtLoadDriver 2103 * 2104 * Loads a device driver. 2105 * 2106 * Parameters 2107 * DriverServiceName 2108 * Name of the service to load (registry key). 2109 * 2110 * Return Value 2111 * Status 2112 * 2113 * Status 2114 * implemented 2115 */ 2116 NTSTATUS NTAPI 2117 NtLoadDriver(IN PUNICODE_STRING DriverServiceName) 2118 { 2119 UNICODE_STRING CapturedDriverServiceName = { 0, 0, NULL }; 2120 KPROCESSOR_MODE PreviousMode; 2121 PDRIVER_OBJECT DriverObject; 2122 NTSTATUS Status; 2123 2124 PAGED_CODE(); 2125 2126 PreviousMode = KeGetPreviousMode(); 2127 2128 /* 2129 * Check security privileges 2130 */ 2131 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode)) 2132 { 2133 DPRINT("Privilege not held\n"); 2134 return STATUS_PRIVILEGE_NOT_HELD; 2135 } 2136 2137 Status = ProbeAndCaptureUnicodeString(&CapturedDriverServiceName, 2138 PreviousMode, 2139 DriverServiceName); 2140 if (!NT_SUCCESS(Status)) 2141 { 2142 return Status; 2143 } 2144 2145 DPRINT("NtLoadDriver('%wZ')\n", &CapturedDriverServiceName); 2146 2147 /* Load driver and call its entry point */ 2148 DriverObject = NULL; 2149 Status = IopLoadUnloadDriver(&CapturedDriverServiceName, &DriverObject); 2150 2151 ReleaseCapturedUnicodeString(&CapturedDriverServiceName, 2152 PreviousMode); 2153 2154 return Status; 2155 } 2156 2157 /* 2158 * NtUnloadDriver 2159 * 2160 * Unloads a legacy device driver. 2161 * 2162 * Parameters 2163 * DriverServiceName 2164 * Name of the service to unload (registry key). 2165 * 2166 * Return Value 2167 * Status 2168 * 2169 * Status 2170 * implemented 2171 */ 2172 2173 NTSTATUS NTAPI 2174 NtUnloadDriver(IN PUNICODE_STRING DriverServiceName) 2175 { 2176 return IopUnloadDriver(DriverServiceName, FALSE); 2177 } 2178 2179 /* EOF */ 2180