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