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