Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendriver.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/io/iomgr/driver.c 00005 * PURPOSE: Driver Object Management 00006 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 00007 * Filip Navara (navaraf@reactos.org) 00008 * Hervé Poussineau (hpoussin@reactos.org) 00009 */ 00010 00011 /* INCLUDES *******************************************************************/ 00012 00013 #include <ntoskrnl.h> 00014 #define NDEBUG 00015 #include <debug.h> 00016 00017 /* GLOBALS ********************************************************************/ 00018 00019 LIST_ENTRY DriverReinitListHead; 00020 KSPIN_LOCK DriverReinitListLock; 00021 PLIST_ENTRY DriverReinitTailEntry; 00022 00023 PLIST_ENTRY DriverBootReinitTailEntry; 00024 LIST_ENTRY DriverBootReinitListHead; 00025 KSPIN_LOCK DriverBootReinitListLock; 00026 00027 UNICODE_STRING IopHardwareDatabaseKey = 00028 RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM"); 00029 00030 POBJECT_TYPE IoDriverObjectType = NULL; 00031 00032 #define TAG_RTLREGISTRY 'vrqR' 00033 00034 extern BOOLEAN ExpInTextModeSetup; 00035 extern BOOLEAN PnpSystemInit; 00036 00037 USHORT IopGroupIndex; 00038 PLIST_ENTRY IopGroupTable; 00039 00040 /* PRIVATE FUNCTIONS **********************************************************/ 00041 00042 NTSTATUS NTAPI 00043 IopInvalidDeviceRequest( 00044 PDEVICE_OBJECT DeviceObject, 00045 PIRP Irp) 00046 { 00047 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; 00048 Irp->IoStatus.Information = 0; 00049 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00050 return STATUS_INVALID_DEVICE_REQUEST; 00051 } 00052 00053 VOID 00054 NTAPI 00055 IopDeleteDriver(IN PVOID ObjectBody) 00056 { 00057 PDRIVER_OBJECT DriverObject = ObjectBody; 00058 PIO_CLIENT_EXTENSION DriverExtension, NextDriverExtension; 00059 PAGED_CODE(); 00060 00061 DPRINT1("Deleting driver object '%wZ'\n", &DriverObject->DriverName); 00062 00063 /* There must be no device objects remaining at this point */ 00064 ASSERT(!DriverObject->DeviceObject); 00065 00066 /* Get the extension and loop them */ 00067 DriverExtension = IoGetDrvObjExtension(DriverObject)-> 00068 ClientDriverExtension; 00069 while (DriverExtension) 00070 { 00071 /* Get the next one */ 00072 NextDriverExtension = DriverExtension->NextExtension; 00073 ExFreePoolWithTag(DriverExtension, TAG_DRIVER_EXTENSION); 00074 00075 /* Move on */ 00076 DriverExtension = NextDriverExtension; 00077 } 00078 00079 #if 0 00080 /* Check if the driver image is still loaded */ 00081 if (DriverObject->DriverSection) 00082 { 00083 /* Unload it */ 00084 MmUnloadSystemImage(DriverObject->DriverSection); 00085 } 00086 #else 00087 DPRINT1("HACK: Not unloading the driver image due to critical bugs!\n"); 00088 #endif 00089 00090 /* Check if it has a name */ 00091 if (DriverObject->DriverName.Buffer) 00092 { 00093 /* Free it */ 00094 ExFreePool(DriverObject->DriverName.Buffer); 00095 } 00096 00097 #if 0 /* See a bit of hack in IopCreateDriver */ 00098 /* Check if it has a service key name */ 00099 if (DriverObject->DriverExtension->ServiceKeyName.Buffer) 00100 { 00101 /* Free it */ 00102 ExFreePool(DriverObject->DriverExtension->ServiceKeyName.Buffer); 00103 } 00104 #endif 00105 } 00106 00107 NTSTATUS FASTCALL 00108 IopGetDriverObject( 00109 PDRIVER_OBJECT *DriverObject, 00110 PUNICODE_STRING ServiceName, 00111 BOOLEAN FileSystem) 00112 { 00113 PDRIVER_OBJECT Object; 00114 WCHAR NameBuffer[MAX_PATH]; 00115 UNICODE_STRING DriverName; 00116 NTSTATUS Status; 00117 00118 DPRINT("IopGetDriverObject(%p '%wZ' %x)\n", 00119 DriverObject, ServiceName, FileSystem); 00120 00121 *DriverObject = NULL; 00122 00123 /* Create ModuleName string */ 00124 if (ServiceName == NULL || ServiceName->Buffer == NULL) 00125 /* We don't know which DriverObject we have to open */ 00126 return STATUS_INVALID_PARAMETER_2; 00127 00128 DriverName.Buffer = NameBuffer; 00129 DriverName.Length = 0; 00130 DriverName.MaximumLength = sizeof(NameBuffer); 00131 00132 if (FileSystem == TRUE) 00133 RtlAppendUnicodeToString(&DriverName, FILESYSTEM_ROOT_NAME); 00134 else 00135 RtlAppendUnicodeToString(&DriverName, DRIVER_ROOT_NAME); 00136 RtlAppendUnicodeStringToString(&DriverName, ServiceName); 00137 00138 DPRINT("Driver name: '%wZ'\n", &DriverName); 00139 00140 /* Open driver object */ 00141 Status = ObReferenceObjectByName( 00142 &DriverName, 00143 OBJ_OPENIF | OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, /* Attributes */ 00144 NULL, /* PassedAccessState */ 00145 0, /* DesiredAccess */ 00146 IoDriverObjectType, 00147 KernelMode, 00148 NULL, /* ParseContext */ 00149 (PVOID*)&Object); 00150 00151 if (!NT_SUCCESS(Status)) 00152 { 00153 DPRINT("Failed to reference driver object, status=0x%08x\n", Status); 00154 return Status; 00155 } 00156 00157 *DriverObject = Object; 00158 00159 DPRINT("Driver Object: %p\n", Object); 00160 00161 return STATUS_SUCCESS; 00162 } 00163 00164 /* 00165 * RETURNS 00166 * TRUE if String2 contains String1 as a suffix. 00167 */ 00168 BOOLEAN 00169 NTAPI 00170 IopSuffixUnicodeString( 00171 IN PCUNICODE_STRING String1, 00172 IN PCUNICODE_STRING String2) 00173 { 00174 PWCHAR pc1; 00175 PWCHAR pc2; 00176 ULONG Length; 00177 00178 if (String2->Length < String1->Length) 00179 return FALSE; 00180 00181 Length = String1->Length / 2; 00182 pc1 = String1->Buffer; 00183 pc2 = &String2->Buffer[String2->Length / sizeof(WCHAR) - Length]; 00184 00185 if (pc1 && pc2) 00186 { 00187 while (Length--) 00188 { 00189 if( *pc1++ != *pc2++ ) 00190 return FALSE; 00191 } 00192 return TRUE; 00193 } 00194 return FALSE; 00195 } 00196 00197 /* 00198 * IopDisplayLoadingMessage 00199 * 00200 * Display 'Loading XXX...' message. 00201 */ 00202 00203 VOID 00204 FASTCALL 00205 INIT_FUNCTION 00206 IopDisplayLoadingMessage(PUNICODE_STRING ServiceName) 00207 { 00208 CHAR TextBuffer[256]; 00209 UNICODE_STRING DotSys = RTL_CONSTANT_STRING(L".SYS"); 00210 00211 if (ExpInTextModeSetup) return; 00212 if (!KeLoaderBlock) return; 00213 RtlUpcaseUnicodeString(ServiceName, ServiceName, FALSE); 00214 snprintf(TextBuffer, sizeof(TextBuffer), 00215 "%s%sSystem32\\Drivers\\%wZ%s\n", 00216 KeLoaderBlock->ArcBootDeviceName, 00217 KeLoaderBlock->NtBootPathName, 00218 ServiceName, 00219 IopSuffixUnicodeString(&DotSys, ServiceName) ? "" : ".SYS"); 00220 HalDisplayString(TextBuffer); 00221 } 00222 00223 /* 00224 * IopNormalizeImagePath 00225 * 00226 * Normalize an image path to contain complete path. 00227 * 00228 * Parameters 00229 * ImagePath 00230 * The input path and on exit the result path. ImagePath.Buffer 00231 * must be allocated by ExAllocatePool on input. Caller is responsible 00232 * for freeing the buffer when it's no longer needed. 00233 * 00234 * ServiceName 00235 * Name of the service that ImagePath belongs to. 00236 * 00237 * Return Value 00238 * Status 00239 * 00240 * Remarks 00241 * The input image path isn't freed on error. 00242 */ 00243 00244 NTSTATUS FASTCALL 00245 IopNormalizeImagePath( 00246 IN OUT PUNICODE_STRING ImagePath, 00247 IN PUNICODE_STRING ServiceName) 00248 { 00249 UNICODE_STRING InputImagePath; 00250 00251 DPRINT("Normalizing image path '%wZ' for service '%wZ'\n", ImagePath, ServiceName); 00252 00253 RtlCopyMemory( 00254 &InputImagePath, 00255 ImagePath, 00256 sizeof(UNICODE_STRING)); 00257 00258 if (InputImagePath.Length == 0) 00259 { 00260 ImagePath->Length = 0; 00261 ImagePath->MaximumLength = 00262 (33 * sizeof(WCHAR)) + ServiceName->Length + sizeof(UNICODE_NULL); 00263 ImagePath->Buffer = ExAllocatePool(NonPagedPool, ImagePath->MaximumLength); 00264 if (ImagePath->Buffer == NULL) 00265 return STATUS_NO_MEMORY; 00266 00267 RtlAppendUnicodeToString(ImagePath, L"\\SystemRoot\\system32\\drivers\\"); 00268 RtlAppendUnicodeStringToString(ImagePath, ServiceName); 00269 RtlAppendUnicodeToString(ImagePath, L".sys"); 00270 } else 00271 if (InputImagePath.Buffer[0] != L'\\') 00272 { 00273 ImagePath->Length = 0; 00274 ImagePath->MaximumLength = 00275 12 * sizeof(WCHAR) + InputImagePath.Length + sizeof(UNICODE_NULL); 00276 ImagePath->Buffer = ExAllocatePool(NonPagedPool, ImagePath->MaximumLength); 00277 if (ImagePath->Buffer == NULL) 00278 return STATUS_NO_MEMORY; 00279 00280 RtlAppendUnicodeToString(ImagePath, L"\\SystemRoot\\"); 00281 RtlAppendUnicodeStringToString(ImagePath, &InputImagePath); 00282 00283 /* Free caller's string */ 00284 ExFreePoolWithTag(InputImagePath.Buffer, TAG_RTLREGISTRY); 00285 } 00286 00287 DPRINT("Normalized image path is '%wZ' for service '%wZ'\n", ImagePath, ServiceName); 00288 00289 return STATUS_SUCCESS; 00290 } 00291 00292 /* 00293 * IopLoadServiceModule 00294 * 00295 * Load a module specified by registry settings for service. 00296 * 00297 * Parameters 00298 * ServiceName 00299 * Name of the service to load. 00300 * 00301 * Return Value 00302 * Status 00303 */ 00304 00305 NTSTATUS FASTCALL 00306 IopLoadServiceModule( 00307 IN PUNICODE_STRING ServiceName, 00308 OUT PLDR_DATA_TABLE_ENTRY *ModuleObject) 00309 { 00310 RTL_QUERY_REGISTRY_TABLE QueryTable[3]; 00311 ULONG ServiceStart; 00312 UNICODE_STRING ServiceImagePath, CCSName; 00313 NTSTATUS Status; 00314 HANDLE CCSKey, ServiceKey; 00315 PVOID BaseAddress; 00316 00317 DPRINT("IopLoadServiceModule(%wZ, 0x%p)\n", ServiceName, ModuleObject); 00318 00319 /* FIXME: This check may be removed once the bug is fixed */ 00320 if (ServiceName->Buffer == NULL) 00321 { 00322 DPRINT1("If you see this, please report to Fireball or hpoussin!\n"); 00323 return STATUS_UNSUCCESSFUL; 00324 } 00325 00326 if (ExpInTextModeSetup) 00327 { 00328 /* We have no registry, but luckily we know where all the drivers are */ 00329 00330 /* ServiceStart < 4 is all that matters */ 00331 ServiceStart = 0; 00332 00333 /* IopNormalizeImagePath will do all of the work for us if we give it an empty string */ 00334 ServiceImagePath.Length = ServiceImagePath.MaximumLength = 0; 00335 ServiceImagePath.Buffer = NULL; 00336 } 00337 else 00338 { 00339 /* Open CurrentControlSet */ 00340 RtlInitUnicodeString(&CCSName, 00341 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services"); 00342 Status = IopOpenRegistryKeyEx(&CCSKey, NULL, &CCSName, KEY_READ); 00343 if (!NT_SUCCESS(Status)) 00344 { 00345 DPRINT1("ZwOpenKey() failed with Status %08X\n", Status); 00346 return Status; 00347 } 00348 00349 /* Open service key */ 00350 Status = IopOpenRegistryKeyEx(&ServiceKey, CCSKey, ServiceName, KEY_READ); 00351 if (!NT_SUCCESS(Status)) 00352 { 00353 DPRINT1("ZwOpenKey() failed with Status %08X\n", Status); 00354 ZwClose(CCSKey); 00355 return Status; 00356 } 00357 00358 /* 00359 * Get information about the service. 00360 */ 00361 00362 RtlZeroMemory(QueryTable, sizeof(QueryTable)); 00363 00364 RtlInitUnicodeString(&ServiceImagePath, NULL); 00365 00366 QueryTable[0].Name = L"Start"; 00367 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; 00368 QueryTable[0].EntryContext = &ServiceStart; 00369 00370 QueryTable[1].Name = L"ImagePath"; 00371 QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; 00372 QueryTable[1].EntryContext = &ServiceImagePath; 00373 00374 Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, 00375 (PWSTR)ServiceKey, QueryTable, NULL, NULL); 00376 00377 ZwClose(ServiceKey); 00378 ZwClose(CCSKey); 00379 00380 if (!NT_SUCCESS(Status)) 00381 { 00382 DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status); 00383 return Status; 00384 } 00385 } 00386 00387 /* 00388 * Normalize the image path for all later processing. 00389 */ 00390 00391 Status = IopNormalizeImagePath(&ServiceImagePath, ServiceName); 00392 00393 if (!NT_SUCCESS(Status)) 00394 { 00395 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status); 00396 return Status; 00397 } 00398 00399 /* 00400 * Case for disabled drivers 00401 */ 00402 00403 if (ServiceStart >= 4) 00404 { 00405 /* We can't load this */ 00406 Status = STATUS_DRIVER_UNABLE_TO_LOAD; 00407 } 00408 else 00409 { 00410 DPRINT("Loading module from %wZ\n", &ServiceImagePath); 00411 Status = MmLoadSystemImage(&ServiceImagePath, NULL, NULL, 0, (PVOID)ModuleObject, &BaseAddress); 00412 if (NT_SUCCESS(Status)) 00413 { 00414 IopDisplayLoadingMessage(ServiceName); 00415 } 00416 } 00417 00418 ExFreePool(ServiceImagePath.Buffer); 00419 00420 /* 00421 * Now check if the module was loaded successfully. 00422 */ 00423 00424 if (!NT_SUCCESS(Status)) 00425 { 00426 DPRINT("Module loading failed (Status %x)\n", Status); 00427 } 00428 00429 DPRINT("Module loading (Status %x)\n", Status); 00430 00431 return Status; 00432 } 00433 00434 VOID 00435 NTAPI 00436 MmFreeDriverInitialization(IN PLDR_DATA_TABLE_ENTRY LdrEntry); 00437 00438 /* 00439 * IopInitializeDriverModule 00440 * 00441 * Initalize a loaded driver. 00442 * 00443 * Parameters 00444 * DeviceNode 00445 * Pointer to device node. 00446 * 00447 * ModuleObject 00448 * Module object representing the driver. It can be retrieve by 00449 * IopLoadServiceModule. 00450 * 00451 * ServiceName 00452 * Name of the service (as in registry). 00453 * 00454 * FileSystemDriver 00455 * Set to TRUE for file system drivers. 00456 * 00457 * DriverObject 00458 * On successful return this contains the driver object representing 00459 * the loaded driver. 00460 */ 00461 00462 NTSTATUS FASTCALL 00463 IopInitializeDriverModule( 00464 IN PDEVICE_NODE DeviceNode, 00465 IN PLDR_DATA_TABLE_ENTRY ModuleObject, 00466 IN PUNICODE_STRING ServiceName, 00467 IN BOOLEAN FileSystemDriver, 00468 OUT PDRIVER_OBJECT *DriverObject) 00469 { 00470 const WCHAR ServicesKeyName[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"; 00471 WCHAR NameBuffer[MAX_PATH]; 00472 UNICODE_STRING DriverName; 00473 UNICODE_STRING RegistryKey; 00474 PDRIVER_INITIALIZE DriverEntry; 00475 PDRIVER_OBJECT Driver; 00476 NTSTATUS Status; 00477 00478 DriverEntry = ModuleObject->EntryPoint; 00479 00480 if (ServiceName != NULL && ServiceName->Length != 0) 00481 { 00482 RegistryKey.Length = 0; 00483 RegistryKey.MaximumLength = sizeof(ServicesKeyName) + ServiceName->Length; 00484 RegistryKey.Buffer = ExAllocatePool(PagedPool, RegistryKey.MaximumLength); 00485 if (RegistryKey.Buffer == NULL) 00486 { 00487 return STATUS_INSUFFICIENT_RESOURCES; 00488 } 00489 RtlAppendUnicodeToString(&RegistryKey, ServicesKeyName); 00490 RtlAppendUnicodeStringToString(&RegistryKey, ServiceName); 00491 } 00492 else 00493 { 00494 RtlInitUnicodeString(&RegistryKey, NULL); 00495 } 00496 00497 /* Create ModuleName string */ 00498 if (ServiceName && ServiceName->Length > 0) 00499 { 00500 if (FileSystemDriver == TRUE) 00501 wcscpy(NameBuffer, FILESYSTEM_ROOT_NAME); 00502 else 00503 wcscpy(NameBuffer, DRIVER_ROOT_NAME); 00504 00505 RtlInitUnicodeString(&DriverName, NameBuffer); 00506 DriverName.MaximumLength = sizeof(NameBuffer); 00507 00508 RtlAppendUnicodeStringToString(&DriverName, ServiceName); 00509 00510 DPRINT("Driver name: '%wZ'\n", &DriverName); 00511 } 00512 else 00513 DriverName.Length = 0; 00514 00515 Status = IopCreateDriver( 00516 DriverName.Length > 0 ? &DriverName : NULL, 00517 DriverEntry, 00518 &RegistryKey, 00519 ModuleObject, 00520 &Driver); 00521 RtlFreeUnicodeString(&RegistryKey); 00522 00523 *DriverObject = Driver; 00524 if (!NT_SUCCESS(Status)) 00525 { 00526 DPRINT("IopCreateDriver() failed (Status 0x%08lx)\n", Status); 00527 return Status; 00528 } 00529 00530 MmFreeDriverInitialization((PLDR_DATA_TABLE_ENTRY)Driver->DriverSection); 00531 00532 /* Set the driver as initialized */ 00533 IopReadyDeviceObjects(Driver); 00534 00535 if (PnpSystemInit) IopReinitializeDrivers(); 00536 00537 return STATUS_SUCCESS; 00538 } 00539 00540 /* 00541 * IopAttachFilterDriversCallback 00542 * 00543 * Internal routine used by IopAttachFilterDrivers. 00544 */ 00545 00546 NTSTATUS NTAPI 00547 IopAttachFilterDriversCallback( 00548 PWSTR ValueName, 00549 ULONG ValueType, 00550 PVOID ValueData, 00551 ULONG ValueLength, 00552 PVOID Context, 00553 PVOID EntryContext) 00554 { 00555 PDEVICE_NODE DeviceNode = Context; 00556 UNICODE_STRING ServiceName; 00557 PWCHAR Filters; 00558 PLDR_DATA_TABLE_ENTRY ModuleObject; 00559 PDRIVER_OBJECT DriverObject; 00560 NTSTATUS Status; 00561 00562 for (Filters = ValueData; 00563 ((ULONG_PTR)Filters - (ULONG_PTR)ValueData) < ValueLength && 00564 *Filters != 0; 00565 Filters += (ServiceName.Length / sizeof(WCHAR)) + 1) 00566 { 00567 DPRINT("Filter Driver: %S (%wZ)\n", Filters, &DeviceNode->InstancePath); 00568 00569 ServiceName.Buffer = Filters; 00570 ServiceName.MaximumLength = 00571 ServiceName.Length = (USHORT)wcslen(Filters) * sizeof(WCHAR); 00572 00573 Status = IopGetDriverObject(&DriverObject, 00574 &ServiceName, 00575 FALSE); 00576 if (!NT_SUCCESS(Status)) 00577 { 00578 /* Load and initialize the filter driver */ 00579 Status = IopLoadServiceModule(&ServiceName, &ModuleObject); 00580 if (!NT_SUCCESS(Status)) 00581 continue; 00582 00583 Status = IopInitializeDriverModule(DeviceNode, ModuleObject, &ServiceName, 00584 FALSE, &DriverObject); 00585 if (!NT_SUCCESS(Status)) 00586 continue; 00587 } 00588 00589 Status = IopInitializeDevice(DeviceNode, DriverObject); 00590 00591 /* Remove extra reference */ 00592 ObDereferenceObject(DriverObject); 00593 } 00594 00595 return STATUS_SUCCESS; 00596 } 00597 00598 /* 00599 * IopAttachFilterDrivers 00600 * 00601 * Load filter drivers for specified device node. 00602 * 00603 * Parameters 00604 * Lower 00605 * Set to TRUE for loading lower level filters or FALSE for upper 00606 * level filters. 00607 */ 00608 00609 NTSTATUS FASTCALL 00610 IopAttachFilterDrivers( 00611 PDEVICE_NODE DeviceNode, 00612 BOOLEAN Lower) 00613 { 00614 RTL_QUERY_REGISTRY_TABLE QueryTable[2] = { { NULL, 0, NULL, NULL, 0, NULL, 0 }, }; 00615 UNICODE_STRING Class; 00616 WCHAR ClassBuffer[40]; 00617 UNICODE_STRING EnumRoot = RTL_CONSTANT_STRING(ENUM_ROOT); 00618 HANDLE EnumRootKey, SubKey; 00619 NTSTATUS Status; 00620 00621 /* Open enumeration root key */ 00622 Status = IopOpenRegistryKeyEx(&EnumRootKey, NULL, 00623 &EnumRoot, KEY_READ); 00624 if (!NT_SUCCESS(Status)) 00625 { 00626 DPRINT1("ZwOpenKey() failed with Status %08X\n", Status); 00627 return Status; 00628 } 00629 00630 /* Open subkey */ 00631 Status = IopOpenRegistryKeyEx(&SubKey, EnumRootKey, 00632 &DeviceNode->InstancePath, KEY_READ); 00633 if (!NT_SUCCESS(Status)) 00634 { 00635 DPRINT1("ZwOpenKey() failed with Status %08X\n", Status); 00636 ZwClose(EnumRootKey); 00637 return Status; 00638 } 00639 00640 /* 00641 * First load the device filters 00642 */ 00643 QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback; 00644 if (Lower) 00645 QueryTable[0].Name = L"LowerFilters"; 00646 else 00647 QueryTable[0].Name = L"UpperFilters"; 00648 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED; 00649 00650 RtlQueryRegistryValues( 00651 RTL_REGISTRY_HANDLE, 00652 (PWSTR)SubKey, 00653 QueryTable, 00654 DeviceNode, 00655 NULL); 00656 00657 /* 00658 * Now get the class GUID 00659 */ 00660 Class.Length = 0; 00661 Class.MaximumLength = 40 * sizeof(WCHAR); 00662 Class.Buffer = ClassBuffer; 00663 QueryTable[0].QueryRoutine = NULL; 00664 QueryTable[0].Name = L"ClassGUID"; 00665 QueryTable[0].EntryContext = &Class; 00666 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT; 00667 00668 Status = RtlQueryRegistryValues( 00669 RTL_REGISTRY_HANDLE, 00670 (PWSTR)SubKey, 00671 QueryTable, 00672 DeviceNode, 00673 NULL); 00674 00675 /* Close handles */ 00676 ZwClose(SubKey); 00677 ZwClose(EnumRootKey); 00678 00679 /* 00680 * Load the class filter driver 00681 */ 00682 if (NT_SUCCESS(Status)) 00683 { 00684 UNICODE_STRING ControlClass = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class"); 00685 00686 Status = IopOpenRegistryKeyEx(&EnumRootKey, NULL, 00687 &ControlClass, KEY_READ); 00688 if (!NT_SUCCESS(Status)) 00689 { 00690 DPRINT1("ZwOpenKey() failed with Status %08X\n", Status); 00691 return Status; 00692 } 00693 00694 /* Open subkey */ 00695 Status = IopOpenRegistryKeyEx(&SubKey, EnumRootKey, 00696 &Class, KEY_READ); 00697 if (!NT_SUCCESS(Status)) 00698 { 00699 DPRINT1("ZwOpenKey() failed with Status %08X\n", Status); 00700 ZwClose(EnumRootKey); 00701 return Status; 00702 } 00703 00704 QueryTable[0].QueryRoutine = IopAttachFilterDriversCallback; 00705 if (Lower) 00706 QueryTable[0].Name = L"LowerFilters"; 00707 else 00708 QueryTable[0].Name = L"UpperFilters"; 00709 QueryTable[0].EntryContext = NULL; 00710 QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED; 00711 00712 RtlQueryRegistryValues( 00713 RTL_REGISTRY_HANDLE, 00714 (PWSTR)SubKey, 00715 QueryTable, 00716 DeviceNode, 00717 NULL); 00718 00719 /* Clean up */ 00720 ZwClose(SubKey); 00721 ZwClose(EnumRootKey); 00722 } 00723 00724 return STATUS_SUCCESS; 00725 } 00726 00727 NTSTATUS 00728 NTAPI 00729 MiResolveImageReferences(IN PVOID ImageBase, 00730 IN PUNICODE_STRING ImageFileDirectory, 00731 IN PUNICODE_STRING NamePrefix OPTIONAL, 00732 OUT PCHAR *MissingApi, 00733 OUT PWCHAR *MissingDriver, 00734 OUT PLOAD_IMPORTS *LoadImports); 00735 00736 // 00737 // Used for images already loaded (boot drivers) 00738 // 00739 NTSTATUS 00740 NTAPI 00741 INIT_FUNCTION 00742 LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry, 00743 PUNICODE_STRING FileName, 00744 PLDR_DATA_TABLE_ENTRY *ModuleObject) 00745 { 00746 NTSTATUS Status; 00747 UNICODE_STRING BaseName, BaseDirectory; 00748 PLOAD_IMPORTS LoadedImports = (PVOID)-2; 00749 PCHAR MissingApiName, Buffer; 00750 PWCHAR MissingDriverName; 00751 PVOID DriverBase = LdrEntry->DllBase; 00752 00753 /* Allocate a buffer we'll use for names */ 00754 Buffer = ExAllocatePoolWithTag(NonPagedPool, MAX_PATH, TAG_LDR_WSTR); 00755 if (!Buffer) 00756 { 00757 /* Fail */ 00758 return STATUS_INSUFFICIENT_RESOURCES; 00759 } 00760 00761 /* Check for a separator */ 00762 if (FileName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR) 00763 { 00764 PWCHAR p; 00765 ULONG BaseLength; 00766 00767 /* Loop the path until we get to the base name */ 00768 p = &FileName->Buffer[FileName->Length / sizeof(WCHAR)]; 00769 while (*(p - 1) != OBJ_NAME_PATH_SEPARATOR) p--; 00770 00771 /* Get the length */ 00772 BaseLength = (ULONG)(&FileName->Buffer[FileName->Length / sizeof(WCHAR)] - p); 00773 BaseLength *= sizeof(WCHAR); 00774 00775 /* Setup the string */ 00776 BaseName.Length = (USHORT)BaseLength; 00777 BaseName.Buffer = p; 00778 } 00779 else 00780 { 00781 /* Otherwise, we already have a base name */ 00782 BaseName.Length = FileName->Length; 00783 BaseName.Buffer = FileName->Buffer; 00784 } 00785 00786 /* Setup the maximum length */ 00787 BaseName.MaximumLength = BaseName.Length; 00788 00789 /* Now compute the base directory */ 00790 BaseDirectory = *FileName; 00791 BaseDirectory.Length -= BaseName.Length; 00792 BaseDirectory.MaximumLength = BaseDirectory.Length; 00793 00794 /* Resolve imports */ 00795 MissingApiName = Buffer; 00796 Status = MiResolveImageReferences(DriverBase, 00797 &BaseDirectory, 00798 NULL, 00799 &MissingApiName, 00800 &MissingDriverName, 00801 &LoadedImports); 00802 if (!NT_SUCCESS(Status)) return Status; 00803 00804 /* Return */ 00805 *ModuleObject = LdrEntry; 00806 return STATUS_SUCCESS; 00807 } 00808 00809 /* 00810 * IopInitializeBuiltinDriver 00811 * 00812 * Initialize a driver that is already loaded in memory. 00813 */ 00814 00815 NTSTATUS 00816 NTAPI 00817 INIT_FUNCTION 00818 IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY LdrEntry) 00819 { 00820 PDEVICE_NODE DeviceNode; 00821 PDRIVER_OBJECT DriverObject; 00822 NTSTATUS Status; 00823 PWCHAR FileNameWithoutPath; 00824 LPWSTR FileExtension; 00825 PUNICODE_STRING ModuleName = &LdrEntry->BaseDllName; 00826 UNICODE_STRING ServiceName; 00827 00828 /* 00829 * Display 'Loading XXX...' message 00830 */ 00831 IopDisplayLoadingMessage(ModuleName); 00832 InbvIndicateProgress(); 00833 00834 /* 00835 * Generate filename without path (not needed by freeldr) 00836 */ 00837 FileNameWithoutPath = wcsrchr(ModuleName->Buffer, L'\\'); 00838 if (FileNameWithoutPath == NULL) 00839 { 00840 FileNameWithoutPath = ModuleName->Buffer; 00841 } 00842 else 00843 { 00844 FileNameWithoutPath++; 00845 } 00846 00847 /* 00848 * Strip the file extension from ServiceName 00849 */ 00850 RtlCreateUnicodeString(&ServiceName, FileNameWithoutPath); 00851 FileExtension = wcsrchr(ServiceName.Buffer, '.'); 00852 if (FileExtension != NULL) 00853 { 00854 ServiceName.Length -= (USHORT)wcslen(FileExtension) * sizeof(WCHAR); 00855 FileExtension[0] = 0; 00856 } 00857 00858 /* 00859 * Determine the right device object 00860 */ 00861 /* Use IopRootDeviceNode for now */ 00862 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &ServiceName, &DeviceNode); 00863 if (!NT_SUCCESS(Status)) 00864 { 00865 DPRINT1("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status); 00866 return(Status); 00867 } 00868 00869 /* 00870 * Initialize the driver 00871 */ 00872 Status = IopInitializeDriverModule(DeviceNode, LdrEntry, 00873 &DeviceNode->ServiceName, FALSE, &DriverObject); 00874 00875 if (!NT_SUCCESS(Status)) 00876 { 00877 IopFreeDeviceNode(DeviceNode); 00878 return Status; 00879 } 00880 00881 Status = IopInitializeDevice(DeviceNode, DriverObject); 00882 if (NT_SUCCESS(Status)) 00883 { 00884 Status = IopStartDevice(DeviceNode); 00885 } 00886 00887 /* Remove extra reference from IopInitializeDriverModule */ 00888 ObDereferenceObject(DriverObject); 00889 00890 return Status; 00891 } 00892 00893 /* 00894 * IopInitializeBootDrivers 00895 * 00896 * Initialize boot drivers and free memory for boot files. 00897 * 00898 * Parameters 00899 * None 00900 * 00901 * Return Value 00902 * None 00903 */ 00904 VOID 00905 FASTCALL 00906 INIT_FUNCTION 00907 IopInitializeBootDrivers(VOID) 00908 { 00909 PLIST_ENTRY ListHead, NextEntry, NextEntry2; 00910 PLDR_DATA_TABLE_ENTRY LdrEntry; 00911 PDEVICE_NODE DeviceNode; 00912 PDRIVER_OBJECT DriverObject; 00913 LDR_DATA_TABLE_ENTRY ModuleObject; 00914 NTSTATUS Status; 00915 UNICODE_STRING DriverName; 00916 ULONG i, Index; 00917 PDRIVER_INFORMATION DriverInfo, DriverInfoTag; 00918 HANDLE KeyHandle; 00919 PBOOT_DRIVER_LIST_ENTRY BootEntry; 00920 DPRINT("IopInitializeBootDrivers()\n"); 00921 00922 /* Use IopRootDeviceNode for now */ 00923 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, NULL, &DeviceNode); 00924 if (!NT_SUCCESS(Status)) return; 00925 00926 /* Setup the module object for the RAW FS Driver */ 00927 ModuleObject.DllBase = NULL; 00928 ModuleObject.SizeOfImage = 0; 00929 ModuleObject.EntryPoint = RawFsDriverEntry; 00930 RtlInitUnicodeString(&DriverName, L"RAW"); 00931 00932 /* Initialize it */ 00933 Status = IopInitializeDriverModule(DeviceNode, 00934 &ModuleObject, 00935 &DriverName, 00936 TRUE, 00937 &DriverObject); 00938 if (!NT_SUCCESS(Status)) 00939 { 00940 /* Fail */ 00941 IopFreeDeviceNode(DeviceNode); 00942 return; 00943 } 00944 00945 /* Now initialize the associated device */ 00946 Status = IopInitializeDevice(DeviceNode, DriverObject); 00947 if (!NT_SUCCESS(Status)) 00948 { 00949 /* Fail */ 00950 IopFreeDeviceNode(DeviceNode); 00951 ObDereferenceObject(DriverObject); 00952 return; 00953 } 00954 00955 /* Start it up */ 00956 Status = IopStartDevice(DeviceNode); 00957 if (!NT_SUCCESS(Status)) 00958 { 00959 /* Fail */ 00960 IopFreeDeviceNode(DeviceNode); 00961 ObDereferenceObject(DriverObject); 00962 return; 00963 } 00964 00965 /* Get highest group order index */ 00966 IopGroupIndex = PpInitGetGroupOrderIndex(NULL); 00967 if (IopGroupIndex == 0xFFFF) ASSERT(FALSE); 00968 00969 /* Allocate the group table */ 00970 IopGroupTable = ExAllocatePoolWithTag(PagedPool, 00971 IopGroupIndex * sizeof(LIST_ENTRY), 00972 TAG_IO); 00973 if (IopGroupTable == NULL) ASSERT(FALSE); 00974 00975 /* Initialize the group table lists */ 00976 for (i = 0; i < IopGroupIndex; i++) InitializeListHead(&IopGroupTable[i]); 00977 00978 /* Loop the boot modules */ 00979 ListHead = &KeLoaderBlock->LoadOrderListHead; 00980 NextEntry = ListHead->Flink; 00981 while (ListHead != NextEntry) 00982 { 00983 /* Get the entry */ 00984 LdrEntry = CONTAINING_RECORD(NextEntry, 00985 LDR_DATA_TABLE_ENTRY, 00986 InLoadOrderLinks); 00987 00988 /* Check if the DLL needs to be initialized */ 00989 if (LdrEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL) 00990 { 00991 /* Call its entrypoint */ 00992 MmCallDllInitialize(LdrEntry, NULL); 00993 } 00994 00995 /* Go to the next driver */ 00996 NextEntry = NextEntry->Flink; 00997 } 00998 00999 /* Loop the boot drivers */ 01000 ListHead = &KeLoaderBlock->BootDriverListHead; 01001 NextEntry = ListHead->Flink; 01002 while (ListHead != NextEntry) 01003 { 01004 /* Get the entry */ 01005 BootEntry = CONTAINING_RECORD(NextEntry, 01006 BOOT_DRIVER_LIST_ENTRY, 01007 Link); 01008 01009 /* Get the driver loader entry */ 01010 LdrEntry = BootEntry->LdrEntry; 01011 01012 /* Allocate our internal accounting structure */ 01013 DriverInfo = ExAllocatePoolWithTag(PagedPool, 01014 sizeof(DRIVER_INFORMATION), 01015 TAG_IO); 01016 if (DriverInfo) 01017 { 01018 /* Zero it and initialize it */ 01019 RtlZeroMemory(DriverInfo, sizeof(DRIVER_INFORMATION)); 01020 InitializeListHead(&DriverInfo->Link); 01021 DriverInfo->DataTableEntry = BootEntry; 01022 01023 /* Open the registry key */ 01024 Status = IopOpenRegistryKeyEx(&KeyHandle, 01025 NULL, 01026 &BootEntry->RegistryPath, 01027 KEY_READ); 01028 if ((NT_SUCCESS(Status)) || /* ReactOS HACK for SETUPLDR */ 01029 ((KeLoaderBlock->SetupLdrBlock) && ((KeyHandle = (PVOID)1)))) // yes, it's an assignment! 01030 { 01031 /* Save the handle */ 01032 DriverInfo->ServiceHandle = KeyHandle; 01033 01034 /* Get the group oder index */ 01035 Index = PpInitGetGroupOrderIndex(KeyHandle); 01036 01037 /* Get the tag position */ 01038 DriverInfo->TagPosition = PipGetDriverTagPriority(KeyHandle); 01039 01040 /* Insert it into the list, at the right place */ 01041 ASSERT(Index < IopGroupIndex); 01042 NextEntry2 = IopGroupTable[Index].Flink; 01043 while (NextEntry2 != &IopGroupTable[Index]) 01044 { 01045 /* Get the driver info */ 01046 DriverInfoTag = CONTAINING_RECORD(NextEntry2, 01047 DRIVER_INFORMATION, 01048 Link); 01049 01050 /* Check if we found the right tag position */ 01051 if (DriverInfoTag->TagPosition > DriverInfo->TagPosition) 01052 { 01053 /* We're done */ 01054 break; 01055 } 01056 01057 /* Next entry */ 01058 NextEntry2 = NextEntry2->Flink; 01059 } 01060 01061 /* Insert us right before the next entry */ 01062 NextEntry2 = NextEntry2->Blink; 01063 InsertHeadList(NextEntry2, &DriverInfo->Link); 01064 } 01065 } 01066 01067 /* Go to the next driver */ 01068 NextEntry = NextEntry->Flink; 01069 } 01070 01071 /* Loop each group index */ 01072 for (i = 0; i < IopGroupIndex; i++) 01073 { 01074 /* Loop each group table */ 01075 NextEntry = IopGroupTable[i].Flink; 01076 while (NextEntry != &IopGroupTable[i]) 01077 { 01078 /* Get the entry */ 01079 DriverInfo = CONTAINING_RECORD(NextEntry, 01080 DRIVER_INFORMATION, 01081 Link); 01082 01083 /* Get the driver loader entry */ 01084 LdrEntry = DriverInfo->DataTableEntry->LdrEntry; 01085 01086 /* Initialize it */ 01087 IopInitializeBuiltinDriver(LdrEntry); 01088 01089 /* Next entry */ 01090 NextEntry = NextEntry->Flink; 01091 } 01092 } 01093 01094 /* In old ROS, the loader list became empty after this point. Simulate. */ 01095 InitializeListHead(&KeLoaderBlock->LoadOrderListHead); 01096 } 01097 01098 VOID 01099 FASTCALL 01100 INIT_FUNCTION 01101 IopInitializeSystemDrivers(VOID) 01102 { 01103 PUNICODE_STRING *DriverList, *SavedList; 01104 01105 /* No system drivers on the boot cd */ 01106 if (KeLoaderBlock->SetupLdrBlock) return; 01107 01108 /* Get the driver list */ 01109 SavedList = DriverList = CmGetSystemDriverList(); 01110 ASSERT(DriverList); 01111 01112 /* Loop it */ 01113 while (*DriverList) 01114 { 01115 /* Load the driver */ 01116 ZwLoadDriver(*DriverList); 01117 01118 /* Free the entry */ 01119 RtlFreeUnicodeString(*DriverList); 01120 ExFreePool(*DriverList); 01121 01122 /* Next entry */ 01123 InbvIndicateProgress(); 01124 DriverList++; 01125 } 01126 01127 /* Free the list */ 01128 ExFreePool(SavedList); 01129 } 01130 01131 /* 01132 * IopUnloadDriver 01133 * 01134 * Unloads a device driver. 01135 * 01136 * Parameters 01137 * DriverServiceName 01138 * Name of the service to unload (registry key). 01139 * 01140 * UnloadPnpDrivers 01141 * Whether to unload Plug & Plug or only legacy drivers. If this 01142 * parameter is set to FALSE, the routine will unload only legacy 01143 * drivers. 01144 * 01145 * Return Value 01146 * Status 01147 * 01148 * To do 01149 * Guard the whole function by SEH. 01150 */ 01151 01152 NTSTATUS NTAPI 01153 IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers) 01154 { 01155 RTL_QUERY_REGISTRY_TABLE QueryTable[2]; 01156 UNICODE_STRING ImagePath; 01157 UNICODE_STRING ServiceName; 01158 UNICODE_STRING ObjectName; 01159 PDRIVER_OBJECT DriverObject; 01160 PDEVICE_OBJECT DeviceObject; 01161 PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; 01162 LOAD_UNLOAD_PARAMS LoadParams; 01163 NTSTATUS Status; 01164 LPWSTR Start; 01165 BOOLEAN SafeToUnload = TRUE; 01166 01167 DPRINT("IopUnloadDriver('%wZ', %d)\n", DriverServiceName, UnloadPnpDrivers); 01168 01169 PAGED_CODE(); 01170 01171 /* 01172 * Get the service name from the registry key name 01173 */ 01174 01175 Start = wcsrchr(DriverServiceName->Buffer, L'\\'); 01176 if (Start == NULL) 01177 Start = DriverServiceName->Buffer; 01178 else 01179 Start++; 01180 01181 RtlInitUnicodeString(&ServiceName, Start); 01182 01183 /* 01184 * Construct the driver object name 01185 */ 01186 01187 ObjectName.Length = ((USHORT)wcslen(Start) + 8) * sizeof(WCHAR); 01188 ObjectName.MaximumLength = ObjectName.Length + sizeof(WCHAR); 01189 ObjectName.Buffer = ExAllocatePool(PagedPool, ObjectName.MaximumLength); 01190 if (!ObjectName.Buffer) return STATUS_INSUFFICIENT_RESOURCES; 01191 wcscpy(ObjectName.Buffer, L"\\Driver\\"); 01192 memcpy(ObjectName.Buffer + 8, Start, ObjectName.Length - 8 * sizeof(WCHAR)); 01193 ObjectName.Buffer[ObjectName.Length/sizeof(WCHAR)] = 0; 01194 01195 /* 01196 * Find the driver object 01197 */ 01198 Status = ObReferenceObjectByName(&ObjectName, 01199 0, 01200 0, 01201 0, 01202 IoDriverObjectType, 01203 KernelMode, 01204 0, 01205 (PVOID*)&DriverObject); 01206 01207 if (!NT_SUCCESS(Status)) 01208 { 01209 DPRINT1("Can't locate driver object for %wZ\n", &ObjectName); 01210 ExFreePool(ObjectName.Buffer); 01211 return Status; 01212 } 01213 01214 /* 01215 * Free the buffer for driver object name 01216 */ 01217 ExFreePool(ObjectName.Buffer); 01218 01219 /* Check that driver is not already unloading */ 01220 if (DriverObject->Flags & DRVO_UNLOAD_INVOKED) 01221 { 01222 DPRINT1("Driver deletion pending\n"); 01223 ObDereferenceObject(DriverObject); 01224 return STATUS_DELETE_PENDING; 01225 } 01226 01227 /* 01228 * Get path of service... 01229 */ 01230 01231 RtlZeroMemory(QueryTable, sizeof(QueryTable)); 01232 01233 RtlInitUnicodeString(&ImagePath, NULL); 01234 01235 QueryTable[0].Name = L"ImagePath"; 01236 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; 01237 QueryTable[0].EntryContext = &ImagePath; 01238 01239 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, 01240 DriverServiceName->Buffer, QueryTable, NULL, NULL); 01241 01242 if (!NT_SUCCESS(Status)) 01243 { 01244 DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status); 01245 ObDereferenceObject(DriverObject); 01246 return Status; 01247 } 01248 01249 /* 01250 * Normalize the image path for all later processing. 01251 */ 01252 01253 Status = IopNormalizeImagePath(&ImagePath, &ServiceName); 01254 01255 if (!NT_SUCCESS(Status)) 01256 { 01257 DPRINT1("IopNormalizeImagePath() failed (Status %x)\n", Status); 01258 ObDereferenceObject(DriverObject); 01259 return Status; 01260 } 01261 01262 /* 01263 * Free the service path 01264 */ 01265 01266 ExFreePool(ImagePath.Buffer); 01267 01268 /* 01269 * Unload the module and release the references to the device object 01270 */ 01271 01272 /* Call the load/unload routine, depending on current process */ 01273 if (DriverObject->DriverUnload && DriverObject->DriverSection && 01274 (UnloadPnpDrivers || (DriverObject->Flags & DRVO_LEGACY_DRIVER))) 01275 { 01276 /* Loop through each device object of the driver 01277 and set DOE_UNLOAD_PENDING flag */ 01278 DeviceObject = DriverObject->DeviceObject; 01279 while (DeviceObject) 01280 { 01281 /* Set the unload pending flag for the device */ 01282 DeviceExtension = IoGetDevObjExtension(DeviceObject); 01283 DeviceExtension->ExtensionFlags |= DOE_UNLOAD_PENDING; 01284 01285 /* Make sure there are no attached devices or no reference counts */ 01286 if ((DeviceObject->ReferenceCount) || (DeviceObject->AttachedDevice)) 01287 { 01288 /* Not safe to unload */ 01289 DPRINT1("Drivers device object is referenced or has attached devices\n"); 01290 01291 SafeToUnload = FALSE; 01292 } 01293 01294 DeviceObject = DeviceObject->NextDevice; 01295 } 01296 01297 /* If not safe to unload, then return success */ 01298 if (!SafeToUnload) 01299 { 01300 ObDereferenceObject(DriverObject); 01301 return STATUS_SUCCESS; 01302 } 01303 01304 DPRINT1("Unloading driver '%wZ' (manual)\n", &DriverObject->DriverName); 01305 01306 /* Set the unload invoked flag */ 01307 DriverObject->Flags |= DRVO_UNLOAD_INVOKED; 01308 01309 if (PsGetCurrentProcess() == PsInitialSystemProcess) 01310 { 01311 /* Just call right away */ 01312 (*DriverObject->DriverUnload)(DriverObject); 01313 } 01314 else 01315 { 01316 /* Load/Unload must be called from system process */ 01317 01318 /* Prepare parameters block */ 01319 LoadParams.DriverObject = DriverObject; 01320 KeInitializeEvent(&LoadParams.Event, NotificationEvent, FALSE); 01321 01322 ExInitializeWorkItem(&LoadParams.WorkItem, 01323 (PWORKER_THREAD_ROUTINE)IopLoadUnloadDriver, 01324 (PVOID)&LoadParams); 01325 01326 /* Queue it */ 01327 ExQueueWorkItem(&LoadParams.WorkItem, DelayedWorkQueue); 01328 01329 /* And wait when it completes */ 01330 KeWaitForSingleObject(&LoadParams.Event, UserRequest, KernelMode, 01331 FALSE, NULL); 01332 } 01333 01334 /* Mark the driver object temporary, so it could be deleted later */ 01335 ObMakeTemporaryObject(DriverObject); 01336 01337 /* Dereference it 2 times */ 01338 ObDereferenceObject(DriverObject); 01339 ObDereferenceObject(DriverObject); 01340 01341 return STATUS_SUCCESS; 01342 } 01343 else 01344 { 01345 DPRINT1("No DriverUnload function! '%wZ' will not be unloaded!\n", &DriverObject->DriverName); 01346 01347 /* Dereference one time (refd inside this function) */ 01348 ObDereferenceObject(DriverObject); 01349 01350 /* Return unloading failure */ 01351 return STATUS_INVALID_DEVICE_REQUEST; 01352 } 01353 } 01354 01355 VOID 01356 NTAPI 01357 IopReinitializeDrivers(VOID) 01358 { 01359 PDRIVER_REINIT_ITEM ReinitItem; 01360 PLIST_ENTRY Entry; 01361 01362 /* Get the first entry and start looping */ 01363 Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead, 01364 &DriverReinitListLock); 01365 while (Entry) 01366 { 01367 /* Get the item*/ 01368 ReinitItem = CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry); 01369 01370 /* Increment reinitialization counter */ 01371 ReinitItem->DriverObject->DriverExtension->Count++; 01372 01373 /* Remove the device object flag */ 01374 ReinitItem->DriverObject->Flags &= ~DRVO_REINIT_REGISTERED; 01375 01376 /* Call the routine */ 01377 ReinitItem->ReinitRoutine(ReinitItem->DriverObject, 01378 ReinitItem->Context, 01379 ReinitItem->DriverObject-> 01380 DriverExtension->Count); 01381 01382 /* Free the entry */ 01383 ExFreePool(Entry); 01384 01385 /* Move to the next one */ 01386 Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead, 01387 &DriverReinitListLock); 01388 } 01389 } 01390 01391 VOID 01392 NTAPI 01393 IopReinitializeBootDrivers(VOID) 01394 { 01395 PDRIVER_REINIT_ITEM ReinitItem; 01396 PLIST_ENTRY Entry; 01397 01398 /* Get the first entry and start looping */ 01399 Entry = ExInterlockedRemoveHeadList(&DriverBootReinitListHead, 01400 &DriverBootReinitListLock); 01401 while (Entry) 01402 { 01403 /* Get the item*/ 01404 ReinitItem = CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry); 01405 01406 /* Increment reinitialization counter */ 01407 ReinitItem->DriverObject->DriverExtension->Count++; 01408 01409 /* Remove the device object flag */ 01410 ReinitItem->DriverObject->Flags &= ~DRVO_BOOTREINIT_REGISTERED; 01411 01412 /* Call the routine */ 01413 ReinitItem->ReinitRoutine(ReinitItem->DriverObject, 01414 ReinitItem->Context, 01415 ReinitItem->DriverObject-> 01416 DriverExtension->Count); 01417 01418 /* Free the entry */ 01419 ExFreePool(Entry); 01420 01421 /* Move to the next one */ 01422 Entry = ExInterlockedRemoveHeadList(&DriverBootReinitListHead, 01423 &DriverBootReinitListLock); 01424 } 01425 } 01426 01427 NTSTATUS 01428 NTAPI 01429 IopCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL, 01430 IN PDRIVER_INITIALIZE InitializationFunction, 01431 IN PUNICODE_STRING RegistryPath, 01432 PLDR_DATA_TABLE_ENTRY ModuleObject, 01433 OUT PDRIVER_OBJECT *pDriverObject) 01434 { 01435 WCHAR NameBuffer[100]; 01436 USHORT NameLength; 01437 UNICODE_STRING LocalDriverName; 01438 NTSTATUS Status; 01439 OBJECT_ATTRIBUTES ObjectAttributes; 01440 ULONG ObjectSize; 01441 PDRIVER_OBJECT DriverObject; 01442 UNICODE_STRING ServiceKeyName; 01443 HANDLE hDriver; 01444 ULONG i, RetryCount = 0; 01445 01446 try_again: 01447 /* First, create a unique name for the driver if we don't have one */ 01448 if (!DriverName) 01449 { 01450 /* Create a random name and set up the string*/ 01451 NameLength = (USHORT)swprintf(NameBuffer, 01452 L"\\Driver\\%08u", 01453 KeTickCount); 01454 LocalDriverName.Length = NameLength * sizeof(WCHAR); 01455 LocalDriverName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL); 01456 LocalDriverName.Buffer = NameBuffer; 01457 } 01458 else 01459 { 01460 /* So we can avoid another code path, use a local var */ 01461 LocalDriverName = *DriverName; 01462 } 01463 01464 /* Initialize the Attributes */ 01465 ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(EXTENDED_DRIVER_EXTENSION); 01466 InitializeObjectAttributes(&ObjectAttributes, 01467 &LocalDriverName, 01468 OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, 01469 NULL, 01470 NULL); 01471 01472 /* Create the Object */ 01473 Status = ObCreateObject(KernelMode, 01474 IoDriverObjectType, 01475 &ObjectAttributes, 01476 KernelMode, 01477 NULL, 01478 ObjectSize, 01479 0, 01480 0, 01481 (PVOID*)&DriverObject); 01482 if (!NT_SUCCESS(Status)) return Status; 01483 01484 DPRINT("IopCreateDriver(): created DO %p\n", DriverObject); 01485 01486 /* Set up the Object */ 01487 RtlZeroMemory(DriverObject, ObjectSize); 01488 DriverObject->Type = IO_TYPE_DRIVER; 01489 DriverObject->Size = sizeof(DRIVER_OBJECT); 01490 DriverObject->Flags = DRVO_LEGACY_DRIVER; 01491 DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1); 01492 DriverObject->DriverExtension->DriverObject = DriverObject; 01493 DriverObject->DriverInit = InitializationFunction; 01494 DriverObject->DriverSection = ModuleObject; 01495 /* Loop all Major Functions */ 01496 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) 01497 { 01498 /* Invalidate each function */ 01499 DriverObject->MajorFunction[i] = IopInvalidDeviceRequest; 01500 } 01501 01502 /* Set up the service key name buffer */ 01503 ServiceKeyName.Buffer = ExAllocatePoolWithTag(PagedPool, 01504 LocalDriverName.Length + 01505 sizeof(WCHAR), 01506 TAG_IO); 01507 if (!ServiceKeyName.Buffer) 01508 { 01509 /* Fail */ 01510 ObMakeTemporaryObject(DriverObject); 01511 ObDereferenceObject(DriverObject); 01512 return STATUS_INSUFFICIENT_RESOURCES; 01513 } 01514 01515 /* Fill out the key data and copy the buffer */ 01516 ServiceKeyName.Length = LocalDriverName.Length; 01517 ServiceKeyName.MaximumLength = LocalDriverName.MaximumLength; 01518 RtlCopyMemory(ServiceKeyName.Buffer, 01519 LocalDriverName.Buffer, 01520 LocalDriverName.Length); 01521 01522 /* Null-terminate it and set it */ 01523 ServiceKeyName.Buffer[ServiceKeyName.Length / sizeof(WCHAR)] = UNICODE_NULL; 01524 DriverObject->DriverExtension->ServiceKeyName = ServiceKeyName; 01525 01526 /* Also store it in the Driver Object. This is a bit of a hack. */ 01527 RtlCopyMemory(&DriverObject->DriverName, 01528 &ServiceKeyName, 01529 sizeof(UNICODE_STRING)); 01530 01531 /* Add the Object and get its handle */ 01532 Status = ObInsertObject(DriverObject, 01533 NULL, 01534 FILE_READ_DATA, 01535 0, 01536 NULL, 01537 &hDriver); 01538 01539 /* Eliminate small possibility when this function is called more than 01540 once in a row, and KeTickCount doesn't get enough time to change */ 01541 if (!DriverName && (Status == STATUS_OBJECT_NAME_COLLISION) && (RetryCount < 100)) 01542 { 01543 RetryCount++; 01544 goto try_again; 01545 } 01546 01547 if (!NT_SUCCESS(Status)) return Status; 01548 01549 /* Now reference it */ 01550 Status = ObReferenceObjectByHandle(hDriver, 01551 0, 01552 IoDriverObjectType, 01553 KernelMode, 01554 (PVOID*)&DriverObject, 01555 NULL); 01556 01557 /* Close the extra handle */ 01558 ZwClose(hDriver); 01559 01560 if (!NT_SUCCESS(Status)) 01561 { 01562 /* Fail */ 01563 ObMakeTemporaryObject(DriverObject); 01564 ObDereferenceObject(DriverObject); 01565 return Status; 01566 } 01567 01568 DriverObject->HardwareDatabase = &IopHardwareDatabaseKey; 01569 DriverObject->DriverStart = ModuleObject ? ModuleObject->DllBase : 0; 01570 DriverObject->DriverSize = ModuleObject ? ModuleObject->SizeOfImage : 0; 01571 01572 /* Finally, call its init function */ 01573 DPRINT("RegistryKey: %wZ\n", RegistryPath); 01574 DPRINT("Calling driver entrypoint at %p\n", InitializationFunction); 01575 Status = (*InitializationFunction)(DriverObject, RegistryPath); 01576 if (!NT_SUCCESS(Status)) 01577 { 01578 /* If it didn't work, then kill the object */ 01579 DPRINT1("'%wZ' initialization failed, status (0x%08lx)\n", DriverName, Status); 01580 DriverObject->DriverSection = NULL; 01581 ObMakeTemporaryObject(DriverObject); 01582 ObDereferenceObject(DriverObject); 01583 return Status; 01584 } 01585 else 01586 { 01587 /* Returns to caller the object */ 01588 *pDriverObject = DriverObject; 01589 } 01590 01591 /* We're going to say if we don't have any DOs from DriverEntry, then we're not legacy. 01592 * Other parts of the I/O manager depend on this behavior */ 01593 if (!DriverObject->DeviceObject) DriverObject->Flags &= ~DRVO_LEGACY_DRIVER; 01594 01595 /* Loop all Major Functions */ 01596 for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) 01597 { 01598 /* 01599 * Make sure the driver didn't set any dispatch entry point to NULL! 01600 * Doing so is illegal; drivers shouldn't touch entry points they 01601 * do not implement. 01602 */ 01603 01604 /* Check if it did so anyway */ 01605 if (!DriverObject->MajorFunction[i]) 01606 { 01607 /* Print a warning in the debug log */ 01608 DPRINT1("Driver <%wZ> set DriverObject->MajorFunction[%d] to NULL!\n", 01609 &DriverObject->DriverName, i); 01610 01611 /* Fix it up */ 01612 DriverObject->MajorFunction[i] = IopInvalidDeviceRequest; 01613 } 01614 } 01615 01616 /* Return the Status */ 01617 return Status; 01618 } 01619 01620 /* PUBLIC FUNCTIONS ***********************************************************/ 01621 01622 /* 01623 * @implemented 01624 */ 01625 NTSTATUS 01626 NTAPI 01627 IoCreateDriver(IN PUNICODE_STRING DriverName OPTIONAL, 01628 IN PDRIVER_INITIALIZE InitializationFunction) 01629 { 01630 PDRIVER_OBJECT DriverObject; 01631 return IopCreateDriver(DriverName, InitializationFunction, NULL, NULL, &DriverObject); 01632 } 01633 01634 /* 01635 * @implemented 01636 */ 01637 VOID 01638 NTAPI 01639 IoDeleteDriver(IN PDRIVER_OBJECT DriverObject) 01640 { 01641 /* Simply dereference the Object */ 01642 ObDereferenceObject(DriverObject); 01643 } 01644 01645 /* 01646 * @implemented 01647 */ 01648 VOID 01649 NTAPI 01650 IoRegisterBootDriverReinitialization(IN PDRIVER_OBJECT DriverObject, 01651 IN PDRIVER_REINITIALIZE ReinitRoutine, 01652 IN PVOID Context) 01653 { 01654 PDRIVER_REINIT_ITEM ReinitItem; 01655 01656 /* Allocate the entry */ 01657 ReinitItem = ExAllocatePoolWithTag(NonPagedPool, 01658 sizeof(DRIVER_REINIT_ITEM), 01659 TAG_REINIT); 01660 if (!ReinitItem) return; 01661 01662 /* Fill it out */ 01663 ReinitItem->DriverObject = DriverObject; 01664 ReinitItem->ReinitRoutine = ReinitRoutine; 01665 ReinitItem->Context = Context; 01666 01667 /* Set the Driver Object flag and insert the entry into the list */ 01668 DriverObject->Flags |= DRVO_BOOTREINIT_REGISTERED; 01669 ExInterlockedInsertTailList(&DriverBootReinitListHead, 01670 &ReinitItem->ItemEntry, 01671 &DriverBootReinitListLock); 01672 } 01673 01674 /* 01675 * @implemented 01676 */ 01677 VOID 01678 NTAPI 01679 IoRegisterDriverReinitialization(IN PDRIVER_OBJECT DriverObject, 01680 IN PDRIVER_REINITIALIZE ReinitRoutine, 01681 IN PVOID Context) 01682 { 01683 PDRIVER_REINIT_ITEM ReinitItem; 01684 01685 /* Allocate the entry */ 01686 ReinitItem = ExAllocatePoolWithTag(NonPagedPool, 01687 sizeof(DRIVER_REINIT_ITEM), 01688 TAG_REINIT); 01689 if (!ReinitItem) return; 01690 01691 /* Fill it out */ 01692 ReinitItem->DriverObject = DriverObject; 01693 ReinitItem->ReinitRoutine = ReinitRoutine; 01694 ReinitItem->Context = Context; 01695 01696 /* Set the Driver Object flag and insert the entry into the list */ 01697 DriverObject->Flags |= DRVO_REINIT_REGISTERED; 01698 ExInterlockedInsertTailList(&DriverReinitListHead, 01699 &ReinitItem->ItemEntry, 01700 &DriverReinitListLock); 01701 } 01702 01703 /* 01704 * @implemented 01705 */ 01706 NTSTATUS 01707 NTAPI 01708 IoAllocateDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, 01709 IN PVOID ClientIdentificationAddress, 01710 IN ULONG DriverObjectExtensionSize, 01711 OUT PVOID *DriverObjectExtension) 01712 { 01713 KIRQL OldIrql; 01714 PIO_CLIENT_EXTENSION DriverExtensions, NewDriverExtension; 01715 BOOLEAN Inserted = FALSE; 01716 01717 /* Assume failure */ 01718 *DriverObjectExtension = NULL; 01719 01720 /* Allocate the extension */ 01721 NewDriverExtension = ExAllocatePoolWithTag(NonPagedPool, 01722 sizeof(IO_CLIENT_EXTENSION) + 01723 DriverObjectExtensionSize, 01724 TAG_DRIVER_EXTENSION); 01725 if (!NewDriverExtension) return STATUS_INSUFFICIENT_RESOURCES; 01726 01727 /* Clear the extension for teh caller */ 01728 RtlZeroMemory(NewDriverExtension, 01729 sizeof(IO_CLIENT_EXTENSION) + DriverObjectExtensionSize); 01730 01731 /* Acqure lock */ 01732 OldIrql = KeRaiseIrqlToDpcLevel(); 01733 01734 /* Fill out the extension */ 01735 NewDriverExtension->ClientIdentificationAddress = ClientIdentificationAddress; 01736 01737 /* Loop the current extensions */ 01738 DriverExtensions = IoGetDrvObjExtension(DriverObject)-> 01739 ClientDriverExtension; 01740 while (DriverExtensions) 01741 { 01742 /* Check if the identifier matches */ 01743 if (DriverExtensions->ClientIdentificationAddress == 01744 ClientIdentificationAddress) 01745 { 01746 /* We have a collision, break out */ 01747 break; 01748 } 01749 01750 /* Go to the next one */ 01751 DriverExtensions = DriverExtensions->NextExtension; 01752 } 01753 01754 /* Check if we didn't collide */ 01755 if (!DriverExtensions) 01756 { 01757 /* Link this one in */ 01758 NewDriverExtension->NextExtension = 01759 IoGetDrvObjExtension(DriverObject)->ClientDriverExtension; 01760 IoGetDrvObjExtension(DriverObject)->ClientDriverExtension = 01761 NewDriverExtension; 01762 Inserted = TRUE; 01763 } 01764 01765 /* Release the lock */ 01766 KeLowerIrql(OldIrql); 01767 01768 /* Check if insertion failed */ 01769 if (!Inserted) 01770 { 01771 /* Free the entry and fail */ 01772 ExFreePool(NewDriverExtension); 01773 return STATUS_OBJECT_NAME_COLLISION; 01774 } 01775 01776 /* Otherwise, return the pointer */ 01777 *DriverObjectExtension = NewDriverExtension + 1; 01778 return STATUS_SUCCESS; 01779 } 01780 01781 /* 01782 * @implemented 01783 */ 01784 PVOID 01785 NTAPI 01786 IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, 01787 IN PVOID ClientIdentificationAddress) 01788 { 01789 KIRQL OldIrql; 01790 PIO_CLIENT_EXTENSION DriverExtensions; 01791 01792 /* Acquire lock */ 01793 OldIrql = KeRaiseIrqlToDpcLevel(); 01794 01795 /* Loop the list until we find the right one */ 01796 DriverExtensions = IoGetDrvObjExtension(DriverObject)->ClientDriverExtension; 01797 while (DriverExtensions) 01798 { 01799 /* Check for a match */ 01800 if (DriverExtensions->ClientIdentificationAddress == 01801 ClientIdentificationAddress) 01802 { 01803 /* Break out */ 01804 break; 01805 } 01806 01807 /* Keep looping */ 01808 DriverExtensions = DriverExtensions->NextExtension; 01809 } 01810 01811 /* Release lock */ 01812 KeLowerIrql(OldIrql); 01813 01814 /* Return nothing or the extension */ 01815 if (!DriverExtensions) return NULL; 01816 return DriverExtensions + 1; 01817 } 01818 01819 VOID NTAPI 01820 IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams) 01821 { 01822 RTL_QUERY_REGISTRY_TABLE QueryTable[3]; 01823 UNICODE_STRING ImagePath; 01824 UNICODE_STRING ServiceName; 01825 NTSTATUS Status; 01826 ULONG Type; 01827 PDEVICE_NODE DeviceNode; 01828 PDRIVER_OBJECT DriverObject; 01829 PLDR_DATA_TABLE_ENTRY ModuleObject; 01830 PVOID BaseAddress; 01831 WCHAR *cur; 01832 01833 /* Check if it's an unload request */ 01834 if (LoadParams->DriverObject) 01835 { 01836 (*LoadParams->DriverObject->DriverUnload)(LoadParams->DriverObject); 01837 01838 /* Return success and signal the event */ 01839 LoadParams->Status = STATUS_SUCCESS; 01840 (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE); 01841 return; 01842 } 01843 01844 RtlInitUnicodeString(&ImagePath, NULL); 01845 01846 /* 01847 * Get the service name from the registry key name. 01848 */ 01849 ASSERT(LoadParams->ServiceName->Length >= sizeof(WCHAR)); 01850 01851 ServiceName = *LoadParams->ServiceName; 01852 cur = LoadParams->ServiceName->Buffer + 01853 (LoadParams->ServiceName->Length / sizeof(WCHAR)) - 1; 01854 while (LoadParams->ServiceName->Buffer != cur) 01855 { 01856 if(*cur == L'\\') 01857 { 01858 ServiceName.Buffer = cur + 1; 01859 ServiceName.Length = LoadParams->ServiceName->Length - 01860 (USHORT)((ULONG_PTR)ServiceName.Buffer - 01861 (ULONG_PTR)LoadParams->ServiceName->Buffer); 01862 break; 01863 } 01864 cur--; 01865 } 01866 01867 /* 01868 * Get service type. 01869 */ 01870 01871 RtlZeroMemory(&QueryTable, sizeof(QueryTable)); 01872 01873 RtlInitUnicodeString(&ImagePath, NULL); 01874 01875 QueryTable[0].Name = L"Type"; 01876 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; 01877 QueryTable[0].EntryContext = &Type; 01878 01879 QueryTable[1].Name = L"ImagePath"; 01880 QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT; 01881 QueryTable[1].EntryContext = &ImagePath; 01882 01883 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, 01884 LoadParams->ServiceName->Buffer, QueryTable, NULL, NULL); 01885 01886 if (!NT_SUCCESS(Status)) 01887 { 01888 DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status); 01889 if (ImagePath.Buffer) 01890 ExFreePool(ImagePath.Buffer); 01891 LoadParams->Status = Status; 01892 (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE); 01893 return; 01894 } 01895 01896 /* 01897 * Normalize the image path for all later processing. 01898 */ 01899 01900 Status = IopNormalizeImagePath(&ImagePath, &ServiceName); 01901 01902 if (!NT_SUCCESS(Status)) 01903 { 01904 DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status); 01905 LoadParams->Status = Status; 01906 (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE); 01907 return; 01908 } 01909 01910 DPRINT("FullImagePath: '%wZ'\n", &ImagePath); 01911 DPRINT("Type: %lx\n", Type); 01912 01913 /* Get existing DriverObject pointer (in case the driver has 01914 already been loaded and initialized) */ 01915 Status = IopGetDriverObject( 01916 &DriverObject, 01917 &ServiceName, 01918 (Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ || 01919 Type == 8 /* SERVICE_RECOGNIZER_DRIVER */)); 01920 01921 if (!NT_SUCCESS(Status)) 01922 { 01923 /* 01924 * Load the driver module 01925 */ 01926 01927 DPRINT("Loading module from %wZ\n", &ImagePath); 01928 Status = MmLoadSystemImage(&ImagePath, NULL, NULL, 0, (PVOID)&ModuleObject, &BaseAddress); 01929 01930 if (!NT_SUCCESS(Status)) 01931 { 01932 DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status); 01933 LoadParams->Status = Status; 01934 (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE); 01935 return; 01936 } 01937 01938 /* 01939 * Initialize the driver module if it's loaded for the first time 01940 */ 01941 Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &ServiceName, &DeviceNode); 01942 if (!NT_SUCCESS(Status)) 01943 { 01944 DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status); 01945 MmUnloadSystemImage(ModuleObject); 01946 LoadParams->Status = Status; 01947 (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE); 01948 return; 01949 } 01950 01951 IopDisplayLoadingMessage(&DeviceNode->ServiceName); 01952 01953 Status = IopInitializeDriverModule(DeviceNode, 01954 ModuleObject, 01955 &DeviceNode->ServiceName, 01956 (Type == 2 /* SERVICE_FILE_SYSTEM_DRIVER */ || 01957 Type == 8 /* SERVICE_RECOGNIZER_DRIVER */), 01958 &DriverObject); 01959 if (!NT_SUCCESS(Status)) 01960 { 01961 DPRINT1("IopInitializeDriver() failed (Status %lx)\n", Status); 01962 MmUnloadSystemImage(ModuleObject); 01963 IopFreeDeviceNode(DeviceNode); 01964 LoadParams->Status = Status; 01965 (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE); 01966 return; 01967 } 01968 01969 /* Initialize and start device */ 01970 IopInitializeDevice(DeviceNode, DriverObject); 01971 Status = IopStartDevice(DeviceNode); 01972 } 01973 else 01974 { 01975 DPRINT("DriverObject already exist in ObjectManager\n"); 01976 Status = STATUS_IMAGE_ALREADY_LOADED; 01977 01978 /* IopGetDriverObject references the DriverObject, so dereference it */ 01979 ObDereferenceObject(DriverObject); 01980 } 01981 01982 /* Pass status to the caller and signal the event */ 01983 LoadParams->Status = Status; 01984 (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE); 01985 } 01986 01987 /* 01988 * NtLoadDriver 01989 * 01990 * Loads a device driver. 01991 * 01992 * Parameters 01993 * DriverServiceName 01994 * Name of the service to load (registry key). 01995 * 01996 * Return Value 01997 * Status 01998 * 01999 * Status 02000 * implemented 02001 */ 02002 NTSTATUS NTAPI 02003 NtLoadDriver(IN PUNICODE_STRING DriverServiceName) 02004 { 02005 UNICODE_STRING CapturedDriverServiceName = { 0, 0, NULL }; 02006 KPROCESSOR_MODE PreviousMode; 02007 LOAD_UNLOAD_PARAMS LoadParams; 02008 NTSTATUS Status; 02009 02010 PAGED_CODE(); 02011 02012 PreviousMode = KeGetPreviousMode(); 02013 02014 /* 02015 * Check security privileges 02016 */ 02017 02018 /* FIXME: Uncomment when privileges will be correctly implemented. */ 02019 #if 0 02020 if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode)) 02021 { 02022 DPRINT("Privilege not held\n"); 02023 return STATUS_PRIVILEGE_NOT_HELD; 02024 } 02025 #endif 02026 02027 Status = ProbeAndCaptureUnicodeString(&CapturedDriverServiceName, 02028 PreviousMode, 02029 DriverServiceName); 02030 if (!NT_SUCCESS(Status)) 02031 { 02032 return Status; 02033 } 02034 02035 DPRINT("NtLoadDriver('%wZ')\n", &CapturedDriverServiceName); 02036 02037 LoadParams.ServiceName = &CapturedDriverServiceName; 02038 LoadParams.DriverObject = NULL; 02039 KeInitializeEvent(&LoadParams.Event, NotificationEvent, FALSE); 02040 02041 /* Call the load/unload routine, depending on current process */ 02042 if (PsGetCurrentProcess() == PsInitialSystemProcess) 02043 { 02044 /* Just call right away */ 02045 IopLoadUnloadDriver(&LoadParams); 02046 } 02047 else 02048 { 02049 /* Load/Unload must be called from system process */ 02050 ExInitializeWorkItem(&LoadParams.WorkItem, 02051 (PWORKER_THREAD_ROUTINE)IopLoadUnloadDriver, 02052 (PVOID)&LoadParams); 02053 02054 /* Queue it */ 02055 ExQueueWorkItem(&LoadParams.WorkItem, DelayedWorkQueue); 02056 02057 /* And wait when it completes */ 02058 KeWaitForSingleObject(&LoadParams.Event, UserRequest, KernelMode, 02059 FALSE, NULL); 02060 } 02061 02062 ReleaseCapturedUnicodeString(&CapturedDriverServiceName, 02063 PreviousMode); 02064 02065 return LoadParams.Status; 02066 } 02067 02068 /* 02069 * NtUnloadDriver 02070 * 02071 * Unloads a legacy device driver. 02072 * 02073 * Parameters 02074 * DriverServiceName 02075 * Name of the service to unload (registry key). 02076 * 02077 * Return Value 02078 * Status 02079 * 02080 * Status 02081 * implemented 02082 */ 02083 02084 NTSTATUS NTAPI 02085 NtUnloadDriver(IN PUNICODE_STRING DriverServiceName) 02086 { 02087 return IopUnloadDriver(DriverServiceName, FALSE); 02088 } 02089 02090 /* EOF */ Generated on Sat May 26 2012 04:17:43 for ReactOS by
1.7.6.1
|