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