1c2c66affSColin Finck /* 2c2c66affSColin Finck * PROJECT: ReactOS Kernel 3c2c66affSColin Finck * LICENSE: GPL - See COPYING in the top level directory 4c2c66affSColin Finck * FILE: ntoskrnl/io/iomgr/driver.c 5c2c66affSColin Finck * PURPOSE: Driver Object Management 6c2c66affSColin Finck * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7c2c66affSColin Finck * Filip Navara (navaraf@reactos.org) 8c2c66affSColin Finck * Herv� Poussineau (hpoussin@reactos.org) 9c2c66affSColin Finck */ 10c2c66affSColin Finck 11c2c66affSColin Finck /* INCLUDES *******************************************************************/ 12c2c66affSColin Finck 13c2c66affSColin Finck #include <ntoskrnl.h> 14c2c66affSColin Finck #define NDEBUG 15c2c66affSColin Finck #include <debug.h> 16c2c66affSColin Finck 17c2c66affSColin Finck /* GLOBALS ********************************************************************/ 18c2c66affSColin Finck 19c2c66affSColin Finck ERESOURCE IopDriverLoadResource; 20c2c66affSColin Finck 21c2c66affSColin Finck LIST_ENTRY DriverReinitListHead; 22c2c66affSColin Finck KSPIN_LOCK DriverReinitListLock; 23c2c66affSColin Finck PLIST_ENTRY DriverReinitTailEntry; 24c2c66affSColin Finck 25c2c66affSColin Finck PLIST_ENTRY DriverBootReinitTailEntry; 26c2c66affSColin Finck LIST_ENTRY DriverBootReinitListHead; 27c2c66affSColin Finck KSPIN_LOCK DriverBootReinitListLock; 28c2c66affSColin Finck 29c2c66affSColin Finck UNICODE_STRING IopHardwareDatabaseKey = 30c2c66affSColin Finck RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM"); 314c95339dSVictor Perevertkin static const WCHAR ServicesKeyName[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"; 32c2c66affSColin Finck 33c2c66affSColin Finck POBJECT_TYPE IoDriverObjectType = NULL; 34c2c66affSColin Finck 35c2c66affSColin Finck #define TAG_RTLREGISTRY 'vrqR' 36c2c66affSColin Finck 37c2c66affSColin Finck extern BOOLEAN ExpInTextModeSetup; 38c2c66affSColin Finck extern BOOLEAN PnpSystemInit; 392839c850SVictor Perevertkin extern BOOLEAN PnPBootDriversLoaded; 402839c850SVictor Perevertkin extern KEVENT PiEnumerationFinished; 41c2c66affSColin Finck 42c2c66affSColin Finck USHORT IopGroupIndex; 43c2c66affSColin Finck PLIST_ENTRY IopGroupTable; 44c2c66affSColin Finck 45a6a3aa0fSVictor Perevertkin /* TYPES *********************************************************************/ 46a6a3aa0fSVictor Perevertkin 47a6a3aa0fSVictor Perevertkin // Parameters packet for Load/Unload work item's context 48a6a3aa0fSVictor Perevertkin typedef struct _LOAD_UNLOAD_PARAMS 49a6a3aa0fSVictor Perevertkin { 50a6a3aa0fSVictor Perevertkin NTSTATUS Status; 514c95339dSVictor Perevertkin PUNICODE_STRING RegistryPath; 52a6a3aa0fSVictor Perevertkin WORK_QUEUE_ITEM WorkItem; 53a6a3aa0fSVictor Perevertkin KEVENT Event; 54a6a3aa0fSVictor Perevertkin PDRIVER_OBJECT DriverObject; 55a6a3aa0fSVictor Perevertkin BOOLEAN SetEvent; 56a6a3aa0fSVictor Perevertkin } LOAD_UNLOAD_PARAMS, *PLOAD_UNLOAD_PARAMS; 57a6a3aa0fSVictor Perevertkin 58a6a3aa0fSVictor Perevertkin NTSTATUS 59a6a3aa0fSVictor Perevertkin IopDoLoadUnloadDriver( 604c95339dSVictor Perevertkin _In_opt_ PUNICODE_STRING RegistryPath, 61a6a3aa0fSVictor Perevertkin _Inout_ PDRIVER_OBJECT *DriverObject); 62a6a3aa0fSVictor Perevertkin 63c2c66affSColin Finck /* PRIVATE FUNCTIONS **********************************************************/ 64c2c66affSColin Finck 65c2c66affSColin Finck NTSTATUS 66c2c66affSColin Finck NTAPI 67c2c66affSColin Finck IopInvalidDeviceRequest( 68c2c66affSColin Finck PDEVICE_OBJECT DeviceObject, 69c2c66affSColin Finck PIRP Irp) 70c2c66affSColin Finck { 71c2c66affSColin Finck Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; 72c2c66affSColin Finck Irp->IoStatus.Information = 0; 73c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT); 74c2c66affSColin Finck return STATUS_INVALID_DEVICE_REQUEST; 75c2c66affSColin Finck } 76c2c66affSColin Finck 77c2c66affSColin Finck VOID 78c2c66affSColin Finck NTAPI 79c2c66affSColin Finck IopDeleteDriver(IN PVOID ObjectBody) 80c2c66affSColin Finck { 81c2c66affSColin Finck PDRIVER_OBJECT DriverObject = ObjectBody; 82c2c66affSColin Finck PIO_CLIENT_EXTENSION DriverExtension, NextDriverExtension; 83c2c66affSColin Finck PAGED_CODE(); 84c2c66affSColin Finck 85c2c66affSColin Finck DPRINT1("Deleting driver object '%wZ'\n", &DriverObject->DriverName); 86c2c66affSColin Finck 87c2c66affSColin Finck /* There must be no device objects remaining at this point */ 88c2c66affSColin Finck ASSERT(!DriverObject->DeviceObject); 89c2c66affSColin Finck 90c2c66affSColin Finck /* Get the extension and loop them */ 91c2c66affSColin Finck DriverExtension = IoGetDrvObjExtension(DriverObject)->ClientDriverExtension; 92c2c66affSColin Finck while (DriverExtension) 93c2c66affSColin Finck { 94c2c66affSColin Finck /* Get the next one */ 95c2c66affSColin Finck NextDriverExtension = DriverExtension->NextExtension; 96c2c66affSColin Finck ExFreePoolWithTag(DriverExtension, TAG_DRIVER_EXTENSION); 97c2c66affSColin Finck 98c2c66affSColin Finck /* Move on */ 99c2c66affSColin Finck DriverExtension = NextDriverExtension; 100c2c66affSColin Finck } 101c2c66affSColin Finck 102c2c66affSColin Finck /* Check if the driver image is still loaded */ 103c2c66affSColin Finck if (DriverObject->DriverSection) 104c2c66affSColin Finck { 105c2c66affSColin Finck /* Unload it */ 106c2c66affSColin Finck MmUnloadSystemImage(DriverObject->DriverSection); 107c2c66affSColin Finck } 108c2c66affSColin Finck 109c2c66affSColin Finck /* Check if it has a name */ 110c2c66affSColin Finck if (DriverObject->DriverName.Buffer) 111c2c66affSColin Finck { 112c2c66affSColin Finck /* Free it */ 113c2c66affSColin Finck ExFreePool(DriverObject->DriverName.Buffer); 114c2c66affSColin Finck } 115c2c66affSColin Finck 116c2c66affSColin Finck /* Check if it has a service key name */ 117c2c66affSColin Finck if (DriverObject->DriverExtension->ServiceKeyName.Buffer) 118c2c66affSColin Finck { 119c2c66affSColin Finck /* Free it */ 120c2c66affSColin Finck ExFreePool(DriverObject->DriverExtension->ServiceKeyName.Buffer); 121c2c66affSColin Finck } 122c2c66affSColin Finck } 123c2c66affSColin Finck 124c2c66affSColin Finck NTSTATUS 125c4c0585fSVictor Perevertkin IopGetDriverNames( 126c4c0585fSVictor Perevertkin _In_ HANDLE ServiceHandle, 127c4c0585fSVictor Perevertkin _Out_ PUNICODE_STRING DriverName, 128c4c0585fSVictor Perevertkin _Out_opt_ PUNICODE_STRING ServiceName) 129c2c66affSColin Finck { 130c4c0585fSVictor Perevertkin UNICODE_STRING driverName = {.Buffer = NULL}, serviceName; 131c4c0585fSVictor Perevertkin PKEY_VALUE_FULL_INFORMATION kvInfo; 132c4c0585fSVictor Perevertkin NTSTATUS status; 133c2c66affSColin Finck 134c4c0585fSVictor Perevertkin PAGED_CODE(); 135c2c66affSColin Finck 136c4c0585fSVictor Perevertkin // 1. Check the "ObjectName" field in the driver's registry key (it has the priority) 137c4c0585fSVictor Perevertkin status = IopGetRegistryValue(ServiceHandle, L"ObjectName", &kvInfo); 138c4c0585fSVictor Perevertkin if (NT_SUCCESS(status)) 139c4c0585fSVictor Perevertkin { 140c4c0585fSVictor Perevertkin // we're got the ObjectName. Use it to create the DRIVER_OBJECT 141c4c0585fSVictor Perevertkin if (kvInfo->Type != REG_SZ || kvInfo->DataLength == 0) 142c4c0585fSVictor Perevertkin { 143c4c0585fSVictor Perevertkin ExFreePool(kvInfo); 144c4c0585fSVictor Perevertkin return STATUS_ILL_FORMED_SERVICE_ENTRY; 145c4c0585fSVictor Perevertkin } 146c2c66affSColin Finck 147c4c0585fSVictor Perevertkin driverName.Length = kvInfo->DataLength - sizeof(WCHAR), 148c4c0585fSVictor Perevertkin driverName.MaximumLength = kvInfo->DataLength, 149c4c0585fSVictor Perevertkin driverName.Buffer = ExAllocatePoolWithTag(NonPagedPool, driverName.MaximumLength, TAG_IO); 150c4c0585fSVictor Perevertkin if (!driverName.Buffer) 151c4c0585fSVictor Perevertkin { 152c4c0585fSVictor Perevertkin ExFreePool(kvInfo); 153c4c0585fSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES; 154c4c0585fSVictor Perevertkin } 155c2c66affSColin Finck 156c4c0585fSVictor Perevertkin RtlMoveMemory(driverName.Buffer, 157c4c0585fSVictor Perevertkin (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset), 158c4c0585fSVictor Perevertkin driverName.Length); 159c4c0585fSVictor Perevertkin ExFreePool(kvInfo); 160c4c0585fSVictor Perevertkin } 161e1b20681SThomas Faber 162c4c0585fSVictor Perevertkin // check if we need to get ServiceName as well 163c4c0585fSVictor Perevertkin PKEY_BASIC_INFORMATION basicInfo; 164c4c0585fSVictor Perevertkin if (!NT_SUCCESS(status) || ServiceName != NULL) 165c4c0585fSVictor Perevertkin { 166c4c0585fSVictor Perevertkin ULONG infoLength; 167c4c0585fSVictor Perevertkin status = ZwQueryKey(ServiceHandle, KeyBasicInformation, NULL, 0, &infoLength); 168c4c0585fSVictor Perevertkin if (status == STATUS_BUFFER_TOO_SMALL) 169c4c0585fSVictor Perevertkin { 170c4c0585fSVictor Perevertkin basicInfo = ExAllocatePoolWithTag(PagedPool, infoLength, TAG_IO); 171c4c0585fSVictor Perevertkin if (!basicInfo) 172e1b20681SThomas Faber { 173e1b20681SThomas Faber return STATUS_INSUFFICIENT_RESOURCES; 174e1b20681SThomas Faber } 175c2c66affSColin Finck 176c4c0585fSVictor Perevertkin status = ZwQueryKey(ServiceHandle, KeyBasicInformation, basicInfo, infoLength, &infoLength); 177c4c0585fSVictor Perevertkin if (!NT_SUCCESS(status)) 178c2c66affSColin Finck { 179c4c0585fSVictor Perevertkin ExFreePoolWithTag(basicInfo, TAG_IO); 180c4c0585fSVictor Perevertkin return status; 181c2c66affSColin Finck } 182c2c66affSColin Finck 183c4c0585fSVictor Perevertkin serviceName.Length = basicInfo->NameLength; 184c4c0585fSVictor Perevertkin serviceName.MaximumLength = basicInfo->NameLength; 185c4c0585fSVictor Perevertkin serviceName.Buffer = basicInfo->Name; 186c4c0585fSVictor Perevertkin } 187c4c0585fSVictor Perevertkin else 188c4c0585fSVictor Perevertkin { 189c4c0585fSVictor Perevertkin return NT_SUCCESS(status) ? STATUS_UNSUCCESSFUL : status; 190c4c0585fSVictor Perevertkin } 191c4c0585fSVictor Perevertkin } 192c2c66affSColin Finck 193c4c0585fSVictor Perevertkin // 2. there is no "ObjectName" - construct it ourselves. Depending on a driver type, 194c4c0585fSVictor Perevertkin // it will be either "\Driver\<ServiceName>" or "\FileSystem\<ServiceName>" 195c4c0585fSVictor Perevertkin if (driverName.Buffer == NULL) 196c4c0585fSVictor Perevertkin { 197c4c0585fSVictor Perevertkin status = IopGetRegistryValue(ServiceHandle, L"Type", &kvInfo); 198c4c0585fSVictor Perevertkin if (!NT_SUCCESS(status) || kvInfo->Type != REG_DWORD) 199c4c0585fSVictor Perevertkin { 200c4c0585fSVictor Perevertkin ExFreePool(kvInfo); 201c4c0585fSVictor Perevertkin ExFreePoolWithTag(basicInfo, TAG_IO); // container for serviceName 202c4c0585fSVictor Perevertkin return STATUS_ILL_FORMED_SERVICE_ENTRY; 203c4c0585fSVictor Perevertkin } 204c4c0585fSVictor Perevertkin 205c4c0585fSVictor Perevertkin UINT32 driverType; 206c4c0585fSVictor Perevertkin RtlMoveMemory(&driverType, (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset), sizeof(UINT32)); 207c4c0585fSVictor Perevertkin ExFreePool(kvInfo); 208c4c0585fSVictor Perevertkin 209c4c0585fSVictor Perevertkin driverName.Length = 0; 210c4c0585fSVictor Perevertkin if (driverType == SERVICE_RECOGNIZER_DRIVER || driverType == SERVICE_FILE_SYSTEM_DRIVER) 211c4c0585fSVictor Perevertkin driverName.MaximumLength = sizeof(FILESYSTEM_ROOT_NAME) + serviceName.Length; 212c4c0585fSVictor Perevertkin else 213c4c0585fSVictor Perevertkin driverName.MaximumLength = sizeof(DRIVER_ROOT_NAME) + serviceName.Length; 214c4c0585fSVictor Perevertkin driverName.Buffer = ExAllocatePoolWithTag(NonPagedPool, driverName.MaximumLength, TAG_IO); 215c4c0585fSVictor Perevertkin if (!driverName.Buffer) 216c4c0585fSVictor Perevertkin { 217c4c0585fSVictor Perevertkin ExFreePoolWithTag(basicInfo, TAG_IO); // container for serviceName 218c4c0585fSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES; 219c4c0585fSVictor Perevertkin } 220c4c0585fSVictor Perevertkin 221c4c0585fSVictor Perevertkin if (driverType == SERVICE_RECOGNIZER_DRIVER || driverType == SERVICE_FILE_SYSTEM_DRIVER) 222c4c0585fSVictor Perevertkin RtlAppendUnicodeToString(&driverName, FILESYSTEM_ROOT_NAME); 223c4c0585fSVictor Perevertkin else 224c4c0585fSVictor Perevertkin RtlAppendUnicodeToString(&driverName, DRIVER_ROOT_NAME); 225c4c0585fSVictor Perevertkin 226c4c0585fSVictor Perevertkin RtlAppendUnicodeStringToString(&driverName, &serviceName); 227c4c0585fSVictor Perevertkin } 228c4c0585fSVictor Perevertkin 229c4c0585fSVictor Perevertkin if (ServiceName) 230c4c0585fSVictor Perevertkin { 231c4c0585fSVictor Perevertkin PWCHAR buf = ExAllocatePoolWithTag(PagedPool, serviceName.Length, TAG_IO); 232c4c0585fSVictor Perevertkin if (!buf) 233c4c0585fSVictor Perevertkin { 234c4c0585fSVictor Perevertkin ExFreePoolWithTag(basicInfo, TAG_IO); // container for serviceName 235c4c0585fSVictor Perevertkin ExFreePoolWithTag(driverName.Buffer, TAG_IO); 236c4c0585fSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES; 237c4c0585fSVictor Perevertkin } 238c4c0585fSVictor Perevertkin RtlMoveMemory(buf, serviceName.Buffer, serviceName.Length); 239c4c0585fSVictor Perevertkin ServiceName->MaximumLength = serviceName.Length; 240c4c0585fSVictor Perevertkin ServiceName->Length = serviceName.Length; 241c4c0585fSVictor Perevertkin ServiceName->Buffer = buf; 242c4c0585fSVictor Perevertkin } 243c4c0585fSVictor Perevertkin ExFreePoolWithTag(basicInfo, TAG_IO); // container for ServiceName 244c4c0585fSVictor Perevertkin 245c4c0585fSVictor Perevertkin *DriverName = driverName; 246c2c66affSColin Finck 247c2c66affSColin Finck return STATUS_SUCCESS; 248c2c66affSColin Finck } 249c2c66affSColin Finck 250c2c66affSColin Finck /* 251c2c66affSColin Finck * RETURNS 252c2c66affSColin Finck * TRUE if String2 contains String1 as a suffix. 253c2c66affSColin Finck */ 254c2c66affSColin Finck BOOLEAN 255c2c66affSColin Finck NTAPI 256c2c66affSColin Finck IopSuffixUnicodeString( 257c2c66affSColin Finck IN PCUNICODE_STRING String1, 258c2c66affSColin Finck IN PCUNICODE_STRING String2) 259c2c66affSColin Finck { 260c2c66affSColin Finck PWCHAR pc1; 261c2c66affSColin Finck PWCHAR pc2; 262c2c66affSColin Finck ULONG Length; 263c2c66affSColin Finck 264c2c66affSColin Finck if (String2->Length < String1->Length) 265c2c66affSColin Finck return FALSE; 266c2c66affSColin Finck 267c2c66affSColin Finck Length = String1->Length / 2; 268c2c66affSColin Finck pc1 = String1->Buffer; 269c2c66affSColin Finck pc2 = &String2->Buffer[String2->Length / sizeof(WCHAR) - Length]; 270c2c66affSColin Finck 271c2c66affSColin Finck if (pc1 && pc2) 272c2c66affSColin Finck { 273c2c66affSColin Finck while (Length--) 274c2c66affSColin Finck { 275c2c66affSColin Finck if( *pc1++ != *pc2++ ) 276c2c66affSColin Finck return FALSE; 277c2c66affSColin Finck } 278c2c66affSColin Finck return TRUE; 279c2c66affSColin Finck } 280c2c66affSColin Finck return FALSE; 281c2c66affSColin Finck } 282c2c66affSColin Finck 283c2c66affSColin Finck /* 284c2c66affSColin Finck * IopDisplayLoadingMessage 285c2c66affSColin Finck * 286c2c66affSColin Finck * Display 'Loading XXX...' message. 287c2c66affSColin Finck */ 288c2c66affSColin Finck VOID 289c2c66affSColin Finck FASTCALL 290c2c66affSColin Finck IopDisplayLoadingMessage(PUNICODE_STRING ServiceName) 291c2c66affSColin Finck { 292c2c66affSColin Finck CHAR TextBuffer[256]; 293c2c66affSColin Finck UNICODE_STRING DotSys = RTL_CONSTANT_STRING(L".SYS"); 294c2c66affSColin Finck 295c2c66affSColin Finck if (ExpInTextModeSetup) return; 296c2c66affSColin Finck if (!KeLoaderBlock) return; 297c2c66affSColin Finck RtlUpcaseUnicodeString(ServiceName, ServiceName, FALSE); 298c2c66affSColin Finck snprintf(TextBuffer, sizeof(TextBuffer), 299c2c66affSColin Finck "%s%sSystem32\\Drivers\\%wZ%s\r\n", 300c2c66affSColin Finck KeLoaderBlock->ArcBootDeviceName, 301c2c66affSColin Finck KeLoaderBlock->NtBootPathName, 302c2c66affSColin Finck ServiceName, 303c2c66affSColin Finck IopSuffixUnicodeString(&DotSys, ServiceName) ? "" : ".SYS"); 304c2c66affSColin Finck HalDisplayString(TextBuffer); 305c2c66affSColin Finck } 306c2c66affSColin Finck 307c2c66affSColin Finck /* 308c2c66affSColin Finck * IopNormalizeImagePath 309c2c66affSColin Finck * 310c2c66affSColin Finck * Normalize an image path to contain complete path. 311c2c66affSColin Finck * 312c2c66affSColin Finck * Parameters 313c2c66affSColin Finck * ImagePath 314c2c66affSColin Finck * The input path and on exit the result path. ImagePath.Buffer 315c2c66affSColin Finck * must be allocated by ExAllocatePool on input. Caller is responsible 316c2c66affSColin Finck * for freeing the buffer when it's no longer needed. 317c2c66affSColin Finck * 318c2c66affSColin Finck * ServiceName 319c2c66affSColin Finck * Name of the service that ImagePath belongs to. 320c2c66affSColin Finck * 321c2c66affSColin Finck * Return Value 322c2c66affSColin Finck * Status 323c2c66affSColin Finck * 324c2c66affSColin Finck * Remarks 325c2c66affSColin Finck * The input image path isn't freed on error. 326c2c66affSColin Finck */ 327c2c66affSColin Finck NTSTATUS 328c2c66affSColin Finck FASTCALL 329c2c66affSColin Finck IopNormalizeImagePath( 330c2c66affSColin Finck _Inout_ _When_(return>=0, _At_(ImagePath->Buffer, _Post_notnull_ __drv_allocatesMem(Mem))) 331c2c66affSColin Finck PUNICODE_STRING ImagePath, 332c2c66affSColin Finck _In_ PUNICODE_STRING ServiceName) 333c2c66affSColin Finck { 334c2c66affSColin Finck UNICODE_STRING SystemRootString = RTL_CONSTANT_STRING(L"\\SystemRoot\\"); 335c2c66affSColin Finck UNICODE_STRING DriversPathString = RTL_CONSTANT_STRING(L"\\SystemRoot\\System32\\drivers\\"); 336c2c66affSColin Finck UNICODE_STRING DotSysString = RTL_CONSTANT_STRING(L".sys"); 337c2c66affSColin Finck UNICODE_STRING InputImagePath; 338c2c66affSColin Finck 339c2c66affSColin Finck DPRINT("Normalizing image path '%wZ' for service '%wZ'\n", ImagePath, ServiceName); 340c2c66affSColin Finck 341c2c66affSColin Finck InputImagePath = *ImagePath; 342c2c66affSColin Finck if (InputImagePath.Length == 0) 343c2c66affSColin Finck { 344c2c66affSColin Finck ImagePath->Length = 0; 345c2c66affSColin Finck ImagePath->MaximumLength = DriversPathString.Length + 346c2c66affSColin Finck ServiceName->Length + 347c2c66affSColin Finck DotSysString.Length + 348c2c66affSColin Finck sizeof(UNICODE_NULL); 349c2c66affSColin Finck ImagePath->Buffer = ExAllocatePoolWithTag(NonPagedPool, 350c2c66affSColin Finck ImagePath->MaximumLength, 351c2c66affSColin Finck TAG_IO); 352c2c66affSColin Finck if (ImagePath->Buffer == NULL) 353c2c66affSColin Finck return STATUS_NO_MEMORY; 354c2c66affSColin Finck 355c2c66affSColin Finck RtlCopyUnicodeString(ImagePath, &DriversPathString); 356c2c66affSColin Finck RtlAppendUnicodeStringToString(ImagePath, ServiceName); 357c2c66affSColin Finck RtlAppendUnicodeStringToString(ImagePath, &DotSysString); 358c2c66affSColin Finck } 359c2c66affSColin Finck else if (InputImagePath.Buffer[0] != L'\\') 360c2c66affSColin Finck { 361c2c66affSColin Finck ImagePath->Length = 0; 362c2c66affSColin Finck ImagePath->MaximumLength = SystemRootString.Length + 363c2c66affSColin Finck InputImagePath.Length + 364c2c66affSColin Finck sizeof(UNICODE_NULL); 365c2c66affSColin Finck ImagePath->Buffer = ExAllocatePoolWithTag(NonPagedPool, 366c2c66affSColin Finck ImagePath->MaximumLength, 367c2c66affSColin Finck TAG_IO); 368c2c66affSColin Finck if (ImagePath->Buffer == NULL) 369c2c66affSColin Finck return STATUS_NO_MEMORY; 370c2c66affSColin Finck 371c2c66affSColin Finck RtlCopyUnicodeString(ImagePath, &SystemRootString); 372c2c66affSColin Finck RtlAppendUnicodeStringToString(ImagePath, &InputImagePath); 373c2c66affSColin Finck 374c2c66affSColin Finck /* Free caller's string */ 375c2c66affSColin Finck ExFreePoolWithTag(InputImagePath.Buffer, TAG_RTLREGISTRY); 376c2c66affSColin Finck } 377c2c66affSColin Finck 378c2c66affSColin Finck DPRINT("Normalized image path is '%wZ' for service '%wZ'\n", ImagePath, ServiceName); 379c2c66affSColin Finck 380c2c66affSColin Finck return STATUS_SUCCESS; 381c2c66affSColin Finck } 382c2c66affSColin Finck 383e18a32dfSVictor Perevertkin /** 384e18a32dfSVictor Perevertkin * @brief Initialize a loaded driver 385c2c66affSColin Finck * 386e18a32dfSVictor Perevertkin * @param[in] ModuleObject 387e18a32dfSVictor Perevertkin * Module object representing the driver. It can be retrieved by IopLoadServiceModule. 388e18a32dfSVictor Perevertkin * Freed on failure, so in a such case this should not be accessed anymore 389c2c66affSColin Finck * 3904c95339dSVictor Perevertkin * @param[in] ServiceHandle 3914c95339dSVictor Perevertkin * Handle to a driver's CCS/Services/<ServiceName> key 392c2c66affSColin Finck * 393e18a32dfSVictor Perevertkin * @param[out] DriverObject 394e18a32dfSVictor Perevertkin * This contains the driver object if it was created (even with unsuccessfull result) 395c2c66affSColin Finck * 396e18a32dfSVictor Perevertkin * @param[out] DriverEntryStatus 397e18a32dfSVictor Perevertkin * This contains the status value returned by the driver's DriverEntry routine 398e18a32dfSVictor Perevertkin * (will not be valid of the return value is not STATUS_SUCCESS or STATUS_FAILED_DRIVER_ENTRY) 399c2c66affSColin Finck * 400e18a32dfSVictor Perevertkin * @return Status of the operation 401c2c66affSColin Finck */ 402c2c66affSColin Finck NTSTATUS 403c2c66affSColin Finck IopInitializeDriverModule( 404e18a32dfSVictor Perevertkin _In_ PLDR_DATA_TABLE_ENTRY ModuleObject, 4054c95339dSVictor Perevertkin _In_ HANDLE ServiceHandle, 406e18a32dfSVictor Perevertkin _Out_ PDRIVER_OBJECT *OutDriverObject, 407e18a32dfSVictor Perevertkin _Out_ NTSTATUS *DriverEntryStatus) 408c2c66affSColin Finck { 4094c95339dSVictor Perevertkin UNICODE_STRING DriverName, RegistryPath, ServiceName; 410c2c66affSColin Finck NTSTATUS Status; 411c2c66affSColin Finck 412e18a32dfSVictor Perevertkin PAGED_CODE(); 413c2c66affSColin Finck 414c4c0585fSVictor Perevertkin Status = IopGetDriverNames(ServiceHandle, &DriverName, &ServiceName); 415e18a32dfSVictor Perevertkin if (!NT_SUCCESS(Status)) 416c2c66affSColin Finck { 417e18a32dfSVictor Perevertkin MmUnloadSystemImage(ModuleObject); 418e18a32dfSVictor Perevertkin return Status; 419e18a32dfSVictor Perevertkin } 420e18a32dfSVictor Perevertkin 421e18a32dfSVictor Perevertkin DPRINT("Driver name: '%wZ'\n", &DriverName); 422e18a32dfSVictor Perevertkin 4234c95339dSVictor Perevertkin // obtain the registry path for the DriverInit routine 4244c95339dSVictor Perevertkin PKEY_NAME_INFORMATION nameInfo; 425c4c0585fSVictor Perevertkin ULONG infoLength; 4264c95339dSVictor Perevertkin Status = ZwQueryKey(ServiceHandle, KeyNameInformation, NULL, 0, &infoLength); 4274c95339dSVictor Perevertkin if (Status == STATUS_BUFFER_TOO_SMALL) 4284c95339dSVictor Perevertkin { 4294c95339dSVictor Perevertkin nameInfo = ExAllocatePoolWithTag(NonPagedPool, infoLength, TAG_IO); 4304c95339dSVictor Perevertkin if (nameInfo) 4314c95339dSVictor Perevertkin { 4324c95339dSVictor Perevertkin Status = ZwQueryKey(ServiceHandle, 4334c95339dSVictor Perevertkin KeyNameInformation, 4344c95339dSVictor Perevertkin nameInfo, 4354c95339dSVictor Perevertkin infoLength, 4364c95339dSVictor Perevertkin &infoLength); 4374c95339dSVictor Perevertkin if (NT_SUCCESS(Status)) 4384c95339dSVictor Perevertkin { 4394c95339dSVictor Perevertkin RegistryPath.Length = nameInfo->NameLength; 4404c95339dSVictor Perevertkin RegistryPath.MaximumLength = nameInfo->NameLength; 4414c95339dSVictor Perevertkin RegistryPath.Buffer = nameInfo->Name; 4424c95339dSVictor Perevertkin } 4434c95339dSVictor Perevertkin else 4444c95339dSVictor Perevertkin { 4454c95339dSVictor Perevertkin ExFreePoolWithTag(nameInfo, TAG_IO); 4464c95339dSVictor Perevertkin } 4474c95339dSVictor Perevertkin } 4484c95339dSVictor Perevertkin else 4494c95339dSVictor Perevertkin { 4504c95339dSVictor Perevertkin Status = STATUS_INSUFFICIENT_RESOURCES; 4514c95339dSVictor Perevertkin } 4524c95339dSVictor Perevertkin } 4534c95339dSVictor Perevertkin else 4544c95339dSVictor Perevertkin { 4554c95339dSVictor Perevertkin Status = NT_SUCCESS(Status) ? STATUS_UNSUCCESSFUL : Status; 4564c95339dSVictor Perevertkin } 4574c95339dSVictor Perevertkin 4584c95339dSVictor Perevertkin if (!NT_SUCCESS(Status)) 4594c95339dSVictor Perevertkin { 460c4c0585fSVictor Perevertkin RtlFreeUnicodeString(&ServiceName); 4614c95339dSVictor Perevertkin RtlFreeUnicodeString(&DriverName); 4624c95339dSVictor Perevertkin MmUnloadSystemImage(ModuleObject); 4634c95339dSVictor Perevertkin return Status; 4644c95339dSVictor Perevertkin } 4654c95339dSVictor Perevertkin 466e18a32dfSVictor Perevertkin // create the driver object 467e18a32dfSVictor Perevertkin UINT32 ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(EXTENDED_DRIVER_EXTENSION); 468e18a32dfSVictor Perevertkin OBJECT_ATTRIBUTES objAttrs; 469e18a32dfSVictor Perevertkin PDRIVER_OBJECT driverObject; 470e18a32dfSVictor Perevertkin InitializeObjectAttributes(&objAttrs, 471e18a32dfSVictor Perevertkin &DriverName, 472e18a32dfSVictor Perevertkin OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 473e18a32dfSVictor Perevertkin NULL, 474e18a32dfSVictor Perevertkin NULL); 475e18a32dfSVictor Perevertkin 476e18a32dfSVictor Perevertkin Status = ObCreateObject(KernelMode, 477e18a32dfSVictor Perevertkin IoDriverObjectType, 478e18a32dfSVictor Perevertkin &objAttrs, 479e18a32dfSVictor Perevertkin KernelMode, 480e18a32dfSVictor Perevertkin NULL, 481e18a32dfSVictor Perevertkin ObjectSize, 482e18a32dfSVictor Perevertkin 0, 483e18a32dfSVictor Perevertkin 0, 484e18a32dfSVictor Perevertkin (PVOID*)&driverObject); 485e18a32dfSVictor Perevertkin if (!NT_SUCCESS(Status)) 486e18a32dfSVictor Perevertkin { 4874c95339dSVictor Perevertkin ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath 488c4c0585fSVictor Perevertkin RtlFreeUnicodeString(&ServiceName); 489e18a32dfSVictor Perevertkin RtlFreeUnicodeString(&DriverName); 490e18a32dfSVictor Perevertkin MmUnloadSystemImage(ModuleObject); 491e18a32dfSVictor Perevertkin DPRINT1("Error while creating driver object \"%wZ\" status %x\n", &DriverName, Status); 492e18a32dfSVictor Perevertkin return Status; 493e18a32dfSVictor Perevertkin } 494e18a32dfSVictor Perevertkin 495e18a32dfSVictor Perevertkin DPRINT("Created driver object 0x%p for \"%wZ\"\n", driverObject, &DriverName); 496e18a32dfSVictor Perevertkin 497e18a32dfSVictor Perevertkin RtlZeroMemory(driverObject, ObjectSize); 498e18a32dfSVictor Perevertkin driverObject->Type = IO_TYPE_DRIVER; 499e18a32dfSVictor Perevertkin driverObject->Size = sizeof(DRIVER_OBJECT); 500e18a32dfSVictor Perevertkin driverObject->Flags = DRVO_LEGACY_DRIVER; // TODO: check the WDM_DRIVER flag on the module 501e18a32dfSVictor Perevertkin driverObject->DriverSection = ModuleObject; 502e18a32dfSVictor Perevertkin driverObject->DriverStart = ModuleObject->DllBase; 503e18a32dfSVictor Perevertkin driverObject->DriverSize = ModuleObject->SizeOfImage; 504e18a32dfSVictor Perevertkin driverObject->DriverInit = ModuleObject->EntryPoint; 505e18a32dfSVictor Perevertkin driverObject->HardwareDatabase = &IopHardwareDatabaseKey; 506e18a32dfSVictor Perevertkin driverObject->DriverExtension = (PDRIVER_EXTENSION)(driverObject + 1); 507e18a32dfSVictor Perevertkin driverObject->DriverExtension->DriverObject = driverObject; 508e18a32dfSVictor Perevertkin 509e18a32dfSVictor Perevertkin /* Loop all Major Functions */ 510e18a32dfSVictor Perevertkin for (INT i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) 511e18a32dfSVictor Perevertkin { 512e18a32dfSVictor Perevertkin /* Invalidate each function */ 513e18a32dfSVictor Perevertkin driverObject->MajorFunction[i] = IopInvalidDeviceRequest; 514e18a32dfSVictor Perevertkin } 515e18a32dfSVictor Perevertkin 516e18a32dfSVictor Perevertkin /* Add the Object and get its handle */ 517e18a32dfSVictor Perevertkin HANDLE hDriver; 518e18a32dfSVictor Perevertkin Status = ObInsertObject(driverObject, NULL, FILE_READ_DATA, 0, NULL, &hDriver); 519e18a32dfSVictor Perevertkin if (!NT_SUCCESS(Status)) 520e18a32dfSVictor Perevertkin { 5214c95339dSVictor Perevertkin ExFreePoolWithTag(nameInfo, TAG_IO); 522c4c0585fSVictor Perevertkin RtlFreeUnicodeString(&ServiceName); 523e18a32dfSVictor Perevertkin RtlFreeUnicodeString(&DriverName); 524e18a32dfSVictor Perevertkin return Status; 525e18a32dfSVictor Perevertkin } 526e18a32dfSVictor Perevertkin 527e18a32dfSVictor Perevertkin /* Now reference it */ 528e18a32dfSVictor Perevertkin Status = ObReferenceObjectByHandle(hDriver, 529e18a32dfSVictor Perevertkin 0, 530e18a32dfSVictor Perevertkin IoDriverObjectType, 531e18a32dfSVictor Perevertkin KernelMode, 532e18a32dfSVictor Perevertkin (PVOID*)&driverObject, 533e18a32dfSVictor Perevertkin NULL); 534e18a32dfSVictor Perevertkin 535e18a32dfSVictor Perevertkin /* Close the extra handle */ 536e18a32dfSVictor Perevertkin ZwClose(hDriver); 537e18a32dfSVictor Perevertkin 538e18a32dfSVictor Perevertkin if (!NT_SUCCESS(Status)) 539e18a32dfSVictor Perevertkin { 5404c95339dSVictor Perevertkin ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath 541c4c0585fSVictor Perevertkin RtlFreeUnicodeString(&ServiceName); 542e18a32dfSVictor Perevertkin RtlFreeUnicodeString(&DriverName); 543e18a32dfSVictor Perevertkin return Status; 544e18a32dfSVictor Perevertkin } 545e18a32dfSVictor Perevertkin 546e18a32dfSVictor Perevertkin /* Set up the service key name buffer */ 547e18a32dfSVictor Perevertkin UNICODE_STRING serviceKeyName; 548e18a32dfSVictor Perevertkin serviceKeyName.Length = 0; 549e18a32dfSVictor Perevertkin // put a NULL character at the end for Windows compatibility 5504c95339dSVictor Perevertkin serviceKeyName.MaximumLength = ServiceName.MaximumLength + sizeof(UNICODE_NULL); 551e18a32dfSVictor Perevertkin serviceKeyName.Buffer = ExAllocatePoolWithTag(NonPagedPool, 552e18a32dfSVictor Perevertkin serviceKeyName.MaximumLength, 553e18a32dfSVictor Perevertkin TAG_IO); 554e18a32dfSVictor Perevertkin if (!serviceKeyName.Buffer) 555e18a32dfSVictor Perevertkin { 556e18a32dfSVictor Perevertkin ObMakeTemporaryObject(driverObject); 557e18a32dfSVictor Perevertkin ObDereferenceObject(driverObject); 5584c95339dSVictor Perevertkin ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath 559c4c0585fSVictor Perevertkin RtlFreeUnicodeString(&ServiceName); 560e18a32dfSVictor Perevertkin RtlFreeUnicodeString(&DriverName); 561e18a32dfSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES; 562e18a32dfSVictor Perevertkin } 563e18a32dfSVictor Perevertkin 564e18a32dfSVictor Perevertkin /* Copy the name and set it in the driver extension */ 5654c95339dSVictor Perevertkin RtlCopyUnicodeString(&serviceKeyName, &ServiceName); 566c4c0585fSVictor Perevertkin RtlFreeUnicodeString(&ServiceName); 567e18a32dfSVictor Perevertkin driverObject->DriverExtension->ServiceKeyName = serviceKeyName; 568e18a32dfSVictor Perevertkin 569e18a32dfSVictor Perevertkin /* Make a copy of the driver name to store in the driver object */ 570e18a32dfSVictor Perevertkin UNICODE_STRING driverNamePaged; 571e18a32dfSVictor Perevertkin driverNamePaged.Length = 0; 572e18a32dfSVictor Perevertkin // put a NULL character at the end for Windows compatibility 573e18a32dfSVictor Perevertkin driverNamePaged.MaximumLength = DriverName.MaximumLength + sizeof(UNICODE_NULL); 574e18a32dfSVictor Perevertkin driverNamePaged.Buffer = ExAllocatePoolWithTag(PagedPool, 575e18a32dfSVictor Perevertkin driverNamePaged.MaximumLength, 576e18a32dfSVictor Perevertkin TAG_IO); 577e18a32dfSVictor Perevertkin if (!driverNamePaged.Buffer) 578e18a32dfSVictor Perevertkin { 579e18a32dfSVictor Perevertkin ObMakeTemporaryObject(driverObject); 580e18a32dfSVictor Perevertkin ObDereferenceObject(driverObject); 5814c95339dSVictor Perevertkin ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath 582e18a32dfSVictor Perevertkin RtlFreeUnicodeString(&DriverName); 583e18a32dfSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES; 584e18a32dfSVictor Perevertkin } 585e18a32dfSVictor Perevertkin 586e18a32dfSVictor Perevertkin RtlCopyUnicodeString(&driverNamePaged, &DriverName); 587e18a32dfSVictor Perevertkin driverObject->DriverName = driverNamePaged; 588e18a32dfSVictor Perevertkin 589e18a32dfSVictor Perevertkin /* Finally, call its init function */ 5904c95339dSVictor Perevertkin Status = driverObject->DriverInit(driverObject, &RegistryPath); 591e18a32dfSVictor Perevertkin *DriverEntryStatus = Status; 592e18a32dfSVictor Perevertkin if (!NT_SUCCESS(Status)) 593e18a32dfSVictor Perevertkin { 594e18a32dfSVictor Perevertkin DPRINT1("'%wZ' initialization failed, status (0x%08lx)\n", &DriverName, Status); 595e18a32dfSVictor Perevertkin // return a special status value in case of failure 596e18a32dfSVictor Perevertkin Status = STATUS_FAILED_DRIVER_ENTRY; 597e18a32dfSVictor Perevertkin } 598e18a32dfSVictor Perevertkin 599e18a32dfSVictor Perevertkin /* HACK: We're going to say if we don't have any DOs from DriverEntry, then we're not legacy. 600e18a32dfSVictor Perevertkin * Other parts of the I/O manager depend on this behavior */ 601e18a32dfSVictor Perevertkin if (!driverObject->DeviceObject) 602e18a32dfSVictor Perevertkin { 603e18a32dfSVictor Perevertkin driverObject->Flags &= ~DRVO_LEGACY_DRIVER; 604e18a32dfSVictor Perevertkin } 605e18a32dfSVictor Perevertkin 606e18a32dfSVictor Perevertkin // Windows does this fixup - keep it for compatibility 607e18a32dfSVictor Perevertkin for (INT i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) 608e18a32dfSVictor Perevertkin { 609e18a32dfSVictor Perevertkin /* 610e18a32dfSVictor Perevertkin * Make sure the driver didn't set any dispatch entry point to NULL! 611e18a32dfSVictor Perevertkin * Doing so is illegal; drivers shouldn't touch entry points they 612e18a32dfSVictor Perevertkin * do not implement. 613e18a32dfSVictor Perevertkin */ 614e18a32dfSVictor Perevertkin 615e18a32dfSVictor Perevertkin /* Check if it did so anyway */ 616e18a32dfSVictor Perevertkin if (!driverObject->MajorFunction[i]) 617e18a32dfSVictor Perevertkin { 618e18a32dfSVictor Perevertkin /* Print a warning in the debug log */ 619e18a32dfSVictor Perevertkin DPRINT1("Driver <%wZ> set DriverObject->MajorFunction[%lu] to NULL!\n", 620e18a32dfSVictor Perevertkin &driverObject->DriverName, i); 621e18a32dfSVictor Perevertkin 622e18a32dfSVictor Perevertkin /* Fix it up */ 623e18a32dfSVictor Perevertkin driverObject->MajorFunction[i] = IopInvalidDeviceRequest; 624e18a32dfSVictor Perevertkin } 625e18a32dfSVictor Perevertkin } 626e18a32dfSVictor Perevertkin 627e18a32dfSVictor Perevertkin // TODO: for legacy drivers, unload the driver if it didn't create any DO 628e18a32dfSVictor Perevertkin 6294c95339dSVictor Perevertkin ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath 630c2c66affSColin Finck RtlFreeUnicodeString(&DriverName); 631c2c66affSColin Finck 632c2c66affSColin Finck if (!NT_SUCCESS(Status)) 633c2c66affSColin Finck { 634e18a32dfSVictor Perevertkin // if the driver entry has been failed, clear the object 635e18a32dfSVictor Perevertkin ObMakeTemporaryObject(driverObject); 636e18a32dfSVictor Perevertkin ObDereferenceObject(driverObject); 637c2c66affSColin Finck return Status; 638c2c66affSColin Finck } 639c2c66affSColin Finck 640e18a32dfSVictor Perevertkin *OutDriverObject = driverObject; 641c2c66affSColin Finck 642e18a32dfSVictor Perevertkin MmFreeDriverInitialization((PLDR_DATA_TABLE_ENTRY)driverObject->DriverSection); 643c2c66affSColin Finck 644c2c66affSColin Finck /* Set the driver as initialized */ 645e18a32dfSVictor Perevertkin IopReadyDeviceObjects(driverObject); 646c2c66affSColin Finck 647c2c66affSColin Finck if (PnpSystemInit) IopReinitializeDrivers(); 648c2c66affSColin Finck 649c2c66affSColin Finck return STATUS_SUCCESS; 650c2c66affSColin Finck } 651c2c66affSColin Finck 652c2c66affSColin Finck NTSTATUS 653c2c66affSColin Finck NTAPI 654c2c66affSColin Finck MiResolveImageReferences(IN PVOID ImageBase, 655c2c66affSColin Finck IN PUNICODE_STRING ImageFileDirectory, 656c2c66affSColin Finck IN PUNICODE_STRING NamePrefix OPTIONAL, 657c2c66affSColin Finck OUT PCHAR *MissingApi, 658c2c66affSColin Finck OUT PWCHAR *MissingDriver, 659c2c66affSColin Finck OUT PLOAD_IMPORTS *LoadImports); 660c2c66affSColin Finck 661c2c66affSColin Finck // 662c2c66affSColin Finck // Used for images already loaded (boot drivers) 663c2c66affSColin Finck // 6645c7ce447SVictor Perevertkin CODE_SEG("INIT") 665c2c66affSColin Finck NTSTATUS 666c2c66affSColin Finck NTAPI 667c2c66affSColin Finck LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry, 668c2c66affSColin Finck PUNICODE_STRING FileName, 669c2c66affSColin Finck PLDR_DATA_TABLE_ENTRY *ModuleObject) 670c2c66affSColin Finck { 671c2c66affSColin Finck NTSTATUS Status; 672c2c66affSColin Finck UNICODE_STRING BaseName, BaseDirectory; 673c2c66affSColin Finck PLOAD_IMPORTS LoadedImports = (PVOID)-2; 674c2c66affSColin Finck PCHAR MissingApiName, Buffer; 675c2c66affSColin Finck PWCHAR MissingDriverName; 676c2c66affSColin Finck PVOID DriverBase = LdrEntry->DllBase; 677c2c66affSColin Finck 678c2c66affSColin Finck /* Allocate a buffer we'll use for names */ 679f3a280f5SThomas Faber Buffer = ExAllocatePoolWithTag(NonPagedPool, 680f3a280f5SThomas Faber MAXIMUM_FILENAME_LENGTH, 681f3a280f5SThomas Faber TAG_LDR_WSTR); 682c2c66affSColin Finck if (!Buffer) 683c2c66affSColin Finck { 684c2c66affSColin Finck /* Fail */ 685c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 686c2c66affSColin Finck } 687c2c66affSColin Finck 688c2c66affSColin Finck /* Check for a separator */ 689c2c66affSColin Finck if (FileName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR) 690c2c66affSColin Finck { 691c2c66affSColin Finck PWCHAR p; 692c2c66affSColin Finck ULONG BaseLength; 693c2c66affSColin Finck 694c2c66affSColin Finck /* Loop the path until we get to the base name */ 695c2c66affSColin Finck p = &FileName->Buffer[FileName->Length / sizeof(WCHAR)]; 696c2c66affSColin Finck while (*(p - 1) != OBJ_NAME_PATH_SEPARATOR) p--; 697c2c66affSColin Finck 698c2c66affSColin Finck /* Get the length */ 699c2c66affSColin Finck BaseLength = (ULONG)(&FileName->Buffer[FileName->Length / sizeof(WCHAR)] - p); 700c2c66affSColin Finck BaseLength *= sizeof(WCHAR); 701c2c66affSColin Finck 702c2c66affSColin Finck /* Setup the string */ 703c2c66affSColin Finck BaseName.Length = (USHORT)BaseLength; 704c2c66affSColin Finck BaseName.Buffer = p; 705c2c66affSColin Finck } 706c2c66affSColin Finck else 707c2c66affSColin Finck { 708c2c66affSColin Finck /* Otherwise, we already have a base name */ 709c2c66affSColin Finck BaseName.Length = FileName->Length; 710c2c66affSColin Finck BaseName.Buffer = FileName->Buffer; 711c2c66affSColin Finck } 712c2c66affSColin Finck 713c2c66affSColin Finck /* Setup the maximum length */ 714c2c66affSColin Finck BaseName.MaximumLength = BaseName.Length; 715c2c66affSColin Finck 716c2c66affSColin Finck /* Now compute the base directory */ 717c2c66affSColin Finck BaseDirectory = *FileName; 718c2c66affSColin Finck BaseDirectory.Length -= BaseName.Length; 719c2c66affSColin Finck BaseDirectory.MaximumLength = BaseDirectory.Length; 720c2c66affSColin Finck 721c2c66affSColin Finck /* Resolve imports */ 722c2c66affSColin Finck MissingApiName = Buffer; 723c2c66affSColin Finck Status = MiResolveImageReferences(DriverBase, 724c2c66affSColin Finck &BaseDirectory, 725c2c66affSColin Finck NULL, 726c2c66affSColin Finck &MissingApiName, 727c2c66affSColin Finck &MissingDriverName, 728c2c66affSColin Finck &LoadedImports); 729c2c66affSColin Finck 730c2c66affSColin Finck /* Free the temporary buffer */ 731c2c66affSColin Finck ExFreePoolWithTag(Buffer, TAG_LDR_WSTR); 732c2c66affSColin Finck 733c2c66affSColin Finck /* Check the result of the imports resolution */ 734c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status; 735c2c66affSColin Finck 736c2c66affSColin Finck /* Return */ 737c2c66affSColin Finck *ModuleObject = LdrEntry; 738c2c66affSColin Finck return STATUS_SUCCESS; 739c2c66affSColin Finck } 740c2c66affSColin Finck 741*91fceab3SVictor Perevertkin PDEVICE_OBJECT 742*91fceab3SVictor Perevertkin IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance); 743*91fceab3SVictor Perevertkin 744c2c66affSColin Finck /* 745c2c66affSColin Finck * IopInitializeBuiltinDriver 746c2c66affSColin Finck * 747c2c66affSColin Finck * Initialize a driver that is already loaded in memory. 748c2c66affSColin Finck */ 7495c7ce447SVictor Perevertkin CODE_SEG("INIT") 750*91fceab3SVictor Perevertkin BOOLEAN 751c2c66affSColin Finck IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY BootLdrEntry) 752c2c66affSColin Finck { 753c2c66affSColin Finck PDRIVER_OBJECT DriverObject; 754c2c66affSColin Finck NTSTATUS Status; 755c2c66affSColin Finck PWCHAR Buffer, FileNameWithoutPath; 756c2c66affSColin Finck PWSTR FileExtension; 757c2c66affSColin Finck PUNICODE_STRING ModuleName = &BootLdrEntry->BaseDllName; 758c2c66affSColin Finck PLDR_DATA_TABLE_ENTRY LdrEntry; 759c2c66affSColin Finck PLIST_ENTRY NextEntry; 760c2c66affSColin Finck UNICODE_STRING ServiceName; 761c2c66affSColin Finck BOOLEAN Success; 762c2c66affSColin Finck 763c2c66affSColin Finck /* 764c2c66affSColin Finck * Display 'Loading XXX...' message 765c2c66affSColin Finck */ 766c2c66affSColin Finck IopDisplayLoadingMessage(ModuleName); 767c2c66affSColin Finck InbvIndicateProgress(); 768c2c66affSColin Finck 769c2c66affSColin Finck Buffer = ExAllocatePoolWithTag(PagedPool, 770c2c66affSColin Finck ModuleName->Length + sizeof(UNICODE_NULL), 771c2c66affSColin Finck TAG_IO); 772c2c66affSColin Finck if (Buffer == NULL) 773c2c66affSColin Finck { 774*91fceab3SVictor Perevertkin return FALSE; 775c2c66affSColin Finck } 776c2c66affSColin Finck 777c2c66affSColin Finck RtlCopyMemory(Buffer, ModuleName->Buffer, ModuleName->Length); 778c2c66affSColin Finck Buffer[ModuleName->Length / sizeof(WCHAR)] = UNICODE_NULL; 779c2c66affSColin Finck 780c2c66affSColin Finck /* 781c2c66affSColin Finck * Generate filename without path (not needed by freeldr) 782c2c66affSColin Finck */ 783c2c66affSColin Finck FileNameWithoutPath = wcsrchr(Buffer, L'\\'); 784c2c66affSColin Finck if (FileNameWithoutPath == NULL) 785c2c66affSColin Finck { 786c2c66affSColin Finck FileNameWithoutPath = Buffer; 787c2c66affSColin Finck } 788c2c66affSColin Finck else 789c2c66affSColin Finck { 790c2c66affSColin Finck FileNameWithoutPath++; 791c2c66affSColin Finck } 792c2c66affSColin Finck 793c2c66affSColin Finck /* 794c2c66affSColin Finck * Strip the file extension from ServiceName 795c2c66affSColin Finck */ 796c2c66affSColin Finck Success = RtlCreateUnicodeString(&ServiceName, FileNameWithoutPath); 797c2c66affSColin Finck ExFreePoolWithTag(Buffer, TAG_IO); 798c2c66affSColin Finck if (!Success) 799c2c66affSColin Finck { 800*91fceab3SVictor Perevertkin return FALSE; 801c2c66affSColin Finck } 802c2c66affSColin Finck 803c2c66affSColin Finck FileExtension = wcsrchr(ServiceName.Buffer, L'.'); 804c2c66affSColin Finck if (FileExtension != NULL) 805c2c66affSColin Finck { 806c2c66affSColin Finck ServiceName.Length -= (USHORT)wcslen(FileExtension) * sizeof(WCHAR); 807c2c66affSColin Finck FileExtension[0] = UNICODE_NULL; 808c2c66affSColin Finck } 809c2c66affSColin Finck 8104c95339dSVictor Perevertkin UNICODE_STRING RegistryPath; 8114c95339dSVictor Perevertkin 8124c95339dSVictor Perevertkin // Make the registry path for the driver 8134c95339dSVictor Perevertkin RegistryPath.Length = 0; 8144c95339dSVictor Perevertkin RegistryPath.MaximumLength = sizeof(ServicesKeyName) + ServiceName.Length; 8154c95339dSVictor Perevertkin RegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, RegistryPath.MaximumLength, TAG_IO); 8164c95339dSVictor Perevertkin if (RegistryPath.Buffer == NULL) 8174c95339dSVictor Perevertkin { 818*91fceab3SVictor Perevertkin return FALSE; 8194c95339dSVictor Perevertkin } 8204c95339dSVictor Perevertkin RtlAppendUnicodeToString(&RegistryPath, ServicesKeyName); 8214c95339dSVictor Perevertkin RtlAppendUnicodeStringToString(&RegistryPath, &ServiceName); 8224c95339dSVictor Perevertkin RtlFreeUnicodeString(&ServiceName); 8234c95339dSVictor Perevertkin 8244c95339dSVictor Perevertkin HANDLE serviceHandle; 8254c95339dSVictor Perevertkin Status = IopOpenRegistryKeyEx(&serviceHandle, NULL, &RegistryPath, KEY_READ); 8264c95339dSVictor Perevertkin RtlFreeUnicodeString(&RegistryPath); 8274c95339dSVictor Perevertkin if (!NT_SUCCESS(Status)) 8284c95339dSVictor Perevertkin { 829*91fceab3SVictor Perevertkin return FALSE; 8304c95339dSVictor Perevertkin } 8314c95339dSVictor Perevertkin 832c2c66affSColin Finck /* Lookup the new Ldr entry in PsLoadedModuleList */ 833c2c66affSColin Finck NextEntry = PsLoadedModuleList.Flink; 834c2c66affSColin Finck while (NextEntry != &PsLoadedModuleList) 835c2c66affSColin Finck { 836c2c66affSColin Finck LdrEntry = CONTAINING_RECORD(NextEntry, 837c2c66affSColin Finck LDR_DATA_TABLE_ENTRY, 838c2c66affSColin Finck InLoadOrderLinks); 839c2c66affSColin Finck if (RtlEqualUnicodeString(ModuleName, &LdrEntry->BaseDllName, TRUE)) 840c2c66affSColin Finck { 841c2c66affSColin Finck break; 842c2c66affSColin Finck } 843c2c66affSColin Finck 844c2c66affSColin Finck NextEntry = NextEntry->Flink; 845c2c66affSColin Finck } 846c2c66affSColin Finck ASSERT(NextEntry != &PsLoadedModuleList); 847c2c66affSColin Finck 848c2c66affSColin Finck /* 849c2c66affSColin Finck * Initialize the driver 850c2c66affSColin Finck */ 851e18a32dfSVictor Perevertkin NTSTATUS driverEntryStatus; 8526f0e37b0SVictor Perevertkin Status = IopInitializeDriverModule(LdrEntry, 8534c95339dSVictor Perevertkin serviceHandle, 854e18a32dfSVictor Perevertkin &DriverObject, 855e18a32dfSVictor Perevertkin &driverEntryStatus); 856c2c66affSColin Finck 857c2c66affSColin Finck if (!NT_SUCCESS(Status)) 858c2c66affSColin Finck { 8596f0e37b0SVictor Perevertkin DPRINT1("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status); 860*91fceab3SVictor Perevertkin return FALSE; 861c2c66affSColin Finck } 862c2c66affSColin Finck 863*91fceab3SVictor Perevertkin // The driver has been loaded, now check if where are any PDOs 864*91fceab3SVictor Perevertkin // for that driver, and queue AddDevice call for them. 865*91fceab3SVictor Perevertkin // The check is possible because HKLM/SYSTEM/CCS/Services/<ServiceName>/Enum directory 866*91fceab3SVictor Perevertkin // is populated upon a new device arrival based on a (critical) device database 867*91fceab3SVictor Perevertkin 868*91fceab3SVictor Perevertkin // Legacy drivers may add devices inside DriverEntry. 869*91fceab3SVictor Perevertkin // We're lazy and always assume that they are doing so 870*91fceab3SVictor Perevertkin BOOLEAN deviceAdded = (_Bool)(DriverObject->Flags & DRVO_LEGACY_DRIVER); 871*91fceab3SVictor Perevertkin 872*91fceab3SVictor Perevertkin HANDLE enumServiceHandle; 873*91fceab3SVictor Perevertkin UNICODE_STRING enumName = RTL_CONSTANT_STRING(L"Enum"); 874*91fceab3SVictor Perevertkin 875*91fceab3SVictor Perevertkin Status = IopOpenRegistryKeyEx(&enumServiceHandle, serviceHandle, &enumName, KEY_READ); 876*91fceab3SVictor Perevertkin ZwClose(serviceHandle); 877*91fceab3SVictor Perevertkin 878*91fceab3SVictor Perevertkin if (NT_SUCCESS(Status)) 879*91fceab3SVictor Perevertkin { 880*91fceab3SVictor Perevertkin UINT32 instanceCount = 0; 881*91fceab3SVictor Perevertkin PKEY_VALUE_FULL_INFORMATION kvInfo; 882*91fceab3SVictor Perevertkin Status = IopGetRegistryValue(enumServiceHandle, L"Count", &kvInfo); 883*91fceab3SVictor Perevertkin if (!NT_SUCCESS(Status)) 884*91fceab3SVictor Perevertkin { 885*91fceab3SVictor Perevertkin goto Cleanup; 886*91fceab3SVictor Perevertkin } 887*91fceab3SVictor Perevertkin if (kvInfo->Type != REG_DWORD) 888*91fceab3SVictor Perevertkin { 889*91fceab3SVictor Perevertkin ExFreePool(kvInfo); 890*91fceab3SVictor Perevertkin goto Cleanup; 891*91fceab3SVictor Perevertkin } 892*91fceab3SVictor Perevertkin 893*91fceab3SVictor Perevertkin RtlMoveMemory(&instanceCount, 894*91fceab3SVictor Perevertkin (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset), 895*91fceab3SVictor Perevertkin sizeof(UINT32)); 896*91fceab3SVictor Perevertkin ExFreePool(kvInfo); 897*91fceab3SVictor Perevertkin 898*91fceab3SVictor Perevertkin DPRINT("Processing %u instances for %wZ module\n", instanceCount, ModuleName); 899*91fceab3SVictor Perevertkin 900*91fceab3SVictor Perevertkin for (UINT32 i = 0; i < instanceCount; i++) 901*91fceab3SVictor Perevertkin { 902*91fceab3SVictor Perevertkin WCHAR num[11]; 903*91fceab3SVictor Perevertkin UNICODE_STRING instancePath; 904*91fceab3SVictor Perevertkin RtlStringCchPrintfW(num, sizeof(num), L"%u", i); 905*91fceab3SVictor Perevertkin 906*91fceab3SVictor Perevertkin Status = IopGetRegistryValue(enumServiceHandle, num, &kvInfo); 907*91fceab3SVictor Perevertkin if (!NT_SUCCESS(Status)) 908*91fceab3SVictor Perevertkin { 909*91fceab3SVictor Perevertkin continue; 910*91fceab3SVictor Perevertkin } 911*91fceab3SVictor Perevertkin if (kvInfo->Type != REG_SZ || kvInfo->DataLength == 0) 912*91fceab3SVictor Perevertkin { 913*91fceab3SVictor Perevertkin ExFreePool(kvInfo); 914*91fceab3SVictor Perevertkin continue; 915*91fceab3SVictor Perevertkin } 916*91fceab3SVictor Perevertkin 917*91fceab3SVictor Perevertkin instancePath.Length = kvInfo->DataLength - sizeof(WCHAR), 918*91fceab3SVictor Perevertkin instancePath.MaximumLength = kvInfo->DataLength, 919*91fceab3SVictor Perevertkin instancePath.Buffer = ExAllocatePoolWithTag(NonPagedPool, 920*91fceab3SVictor Perevertkin instancePath.MaximumLength, 921*91fceab3SVictor Perevertkin TAG_IO); 922*91fceab3SVictor Perevertkin if (instancePath.Buffer) 923*91fceab3SVictor Perevertkin { 924*91fceab3SVictor Perevertkin RtlMoveMemory(instancePath.Buffer, 925*91fceab3SVictor Perevertkin (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset), 926*91fceab3SVictor Perevertkin instancePath.Length); 927*91fceab3SVictor Perevertkin 928*91fceab3SVictor Perevertkin PDEVICE_OBJECT pdo = IopGetDeviceObjectFromDeviceInstance(&instancePath); 929*91fceab3SVictor Perevertkin PiQueueDeviceAction(pdo, PiActionAddBootDevices, NULL, NULL); 930*91fceab3SVictor Perevertkin ObDereferenceObject(pdo); 931*91fceab3SVictor Perevertkin deviceAdded = TRUE; 932*91fceab3SVictor Perevertkin } 933*91fceab3SVictor Perevertkin 934*91fceab3SVictor Perevertkin ExFreePool(kvInfo); 935*91fceab3SVictor Perevertkin } 936*91fceab3SVictor Perevertkin 937*91fceab3SVictor Perevertkin ZwClose(enumServiceHandle); 938*91fceab3SVictor Perevertkin } 939*91fceab3SVictor Perevertkin Cleanup: 940c2c66affSColin Finck /* Remove extra reference from IopInitializeDriverModule */ 941c2c66affSColin Finck ObDereferenceObject(DriverObject); 942c2c66affSColin Finck 943*91fceab3SVictor Perevertkin return deviceAdded; 944c2c66affSColin Finck } 945c2c66affSColin Finck 946c2c66affSColin Finck /* 947c2c66affSColin Finck * IopInitializeBootDrivers 948c2c66affSColin Finck * 949c2c66affSColin Finck * Initialize boot drivers and free memory for boot files. 950c2c66affSColin Finck * 951c2c66affSColin Finck * Parameters 952c2c66affSColin Finck * None 953c2c66affSColin Finck * 954c2c66affSColin Finck * Return Value 955c2c66affSColin Finck * None 956c2c66affSColin Finck */ 9575c7ce447SVictor Perevertkin CODE_SEG("INIT") 958c2c66affSColin Finck VOID 959c2c66affSColin Finck FASTCALL 960c2c66affSColin Finck IopInitializeBootDrivers(VOID) 961c2c66affSColin Finck { 962c2c66affSColin Finck PLIST_ENTRY ListHead, NextEntry, NextEntry2; 963c2c66affSColin Finck PLDR_DATA_TABLE_ENTRY LdrEntry; 964c2c66affSColin Finck NTSTATUS Status; 965c2c66affSColin Finck UNICODE_STRING DriverName; 966c2c66affSColin Finck ULONG i, Index; 967c2c66affSColin Finck PDRIVER_INFORMATION DriverInfo, DriverInfoTag; 968c2c66affSColin Finck HANDLE KeyHandle; 969c2c66affSColin Finck PBOOT_DRIVER_LIST_ENTRY BootEntry; 970c2c66affSColin Finck DPRINT("IopInitializeBootDrivers()\n"); 971c2c66affSColin Finck 972e18a32dfSVictor Perevertkin /* Create the RAW FS built-in driver */ 973e18a32dfSVictor Perevertkin RtlInitUnicodeString(&DriverName, L"\\FileSystem\\RAW"); 974c2c66affSColin Finck 975e18a32dfSVictor Perevertkin Status = IoCreateDriver(&DriverName, RawFsDriverEntry); 976c2c66affSColin Finck if (!NT_SUCCESS(Status)) 977c2c66affSColin Finck { 978c2c66affSColin Finck /* Fail */ 979c2c66affSColin Finck return; 980c2c66affSColin Finck } 981c2c66affSColin Finck 982c2c66affSColin Finck /* Get highest group order index */ 983c2c66affSColin Finck IopGroupIndex = PpInitGetGroupOrderIndex(NULL); 984c2c66affSColin Finck if (IopGroupIndex == 0xFFFF) ASSERT(FALSE); 985c2c66affSColin Finck 986c2c66affSColin Finck /* Allocate the group table */ 987c2c66affSColin Finck IopGroupTable = ExAllocatePoolWithTag(PagedPool, 988c2c66affSColin Finck IopGroupIndex * sizeof(LIST_ENTRY), 989c2c66affSColin Finck TAG_IO); 990c2c66affSColin Finck if (IopGroupTable == NULL) ASSERT(FALSE); 991c2c66affSColin Finck 992c2c66affSColin Finck /* Initialize the group table lists */ 993c2c66affSColin Finck for (i = 0; i < IopGroupIndex; i++) InitializeListHead(&IopGroupTable[i]); 994c2c66affSColin Finck 995c2c66affSColin Finck /* Loop the boot modules */ 996c2c66affSColin Finck ListHead = &KeLoaderBlock->LoadOrderListHead; 997c2c66affSColin Finck NextEntry = ListHead->Flink; 998c2c66affSColin Finck while (ListHead != NextEntry) 999c2c66affSColin Finck { 1000c2c66affSColin Finck /* Get the entry */ 1001c2c66affSColin Finck LdrEntry = CONTAINING_RECORD(NextEntry, 1002c2c66affSColin Finck LDR_DATA_TABLE_ENTRY, 1003c2c66affSColin Finck InLoadOrderLinks); 1004c2c66affSColin Finck 1005c2c66affSColin Finck /* Check if the DLL needs to be initialized */ 1006c2c66affSColin Finck if (LdrEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL) 1007c2c66affSColin Finck { 1008c2c66affSColin Finck /* Call its entrypoint */ 1009c2c66affSColin Finck MmCallDllInitialize(LdrEntry, NULL); 1010c2c66affSColin Finck } 1011c2c66affSColin Finck 1012c2c66affSColin Finck /* Go to the next driver */ 1013c2c66affSColin Finck NextEntry = NextEntry->Flink; 1014c2c66affSColin Finck } 1015c2c66affSColin Finck 1016c2c66affSColin Finck /* Loop the boot drivers */ 1017c2c66affSColin Finck ListHead = &KeLoaderBlock->BootDriverListHead; 1018c2c66affSColin Finck NextEntry = ListHead->Flink; 1019c2c66affSColin Finck while (ListHead != NextEntry) 1020c2c66affSColin Finck { 1021c2c66affSColin Finck /* Get the entry */ 1022c2c66affSColin Finck BootEntry = CONTAINING_RECORD(NextEntry, 1023c2c66affSColin Finck BOOT_DRIVER_LIST_ENTRY, 1024c2c66affSColin Finck Link); 1025c2c66affSColin Finck 1026c2c66affSColin Finck /* Get the driver loader entry */ 1027c2c66affSColin Finck LdrEntry = BootEntry->LdrEntry; 1028c2c66affSColin Finck 1029c2c66affSColin Finck /* Allocate our internal accounting structure */ 1030c2c66affSColin Finck DriverInfo = ExAllocatePoolWithTag(PagedPool, 1031c2c66affSColin Finck sizeof(DRIVER_INFORMATION), 1032c2c66affSColin Finck TAG_IO); 1033c2c66affSColin Finck if (DriverInfo) 1034c2c66affSColin Finck { 1035c2c66affSColin Finck /* Zero it and initialize it */ 1036c2c66affSColin Finck RtlZeroMemory(DriverInfo, sizeof(DRIVER_INFORMATION)); 1037c2c66affSColin Finck InitializeListHead(&DriverInfo->Link); 1038c2c66affSColin Finck DriverInfo->DataTableEntry = BootEntry; 1039c2c66affSColin Finck 1040c2c66affSColin Finck /* Open the registry key */ 1041c2c66affSColin Finck Status = IopOpenRegistryKeyEx(&KeyHandle, 1042c2c66affSColin Finck NULL, 1043c2c66affSColin Finck &BootEntry->RegistryPath, 1044c2c66affSColin Finck KEY_READ); 10458e51bb65SPierre Schweitzer DPRINT("IopOpenRegistryKeyEx(%wZ) returned 0x%08lx\n", &BootEntry->RegistryPath, Status); 1046cb69c4c6SHermès Bélusca-Maïto #if 0 1047cb69c4c6SHermès Bélusca-Maïto if (NT_SUCCESS(Status)) 1048cb69c4c6SHermès Bélusca-Maïto #else // Hack still needed... 1049c2c66affSColin Finck if ((NT_SUCCESS(Status)) || /* ReactOS HACK for SETUPLDR */ 1050c2c66affSColin Finck ((KeLoaderBlock->SetupLdrBlock) && ((KeyHandle = (PVOID)1)))) // yes, it's an assignment! 1051cb69c4c6SHermès Bélusca-Maïto #endif 1052c2c66affSColin Finck { 1053c2c66affSColin Finck /* Save the handle */ 1054c2c66affSColin Finck DriverInfo->ServiceHandle = KeyHandle; 1055c2c66affSColin Finck 1056c2c66affSColin Finck /* Get the group oder index */ 1057c2c66affSColin Finck Index = PpInitGetGroupOrderIndex(KeyHandle); 1058c2c66affSColin Finck 1059c2c66affSColin Finck /* Get the tag position */ 1060c2c66affSColin Finck DriverInfo->TagPosition = PipGetDriverTagPriority(KeyHandle); 1061c2c66affSColin Finck 1062c2c66affSColin Finck /* Insert it into the list, at the right place */ 1063c2c66affSColin Finck ASSERT(Index < IopGroupIndex); 1064c2c66affSColin Finck NextEntry2 = IopGroupTable[Index].Flink; 1065c2c66affSColin Finck while (NextEntry2 != &IopGroupTable[Index]) 1066c2c66affSColin Finck { 1067c2c66affSColin Finck /* Get the driver info */ 1068c2c66affSColin Finck DriverInfoTag = CONTAINING_RECORD(NextEntry2, 1069c2c66affSColin Finck DRIVER_INFORMATION, 1070c2c66affSColin Finck Link); 1071c2c66affSColin Finck 1072c2c66affSColin Finck /* Check if we found the right tag position */ 1073c2c66affSColin Finck if (DriverInfoTag->TagPosition > DriverInfo->TagPosition) 1074c2c66affSColin Finck { 1075c2c66affSColin Finck /* We're done */ 1076c2c66affSColin Finck break; 1077c2c66affSColin Finck } 1078c2c66affSColin Finck 1079c2c66affSColin Finck /* Next entry */ 1080c2c66affSColin Finck NextEntry2 = NextEntry2->Flink; 1081c2c66affSColin Finck } 1082c2c66affSColin Finck 1083c2c66affSColin Finck /* Insert us right before the next entry */ 1084c2c66affSColin Finck NextEntry2 = NextEntry2->Blink; 1085c2c66affSColin Finck InsertHeadList(NextEntry2, &DriverInfo->Link); 1086c2c66affSColin Finck } 1087c2c66affSColin Finck } 1088c2c66affSColin Finck 1089c2c66affSColin Finck /* Go to the next driver */ 1090c2c66affSColin Finck NextEntry = NextEntry->Flink; 1091c2c66affSColin Finck } 1092c2c66affSColin Finck 1093c2c66affSColin Finck /* Loop each group index */ 1094c2c66affSColin Finck for (i = 0; i < IopGroupIndex; i++) 1095c2c66affSColin Finck { 1096c2c66affSColin Finck /* Loop each group table */ 1097c2c66affSColin Finck NextEntry = IopGroupTable[i].Flink; 1098c2c66affSColin Finck while (NextEntry != &IopGroupTable[i]) 1099c2c66affSColin Finck { 1100c2c66affSColin Finck /* Get the entry */ 1101c2c66affSColin Finck DriverInfo = CONTAINING_RECORD(NextEntry, 1102c2c66affSColin Finck DRIVER_INFORMATION, 1103c2c66affSColin Finck Link); 1104c2c66affSColin Finck 1105c2c66affSColin Finck /* Get the driver loader entry */ 1106c2c66affSColin Finck LdrEntry = DriverInfo->DataTableEntry->LdrEntry; 1107c2c66affSColin Finck 1108c2c66affSColin Finck /* Initialize it */ 1109*91fceab3SVictor Perevertkin if (IopInitializeBuiltinDriver(LdrEntry)) 1110*91fceab3SVictor Perevertkin { 1111*91fceab3SVictor Perevertkin // it does not make sense to enumerate the tree if there are no new devices added 1112d6ef8f97SVictor Perevertkin PiQueueDeviceAction(IopRootDeviceNode->PhysicalDeviceObject, 1113d6ef8f97SVictor Perevertkin PiActionEnumRootDevices, 1114d6ef8f97SVictor Perevertkin NULL, 1115d6ef8f97SVictor Perevertkin NULL); 1116*91fceab3SVictor Perevertkin } 1117d6ef8f97SVictor Perevertkin 1118c2c66affSColin Finck /* Next entry */ 1119c2c66affSColin Finck NextEntry = NextEntry->Flink; 1120c2c66affSColin Finck } 1121c2c66affSColin Finck } 1122c2c66affSColin Finck 11232839c850SVictor Perevertkin /* HAL Root Bus is being initialized before loading the boot drivers so this may cause issues 11242839c850SVictor Perevertkin * when some devices are not being initialized with their drivers. This flag is used to delay 11252839c850SVictor Perevertkin * all actions with devices (except PnP root device) until boot drivers are loaded. 11262839c850SVictor Perevertkin * See PiQueueDeviceAction function 11272839c850SVictor Perevertkin */ 11282839c850SVictor Perevertkin PnPBootDriversLoaded = TRUE; 1129b7042928SVictor Perevertkin 1130b7042928SVictor Perevertkin DbgPrint("BOOT DRIVERS LOADED\n"); 1131b7042928SVictor Perevertkin 1132b7042928SVictor Perevertkin PiQueueDeviceAction(IopRootDeviceNode->PhysicalDeviceObject, 1133b7042928SVictor Perevertkin PiActionEnumDeviceTree, 1134b7042928SVictor Perevertkin NULL, 1135b7042928SVictor Perevertkin NULL); 1136c2c66affSColin Finck } 1137c2c66affSColin Finck 11385c7ce447SVictor Perevertkin CODE_SEG("INIT") 1139c2c66affSColin Finck VOID 1140c2c66affSColin Finck FASTCALL 1141c2c66affSColin Finck IopInitializeSystemDrivers(VOID) 1142c2c66affSColin Finck { 1143c2c66affSColin Finck PUNICODE_STRING *DriverList, *SavedList; 1144c2c66affSColin Finck 1145b7042928SVictor Perevertkin PiPerformSyncDeviceAction(IopRootDeviceNode->PhysicalDeviceObject, PiActionEnumDeviceTree); 1146b7042928SVictor Perevertkin 1147c2c66affSColin Finck /* No system drivers on the boot cd */ 1148cb69c4c6SHermès Bélusca-Maïto if (KeLoaderBlock->SetupLdrBlock) return; // ExpInTextModeSetup 1149c2c66affSColin Finck 1150c2c66affSColin Finck /* Get the driver list */ 1151c2c66affSColin Finck SavedList = DriverList = CmGetSystemDriverList(); 1152c2c66affSColin Finck ASSERT(DriverList); 1153c2c66affSColin Finck 1154c2c66affSColin Finck /* Loop it */ 1155c2c66affSColin Finck while (*DriverList) 1156c2c66affSColin Finck { 1157c2c66affSColin Finck /* Load the driver */ 1158c2c66affSColin Finck ZwLoadDriver(*DriverList); 1159c2c66affSColin Finck 1160c2c66affSColin Finck /* Free the entry */ 1161c2c66affSColin Finck RtlFreeUnicodeString(*DriverList); 1162c2c66affSColin Finck ExFreePool(*DriverList); 1163c2c66affSColin Finck 1164c2c66affSColin Finck /* Next entry */ 1165c2c66affSColin Finck InbvIndicateProgress(); 1166c2c66affSColin Finck DriverList++; 1167c2c66affSColin Finck } 1168c2c66affSColin Finck 1169c2c66affSColin Finck /* Free the list */ 1170c2c66affSColin Finck ExFreePool(SavedList); 1171b7042928SVictor Perevertkin 1172b7042928SVictor Perevertkin PiQueueDeviceAction(IopRootDeviceNode->PhysicalDeviceObject, 1173b7042928SVictor Perevertkin PiActionEnumDeviceTree, 1174b7042928SVictor Perevertkin NULL, 1175b7042928SVictor Perevertkin NULL); 1176c2c66affSColin Finck } 1177c2c66affSColin Finck 1178c2c66affSColin Finck /* 1179c2c66affSColin Finck * IopUnloadDriver 1180c2c66affSColin Finck * 1181c2c66affSColin Finck * Unloads a device driver. 1182c2c66affSColin Finck * 1183c2c66affSColin Finck * Parameters 1184c2c66affSColin Finck * DriverServiceName 1185c2c66affSColin Finck * Name of the service to unload (registry key). 1186c2c66affSColin Finck * 1187c2c66affSColin Finck * UnloadPnpDrivers 1188c2c66affSColin Finck * Whether to unload Plug & Plug or only legacy drivers. If this 1189c2c66affSColin Finck * parameter is set to FALSE, the routine will unload only legacy 1190c2c66affSColin Finck * drivers. 1191c2c66affSColin Finck * 1192c2c66affSColin Finck * Return Value 1193c2c66affSColin Finck * Status 1194c2c66affSColin Finck * 1195c2c66affSColin Finck * To do 1196c2c66affSColin Finck * Guard the whole function by SEH. 1197c2c66affSColin Finck */ 1198c2c66affSColin Finck 1199c2c66affSColin Finck NTSTATUS NTAPI 1200c2c66affSColin Finck IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers) 1201c2c66affSColin Finck { 1202c904983bSThomas Faber UNICODE_STRING Backslash = RTL_CONSTANT_STRING(L"\\"); 1203c2c66affSColin Finck RTL_QUERY_REGISTRY_TABLE QueryTable[2]; 1204c2c66affSColin Finck UNICODE_STRING ImagePath; 1205c2c66affSColin Finck UNICODE_STRING ServiceName; 1206c2c66affSColin Finck UNICODE_STRING ObjectName; 1207c2c66affSColin Finck PDRIVER_OBJECT DriverObject; 1208c2c66affSColin Finck PDEVICE_OBJECT DeviceObject; 1209c2c66affSColin Finck PEXTENDED_DEVOBJ_EXTENSION DeviceExtension; 1210c2c66affSColin Finck NTSTATUS Status; 1211c904983bSThomas Faber USHORT LastBackslash; 1212c2c66affSColin Finck BOOLEAN SafeToUnload = TRUE; 1213daf9743cSPierre Schweitzer KPROCESSOR_MODE PreviousMode; 1214daf9743cSPierre Schweitzer UNICODE_STRING CapturedServiceName; 1215c2c66affSColin Finck 1216c2c66affSColin Finck PAGED_CODE(); 1217c2c66affSColin Finck 1218daf9743cSPierre Schweitzer PreviousMode = ExGetPreviousMode(); 1219daf9743cSPierre Schweitzer 1220daf9743cSPierre Schweitzer /* Need the appropriate priviliege */ 1221daf9743cSPierre Schweitzer if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode)) 1222daf9743cSPierre Schweitzer { 1223daf9743cSPierre Schweitzer DPRINT1("No unload privilege!\n"); 1224daf9743cSPierre Schweitzer return STATUS_PRIVILEGE_NOT_HELD; 1225daf9743cSPierre Schweitzer } 1226daf9743cSPierre Schweitzer 1227daf9743cSPierre Schweitzer /* Capture the service name */ 122844511f08SHermès Bélusca-Maïto Status = ProbeAndCaptureUnicodeString(&CapturedServiceName, 122944511f08SHermès Bélusca-Maïto PreviousMode, 123044511f08SHermès Bélusca-Maïto DriverServiceName); 1231daf9743cSPierre Schweitzer if (!NT_SUCCESS(Status)) 1232a6a3aa0fSVictor Perevertkin { 1233daf9743cSPierre Schweitzer return Status; 1234a6a3aa0fSVictor Perevertkin } 1235daf9743cSPierre Schweitzer 1236daf9743cSPierre Schweitzer DPRINT("IopUnloadDriver('%wZ', %u)\n", &CapturedServiceName, UnloadPnpDrivers); 1237daf9743cSPierre Schweitzer 1238daf9743cSPierre Schweitzer /* We need a service name */ 1239a748350fSHermès Bélusca-Maïto if (CapturedServiceName.Length == 0 || CapturedServiceName.Buffer == NULL) 1240daf9743cSPierre Schweitzer { 1241daf9743cSPierre Schweitzer ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1242daf9743cSPierre Schweitzer return STATUS_INVALID_PARAMETER; 1243daf9743cSPierre Schweitzer } 1244daf9743cSPierre Schweitzer 1245c2c66affSColin Finck /* 1246c2c66affSColin Finck * Get the service name from the registry key name 1247c2c66affSColin Finck */ 1248c904983bSThomas Faber Status = RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END, 1249c904983bSThomas Faber &CapturedServiceName, 1250c904983bSThomas Faber &Backslash, 1251c904983bSThomas Faber &LastBackslash); 1252c904983bSThomas Faber if (NT_SUCCESS(Status)) 1253c904983bSThomas Faber { 1254c904983bSThomas Faber NT_ASSERT(CapturedServiceName.Length >= LastBackslash + sizeof(WCHAR)); 1255c904983bSThomas Faber ServiceName.Buffer = &CapturedServiceName.Buffer[LastBackslash / sizeof(WCHAR) + 1]; 1256c904983bSThomas Faber ServiceName.Length = CapturedServiceName.Length - LastBackslash - sizeof(WCHAR); 1257c904983bSThomas Faber ServiceName.MaximumLength = CapturedServiceName.MaximumLength - LastBackslash - sizeof(WCHAR); 1258c904983bSThomas Faber } 1259c2c66affSColin Finck else 1260c904983bSThomas Faber { 1261c904983bSThomas Faber ServiceName = CapturedServiceName; 1262c904983bSThomas Faber } 1263c2c66affSColin Finck 1264c2c66affSColin Finck /* 1265c2c66affSColin Finck * Construct the driver object name 1266c2c66affSColin Finck */ 1267c904983bSThomas Faber Status = RtlUShortAdd(sizeof(DRIVER_ROOT_NAME), 1268c904983bSThomas Faber ServiceName.Length, 1269c904983bSThomas Faber &ObjectName.MaximumLength); 1270c904983bSThomas Faber if (!NT_SUCCESS(Status)) 1271c904983bSThomas Faber { 1272c904983bSThomas Faber ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1273c904983bSThomas Faber return Status; 1274c904983bSThomas Faber } 1275c904983bSThomas Faber ObjectName.Length = 0; 1276c2c66affSColin Finck ObjectName.Buffer = ExAllocatePoolWithTag(PagedPool, 1277c2c66affSColin Finck ObjectName.MaximumLength, 1278c2c66affSColin Finck TAG_IO); 1279daf9743cSPierre Schweitzer if (!ObjectName.Buffer) 1280daf9743cSPierre Schweitzer { 1281daf9743cSPierre Schweitzer ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1282daf9743cSPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES; 1283daf9743cSPierre Schweitzer } 1284c904983bSThomas Faber NT_VERIFY(NT_SUCCESS(RtlAppendUnicodeToString(&ObjectName, DRIVER_ROOT_NAME))); 1285c904983bSThomas Faber NT_VERIFY(NT_SUCCESS(RtlAppendUnicodeStringToString(&ObjectName, &ServiceName))); 1286c2c66affSColin Finck 1287c2c66affSColin Finck /* 1288c2c66affSColin Finck * Find the driver object 1289c2c66affSColin Finck */ 1290c2c66affSColin Finck Status = ObReferenceObjectByName(&ObjectName, 1291c2c66affSColin Finck 0, 1292c2c66affSColin Finck 0, 1293c2c66affSColin Finck 0, 1294c2c66affSColin Finck IoDriverObjectType, 1295c2c66affSColin Finck KernelMode, 1296c2c66affSColin Finck 0, 1297c2c66affSColin Finck (PVOID*)&DriverObject); 1298c2c66affSColin Finck 1299c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1300c2c66affSColin Finck { 1301c2c66affSColin Finck DPRINT1("Can't locate driver object for %wZ\n", &ObjectName); 1302c2c66affSColin Finck ExFreePoolWithTag(ObjectName.Buffer, TAG_IO); 1303daf9743cSPierre Schweitzer ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1304c2c66affSColin Finck return Status; 1305c2c66affSColin Finck } 1306c2c66affSColin Finck 1307c2c66affSColin Finck /* Free the buffer for driver object name */ 1308c2c66affSColin Finck ExFreePoolWithTag(ObjectName.Buffer, TAG_IO); 1309c2c66affSColin Finck 1310c2c66affSColin Finck /* Check that driver is not already unloading */ 1311c2c66affSColin Finck if (DriverObject->Flags & DRVO_UNLOAD_INVOKED) 1312c2c66affSColin Finck { 1313c2c66affSColin Finck DPRINT1("Driver deletion pending\n"); 1314c2c66affSColin Finck ObDereferenceObject(DriverObject); 1315daf9743cSPierre Schweitzer ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1316c2c66affSColin Finck return STATUS_DELETE_PENDING; 1317c2c66affSColin Finck } 1318c2c66affSColin Finck 1319c2c66affSColin Finck /* 1320c2c66affSColin Finck * Get path of service... 1321c2c66affSColin Finck */ 1322c2c66affSColin Finck RtlZeroMemory(QueryTable, sizeof(QueryTable)); 1323c2c66affSColin Finck 1324c2c66affSColin Finck RtlInitUnicodeString(&ImagePath, NULL); 1325c2c66affSColin Finck 1326c2c66affSColin Finck QueryTable[0].Name = L"ImagePath"; 1327c2c66affSColin Finck QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; 1328c2c66affSColin Finck QueryTable[0].EntryContext = &ImagePath; 1329c2c66affSColin Finck 1330c2c66affSColin Finck Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, 1331daf9743cSPierre Schweitzer CapturedServiceName.Buffer, 1332c2c66affSColin Finck QueryTable, 1333c2c66affSColin Finck NULL, 1334c2c66affSColin Finck NULL); 1335c2c66affSColin Finck 1336daf9743cSPierre Schweitzer /* We no longer need service name */ 1337daf9743cSPierre Schweitzer ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 1338daf9743cSPierre Schweitzer 1339c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1340c2c66affSColin Finck { 1341c2c66affSColin Finck DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status); 1342c2c66affSColin Finck ObDereferenceObject(DriverObject); 1343c2c66affSColin Finck return Status; 1344c2c66affSColin Finck } 1345c2c66affSColin Finck 1346c2c66affSColin Finck /* 1347c2c66affSColin Finck * Normalize the image path for all later processing. 1348c2c66affSColin Finck */ 1349c2c66affSColin Finck Status = IopNormalizeImagePath(&ImagePath, &ServiceName); 1350c2c66affSColin Finck 1351c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1352c2c66affSColin Finck { 1353c2c66affSColin Finck DPRINT1("IopNormalizeImagePath() failed (Status %x)\n", Status); 1354c2c66affSColin Finck ObDereferenceObject(DriverObject); 1355c2c66affSColin Finck return Status; 1356c2c66affSColin Finck } 1357c2c66affSColin Finck 1358c2c66affSColin Finck /* Free the service path */ 1359c2c66affSColin Finck ExFreePool(ImagePath.Buffer); 1360c2c66affSColin Finck 1361c2c66affSColin Finck /* 1362c2c66affSColin Finck * Unload the module and release the references to the device object 1363c2c66affSColin Finck */ 1364c2c66affSColin Finck 1365c2c66affSColin Finck /* Call the load/unload routine, depending on current process */ 1366c2c66affSColin Finck if (DriverObject->DriverUnload && DriverObject->DriverSection && 1367c2c66affSColin Finck (UnloadPnpDrivers || (DriverObject->Flags & DRVO_LEGACY_DRIVER))) 1368c2c66affSColin Finck { 1369c2c66affSColin Finck /* Loop through each device object of the driver 1370c2c66affSColin Finck and set DOE_UNLOAD_PENDING flag */ 1371c2c66affSColin Finck DeviceObject = DriverObject->DeviceObject; 1372c2c66affSColin Finck while (DeviceObject) 1373c2c66affSColin Finck { 1374c2c66affSColin Finck /* Set the unload pending flag for the device */ 1375c2c66affSColin Finck DeviceExtension = IoGetDevObjExtension(DeviceObject); 1376c2c66affSColin Finck DeviceExtension->ExtensionFlags |= DOE_UNLOAD_PENDING; 1377c2c66affSColin Finck 1378c2c66affSColin Finck /* Make sure there are no attached devices or no reference counts */ 1379c2c66affSColin Finck if ((DeviceObject->ReferenceCount) || (DeviceObject->AttachedDevice)) 1380c2c66affSColin Finck { 1381c2c66affSColin Finck /* Not safe to unload */ 1382c2c66affSColin Finck DPRINT1("Drivers device object is referenced or has attached devices\n"); 1383c2c66affSColin Finck 1384c2c66affSColin Finck SafeToUnload = FALSE; 1385c2c66affSColin Finck } 1386c2c66affSColin Finck 1387c2c66affSColin Finck DeviceObject = DeviceObject->NextDevice; 1388c2c66affSColin Finck } 1389c2c66affSColin Finck 1390c2c66affSColin Finck /* If not safe to unload, then return success */ 1391c2c66affSColin Finck if (!SafeToUnload) 1392c2c66affSColin Finck { 1393c2c66affSColin Finck ObDereferenceObject(DriverObject); 1394c2c66affSColin Finck return STATUS_SUCCESS; 1395c2c66affSColin Finck } 1396c2c66affSColin Finck 1397c2c66affSColin Finck DPRINT1("Unloading driver '%wZ' (manual)\n", &DriverObject->DriverName); 1398c2c66affSColin Finck 1399c2c66affSColin Finck /* Set the unload invoked flag and call the unload routine */ 1400c2c66affSColin Finck DriverObject->Flags |= DRVO_UNLOAD_INVOKED; 1401a6a3aa0fSVictor Perevertkin Status = IopDoLoadUnloadDriver(NULL, &DriverObject); 1402c2c66affSColin Finck ASSERT(Status == STATUS_SUCCESS); 1403c2c66affSColin Finck 1404c2c66affSColin Finck /* Mark the driver object temporary, so it could be deleted later */ 1405c2c66affSColin Finck ObMakeTemporaryObject(DriverObject); 1406c2c66affSColin Finck 1407c2c66affSColin Finck /* Dereference it 2 times */ 1408c2c66affSColin Finck ObDereferenceObject(DriverObject); 1409c2c66affSColin Finck ObDereferenceObject(DriverObject); 1410c2c66affSColin Finck 1411c2c66affSColin Finck return Status; 1412c2c66affSColin Finck } 1413c2c66affSColin Finck else 1414c2c66affSColin Finck { 1415c2c66affSColin Finck DPRINT1("No DriverUnload function! '%wZ' will not be unloaded!\n", &DriverObject->DriverName); 1416c2c66affSColin Finck 1417c2c66affSColin Finck /* Dereference one time (refd inside this function) */ 1418c2c66affSColin Finck ObDereferenceObject(DriverObject); 1419c2c66affSColin Finck 1420c2c66affSColin Finck /* Return unloading failure */ 1421c2c66affSColin Finck return STATUS_INVALID_DEVICE_REQUEST; 1422c2c66affSColin Finck } 1423c2c66affSColin Finck } 1424c2c66affSColin Finck 1425c2c66affSColin Finck VOID 1426c2c66affSColin Finck NTAPI 1427c2c66affSColin Finck IopReinitializeDrivers(VOID) 1428c2c66affSColin Finck { 1429c2c66affSColin Finck PDRIVER_REINIT_ITEM ReinitItem; 1430c2c66affSColin Finck PLIST_ENTRY Entry; 1431c2c66affSColin Finck 1432c2c66affSColin Finck /* Get the first entry and start looping */ 1433c2c66affSColin Finck Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead, 1434c2c66affSColin Finck &DriverReinitListLock); 1435c2c66affSColin Finck while (Entry) 1436c2c66affSColin Finck { 1437c2c66affSColin Finck /* Get the item */ 1438c2c66affSColin Finck ReinitItem = CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry); 1439c2c66affSColin Finck 1440c2c66affSColin Finck /* Increment reinitialization counter */ 1441c2c66affSColin Finck ReinitItem->DriverObject->DriverExtension->Count++; 1442c2c66affSColin Finck 1443c2c66affSColin Finck /* Remove the device object flag */ 1444c2c66affSColin Finck ReinitItem->DriverObject->Flags &= ~DRVO_REINIT_REGISTERED; 1445c2c66affSColin Finck 1446c2c66affSColin Finck /* Call the routine */ 1447c2c66affSColin Finck ReinitItem->ReinitRoutine(ReinitItem->DriverObject, 1448c2c66affSColin Finck ReinitItem->Context, 1449c2c66affSColin Finck ReinitItem->DriverObject-> 1450c2c66affSColin Finck DriverExtension->Count); 1451c2c66affSColin Finck 1452c2c66affSColin Finck /* Free the entry */ 1453c2c66affSColin Finck ExFreePool(Entry); 1454c2c66affSColin Finck 1455c2c66affSColin Finck /* Move to the next one */ 1456c2c66affSColin Finck Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead, 1457c2c66affSColin Finck &DriverReinitListLock); 1458c2c66affSColin Finck } 1459c2c66affSColin Finck } 1460c2c66affSColin Finck 1461c2c66affSColin Finck VOID 1462c2c66affSColin Finck NTAPI 1463c2c66affSColin Finck IopReinitializeBootDrivers(VOID) 1464c2c66affSColin Finck { 1465c2c66affSColin Finck PDRIVER_REINIT_ITEM ReinitItem; 1466c2c66affSColin Finck PLIST_ENTRY Entry; 1467c2c66affSColin Finck 1468c2c66affSColin Finck /* Get the first entry and start looping */ 1469c2c66affSColin Finck Entry = ExInterlockedRemoveHeadList(&DriverBootReinitListHead, 1470c2c66affSColin Finck &DriverBootReinitListLock); 1471c2c66affSColin Finck while (Entry) 1472c2c66affSColin Finck { 1473c2c66affSColin Finck /* Get the item */ 1474c2c66affSColin Finck ReinitItem = CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry); 1475c2c66affSColin Finck 1476c2c66affSColin Finck /* Increment reinitialization counter */ 1477c2c66affSColin Finck ReinitItem->DriverObject->DriverExtension->Count++; 1478c2c66affSColin Finck 1479c2c66affSColin Finck /* Remove the device object flag */ 1480c2c66affSColin Finck ReinitItem->DriverObject->Flags &= ~DRVO_BOOTREINIT_REGISTERED; 1481c2c66affSColin Finck 1482c2c66affSColin Finck /* Call the routine */ 1483c2c66affSColin Finck ReinitItem->ReinitRoutine(ReinitItem->DriverObject, 1484c2c66affSColin Finck ReinitItem->Context, 1485c2c66affSColin Finck ReinitItem->DriverObject-> 1486c2c66affSColin Finck DriverExtension->Count); 1487c2c66affSColin Finck 1488c2c66affSColin Finck /* Free the entry */ 1489c2c66affSColin Finck ExFreePool(Entry); 1490c2c66affSColin Finck 1491c2c66affSColin Finck /* Move to the next one */ 1492c2c66affSColin Finck Entry = ExInterlockedRemoveHeadList(&DriverBootReinitListHead, 1493c2c66affSColin Finck &DriverBootReinitListLock); 1494c2c66affSColin Finck } 14952839c850SVictor Perevertkin 14962839c850SVictor Perevertkin /* Wait for all device actions being finished*/ 14972839c850SVictor Perevertkin KeWaitForSingleObject(&PiEnumerationFinished, Executive, KernelMode, FALSE, NULL); 1498c2c66affSColin Finck } 1499c2c66affSColin Finck 1500e18a32dfSVictor Perevertkin /* PUBLIC FUNCTIONS ***********************************************************/ 1501e18a32dfSVictor Perevertkin 1502e18a32dfSVictor Perevertkin /* 1503e18a32dfSVictor Perevertkin * @implemented 1504e18a32dfSVictor Perevertkin */ 1505c2c66affSColin Finck NTSTATUS 1506c2c66affSColin Finck NTAPI 1507e18a32dfSVictor Perevertkin IoCreateDriver( 1508e18a32dfSVictor Perevertkin _In_opt_ PUNICODE_STRING DriverName, 1509e18a32dfSVictor Perevertkin _In_ PDRIVER_INITIALIZE InitializationFunction) 1510c2c66affSColin Finck { 1511c2c66affSColin Finck WCHAR NameBuffer[100]; 1512c2c66affSColin Finck USHORT NameLength; 1513c2c66affSColin Finck UNICODE_STRING LocalDriverName; 1514c2c66affSColin Finck NTSTATUS Status; 1515c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes; 1516c2c66affSColin Finck ULONG ObjectSize; 1517c2c66affSColin Finck PDRIVER_OBJECT DriverObject; 1518c2c66affSColin Finck UNICODE_STRING ServiceKeyName; 1519c2c66affSColin Finck HANDLE hDriver; 1520c2c66affSColin Finck ULONG i, RetryCount = 0; 1521c2c66affSColin Finck 1522c2c66affSColin Finck try_again: 1523c2c66affSColin Finck /* First, create a unique name for the driver if we don't have one */ 1524c2c66affSColin Finck if (!DriverName) 1525c2c66affSColin Finck { 1526c2c66affSColin Finck /* Create a random name and set up the string */ 1527c2c66affSColin Finck NameLength = (USHORT)swprintf(NameBuffer, 1528c2c66affSColin Finck DRIVER_ROOT_NAME L"%08u", 1529c2c66affSColin Finck KeTickCount.LowPart); 1530c2c66affSColin Finck LocalDriverName.Length = NameLength * sizeof(WCHAR); 1531c2c66affSColin Finck LocalDriverName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL); 1532c2c66affSColin Finck LocalDriverName.Buffer = NameBuffer; 1533c2c66affSColin Finck } 1534c2c66affSColin Finck else 1535c2c66affSColin Finck { 1536c2c66affSColin Finck /* So we can avoid another code path, use a local var */ 1537c2c66affSColin Finck LocalDriverName = *DriverName; 1538c2c66affSColin Finck } 1539c2c66affSColin Finck 1540c2c66affSColin Finck /* Initialize the Attributes */ 1541c2c66affSColin Finck ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(EXTENDED_DRIVER_EXTENSION); 1542c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes, 1543c2c66affSColin Finck &LocalDriverName, 1544c2c66affSColin Finck OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 1545c2c66affSColin Finck NULL, 1546c2c66affSColin Finck NULL); 1547c2c66affSColin Finck 1548c2c66affSColin Finck /* Create the Object */ 1549c2c66affSColin Finck Status = ObCreateObject(KernelMode, 1550c2c66affSColin Finck IoDriverObjectType, 1551c2c66affSColin Finck &ObjectAttributes, 1552c2c66affSColin Finck KernelMode, 1553c2c66affSColin Finck NULL, 1554c2c66affSColin Finck ObjectSize, 1555c2c66affSColin Finck 0, 1556c2c66affSColin Finck 0, 1557c2c66affSColin Finck (PVOID*)&DriverObject); 1558c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status; 1559c2c66affSColin Finck 1560c2c66affSColin Finck DPRINT("IopCreateDriver(): created DO %p\n", DriverObject); 1561c2c66affSColin Finck 1562c2c66affSColin Finck /* Set up the Object */ 1563c2c66affSColin Finck RtlZeroMemory(DriverObject, ObjectSize); 1564c2c66affSColin Finck DriverObject->Type = IO_TYPE_DRIVER; 1565c2c66affSColin Finck DriverObject->Size = sizeof(DRIVER_OBJECT); 156645012aa4SHermès Bélusca-Maïto DriverObject->Flags = DRVO_BUILTIN_DRIVER; 1567c2c66affSColin Finck DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1); 1568c2c66affSColin Finck DriverObject->DriverExtension->DriverObject = DriverObject; 1569c2c66affSColin Finck DriverObject->DriverInit = InitializationFunction; 1570c2c66affSColin Finck /* Loop all Major Functions */ 1571c2c66affSColin Finck for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) 1572c2c66affSColin Finck { 1573c2c66affSColin Finck /* Invalidate each function */ 1574c2c66affSColin Finck DriverObject->MajorFunction[i] = IopInvalidDeviceRequest; 1575c2c66affSColin Finck } 1576c2c66affSColin Finck 1577c2c66affSColin Finck /* Set up the service key name buffer */ 1578e18a32dfSVictor Perevertkin ServiceKeyName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL); 1579e18a32dfSVictor Perevertkin ServiceKeyName.Buffer = ExAllocatePoolWithTag(PagedPool, LocalDriverName.MaximumLength, TAG_IO); 1580c2c66affSColin Finck if (!ServiceKeyName.Buffer) 1581c2c66affSColin Finck { 1582c2c66affSColin Finck /* Fail */ 1583c2c66affSColin Finck ObMakeTemporaryObject(DriverObject); 1584c2c66affSColin Finck ObDereferenceObject(DriverObject); 1585c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 1586c2c66affSColin Finck } 1587c2c66affSColin Finck 1588e18a32dfSVictor Perevertkin /* For builtin drivers, the ServiceKeyName is equal to DriverName */ 1589e18a32dfSVictor Perevertkin RtlCopyUnicodeString(&ServiceKeyName, &LocalDriverName); 1590e18a32dfSVictor Perevertkin ServiceKeyName.Buffer[ServiceKeyName.Length / sizeof(WCHAR)] = UNICODE_NULL; 1591c2c66affSColin Finck DriverObject->DriverExtension->ServiceKeyName = ServiceKeyName; 1592c2c66affSColin Finck 1593c2c66affSColin Finck /* Make a copy of the driver name to store in the driver object */ 1594c2c66affSColin Finck DriverObject->DriverName.MaximumLength = LocalDriverName.Length; 1595c2c66affSColin Finck DriverObject->DriverName.Buffer = ExAllocatePoolWithTag(PagedPool, 1596c2c66affSColin Finck DriverObject->DriverName.MaximumLength, 1597c2c66affSColin Finck TAG_IO); 1598c2c66affSColin Finck if (!DriverObject->DriverName.Buffer) 1599c2c66affSColin Finck { 1600c2c66affSColin Finck /* Fail */ 1601c2c66affSColin Finck ObMakeTemporaryObject(DriverObject); 1602c2c66affSColin Finck ObDereferenceObject(DriverObject); 1603c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 1604c2c66affSColin Finck } 1605c2c66affSColin Finck 1606e18a32dfSVictor Perevertkin RtlCopyUnicodeString(&DriverObject->DriverName, &LocalDriverName); 1607c2c66affSColin Finck 1608c2c66affSColin Finck /* Add the Object and get its handle */ 1609c2c66affSColin Finck Status = ObInsertObject(DriverObject, 1610c2c66affSColin Finck NULL, 1611c2c66affSColin Finck FILE_READ_DATA, 1612c2c66affSColin Finck 0, 1613c2c66affSColin Finck NULL, 1614c2c66affSColin Finck &hDriver); 1615c2c66affSColin Finck 1616c2c66affSColin Finck /* Eliminate small possibility when this function is called more than 1617c2c66affSColin Finck once in a row, and KeTickCount doesn't get enough time to change */ 1618c2c66affSColin Finck if (!DriverName && (Status == STATUS_OBJECT_NAME_COLLISION) && (RetryCount < 100)) 1619c2c66affSColin Finck { 1620c2c66affSColin Finck RetryCount++; 1621c2c66affSColin Finck goto try_again; 1622c2c66affSColin Finck } 1623c2c66affSColin Finck 1624c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status; 1625c2c66affSColin Finck 1626c2c66affSColin Finck /* Now reference it */ 1627c2c66affSColin Finck Status = ObReferenceObjectByHandle(hDriver, 1628c2c66affSColin Finck 0, 1629c2c66affSColin Finck IoDriverObjectType, 1630c2c66affSColin Finck KernelMode, 1631c2c66affSColin Finck (PVOID*)&DriverObject, 1632c2c66affSColin Finck NULL); 1633c2c66affSColin Finck 1634c2c66affSColin Finck /* Close the extra handle */ 1635c2c66affSColin Finck ZwClose(hDriver); 1636c2c66affSColin Finck 1637c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1638c2c66affSColin Finck { 1639c2c66affSColin Finck /* Fail */ 1640c2c66affSColin Finck ObMakeTemporaryObject(DriverObject); 1641c2c66affSColin Finck ObDereferenceObject(DriverObject); 1642c2c66affSColin Finck return Status; 1643c2c66affSColin Finck } 1644c2c66affSColin Finck 1645c2c66affSColin Finck /* Finally, call its init function */ 1646c2c66affSColin Finck DPRINT("Calling driver entrypoint at %p\n", InitializationFunction); 1647e18a32dfSVictor Perevertkin Status = (*InitializationFunction)(DriverObject, NULL); 1648c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1649c2c66affSColin Finck { 1650c2c66affSColin Finck /* If it didn't work, then kill the object */ 1651c2c66affSColin Finck DPRINT1("'%wZ' initialization failed, status (0x%08lx)\n", DriverName, Status); 1652c2c66affSColin Finck ObMakeTemporaryObject(DriverObject); 1653c2c66affSColin Finck ObDereferenceObject(DriverObject); 1654c2c66affSColin Finck return Status; 1655c2c66affSColin Finck } 1656c2c66affSColin Finck 1657e18a32dfSVictor Perevertkin // Windows does this fixup - keep it for compatibility 1658c2c66affSColin Finck for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) 1659c2c66affSColin Finck { 1660c2c66affSColin Finck /* 1661c2c66affSColin Finck * Make sure the driver didn't set any dispatch entry point to NULL! 1662c2c66affSColin Finck * Doing so is illegal; drivers shouldn't touch entry points they 1663c2c66affSColin Finck * do not implement. 1664c2c66affSColin Finck */ 1665c2c66affSColin Finck 1666c2c66affSColin Finck /* Check if it did so anyway */ 1667c2c66affSColin Finck if (!DriverObject->MajorFunction[i]) 1668c2c66affSColin Finck { 1669c2c66affSColin Finck /* Print a warning in the debug log */ 1670c2c66affSColin Finck DPRINT1("Driver <%wZ> set DriverObject->MajorFunction[%lu] to NULL!\n", 1671c2c66affSColin Finck &DriverObject->DriverName, i); 1672c2c66affSColin Finck 1673c2c66affSColin Finck /* Fix it up */ 1674c2c66affSColin Finck DriverObject->MajorFunction[i] = IopInvalidDeviceRequest; 1675c2c66affSColin Finck } 1676c2c66affSColin Finck } 1677c2c66affSColin Finck 1678c2c66affSColin Finck /* Return the Status */ 1679c2c66affSColin Finck return Status; 1680c2c66affSColin Finck } 1681c2c66affSColin Finck 1682c2c66affSColin Finck /* 1683c2c66affSColin Finck * @implemented 1684c2c66affSColin Finck */ 1685c2c66affSColin Finck VOID 1686c2c66affSColin Finck NTAPI 1687c2c66affSColin Finck IoDeleteDriver(IN PDRIVER_OBJECT DriverObject) 1688c2c66affSColin Finck { 1689c2c66affSColin Finck /* Simply dereference the Object */ 1690c2c66affSColin Finck ObDereferenceObject(DriverObject); 1691c2c66affSColin Finck } 1692c2c66affSColin Finck 1693c2c66affSColin Finck /* 1694c2c66affSColin Finck * @implemented 1695c2c66affSColin Finck */ 1696c2c66affSColin Finck VOID 1697c2c66affSColin Finck NTAPI 1698c2c66affSColin Finck IoRegisterBootDriverReinitialization(IN PDRIVER_OBJECT DriverObject, 1699c2c66affSColin Finck IN PDRIVER_REINITIALIZE ReinitRoutine, 1700c2c66affSColin Finck IN PVOID Context) 1701c2c66affSColin Finck { 1702c2c66affSColin Finck PDRIVER_REINIT_ITEM ReinitItem; 1703c2c66affSColin Finck 1704c2c66affSColin Finck /* Allocate the entry */ 1705c2c66affSColin Finck ReinitItem = ExAllocatePoolWithTag(NonPagedPool, 1706c2c66affSColin Finck sizeof(DRIVER_REINIT_ITEM), 1707c2c66affSColin Finck TAG_REINIT); 1708c2c66affSColin Finck if (!ReinitItem) return; 1709c2c66affSColin Finck 1710c2c66affSColin Finck /* Fill it out */ 1711c2c66affSColin Finck ReinitItem->DriverObject = DriverObject; 1712c2c66affSColin Finck ReinitItem->ReinitRoutine = ReinitRoutine; 1713c2c66affSColin Finck ReinitItem->Context = Context; 1714c2c66affSColin Finck 1715c2c66affSColin Finck /* Set the Driver Object flag and insert the entry into the list */ 1716c2c66affSColin Finck DriverObject->Flags |= DRVO_BOOTREINIT_REGISTERED; 1717c2c66affSColin Finck ExInterlockedInsertTailList(&DriverBootReinitListHead, 1718c2c66affSColin Finck &ReinitItem->ItemEntry, 1719c2c66affSColin Finck &DriverBootReinitListLock); 1720c2c66affSColin Finck } 1721c2c66affSColin Finck 1722c2c66affSColin Finck /* 1723c2c66affSColin Finck * @implemented 1724c2c66affSColin Finck */ 1725c2c66affSColin Finck VOID 1726c2c66affSColin Finck NTAPI 1727c2c66affSColin Finck IoRegisterDriverReinitialization(IN PDRIVER_OBJECT DriverObject, 1728c2c66affSColin Finck IN PDRIVER_REINITIALIZE ReinitRoutine, 1729c2c66affSColin Finck IN PVOID Context) 1730c2c66affSColin Finck { 1731c2c66affSColin Finck PDRIVER_REINIT_ITEM ReinitItem; 1732c2c66affSColin Finck 1733c2c66affSColin Finck /* Allocate the entry */ 1734c2c66affSColin Finck ReinitItem = ExAllocatePoolWithTag(NonPagedPool, 1735c2c66affSColin Finck sizeof(DRIVER_REINIT_ITEM), 1736c2c66affSColin Finck TAG_REINIT); 1737c2c66affSColin Finck if (!ReinitItem) return; 1738c2c66affSColin Finck 1739c2c66affSColin Finck /* Fill it out */ 1740c2c66affSColin Finck ReinitItem->DriverObject = DriverObject; 1741c2c66affSColin Finck ReinitItem->ReinitRoutine = ReinitRoutine; 1742c2c66affSColin Finck ReinitItem->Context = Context; 1743c2c66affSColin Finck 1744c2c66affSColin Finck /* Set the Driver Object flag and insert the entry into the list */ 1745c2c66affSColin Finck DriverObject->Flags |= DRVO_REINIT_REGISTERED; 1746c2c66affSColin Finck ExInterlockedInsertTailList(&DriverReinitListHead, 1747c2c66affSColin Finck &ReinitItem->ItemEntry, 1748c2c66affSColin Finck &DriverReinitListLock); 1749c2c66affSColin Finck } 1750c2c66affSColin Finck 1751c2c66affSColin Finck /* 1752c2c66affSColin Finck * @implemented 1753c2c66affSColin Finck */ 1754c2c66affSColin Finck NTSTATUS 1755c2c66affSColin Finck NTAPI 1756c2c66affSColin Finck IoAllocateDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, 1757c2c66affSColin Finck IN PVOID ClientIdentificationAddress, 1758c2c66affSColin Finck IN ULONG DriverObjectExtensionSize, 1759c2c66affSColin Finck OUT PVOID *DriverObjectExtension) 1760c2c66affSColin Finck { 1761c2c66affSColin Finck KIRQL OldIrql; 1762c2c66affSColin Finck PIO_CLIENT_EXTENSION DriverExtensions, NewDriverExtension; 1763c2c66affSColin Finck BOOLEAN Inserted = FALSE; 1764c2c66affSColin Finck 1765c2c66affSColin Finck /* Assume failure */ 1766c2c66affSColin Finck *DriverObjectExtension = NULL; 1767c2c66affSColin Finck 1768c2c66affSColin Finck /* Allocate the extension */ 1769c2c66affSColin Finck NewDriverExtension = ExAllocatePoolWithTag(NonPagedPool, 1770c2c66affSColin Finck sizeof(IO_CLIENT_EXTENSION) + 1771c2c66affSColin Finck DriverObjectExtensionSize, 1772c2c66affSColin Finck TAG_DRIVER_EXTENSION); 1773c2c66affSColin Finck if (!NewDriverExtension) return STATUS_INSUFFICIENT_RESOURCES; 1774c2c66affSColin Finck 1775c2c66affSColin Finck /* Clear the extension for teh caller */ 1776c2c66affSColin Finck RtlZeroMemory(NewDriverExtension, 1777c2c66affSColin Finck sizeof(IO_CLIENT_EXTENSION) + DriverObjectExtensionSize); 1778c2c66affSColin Finck 1779c2c66affSColin Finck /* Acqure lock */ 1780c2c66affSColin Finck OldIrql = KeRaiseIrqlToDpcLevel(); 1781c2c66affSColin Finck 1782c2c66affSColin Finck /* Fill out the extension */ 1783c2c66affSColin Finck NewDriverExtension->ClientIdentificationAddress = ClientIdentificationAddress; 1784c2c66affSColin Finck 1785c2c66affSColin Finck /* Loop the current extensions */ 1786c2c66affSColin Finck DriverExtensions = IoGetDrvObjExtension(DriverObject)-> 1787c2c66affSColin Finck ClientDriverExtension; 1788c2c66affSColin Finck while (DriverExtensions) 1789c2c66affSColin Finck { 1790c2c66affSColin Finck /* Check if the identifier matches */ 1791c2c66affSColin Finck if (DriverExtensions->ClientIdentificationAddress == 1792c2c66affSColin Finck ClientIdentificationAddress) 1793c2c66affSColin Finck { 1794c2c66affSColin Finck /* We have a collision, break out */ 1795c2c66affSColin Finck break; 1796c2c66affSColin Finck } 1797c2c66affSColin Finck 1798c2c66affSColin Finck /* Go to the next one */ 1799c2c66affSColin Finck DriverExtensions = DriverExtensions->NextExtension; 1800c2c66affSColin Finck } 1801c2c66affSColin Finck 1802c2c66affSColin Finck /* Check if we didn't collide */ 1803c2c66affSColin Finck if (!DriverExtensions) 1804c2c66affSColin Finck { 1805c2c66affSColin Finck /* Link this one in */ 1806c2c66affSColin Finck NewDriverExtension->NextExtension = 1807c2c66affSColin Finck IoGetDrvObjExtension(DriverObject)->ClientDriverExtension; 1808c2c66affSColin Finck IoGetDrvObjExtension(DriverObject)->ClientDriverExtension = 1809c2c66affSColin Finck NewDriverExtension; 1810c2c66affSColin Finck Inserted = TRUE; 1811c2c66affSColin Finck } 1812c2c66affSColin Finck 1813c2c66affSColin Finck /* Release the lock */ 1814c2c66affSColin Finck KeLowerIrql(OldIrql); 1815c2c66affSColin Finck 1816c2c66affSColin Finck /* Check if insertion failed */ 1817c2c66affSColin Finck if (!Inserted) 1818c2c66affSColin Finck { 1819c2c66affSColin Finck /* Free the entry and fail */ 1820c2c66affSColin Finck ExFreePoolWithTag(NewDriverExtension, TAG_DRIVER_EXTENSION); 1821c2c66affSColin Finck return STATUS_OBJECT_NAME_COLLISION; 1822c2c66affSColin Finck } 1823c2c66affSColin Finck 1824c2c66affSColin Finck /* Otherwise, return the pointer */ 1825c2c66affSColin Finck *DriverObjectExtension = NewDriverExtension + 1; 1826c2c66affSColin Finck return STATUS_SUCCESS; 1827c2c66affSColin Finck } 1828c2c66affSColin Finck 1829c2c66affSColin Finck /* 1830c2c66affSColin Finck * @implemented 1831c2c66affSColin Finck */ 1832c2c66affSColin Finck PVOID 1833c2c66affSColin Finck NTAPI 1834c2c66affSColin Finck IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, 1835c2c66affSColin Finck IN PVOID ClientIdentificationAddress) 1836c2c66affSColin Finck { 1837c2c66affSColin Finck KIRQL OldIrql; 1838c2c66affSColin Finck PIO_CLIENT_EXTENSION DriverExtensions; 1839c2c66affSColin Finck 1840c2c66affSColin Finck /* Acquire lock */ 1841c2c66affSColin Finck OldIrql = KeRaiseIrqlToDpcLevel(); 1842c2c66affSColin Finck 1843c2c66affSColin Finck /* Loop the list until we find the right one */ 1844c2c66affSColin Finck DriverExtensions = IoGetDrvObjExtension(DriverObject)->ClientDriverExtension; 1845c2c66affSColin Finck while (DriverExtensions) 1846c2c66affSColin Finck { 1847c2c66affSColin Finck /* Check for a match */ 1848c2c66affSColin Finck if (DriverExtensions->ClientIdentificationAddress == 1849c2c66affSColin Finck ClientIdentificationAddress) 1850c2c66affSColin Finck { 1851c2c66affSColin Finck /* Break out */ 1852c2c66affSColin Finck break; 1853c2c66affSColin Finck } 1854c2c66affSColin Finck 1855c2c66affSColin Finck /* Keep looping */ 1856c2c66affSColin Finck DriverExtensions = DriverExtensions->NextExtension; 1857c2c66affSColin Finck } 1858c2c66affSColin Finck 1859c2c66affSColin Finck /* Release lock */ 1860c2c66affSColin Finck KeLowerIrql(OldIrql); 1861c2c66affSColin Finck 1862c2c66affSColin Finck /* Return nothing or the extension */ 1863c2c66affSColin Finck if (!DriverExtensions) return NULL; 1864c2c66affSColin Finck return DriverExtensions + 1; 1865c2c66affSColin Finck } 1866c2c66affSColin Finck 1867c2c66affSColin Finck NTSTATUS 1868a6a3aa0fSVictor Perevertkin IopLoadDriver( 18694c95339dSVictor Perevertkin _In_ HANDLE ServiceHandle, 18704c95339dSVictor Perevertkin _Out_ PDRIVER_OBJECT *DriverObject) 1871c2c66affSColin Finck { 1872c2c66affSColin Finck UNICODE_STRING ImagePath; 1873c2c66affSColin Finck NTSTATUS Status; 1874c2c66affSColin Finck PLDR_DATA_TABLE_ENTRY ModuleObject; 1875c2c66affSColin Finck PVOID BaseAddress; 1876c2c66affSColin Finck 18774c95339dSVictor Perevertkin PKEY_VALUE_FULL_INFORMATION kvInfo; 18784c95339dSVictor Perevertkin Status = IopGetRegistryValue(ServiceHandle, L"ImagePath", &kvInfo); 18794c95339dSVictor Perevertkin if (NT_SUCCESS(Status)) 1880c2c66affSColin Finck { 18814c95339dSVictor Perevertkin if (kvInfo->Type != REG_EXPAND_SZ || kvInfo->DataLength == 0) 1882c2c66affSColin Finck { 18834c95339dSVictor Perevertkin ExFreePool(kvInfo); 18844c95339dSVictor Perevertkin return STATUS_ILL_FORMED_SERVICE_ENTRY; 1885c2c66affSColin Finck } 1886c2c66affSColin Finck 18874c95339dSVictor Perevertkin ImagePath.Length = kvInfo->DataLength - sizeof(UNICODE_NULL), 18884c95339dSVictor Perevertkin ImagePath.MaximumLength = kvInfo->DataLength, 18894c95339dSVictor Perevertkin ImagePath.Buffer = ExAllocatePoolWithTag(PagedPool, ImagePath.MaximumLength, TAG_RTLREGISTRY); 18904c95339dSVictor Perevertkin if (!ImagePath.Buffer) 1891c2c66affSColin Finck { 18924c95339dSVictor Perevertkin ExFreePool(kvInfo); 18934c95339dSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES; 18944c95339dSVictor Perevertkin } 18954c95339dSVictor Perevertkin 18964c95339dSVictor Perevertkin RtlMoveMemory(ImagePath.Buffer, 18974c95339dSVictor Perevertkin (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset), 18984c95339dSVictor Perevertkin ImagePath.Length); 18994c95339dSVictor Perevertkin ExFreePool(kvInfo); 19004c95339dSVictor Perevertkin } 19014c95339dSVictor Perevertkin else 19024c95339dSVictor Perevertkin { 1903c2c66affSColin Finck return Status; 1904c2c66affSColin Finck } 1905c2c66affSColin Finck 1906c2c66affSColin Finck /* 1907c2c66affSColin Finck * Normalize the image path for all later processing. 1908c2c66affSColin Finck */ 19094c95339dSVictor Perevertkin Status = IopNormalizeImagePath(&ImagePath, NULL); 1910c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1911c2c66affSColin Finck { 1912c2c66affSColin Finck DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status); 1913c2c66affSColin Finck return Status; 1914c2c66affSColin Finck } 1915c2c66affSColin Finck 1916c2c66affSColin Finck DPRINT("FullImagePath: '%wZ'\n", &ImagePath); 1917c2c66affSColin Finck 1918c2c66affSColin Finck KeEnterCriticalRegion(); 1919c2c66affSColin Finck ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE); 1920c2c66affSColin Finck 1921c2c66affSColin Finck /* 1922c2c66affSColin Finck * Load the driver module 1923c2c66affSColin Finck */ 1924c2c66affSColin Finck DPRINT("Loading module from %wZ\n", &ImagePath); 1925c2c66affSColin Finck Status = MmLoadSystemImage(&ImagePath, NULL, NULL, 0, (PVOID)&ModuleObject, &BaseAddress); 19264c95339dSVictor Perevertkin RtlFreeUnicodeString(&ImagePath); 19274c95339dSVictor Perevertkin 1928c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1929c2c66affSColin Finck { 1930c2c66affSColin Finck DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status); 1931c2c66affSColin Finck ExReleaseResourceLite(&IopDriverLoadResource); 1932c2c66affSColin Finck KeLeaveCriticalRegion(); 1933c2c66affSColin Finck return Status; 1934c2c66affSColin Finck } 1935c2c66affSColin Finck 19364c95339dSVictor Perevertkin // Display the loading message 19374c95339dSVictor Perevertkin ULONG infoLength; 19384c95339dSVictor Perevertkin Status = ZwQueryKey(ServiceHandle, KeyBasicInformation, NULL, 0, &infoLength); 19394c95339dSVictor Perevertkin if (Status == STATUS_BUFFER_TOO_SMALL) 19404c95339dSVictor Perevertkin { 19414c95339dSVictor Perevertkin PKEY_BASIC_INFORMATION servName = ExAllocatePoolWithTag(PagedPool, infoLength, TAG_IO); 19424c95339dSVictor Perevertkin if (servName) 19434c95339dSVictor Perevertkin { 19444c95339dSVictor Perevertkin Status = ZwQueryKey(ServiceHandle, 19454c95339dSVictor Perevertkin KeyBasicInformation, 19464c95339dSVictor Perevertkin servName, 19474c95339dSVictor Perevertkin infoLength, 19484c95339dSVictor Perevertkin &infoLength); 19494c95339dSVictor Perevertkin if (NT_SUCCESS(Status)) 19504c95339dSVictor Perevertkin { 19514c95339dSVictor Perevertkin UNICODE_STRING serviceName = { 19524c95339dSVictor Perevertkin .Length = servName->NameLength, 19534c95339dSVictor Perevertkin .MaximumLength = servName->NameLength, 19544c95339dSVictor Perevertkin .Buffer = servName->Name 19554c95339dSVictor Perevertkin }; 19564c95339dSVictor Perevertkin 19574c95339dSVictor Perevertkin IopDisplayLoadingMessage(&serviceName); 19584c95339dSVictor Perevertkin } 19594c95339dSVictor Perevertkin ExFreePoolWithTag(servName, TAG_IO); 19604c95339dSVictor Perevertkin } 19614c95339dSVictor Perevertkin } 1962c2c66affSColin Finck 1963e18a32dfSVictor Perevertkin NTSTATUS driverEntryStatus; 19646f0e37b0SVictor Perevertkin Status = IopInitializeDriverModule(ModuleObject, 19654c95339dSVictor Perevertkin ServiceHandle, 1966e18a32dfSVictor Perevertkin DriverObject, 1967e18a32dfSVictor Perevertkin &driverEntryStatus); 1968c2c66affSColin Finck if (!NT_SUCCESS(Status)) 1969c2c66affSColin Finck { 1970c2c66affSColin Finck DPRINT1("IopInitializeDriverModule() failed (Status %lx)\n", Status); 1971c2c66affSColin Finck } 1972c2c66affSColin Finck 1973c2c66affSColin Finck ExReleaseResourceLite(&IopDriverLoadResource); 1974c2c66affSColin Finck KeLeaveCriticalRegion(); 1975c2c66affSColin Finck 1976c2c66affSColin Finck return Status; 1977c2c66affSColin Finck } 1978c2c66affSColin Finck 1979a6a3aa0fSVictor Perevertkin static 1980a6a3aa0fSVictor Perevertkin VOID 1981a6a3aa0fSVictor Perevertkin NTAPI 1982a6a3aa0fSVictor Perevertkin IopLoadUnloadDriverWorker( 1983a6a3aa0fSVictor Perevertkin _Inout_ PVOID Parameter) 1984a6a3aa0fSVictor Perevertkin { 1985a6a3aa0fSVictor Perevertkin PLOAD_UNLOAD_PARAMS LoadParams = Parameter; 1986a6a3aa0fSVictor Perevertkin 1987a6a3aa0fSVictor Perevertkin ASSERT(PsGetCurrentProcess() == PsInitialSystemProcess); 1988a6a3aa0fSVictor Perevertkin 1989a6a3aa0fSVictor Perevertkin if (LoadParams->DriverObject) 1990a6a3aa0fSVictor Perevertkin { 1991a6a3aa0fSVictor Perevertkin // unload request 1992a6a3aa0fSVictor Perevertkin LoadParams->DriverObject->DriverUnload(LoadParams->DriverObject); 1993a6a3aa0fSVictor Perevertkin LoadParams->Status = STATUS_SUCCESS; 1994a6a3aa0fSVictor Perevertkin } 1995a6a3aa0fSVictor Perevertkin else 1996a6a3aa0fSVictor Perevertkin { 1997a6a3aa0fSVictor Perevertkin // load request 19984c95339dSVictor Perevertkin HANDLE serviceHandle; 19994c95339dSVictor Perevertkin NTSTATUS status; 20004c95339dSVictor Perevertkin status = IopOpenRegistryKeyEx(&serviceHandle, NULL, LoadParams->RegistryPath, KEY_READ); 20014c95339dSVictor Perevertkin if (!NT_SUCCESS(status)) 20024c95339dSVictor Perevertkin { 20034c95339dSVictor Perevertkin LoadParams->Status = status; 20044c95339dSVictor Perevertkin } 20054c95339dSVictor Perevertkin else 20064c95339dSVictor Perevertkin { 20074c95339dSVictor Perevertkin LoadParams->Status = IopLoadDriver(serviceHandle, &LoadParams->DriverObject); 20084c95339dSVictor Perevertkin ZwClose(serviceHandle); 20094c95339dSVictor Perevertkin } 2010a6a3aa0fSVictor Perevertkin } 2011a6a3aa0fSVictor Perevertkin 2012a6a3aa0fSVictor Perevertkin if (LoadParams->SetEvent) 2013a6a3aa0fSVictor Perevertkin { 2014a6a3aa0fSVictor Perevertkin KeSetEvent(&LoadParams->Event, 0, FALSE); 2015a6a3aa0fSVictor Perevertkin } 2016a6a3aa0fSVictor Perevertkin } 2017a6a3aa0fSVictor Perevertkin 2018a6a3aa0fSVictor Perevertkin /** 2019a6a3aa0fSVictor Perevertkin * @brief Process load and unload driver operations. This is mostly for NtLoadDriver 2020a6a3aa0fSVictor Perevertkin * and NtUnloadDriver, because their code should run inside PsInitialSystemProcess 2021a6a3aa0fSVictor Perevertkin * 2022a6a3aa0fSVictor Perevertkin * @param[in] RegistryPath The registry path 2023a6a3aa0fSVictor Perevertkin * @param DriverObject The driver object 2024a6a3aa0fSVictor Perevertkin * 2025a6a3aa0fSVictor Perevertkin * @return Status of the operation 2026a6a3aa0fSVictor Perevertkin */ 2027a6a3aa0fSVictor Perevertkin NTSTATUS 2028a6a3aa0fSVictor Perevertkin IopDoLoadUnloadDriver( 20294c95339dSVictor Perevertkin _In_opt_ PUNICODE_STRING RegistryPath, 2030a6a3aa0fSVictor Perevertkin _Inout_ PDRIVER_OBJECT *DriverObject) 2031a6a3aa0fSVictor Perevertkin { 2032a6a3aa0fSVictor Perevertkin LOAD_UNLOAD_PARAMS LoadParams; 2033a6a3aa0fSVictor Perevertkin 2034a6a3aa0fSVictor Perevertkin /* Prepare parameters block */ 2035a6a3aa0fSVictor Perevertkin LoadParams.RegistryPath = RegistryPath; 2036a6a3aa0fSVictor Perevertkin LoadParams.DriverObject = *DriverObject; 2037a6a3aa0fSVictor Perevertkin 2038a6a3aa0fSVictor Perevertkin if (PsGetCurrentProcess() != PsInitialSystemProcess) 2039a6a3aa0fSVictor Perevertkin { 2040a6a3aa0fSVictor Perevertkin LoadParams.SetEvent = TRUE; 2041a6a3aa0fSVictor Perevertkin KeInitializeEvent(&LoadParams.Event, NotificationEvent, FALSE); 2042a6a3aa0fSVictor Perevertkin 2043a6a3aa0fSVictor Perevertkin /* Initialize and queue a work item */ 2044a6a3aa0fSVictor Perevertkin ExInitializeWorkItem(&LoadParams.WorkItem, IopLoadUnloadDriverWorker, &LoadParams); 2045a6a3aa0fSVictor Perevertkin ExQueueWorkItem(&LoadParams.WorkItem, DelayedWorkQueue); 2046a6a3aa0fSVictor Perevertkin 2047a6a3aa0fSVictor Perevertkin /* And wait till it completes */ 2048a6a3aa0fSVictor Perevertkin KeWaitForSingleObject(&LoadParams.Event, UserRequest, KernelMode, FALSE, NULL); 2049a6a3aa0fSVictor Perevertkin } 2050a6a3aa0fSVictor Perevertkin else 2051a6a3aa0fSVictor Perevertkin { 2052a6a3aa0fSVictor Perevertkin /* If we're already in a system process, call it right here */ 2053a6a3aa0fSVictor Perevertkin LoadParams.SetEvent = FALSE; 2054a6a3aa0fSVictor Perevertkin IopLoadUnloadDriverWorker(&LoadParams); 2055a6a3aa0fSVictor Perevertkin } 2056a6a3aa0fSVictor Perevertkin 2057a6a3aa0fSVictor Perevertkin return LoadParams.Status; 2058a6a3aa0fSVictor Perevertkin } 2059a6a3aa0fSVictor Perevertkin 2060c2c66affSColin Finck /* 2061c2c66affSColin Finck * NtLoadDriver 2062c2c66affSColin Finck * 2063c2c66affSColin Finck * Loads a device driver. 2064c2c66affSColin Finck * 2065c2c66affSColin Finck * Parameters 2066c2c66affSColin Finck * DriverServiceName 2067c2c66affSColin Finck * Name of the service to load (registry key). 2068c2c66affSColin Finck * 2069c2c66affSColin Finck * Return Value 2070c2c66affSColin Finck * Status 2071c2c66affSColin Finck * 2072c2c66affSColin Finck * Status 2073c2c66affSColin Finck * implemented 2074c2c66affSColin Finck */ 2075c2c66affSColin Finck NTSTATUS NTAPI 2076c2c66affSColin Finck NtLoadDriver(IN PUNICODE_STRING DriverServiceName) 2077c2c66affSColin Finck { 207844511f08SHermès Bélusca-Maïto UNICODE_STRING CapturedServiceName = { 0, 0, NULL }; 2079c2c66affSColin Finck KPROCESSOR_MODE PreviousMode; 2080c2c66affSColin Finck PDRIVER_OBJECT DriverObject; 2081c2c66affSColin Finck NTSTATUS Status; 2082c2c66affSColin Finck 2083c2c66affSColin Finck PAGED_CODE(); 2084c2c66affSColin Finck 2085c2c66affSColin Finck PreviousMode = KeGetPreviousMode(); 2086c2c66affSColin Finck 208744511f08SHermès Bélusca-Maïto /* Need the appropriate priviliege */ 2088c2c66affSColin Finck if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode)) 2089c2c66affSColin Finck { 209044511f08SHermès Bélusca-Maïto DPRINT1("No load privilege!\n"); 2091c2c66affSColin Finck return STATUS_PRIVILEGE_NOT_HELD; 2092c2c66affSColin Finck } 2093c2c66affSColin Finck 209444511f08SHermès Bélusca-Maïto /* Capture the service name */ 209544511f08SHermès Bélusca-Maïto Status = ProbeAndCaptureUnicodeString(&CapturedServiceName, 2096c2c66affSColin Finck PreviousMode, 2097c2c66affSColin Finck DriverServiceName); 2098c2c66affSColin Finck if (!NT_SUCCESS(Status)) 2099a6a3aa0fSVictor Perevertkin { 2100c2c66affSColin Finck return Status; 2101a6a3aa0fSVictor Perevertkin } 2102c2c66affSColin Finck 210344511f08SHermès Bélusca-Maïto DPRINT("NtLoadDriver('%wZ')\n", &CapturedServiceName); 2104c2c66affSColin Finck 2105a748350fSHermès Bélusca-Maïto /* We need a service name */ 2106a748350fSHermès Bélusca-Maïto if (CapturedServiceName.Length == 0 || CapturedServiceName.Buffer == NULL) 2107a748350fSHermès Bélusca-Maïto { 2108a748350fSHermès Bélusca-Maïto ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 2109a748350fSHermès Bélusca-Maïto return STATUS_INVALID_PARAMETER; 2110a748350fSHermès Bélusca-Maïto } 2111a748350fSHermès Bélusca-Maïto 2112c2c66affSColin Finck /* Load driver and call its entry point */ 2113c2c66affSColin Finck DriverObject = NULL; 2114a6a3aa0fSVictor Perevertkin Status = IopDoLoadUnloadDriver(&CapturedServiceName, &DriverObject); 2115c2c66affSColin Finck 211644511f08SHermès Bélusca-Maïto ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode); 2117c2c66affSColin Finck return Status; 2118c2c66affSColin Finck } 2119c2c66affSColin Finck 2120c2c66affSColin Finck /* 2121c2c66affSColin Finck * NtUnloadDriver 2122c2c66affSColin Finck * 2123c2c66affSColin Finck * Unloads a legacy device driver. 2124c2c66affSColin Finck * 2125c2c66affSColin Finck * Parameters 2126c2c66affSColin Finck * DriverServiceName 2127c2c66affSColin Finck * Name of the service to unload (registry key). 2128c2c66affSColin Finck * 2129c2c66affSColin Finck * Return Value 2130c2c66affSColin Finck * Status 2131c2c66affSColin Finck * 2132c2c66affSColin Finck * Status 2133c2c66affSColin Finck * implemented 2134c2c66affSColin Finck */ 2135c2c66affSColin Finck 2136c2c66affSColin Finck NTSTATUS NTAPI 2137c2c66affSColin Finck NtUnloadDriver(IN PUNICODE_STRING DriverServiceName) 2138c2c66affSColin Finck { 2139c2c66affSColin Finck return IopUnloadDriver(DriverServiceName, FALSE); 2140c2c66affSColin Finck } 2141c2c66affSColin Finck 2142c2c66affSColin Finck /* EOF */ 2143