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>
1453de4fd9SVictor Perevertkin #define NDEBUG
15c2c66affSColin Finck #include <debug.h>
162b27d085SHermès Bélusca-Maïto #include <mm/ARM3/miarm.h>
17c2c66affSColin Finck
18c2c66affSColin Finck /* GLOBALS ********************************************************************/
19c2c66affSColin Finck
20c2c66affSColin Finck ERESOURCE IopDriverLoadResource;
21c2c66affSColin Finck
22c2c66affSColin Finck LIST_ENTRY DriverReinitListHead;
23c2c66affSColin Finck KSPIN_LOCK DriverReinitListLock;
24c2c66affSColin Finck PLIST_ENTRY DriverReinitTailEntry;
25c2c66affSColin Finck
26c2c66affSColin Finck PLIST_ENTRY DriverBootReinitTailEntry;
27c2c66affSColin Finck LIST_ENTRY DriverBootReinitListHead;
28c2c66affSColin Finck KSPIN_LOCK DriverBootReinitListLock;
29c2c66affSColin Finck
30c2c66affSColin Finck UNICODE_STRING IopHardwareDatabaseKey =
31c2c66affSColin Finck RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
324c95339dSVictor Perevertkin static const WCHAR ServicesKeyName[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
33c2c66affSColin Finck
34c2c66affSColin Finck POBJECT_TYPE IoDriverObjectType = NULL;
35c2c66affSColin Finck
36c2c66affSColin Finck extern BOOLEAN PnpSystemInit;
372839c850SVictor Perevertkin extern BOOLEAN PnPBootDriversLoaded;
382839c850SVictor Perevertkin extern KEVENT PiEnumerationFinished;
39c2c66affSColin Finck
40c2c66affSColin Finck USHORT IopGroupIndex;
41c2c66affSColin Finck PLIST_ENTRY IopGroupTable;
42c2c66affSColin Finck
43a6a3aa0fSVictor Perevertkin /* TYPES *********************************************************************/
44a6a3aa0fSVictor Perevertkin
45a6a3aa0fSVictor Perevertkin // Parameters packet for Load/Unload work item's context
46a6a3aa0fSVictor Perevertkin typedef struct _LOAD_UNLOAD_PARAMS
47a6a3aa0fSVictor Perevertkin {
48a6a3aa0fSVictor Perevertkin NTSTATUS Status;
494c95339dSVictor Perevertkin PUNICODE_STRING RegistryPath;
50a6a3aa0fSVictor Perevertkin WORK_QUEUE_ITEM WorkItem;
51a6a3aa0fSVictor Perevertkin KEVENT Event;
52a6a3aa0fSVictor Perevertkin PDRIVER_OBJECT DriverObject;
53a6a3aa0fSVictor Perevertkin BOOLEAN SetEvent;
54a6a3aa0fSVictor Perevertkin } LOAD_UNLOAD_PARAMS, *PLOAD_UNLOAD_PARAMS;
55a6a3aa0fSVictor Perevertkin
56a6a3aa0fSVictor Perevertkin NTSTATUS
57a6a3aa0fSVictor Perevertkin IopDoLoadUnloadDriver(
584c95339dSVictor Perevertkin _In_opt_ PUNICODE_STRING RegistryPath,
59a6a3aa0fSVictor Perevertkin _Inout_ PDRIVER_OBJECT *DriverObject);
60a6a3aa0fSVictor Perevertkin
61c2c66affSColin Finck /* PRIVATE FUNCTIONS **********************************************************/
62c2c66affSColin Finck
63c2c66affSColin Finck NTSTATUS
64c2c66affSColin Finck NTAPI
IopInvalidDeviceRequest(PDEVICE_OBJECT DeviceObject,PIRP Irp)65c2c66affSColin Finck IopInvalidDeviceRequest(
66c2c66affSColin Finck PDEVICE_OBJECT DeviceObject,
67c2c66affSColin Finck PIRP Irp)
68c2c66affSColin Finck {
69c2c66affSColin Finck Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
70c2c66affSColin Finck Irp->IoStatus.Information = 0;
71c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT);
72c2c66affSColin Finck return STATUS_INVALID_DEVICE_REQUEST;
73c2c66affSColin Finck }
74c2c66affSColin Finck
75c2c66affSColin Finck VOID
76c2c66affSColin Finck NTAPI
IopDeleteDriver(IN PVOID ObjectBody)77c2c66affSColin Finck IopDeleteDriver(IN PVOID ObjectBody)
78c2c66affSColin Finck {
79c2c66affSColin Finck PDRIVER_OBJECT DriverObject = ObjectBody;
80c2c66affSColin Finck PIO_CLIENT_EXTENSION DriverExtension, NextDriverExtension;
81c2c66affSColin Finck PAGED_CODE();
82c2c66affSColin Finck
83c2c66affSColin Finck DPRINT1("Deleting driver object '%wZ'\n", &DriverObject->DriverName);
84c2c66affSColin Finck
85c2c66affSColin Finck /* There must be no device objects remaining at this point */
86c2c66affSColin Finck ASSERT(!DriverObject->DeviceObject);
87c2c66affSColin Finck
88c2c66affSColin Finck /* Get the extension and loop them */
89c2c66affSColin Finck DriverExtension = IoGetDrvObjExtension(DriverObject)->ClientDriverExtension;
90c2c66affSColin Finck while (DriverExtension)
91c2c66affSColin Finck {
92c2c66affSColin Finck /* Get the next one */
93c2c66affSColin Finck NextDriverExtension = DriverExtension->NextExtension;
94c2c66affSColin Finck ExFreePoolWithTag(DriverExtension, TAG_DRIVER_EXTENSION);
95c2c66affSColin Finck
96c2c66affSColin Finck /* Move on */
97c2c66affSColin Finck DriverExtension = NextDriverExtension;
98c2c66affSColin Finck }
99c2c66affSColin Finck
100c2c66affSColin Finck /* Check if the driver image is still loaded */
101c2c66affSColin Finck if (DriverObject->DriverSection)
102c2c66affSColin Finck {
103c2c66affSColin Finck /* Unload it */
104c2c66affSColin Finck MmUnloadSystemImage(DriverObject->DriverSection);
105c2c66affSColin Finck }
106c2c66affSColin Finck
107c2c66affSColin Finck /* Check if it has a name */
108c2c66affSColin Finck if (DriverObject->DriverName.Buffer)
109c2c66affSColin Finck {
110c2c66affSColin Finck /* Free it */
111c2c66affSColin Finck ExFreePool(DriverObject->DriverName.Buffer);
112c2c66affSColin Finck }
113c2c66affSColin Finck
114c2c66affSColin Finck /* Check if it has a service key name */
115c2c66affSColin Finck if (DriverObject->DriverExtension->ServiceKeyName.Buffer)
116c2c66affSColin Finck {
117c2c66affSColin Finck /* Free it */
118c2c66affSColin Finck ExFreePool(DriverObject->DriverExtension->ServiceKeyName.Buffer);
119c2c66affSColin Finck }
120c2c66affSColin Finck }
121c2c66affSColin Finck
122c2c66affSColin Finck NTSTATUS
IopGetDriverNames(_In_ HANDLE ServiceHandle,_Out_ PUNICODE_STRING DriverName,_Out_opt_ PUNICODE_STRING ServiceName)123c4c0585fSVictor Perevertkin IopGetDriverNames(
124c4c0585fSVictor Perevertkin _In_ HANDLE ServiceHandle,
125c4c0585fSVictor Perevertkin _Out_ PUNICODE_STRING DriverName,
126c4c0585fSVictor Perevertkin _Out_opt_ PUNICODE_STRING ServiceName)
127c2c66affSColin Finck {
128c4c0585fSVictor Perevertkin UNICODE_STRING driverName = {.Buffer = NULL}, serviceName;
129c4c0585fSVictor Perevertkin PKEY_VALUE_FULL_INFORMATION kvInfo;
130c4c0585fSVictor Perevertkin NTSTATUS status;
131c2c66affSColin Finck
132c4c0585fSVictor Perevertkin PAGED_CODE();
133c2c66affSColin Finck
134a82ff90bSHermès Bélusca-Maïto /* 1. Check the "ObjectName" field in the driver's registry key (it has priority) */
135c4c0585fSVictor Perevertkin status = IopGetRegistryValue(ServiceHandle, L"ObjectName", &kvInfo);
136c4c0585fSVictor Perevertkin if (NT_SUCCESS(status))
137c4c0585fSVictor Perevertkin {
138a82ff90bSHermès Bélusca-Maïto /* We've got the ObjectName, use it as the driver name */
139c4c0585fSVictor Perevertkin if (kvInfo->Type != REG_SZ || kvInfo->DataLength == 0)
140c4c0585fSVictor Perevertkin {
141c4c0585fSVictor Perevertkin ExFreePool(kvInfo);
142c4c0585fSVictor Perevertkin return STATUS_ILL_FORMED_SERVICE_ENTRY;
143c4c0585fSVictor Perevertkin }
144c2c66affSColin Finck
1450d28f271SHermès Bélusca-Maïto driverName.Length = kvInfo->DataLength - sizeof(UNICODE_NULL);
146a82ff90bSHermès Bélusca-Maïto driverName.MaximumLength = kvInfo->DataLength;
147c4c0585fSVictor Perevertkin driverName.Buffer = ExAllocatePoolWithTag(NonPagedPool, driverName.MaximumLength, TAG_IO);
148c4c0585fSVictor Perevertkin if (!driverName.Buffer)
149c4c0585fSVictor Perevertkin {
150c4c0585fSVictor Perevertkin ExFreePool(kvInfo);
151c4c0585fSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
152c4c0585fSVictor Perevertkin }
153c2c66affSColin Finck
154c4c0585fSVictor Perevertkin RtlMoveMemory(driverName.Buffer,
155c4c0585fSVictor Perevertkin (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
156c4c0585fSVictor Perevertkin driverName.Length);
1570d28f271SHermès Bélusca-Maïto driverName.Buffer[driverName.Length / sizeof(WCHAR)] = UNICODE_NULL;
158c4c0585fSVictor Perevertkin ExFreePool(kvInfo);
159c4c0585fSVictor Perevertkin }
160e1b20681SThomas Faber
161a82ff90bSHermès Bélusca-Maïto /* Check whether we need to get ServiceName as well, either to construct
162a82ff90bSHermès Bélusca-Maïto * the driver name (because we could not use "ObjectName"), or because
163a82ff90bSHermès Bélusca-Maïto * it is requested by the caller. */
164e09d1decSHermès Bélusca-Maïto PKEY_BASIC_INFORMATION basicInfo = NULL;
165c4c0585fSVictor Perevertkin if (!NT_SUCCESS(status) || ServiceName != NULL)
166c4c0585fSVictor Perevertkin {
167a82ff90bSHermès Bélusca-Maïto /* Retrieve the necessary buffer size */
168c4c0585fSVictor Perevertkin ULONG infoLength;
169c4c0585fSVictor Perevertkin status = ZwQueryKey(ServiceHandle, KeyBasicInformation, NULL, 0, &infoLength);
170a82ff90bSHermès Bélusca-Maïto if (status != STATUS_BUFFER_TOO_SMALL)
171c4c0585fSVictor Perevertkin {
17232a82eb1SHermès Bélusca-Maïto status = (NT_SUCCESS(status) ? STATUS_UNSUCCESSFUL : status);
17332a82eb1SHermès Bélusca-Maïto goto Cleanup;
174a82ff90bSHermès Bélusca-Maïto }
175a82ff90bSHermès Bélusca-Maïto
176a82ff90bSHermès Bélusca-Maïto /* Allocate the buffer and retrieve the data */
177c4c0585fSVictor Perevertkin basicInfo = ExAllocatePoolWithTag(PagedPool, infoLength, TAG_IO);
178c4c0585fSVictor Perevertkin if (!basicInfo)
179e1b20681SThomas Faber {
18032a82eb1SHermès Bélusca-Maïto status = STATUS_INSUFFICIENT_RESOURCES;
18132a82eb1SHermès Bélusca-Maïto goto Cleanup;
182e1b20681SThomas Faber }
183c2c66affSColin Finck
184c4c0585fSVictor Perevertkin status = ZwQueryKey(ServiceHandle, KeyBasicInformation, basicInfo, infoLength, &infoLength);
185c4c0585fSVictor Perevertkin if (!NT_SUCCESS(status))
186c2c66affSColin Finck {
18732a82eb1SHermès Bélusca-Maïto goto Cleanup;
188c2c66affSColin Finck }
189c2c66affSColin Finck
190c4c0585fSVictor Perevertkin serviceName.Length = basicInfo->NameLength;
191c4c0585fSVictor Perevertkin serviceName.MaximumLength = basicInfo->NameLength;
192c4c0585fSVictor Perevertkin serviceName.Buffer = basicInfo->Name;
193c4c0585fSVictor Perevertkin }
194c2c66affSColin Finck
195a82ff90bSHermès Bélusca-Maïto /* 2. There is no "ObjectName" - construct it ourselves. Depending on the driver type,
196a82ff90bSHermès Bélusca-Maïto * it will be either "\Driver\<ServiceName>" or "\FileSystem\<ServiceName>" */
197c4c0585fSVictor Perevertkin if (driverName.Buffer == NULL)
198c4c0585fSVictor Perevertkin {
199e09d1decSHermès Bélusca-Maïto ASSERT(basicInfo); // Container for serviceName
200e09d1decSHermès Bélusca-Maïto
201a82ff90bSHermès Bélusca-Maïto /* Retrieve the driver type */
202a82ff90bSHermès Bélusca-Maïto ULONG driverType;
203c4c0585fSVictor Perevertkin status = IopGetRegistryValue(ServiceHandle, L"Type", &kvInfo);
204aec3d9ccSVictor Perevertkin if (!NT_SUCCESS(status))
205aec3d9ccSVictor Perevertkin {
206e09d1decSHermès Bélusca-Maïto goto Cleanup;
207aec3d9ccSVictor Perevertkin }
2080d28f271SHermès Bélusca-Maïto if (kvInfo->Type != REG_DWORD || kvInfo->DataLength != sizeof(ULONG))
209c4c0585fSVictor Perevertkin {
210c4c0585fSVictor Perevertkin ExFreePool(kvInfo);
211e09d1decSHermès Bélusca-Maïto status = STATUS_ILL_FORMED_SERVICE_ENTRY;
212e09d1decSHermès Bélusca-Maïto goto Cleanup;
213c4c0585fSVictor Perevertkin }
214fe416b67SHermès Bélusca-Maïto
215fe416b67SHermès Bélusca-Maïto RtlMoveMemory(&driverType,
216fe416b67SHermès Bélusca-Maïto (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
217fe416b67SHermès Bélusca-Maïto sizeof(ULONG));
218c4c0585fSVictor Perevertkin ExFreePool(kvInfo);
219c4c0585fSVictor Perevertkin
220a82ff90bSHermès Bélusca-Maïto /* Compute the necessary driver name string size */
221c4c0585fSVictor Perevertkin if (driverType == SERVICE_RECOGNIZER_DRIVER || driverType == SERVICE_FILE_SYSTEM_DRIVER)
222a82ff90bSHermès Bélusca-Maïto driverName.MaximumLength = sizeof(FILESYSTEM_ROOT_NAME);
223c4c0585fSVictor Perevertkin else
224a82ff90bSHermès Bélusca-Maïto driverName.MaximumLength = sizeof(DRIVER_ROOT_NAME);
225a82ff90bSHermès Bélusca-Maïto
226a82ff90bSHermès Bélusca-Maïto driverName.MaximumLength += serviceName.Length;
227a82ff90bSHermès Bélusca-Maïto driverName.Length = 0;
228a82ff90bSHermès Bélusca-Maïto
229a82ff90bSHermès Bélusca-Maïto /* Allocate and build it */
230c4c0585fSVictor Perevertkin driverName.Buffer = ExAllocatePoolWithTag(NonPagedPool, driverName.MaximumLength, TAG_IO);
231c4c0585fSVictor Perevertkin if (!driverName.Buffer)
232c4c0585fSVictor Perevertkin {
233e09d1decSHermès Bélusca-Maïto status = STATUS_INSUFFICIENT_RESOURCES;
234e09d1decSHermès Bélusca-Maïto goto Cleanup;
235c4c0585fSVictor Perevertkin }
236c4c0585fSVictor Perevertkin
237c4c0585fSVictor Perevertkin if (driverType == SERVICE_RECOGNIZER_DRIVER || driverType == SERVICE_FILE_SYSTEM_DRIVER)
238c4c0585fSVictor Perevertkin RtlAppendUnicodeToString(&driverName, FILESYSTEM_ROOT_NAME);
239c4c0585fSVictor Perevertkin else
240c4c0585fSVictor Perevertkin RtlAppendUnicodeToString(&driverName, DRIVER_ROOT_NAME);
241c4c0585fSVictor Perevertkin
242c4c0585fSVictor Perevertkin RtlAppendUnicodeStringToString(&driverName, &serviceName);
243c4c0585fSVictor Perevertkin }
244c4c0585fSVictor Perevertkin
245a82ff90bSHermès Bélusca-Maïto if (ServiceName != NULL)
246c4c0585fSVictor Perevertkin {
247e09d1decSHermès Bélusca-Maïto ASSERT(basicInfo); // Container for serviceName
248e09d1decSHermès Bélusca-Maïto
249a82ff90bSHermès Bélusca-Maïto /* Allocate a copy for the caller */
250c4c0585fSVictor Perevertkin PWCHAR buf = ExAllocatePoolWithTag(PagedPool, serviceName.Length, TAG_IO);
251c4c0585fSVictor Perevertkin if (!buf)
252c4c0585fSVictor Perevertkin {
253e09d1decSHermès Bélusca-Maïto status = STATUS_INSUFFICIENT_RESOURCES;
254e09d1decSHermès Bélusca-Maïto goto Cleanup;
255c4c0585fSVictor Perevertkin }
256c4c0585fSVictor Perevertkin RtlMoveMemory(buf, serviceName.Buffer, serviceName.Length);
257c4c0585fSVictor Perevertkin ServiceName->MaximumLength = serviceName.Length;
258c4c0585fSVictor Perevertkin ServiceName->Length = serviceName.Length;
259c4c0585fSVictor Perevertkin ServiceName->Buffer = buf;
260c4c0585fSVictor Perevertkin }
261c4c0585fSVictor Perevertkin
262c4c0585fSVictor Perevertkin *DriverName = driverName;
263e09d1decSHermès Bélusca-Maïto status = STATUS_SUCCESS;
264c2c66affSColin Finck
265e09d1decSHermès Bélusca-Maïto Cleanup:
266e09d1decSHermès Bélusca-Maïto if (basicInfo)
267e09d1decSHermès Bélusca-Maïto ExFreePoolWithTag(basicInfo, TAG_IO);
268e09d1decSHermès Bélusca-Maïto
26932a82eb1SHermès Bélusca-Maïto if (!NT_SUCCESS(status) && driverName.Buffer)
27032a82eb1SHermès Bélusca-Maïto ExFreePoolWithTag(driverName.Buffer, TAG_IO);
27132a82eb1SHermès Bélusca-Maïto
272e09d1decSHermès Bélusca-Maïto return status;
273c2c66affSColin Finck }
274c2c66affSColin Finck
27517c59456SHermès Bélusca-Maïto /**
27617c59456SHermès Bélusca-Maïto * @brief Determines whether String1 may be a suffix of String2.
27717c59456SHermès Bélusca-Maïto * @return TRUE if String2 contains String1 as a suffix.
27817c59456SHermès Bélusca-Maïto **/
27917c59456SHermès Bélusca-Maïto static BOOLEAN
IopSuffixUnicodeString(_In_ PCUNICODE_STRING String1,_In_ PCUNICODE_STRING String2,_In_ BOOLEAN CaseInSensitive)280c2c66affSColin Finck IopSuffixUnicodeString(
28117c59456SHermès Bélusca-Maïto _In_ PCUNICODE_STRING String1,
282*475098c8SHermès Bélusca-Maïto _In_ PCUNICODE_STRING String2,
283*475098c8SHermès Bélusca-Maïto _In_ BOOLEAN CaseInSensitive)
284c2c66affSColin Finck {
28517c59456SHermès Bélusca-Maïto PWCHAR pc1, pc2;
28617c59456SHermès Bélusca-Maïto ULONG NumChars;
287c2c66affSColin Finck
288c2c66affSColin Finck if (String2->Length < String1->Length)
289c2c66affSColin Finck return FALSE;
290c2c66affSColin Finck
29117c59456SHermès Bélusca-Maïto NumChars = String1->Length / sizeof(WCHAR);
292c2c66affSColin Finck pc1 = String1->Buffer;
29317c59456SHermès Bélusca-Maïto pc2 = &String2->Buffer[String2->Length / sizeof(WCHAR) - NumChars];
294c2c66affSColin Finck
295c2c66affSColin Finck if (pc1 && pc2)
296c2c66affSColin Finck {
297*475098c8SHermès Bélusca-Maïto if (CaseInSensitive)
298*475098c8SHermès Bélusca-Maïto {
299*475098c8SHermès Bélusca-Maïto while (NumChars--)
300*475098c8SHermès Bélusca-Maïto {
301*475098c8SHermès Bélusca-Maïto if (RtlUpcaseUnicodeChar(*pc1++) !=
302*475098c8SHermès Bélusca-Maïto RtlUpcaseUnicodeChar(*pc2++))
303*475098c8SHermès Bélusca-Maïto {
304*475098c8SHermès Bélusca-Maïto return FALSE;
305*475098c8SHermès Bélusca-Maïto }
306*475098c8SHermès Bélusca-Maïto }
307*475098c8SHermès Bélusca-Maïto }
308*475098c8SHermès Bélusca-Maïto else
309*475098c8SHermès Bélusca-Maïto {
31017c59456SHermès Bélusca-Maïto while (NumChars--)
311c2c66affSColin Finck {
312c2c66affSColin Finck if (*pc1++ != *pc2++)
313c2c66affSColin Finck return FALSE;
314c2c66affSColin Finck }
315*475098c8SHermès Bélusca-Maïto }
316*475098c8SHermès Bélusca-Maïto
317c2c66affSColin Finck return TRUE;
318c2c66affSColin Finck }
319*475098c8SHermès Bélusca-Maïto
320c2c66affSColin Finck return FALSE;
321c2c66affSColin Finck }
322c2c66affSColin Finck
32317c59456SHermès Bélusca-Maïto /**
324d1b3115aSHermès Bélusca-Maïto * @brief Displays a driver-loading message in SOS mode.
32517c59456SHermès Bélusca-Maïto **/
32617c59456SHermès Bélusca-Maïto static VOID
327c2c66affSColin Finck FASTCALL
IopDisplayLoadingMessage(_In_ PCUNICODE_STRING ServiceName)32817c59456SHermès Bélusca-Maïto IopDisplayLoadingMessage(
329*475098c8SHermès Bélusca-Maïto _In_ PCUNICODE_STRING ServiceName)
330c2c66affSColin Finck {
331d1b3115aSHermès Bélusca-Maïto extern BOOLEAN SosEnabled; // See ex/init.c
33217c59456SHermès Bélusca-Maïto static const UNICODE_STRING DotSys = RTL_CONSTANT_STRING(L".SYS");
333c2c66affSColin Finck CHAR TextBuffer[256];
334c2c66affSColin Finck
335d1b3115aSHermès Bélusca-Maïto if (!SosEnabled) return;
336c2c66affSColin Finck if (!KeLoaderBlock) return;
337d1b3115aSHermès Bélusca-Maïto RtlStringCbPrintfA(TextBuffer, sizeof(TextBuffer),
338c2c66affSColin Finck "%s%sSystem32\\Drivers\\%wZ%s\r\n",
339c2c66affSColin Finck KeLoaderBlock->ArcBootDeviceName,
340c2c66affSColin Finck KeLoaderBlock->NtBootPathName,
341c2c66affSColin Finck ServiceName,
342*475098c8SHermès Bélusca-Maïto IopSuffixUnicodeString(&DotSys, ServiceName, TRUE)
343*475098c8SHermès Bélusca-Maïto ? "" : ".SYS");
344c2c66affSColin Finck HalDisplayString(TextBuffer);
345c2c66affSColin Finck }
346c2c66affSColin Finck
347c2c66affSColin Finck /*
348c2c66affSColin Finck * IopNormalizeImagePath
349c2c66affSColin Finck *
350c2c66affSColin Finck * Normalize an image path to contain complete path.
351c2c66affSColin Finck *
352c2c66affSColin Finck * Parameters
353c2c66affSColin Finck * ImagePath
354c2c66affSColin Finck * The input path and on exit the result path. ImagePath.Buffer
355c2c66affSColin Finck * must be allocated by ExAllocatePool on input. Caller is responsible
356c2c66affSColin Finck * for freeing the buffer when it's no longer needed.
357c2c66affSColin Finck *
358c2c66affSColin Finck * ServiceName
359c2c66affSColin Finck * Name of the service that ImagePath belongs to.
360c2c66affSColin Finck *
361c2c66affSColin Finck * Return Value
362c2c66affSColin Finck * Status
363c2c66affSColin Finck *
364c2c66affSColin Finck * Remarks
365c2c66affSColin Finck * The input image path isn't freed on error.
366c2c66affSColin Finck */
367c2c66affSColin Finck NTSTATUS
368c2c66affSColin Finck FASTCALL
369c2c66affSColin Finck IopNormalizeImagePath(
370c2c66affSColin Finck _Inout_ _When_(return>=0, _At_(ImagePath->Buffer, _Post_notnull_ __drv_allocatesMem(Mem)))
371c2c66affSColin Finck PUNICODE_STRING ImagePath,
372c2c66affSColin Finck _In_ PUNICODE_STRING ServiceName)
373c2c66affSColin Finck {
374c2c66affSColin Finck UNICODE_STRING SystemRootString = RTL_CONSTANT_STRING(L"\\SystemRoot\\");
375c2c66affSColin Finck UNICODE_STRING DriversPathString = RTL_CONSTANT_STRING(L"\\SystemRoot\\System32\\drivers\\");
376c2c66affSColin Finck UNICODE_STRING DotSysString = RTL_CONSTANT_STRING(L".sys");
377c2c66affSColin Finck UNICODE_STRING InputImagePath;
378c2c66affSColin Finck
379c2c66affSColin Finck DPRINT("Normalizing image path '%wZ' for service '%wZ'\n", ImagePath, ServiceName);
380c2c66affSColin Finck
381c2c66affSColin Finck InputImagePath = *ImagePath;
382c2c66affSColin Finck if (InputImagePath.Length == 0)
383c2c66affSColin Finck {
384c2c66affSColin Finck ImagePath->Length = 0;
385c2c66affSColin Finck ImagePath->MaximumLength = DriversPathString.Length +
386c2c66affSColin Finck ServiceName->Length +
387c2c66affSColin Finck DotSysString.Length +
388c2c66affSColin Finck sizeof(UNICODE_NULL);
389c2c66affSColin Finck ImagePath->Buffer = ExAllocatePoolWithTag(NonPagedPool,
390c2c66affSColin Finck ImagePath->MaximumLength,
391c2c66affSColin Finck TAG_IO);
392c2c66affSColin Finck if (ImagePath->Buffer == NULL)
393c2c66affSColin Finck return STATUS_NO_MEMORY;
394c2c66affSColin Finck
395c2c66affSColin Finck RtlCopyUnicodeString(ImagePath, &DriversPathString);
396c2c66affSColin Finck RtlAppendUnicodeStringToString(ImagePath, ServiceName);
397c2c66affSColin Finck RtlAppendUnicodeStringToString(ImagePath, &DotSysString);
398c2c66affSColin Finck }
399c2c66affSColin Finck else if (InputImagePath.Buffer[0] != L'\\')
400c2c66affSColin Finck {
401c2c66affSColin Finck ImagePath->Length = 0;
402c2c66affSColin Finck ImagePath->MaximumLength = SystemRootString.Length +
403c2c66affSColin Finck InputImagePath.Length +
404c2c66affSColin Finck sizeof(UNICODE_NULL);
405c2c66affSColin Finck ImagePath->Buffer = ExAllocatePoolWithTag(NonPagedPool,
406c2c66affSColin Finck ImagePath->MaximumLength,
407c2c66affSColin Finck TAG_IO);
408c2c66affSColin Finck if (ImagePath->Buffer == NULL)
409c2c66affSColin Finck return STATUS_NO_MEMORY;
410c2c66affSColin Finck
411c2c66affSColin Finck RtlCopyUnicodeString(ImagePath, &SystemRootString);
412c2c66affSColin Finck RtlAppendUnicodeStringToString(ImagePath, &InputImagePath);
413c2c66affSColin Finck
414c2c66affSColin Finck /* Free caller's string */
415c2c66affSColin Finck ExFreePoolWithTag(InputImagePath.Buffer, TAG_RTLREGISTRY);
416c2c66affSColin Finck }
417c2c66affSColin Finck
418c2c66affSColin Finck DPRINT("Normalized image path is '%wZ' for service '%wZ'\n", ImagePath, ServiceName);
419c2c66affSColin Finck
420c2c66affSColin Finck return STATUS_SUCCESS;
421c2c66affSColin Finck }
422c2c66affSColin Finck
423e18a32dfSVictor Perevertkin /**
424e18a32dfSVictor Perevertkin * @brief Initialize a loaded driver
425c2c66affSColin Finck *
426e18a32dfSVictor Perevertkin * @param[in] ModuleObject
427e18a32dfSVictor Perevertkin * Module object representing the driver. It can be retrieved by IopLoadServiceModule.
428e18a32dfSVictor Perevertkin * Freed on failure, so in a such case this should not be accessed anymore
429c2c66affSColin Finck *
4304c95339dSVictor Perevertkin * @param[in] ServiceHandle
4314c95339dSVictor Perevertkin * Handle to a driver's CCS/Services/<ServiceName> key
432c2c66affSColin Finck *
433e18a32dfSVictor Perevertkin * @param[out] DriverObject
434e18a32dfSVictor Perevertkin * This contains the driver object if it was created (even with unsuccessfull result)
435c2c66affSColin Finck *
436e18a32dfSVictor Perevertkin * @param[out] DriverEntryStatus
437e18a32dfSVictor Perevertkin * This contains the status value returned by the driver's DriverEntry routine
438e18a32dfSVictor Perevertkin * (will not be valid of the return value is not STATUS_SUCCESS or STATUS_FAILED_DRIVER_ENTRY)
439c2c66affSColin Finck *
440e18a32dfSVictor Perevertkin * @return Status of the operation
441c2c66affSColin Finck */
442c2c66affSColin Finck NTSTATUS
IopInitializeDriverModule(_In_ PLDR_DATA_TABLE_ENTRY ModuleObject,_In_ HANDLE ServiceHandle,_Out_ PDRIVER_OBJECT * OutDriverObject,_Out_ NTSTATUS * DriverEntryStatus)443c2c66affSColin Finck IopInitializeDriverModule(
444e18a32dfSVictor Perevertkin _In_ PLDR_DATA_TABLE_ENTRY ModuleObject,
4454c95339dSVictor Perevertkin _In_ HANDLE ServiceHandle,
446e18a32dfSVictor Perevertkin _Out_ PDRIVER_OBJECT *OutDriverObject,
447e18a32dfSVictor Perevertkin _Out_ NTSTATUS *DriverEntryStatus)
448c2c66affSColin Finck {
4494c95339dSVictor Perevertkin UNICODE_STRING DriverName, RegistryPath, ServiceName;
450c2c66affSColin Finck NTSTATUS Status;
451c2c66affSColin Finck
452e18a32dfSVictor Perevertkin PAGED_CODE();
453c2c66affSColin Finck
454c4c0585fSVictor Perevertkin Status = IopGetDriverNames(ServiceHandle, &DriverName, &ServiceName);
455e18a32dfSVictor Perevertkin if (!NT_SUCCESS(Status))
456c2c66affSColin Finck {
457e18a32dfSVictor Perevertkin MmUnloadSystemImage(ModuleObject);
458e18a32dfSVictor Perevertkin return Status;
459e18a32dfSVictor Perevertkin }
460e18a32dfSVictor Perevertkin
461e18a32dfSVictor Perevertkin DPRINT("Driver name: '%wZ'\n", &DriverName);
462e18a32dfSVictor Perevertkin
4631fd730b7SHermès Bélusca-Maïto /*
4641fd730b7SHermès Bélusca-Maïto * Retrieve the driver's PE image NT header and perform some sanity checks.
4651fd730b7SHermès Bélusca-Maïto * NOTE: We suppose that since the driver has been successfully loaded,
4661fd730b7SHermès Bélusca-Maïto * its NT and optional headers are all valid and have expected sizes.
4671fd730b7SHermès Bélusca-Maïto */
4681fd730b7SHermès Bélusca-Maïto PIMAGE_NT_HEADERS NtHeaders = RtlImageNtHeader(ModuleObject->DllBase);
4691fd730b7SHermès Bélusca-Maïto ASSERT(NtHeaders);
4704795d953SHermès Bélusca-Maïto // NOTE: ModuleObject->SizeOfImage is actually (number of PTEs)*PAGE_SIZE.
4714795d953SHermès Bélusca-Maïto ASSERT(ModuleObject->SizeOfImage == ROUND_TO_PAGES(NtHeaders->OptionalHeader.SizeOfImage));
4721fd730b7SHermès Bélusca-Maïto ASSERT(ModuleObject->EntryPoint == RVA(ModuleObject->DllBase, NtHeaders->OptionalHeader.AddressOfEntryPoint));
4731fd730b7SHermès Bélusca-Maïto
474a82ff90bSHermès Bélusca-Maïto /* Obtain the registry path for the DriverInit routine */
4754c95339dSVictor Perevertkin PKEY_NAME_INFORMATION nameInfo;
476c4c0585fSVictor Perevertkin ULONG infoLength;
4774c95339dSVictor Perevertkin Status = ZwQueryKey(ServiceHandle, KeyNameInformation, NULL, 0, &infoLength);
4784c95339dSVictor Perevertkin if (Status == STATUS_BUFFER_TOO_SMALL)
4794c95339dSVictor Perevertkin {
4804c95339dSVictor Perevertkin nameInfo = ExAllocatePoolWithTag(NonPagedPool, infoLength, TAG_IO);
4814c95339dSVictor Perevertkin if (nameInfo)
4824c95339dSVictor Perevertkin {
4834c95339dSVictor Perevertkin Status = ZwQueryKey(ServiceHandle,
4844c95339dSVictor Perevertkin KeyNameInformation,
4854c95339dSVictor Perevertkin nameInfo,
4864c95339dSVictor Perevertkin infoLength,
4874c95339dSVictor Perevertkin &infoLength);
4884c95339dSVictor Perevertkin if (NT_SUCCESS(Status))
4894c95339dSVictor Perevertkin {
4904c95339dSVictor Perevertkin RegistryPath.Length = nameInfo->NameLength;
4914c95339dSVictor Perevertkin RegistryPath.MaximumLength = nameInfo->NameLength;
4924c95339dSVictor Perevertkin RegistryPath.Buffer = nameInfo->Name;
4934c95339dSVictor Perevertkin }
4944c95339dSVictor Perevertkin else
4954c95339dSVictor Perevertkin {
4964c95339dSVictor Perevertkin ExFreePoolWithTag(nameInfo, TAG_IO);
4974c95339dSVictor Perevertkin }
4984c95339dSVictor Perevertkin }
4994c95339dSVictor Perevertkin else
5004c95339dSVictor Perevertkin {
5014c95339dSVictor Perevertkin Status = STATUS_INSUFFICIENT_RESOURCES;
5024c95339dSVictor Perevertkin }
5034c95339dSVictor Perevertkin }
5044c95339dSVictor Perevertkin else
5054c95339dSVictor Perevertkin {
5064c95339dSVictor Perevertkin Status = NT_SUCCESS(Status) ? STATUS_UNSUCCESSFUL : Status;
5074c95339dSVictor Perevertkin }
5084c95339dSVictor Perevertkin
5094c95339dSVictor Perevertkin if (!NT_SUCCESS(Status))
5104c95339dSVictor Perevertkin {
511c4c0585fSVictor Perevertkin RtlFreeUnicodeString(&ServiceName);
5124c95339dSVictor Perevertkin RtlFreeUnicodeString(&DriverName);
5134c95339dSVictor Perevertkin MmUnloadSystemImage(ModuleObject);
5144c95339dSVictor Perevertkin return Status;
5154c95339dSVictor Perevertkin }
5164c95339dSVictor Perevertkin
517a82ff90bSHermès Bélusca-Maïto /* Create the driver object */
518a82ff90bSHermès Bélusca-Maïto ULONG ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(EXTENDED_DRIVER_EXTENSION);
519e18a32dfSVictor Perevertkin OBJECT_ATTRIBUTES objAttrs;
520e18a32dfSVictor Perevertkin PDRIVER_OBJECT driverObject;
521e18a32dfSVictor Perevertkin InitializeObjectAttributes(&objAttrs,
522e18a32dfSVictor Perevertkin &DriverName,
523e18a32dfSVictor Perevertkin OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
524e18a32dfSVictor Perevertkin NULL,
525e18a32dfSVictor Perevertkin NULL);
526e18a32dfSVictor Perevertkin
527e18a32dfSVictor Perevertkin Status = ObCreateObject(KernelMode,
528e18a32dfSVictor Perevertkin IoDriverObjectType,
529e18a32dfSVictor Perevertkin &objAttrs,
530e18a32dfSVictor Perevertkin KernelMode,
531e18a32dfSVictor Perevertkin NULL,
532e18a32dfSVictor Perevertkin ObjectSize,
533e18a32dfSVictor Perevertkin 0,
534e18a32dfSVictor Perevertkin 0,
535e18a32dfSVictor Perevertkin (PVOID*)&driverObject);
536e18a32dfSVictor Perevertkin if (!NT_SUCCESS(Status))
537e18a32dfSVictor Perevertkin {
5384c95339dSVictor Perevertkin ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath
539c4c0585fSVictor Perevertkin RtlFreeUnicodeString(&ServiceName);
540e18a32dfSVictor Perevertkin RtlFreeUnicodeString(&DriverName);
541e18a32dfSVictor Perevertkin MmUnloadSystemImage(ModuleObject);
542e18a32dfSVictor Perevertkin DPRINT1("Error while creating driver object \"%wZ\" status %x\n", &DriverName, Status);
543e18a32dfSVictor Perevertkin return Status;
544e18a32dfSVictor Perevertkin }
545e18a32dfSVictor Perevertkin
546e18a32dfSVictor Perevertkin DPRINT("Created driver object 0x%p for \"%wZ\"\n", driverObject, &DriverName);
547e18a32dfSVictor Perevertkin
548e18a32dfSVictor Perevertkin RtlZeroMemory(driverObject, ObjectSize);
549e18a32dfSVictor Perevertkin driverObject->Type = IO_TYPE_DRIVER;
550e18a32dfSVictor Perevertkin driverObject->Size = sizeof(DRIVER_OBJECT);
5511fd730b7SHermès Bélusca-Maïto
5521fd730b7SHermès Bélusca-Maïto /* Set the legacy flag if this is not a WDM driver */
5531fd730b7SHermès Bélusca-Maïto if (!(NtHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_WDM_DRIVER))
5541fd730b7SHermès Bélusca-Maïto driverObject->Flags |= DRVO_LEGACY_DRIVER;
5551fd730b7SHermès Bélusca-Maïto
556e18a32dfSVictor Perevertkin driverObject->DriverSection = ModuleObject;
557e18a32dfSVictor Perevertkin driverObject->DriverStart = ModuleObject->DllBase;
558e18a32dfSVictor Perevertkin driverObject->DriverSize = ModuleObject->SizeOfImage;
559e18a32dfSVictor Perevertkin driverObject->DriverInit = ModuleObject->EntryPoint;
560e18a32dfSVictor Perevertkin driverObject->HardwareDatabase = &IopHardwareDatabaseKey;
561e18a32dfSVictor Perevertkin driverObject->DriverExtension = (PDRIVER_EXTENSION)(driverObject + 1);
562e18a32dfSVictor Perevertkin driverObject->DriverExtension->DriverObject = driverObject;
563e18a32dfSVictor Perevertkin
564e18a32dfSVictor Perevertkin /* Loop all Major Functions */
565e18a32dfSVictor Perevertkin for (INT i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
566e18a32dfSVictor Perevertkin {
567e18a32dfSVictor Perevertkin /* Invalidate each function */
568e18a32dfSVictor Perevertkin driverObject->MajorFunction[i] = IopInvalidDeviceRequest;
569e18a32dfSVictor Perevertkin }
570e18a32dfSVictor Perevertkin
571e18a32dfSVictor Perevertkin /* Add the Object and get its handle */
572e18a32dfSVictor Perevertkin HANDLE hDriver;
573e18a32dfSVictor Perevertkin Status = ObInsertObject(driverObject, NULL, FILE_READ_DATA, 0, NULL, &hDriver);
574e18a32dfSVictor Perevertkin if (!NT_SUCCESS(Status))
575e18a32dfSVictor Perevertkin {
5764c95339dSVictor Perevertkin ExFreePoolWithTag(nameInfo, TAG_IO);
577c4c0585fSVictor Perevertkin RtlFreeUnicodeString(&ServiceName);
578e18a32dfSVictor Perevertkin RtlFreeUnicodeString(&DriverName);
579e18a32dfSVictor Perevertkin return Status;
580e18a32dfSVictor Perevertkin }
581e18a32dfSVictor Perevertkin
582e18a32dfSVictor Perevertkin /* Now reference it */
583e18a32dfSVictor Perevertkin Status = ObReferenceObjectByHandle(hDriver,
584e18a32dfSVictor Perevertkin 0,
585e18a32dfSVictor Perevertkin IoDriverObjectType,
586e18a32dfSVictor Perevertkin KernelMode,
587e18a32dfSVictor Perevertkin (PVOID*)&driverObject,
588e18a32dfSVictor Perevertkin NULL);
589e18a32dfSVictor Perevertkin
590e18a32dfSVictor Perevertkin /* Close the extra handle */
591e18a32dfSVictor Perevertkin ZwClose(hDriver);
592e18a32dfSVictor Perevertkin
593e18a32dfSVictor Perevertkin if (!NT_SUCCESS(Status))
594e18a32dfSVictor Perevertkin {
5954c95339dSVictor Perevertkin ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath
596c4c0585fSVictor Perevertkin RtlFreeUnicodeString(&ServiceName);
597e18a32dfSVictor Perevertkin RtlFreeUnicodeString(&DriverName);
598e18a32dfSVictor Perevertkin return Status;
599e18a32dfSVictor Perevertkin }
600e18a32dfSVictor Perevertkin
601e18a32dfSVictor Perevertkin /* Set up the service key name buffer */
602e18a32dfSVictor Perevertkin UNICODE_STRING serviceKeyName;
603e18a32dfSVictor Perevertkin serviceKeyName.Length = 0;
604a82ff90bSHermès Bélusca-Maïto // NULL-terminate for Windows compatibility
6054c95339dSVictor Perevertkin serviceKeyName.MaximumLength = ServiceName.MaximumLength + sizeof(UNICODE_NULL);
606e18a32dfSVictor Perevertkin serviceKeyName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
607e18a32dfSVictor Perevertkin serviceKeyName.MaximumLength,
608e18a32dfSVictor Perevertkin TAG_IO);
609e18a32dfSVictor Perevertkin if (!serviceKeyName.Buffer)
610e18a32dfSVictor Perevertkin {
611e18a32dfSVictor Perevertkin ObMakeTemporaryObject(driverObject);
612e18a32dfSVictor Perevertkin ObDereferenceObject(driverObject);
6134c95339dSVictor Perevertkin ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath
614c4c0585fSVictor Perevertkin RtlFreeUnicodeString(&ServiceName);
615e18a32dfSVictor Perevertkin RtlFreeUnicodeString(&DriverName);
616e18a32dfSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
617e18a32dfSVictor Perevertkin }
618e18a32dfSVictor Perevertkin
619e18a32dfSVictor Perevertkin /* Copy the name and set it in the driver extension */
6204c95339dSVictor Perevertkin RtlCopyUnicodeString(&serviceKeyName, &ServiceName);
621c4c0585fSVictor Perevertkin RtlFreeUnicodeString(&ServiceName);
622e18a32dfSVictor Perevertkin driverObject->DriverExtension->ServiceKeyName = serviceKeyName;
623e18a32dfSVictor Perevertkin
624e18a32dfSVictor Perevertkin /* Make a copy of the driver name to store in the driver object */
625e18a32dfSVictor Perevertkin UNICODE_STRING driverNamePaged;
626e18a32dfSVictor Perevertkin driverNamePaged.Length = 0;
627a82ff90bSHermès Bélusca-Maïto // NULL-terminate for Windows compatibility
628e18a32dfSVictor Perevertkin driverNamePaged.MaximumLength = DriverName.MaximumLength + sizeof(UNICODE_NULL);
629e18a32dfSVictor Perevertkin driverNamePaged.Buffer = ExAllocatePoolWithTag(PagedPool,
630e18a32dfSVictor Perevertkin driverNamePaged.MaximumLength,
631e18a32dfSVictor Perevertkin TAG_IO);
632e18a32dfSVictor Perevertkin if (!driverNamePaged.Buffer)
633e18a32dfSVictor Perevertkin {
634e18a32dfSVictor Perevertkin ObMakeTemporaryObject(driverObject);
635e18a32dfSVictor Perevertkin ObDereferenceObject(driverObject);
6364c95339dSVictor Perevertkin ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath
637e18a32dfSVictor Perevertkin RtlFreeUnicodeString(&DriverName);
638e18a32dfSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
639e18a32dfSVictor Perevertkin }
640e18a32dfSVictor Perevertkin
641e18a32dfSVictor Perevertkin RtlCopyUnicodeString(&driverNamePaged, &DriverName);
642e18a32dfSVictor Perevertkin driverObject->DriverName = driverNamePaged;
643e18a32dfSVictor Perevertkin
644e18a32dfSVictor Perevertkin /* Finally, call its init function */
6454c95339dSVictor Perevertkin Status = driverObject->DriverInit(driverObject, &RegistryPath);
646e18a32dfSVictor Perevertkin *DriverEntryStatus = Status;
647e18a32dfSVictor Perevertkin if (!NT_SUCCESS(Status))
648e18a32dfSVictor Perevertkin {
649e18a32dfSVictor Perevertkin DPRINT1("'%wZ' initialization failed, status (0x%08lx)\n", &DriverName, Status);
650e18a32dfSVictor Perevertkin // return a special status value in case of failure
651e18a32dfSVictor Perevertkin Status = STATUS_FAILED_DRIVER_ENTRY;
652e18a32dfSVictor Perevertkin }
653e18a32dfSVictor Perevertkin
654e18a32dfSVictor Perevertkin /* HACK: We're going to say if we don't have any DOs from DriverEntry, then we're not legacy.
655e18a32dfSVictor Perevertkin * Other parts of the I/O manager depend on this behavior */
656e18a32dfSVictor Perevertkin if (!driverObject->DeviceObject)
657e18a32dfSVictor Perevertkin {
658e18a32dfSVictor Perevertkin driverObject->Flags &= ~DRVO_LEGACY_DRIVER;
659e18a32dfSVictor Perevertkin }
660e18a32dfSVictor Perevertkin
6614a93b0a4SHermès Bélusca-Maïto /* Windows does this fixup, keep it for compatibility */
662e18a32dfSVictor Perevertkin for (INT i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
663e18a32dfSVictor Perevertkin {
664e18a32dfSVictor Perevertkin /*
665e18a32dfSVictor Perevertkin * Make sure the driver didn't set any dispatch entry point to NULL!
666e18a32dfSVictor Perevertkin * Doing so is illegal; drivers shouldn't touch entry points they
667e18a32dfSVictor Perevertkin * do not implement.
668e18a32dfSVictor Perevertkin */
669e18a32dfSVictor Perevertkin
670e18a32dfSVictor Perevertkin /* Check if it did so anyway */
671e18a32dfSVictor Perevertkin if (!driverObject->MajorFunction[i])
672e18a32dfSVictor Perevertkin {
673e18a32dfSVictor Perevertkin /* Print a warning in the debug log */
674e18a32dfSVictor Perevertkin DPRINT1("Driver <%wZ> set DriverObject->MajorFunction[%lu] to NULL!\n",
675e18a32dfSVictor Perevertkin &driverObject->DriverName, i);
676e18a32dfSVictor Perevertkin
677e18a32dfSVictor Perevertkin /* Fix it up */
678e18a32dfSVictor Perevertkin driverObject->MajorFunction[i] = IopInvalidDeviceRequest;
679e18a32dfSVictor Perevertkin }
680e18a32dfSVictor Perevertkin }
681e18a32dfSVictor Perevertkin
682e18a32dfSVictor Perevertkin // TODO: for legacy drivers, unload the driver if it didn't create any DO
683e18a32dfSVictor Perevertkin
6844c95339dSVictor Perevertkin ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath
685c2c66affSColin Finck RtlFreeUnicodeString(&DriverName);
686c2c66affSColin Finck
687c2c66affSColin Finck if (!NT_SUCCESS(Status))
688c2c66affSColin Finck {
689e18a32dfSVictor Perevertkin // if the driver entry has been failed, clear the object
690e18a32dfSVictor Perevertkin ObMakeTemporaryObject(driverObject);
691e18a32dfSVictor Perevertkin ObDereferenceObject(driverObject);
692c2c66affSColin Finck return Status;
693c2c66affSColin Finck }
694c2c66affSColin Finck
695e18a32dfSVictor Perevertkin *OutDriverObject = driverObject;
696c2c66affSColin Finck
697e18a32dfSVictor Perevertkin MmFreeDriverInitialization((PLDR_DATA_TABLE_ENTRY)driverObject->DriverSection);
698c2c66affSColin Finck
699c2c66affSColin Finck /* Set the driver as initialized */
700e18a32dfSVictor Perevertkin IopReadyDeviceObjects(driverObject);
701c2c66affSColin Finck
702c2c66affSColin Finck if (PnpSystemInit) IopReinitializeDrivers();
703c2c66affSColin Finck
704c2c66affSColin Finck return STATUS_SUCCESS;
705c2c66affSColin Finck }
706c2c66affSColin Finck
707c2c66affSColin Finck NTSTATUS
708c2c66affSColin Finck NTAPI
709c2c66affSColin Finck MiResolveImageReferences(IN PVOID ImageBase,
710c2c66affSColin Finck IN PUNICODE_STRING ImageFileDirectory,
711c2c66affSColin Finck IN PUNICODE_STRING NamePrefix OPTIONAL,
712c2c66affSColin Finck OUT PCHAR *MissingApi,
713c2c66affSColin Finck OUT PWCHAR *MissingDriver,
714c2c66affSColin Finck OUT PLOAD_IMPORTS *LoadImports);
715c2c66affSColin Finck
716c2c66affSColin Finck //
717c2c66affSColin Finck // Used for images already loaded (boot drivers)
718c2c66affSColin Finck //
7195c7ce447SVictor Perevertkin CODE_SEG("INIT")
720c2c66affSColin Finck NTSTATUS
721c2c66affSColin Finck NTAPI
LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry,PUNICODE_STRING FileName,PLDR_DATA_TABLE_ENTRY * ModuleObject)722c2c66affSColin Finck LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry,
723c2c66affSColin Finck PUNICODE_STRING FileName,
724c2c66affSColin Finck PLDR_DATA_TABLE_ENTRY *ModuleObject)
725c2c66affSColin Finck {
726c2c66affSColin Finck NTSTATUS Status;
727c2c66affSColin Finck UNICODE_STRING BaseName, BaseDirectory;
7284c6f7c01SHermès Bélusca-Maïto PLOAD_IMPORTS LoadedImports = MM_SYSLDR_NO_IMPORTS;
729c2c66affSColin Finck PCHAR MissingApiName, Buffer;
730c2c66affSColin Finck PWCHAR MissingDriverName;
731c2c66affSColin Finck PVOID DriverBase = LdrEntry->DllBase;
732c2c66affSColin Finck
733c2c66affSColin Finck /* Allocate a buffer we'll use for names */
734f3a280f5SThomas Faber Buffer = ExAllocatePoolWithTag(NonPagedPool,
735f3a280f5SThomas Faber MAXIMUM_FILENAME_LENGTH,
736f3a280f5SThomas Faber TAG_LDR_WSTR);
737c2c66affSColin Finck if (!Buffer)
738c2c66affSColin Finck {
739c2c66affSColin Finck /* Fail */
740c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
741c2c66affSColin Finck }
742c2c66affSColin Finck
743c2c66affSColin Finck /* Check for a separator */
744c2c66affSColin Finck if (FileName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
745c2c66affSColin Finck {
746c2c66affSColin Finck PWCHAR p;
747c2c66affSColin Finck ULONG BaseLength;
748c2c66affSColin Finck
749c2c66affSColin Finck /* Loop the path until we get to the base name */
750c2c66affSColin Finck p = &FileName->Buffer[FileName->Length / sizeof(WCHAR)];
751c2c66affSColin Finck while (*(p - 1) != OBJ_NAME_PATH_SEPARATOR) p--;
752c2c66affSColin Finck
753c2c66affSColin Finck /* Get the length */
754c2c66affSColin Finck BaseLength = (ULONG)(&FileName->Buffer[FileName->Length / sizeof(WCHAR)] - p);
755c2c66affSColin Finck BaseLength *= sizeof(WCHAR);
756c2c66affSColin Finck
757c2c66affSColin Finck /* Setup the string */
758c2c66affSColin Finck BaseName.Length = (USHORT)BaseLength;
759c2c66affSColin Finck BaseName.Buffer = p;
760c2c66affSColin Finck }
761c2c66affSColin Finck else
762c2c66affSColin Finck {
763c2c66affSColin Finck /* Otherwise, we already have a base name */
764c2c66affSColin Finck BaseName.Length = FileName->Length;
765c2c66affSColin Finck BaseName.Buffer = FileName->Buffer;
766c2c66affSColin Finck }
767c2c66affSColin Finck
768c2c66affSColin Finck /* Setup the maximum length */
769c2c66affSColin Finck BaseName.MaximumLength = BaseName.Length;
770c2c66affSColin Finck
771c2c66affSColin Finck /* Now compute the base directory */
772c2c66affSColin Finck BaseDirectory = *FileName;
773c2c66affSColin Finck BaseDirectory.Length -= BaseName.Length;
774c2c66affSColin Finck BaseDirectory.MaximumLength = BaseDirectory.Length;
775c2c66affSColin Finck
776c2c66affSColin Finck /* Resolve imports */
777c2c66affSColin Finck MissingApiName = Buffer;
778c2c66affSColin Finck Status = MiResolveImageReferences(DriverBase,
779c2c66affSColin Finck &BaseDirectory,
780c2c66affSColin Finck NULL,
781c2c66affSColin Finck &MissingApiName,
782c2c66affSColin Finck &MissingDriverName,
783c2c66affSColin Finck &LoadedImports);
784c2c66affSColin Finck
785c2c66affSColin Finck /* Free the temporary buffer */
786c2c66affSColin Finck ExFreePoolWithTag(Buffer, TAG_LDR_WSTR);
787c2c66affSColin Finck
788c2c66affSColin Finck /* Check the result of the imports resolution */
789c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status;
790c2c66affSColin Finck
791c2c66affSColin Finck /* Return */
792c2c66affSColin Finck *ModuleObject = LdrEntry;
793c2c66affSColin Finck return STATUS_SUCCESS;
794c2c66affSColin Finck }
795c2c66affSColin Finck
79691fceab3SVictor Perevertkin PDEVICE_OBJECT
79791fceab3SVictor Perevertkin IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance);
79891fceab3SVictor Perevertkin
799c2c66affSColin Finck /*
800c2c66affSColin Finck * IopInitializeBuiltinDriver
801c2c66affSColin Finck *
802c2c66affSColin Finck * Initialize a driver that is already loaded in memory.
803c2c66affSColin Finck */
8045c7ce447SVictor Perevertkin CODE_SEG("INIT")
8053adf4508SJérôme Gardou static
80691fceab3SVictor Perevertkin BOOLEAN
IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY BootLdrEntry)807c2c66affSColin Finck IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY BootLdrEntry)
808c2c66affSColin Finck {
809c2c66affSColin Finck PDRIVER_OBJECT DriverObject;
810c2c66affSColin Finck NTSTATUS Status;
811c2c66affSColin Finck PWCHAR Buffer, FileNameWithoutPath;
812c2c66affSColin Finck PWSTR FileExtension;
813c2c66affSColin Finck PUNICODE_STRING ModuleName = &BootLdrEntry->BaseDllName;
814c2c66affSColin Finck PLDR_DATA_TABLE_ENTRY LdrEntry;
815c2c66affSColin Finck PLIST_ENTRY NextEntry;
816c2c66affSColin Finck UNICODE_STRING ServiceName;
817c2c66affSColin Finck BOOLEAN Success;
818c2c66affSColin Finck
819c2c66affSColin Finck /*
820c2c66affSColin Finck * Display 'Loading XXX...' message
821c2c66affSColin Finck */
822c2c66affSColin Finck IopDisplayLoadingMessage(ModuleName);
823c2c66affSColin Finck InbvIndicateProgress();
824c2c66affSColin Finck
825c2c66affSColin Finck Buffer = ExAllocatePoolWithTag(PagedPool,
826c2c66affSColin Finck ModuleName->Length + sizeof(UNICODE_NULL),
827c2c66affSColin Finck TAG_IO);
828c2c66affSColin Finck if (Buffer == NULL)
829c2c66affSColin Finck {
83091fceab3SVictor Perevertkin return FALSE;
831c2c66affSColin Finck }
832c2c66affSColin Finck
833c2c66affSColin Finck RtlCopyMemory(Buffer, ModuleName->Buffer, ModuleName->Length);
834c2c66affSColin Finck Buffer[ModuleName->Length / sizeof(WCHAR)] = UNICODE_NULL;
835c2c66affSColin Finck
836c2c66affSColin Finck /*
837c2c66affSColin Finck * Generate filename without path (not needed by freeldr)
838c2c66affSColin Finck */
839c2c66affSColin Finck FileNameWithoutPath = wcsrchr(Buffer, L'\\');
840c2c66affSColin Finck if (FileNameWithoutPath == NULL)
841c2c66affSColin Finck {
842c2c66affSColin Finck FileNameWithoutPath = Buffer;
843c2c66affSColin Finck }
844c2c66affSColin Finck else
845c2c66affSColin Finck {
846c2c66affSColin Finck FileNameWithoutPath++;
847c2c66affSColin Finck }
848c2c66affSColin Finck
849c2c66affSColin Finck /*
850c2c66affSColin Finck * Strip the file extension from ServiceName
851c2c66affSColin Finck */
852c2c66affSColin Finck Success = RtlCreateUnicodeString(&ServiceName, FileNameWithoutPath);
853c2c66affSColin Finck ExFreePoolWithTag(Buffer, TAG_IO);
854c2c66affSColin Finck if (!Success)
855c2c66affSColin Finck {
85691fceab3SVictor Perevertkin return FALSE;
857c2c66affSColin Finck }
858c2c66affSColin Finck
859c2c66affSColin Finck FileExtension = wcsrchr(ServiceName.Buffer, L'.');
860c2c66affSColin Finck if (FileExtension != NULL)
861c2c66affSColin Finck {
862c2c66affSColin Finck ServiceName.Length -= (USHORT)wcslen(FileExtension) * sizeof(WCHAR);
863c2c66affSColin Finck FileExtension[0] = UNICODE_NULL;
864c2c66affSColin Finck }
865c2c66affSColin Finck
8664c95339dSVictor Perevertkin UNICODE_STRING RegistryPath;
8674c95339dSVictor Perevertkin
8684c95339dSVictor Perevertkin // Make the registry path for the driver
8694c95339dSVictor Perevertkin RegistryPath.Length = 0;
8704c95339dSVictor Perevertkin RegistryPath.MaximumLength = sizeof(ServicesKeyName) + ServiceName.Length;
8714c95339dSVictor Perevertkin RegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, RegistryPath.MaximumLength, TAG_IO);
8724c95339dSVictor Perevertkin if (RegistryPath.Buffer == NULL)
8734c95339dSVictor Perevertkin {
87491fceab3SVictor Perevertkin return FALSE;
8754c95339dSVictor Perevertkin }
8764c95339dSVictor Perevertkin RtlAppendUnicodeToString(&RegistryPath, ServicesKeyName);
8774c95339dSVictor Perevertkin RtlAppendUnicodeStringToString(&RegistryPath, &ServiceName);
8784c95339dSVictor Perevertkin RtlFreeUnicodeString(&ServiceName);
8794c95339dSVictor Perevertkin
8804c95339dSVictor Perevertkin HANDLE serviceHandle;
8814c95339dSVictor Perevertkin Status = IopOpenRegistryKeyEx(&serviceHandle, NULL, &RegistryPath, KEY_READ);
8824c95339dSVictor Perevertkin RtlFreeUnicodeString(&RegistryPath);
8834c95339dSVictor Perevertkin if (!NT_SUCCESS(Status))
8844c95339dSVictor Perevertkin {
88591fceab3SVictor Perevertkin return FALSE;
8864c95339dSVictor Perevertkin }
8874c95339dSVictor Perevertkin
888c2c66affSColin Finck /* Lookup the new Ldr entry in PsLoadedModuleList */
889a82ff90bSHermès Bélusca-Maïto for (NextEntry = PsLoadedModuleList.Flink;
890a82ff90bSHermès Bélusca-Maïto NextEntry != &PsLoadedModuleList;
891a82ff90bSHermès Bélusca-Maïto NextEntry = NextEntry->Flink)
892c2c66affSColin Finck {
893c2c66affSColin Finck LdrEntry = CONTAINING_RECORD(NextEntry,
894c2c66affSColin Finck LDR_DATA_TABLE_ENTRY,
895c2c66affSColin Finck InLoadOrderLinks);
896c2c66affSColin Finck if (RtlEqualUnicodeString(ModuleName, &LdrEntry->BaseDllName, TRUE))
897c2c66affSColin Finck {
898c2c66affSColin Finck break;
899c2c66affSColin Finck }
900c2c66affSColin Finck }
901c2c66affSColin Finck ASSERT(NextEntry != &PsLoadedModuleList);
902c2c66affSColin Finck
903c2c66affSColin Finck /*
904c2c66affSColin Finck * Initialize the driver
905c2c66affSColin Finck */
906e18a32dfSVictor Perevertkin NTSTATUS driverEntryStatus;
9076f0e37b0SVictor Perevertkin Status = IopInitializeDriverModule(LdrEntry,
9084c95339dSVictor Perevertkin serviceHandle,
909e18a32dfSVictor Perevertkin &DriverObject,
910e18a32dfSVictor Perevertkin &driverEntryStatus);
911c2c66affSColin Finck
912c2c66affSColin Finck if (!NT_SUCCESS(Status))
913c2c66affSColin Finck {
9146f0e37b0SVictor Perevertkin DPRINT1("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status);
91591fceab3SVictor Perevertkin return FALSE;
916c2c66affSColin Finck }
917c2c66affSColin Finck
91891fceab3SVictor Perevertkin // The driver has been loaded, now check if where are any PDOs
91991fceab3SVictor Perevertkin // for that driver, and queue AddDevice call for them.
92091fceab3SVictor Perevertkin // The check is possible because HKLM/SYSTEM/CCS/Services/<ServiceName>/Enum directory
92191fceab3SVictor Perevertkin // is populated upon a new device arrival based on a (critical) device database
92291fceab3SVictor Perevertkin
92391fceab3SVictor Perevertkin // Legacy drivers may add devices inside DriverEntry.
92491fceab3SVictor Perevertkin // We're lazy and always assume that they are doing so
925a82ff90bSHermès Bélusca-Maïto BOOLEAN deviceAdded = !!(DriverObject->Flags & DRVO_LEGACY_DRIVER);
92691fceab3SVictor Perevertkin
92791fceab3SVictor Perevertkin HANDLE enumServiceHandle;
92891fceab3SVictor Perevertkin UNICODE_STRING enumName = RTL_CONSTANT_STRING(L"Enum");
92991fceab3SVictor Perevertkin
93091fceab3SVictor Perevertkin Status = IopOpenRegistryKeyEx(&enumServiceHandle, serviceHandle, &enumName, KEY_READ);
93191fceab3SVictor Perevertkin ZwClose(serviceHandle);
93291fceab3SVictor Perevertkin
93391fceab3SVictor Perevertkin if (NT_SUCCESS(Status))
93491fceab3SVictor Perevertkin {
935a82ff90bSHermès Bélusca-Maïto ULONG instanceCount = 0;
93691fceab3SVictor Perevertkin PKEY_VALUE_FULL_INFORMATION kvInfo;
93791fceab3SVictor Perevertkin Status = IopGetRegistryValue(enumServiceHandle, L"Count", &kvInfo);
93891fceab3SVictor Perevertkin if (!NT_SUCCESS(Status))
93991fceab3SVictor Perevertkin {
94091fceab3SVictor Perevertkin goto Cleanup;
94191fceab3SVictor Perevertkin }
9420d28f271SHermès Bélusca-Maïto if (kvInfo->Type != REG_DWORD || kvInfo->DataLength != sizeof(ULONG))
94391fceab3SVictor Perevertkin {
94491fceab3SVictor Perevertkin ExFreePool(kvInfo);
94591fceab3SVictor Perevertkin goto Cleanup;
94691fceab3SVictor Perevertkin }
947fe416b67SHermès Bélusca-Maïto
948fe416b67SHermès Bélusca-Maïto RtlMoveMemory(&instanceCount,
949fe416b67SHermès Bélusca-Maïto (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
950fe416b67SHermès Bélusca-Maïto sizeof(ULONG));
95191fceab3SVictor Perevertkin ExFreePool(kvInfo);
95291fceab3SVictor Perevertkin
95391fceab3SVictor Perevertkin DPRINT("Processing %u instances for %wZ module\n", instanceCount, ModuleName);
95491fceab3SVictor Perevertkin
955a82ff90bSHermès Bélusca-Maïto for (ULONG i = 0; i < instanceCount; i++)
95691fceab3SVictor Perevertkin {
95791fceab3SVictor Perevertkin WCHAR num[11];
95891fceab3SVictor Perevertkin UNICODE_STRING instancePath;
9593b60f4faSHermès Bélusca-Maïto RtlStringCbPrintfW(num, sizeof(num), L"%u", i);
96091fceab3SVictor Perevertkin
96191fceab3SVictor Perevertkin Status = IopGetRegistryValue(enumServiceHandle, num, &kvInfo);
96291fceab3SVictor Perevertkin if (!NT_SUCCESS(Status))
96391fceab3SVictor Perevertkin {
96491fceab3SVictor Perevertkin continue;
96591fceab3SVictor Perevertkin }
96691fceab3SVictor Perevertkin if (kvInfo->Type != REG_SZ || kvInfo->DataLength == 0)
96791fceab3SVictor Perevertkin {
96891fceab3SVictor Perevertkin ExFreePool(kvInfo);
96991fceab3SVictor Perevertkin continue;
97091fceab3SVictor Perevertkin }
97191fceab3SVictor Perevertkin
9720d28f271SHermès Bélusca-Maïto instancePath.Length = kvInfo->DataLength - sizeof(UNICODE_NULL);
973a82ff90bSHermès Bélusca-Maïto instancePath.MaximumLength = kvInfo->DataLength;
97491fceab3SVictor Perevertkin instancePath.Buffer = ExAllocatePoolWithTag(NonPagedPool,
97591fceab3SVictor Perevertkin instancePath.MaximumLength,
97691fceab3SVictor Perevertkin TAG_IO);
97791fceab3SVictor Perevertkin if (instancePath.Buffer)
97891fceab3SVictor Perevertkin {
97991fceab3SVictor Perevertkin RtlMoveMemory(instancePath.Buffer,
98091fceab3SVictor Perevertkin (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
98191fceab3SVictor Perevertkin instancePath.Length);
9820d28f271SHermès Bélusca-Maïto instancePath.Buffer[instancePath.Length / sizeof(WCHAR)] = UNICODE_NULL;
98391fceab3SVictor Perevertkin
98491fceab3SVictor Perevertkin PDEVICE_OBJECT pdo = IopGetDeviceObjectFromDeviceInstance(&instancePath);
985543d3902SThomas Faber if (pdo != NULL)
986543d3902SThomas Faber {
98791fceab3SVictor Perevertkin PiQueueDeviceAction(pdo, PiActionAddBootDevices, NULL, NULL);
98891fceab3SVictor Perevertkin ObDereferenceObject(pdo);
98991fceab3SVictor Perevertkin deviceAdded = TRUE;
99091fceab3SVictor Perevertkin }
991543d3902SThomas Faber else
992543d3902SThomas Faber {
993543d3902SThomas Faber DPRINT1("No device node found matching instance path '%wZ'\n", &instancePath);
994543d3902SThomas Faber }
995543d3902SThomas Faber }
99691fceab3SVictor Perevertkin
99791fceab3SVictor Perevertkin ExFreePool(kvInfo);
99891fceab3SVictor Perevertkin }
99991fceab3SVictor Perevertkin
100091fceab3SVictor Perevertkin ZwClose(enumServiceHandle);
100191fceab3SVictor Perevertkin }
100291fceab3SVictor Perevertkin Cleanup:
1003c2c66affSColin Finck /* Remove extra reference from IopInitializeDriverModule */
1004c2c66affSColin Finck ObDereferenceObject(DriverObject);
1005c2c66affSColin Finck
100691fceab3SVictor Perevertkin return deviceAdded;
1007c2c66affSColin Finck }
1008c2c66affSColin Finck
1009c2c66affSColin Finck /*
1010c2c66affSColin Finck * IopInitializeBootDrivers
1011c2c66affSColin Finck *
1012c2c66affSColin Finck * Initialize boot drivers and free memory for boot files.
1013c2c66affSColin Finck *
1014c2c66affSColin Finck * Parameters
1015c2c66affSColin Finck * None
1016c2c66affSColin Finck *
1017c2c66affSColin Finck * Return Value
1018c2c66affSColin Finck * None
1019c2c66affSColin Finck */
10205c7ce447SVictor Perevertkin CODE_SEG("INIT")
1021c2c66affSColin Finck VOID
1022c2c66affSColin Finck FASTCALL
IopInitializeBootDrivers(VOID)1023c2c66affSColin Finck IopInitializeBootDrivers(VOID)
1024c2c66affSColin Finck {
1025c2c66affSColin Finck PLIST_ENTRY ListHead, NextEntry, NextEntry2;
1026c2c66affSColin Finck PLDR_DATA_TABLE_ENTRY LdrEntry;
1027c2c66affSColin Finck NTSTATUS Status;
1028c2c66affSColin Finck UNICODE_STRING DriverName;
1029c2c66affSColin Finck ULONG i, Index;
1030c2c66affSColin Finck PDRIVER_INFORMATION DriverInfo, DriverInfoTag;
1031c2c66affSColin Finck HANDLE KeyHandle;
1032c2c66affSColin Finck PBOOT_DRIVER_LIST_ENTRY BootEntry;
1033c2c66affSColin Finck DPRINT("IopInitializeBootDrivers()\n");
1034c2c66affSColin Finck
1035e18a32dfSVictor Perevertkin /* Create the RAW FS built-in driver */
1036e18a32dfSVictor Perevertkin RtlInitUnicodeString(&DriverName, L"\\FileSystem\\RAW");
1037c2c66affSColin Finck
1038e18a32dfSVictor Perevertkin Status = IoCreateDriver(&DriverName, RawFsDriverEntry);
1039c2c66affSColin Finck if (!NT_SUCCESS(Status))
1040c2c66affSColin Finck {
1041c2c66affSColin Finck /* Fail */
1042c2c66affSColin Finck return;
1043c2c66affSColin Finck }
1044c2c66affSColin Finck
1045c2c66affSColin Finck /* Get highest group order index */
1046c2c66affSColin Finck IopGroupIndex = PpInitGetGroupOrderIndex(NULL);
104700bd373eSKatayama Hirofumi MZ if (IopGroupIndex == 0xFFFF)
104800bd373eSKatayama Hirofumi MZ {
104900bd373eSKatayama Hirofumi MZ UNIMPLEMENTED_DBGBREAK();
105000bd373eSKatayama Hirofumi MZ }
1051c2c66affSColin Finck
1052c2c66affSColin Finck /* Allocate the group table */
1053c2c66affSColin Finck IopGroupTable = ExAllocatePoolWithTag(PagedPool,
1054c2c66affSColin Finck IopGroupIndex * sizeof(LIST_ENTRY),
1055c2c66affSColin Finck TAG_IO);
105600bd373eSKatayama Hirofumi MZ if (IopGroupTable == NULL)
105700bd373eSKatayama Hirofumi MZ {
105800bd373eSKatayama Hirofumi MZ UNIMPLEMENTED_DBGBREAK();
105900bd373eSKatayama Hirofumi MZ }
1060c2c66affSColin Finck
1061c2c66affSColin Finck /* Initialize the group table lists */
1062c2c66affSColin Finck for (i = 0; i < IopGroupIndex; i++) InitializeListHead(&IopGroupTable[i]);
1063c2c66affSColin Finck
1064c2c66affSColin Finck /* Loop the boot modules */
1065c2c66affSColin Finck ListHead = &KeLoaderBlock->LoadOrderListHead;
1066a82ff90bSHermès Bélusca-Maïto for (NextEntry = ListHead->Flink;
1067a82ff90bSHermès Bélusca-Maïto NextEntry != ListHead;
1068a82ff90bSHermès Bélusca-Maïto NextEntry = NextEntry->Flink)
1069c2c66affSColin Finck {
1070c2c66affSColin Finck /* Get the entry */
1071c2c66affSColin Finck LdrEntry = CONTAINING_RECORD(NextEntry,
1072c2c66affSColin Finck LDR_DATA_TABLE_ENTRY,
1073c2c66affSColin Finck InLoadOrderLinks);
1074c2c66affSColin Finck
1075c2c66affSColin Finck /* Check if the DLL needs to be initialized */
1076c2c66affSColin Finck if (LdrEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL)
1077c2c66affSColin Finck {
1078c2c66affSColin Finck /* Call its entrypoint */
1079c2c66affSColin Finck MmCallDllInitialize(LdrEntry, NULL);
1080c2c66affSColin Finck }
1081c2c66affSColin Finck }
1082c2c66affSColin Finck
1083c2c66affSColin Finck /* Loop the boot drivers */
1084c2c66affSColin Finck ListHead = &KeLoaderBlock->BootDriverListHead;
1085a82ff90bSHermès Bélusca-Maïto for (NextEntry = ListHead->Flink;
1086a82ff90bSHermès Bélusca-Maïto NextEntry != ListHead;
1087a82ff90bSHermès Bélusca-Maïto NextEntry = NextEntry->Flink)
1088c2c66affSColin Finck {
1089c2c66affSColin Finck /* Get the entry */
1090c2c66affSColin Finck BootEntry = CONTAINING_RECORD(NextEntry,
1091c2c66affSColin Finck BOOT_DRIVER_LIST_ENTRY,
1092c2c66affSColin Finck Link);
1093c2c66affSColin Finck
1094f2645e48SHermès Bélusca-Maïto // FIXME: TODO: This LdrEntry is to be used in a special handling
1095f2645e48SHermès Bélusca-Maïto // for SETUPLDR (a similar procedure is done on Windows), where
1096f2645e48SHermès Bélusca-Maïto // the loader would, under certain conditions, be loaded in the
1097f2645e48SHermès Bélusca-Maïto // SETUPLDR-specific code block below...
1098f2645e48SHermès Bélusca-Maïto #if 0
1099c2c66affSColin Finck /* Get the driver loader entry */
1100c2c66affSColin Finck LdrEntry = BootEntry->LdrEntry;
1101f2645e48SHermès Bélusca-Maïto #endif
1102c2c66affSColin Finck
1103c2c66affSColin Finck /* Allocate our internal accounting structure */
1104c2c66affSColin Finck DriverInfo = ExAllocatePoolWithTag(PagedPool,
1105c2c66affSColin Finck sizeof(DRIVER_INFORMATION),
1106c2c66affSColin Finck TAG_IO);
1107c2c66affSColin Finck if (DriverInfo)
1108c2c66affSColin Finck {
1109c2c66affSColin Finck /* Zero it and initialize it */
1110c2c66affSColin Finck RtlZeroMemory(DriverInfo, sizeof(DRIVER_INFORMATION));
1111c2c66affSColin Finck InitializeListHead(&DriverInfo->Link);
1112c2c66affSColin Finck DriverInfo->DataTableEntry = BootEntry;
1113c2c66affSColin Finck
1114c2c66affSColin Finck /* Open the registry key */
1115c2c66affSColin Finck Status = IopOpenRegistryKeyEx(&KeyHandle,
1116c2c66affSColin Finck NULL,
1117c2c66affSColin Finck &BootEntry->RegistryPath,
1118c2c66affSColin Finck KEY_READ);
11198e51bb65SPierre Schweitzer DPRINT("IopOpenRegistryKeyEx(%wZ) returned 0x%08lx\n", &BootEntry->RegistryPath, Status);
1120cb69c4c6SHermès Bélusca-Maïto #if 0
1121cb69c4c6SHermès Bélusca-Maïto if (NT_SUCCESS(Status))
1122cb69c4c6SHermès Bélusca-Maïto #else // Hack still needed...
1123c2c66affSColin Finck if ((NT_SUCCESS(Status)) || /* ReactOS HACK for SETUPLDR */
1124c2c66affSColin Finck ((KeLoaderBlock->SetupLdrBlock) && ((KeyHandle = (PVOID)1)))) // yes, it's an assignment!
1125cb69c4c6SHermès Bélusca-Maïto #endif
1126c2c66affSColin Finck {
1127c2c66affSColin Finck /* Save the handle */
1128c2c66affSColin Finck DriverInfo->ServiceHandle = KeyHandle;
1129c2c66affSColin Finck
1130c2c66affSColin Finck /* Get the group oder index */
1131c2c66affSColin Finck Index = PpInitGetGroupOrderIndex(KeyHandle);
1132c2c66affSColin Finck
1133c2c66affSColin Finck /* Get the tag position */
1134c2c66affSColin Finck DriverInfo->TagPosition = PipGetDriverTagPriority(KeyHandle);
1135c2c66affSColin Finck
1136c2c66affSColin Finck /* Insert it into the list, at the right place */
1137c2c66affSColin Finck ASSERT(Index < IopGroupIndex);
1138c2c66affSColin Finck NextEntry2 = IopGroupTable[Index].Flink;
1139c2c66affSColin Finck while (NextEntry2 != &IopGroupTable[Index])
1140c2c66affSColin Finck {
1141c2c66affSColin Finck /* Get the driver info */
1142c2c66affSColin Finck DriverInfoTag = CONTAINING_RECORD(NextEntry2,
1143c2c66affSColin Finck DRIVER_INFORMATION,
1144c2c66affSColin Finck Link);
1145c2c66affSColin Finck
1146c2c66affSColin Finck /* Check if we found the right tag position */
1147c2c66affSColin Finck if (DriverInfoTag->TagPosition > DriverInfo->TagPosition)
1148c2c66affSColin Finck {
1149c2c66affSColin Finck /* We're done */
1150c2c66affSColin Finck break;
1151c2c66affSColin Finck }
1152c2c66affSColin Finck
1153c2c66affSColin Finck /* Next entry */
1154c2c66affSColin Finck NextEntry2 = NextEntry2->Flink;
1155c2c66affSColin Finck }
1156c2c66affSColin Finck
1157c2c66affSColin Finck /* Insert us right before the next entry */
1158c2c66affSColin Finck NextEntry2 = NextEntry2->Blink;
1159c2c66affSColin Finck InsertHeadList(NextEntry2, &DriverInfo->Link);
1160c2c66affSColin Finck }
1161c2c66affSColin Finck }
1162c2c66affSColin Finck }
1163c2c66affSColin Finck
1164c2c66affSColin Finck /* Loop each group index */
1165c2c66affSColin Finck for (i = 0; i < IopGroupIndex; i++)
1166c2c66affSColin Finck {
1167c2c66affSColin Finck /* Loop each group table */
1168a82ff90bSHermès Bélusca-Maïto for (NextEntry = IopGroupTable[i].Flink;
1169a82ff90bSHermès Bélusca-Maïto NextEntry != &IopGroupTable[i];
1170a82ff90bSHermès Bélusca-Maïto NextEntry = NextEntry->Flink)
1171c2c66affSColin Finck {
1172c2c66affSColin Finck /* Get the entry */
1173c2c66affSColin Finck DriverInfo = CONTAINING_RECORD(NextEntry,
1174c2c66affSColin Finck DRIVER_INFORMATION,
1175c2c66affSColin Finck Link);
1176c2c66affSColin Finck
1177c2c66affSColin Finck /* Get the driver loader entry */
1178c2c66affSColin Finck LdrEntry = DriverInfo->DataTableEntry->LdrEntry;
1179c2c66affSColin Finck
1180c2c66affSColin Finck /* Initialize it */
118191fceab3SVictor Perevertkin if (IopInitializeBuiltinDriver(LdrEntry))
118291fceab3SVictor Perevertkin {
118391fceab3SVictor Perevertkin // it does not make sense to enumerate the tree if there are no new devices added
1184d6ef8f97SVictor Perevertkin PiQueueDeviceAction(IopRootDeviceNode->PhysicalDeviceObject,
1185d6ef8f97SVictor Perevertkin PiActionEnumRootDevices,
1186d6ef8f97SVictor Perevertkin NULL,
1187d6ef8f97SVictor Perevertkin NULL);
118891fceab3SVictor Perevertkin }
1189c2c66affSColin Finck }
1190c2c66affSColin Finck }
1191c2c66affSColin Finck
11922839c850SVictor Perevertkin /* HAL Root Bus is being initialized before loading the boot drivers so this may cause issues
11932839c850SVictor Perevertkin * when some devices are not being initialized with their drivers. This flag is used to delay
11942839c850SVictor Perevertkin * all actions with devices (except PnP root device) until boot drivers are loaded.
11952839c850SVictor Perevertkin * See PiQueueDeviceAction function
11962839c850SVictor Perevertkin */
11972839c850SVictor Perevertkin PnPBootDriversLoaded = TRUE;
1198b7042928SVictor Perevertkin
1199b7042928SVictor Perevertkin DbgPrint("BOOT DRIVERS LOADED\n");
1200b7042928SVictor Perevertkin
1201b7042928SVictor Perevertkin PiQueueDeviceAction(IopRootDeviceNode->PhysicalDeviceObject,
1202b7042928SVictor Perevertkin PiActionEnumDeviceTree,
1203b7042928SVictor Perevertkin NULL,
1204b7042928SVictor Perevertkin NULL);
1205c2c66affSColin Finck }
1206c2c66affSColin Finck
12075c7ce447SVictor Perevertkin CODE_SEG("INIT")
1208c2c66affSColin Finck VOID
1209c2c66affSColin Finck FASTCALL
IopInitializeSystemDrivers(VOID)1210c2c66affSColin Finck IopInitializeSystemDrivers(VOID)
1211c2c66affSColin Finck {
1212c2c66affSColin Finck PUNICODE_STRING *DriverList, *SavedList;
1213c2c66affSColin Finck
1214b7042928SVictor Perevertkin PiPerformSyncDeviceAction(IopRootDeviceNode->PhysicalDeviceObject, PiActionEnumDeviceTree);
1215b7042928SVictor Perevertkin
1216d1b3115aSHermès Bélusca-Maïto /* HACK: No system drivers on the BootCD */
1217d1b3115aSHermès Bélusca-Maïto if (KeLoaderBlock->SetupLdrBlock) return;
1218c2c66affSColin Finck
1219c2c66affSColin Finck /* Get the driver list */
1220c2c66affSColin Finck SavedList = DriverList = CmGetSystemDriverList();
1221c2c66affSColin Finck ASSERT(DriverList);
1222c2c66affSColin Finck
1223c2c66affSColin Finck /* Loop it */
1224c2c66affSColin Finck while (*DriverList)
1225c2c66affSColin Finck {
1226c2c66affSColin Finck /* Load the driver */
1227c2c66affSColin Finck ZwLoadDriver(*DriverList);
1228c2c66affSColin Finck
1229c2c66affSColin Finck /* Free the entry */
1230c2c66affSColin Finck RtlFreeUnicodeString(*DriverList);
1231c2c66affSColin Finck ExFreePool(*DriverList);
1232c2c66affSColin Finck
1233c2c66affSColin Finck /* Next entry */
1234c2c66affSColin Finck InbvIndicateProgress();
1235c2c66affSColin Finck DriverList++;
1236c2c66affSColin Finck }
1237c2c66affSColin Finck
1238c2c66affSColin Finck /* Free the list */
1239c2c66affSColin Finck ExFreePool(SavedList);
1240b7042928SVictor Perevertkin
1241b7042928SVictor Perevertkin PiQueueDeviceAction(IopRootDeviceNode->PhysicalDeviceObject,
1242b7042928SVictor Perevertkin PiActionEnumDeviceTree,
1243b7042928SVictor Perevertkin NULL,
1244b7042928SVictor Perevertkin NULL);
1245c2c66affSColin Finck }
1246c2c66affSColin Finck
1247c2c66affSColin Finck /*
1248c2c66affSColin Finck * IopUnloadDriver
1249c2c66affSColin Finck *
1250c2c66affSColin Finck * Unloads a device driver.
1251c2c66affSColin Finck *
1252c2c66affSColin Finck * Parameters
1253c2c66affSColin Finck * DriverServiceName
1254c2c66affSColin Finck * Name of the service to unload (registry key).
1255c2c66affSColin Finck *
1256c2c66affSColin Finck * UnloadPnpDrivers
1257c2c66affSColin Finck * Whether to unload Plug & Plug or only legacy drivers. If this
1258c2c66affSColin Finck * parameter is set to FALSE, the routine will unload only legacy
1259c2c66affSColin Finck * drivers.
1260c2c66affSColin Finck *
1261c2c66affSColin Finck * Return Value
1262c2c66affSColin Finck * Status
1263c2c66affSColin Finck *
1264c2c66affSColin Finck * To do
1265c2c66affSColin Finck * Guard the whole function by SEH.
1266c2c66affSColin Finck */
1267c2c66affSColin Finck
1268c2c66affSColin Finck NTSTATUS NTAPI
IopUnloadDriver(PUNICODE_STRING DriverServiceName,BOOLEAN UnloadPnpDrivers)1269c2c66affSColin Finck IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
1270c2c66affSColin Finck {
1271c904983bSThomas Faber UNICODE_STRING Backslash = RTL_CONSTANT_STRING(L"\\");
1272c2c66affSColin Finck RTL_QUERY_REGISTRY_TABLE QueryTable[2];
1273c2c66affSColin Finck UNICODE_STRING ImagePath;
1274c2c66affSColin Finck UNICODE_STRING ServiceName;
1275c2c66affSColin Finck UNICODE_STRING ObjectName;
1276c2c66affSColin Finck PDRIVER_OBJECT DriverObject;
1277c2c66affSColin Finck PDEVICE_OBJECT DeviceObject;
1278c2c66affSColin Finck PEXTENDED_DEVOBJ_EXTENSION DeviceExtension;
1279c2c66affSColin Finck NTSTATUS Status;
1280c904983bSThomas Faber USHORT LastBackslash;
1281c2c66affSColin Finck BOOLEAN SafeToUnload = TRUE;
1282daf9743cSPierre Schweitzer KPROCESSOR_MODE PreviousMode;
1283daf9743cSPierre Schweitzer UNICODE_STRING CapturedServiceName;
1284c2c66affSColin Finck
1285c2c66affSColin Finck PAGED_CODE();
1286c2c66affSColin Finck
1287daf9743cSPierre Schweitzer PreviousMode = ExGetPreviousMode();
1288daf9743cSPierre Schweitzer
1289daf9743cSPierre Schweitzer /* Need the appropriate priviliege */
1290daf9743cSPierre Schweitzer if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode))
1291daf9743cSPierre Schweitzer {
1292daf9743cSPierre Schweitzer DPRINT1("No unload privilege!\n");
1293daf9743cSPierre Schweitzer return STATUS_PRIVILEGE_NOT_HELD;
1294daf9743cSPierre Schweitzer }
1295daf9743cSPierre Schweitzer
1296daf9743cSPierre Schweitzer /* Capture the service name */
129744511f08SHermès Bélusca-Maïto Status = ProbeAndCaptureUnicodeString(&CapturedServiceName,
129844511f08SHermès Bélusca-Maïto PreviousMode,
129944511f08SHermès Bélusca-Maïto DriverServiceName);
1300daf9743cSPierre Schweitzer if (!NT_SUCCESS(Status))
1301a6a3aa0fSVictor Perevertkin {
1302daf9743cSPierre Schweitzer return Status;
1303a6a3aa0fSVictor Perevertkin }
1304daf9743cSPierre Schweitzer
1305daf9743cSPierre Schweitzer DPRINT("IopUnloadDriver('%wZ', %u)\n", &CapturedServiceName, UnloadPnpDrivers);
1306daf9743cSPierre Schweitzer
1307daf9743cSPierre Schweitzer /* We need a service name */
1308a748350fSHermès Bélusca-Maïto if (CapturedServiceName.Length == 0 || CapturedServiceName.Buffer == NULL)
1309daf9743cSPierre Schweitzer {
1310daf9743cSPierre Schweitzer ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1311daf9743cSPierre Schweitzer return STATUS_INVALID_PARAMETER;
1312daf9743cSPierre Schweitzer }
1313daf9743cSPierre Schweitzer
1314c2c66affSColin Finck /*
1315c2c66affSColin Finck * Get the service name from the registry key name
1316c2c66affSColin Finck */
1317c904983bSThomas Faber Status = RtlFindCharInUnicodeString(RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END,
1318c904983bSThomas Faber &CapturedServiceName,
1319c904983bSThomas Faber &Backslash,
1320c904983bSThomas Faber &LastBackslash);
1321c904983bSThomas Faber if (NT_SUCCESS(Status))
1322c904983bSThomas Faber {
1323c904983bSThomas Faber NT_ASSERT(CapturedServiceName.Length >= LastBackslash + sizeof(WCHAR));
1324c904983bSThomas Faber ServiceName.Buffer = &CapturedServiceName.Buffer[LastBackslash / sizeof(WCHAR) + 1];
1325c904983bSThomas Faber ServiceName.Length = CapturedServiceName.Length - LastBackslash - sizeof(WCHAR);
1326c904983bSThomas Faber ServiceName.MaximumLength = CapturedServiceName.MaximumLength - LastBackslash - sizeof(WCHAR);
1327c904983bSThomas Faber }
1328c2c66affSColin Finck else
1329c904983bSThomas Faber {
1330c904983bSThomas Faber ServiceName = CapturedServiceName;
1331c904983bSThomas Faber }
1332c2c66affSColin Finck
1333c2c66affSColin Finck /*
1334c2c66affSColin Finck * Construct the driver object name
1335c2c66affSColin Finck */
1336c904983bSThomas Faber Status = RtlUShortAdd(sizeof(DRIVER_ROOT_NAME),
1337c904983bSThomas Faber ServiceName.Length,
1338c904983bSThomas Faber &ObjectName.MaximumLength);
1339c904983bSThomas Faber if (!NT_SUCCESS(Status))
1340c904983bSThomas Faber {
1341c904983bSThomas Faber ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1342c904983bSThomas Faber return Status;
1343c904983bSThomas Faber }
1344c904983bSThomas Faber ObjectName.Length = 0;
1345c2c66affSColin Finck ObjectName.Buffer = ExAllocatePoolWithTag(PagedPool,
1346c2c66affSColin Finck ObjectName.MaximumLength,
1347c2c66affSColin Finck TAG_IO);
1348daf9743cSPierre Schweitzer if (!ObjectName.Buffer)
1349daf9743cSPierre Schweitzer {
1350daf9743cSPierre Schweitzer ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1351daf9743cSPierre Schweitzer return STATUS_INSUFFICIENT_RESOURCES;
1352daf9743cSPierre Schweitzer }
1353c904983bSThomas Faber NT_VERIFY(NT_SUCCESS(RtlAppendUnicodeToString(&ObjectName, DRIVER_ROOT_NAME)));
1354c904983bSThomas Faber NT_VERIFY(NT_SUCCESS(RtlAppendUnicodeStringToString(&ObjectName, &ServiceName)));
1355c2c66affSColin Finck
1356c2c66affSColin Finck /*
1357c2c66affSColin Finck * Find the driver object
1358c2c66affSColin Finck */
1359c2c66affSColin Finck Status = ObReferenceObjectByName(&ObjectName,
1360c2c66affSColin Finck 0,
1361c2c66affSColin Finck 0,
1362c2c66affSColin Finck 0,
1363c2c66affSColin Finck IoDriverObjectType,
1364c2c66affSColin Finck KernelMode,
1365c2c66affSColin Finck 0,
1366c2c66affSColin Finck (PVOID*)&DriverObject);
1367c2c66affSColin Finck
1368c2c66affSColin Finck if (!NT_SUCCESS(Status))
1369c2c66affSColin Finck {
1370c2c66affSColin Finck DPRINT1("Can't locate driver object for %wZ\n", &ObjectName);
1371c2c66affSColin Finck ExFreePoolWithTag(ObjectName.Buffer, TAG_IO);
1372daf9743cSPierre Schweitzer ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1373c2c66affSColin Finck return Status;
1374c2c66affSColin Finck }
1375c2c66affSColin Finck
1376c2c66affSColin Finck /* Free the buffer for driver object name */
1377c2c66affSColin Finck ExFreePoolWithTag(ObjectName.Buffer, TAG_IO);
1378c2c66affSColin Finck
1379c2c66affSColin Finck /* Check that driver is not already unloading */
1380c2c66affSColin Finck if (DriverObject->Flags & DRVO_UNLOAD_INVOKED)
1381c2c66affSColin Finck {
1382c2c66affSColin Finck DPRINT1("Driver deletion pending\n");
1383c2c66affSColin Finck ObDereferenceObject(DriverObject);
1384daf9743cSPierre Schweitzer ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1385c2c66affSColin Finck return STATUS_DELETE_PENDING;
1386c2c66affSColin Finck }
1387c2c66affSColin Finck
1388c2c66affSColin Finck /*
1389c2c66affSColin Finck * Get path of service...
1390c2c66affSColin Finck */
1391c2c66affSColin Finck RtlZeroMemory(QueryTable, sizeof(QueryTable));
1392c2c66affSColin Finck
1393c2c66affSColin Finck RtlInitUnicodeString(&ImagePath, NULL);
1394c2c66affSColin Finck
1395c2c66affSColin Finck QueryTable[0].Name = L"ImagePath";
1396c2c66affSColin Finck QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
1397c2c66affSColin Finck QueryTable[0].EntryContext = &ImagePath;
1398c2c66affSColin Finck
1399c2c66affSColin Finck Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
1400daf9743cSPierre Schweitzer CapturedServiceName.Buffer,
1401c2c66affSColin Finck QueryTable,
1402c2c66affSColin Finck NULL,
1403c2c66affSColin Finck NULL);
1404c2c66affSColin Finck
1405daf9743cSPierre Schweitzer /* We no longer need service name */
1406daf9743cSPierre Schweitzer ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1407daf9743cSPierre Schweitzer
1408c2c66affSColin Finck if (!NT_SUCCESS(Status))
1409c2c66affSColin Finck {
1410c2c66affSColin Finck DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status);
1411c2c66affSColin Finck ObDereferenceObject(DriverObject);
1412c2c66affSColin Finck return Status;
1413c2c66affSColin Finck }
1414c2c66affSColin Finck
1415c2c66affSColin Finck /*
1416c2c66affSColin Finck * Normalize the image path for all later processing.
1417c2c66affSColin Finck */
1418c2c66affSColin Finck Status = IopNormalizeImagePath(&ImagePath, &ServiceName);
1419c2c66affSColin Finck
1420c2c66affSColin Finck if (!NT_SUCCESS(Status))
1421c2c66affSColin Finck {
1422c2c66affSColin Finck DPRINT1("IopNormalizeImagePath() failed (Status %x)\n", Status);
1423c2c66affSColin Finck ObDereferenceObject(DriverObject);
1424c2c66affSColin Finck return Status;
1425c2c66affSColin Finck }
1426c2c66affSColin Finck
1427c2c66affSColin Finck /* Free the service path */
1428c2c66affSColin Finck ExFreePool(ImagePath.Buffer);
1429c2c66affSColin Finck
1430c2c66affSColin Finck /*
1431c2c66affSColin Finck * Unload the module and release the references to the device object
1432c2c66affSColin Finck */
1433c2c66affSColin Finck
1434c2c66affSColin Finck /* Call the load/unload routine, depending on current process */
1435c2c66affSColin Finck if (DriverObject->DriverUnload && DriverObject->DriverSection &&
1436c2c66affSColin Finck (UnloadPnpDrivers || (DriverObject->Flags & DRVO_LEGACY_DRIVER)))
1437c2c66affSColin Finck {
1438c2c66affSColin Finck /* Loop through each device object of the driver
1439c2c66affSColin Finck and set DOE_UNLOAD_PENDING flag */
1440c2c66affSColin Finck DeviceObject = DriverObject->DeviceObject;
1441c2c66affSColin Finck while (DeviceObject)
1442c2c66affSColin Finck {
1443c2c66affSColin Finck /* Set the unload pending flag for the device */
1444c2c66affSColin Finck DeviceExtension = IoGetDevObjExtension(DeviceObject);
1445c2c66affSColin Finck DeviceExtension->ExtensionFlags |= DOE_UNLOAD_PENDING;
1446c2c66affSColin Finck
1447c2c66affSColin Finck /* Make sure there are no attached devices or no reference counts */
1448c2c66affSColin Finck if ((DeviceObject->ReferenceCount) || (DeviceObject->AttachedDevice))
1449c2c66affSColin Finck {
1450c2c66affSColin Finck /* Not safe to unload */
1451c2c66affSColin Finck DPRINT1("Drivers device object is referenced or has attached devices\n");
1452c2c66affSColin Finck
1453c2c66affSColin Finck SafeToUnload = FALSE;
1454c2c66affSColin Finck }
1455c2c66affSColin Finck
1456c2c66affSColin Finck DeviceObject = DeviceObject->NextDevice;
1457c2c66affSColin Finck }
1458c2c66affSColin Finck
1459c2c66affSColin Finck /* If not safe to unload, then return success */
1460c2c66affSColin Finck if (!SafeToUnload)
1461c2c66affSColin Finck {
1462c2c66affSColin Finck ObDereferenceObject(DriverObject);
1463c2c66affSColin Finck return STATUS_SUCCESS;
1464c2c66affSColin Finck }
1465c2c66affSColin Finck
1466c2c66affSColin Finck DPRINT1("Unloading driver '%wZ' (manual)\n", &DriverObject->DriverName);
1467c2c66affSColin Finck
1468c2c66affSColin Finck /* Set the unload invoked flag and call the unload routine */
1469c2c66affSColin Finck DriverObject->Flags |= DRVO_UNLOAD_INVOKED;
1470a6a3aa0fSVictor Perevertkin Status = IopDoLoadUnloadDriver(NULL, &DriverObject);
1471c2c66affSColin Finck ASSERT(Status == STATUS_SUCCESS);
1472c2c66affSColin Finck
1473c2c66affSColin Finck /* Mark the driver object temporary, so it could be deleted later */
1474c2c66affSColin Finck ObMakeTemporaryObject(DriverObject);
1475c2c66affSColin Finck
1476c2c66affSColin Finck /* Dereference it 2 times */
1477c2c66affSColin Finck ObDereferenceObject(DriverObject);
1478c2c66affSColin Finck ObDereferenceObject(DriverObject);
1479c2c66affSColin Finck
1480c2c66affSColin Finck return Status;
1481c2c66affSColin Finck }
1482c2c66affSColin Finck else
1483c2c66affSColin Finck {
1484c2c66affSColin Finck DPRINT1("No DriverUnload function! '%wZ' will not be unloaded!\n", &DriverObject->DriverName);
1485c2c66affSColin Finck
1486c2c66affSColin Finck /* Dereference one time (refd inside this function) */
1487c2c66affSColin Finck ObDereferenceObject(DriverObject);
1488c2c66affSColin Finck
1489c2c66affSColin Finck /* Return unloading failure */
1490c2c66affSColin Finck return STATUS_INVALID_DEVICE_REQUEST;
1491c2c66affSColin Finck }
1492c2c66affSColin Finck }
1493c2c66affSColin Finck
1494c2c66affSColin Finck VOID
1495c2c66affSColin Finck NTAPI
IopReinitializeDrivers(VOID)1496c2c66affSColin Finck IopReinitializeDrivers(VOID)
1497c2c66affSColin Finck {
1498c2c66affSColin Finck PDRIVER_REINIT_ITEM ReinitItem;
1499c2c66affSColin Finck PLIST_ENTRY Entry;
1500c2c66affSColin Finck
1501c2c66affSColin Finck /* Get the first entry and start looping */
1502c2c66affSColin Finck Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead,
1503c2c66affSColin Finck &DriverReinitListLock);
1504c2c66affSColin Finck while (Entry)
1505c2c66affSColin Finck {
1506c2c66affSColin Finck /* Get the item */
1507c2c66affSColin Finck ReinitItem = CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry);
1508c2c66affSColin Finck
1509c2c66affSColin Finck /* Increment reinitialization counter */
1510c2c66affSColin Finck ReinitItem->DriverObject->DriverExtension->Count++;
1511c2c66affSColin Finck
1512c2c66affSColin Finck /* Remove the device object flag */
1513c2c66affSColin Finck ReinitItem->DriverObject->Flags &= ~DRVO_REINIT_REGISTERED;
1514c2c66affSColin Finck
1515c2c66affSColin Finck /* Call the routine */
1516c2c66affSColin Finck ReinitItem->ReinitRoutine(ReinitItem->DriverObject,
1517c2c66affSColin Finck ReinitItem->Context,
1518c2c66affSColin Finck ReinitItem->DriverObject->
1519c2c66affSColin Finck DriverExtension->Count);
1520c2c66affSColin Finck
1521c2c66affSColin Finck /* Free the entry */
1522c2c66affSColin Finck ExFreePool(Entry);
1523c2c66affSColin Finck
1524c2c66affSColin Finck /* Move to the next one */
1525c2c66affSColin Finck Entry = ExInterlockedRemoveHeadList(&DriverReinitListHead,
1526c2c66affSColin Finck &DriverReinitListLock);
1527c2c66affSColin Finck }
1528c2c66affSColin Finck }
1529c2c66affSColin Finck
1530c2c66affSColin Finck VOID
1531c2c66affSColin Finck NTAPI
IopReinitializeBootDrivers(VOID)1532c2c66affSColin Finck IopReinitializeBootDrivers(VOID)
1533c2c66affSColin Finck {
1534c2c66affSColin Finck PDRIVER_REINIT_ITEM ReinitItem;
1535c2c66affSColin Finck PLIST_ENTRY Entry;
1536c2c66affSColin Finck
1537c2c66affSColin Finck /* Get the first entry and start looping */
1538c2c66affSColin Finck Entry = ExInterlockedRemoveHeadList(&DriverBootReinitListHead,
1539c2c66affSColin Finck &DriverBootReinitListLock);
1540c2c66affSColin Finck while (Entry)
1541c2c66affSColin Finck {
1542c2c66affSColin Finck /* Get the item */
1543c2c66affSColin Finck ReinitItem = CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry);
1544c2c66affSColin Finck
1545c2c66affSColin Finck /* Increment reinitialization counter */
1546c2c66affSColin Finck ReinitItem->DriverObject->DriverExtension->Count++;
1547c2c66affSColin Finck
1548c2c66affSColin Finck /* Remove the device object flag */
1549c2c66affSColin Finck ReinitItem->DriverObject->Flags &= ~DRVO_BOOTREINIT_REGISTERED;
1550c2c66affSColin Finck
1551c2c66affSColin Finck /* Call the routine */
1552c2c66affSColin Finck ReinitItem->ReinitRoutine(ReinitItem->DriverObject,
1553c2c66affSColin Finck ReinitItem->Context,
1554c2c66affSColin Finck ReinitItem->DriverObject->
1555c2c66affSColin Finck DriverExtension->Count);
1556c2c66affSColin Finck
1557c2c66affSColin Finck /* Free the entry */
1558c2c66affSColin Finck ExFreePool(Entry);
1559c2c66affSColin Finck
1560c2c66affSColin Finck /* Move to the next one */
1561c2c66affSColin Finck Entry = ExInterlockedRemoveHeadList(&DriverBootReinitListHead,
1562c2c66affSColin Finck &DriverBootReinitListLock);
1563c2c66affSColin Finck }
15642839c850SVictor Perevertkin
15652839c850SVictor Perevertkin /* Wait for all device actions being finished*/
15662839c850SVictor Perevertkin KeWaitForSingleObject(&PiEnumerationFinished, Executive, KernelMode, FALSE, NULL);
1567c2c66affSColin Finck }
1568c2c66affSColin Finck
1569e18a32dfSVictor Perevertkin /* PUBLIC FUNCTIONS ***********************************************************/
1570e18a32dfSVictor Perevertkin
1571e18a32dfSVictor Perevertkin /*
1572e18a32dfSVictor Perevertkin * @implemented
1573e18a32dfSVictor Perevertkin */
1574c2c66affSColin Finck NTSTATUS
1575c2c66affSColin Finck NTAPI
IoCreateDriver(_In_opt_ PUNICODE_STRING DriverName,_In_ PDRIVER_INITIALIZE InitializationFunction)1576e18a32dfSVictor Perevertkin IoCreateDriver(
1577e18a32dfSVictor Perevertkin _In_opt_ PUNICODE_STRING DriverName,
1578e18a32dfSVictor Perevertkin _In_ PDRIVER_INITIALIZE InitializationFunction)
1579c2c66affSColin Finck {
1580c2c66affSColin Finck WCHAR NameBuffer[100];
1581c2c66affSColin Finck USHORT NameLength;
1582c2c66affSColin Finck UNICODE_STRING LocalDriverName;
1583c2c66affSColin Finck NTSTATUS Status;
1584c2c66affSColin Finck OBJECT_ATTRIBUTES ObjectAttributes;
1585c2c66affSColin Finck ULONG ObjectSize;
1586c2c66affSColin Finck PDRIVER_OBJECT DriverObject;
1587c2c66affSColin Finck UNICODE_STRING ServiceKeyName;
1588c2c66affSColin Finck HANDLE hDriver;
1589c2c66affSColin Finck ULONG i, RetryCount = 0;
1590c2c66affSColin Finck
1591c2c66affSColin Finck try_again:
1592c2c66affSColin Finck /* First, create a unique name for the driver if we don't have one */
1593c2c66affSColin Finck if (!DriverName)
1594c2c66affSColin Finck {
1595c2c66affSColin Finck /* Create a random name and set up the string */
1596c2c66affSColin Finck NameLength = (USHORT)swprintf(NameBuffer,
1597c2c66affSColin Finck DRIVER_ROOT_NAME L"%08u",
1598c2c66affSColin Finck KeTickCount.LowPart);
1599c2c66affSColin Finck LocalDriverName.Length = NameLength * sizeof(WCHAR);
1600c2c66affSColin Finck LocalDriverName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL);
1601c2c66affSColin Finck LocalDriverName.Buffer = NameBuffer;
1602c2c66affSColin Finck }
1603c2c66affSColin Finck else
1604c2c66affSColin Finck {
1605c2c66affSColin Finck /* So we can avoid another code path, use a local var */
1606c2c66affSColin Finck LocalDriverName = *DriverName;
1607c2c66affSColin Finck }
1608c2c66affSColin Finck
1609c2c66affSColin Finck /* Initialize the Attributes */
1610c2c66affSColin Finck ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(EXTENDED_DRIVER_EXTENSION);
1611c2c66affSColin Finck InitializeObjectAttributes(&ObjectAttributes,
1612c2c66affSColin Finck &LocalDriverName,
1613c2c66affSColin Finck OBJ_PERMANENT | OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
1614c2c66affSColin Finck NULL,
1615c2c66affSColin Finck NULL);
1616c2c66affSColin Finck
1617c2c66affSColin Finck /* Create the Object */
1618c2c66affSColin Finck Status = ObCreateObject(KernelMode,
1619c2c66affSColin Finck IoDriverObjectType,
1620c2c66affSColin Finck &ObjectAttributes,
1621c2c66affSColin Finck KernelMode,
1622c2c66affSColin Finck NULL,
1623c2c66affSColin Finck ObjectSize,
1624c2c66affSColin Finck 0,
1625c2c66affSColin Finck 0,
1626c2c66affSColin Finck (PVOID*)&DriverObject);
1627c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status;
1628c2c66affSColin Finck
1629c2c66affSColin Finck DPRINT("IopCreateDriver(): created DO %p\n", DriverObject);
1630c2c66affSColin Finck
1631c2c66affSColin Finck /* Set up the Object */
1632c2c66affSColin Finck RtlZeroMemory(DriverObject, ObjectSize);
1633c2c66affSColin Finck DriverObject->Type = IO_TYPE_DRIVER;
1634c2c66affSColin Finck DriverObject->Size = sizeof(DRIVER_OBJECT);
163545012aa4SHermès Bélusca-Maïto DriverObject->Flags = DRVO_BUILTIN_DRIVER;
1636c2c66affSColin Finck DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1);
1637c2c66affSColin Finck DriverObject->DriverExtension->DriverObject = DriverObject;
1638c2c66affSColin Finck DriverObject->DriverInit = InitializationFunction;
1639c2c66affSColin Finck /* Loop all Major Functions */
1640c2c66affSColin Finck for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
1641c2c66affSColin Finck {
1642c2c66affSColin Finck /* Invalidate each function */
1643c2c66affSColin Finck DriverObject->MajorFunction[i] = IopInvalidDeviceRequest;
1644c2c66affSColin Finck }
1645c2c66affSColin Finck
1646c2c66affSColin Finck /* Set up the service key name buffer */
1647e18a32dfSVictor Perevertkin ServiceKeyName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL);
1648e18a32dfSVictor Perevertkin ServiceKeyName.Buffer = ExAllocatePoolWithTag(PagedPool, LocalDriverName.MaximumLength, TAG_IO);
1649c2c66affSColin Finck if (!ServiceKeyName.Buffer)
1650c2c66affSColin Finck {
1651c2c66affSColin Finck /* Fail */
1652c2c66affSColin Finck ObMakeTemporaryObject(DriverObject);
1653c2c66affSColin Finck ObDereferenceObject(DriverObject);
1654c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
1655c2c66affSColin Finck }
1656c2c66affSColin Finck
1657e18a32dfSVictor Perevertkin /* For builtin drivers, the ServiceKeyName is equal to DriverName */
1658e18a32dfSVictor Perevertkin RtlCopyUnicodeString(&ServiceKeyName, &LocalDriverName);
1659e18a32dfSVictor Perevertkin ServiceKeyName.Buffer[ServiceKeyName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1660c2c66affSColin Finck DriverObject->DriverExtension->ServiceKeyName = ServiceKeyName;
1661c2c66affSColin Finck
1662c2c66affSColin Finck /* Make a copy of the driver name to store in the driver object */
1663c2c66affSColin Finck DriverObject->DriverName.MaximumLength = LocalDriverName.Length;
1664c2c66affSColin Finck DriverObject->DriverName.Buffer = ExAllocatePoolWithTag(PagedPool,
1665c2c66affSColin Finck DriverObject->DriverName.MaximumLength,
1666c2c66affSColin Finck TAG_IO);
1667c2c66affSColin Finck if (!DriverObject->DriverName.Buffer)
1668c2c66affSColin Finck {
1669c2c66affSColin Finck /* Fail */
1670c2c66affSColin Finck ObMakeTemporaryObject(DriverObject);
1671c2c66affSColin Finck ObDereferenceObject(DriverObject);
1672c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
1673c2c66affSColin Finck }
1674c2c66affSColin Finck
1675e18a32dfSVictor Perevertkin RtlCopyUnicodeString(&DriverObject->DriverName, &LocalDriverName);
1676c2c66affSColin Finck
1677c2c66affSColin Finck /* Add the Object and get its handle */
1678c2c66affSColin Finck Status = ObInsertObject(DriverObject,
1679c2c66affSColin Finck NULL,
1680c2c66affSColin Finck FILE_READ_DATA,
1681c2c66affSColin Finck 0,
1682c2c66affSColin Finck NULL,
1683c2c66affSColin Finck &hDriver);
1684c2c66affSColin Finck
1685c2c66affSColin Finck /* Eliminate small possibility when this function is called more than
1686c2c66affSColin Finck once in a row, and KeTickCount doesn't get enough time to change */
1687c2c66affSColin Finck if (!DriverName && (Status == STATUS_OBJECT_NAME_COLLISION) && (RetryCount < 100))
1688c2c66affSColin Finck {
1689c2c66affSColin Finck RetryCount++;
1690c2c66affSColin Finck goto try_again;
1691c2c66affSColin Finck }
1692c2c66affSColin Finck
1693c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status;
1694c2c66affSColin Finck
1695c2c66affSColin Finck /* Now reference it */
1696c2c66affSColin Finck Status = ObReferenceObjectByHandle(hDriver,
1697c2c66affSColin Finck 0,
1698c2c66affSColin Finck IoDriverObjectType,
1699c2c66affSColin Finck KernelMode,
1700c2c66affSColin Finck (PVOID*)&DriverObject,
1701c2c66affSColin Finck NULL);
1702c2c66affSColin Finck
1703c2c66affSColin Finck /* Close the extra handle */
1704c2c66affSColin Finck ZwClose(hDriver);
1705c2c66affSColin Finck
1706c2c66affSColin Finck if (!NT_SUCCESS(Status))
1707c2c66affSColin Finck {
1708c2c66affSColin Finck /* Fail */
1709c2c66affSColin Finck ObMakeTemporaryObject(DriverObject);
1710c2c66affSColin Finck ObDereferenceObject(DriverObject);
1711c2c66affSColin Finck return Status;
1712c2c66affSColin Finck }
1713c2c66affSColin Finck
1714c2c66affSColin Finck /* Finally, call its init function */
1715c2c66affSColin Finck DPRINT("Calling driver entrypoint at %p\n", InitializationFunction);
1716a82ff90bSHermès Bélusca-Maïto Status = InitializationFunction(DriverObject, NULL);
1717c2c66affSColin Finck if (!NT_SUCCESS(Status))
1718c2c66affSColin Finck {
1719c2c66affSColin Finck /* If it didn't work, then kill the object */
17204a93b0a4SHermès Bélusca-Maïto DPRINT1("'%wZ' initialization failed, status (0x%08lx)\n", &LocalDriverName, Status);
1721c2c66affSColin Finck ObMakeTemporaryObject(DriverObject);
1722c2c66affSColin Finck ObDereferenceObject(DriverObject);
1723c2c66affSColin Finck return Status;
1724c2c66affSColin Finck }
1725c2c66affSColin Finck
17264a93b0a4SHermès Bélusca-Maïto /* Windows does this fixup, keep it for compatibility */
1727c2c66affSColin Finck for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
1728c2c66affSColin Finck {
1729c2c66affSColin Finck /*
1730c2c66affSColin Finck * Make sure the driver didn't set any dispatch entry point to NULL!
1731c2c66affSColin Finck * Doing so is illegal; drivers shouldn't touch entry points they
1732c2c66affSColin Finck * do not implement.
1733c2c66affSColin Finck */
1734c2c66affSColin Finck
1735c2c66affSColin Finck /* Check if it did so anyway */
1736c2c66affSColin Finck if (!DriverObject->MajorFunction[i])
1737c2c66affSColin Finck {
1738c2c66affSColin Finck /* Print a warning in the debug log */
1739c2c66affSColin Finck DPRINT1("Driver <%wZ> set DriverObject->MajorFunction[%lu] to NULL!\n",
1740c2c66affSColin Finck &DriverObject->DriverName, i);
1741c2c66affSColin Finck
1742c2c66affSColin Finck /* Fix it up */
1743c2c66affSColin Finck DriverObject->MajorFunction[i] = IopInvalidDeviceRequest;
1744c2c66affSColin Finck }
1745c2c66affSColin Finck }
1746c2c66affSColin Finck
1747c2c66affSColin Finck /* Return the Status */
1748c2c66affSColin Finck return Status;
1749c2c66affSColin Finck }
1750c2c66affSColin Finck
1751c2c66affSColin Finck /*
1752c2c66affSColin Finck * @implemented
1753c2c66affSColin Finck */
1754c2c66affSColin Finck VOID
1755c2c66affSColin Finck NTAPI
IoDeleteDriver(_In_ PDRIVER_OBJECT DriverObject)175656be4eafSHermès Bélusca-Maïto IoDeleteDriver(
175756be4eafSHermès Bélusca-Maïto _In_ PDRIVER_OBJECT DriverObject)
1758c2c66affSColin Finck {
1759c2c66affSColin Finck /* Simply dereference the Object */
1760c2c66affSColin Finck ObDereferenceObject(DriverObject);
1761c2c66affSColin Finck }
1762c2c66affSColin Finck
1763c2c66affSColin Finck /*
1764c2c66affSColin Finck * @implemented
1765c2c66affSColin Finck */
1766c2c66affSColin Finck VOID
1767c2c66affSColin Finck NTAPI
IoRegisterBootDriverReinitialization(IN PDRIVER_OBJECT DriverObject,IN PDRIVER_REINITIALIZE ReinitRoutine,IN PVOID Context)1768c2c66affSColin Finck IoRegisterBootDriverReinitialization(IN PDRIVER_OBJECT DriverObject,
1769c2c66affSColin Finck IN PDRIVER_REINITIALIZE ReinitRoutine,
1770c2c66affSColin Finck IN PVOID Context)
1771c2c66affSColin Finck {
1772c2c66affSColin Finck PDRIVER_REINIT_ITEM ReinitItem;
1773c2c66affSColin Finck
1774c2c66affSColin Finck /* Allocate the entry */
1775c2c66affSColin Finck ReinitItem = ExAllocatePoolWithTag(NonPagedPool,
1776c2c66affSColin Finck sizeof(DRIVER_REINIT_ITEM),
1777c2c66affSColin Finck TAG_REINIT);
1778c2c66affSColin Finck if (!ReinitItem) return;
1779c2c66affSColin Finck
1780c2c66affSColin Finck /* Fill it out */
1781c2c66affSColin Finck ReinitItem->DriverObject = DriverObject;
1782c2c66affSColin Finck ReinitItem->ReinitRoutine = ReinitRoutine;
1783c2c66affSColin Finck ReinitItem->Context = Context;
1784c2c66affSColin Finck
1785c2c66affSColin Finck /* Set the Driver Object flag and insert the entry into the list */
1786c2c66affSColin Finck DriverObject->Flags |= DRVO_BOOTREINIT_REGISTERED;
1787c2c66affSColin Finck ExInterlockedInsertTailList(&DriverBootReinitListHead,
1788c2c66affSColin Finck &ReinitItem->ItemEntry,
1789c2c66affSColin Finck &DriverBootReinitListLock);
1790c2c66affSColin Finck }
1791c2c66affSColin Finck
1792c2c66affSColin Finck /*
1793c2c66affSColin Finck * @implemented
1794c2c66affSColin Finck */
1795c2c66affSColin Finck VOID
1796c2c66affSColin Finck NTAPI
IoRegisterDriverReinitialization(IN PDRIVER_OBJECT DriverObject,IN PDRIVER_REINITIALIZE ReinitRoutine,IN PVOID Context)1797c2c66affSColin Finck IoRegisterDriverReinitialization(IN PDRIVER_OBJECT DriverObject,
1798c2c66affSColin Finck IN PDRIVER_REINITIALIZE ReinitRoutine,
1799c2c66affSColin Finck IN PVOID Context)
1800c2c66affSColin Finck {
1801c2c66affSColin Finck PDRIVER_REINIT_ITEM ReinitItem;
1802c2c66affSColin Finck
1803c2c66affSColin Finck /* Allocate the entry */
1804c2c66affSColin Finck ReinitItem = ExAllocatePoolWithTag(NonPagedPool,
1805c2c66affSColin Finck sizeof(DRIVER_REINIT_ITEM),
1806c2c66affSColin Finck TAG_REINIT);
1807c2c66affSColin Finck if (!ReinitItem) return;
1808c2c66affSColin Finck
1809c2c66affSColin Finck /* Fill it out */
1810c2c66affSColin Finck ReinitItem->DriverObject = DriverObject;
1811c2c66affSColin Finck ReinitItem->ReinitRoutine = ReinitRoutine;
1812c2c66affSColin Finck ReinitItem->Context = Context;
1813c2c66affSColin Finck
1814c2c66affSColin Finck /* Set the Driver Object flag and insert the entry into the list */
1815c2c66affSColin Finck DriverObject->Flags |= DRVO_REINIT_REGISTERED;
1816c2c66affSColin Finck ExInterlockedInsertTailList(&DriverReinitListHead,
1817c2c66affSColin Finck &ReinitItem->ItemEntry,
1818c2c66affSColin Finck &DriverReinitListLock);
1819c2c66affSColin Finck }
1820c2c66affSColin Finck
1821c2c66affSColin Finck /*
1822c2c66affSColin Finck * @implemented
1823c2c66affSColin Finck */
1824c2c66affSColin Finck NTSTATUS
1825c2c66affSColin Finck NTAPI
IoAllocateDriverObjectExtension(IN PDRIVER_OBJECT DriverObject,IN PVOID ClientIdentificationAddress,IN ULONG DriverObjectExtensionSize,OUT PVOID * DriverObjectExtension)1826c2c66affSColin Finck IoAllocateDriverObjectExtension(IN PDRIVER_OBJECT DriverObject,
1827c2c66affSColin Finck IN PVOID ClientIdentificationAddress,
1828c2c66affSColin Finck IN ULONG DriverObjectExtensionSize,
1829c2c66affSColin Finck OUT PVOID *DriverObjectExtension)
1830c2c66affSColin Finck {
1831c2c66affSColin Finck KIRQL OldIrql;
1832c2c66affSColin Finck PIO_CLIENT_EXTENSION DriverExtensions, NewDriverExtension;
1833c2c66affSColin Finck BOOLEAN Inserted = FALSE;
1834c2c66affSColin Finck
1835c2c66affSColin Finck /* Assume failure */
1836c2c66affSColin Finck *DriverObjectExtension = NULL;
1837c2c66affSColin Finck
1838c2c66affSColin Finck /* Allocate the extension */
1839c2c66affSColin Finck NewDriverExtension = ExAllocatePoolWithTag(NonPagedPool,
1840c2c66affSColin Finck sizeof(IO_CLIENT_EXTENSION) +
1841c2c66affSColin Finck DriverObjectExtensionSize,
1842c2c66affSColin Finck TAG_DRIVER_EXTENSION);
1843c2c66affSColin Finck if (!NewDriverExtension) return STATUS_INSUFFICIENT_RESOURCES;
1844c2c66affSColin Finck
1845c2c66affSColin Finck /* Clear the extension for teh caller */
1846c2c66affSColin Finck RtlZeroMemory(NewDriverExtension,
1847c2c66affSColin Finck sizeof(IO_CLIENT_EXTENSION) + DriverObjectExtensionSize);
1848c2c66affSColin Finck
1849c2c66affSColin Finck /* Acqure lock */
1850c2c66affSColin Finck OldIrql = KeRaiseIrqlToDpcLevel();
1851c2c66affSColin Finck
1852c2c66affSColin Finck /* Fill out the extension */
1853c2c66affSColin Finck NewDriverExtension->ClientIdentificationAddress = ClientIdentificationAddress;
1854c2c66affSColin Finck
1855c2c66affSColin Finck /* Loop the current extensions */
1856c2c66affSColin Finck DriverExtensions = IoGetDrvObjExtension(DriverObject)->
1857c2c66affSColin Finck ClientDriverExtension;
1858c2c66affSColin Finck while (DriverExtensions)
1859c2c66affSColin Finck {
1860c2c66affSColin Finck /* Check if the identifier matches */
1861c2c66affSColin Finck if (DriverExtensions->ClientIdentificationAddress ==
1862c2c66affSColin Finck ClientIdentificationAddress)
1863c2c66affSColin Finck {
1864c2c66affSColin Finck /* We have a collision, break out */
1865c2c66affSColin Finck break;
1866c2c66affSColin Finck }
1867c2c66affSColin Finck
1868c2c66affSColin Finck /* Go to the next one */
1869c2c66affSColin Finck DriverExtensions = DriverExtensions->NextExtension;
1870c2c66affSColin Finck }
1871c2c66affSColin Finck
1872c2c66affSColin Finck /* Check if we didn't collide */
1873c2c66affSColin Finck if (!DriverExtensions)
1874c2c66affSColin Finck {
1875c2c66affSColin Finck /* Link this one in */
1876c2c66affSColin Finck NewDriverExtension->NextExtension =
1877c2c66affSColin Finck IoGetDrvObjExtension(DriverObject)->ClientDriverExtension;
1878c2c66affSColin Finck IoGetDrvObjExtension(DriverObject)->ClientDriverExtension =
1879c2c66affSColin Finck NewDriverExtension;
1880c2c66affSColin Finck Inserted = TRUE;
1881c2c66affSColin Finck }
1882c2c66affSColin Finck
1883c2c66affSColin Finck /* Release the lock */
1884c2c66affSColin Finck KeLowerIrql(OldIrql);
1885c2c66affSColin Finck
1886c2c66affSColin Finck /* Check if insertion failed */
1887c2c66affSColin Finck if (!Inserted)
1888c2c66affSColin Finck {
1889c2c66affSColin Finck /* Free the entry and fail */
1890c2c66affSColin Finck ExFreePoolWithTag(NewDriverExtension, TAG_DRIVER_EXTENSION);
1891c2c66affSColin Finck return STATUS_OBJECT_NAME_COLLISION;
1892c2c66affSColin Finck }
1893c2c66affSColin Finck
1894c2c66affSColin Finck /* Otherwise, return the pointer */
1895c2c66affSColin Finck *DriverObjectExtension = NewDriverExtension + 1;
1896c2c66affSColin Finck return STATUS_SUCCESS;
1897c2c66affSColin Finck }
1898c2c66affSColin Finck
1899c2c66affSColin Finck /*
1900c2c66affSColin Finck * @implemented
1901c2c66affSColin Finck */
1902c2c66affSColin Finck PVOID
1903c2c66affSColin Finck NTAPI
IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject,IN PVOID ClientIdentificationAddress)1904c2c66affSColin Finck IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject,
1905c2c66affSColin Finck IN PVOID ClientIdentificationAddress)
1906c2c66affSColin Finck {
1907c2c66affSColin Finck KIRQL OldIrql;
1908c2c66affSColin Finck PIO_CLIENT_EXTENSION DriverExtensions;
1909c2c66affSColin Finck
1910c2c66affSColin Finck /* Acquire lock */
1911c2c66affSColin Finck OldIrql = KeRaiseIrqlToDpcLevel();
1912c2c66affSColin Finck
1913c2c66affSColin Finck /* Loop the list until we find the right one */
1914c2c66affSColin Finck DriverExtensions = IoGetDrvObjExtension(DriverObject)->ClientDriverExtension;
1915c2c66affSColin Finck while (DriverExtensions)
1916c2c66affSColin Finck {
1917c2c66affSColin Finck /* Check for a match */
1918c2c66affSColin Finck if (DriverExtensions->ClientIdentificationAddress ==
1919c2c66affSColin Finck ClientIdentificationAddress)
1920c2c66affSColin Finck {
1921c2c66affSColin Finck /* Break out */
1922c2c66affSColin Finck break;
1923c2c66affSColin Finck }
1924c2c66affSColin Finck
1925c2c66affSColin Finck /* Keep looping */
1926c2c66affSColin Finck DriverExtensions = DriverExtensions->NextExtension;
1927c2c66affSColin Finck }
1928c2c66affSColin Finck
1929c2c66affSColin Finck /* Release lock */
1930c2c66affSColin Finck KeLowerIrql(OldIrql);
1931c2c66affSColin Finck
1932c2c66affSColin Finck /* Return nothing or the extension */
1933c2c66affSColin Finck if (!DriverExtensions) return NULL;
1934c2c66affSColin Finck return DriverExtensions + 1;
1935c2c66affSColin Finck }
1936c2c66affSColin Finck
1937c2c66affSColin Finck NTSTATUS
IopLoadDriver(_In_ HANDLE ServiceHandle,_Out_ PDRIVER_OBJECT * DriverObject)1938a6a3aa0fSVictor Perevertkin IopLoadDriver(
19394c95339dSVictor Perevertkin _In_ HANDLE ServiceHandle,
19404c95339dSVictor Perevertkin _Out_ PDRIVER_OBJECT *DriverObject)
1941c2c66affSColin Finck {
1942c2c66affSColin Finck UNICODE_STRING ImagePath;
1943c2c66affSColin Finck NTSTATUS Status;
1944c2c66affSColin Finck PLDR_DATA_TABLE_ENTRY ModuleObject;
1945c2c66affSColin Finck PVOID BaseAddress;
1946c2c66affSColin Finck
19474c95339dSVictor Perevertkin PKEY_VALUE_FULL_INFORMATION kvInfo;
19484c95339dSVictor Perevertkin Status = IopGetRegistryValue(ServiceHandle, L"ImagePath", &kvInfo);
19494c95339dSVictor Perevertkin if (NT_SUCCESS(Status))
1950c2c66affSColin Finck {
1951947f60b2SVictor Perevertkin if ((kvInfo->Type != REG_EXPAND_SZ && kvInfo->Type != REG_SZ) || kvInfo->DataLength == 0)
1952c2c66affSColin Finck {
19534c95339dSVictor Perevertkin ExFreePool(kvInfo);
19544c95339dSVictor Perevertkin return STATUS_ILL_FORMED_SERVICE_ENTRY;
1955c2c66affSColin Finck }
1956c2c66affSColin Finck
1957a82ff90bSHermès Bélusca-Maïto ImagePath.Length = kvInfo->DataLength - sizeof(UNICODE_NULL);
1958a82ff90bSHermès Bélusca-Maïto ImagePath.MaximumLength = kvInfo->DataLength;
19594c95339dSVictor Perevertkin ImagePath.Buffer = ExAllocatePoolWithTag(PagedPool, ImagePath.MaximumLength, TAG_RTLREGISTRY);
19604c95339dSVictor Perevertkin if (!ImagePath.Buffer)
1961c2c66affSColin Finck {
19624c95339dSVictor Perevertkin ExFreePool(kvInfo);
19634c95339dSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES;
19644c95339dSVictor Perevertkin }
19654c95339dSVictor Perevertkin
19664c95339dSVictor Perevertkin RtlMoveMemory(ImagePath.Buffer,
19674c95339dSVictor Perevertkin (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
19684c95339dSVictor Perevertkin ImagePath.Length);
19690d28f271SHermès Bélusca-Maïto ImagePath.Buffer[ImagePath.Length / sizeof(WCHAR)] = UNICODE_NULL;
19704c95339dSVictor Perevertkin ExFreePool(kvInfo);
19714c95339dSVictor Perevertkin }
19724c95339dSVictor Perevertkin else
19734c95339dSVictor Perevertkin {
1974c2c66affSColin Finck return Status;
1975c2c66affSColin Finck }
1976c2c66affSColin Finck
1977c2c66affSColin Finck /*
1978c2c66affSColin Finck * Normalize the image path for all later processing.
1979c2c66affSColin Finck */
19804c95339dSVictor Perevertkin Status = IopNormalizeImagePath(&ImagePath, NULL);
1981c2c66affSColin Finck if (!NT_SUCCESS(Status))
1982c2c66affSColin Finck {
1983c2c66affSColin Finck DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status);
1984c2c66affSColin Finck return Status;
1985c2c66affSColin Finck }
1986c2c66affSColin Finck
1987c2c66affSColin Finck DPRINT("FullImagePath: '%wZ'\n", &ImagePath);
1988c2c66affSColin Finck
1989c2c66affSColin Finck KeEnterCriticalRegion();
1990c2c66affSColin Finck ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE);
1991c2c66affSColin Finck
1992c2c66affSColin Finck /*
1993c2c66affSColin Finck * Load the driver module
1994c2c66affSColin Finck */
1995c2c66affSColin Finck DPRINT("Loading module from %wZ\n", &ImagePath);
1996c2c66affSColin Finck Status = MmLoadSystemImage(&ImagePath, NULL, NULL, 0, (PVOID)&ModuleObject, &BaseAddress);
19974c95339dSVictor Perevertkin RtlFreeUnicodeString(&ImagePath);
19984c95339dSVictor Perevertkin
1999c2c66affSColin Finck if (!NT_SUCCESS(Status))
2000c2c66affSColin Finck {
2001c2c66affSColin Finck DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status);
2002c2c66affSColin Finck ExReleaseResourceLite(&IopDriverLoadResource);
2003c2c66affSColin Finck KeLeaveCriticalRegion();
2004c2c66affSColin Finck return Status;
2005c2c66affSColin Finck }
2006c2c66affSColin Finck
20074c95339dSVictor Perevertkin // Display the loading message
20084c95339dSVictor Perevertkin ULONG infoLength;
20094c95339dSVictor Perevertkin Status = ZwQueryKey(ServiceHandle, KeyBasicInformation, NULL, 0, &infoLength);
20104c95339dSVictor Perevertkin if (Status == STATUS_BUFFER_TOO_SMALL)
20114c95339dSVictor Perevertkin {
20124c95339dSVictor Perevertkin PKEY_BASIC_INFORMATION servName = ExAllocatePoolWithTag(PagedPool, infoLength, TAG_IO);
20134c95339dSVictor Perevertkin if (servName)
20144c95339dSVictor Perevertkin {
20154c95339dSVictor Perevertkin Status = ZwQueryKey(ServiceHandle,
20164c95339dSVictor Perevertkin KeyBasicInformation,
20174c95339dSVictor Perevertkin servName,
20184c95339dSVictor Perevertkin infoLength,
20194c95339dSVictor Perevertkin &infoLength);
20204c95339dSVictor Perevertkin if (NT_SUCCESS(Status))
20214c95339dSVictor Perevertkin {
20224c95339dSVictor Perevertkin UNICODE_STRING serviceName = {
20234c95339dSVictor Perevertkin .Length = servName->NameLength,
20244c95339dSVictor Perevertkin .MaximumLength = servName->NameLength,
20254c95339dSVictor Perevertkin .Buffer = servName->Name
20264c95339dSVictor Perevertkin };
20274c95339dSVictor Perevertkin
20284c95339dSVictor Perevertkin IopDisplayLoadingMessage(&serviceName);
20294c95339dSVictor Perevertkin }
20304c95339dSVictor Perevertkin ExFreePoolWithTag(servName, TAG_IO);
20314c95339dSVictor Perevertkin }
20324c95339dSVictor Perevertkin }
2033c2c66affSColin Finck
2034e18a32dfSVictor Perevertkin NTSTATUS driverEntryStatus;
20356f0e37b0SVictor Perevertkin Status = IopInitializeDriverModule(ModuleObject,
20364c95339dSVictor Perevertkin ServiceHandle,
2037e18a32dfSVictor Perevertkin DriverObject,
2038e18a32dfSVictor Perevertkin &driverEntryStatus);
2039c2c66affSColin Finck if (!NT_SUCCESS(Status))
2040c2c66affSColin Finck {
2041c2c66affSColin Finck DPRINT1("IopInitializeDriverModule() failed (Status %lx)\n", Status);
2042c2c66affSColin Finck }
2043c2c66affSColin Finck
2044c2c66affSColin Finck ExReleaseResourceLite(&IopDriverLoadResource);
2045c2c66affSColin Finck KeLeaveCriticalRegion();
2046c2c66affSColin Finck
2047c2c66affSColin Finck return Status;
2048c2c66affSColin Finck }
2049c2c66affSColin Finck
2050a6a3aa0fSVictor Perevertkin static
2051a6a3aa0fSVictor Perevertkin VOID
2052a6a3aa0fSVictor Perevertkin NTAPI
IopLoadUnloadDriverWorker(_Inout_ PVOID Parameter)2053a6a3aa0fSVictor Perevertkin IopLoadUnloadDriverWorker(
2054a6a3aa0fSVictor Perevertkin _Inout_ PVOID Parameter)
2055a6a3aa0fSVictor Perevertkin {
2056a6a3aa0fSVictor Perevertkin PLOAD_UNLOAD_PARAMS LoadParams = Parameter;
2057a6a3aa0fSVictor Perevertkin
2058a6a3aa0fSVictor Perevertkin ASSERT(PsGetCurrentProcess() == PsInitialSystemProcess);
2059a6a3aa0fSVictor Perevertkin
2060a6a3aa0fSVictor Perevertkin if (LoadParams->DriverObject)
2061a6a3aa0fSVictor Perevertkin {
2062a6a3aa0fSVictor Perevertkin // unload request
2063a6a3aa0fSVictor Perevertkin LoadParams->DriverObject->DriverUnload(LoadParams->DriverObject);
2064a6a3aa0fSVictor Perevertkin LoadParams->Status = STATUS_SUCCESS;
2065a6a3aa0fSVictor Perevertkin }
2066a6a3aa0fSVictor Perevertkin else
2067a6a3aa0fSVictor Perevertkin {
2068a6a3aa0fSVictor Perevertkin // load request
20694c95339dSVictor Perevertkin HANDLE serviceHandle;
20704c95339dSVictor Perevertkin NTSTATUS status;
20714c95339dSVictor Perevertkin status = IopOpenRegistryKeyEx(&serviceHandle, NULL, LoadParams->RegistryPath, KEY_READ);
20724c95339dSVictor Perevertkin if (!NT_SUCCESS(status))
20734c95339dSVictor Perevertkin {
20744c95339dSVictor Perevertkin LoadParams->Status = status;
20754c95339dSVictor Perevertkin }
20764c95339dSVictor Perevertkin else
20774c95339dSVictor Perevertkin {
20784c95339dSVictor Perevertkin LoadParams->Status = IopLoadDriver(serviceHandle, &LoadParams->DriverObject);
20794c95339dSVictor Perevertkin ZwClose(serviceHandle);
20804c95339dSVictor Perevertkin }
2081a6a3aa0fSVictor Perevertkin }
2082a6a3aa0fSVictor Perevertkin
2083a6a3aa0fSVictor Perevertkin if (LoadParams->SetEvent)
2084a6a3aa0fSVictor Perevertkin {
2085a6a3aa0fSVictor Perevertkin KeSetEvent(&LoadParams->Event, 0, FALSE);
2086a6a3aa0fSVictor Perevertkin }
2087a6a3aa0fSVictor Perevertkin }
2088a6a3aa0fSVictor Perevertkin
2089a6a3aa0fSVictor Perevertkin /**
2090a6a3aa0fSVictor Perevertkin * @brief Process load and unload driver operations. This is mostly for NtLoadDriver
2091a6a3aa0fSVictor Perevertkin * and NtUnloadDriver, because their code should run inside PsInitialSystemProcess
2092a6a3aa0fSVictor Perevertkin *
2093a6a3aa0fSVictor Perevertkin * @param[in] RegistryPath The registry path
2094a6a3aa0fSVictor Perevertkin * @param DriverObject The driver object
2095a6a3aa0fSVictor Perevertkin *
2096a6a3aa0fSVictor Perevertkin * @return Status of the operation
2097a6a3aa0fSVictor Perevertkin */
2098a6a3aa0fSVictor Perevertkin NTSTATUS
IopDoLoadUnloadDriver(_In_opt_ PUNICODE_STRING RegistryPath,_Inout_ PDRIVER_OBJECT * DriverObject)2099a6a3aa0fSVictor Perevertkin IopDoLoadUnloadDriver(
21004c95339dSVictor Perevertkin _In_opt_ PUNICODE_STRING RegistryPath,
2101a6a3aa0fSVictor Perevertkin _Inout_ PDRIVER_OBJECT *DriverObject)
2102a6a3aa0fSVictor Perevertkin {
2103a6a3aa0fSVictor Perevertkin LOAD_UNLOAD_PARAMS LoadParams;
2104a6a3aa0fSVictor Perevertkin
2105a6a3aa0fSVictor Perevertkin /* Prepare parameters block */
2106a6a3aa0fSVictor Perevertkin LoadParams.RegistryPath = RegistryPath;
2107a6a3aa0fSVictor Perevertkin LoadParams.DriverObject = *DriverObject;
2108a6a3aa0fSVictor Perevertkin
2109a6a3aa0fSVictor Perevertkin if (PsGetCurrentProcess() != PsInitialSystemProcess)
2110a6a3aa0fSVictor Perevertkin {
2111a6a3aa0fSVictor Perevertkin LoadParams.SetEvent = TRUE;
2112a6a3aa0fSVictor Perevertkin KeInitializeEvent(&LoadParams.Event, NotificationEvent, FALSE);
2113a6a3aa0fSVictor Perevertkin
2114a6a3aa0fSVictor Perevertkin /* Initialize and queue a work item */
2115a6a3aa0fSVictor Perevertkin ExInitializeWorkItem(&LoadParams.WorkItem, IopLoadUnloadDriverWorker, &LoadParams);
2116a6a3aa0fSVictor Perevertkin ExQueueWorkItem(&LoadParams.WorkItem, DelayedWorkQueue);
2117a6a3aa0fSVictor Perevertkin
2118a6a3aa0fSVictor Perevertkin /* And wait till it completes */
2119a6a3aa0fSVictor Perevertkin KeWaitForSingleObject(&LoadParams.Event, UserRequest, KernelMode, FALSE, NULL);
2120a6a3aa0fSVictor Perevertkin }
2121a6a3aa0fSVictor Perevertkin else
2122a6a3aa0fSVictor Perevertkin {
2123a6a3aa0fSVictor Perevertkin /* If we're already in a system process, call it right here */
2124a6a3aa0fSVictor Perevertkin LoadParams.SetEvent = FALSE;
2125a6a3aa0fSVictor Perevertkin IopLoadUnloadDriverWorker(&LoadParams);
2126a6a3aa0fSVictor Perevertkin }
2127a6a3aa0fSVictor Perevertkin
2128a6a3aa0fSVictor Perevertkin return LoadParams.Status;
2129a6a3aa0fSVictor Perevertkin }
2130a6a3aa0fSVictor Perevertkin
2131c2c66affSColin Finck /*
2132c2c66affSColin Finck * NtLoadDriver
2133c2c66affSColin Finck *
2134c2c66affSColin Finck * Loads a device driver.
2135c2c66affSColin Finck *
2136c2c66affSColin Finck * Parameters
2137c2c66affSColin Finck * DriverServiceName
2138c2c66affSColin Finck * Name of the service to load (registry key).
2139c2c66affSColin Finck *
2140c2c66affSColin Finck * Return Value
2141c2c66affSColin Finck * Status
2142c2c66affSColin Finck *
2143c2c66affSColin Finck * Status
2144c2c66affSColin Finck * implemented
2145c2c66affSColin Finck */
2146c2c66affSColin Finck NTSTATUS NTAPI
NtLoadDriver(IN PUNICODE_STRING DriverServiceName)2147c2c66affSColin Finck NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
2148c2c66affSColin Finck {
214944511f08SHermès Bélusca-Maïto UNICODE_STRING CapturedServiceName = { 0, 0, NULL };
2150c2c66affSColin Finck KPROCESSOR_MODE PreviousMode;
2151c2c66affSColin Finck PDRIVER_OBJECT DriverObject;
2152c2c66affSColin Finck NTSTATUS Status;
2153c2c66affSColin Finck
2154c2c66affSColin Finck PAGED_CODE();
2155c2c66affSColin Finck
2156c2c66affSColin Finck PreviousMode = KeGetPreviousMode();
2157c2c66affSColin Finck
215844511f08SHermès Bélusca-Maïto /* Need the appropriate priviliege */
2159c2c66affSColin Finck if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode))
2160c2c66affSColin Finck {
216144511f08SHermès Bélusca-Maïto DPRINT1("No load privilege!\n");
2162c2c66affSColin Finck return STATUS_PRIVILEGE_NOT_HELD;
2163c2c66affSColin Finck }
2164c2c66affSColin Finck
216544511f08SHermès Bélusca-Maïto /* Capture the service name */
216644511f08SHermès Bélusca-Maïto Status = ProbeAndCaptureUnicodeString(&CapturedServiceName,
2167c2c66affSColin Finck PreviousMode,
2168c2c66affSColin Finck DriverServiceName);
2169c2c66affSColin Finck if (!NT_SUCCESS(Status))
2170a6a3aa0fSVictor Perevertkin {
2171c2c66affSColin Finck return Status;
2172a6a3aa0fSVictor Perevertkin }
2173c2c66affSColin Finck
217444511f08SHermès Bélusca-Maïto DPRINT("NtLoadDriver('%wZ')\n", &CapturedServiceName);
2175c2c66affSColin Finck
2176a748350fSHermès Bélusca-Maïto /* We need a service name */
2177a748350fSHermès Bélusca-Maïto if (CapturedServiceName.Length == 0 || CapturedServiceName.Buffer == NULL)
2178a748350fSHermès Bélusca-Maïto {
2179a748350fSHermès Bélusca-Maïto ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
2180a748350fSHermès Bélusca-Maïto return STATUS_INVALID_PARAMETER;
2181a748350fSHermès Bélusca-Maïto }
2182a748350fSHermès Bélusca-Maïto
2183c2c66affSColin Finck /* Load driver and call its entry point */
2184c2c66affSColin Finck DriverObject = NULL;
2185a6a3aa0fSVictor Perevertkin Status = IopDoLoadUnloadDriver(&CapturedServiceName, &DriverObject);
2186c2c66affSColin Finck
218744511f08SHermès Bélusca-Maïto ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
2188c2c66affSColin Finck return Status;
2189c2c66affSColin Finck }
2190c2c66affSColin Finck
2191c2c66affSColin Finck /*
2192c2c66affSColin Finck * NtUnloadDriver
2193c2c66affSColin Finck *
2194c2c66affSColin Finck * Unloads a legacy device driver.
2195c2c66affSColin Finck *
2196c2c66affSColin Finck * Parameters
2197c2c66affSColin Finck * DriverServiceName
2198c2c66affSColin Finck * Name of the service to unload (registry key).
2199c2c66affSColin Finck *
2200c2c66affSColin Finck * Return Value
2201c2c66affSColin Finck * Status
2202c2c66affSColin Finck *
2203c2c66affSColin Finck * Status
2204c2c66affSColin Finck * implemented
2205c2c66affSColin Finck */
2206c2c66affSColin Finck
2207c2c66affSColin Finck NTSTATUS NTAPI
NtUnloadDriver(IN PUNICODE_STRING DriverServiceName)2208c2c66affSColin Finck NtUnloadDriver(IN PUNICODE_STRING DriverServiceName)
2209c2c66affSColin Finck {
2210c2c66affSColin Finck return IopUnloadDriver(DriverServiceName, FALSE);
2211c2c66affSColin Finck }
2212c2c66affSColin Finck
2213c2c66affSColin Finck /* EOF */
2214