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