ReactOS  0.4.15-dev-2100-g9e32854
driver.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: ntoskrnl/io/iomgr/driver.c
5  * PURPOSE: Driver Object Management
6  * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7  * Filip Navara (navaraf@reactos.org)
8  * Hervé Poussineau (hpoussin@reactos.org)
9  */
10 
11 /* INCLUDES *******************************************************************/
12 
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* GLOBALS ********************************************************************/
18 
20 
24 
28 
30  RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM");
31 static const WCHAR ServicesKeyName[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
32 
34 
35 #define TAG_RTLREGISTRY 'vrqR'
36 
38 extern BOOLEAN PnpSystemInit;
41 
44 
45 /* TYPES *********************************************************************/
46 
47 // Parameters packet for Load/Unload work item's context
48 typedef struct _LOAD_UNLOAD_PARAMS
49 {
57 
62 
63 /* PRIVATE FUNCTIONS **********************************************************/
64 
66 NTAPI
69  PIRP Irp)
70 {
71  Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
72  Irp->IoStatus.Information = 0;
75 }
76 
77 VOID
78 NTAPI
80 {
81  PDRIVER_OBJECT DriverObject = ObjectBody;
82  PIO_CLIENT_EXTENSION DriverExtension, NextDriverExtension;
83  PAGED_CODE();
84 
85  DPRINT1("Deleting driver object '%wZ'\n", &DriverObject->DriverName);
86 
87  /* There must be no device objects remaining at this point */
88  ASSERT(!DriverObject->DeviceObject);
89 
90  /* Get the extension and loop them */
91  DriverExtension = IoGetDrvObjExtension(DriverObject)->ClientDriverExtension;
92  while (DriverExtension)
93  {
94  /* Get the next one */
95  NextDriverExtension = DriverExtension->NextExtension;
97 
98  /* Move on */
99  DriverExtension = NextDriverExtension;
100  }
101 
102  /* Check if the driver image is still loaded */
103  if (DriverObject->DriverSection)
104  {
105  /* Unload it */
106  MmUnloadSystemImage(DriverObject->DriverSection);
107  }
108 
109  /* Check if it has a name */
110  if (DriverObject->DriverName.Buffer)
111  {
112  /* Free it */
113  ExFreePool(DriverObject->DriverName.Buffer);
114  }
115 
116  /* Check if it has a service key name */
117  if (DriverObject->DriverExtension->ServiceKeyName.Buffer)
118  {
119  /* Free it */
120  ExFreePool(DriverObject->DriverExtension->ServiceKeyName.Buffer);
121  }
122 }
123 
124 NTSTATUS
126  _In_ HANDLE ServiceHandle,
127  _Out_ PUNICODE_STRING DriverName,
129 {
130  UNICODE_STRING driverName = {.Buffer = NULL}, serviceName;
133 
134  PAGED_CODE();
135 
136  // 1. Check the "ObjectName" field in the driver's registry key (it has the priority)
137  status = IopGetRegistryValue(ServiceHandle, L"ObjectName", &kvInfo);
138  if (NT_SUCCESS(status))
139  {
140  // we're got the ObjectName. Use it to create the DRIVER_OBJECT
141  if (kvInfo->Type != REG_SZ || kvInfo->DataLength == 0)
142  {
143  ExFreePool(kvInfo);
145  }
146 
147  driverName.Length = kvInfo->DataLength - sizeof(WCHAR),
148  driverName.MaximumLength = kvInfo->DataLength,
149  driverName.Buffer = ExAllocatePoolWithTag(NonPagedPool, driverName.MaximumLength, TAG_IO);
150  if (!driverName.Buffer)
151  {
152  ExFreePool(kvInfo);
154  }
155 
156  RtlMoveMemory(driverName.Buffer,
157  (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
158  driverName.Length);
159  ExFreePool(kvInfo);
160  }
161 
162  // check if we need to get ServiceName as well
163  PKEY_BASIC_INFORMATION basicInfo;
164  if (!NT_SUCCESS(status) || ServiceName != NULL)
165  {
166  ULONG infoLength;
167  status = ZwQueryKey(ServiceHandle, KeyBasicInformation, NULL, 0, &infoLength);
169  {
170  basicInfo = ExAllocatePoolWithTag(PagedPool, infoLength, TAG_IO);
171  if (!basicInfo)
172  {
174  }
175 
176  status = ZwQueryKey(ServiceHandle, KeyBasicInformation, basicInfo, infoLength, &infoLength);
177  if (!NT_SUCCESS(status))
178  {
179  ExFreePoolWithTag(basicInfo, TAG_IO);
180  return status;
181  }
182 
183  serviceName.Length = basicInfo->NameLength;
184  serviceName.MaximumLength = basicInfo->NameLength;
185  serviceName.Buffer = basicInfo->Name;
186  }
187  else
188  {
190  }
191  }
192 
193  // 2. there is no "ObjectName" - construct it ourselves. Depending on a driver type,
194  // it will be either "\Driver<ServiceName>" or "\FileSystem<ServiceName>"
195  if (driverName.Buffer == NULL)
196  {
197  status = IopGetRegistryValue(ServiceHandle, L"Type", &kvInfo);
198  if (!NT_SUCCESS(status) || kvInfo->Type != REG_DWORD)
199  {
200  ExFreePool(kvInfo);
201  ExFreePoolWithTag(basicInfo, TAG_IO); // container for serviceName
203  }
204 
205  UINT32 driverType;
206  RtlMoveMemory(&driverType, (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset), sizeof(UINT32));
207  ExFreePool(kvInfo);
208 
209  driverName.Length = 0;
210  if (driverType == SERVICE_RECOGNIZER_DRIVER || driverType == SERVICE_FILE_SYSTEM_DRIVER)
211  driverName.MaximumLength = sizeof(FILESYSTEM_ROOT_NAME) + serviceName.Length;
212  else
213  driverName.MaximumLength = sizeof(DRIVER_ROOT_NAME) + serviceName.Length;
214  driverName.Buffer = ExAllocatePoolWithTag(NonPagedPool, driverName.MaximumLength, TAG_IO);
215  if (!driverName.Buffer)
216  {
217  ExFreePoolWithTag(basicInfo, TAG_IO); // container for serviceName
219  }
220 
221  if (driverType == SERVICE_RECOGNIZER_DRIVER || driverType == SERVICE_FILE_SYSTEM_DRIVER)
223  else
225 
227  }
228 
229  if (ServiceName)
230  {
232  if (!buf)
233  {
234  ExFreePoolWithTag(basicInfo, TAG_IO); // container for serviceName
235  ExFreePoolWithTag(driverName.Buffer, TAG_IO);
237  }
238  RtlMoveMemory(buf, serviceName.Buffer, serviceName.Length);
239  ServiceName->MaximumLength = serviceName.Length;
240  ServiceName->Length = serviceName.Length;
241  ServiceName->Buffer = buf;
242  }
243  ExFreePoolWithTag(basicInfo, TAG_IO); // container for ServiceName
244 
245  *DriverName = driverName;
246 
247  return STATUS_SUCCESS;
248 }
249 
250 /*
251  * RETURNS
252  * TRUE if String2 contains String1 as a suffix.
253  */
254 BOOLEAN
255 NTAPI
257  IN PCUNICODE_STRING String1,
259 {
260  PWCHAR pc1;
261  PWCHAR pc2;
262  ULONG Length;
263 
264  if (String2->Length < String1->Length)
265  return FALSE;
266 
267  Length = String1->Length / 2;
268  pc1 = String1->Buffer;
269  pc2 = &String2->Buffer[String2->Length / sizeof(WCHAR) - Length];
270 
271  if (pc1 && pc2)
272  {
273  while (Length--)
274  {
275  if( *pc1++ != *pc2++ )
276  return FALSE;
277  }
278  return TRUE;
279  }
280  return FALSE;
281 }
282 
283 /*
284  * IopDisplayLoadingMessage
285  *
286  * Display 'Loading XXX...' message.
287  */
288 VOID
289 FASTCALL
291 {
292  CHAR TextBuffer[256];
293  UNICODE_STRING DotSys = RTL_CONSTANT_STRING(L".SYS");
294 
295  if (ExpInTextModeSetup) return;
296  if (!KeLoaderBlock) return;
298  snprintf(TextBuffer, sizeof(TextBuffer),
299  "%s%sSystem32\\Drivers\\%wZ%s\r\n",
302  ServiceName,
303  IopSuffixUnicodeString(&DotSys, ServiceName) ? "" : ".SYS");
305 }
306 
307 /*
308  * IopNormalizeImagePath
309  *
310  * Normalize an image path to contain complete path.
311  *
312  * Parameters
313  * ImagePath
314  * The input path and on exit the result path. ImagePath.Buffer
315  * must be allocated by ExAllocatePool on input. Caller is responsible
316  * for freeing the buffer when it's no longer needed.
317  *
318  * ServiceName
319  * Name of the service that ImagePath belongs to.
320  *
321  * Return Value
322  * Status
323  *
324  * Remarks
325  * The input image path isn't freed on error.
326  */
327 NTSTATUS
328 FASTCALL
330  _Inout_ _When_(return>=0, _At_(ImagePath->Buffer, _Post_notnull_ __drv_allocatesMem(Mem)))
331  PUNICODE_STRING ImagePath,
333 {
334  UNICODE_STRING SystemRootString = RTL_CONSTANT_STRING(L"\\SystemRoot\\");
335  UNICODE_STRING DriversPathString = RTL_CONSTANT_STRING(L"\\SystemRoot\\System32\\drivers\\");
336  UNICODE_STRING DotSysString = RTL_CONSTANT_STRING(L".sys");
337  UNICODE_STRING InputImagePath;
338 
339  DPRINT("Normalizing image path '%wZ' for service '%wZ'\n", ImagePath, ServiceName);
340 
341  InputImagePath = *ImagePath;
342  if (InputImagePath.Length == 0)
343  {
344  ImagePath->Length = 0;
345  ImagePath->MaximumLength = DriversPathString.Length +
346  ServiceName->Length +
347  DotSysString.Length +
348  sizeof(UNICODE_NULL);
349  ImagePath->Buffer = ExAllocatePoolWithTag(NonPagedPool,
350  ImagePath->MaximumLength,
351  TAG_IO);
352  if (ImagePath->Buffer == NULL)
353  return STATUS_NO_MEMORY;
354 
355  RtlCopyUnicodeString(ImagePath, &DriversPathString);
357  RtlAppendUnicodeStringToString(ImagePath, &DotSysString);
358  }
359  else if (InputImagePath.Buffer[0] != L'\\')
360  {
361  ImagePath->Length = 0;
362  ImagePath->MaximumLength = SystemRootString.Length +
363  InputImagePath.Length +
364  sizeof(UNICODE_NULL);
365  ImagePath->Buffer = ExAllocatePoolWithTag(NonPagedPool,
366  ImagePath->MaximumLength,
367  TAG_IO);
368  if (ImagePath->Buffer == NULL)
369  return STATUS_NO_MEMORY;
370 
371  RtlCopyUnicodeString(ImagePath, &SystemRootString);
372  RtlAppendUnicodeStringToString(ImagePath, &InputImagePath);
373 
374  /* Free caller's string */
375  ExFreePoolWithTag(InputImagePath.Buffer, TAG_RTLREGISTRY);
376  }
377 
378  DPRINT("Normalized image path is '%wZ' for service '%wZ'\n", ImagePath, ServiceName);
379 
380  return STATUS_SUCCESS;
381 }
382 
402 NTSTATUS
404  _In_ PLDR_DATA_TABLE_ENTRY ModuleObject,
405  _In_ HANDLE ServiceHandle,
406  _Out_ PDRIVER_OBJECT *OutDriverObject,
407  _Out_ NTSTATUS *DriverEntryStatus)
408 {
411 
412  PAGED_CODE();
413 
414  Status = IopGetDriverNames(ServiceHandle, &DriverName, &ServiceName);
415  if (!NT_SUCCESS(Status))
416  {
417  MmUnloadSystemImage(ModuleObject);
418  return Status;
419  }
420 
421  DPRINT("Driver name: '%wZ'\n", &DriverName);
422 
423  // obtain the registry path for the DriverInit routine
424  PKEY_NAME_INFORMATION nameInfo;
425  ULONG infoLength;
426  Status = ZwQueryKey(ServiceHandle, KeyNameInformation, NULL, 0, &infoLength);
428  {
429  nameInfo = ExAllocatePoolWithTag(NonPagedPool, infoLength, TAG_IO);
430  if (nameInfo)
431  {
432  Status = ZwQueryKey(ServiceHandle,
434  nameInfo,
435  infoLength,
436  &infoLength);
437  if (NT_SUCCESS(Status))
438  {
439  RegistryPath.Length = nameInfo->NameLength;
440  RegistryPath.MaximumLength = nameInfo->NameLength;
441  RegistryPath.Buffer = nameInfo->Name;
442  }
443  else
444  {
445  ExFreePoolWithTag(nameInfo, TAG_IO);
446  }
447  }
448  else
449  {
451  }
452  }
453  else
454  {
456  }
457 
458  if (!NT_SUCCESS(Status))
459  {
461  RtlFreeUnicodeString(&DriverName);
462  MmUnloadSystemImage(ModuleObject);
463  return Status;
464  }
465 
466  // create the driver object
467  UINT32 ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(EXTENDED_DRIVER_EXTENSION);
468  OBJECT_ATTRIBUTES objAttrs;
469  PDRIVER_OBJECT driverObject;
470  InitializeObjectAttributes(&objAttrs,
471  &DriverName,
473  NULL,
474  NULL);
475 
478  &objAttrs,
479  KernelMode,
480  NULL,
481  ObjectSize,
482  0,
483  0,
484  (PVOID*)&driverObject);
485  if (!NT_SUCCESS(Status))
486  {
487  ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath
489  RtlFreeUnicodeString(&DriverName);
490  MmUnloadSystemImage(ModuleObject);
491  DPRINT1("Error while creating driver object \"%wZ\" status %x\n", &DriverName, Status);
492  return Status;
493  }
494 
495  DPRINT("Created driver object 0x%p for \"%wZ\"\n", driverObject, &DriverName);
496 
497  RtlZeroMemory(driverObject, ObjectSize);
498  driverObject->Type = IO_TYPE_DRIVER;
499  driverObject->Size = sizeof(DRIVER_OBJECT);
500  driverObject->Flags = DRVO_LEGACY_DRIVER; // TODO: check the WDM_DRIVER flag on the module
501  driverObject->DriverSection = ModuleObject;
502  driverObject->DriverStart = ModuleObject->DllBase;
503  driverObject->DriverSize = ModuleObject->SizeOfImage;
504  driverObject->DriverInit = ModuleObject->EntryPoint;
505  driverObject->HardwareDatabase = &IopHardwareDatabaseKey;
506  driverObject->DriverExtension = (PDRIVER_EXTENSION)(driverObject + 1);
507  driverObject->DriverExtension->DriverObject = driverObject;
508 
509  /* Loop all Major Functions */
510  for (INT i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
511  {
512  /* Invalidate each function */
513  driverObject->MajorFunction[i] = IopInvalidDeviceRequest;
514  }
515 
516  /* Add the Object and get its handle */
517  HANDLE hDriver;
518  Status = ObInsertObject(driverObject, NULL, FILE_READ_DATA, 0, NULL, &hDriver);
519  if (!NT_SUCCESS(Status))
520  {
521  ExFreePoolWithTag(nameInfo, TAG_IO);
523  RtlFreeUnicodeString(&DriverName);
524  return Status;
525  }
526 
527  /* Now reference it */
529  0,
531  KernelMode,
532  (PVOID*)&driverObject,
533  NULL);
534 
535  /* Close the extra handle */
536  ZwClose(hDriver);
537 
538  if (!NT_SUCCESS(Status))
539  {
540  ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath
542  RtlFreeUnicodeString(&DriverName);
543  return Status;
544  }
545 
546  /* Set up the service key name buffer */
547  UNICODE_STRING serviceKeyName;
548  serviceKeyName.Length = 0;
549  // put a NULL character at the end for Windows compatibility
550  serviceKeyName.MaximumLength = ServiceName.MaximumLength + sizeof(UNICODE_NULL);
551  serviceKeyName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
552  serviceKeyName.MaximumLength,
553  TAG_IO);
554  if (!serviceKeyName.Buffer)
555  {
556  ObMakeTemporaryObject(driverObject);
557  ObDereferenceObject(driverObject);
558  ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath
560  RtlFreeUnicodeString(&DriverName);
562  }
563 
564  /* Copy the name and set it in the driver extension */
565  RtlCopyUnicodeString(&serviceKeyName, &ServiceName);
567  driverObject->DriverExtension->ServiceKeyName = serviceKeyName;
568 
569  /* Make a copy of the driver name to store in the driver object */
570  UNICODE_STRING driverNamePaged;
571  driverNamePaged.Length = 0;
572  // put a NULL character at the end for Windows compatibility
573  driverNamePaged.MaximumLength = DriverName.MaximumLength + sizeof(UNICODE_NULL);
574  driverNamePaged.Buffer = ExAllocatePoolWithTag(PagedPool,
575  driverNamePaged.MaximumLength,
576  TAG_IO);
577  if (!driverNamePaged.Buffer)
578  {
579  ObMakeTemporaryObject(driverObject);
580  ObDereferenceObject(driverObject);
581  ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath
582  RtlFreeUnicodeString(&DriverName);
584  }
585 
586  RtlCopyUnicodeString(&driverNamePaged, &DriverName);
587  driverObject->DriverName = driverNamePaged;
588 
589  /* Finally, call its init function */
590  Status = driverObject->DriverInit(driverObject, &RegistryPath);
591  *DriverEntryStatus = Status;
592  if (!NT_SUCCESS(Status))
593  {
594  DPRINT1("'%wZ' initialization failed, status (0x%08lx)\n", &DriverName, Status);
595  // return a special status value in case of failure
597  }
598 
599  /* HACK: We're going to say if we don't have any DOs from DriverEntry, then we're not legacy.
600  * Other parts of the I/O manager depend on this behavior */
601  if (!driverObject->DeviceObject)
602  {
603  driverObject->Flags &= ~DRVO_LEGACY_DRIVER;
604  }
605 
606  // Windows does this fixup - keep it for compatibility
607  for (INT i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
608  {
609  /*
610  * Make sure the driver didn't set any dispatch entry point to NULL!
611  * Doing so is illegal; drivers shouldn't touch entry points they
612  * do not implement.
613  */
614 
615  /* Check if it did so anyway */
616  if (!driverObject->MajorFunction[i])
617  {
618  /* Print a warning in the debug log */
619  DPRINT1("Driver <%wZ> set DriverObject->MajorFunction[%lu] to NULL!\n",
620  &driverObject->DriverName, i);
621 
622  /* Fix it up */
623  driverObject->MajorFunction[i] = IopInvalidDeviceRequest;
624  }
625  }
626 
627  // TODO: for legacy drivers, unload the driver if it didn't create any DO
628 
629  ExFreePoolWithTag(nameInfo, TAG_IO); // container for RegistryPath
630  RtlFreeUnicodeString(&DriverName);
631 
632  if (!NT_SUCCESS(Status))
633  {
634  // if the driver entry has been failed, clear the object
635  ObMakeTemporaryObject(driverObject);
636  ObDereferenceObject(driverObject);
637  return Status;
638  }
639 
640  *OutDriverObject = driverObject;
641 
642  MmFreeDriverInitialization((PLDR_DATA_TABLE_ENTRY)driverObject->DriverSection);
643 
644  /* Set the driver as initialized */
645  IopReadyDeviceObjects(driverObject);
646 
648 
649  return STATUS_SUCCESS;
650 }
651 
652 NTSTATUS
653 NTAPI
655  IN PUNICODE_STRING ImageFileDirectory,
656  IN PUNICODE_STRING NamePrefix OPTIONAL,
657  OUT PCHAR *MissingApi,
658  OUT PWCHAR *MissingDriver,
659  OUT PLOAD_IMPORTS *LoadImports);
660 
661 //
662 // Used for images already loaded (boot drivers)
663 //
664 CODE_SEG("INIT")
665 NTSTATUS
666 NTAPI
669  PLDR_DATA_TABLE_ENTRY *ModuleObject)
670 {
672  UNICODE_STRING BaseName, BaseDirectory;
673  PLOAD_IMPORTS LoadedImports = (PVOID)-2;
674  PCHAR MissingApiName, Buffer;
675  PWCHAR MissingDriverName;
676  PVOID DriverBase = LdrEntry->DllBase;
677 
678  /* Allocate a buffer we'll use for names */
681  TAG_LDR_WSTR);
682  if (!Buffer)
683  {
684  /* Fail */
686  }
687 
688  /* Check for a separator */
689  if (FileName->Buffer[0] == OBJ_NAME_PATH_SEPARATOR)
690  {
691  PWCHAR p;
692  ULONG BaseLength;
693 
694  /* Loop the path until we get to the base name */
695  p = &FileName->Buffer[FileName->Length / sizeof(WCHAR)];
696  while (*(p - 1) != OBJ_NAME_PATH_SEPARATOR) p--;
697 
698  /* Get the length */
699  BaseLength = (ULONG)(&FileName->Buffer[FileName->Length / sizeof(WCHAR)] - p);
700  BaseLength *= sizeof(WCHAR);
701 
702  /* Setup the string */
703  BaseName.Length = (USHORT)BaseLength;
704  BaseName.Buffer = p;
705  }
706  else
707  {
708  /* Otherwise, we already have a base name */
709  BaseName.Length = FileName->Length;
710  BaseName.Buffer = FileName->Buffer;
711  }
712 
713  /* Setup the maximum length */
714  BaseName.MaximumLength = BaseName.Length;
715 
716  /* Now compute the base directory */
717  BaseDirectory = *FileName;
718  BaseDirectory.Length -= BaseName.Length;
719  BaseDirectory.MaximumLength = BaseDirectory.Length;
720 
721  /* Resolve imports */
722  MissingApiName = Buffer;
723  Status = MiResolveImageReferences(DriverBase,
724  &BaseDirectory,
725  NULL,
726  &MissingApiName,
727  &MissingDriverName,
728  &LoadedImports);
729 
730  /* Free the temporary buffer */
732 
733  /* Check the result of the imports resolution */
734  if (!NT_SUCCESS(Status)) return Status;
735 
736  /* Return */
737  *ModuleObject = LdrEntry;
738  return STATUS_SUCCESS;
739 }
740 
743 
744 /*
745  * IopInitializeBuiltinDriver
746  *
747  * Initialize a driver that is already loaded in memory.
748  */
749 CODE_SEG("INIT")
750 BOOLEAN
752 {
755  PWCHAR Buffer, FileNameWithoutPath;
756  PWSTR FileExtension;
757  PUNICODE_STRING ModuleName = &BootLdrEntry->BaseDllName;
758  PLDR_DATA_TABLE_ENTRY LdrEntry;
759  PLIST_ENTRY NextEntry;
762 
763  /*
764  * Display 'Loading XXX...' message
765  */
768 
770  ModuleName->Length + sizeof(UNICODE_NULL),
771  TAG_IO);
772  if (Buffer == NULL)
773  {
774  return FALSE;
775  }
776 
778  Buffer[ModuleName->Length / sizeof(WCHAR)] = UNICODE_NULL;
779 
780  /*
781  * Generate filename without path (not needed by freeldr)
782  */
783  FileNameWithoutPath = wcsrchr(Buffer, L'\\');
784  if (FileNameWithoutPath == NULL)
785  {
786  FileNameWithoutPath = Buffer;
787  }
788  else
789  {
790  FileNameWithoutPath++;
791  }
792 
793  /*
794  * Strip the file extension from ServiceName
795  */
796  Success = RtlCreateUnicodeString(&ServiceName, FileNameWithoutPath);
798  if (!Success)
799  {
800  return FALSE;
801  }
802 
803  FileExtension = wcsrchr(ServiceName.Buffer, L'.');
804  if (FileExtension != NULL)
805  {
806  ServiceName.Length -= (USHORT)wcslen(FileExtension) * sizeof(WCHAR);
807  FileExtension[0] = UNICODE_NULL;
808  }
809 
811 
812  // Make the registry path for the driver
813  RegistryPath.Length = 0;
814  RegistryPath.MaximumLength = sizeof(ServicesKeyName) + ServiceName.Length;
816  if (RegistryPath.Buffer == NULL)
817  {
818  return FALSE;
819  }
823 
824  HANDLE serviceHandle;
825  Status = IopOpenRegistryKeyEx(&serviceHandle, NULL, &RegistryPath, KEY_READ);
827  if (!NT_SUCCESS(Status))
828  {
829  return FALSE;
830  }
831 
832  /* Lookup the new Ldr entry in PsLoadedModuleList */
833  NextEntry = PsLoadedModuleList.Flink;
834  while (NextEntry != &PsLoadedModuleList)
835  {
836  LdrEntry = CONTAINING_RECORD(NextEntry,
838  InLoadOrderLinks);
840  {
841  break;
842  }
843 
844  NextEntry = NextEntry->Flink;
845  }
846  ASSERT(NextEntry != &PsLoadedModuleList);
847 
848  /*
849  * Initialize the driver
850  */
851  NTSTATUS driverEntryStatus;
853  serviceHandle,
854  &DriverObject,
855  &driverEntryStatus);
856 
857  if (!NT_SUCCESS(Status))
858  {
859  DPRINT1("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status);
860  return FALSE;
861  }
862 
863  // The driver has been loaded, now check if where are any PDOs
864  // for that driver, and queue AddDevice call for them.
865  // The check is possible because HKLM/SYSTEM/CCS/Services/<ServiceName>/Enum directory
866  // is populated upon a new device arrival based on a (critical) device database
867 
868  // Legacy drivers may add devices inside DriverEntry.
869  // We're lazy and always assume that they are doing so
870  BOOLEAN deviceAdded = (_Bool)(DriverObject->Flags & DRVO_LEGACY_DRIVER);
871 
872  HANDLE enumServiceHandle;
873  UNICODE_STRING enumName = RTL_CONSTANT_STRING(L"Enum");
874 
875  Status = IopOpenRegistryKeyEx(&enumServiceHandle, serviceHandle, &enumName, KEY_READ);
876  ZwClose(serviceHandle);
877 
878  if (NT_SUCCESS(Status))
879  {
880  UINT32 instanceCount = 0;
882  Status = IopGetRegistryValue(enumServiceHandle, L"Count", &kvInfo);
883  if (!NT_SUCCESS(Status))
884  {
885  goto Cleanup;
886  }
887  if (kvInfo->Type != REG_DWORD)
888  {
889  ExFreePool(kvInfo);
890  goto Cleanup;
891  }
892 
893  RtlMoveMemory(&instanceCount,
894  (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
895  sizeof(UINT32));
896  ExFreePool(kvInfo);
897 
898  DPRINT("Processing %u instances for %wZ module\n", instanceCount, ModuleName);
899 
900  for (UINT32 i = 0; i < instanceCount; i++)
901  {
902  WCHAR num[11];
903  UNICODE_STRING instancePath;
904  RtlStringCchPrintfW(num, sizeof(num), L"%u", i);
905 
906  Status = IopGetRegistryValue(enumServiceHandle, num, &kvInfo);
907  if (!NT_SUCCESS(Status))
908  {
909  continue;
910  }
911  if (kvInfo->Type != REG_SZ || kvInfo->DataLength == 0)
912  {
913  ExFreePool(kvInfo);
914  continue;
915  }
916 
917  instancePath.Length = kvInfo->DataLength - sizeof(WCHAR),
918  instancePath.MaximumLength = kvInfo->DataLength,
920  instancePath.MaximumLength,
921  TAG_IO);
922  if (instancePath.Buffer)
923  {
924  RtlMoveMemory(instancePath.Buffer,
925  (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
926  instancePath.Length);
927 
930  ObDereferenceObject(pdo);
931  deviceAdded = TRUE;
932  }
933 
934  ExFreePool(kvInfo);
935  }
936 
937  ZwClose(enumServiceHandle);
938  }
939 Cleanup:
940  /* Remove extra reference from IopInitializeDriverModule */
942 
943  return deviceAdded;
944 }
945 
946 /*
947  * IopInitializeBootDrivers
948  *
949  * Initialize boot drivers and free memory for boot files.
950  *
951  * Parameters
952  * None
953  *
954  * Return Value
955  * None
956  */
957 CODE_SEG("INIT")
958 VOID
959 FASTCALL
961 {
962  PLIST_ENTRY ListHead, NextEntry, NextEntry2;
963  PLDR_DATA_TABLE_ENTRY LdrEntry;
965  UNICODE_STRING DriverName;
966  ULONG i, Index;
967  PDRIVER_INFORMATION DriverInfo, DriverInfoTag;
969  PBOOT_DRIVER_LIST_ENTRY BootEntry;
970  DPRINT("IopInitializeBootDrivers()\n");
971 
972  /* Create the RAW FS built-in driver */
973  RtlInitUnicodeString(&DriverName, L"\\FileSystem\\RAW");
974 
975  Status = IoCreateDriver(&DriverName, RawFsDriverEntry);
976  if (!NT_SUCCESS(Status))
977  {
978  /* Fail */
979  return;
980  }
981 
982  /* Get highest group order index */
984  if (IopGroupIndex == 0xFFFF) ASSERT(FALSE);
985 
986  /* Allocate the group table */
988  IopGroupIndex * sizeof(LIST_ENTRY),
989  TAG_IO);
990  if (IopGroupTable == NULL) ASSERT(FALSE);
991 
992  /* Initialize the group table lists */
993  for (i = 0; i < IopGroupIndex; i++) InitializeListHead(&IopGroupTable[i]);
994 
995  /* Loop the boot modules */
996  ListHead = &KeLoaderBlock->LoadOrderListHead;
997  NextEntry = ListHead->Flink;
998  while (ListHead != NextEntry)
999  {
1000  /* Get the entry */
1001  LdrEntry = CONTAINING_RECORD(NextEntry,
1003  InLoadOrderLinks);
1004 
1005  /* Check if the DLL needs to be initialized */
1006  if (LdrEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL)
1007  {
1008  /* Call its entrypoint */
1009  MmCallDllInitialize(LdrEntry, NULL);
1010  }
1011 
1012  /* Go to the next driver */
1013  NextEntry = NextEntry->Flink;
1014  }
1015 
1016  /* Loop the boot drivers */
1017  ListHead = &KeLoaderBlock->BootDriverListHead;
1018  NextEntry = ListHead->Flink;
1019  while (ListHead != NextEntry)
1020  {
1021  /* Get the entry */
1022  BootEntry = CONTAINING_RECORD(NextEntry,
1024  Link);
1025 
1026  /* Get the driver loader entry */
1027  LdrEntry = BootEntry->LdrEntry;
1028 
1029  /* Allocate our internal accounting structure */
1031  sizeof(DRIVER_INFORMATION),
1032  TAG_IO);
1033  if (DriverInfo)
1034  {
1035  /* Zero it and initialize it */
1038  DriverInfo->DataTableEntry = BootEntry;
1039 
1040  /* Open the registry key */
1042  NULL,
1043  &BootEntry->RegistryPath,
1044  KEY_READ);
1045  DPRINT("IopOpenRegistryKeyEx(%wZ) returned 0x%08lx\n", &BootEntry->RegistryPath, Status);
1046 #if 0
1047  if (NT_SUCCESS(Status))
1048 #else // Hack still needed...
1049  if ((NT_SUCCESS(Status)) || /* ReactOS HACK for SETUPLDR */
1050  ((KeLoaderBlock->SetupLdrBlock) && ((KeyHandle = (PVOID)1)))) // yes, it's an assignment!
1051 #endif
1052  {
1053  /* Save the handle */
1055 
1056  /* Get the group oder index */
1058 
1059  /* Get the tag position */
1061 
1062  /* Insert it into the list, at the right place */
1064  NextEntry2 = IopGroupTable[Index].Flink;
1065  while (NextEntry2 != &IopGroupTable[Index])
1066  {
1067  /* Get the driver info */
1068  DriverInfoTag = CONTAINING_RECORD(NextEntry2,
1070  Link);
1071 
1072  /* Check if we found the right tag position */
1073  if (DriverInfoTag->TagPosition > DriverInfo->TagPosition)
1074  {
1075  /* We're done */
1076  break;
1077  }
1078 
1079  /* Next entry */
1080  NextEntry2 = NextEntry2->Flink;
1081  }
1082 
1083  /* Insert us right before the next entry */
1084  NextEntry2 = NextEntry2->Blink;
1085  InsertHeadList(NextEntry2, &DriverInfo->Link);
1086  }
1087  }
1088 
1089  /* Go to the next driver */
1090  NextEntry = NextEntry->Flink;
1091  }
1092 
1093  /* Loop each group index */
1094  for (i = 0; i < IopGroupIndex; i++)
1095  {
1096  /* Loop each group table */
1097  NextEntry = IopGroupTable[i].Flink;
1098  while (NextEntry != &IopGroupTable[i])
1099  {
1100  /* Get the entry */
1101  DriverInfo = CONTAINING_RECORD(NextEntry,
1103  Link);
1104 
1105  /* Get the driver loader entry */
1106  LdrEntry = DriverInfo->DataTableEntry->LdrEntry;
1107 
1108  /* Initialize it */
1109  if (IopInitializeBuiltinDriver(LdrEntry))
1110  {
1111  // it does not make sense to enumerate the tree if there are no new devices added
1114  NULL,
1115  NULL);
1116  }
1117 
1118  /* Next entry */
1119  NextEntry = NextEntry->Flink;
1120  }
1121  }
1122 
1123  /* HAL Root Bus is being initialized before loading the boot drivers so this may cause issues
1124  * when some devices are not being initialized with their drivers. This flag is used to delay
1125  * all actions with devices (except PnP root device) until boot drivers are loaded.
1126  * See PiQueueDeviceAction function
1127  */
1129 
1130  DbgPrint("BOOT DRIVERS LOADED\n");
1131 
1134  NULL,
1135  NULL);
1136 }
1137 
1138 CODE_SEG("INIT")
1139 VOID
1140 FASTCALL
1142 {
1143  PUNICODE_STRING *DriverList, *SavedList;
1144 
1146 
1147  /* No system drivers on the boot cd */
1148  if (KeLoaderBlock->SetupLdrBlock) return; // ExpInTextModeSetup
1149 
1150  /* Get the driver list */
1151  SavedList = DriverList = CmGetSystemDriverList();
1152  ASSERT(DriverList);
1153 
1154  /* Loop it */
1155  while (*DriverList)
1156  {
1157  /* Load the driver */
1158  ZwLoadDriver(*DriverList);
1159 
1160  /* Free the entry */
1161  RtlFreeUnicodeString(*DriverList);
1162  ExFreePool(*DriverList);
1163 
1164  /* Next entry */
1166  DriverList++;
1167  }
1168 
1169  /* Free the list */
1170  ExFreePool(SavedList);
1171 
1174  NULL,
1175  NULL);
1176 }
1177 
1178 /*
1179  * IopUnloadDriver
1180  *
1181  * Unloads a device driver.
1182  *
1183  * Parameters
1184  * DriverServiceName
1185  * Name of the service to unload (registry key).
1186  *
1187  * UnloadPnpDrivers
1188  * Whether to unload Plug & Plug or only legacy drivers. If this
1189  * parameter is set to FALSE, the routine will unload only legacy
1190  * drivers.
1191  *
1192  * Return Value
1193  * Status
1194  *
1195  * To do
1196  * Guard the whole function by SEH.
1197  */
1198 
1200 IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
1201 {
1204  UNICODE_STRING ImagePath;
1209  PEXTENDED_DEVOBJ_EXTENSION DeviceExtension;
1210  NTSTATUS Status;
1211  USHORT LastBackslash;
1212  BOOLEAN SafeToUnload = TRUE;
1214  UNICODE_STRING CapturedServiceName;
1215 
1216  PAGED_CODE();
1217 
1219 
1220  /* Need the appropriate priviliege */
1222  {
1223  DPRINT1("No unload privilege!\n");
1225  }
1226 
1227  /* Capture the service name */
1228  Status = ProbeAndCaptureUnicodeString(&CapturedServiceName,
1229  PreviousMode,
1230  DriverServiceName);
1231  if (!NT_SUCCESS(Status))
1232  {
1233  return Status;
1234  }
1235 
1236  DPRINT("IopUnloadDriver('%wZ', %u)\n", &CapturedServiceName, UnloadPnpDrivers);
1237 
1238  /* We need a service name */
1239  if (CapturedServiceName.Length == 0 || CapturedServiceName.Buffer == NULL)
1240  {
1241  ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1242  return STATUS_INVALID_PARAMETER;
1243  }
1244 
1245  /*
1246  * Get the service name from the registry key name
1247  */
1249  &CapturedServiceName,
1250  &Backslash,
1251  &LastBackslash);
1252  if (NT_SUCCESS(Status))
1253  {
1254  NT_ASSERT(CapturedServiceName.Length >= LastBackslash + sizeof(WCHAR));
1255  ServiceName.Buffer = &CapturedServiceName.Buffer[LastBackslash / sizeof(WCHAR) + 1];
1256  ServiceName.Length = CapturedServiceName.Length - LastBackslash - sizeof(WCHAR);
1257  ServiceName.MaximumLength = CapturedServiceName.MaximumLength - LastBackslash - sizeof(WCHAR);
1258  }
1259  else
1260  {
1261  ServiceName = CapturedServiceName;
1262  }
1263 
1264  /*
1265  * Construct the driver object name
1266  */
1267  Status = RtlUShortAdd(sizeof(DRIVER_ROOT_NAME),
1268  ServiceName.Length,
1269  &ObjectName.MaximumLength);
1270  if (!NT_SUCCESS(Status))
1271  {
1272  ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1273  return Status;
1274  }
1275  ObjectName.Length = 0;
1277  ObjectName.MaximumLength,
1278  TAG_IO);
1279  if (!ObjectName.Buffer)
1280  {
1281  ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1283  }
1286 
1287  /*
1288  * Find the driver object
1289  */
1291  0,
1292  0,
1293  0,
1295  KernelMode,
1296  0,
1297  (PVOID*)&DriverObject);
1298 
1299  if (!NT_SUCCESS(Status))
1300  {
1301  DPRINT1("Can't locate driver object for %wZ\n", &ObjectName);
1303  ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1304  return Status;
1305  }
1306 
1307  /* Free the buffer for driver object name */
1309 
1310  /* Check that driver is not already unloading */
1311  if (DriverObject->Flags & DRVO_UNLOAD_INVOKED)
1312  {
1313  DPRINT1("Driver deletion pending\n");
1315  ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1316  return STATUS_DELETE_PENDING;
1317  }
1318 
1319  /*
1320  * Get path of service...
1321  */
1323 
1324  RtlInitUnicodeString(&ImagePath, NULL);
1325 
1326  QueryTable[0].Name = L"ImagePath";
1328  QueryTable[0].EntryContext = &ImagePath;
1329 
1331  CapturedServiceName.Buffer,
1332  QueryTable,
1333  NULL,
1334  NULL);
1335 
1336  /* We no longer need service name */
1337  ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
1338 
1339  if (!NT_SUCCESS(Status))
1340  {
1341  DPRINT1("RtlQueryRegistryValues() failed (Status %x)\n", Status);
1343  return Status;
1344  }
1345 
1346  /*
1347  * Normalize the image path for all later processing.
1348  */
1349  Status = IopNormalizeImagePath(&ImagePath, &ServiceName);
1350 
1351  if (!NT_SUCCESS(Status))
1352  {
1353  DPRINT1("IopNormalizeImagePath() failed (Status %x)\n", Status);
1355  return Status;
1356  }
1357 
1358  /* Free the service path */
1359  ExFreePool(ImagePath.Buffer);
1360 
1361  /*
1362  * Unload the module and release the references to the device object
1363  */
1364 
1365  /* Call the load/unload routine, depending on current process */
1366  if (DriverObject->DriverUnload && DriverObject->DriverSection &&
1367  (UnloadPnpDrivers || (DriverObject->Flags & DRVO_LEGACY_DRIVER)))
1368  {
1369  /* Loop through each device object of the driver
1370  and set DOE_UNLOAD_PENDING flag */
1371  DeviceObject = DriverObject->DeviceObject;
1372  while (DeviceObject)
1373  {
1374  /* Set the unload pending flag for the device */
1375  DeviceExtension = IoGetDevObjExtension(DeviceObject);
1376  DeviceExtension->ExtensionFlags |= DOE_UNLOAD_PENDING;
1377 
1378  /* Make sure there are no attached devices or no reference counts */
1379  if ((DeviceObject->ReferenceCount) || (DeviceObject->AttachedDevice))
1380  {
1381  /* Not safe to unload */
1382  DPRINT1("Drivers device object is referenced or has attached devices\n");
1383 
1384  SafeToUnload = FALSE;
1385  }
1386 
1387  DeviceObject = DeviceObject->NextDevice;
1388  }
1389 
1390  /* If not safe to unload, then return success */
1391  if (!SafeToUnload)
1392  {
1394  return STATUS_SUCCESS;
1395  }
1396 
1397  DPRINT1("Unloading driver '%wZ' (manual)\n", &DriverObject->DriverName);
1398 
1399  /* Set the unload invoked flag and call the unload routine */
1403 
1404  /* Mark the driver object temporary, so it could be deleted later */
1406 
1407  /* Dereference it 2 times */
1410 
1411  return Status;
1412  }
1413  else
1414  {
1415  DPRINT1("No DriverUnload function! '%wZ' will not be unloaded!\n", &DriverObject->DriverName);
1416 
1417  /* Dereference one time (refd inside this function) */
1419 
1420  /* Return unloading failure */
1422  }
1423 }
1424 
1425 VOID
1426 NTAPI
1428 {
1429  PDRIVER_REINIT_ITEM ReinitItem;
1431 
1432  /* Get the first entry and start looping */
1435  while (Entry)
1436  {
1437  /* Get the item */
1438  ReinitItem = CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry);
1439 
1440  /* Increment reinitialization counter */
1441  ReinitItem->DriverObject->DriverExtension->Count++;
1442 
1443  /* Remove the device object flag */
1444  ReinitItem->DriverObject->Flags &= ~DRVO_REINIT_REGISTERED;
1445 
1446  /* Call the routine */
1447  ReinitItem->ReinitRoutine(ReinitItem->DriverObject,
1448  ReinitItem->Context,
1449  ReinitItem->DriverObject->
1450  DriverExtension->Count);
1451 
1452  /* Free the entry */
1453  ExFreePool(Entry);
1454 
1455  /* Move to the next one */
1458  }
1459 }
1460 
1461 VOID
1462 NTAPI
1464 {
1465  PDRIVER_REINIT_ITEM ReinitItem;
1467 
1468  /* Get the first entry and start looping */
1471  while (Entry)
1472  {
1473  /* Get the item */
1474  ReinitItem = CONTAINING_RECORD(Entry, DRIVER_REINIT_ITEM, ItemEntry);
1475 
1476  /* Increment reinitialization counter */
1477  ReinitItem->DriverObject->DriverExtension->Count++;
1478 
1479  /* Remove the device object flag */
1481 
1482  /* Call the routine */
1483  ReinitItem->ReinitRoutine(ReinitItem->DriverObject,
1484  ReinitItem->Context,
1485  ReinitItem->DriverObject->
1486  DriverExtension->Count);
1487 
1488  /* Free the entry */
1489  ExFreePool(Entry);
1490 
1491  /* Move to the next one */
1494  }
1495 
1496  /* Wait for all device actions being finished*/
1498 }
1499 
1500 /* PUBLIC FUNCTIONS ***********************************************************/
1501 
1502 /*
1503  * @implemented
1504  */
1505 NTSTATUS
1506 NTAPI
1508  _In_opt_ PUNICODE_STRING DriverName,
1509  _In_ PDRIVER_INITIALIZE InitializationFunction)
1510 {
1511  WCHAR NameBuffer[100];
1512  USHORT NameLength;
1513  UNICODE_STRING LocalDriverName;
1514  NTSTATUS Status;
1516  ULONG ObjectSize;
1518  UNICODE_STRING ServiceKeyName;
1519  HANDLE hDriver;
1520  ULONG i, RetryCount = 0;
1521 
1522 try_again:
1523  /* First, create a unique name for the driver if we don't have one */
1524  if (!DriverName)
1525  {
1526  /* Create a random name and set up the string */
1527  NameLength = (USHORT)swprintf(NameBuffer,
1528  DRIVER_ROOT_NAME L"%08u",
1530  LocalDriverName.Length = NameLength * sizeof(WCHAR);
1531  LocalDriverName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL);
1532  LocalDriverName.Buffer = NameBuffer;
1533  }
1534  else
1535  {
1536  /* So we can avoid another code path, use a local var */
1537  LocalDriverName = *DriverName;
1538  }
1539 
1540  /* Initialize the Attributes */
1541  ObjectSize = sizeof(DRIVER_OBJECT) + sizeof(EXTENDED_DRIVER_EXTENSION);
1543  &LocalDriverName,
1545  NULL,
1546  NULL);
1547 
1548  /* Create the Object */
1552  KernelMode,
1553  NULL,
1554  ObjectSize,
1555  0,
1556  0,
1557  (PVOID*)&DriverObject);
1558  if (!NT_SUCCESS(Status)) return Status;
1559 
1560  DPRINT("IopCreateDriver(): created DO %p\n", DriverObject);
1561 
1562  /* Set up the Object */
1563  RtlZeroMemory(DriverObject, ObjectSize);
1564  DriverObject->Type = IO_TYPE_DRIVER;
1565  DriverObject->Size = sizeof(DRIVER_OBJECT);
1567  DriverObject->DriverExtension = (PDRIVER_EXTENSION)(DriverObject + 1);
1568  DriverObject->DriverExtension->DriverObject = DriverObject;
1569  DriverObject->DriverInit = InitializationFunction;
1570  /* Loop all Major Functions */
1571  for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
1572  {
1573  /* Invalidate each function */
1574  DriverObject->MajorFunction[i] = IopInvalidDeviceRequest;
1575  }
1576 
1577  /* Set up the service key name buffer */
1578  ServiceKeyName.MaximumLength = LocalDriverName.Length + sizeof(UNICODE_NULL);
1579  ServiceKeyName.Buffer = ExAllocatePoolWithTag(PagedPool, LocalDriverName.MaximumLength, TAG_IO);
1580  if (!ServiceKeyName.Buffer)
1581  {
1582  /* Fail */
1586  }
1587 
1588  /* For builtin drivers, the ServiceKeyName is equal to DriverName */
1589  RtlCopyUnicodeString(&ServiceKeyName, &LocalDriverName);
1590  ServiceKeyName.Buffer[ServiceKeyName.Length / sizeof(WCHAR)] = UNICODE_NULL;
1591  DriverObject->DriverExtension->ServiceKeyName = ServiceKeyName;
1592 
1593  /* Make a copy of the driver name to store in the driver object */
1594  DriverObject->DriverName.MaximumLength = LocalDriverName.Length;
1595  DriverObject->DriverName.Buffer = ExAllocatePoolWithTag(PagedPool,
1596  DriverObject->DriverName.MaximumLength,
1597  TAG_IO);
1598  if (!DriverObject->DriverName.Buffer)
1599  {
1600  /* Fail */
1604  }
1605 
1606  RtlCopyUnicodeString(&DriverObject->DriverName, &LocalDriverName);
1607 
1608  /* Add the Object and get its handle */
1610  NULL,
1612  0,
1613  NULL,
1614  &hDriver);
1615 
1616  /* Eliminate small possibility when this function is called more than
1617  once in a row, and KeTickCount doesn't get enough time to change */
1618  if (!DriverName && (Status == STATUS_OBJECT_NAME_COLLISION) && (RetryCount < 100))
1619  {
1620  RetryCount++;
1621  goto try_again;
1622  }
1623 
1624  if (!NT_SUCCESS(Status)) return Status;
1625 
1626  /* Now reference it */
1628  0,
1630  KernelMode,
1631  (PVOID*)&DriverObject,
1632  NULL);
1633 
1634  /* Close the extra handle */
1635  ZwClose(hDriver);
1636 
1637  if (!NT_SUCCESS(Status))
1638  {
1639  /* Fail */
1642  return Status;
1643  }
1644 
1645  /* Finally, call its init function */
1646  DPRINT("Calling driver entrypoint at %p\n", InitializationFunction);
1647  Status = (*InitializationFunction)(DriverObject, NULL);
1648  if (!NT_SUCCESS(Status))
1649  {
1650  /* If it didn't work, then kill the object */
1651  DPRINT1("'%wZ' initialization failed, status (0x%08lx)\n", DriverName, Status);
1654  return Status;
1655  }
1656 
1657  // Windows does this fixup - keep it for compatibility
1658  for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
1659  {
1660  /*
1661  * Make sure the driver didn't set any dispatch entry point to NULL!
1662  * Doing so is illegal; drivers shouldn't touch entry points they
1663  * do not implement.
1664  */
1665 
1666  /* Check if it did so anyway */
1667  if (!DriverObject->MajorFunction[i])
1668  {
1669  /* Print a warning in the debug log */
1670  DPRINT1("Driver <%wZ> set DriverObject->MajorFunction[%lu] to NULL!\n",
1671  &DriverObject->DriverName, i);
1672 
1673  /* Fix it up */
1674  DriverObject->MajorFunction[i] = IopInvalidDeviceRequest;
1675  }
1676  }
1677 
1678  /* Return the Status */
1679  return Status;
1680 }
1681 
1682 /*
1683  * @implemented
1684  */
1685 VOID
1686 NTAPI
1688 {
1689  /* Simply dereference the Object */
1691 }
1692 
1693 /*
1694  * @implemented
1695  */
1696 VOID
1697 NTAPI
1699  IN PDRIVER_REINITIALIZE ReinitRoutine,
1700  IN PVOID Context)
1701 {
1702  PDRIVER_REINIT_ITEM ReinitItem;
1703 
1704  /* Allocate the entry */
1705  ReinitItem = ExAllocatePoolWithTag(NonPagedPool,
1706  sizeof(DRIVER_REINIT_ITEM),
1707  TAG_REINIT);
1708  if (!ReinitItem) return;
1709 
1710  /* Fill it out */
1711  ReinitItem->DriverObject = DriverObject;
1712  ReinitItem->ReinitRoutine = ReinitRoutine;
1713  ReinitItem->Context = Context;
1714 
1715  /* Set the Driver Object flag and insert the entry into the list */
1718  &ReinitItem->ItemEntry,
1720 }
1721 
1722 /*
1723  * @implemented
1724  */
1725 VOID
1726 NTAPI
1728  IN PDRIVER_REINITIALIZE ReinitRoutine,
1729  IN PVOID Context)
1730 {
1731  PDRIVER_REINIT_ITEM ReinitItem;
1732 
1733  /* Allocate the entry */
1734  ReinitItem = ExAllocatePoolWithTag(NonPagedPool,
1735  sizeof(DRIVER_REINIT_ITEM),
1736  TAG_REINIT);
1737  if (!ReinitItem) return;
1738 
1739  /* Fill it out */
1740  ReinitItem->DriverObject = DriverObject;
1741  ReinitItem->ReinitRoutine = ReinitRoutine;
1742  ReinitItem->Context = Context;
1743 
1744  /* Set the Driver Object flag and insert the entry into the list */
1747  &ReinitItem->ItemEntry,
1749 }
1750 
1751 /*
1752  * @implemented
1753  */
1754 NTSTATUS
1755 NTAPI
1758  IN ULONG DriverObjectExtensionSize,
1759  OUT PVOID *DriverObjectExtension)
1760 {
1761  KIRQL OldIrql;
1762  PIO_CLIENT_EXTENSION DriverExtensions, NewDriverExtension;
1763  BOOLEAN Inserted = FALSE;
1764 
1765  /* Assume failure */
1766  *DriverObjectExtension = NULL;
1767 
1768  /* Allocate the extension */
1769  NewDriverExtension = ExAllocatePoolWithTag(NonPagedPool,
1770  sizeof(IO_CLIENT_EXTENSION) +
1771  DriverObjectExtensionSize,
1773  if (!NewDriverExtension) return STATUS_INSUFFICIENT_RESOURCES;
1774 
1775  /* Clear the extension for teh caller */
1776  RtlZeroMemory(NewDriverExtension,
1777  sizeof(IO_CLIENT_EXTENSION) + DriverObjectExtensionSize);
1778 
1779  /* Acqure lock */
1781 
1782  /* Fill out the extension */
1784 
1785  /* Loop the current extensions */
1786  DriverExtensions = IoGetDrvObjExtension(DriverObject)->
1787  ClientDriverExtension;
1788  while (DriverExtensions)
1789  {
1790  /* Check if the identifier matches */
1791  if (DriverExtensions->ClientIdentificationAddress ==
1793  {
1794  /* We have a collision, break out */
1795  break;
1796  }
1797 
1798  /* Go to the next one */
1799  DriverExtensions = DriverExtensions->NextExtension;
1800  }
1801 
1802  /* Check if we didn't collide */
1803  if (!DriverExtensions)
1804  {
1805  /* Link this one in */
1806  NewDriverExtension->NextExtension =
1807  IoGetDrvObjExtension(DriverObject)->ClientDriverExtension;
1808  IoGetDrvObjExtension(DriverObject)->ClientDriverExtension =
1809  NewDriverExtension;
1810  Inserted = TRUE;
1811  }
1812 
1813  /* Release the lock */
1815 
1816  /* Check if insertion failed */
1817  if (!Inserted)
1818  {
1819  /* Free the entry and fail */
1820  ExFreePoolWithTag(NewDriverExtension, TAG_DRIVER_EXTENSION);
1822  }
1823 
1824  /* Otherwise, return the pointer */
1825  *DriverObjectExtension = NewDriverExtension + 1;
1826  return STATUS_SUCCESS;
1827 }
1828 
1829 /*
1830  * @implemented
1831  */
1832 PVOID
1833 NTAPI
1836 {
1837  KIRQL OldIrql;
1838  PIO_CLIENT_EXTENSION DriverExtensions;
1839 
1840  /* Acquire lock */
1842 
1843  /* Loop the list until we find the right one */
1844  DriverExtensions = IoGetDrvObjExtension(DriverObject)->ClientDriverExtension;
1845  while (DriverExtensions)
1846  {
1847  /* Check for a match */
1848  if (DriverExtensions->ClientIdentificationAddress ==
1850  {
1851  /* Break out */
1852  break;
1853  }
1854 
1855  /* Keep looping */
1856  DriverExtensions = DriverExtensions->NextExtension;
1857  }
1858 
1859  /* Release lock */
1861 
1862  /* Return nothing or the extension */
1863  if (!DriverExtensions) return NULL;
1864  return DriverExtensions + 1;
1865 }
1866 
1867 NTSTATUS
1869  _In_ HANDLE ServiceHandle,
1871 {
1872  UNICODE_STRING ImagePath;
1873  NTSTATUS Status;
1874  PLDR_DATA_TABLE_ENTRY ModuleObject;
1876 
1878  Status = IopGetRegistryValue(ServiceHandle, L"ImagePath", &kvInfo);
1879  if (NT_SUCCESS(Status))
1880  {
1881  if (kvInfo->Type != REG_EXPAND_SZ || kvInfo->DataLength == 0)
1882  {
1883  ExFreePool(kvInfo);
1885  }
1886 
1887  ImagePath.Length = kvInfo->DataLength - sizeof(UNICODE_NULL),
1888  ImagePath.MaximumLength = kvInfo->DataLength,
1890  if (!ImagePath.Buffer)
1891  {
1892  ExFreePool(kvInfo);
1894  }
1895 
1896  RtlMoveMemory(ImagePath.Buffer,
1897  (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
1898  ImagePath.Length);
1899  ExFreePool(kvInfo);
1900  }
1901  else
1902  {
1903  return Status;
1904  }
1905 
1906  /*
1907  * Normalize the image path for all later processing.
1908  */
1909  Status = IopNormalizeImagePath(&ImagePath, NULL);
1910  if (!NT_SUCCESS(Status))
1911  {
1912  DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status);
1913  return Status;
1914  }
1915 
1916  DPRINT("FullImagePath: '%wZ'\n", &ImagePath);
1917 
1920 
1921  /*
1922  * Load the driver module
1923  */
1924  DPRINT("Loading module from %wZ\n", &ImagePath);
1925  Status = MmLoadSystemImage(&ImagePath, NULL, NULL, 0, (PVOID)&ModuleObject, &BaseAddress);
1926  RtlFreeUnicodeString(&ImagePath);
1927 
1928  if (!NT_SUCCESS(Status))
1929  {
1930  DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status);
1933  return Status;
1934  }
1935 
1936  // Display the loading message
1937  ULONG infoLength;
1938  Status = ZwQueryKey(ServiceHandle, KeyBasicInformation, NULL, 0, &infoLength);
1940  {
1942  if (servName)
1943  {
1944  Status = ZwQueryKey(ServiceHandle,
1946  servName,
1947  infoLength,
1948  &infoLength);
1949  if (NT_SUCCESS(Status))
1950  {
1952  .Length = servName->NameLength,
1953  .MaximumLength = servName->NameLength,
1954  .Buffer = servName->Name
1955  };
1956 
1958  }
1959  ExFreePoolWithTag(servName, TAG_IO);
1960  }
1961  }
1962 
1963  NTSTATUS driverEntryStatus;
1964  Status = IopInitializeDriverModule(ModuleObject,
1965  ServiceHandle,
1966  DriverObject,
1967  &driverEntryStatus);
1968  if (!NT_SUCCESS(Status))
1969  {
1970  DPRINT1("IopInitializeDriverModule() failed (Status %lx)\n", Status);
1971  }
1972 
1975 
1976  return Status;
1977 }
1978 
1979 static
1980 VOID
1981 NTAPI
1984 {
1985  PLOAD_UNLOAD_PARAMS LoadParams = Parameter;
1986 
1988 
1989  if (LoadParams->DriverObject)
1990  {
1991  // unload request
1992  LoadParams->DriverObject->DriverUnload(LoadParams->DriverObject);
1993  LoadParams->Status = STATUS_SUCCESS;
1994  }
1995  else
1996  {
1997  // load request
1998  HANDLE serviceHandle;
1999  NTSTATUS status;
2000  status = IopOpenRegistryKeyEx(&serviceHandle, NULL, LoadParams->RegistryPath, KEY_READ);
2001  if (!NT_SUCCESS(status))
2002  {
2003  LoadParams->Status = status;
2004  }
2005  else
2006  {
2007  LoadParams->Status = IopLoadDriver(serviceHandle, &LoadParams->DriverObject);
2008  ZwClose(serviceHandle);
2009  }
2010  }
2011 
2012  if (LoadParams->SetEvent)
2013  {
2014  KeSetEvent(&LoadParams->Event, 0, FALSE);
2015  }
2016 }
2017 
2027 NTSTATUS
2031 {
2032  LOAD_UNLOAD_PARAMS LoadParams;
2033 
2034  /* Prepare parameters block */
2035  LoadParams.RegistryPath = RegistryPath;
2036  LoadParams.DriverObject = *DriverObject;
2037 
2039  {
2040  LoadParams.SetEvent = TRUE;
2042 
2043  /* Initialize and queue a work item */
2044  ExInitializeWorkItem(&LoadParams.WorkItem, IopLoadUnloadDriverWorker, &LoadParams);
2046 
2047  /* And wait till it completes */
2049  }
2050  else
2051  {
2052  /* If we're already in a system process, call it right here */
2053  LoadParams.SetEvent = FALSE;
2054  IopLoadUnloadDriverWorker(&LoadParams);
2055  }
2056 
2057  return LoadParams.Status;
2058 }
2059 
2060 /*
2061  * NtLoadDriver
2062  *
2063  * Loads a device driver.
2064  *
2065  * Parameters
2066  * DriverServiceName
2067  * Name of the service to load (registry key).
2068  *
2069  * Return Value
2070  * Status
2071  *
2072  * Status
2073  * implemented
2074  */
2076 NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
2077 {
2078  UNICODE_STRING CapturedServiceName = { 0, 0, NULL };
2081  NTSTATUS Status;
2082 
2083  PAGED_CODE();
2084 
2086 
2087  /* Need the appropriate priviliege */
2089  {
2090  DPRINT1("No load privilege!\n");
2092  }
2093 
2094  /* Capture the service name */
2095  Status = ProbeAndCaptureUnicodeString(&CapturedServiceName,
2096  PreviousMode,
2097  DriverServiceName);
2098  if (!NT_SUCCESS(Status))
2099  {
2100  return Status;
2101  }
2102 
2103  DPRINT("NtLoadDriver('%wZ')\n", &CapturedServiceName);
2104 
2105  /* We need a service name */
2106  if (CapturedServiceName.Length == 0 || CapturedServiceName.Buffer == NULL)
2107  {
2108  ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
2109  return STATUS_INVALID_PARAMETER;
2110  }
2111 
2112  /* Load driver and call its entry point */
2113  DriverObject = NULL;
2114  Status = IopDoLoadUnloadDriver(&CapturedServiceName, &DriverObject);
2115 
2116  ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
2117  return Status;
2118 }
2119 
2120 /*
2121  * NtUnloadDriver
2122  *
2123  * Unloads a legacy device driver.
2124  *
2125  * Parameters
2126  * DriverServiceName
2127  * Name of the service to unload (registry key).
2128  *
2129  * Return Value
2130  * Status
2131  *
2132  * Status
2133  * implemented
2134  */
2135 
2138 {
2139  return IopUnloadDriver(DriverServiceName, FALSE);
2140 }
2141 
2142 /* EOF */
static __inline NTSTATUS ProbeAndCaptureUnicodeString(OUT PUNICODE_STRING Dest, IN KPROCESSOR_MODE CurrentMode, IN const UNICODE_STRING *UnsafeSrc)
Definition: probe.h:142
#define RTL_FIND_CHAR_IN_UNICODE_STRING_START_AT_END
Definition: rtl.h:25
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
signed char * PCHAR
Definition: retypes.h:7
static const unsigned char pc2[48]
Definition: des.c:68
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
ULONG LowPart
Definition: ketypes.h:917
BOOLEAN ExpInTextModeSetup
Definition: init.c:67
#define DRVO_BUILTIN_DRIVER
Definition: iotypes.h:2224
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4142
#define IN
Definition: typedefs.h:39
#define STATUS_DELETE_PENDING
Definition: ntstatus.h:322
NTSTATUS NTAPI RawFsDriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
Definition: rawfs.c:1193
#define DRVO_LEGACY_DRIVER
Definition: iotypes.h:2223
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
VOID NTAPI MmFreeDriverInitialization(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
Definition: sysldr.c:1636
VOID FASTCALL IopInitializeBootDrivers(VOID)
Definition: driver.c:960
PDEVICE_OBJECT PhysicalDeviceObject
Definition: iotypes.h:850
VOID NTAPI InbvIndicateProgress(VOID)
Definition: inbv.c:884
PDEVICE_NODE IopRootDeviceNode
Definition: devnode.c:18
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:711
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG IN OUT PLONG IN LONG Increment KeRaiseIrqlToDpcLevel
Definition: CrNtStubs.h:67
struct _IO_CLIENT_EXTENSION * NextExtension
Definition: iotypes.h:823
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
VOID FASTCALL IopInitializeSystemDrivers(VOID)
Definition: driver.c:1141
PSTR ArcBootDeviceName
Definition: arc.h:503
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
static const unsigned char pc1[56]
Definition: des.c:54
#define TAG_IO
Definition: tag.h:69
PUNICODE_STRING *NTAPI CmGetSystemDriverList(VOID)
Definition: cmsysini.c:1776
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
NTSTATUS NTAPI IoAllocateDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress, IN ULONG DriverObjectExtensionSize, OUT PVOID *DriverObjectExtension)
Definition: driver.c:1756
struct _Entry Entry
Definition: kefuncs.h:627
VOID PiQueueDeviceAction(_In_ PDEVICE_OBJECT DeviceObject, _In_ DEVICE_ACTION Action, _In_opt_ PKEVENT CompletionEvent, _Out_opt_ NTSTATUS *CompletionStatus)
Queue a device operation to a worker thread.
Definition: devaction.c:2579
static VOID NTAPI IopLoadUnloadDriverWorker(_Inout_ PVOID Parameter)
Definition: driver.c:1982
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
VOID NTAPI IopReinitializeDrivers(VOID)
Definition: driver.c:1427
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4711
#define DbgPrint
Definition: loader.c:25
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define TAG_RTLREGISTRY
Definition: driver.c:35
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define KEY_READ
Definition: nt_native.h:1023
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
VOID FASTCALL IopDisplayLoadingMessage(PUNICODE_STRING ServiceName)
Definition: driver.c:290
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
uint16_t * PWSTR
Definition: typedefs.h:56
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
PVOID Context
Definition: io.h:459
NTSTRSAFEVAPI RtlStringCchPrintfW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1110
ACPI_SIZE Length
Definition: actypes.h:1044
char CHAR
Definition: xmlstorage.h:175
PLIST_ENTRY NTAPI ExInterlockedInsertTailList(IN OUT PLIST_ENTRY ListHead, IN OUT PLIST_ENTRY ListEntry, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:140
#define KeGetPreviousMode()
Definition: ketypes.h:1107
#define IRP_MJ_MAXIMUM_FUNCTION
NTSTATUS IopDoLoadUnloadDriver(_In_opt_ PUNICODE_STRING RegistryPath, _Inout_ PDRIVER_OBJECT *DriverObject)
Process load and unload driver operations. This is mostly for NtLoadDriver and NtUnloadDriver,...
Definition: driver.c:2028
LONG NTSTATUS
Definition: precomp.h:26
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:213
#define STATUS_FAILED_DRIVER_ENTRY
Definition: ntstatus.h:911
WORK_QUEUE_ITEM WorkItem
Definition: driver.c:52
LIST_ENTRY DriverBootReinitListHead
Definition: driver.c:26
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define snprintf
Definition: wintirpc.h:48
_In_ LPWSTR _In_ ULONG _In_ ULONG _In_ ULONG _Out_ DEVINFO _In_ HDEV _In_ LPWSTR _In_ HANDLE hDriver
Definition: winddi.h:3553
BOOLEAN NTAPI SeSinglePrivilegeCheck(IN LUID PrivilegeValue, IN KPROCESSOR_MODE PreviousMode)
Definition: priv.c:520
KPROCESSOR_MODE NTAPI ExGetPreviousMode(VOID)
Definition: sysinfo.c:3066
#define FILESYSTEM_ROOT_NAME
Definition: ldr.h:6
NTSTATUS IopLoadDriver(_In_ HANDLE ServiceHandle, _Out_ PDRIVER_OBJECT *DriverObject)
Definition: driver.c:1868
POBJECT_TYPE IoDriverObjectType
Definition: driver.c:33
BOOLEAN PnpSystemInit
Definition: iomgr.c:17
ACPI_BUFFER *RetBuffer ACPI_BUFFER *RetBuffer char ACPI_WALK_RESOURCE_CALLBACK void *Context ACPI_BUFFER *RetBuffer UINT16 ACPI_RESOURCE **ResourcePtr ACPI_GENERIC_ADDRESS *Reg UINT32 *ReturnValue UINT8 UINT8 *Slp_TypB ACPI_PHYSICAL_ADDRESS PhysicalAddress64 UINT32 UINT32 *TimeElapsed UINT32 ACPI_STATUS const char UINT32 ACPI_STATUS const char UINT32 const char const char * ModuleName
Definition: acpixf.h:1274
uint16_t * PWCHAR
Definition: typedefs.h:56
#define swprintf
Definition: precomp.h:40
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3289
_In_ PVOID _Out_opt_ PULONG_PTR _Outptr_opt_ PCUNICODE_STRING * ObjectName
Definition: cmfuncs.h:62
_In_ PVOID Parameter
Definition: ldrtypes.h:241
VOID NTAPI IoDeleteDriver(IN PDRIVER_OBJECT DriverObject)
Definition: driver.c:1687
NTSTATUS IopGetDriverNames(_In_ HANDLE ServiceHandle, _Out_ PUNICODE_STRING DriverName, _Out_opt_ PUNICODE_STRING ServiceName)
Definition: driver.c:125
#define LDRP_DRIVER_DEPENDENT_DLL
Definition: ldrtypes.h:56
NTSTATUS NTAPI IopInvalidDeviceRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: driver.c:67
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
#define FASTCALL
Definition: nt_native.h:50
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
VOID NTAPI IopReinitializeBootDrivers(VOID)
Definition: driver.c:1463
#define SERVICE_RECOGNIZER_DRIVER
Definition: cmtypes.h:956
int32_t INT
Definition: typedefs.h:58
static int Link(const char **args)
Definition: vfdcmd.c:2414
#define MAXIMUM_FILENAME_LENGTH
Definition: env_spec_w32.h:41
#define _In_opt_
Definition: no_sal2.h:212
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
USHORT NTAPI PpInitGetGroupOrderIndex(IN HANDLE ServiceHandle)
Definition: pnpinit.c:155
#define DRVO_REINIT_REGISTERED
Definition: iotypes.h:4465
VOID NTAPI IoRegisterDriverReinitialization(IN PDRIVER_OBJECT DriverObject, IN PDRIVER_REINITIALIZE ReinitRoutine, IN PVOID Context)
Definition: driver.c:1727
uint32_t ULONG_PTR
Definition: typedefs.h:65
LIST_ENTRY ItemEntry
Definition: io.h:456
Definition: arc.h:198
NTSTATUS NTAPI RtlFindCharInUnicodeString(_In_ ULONG Flags, _In_ PCUNICODE_STRING SearchString, _In_ PCUNICODE_STRING MatchString, _Out_ PUSHORT Position)
BOOLEAN NTAPI ExAcquireResourceExclusiveLite(IN PERESOURCE Resource, IN BOOLEAN Wait)
Definition: resource.c:770
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
UCHAR KIRQL
Definition: env_spec_w32.h:591
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
KSPIN_LOCK DriverReinitListLock
Definition: driver.c:22
NTSTATUS NTAPI ObReferenceObjectByHandle(IN HANDLE Handle, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, OUT PVOID *Object, OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
Definition: obref.c:496
KSPIN_LOCK DriverBootReinitListLock
Definition: driver.c:27
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
struct _SETUP_LOADER_BLOCK * SetupLdrBlock
Definition: arc.h:511
#define TAG_LDR_WSTR
Definition: tag.h:110
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
PEPROCESS PsInitialSystemProcess
Definition: psmgr.c:50
_In_ PIRP Irp
Definition: csq.h:116
unsigned int UINT32
NTSTATUS NTAPI MmCallDllInitialize(IN PLDR_DATA_TABLE_ENTRY LdrEntry, IN PLIST_ENTRY ListHead)
Definition: sysldr.c:309
struct _LOAD_UNLOAD_PARAMS LOAD_UNLOAD_PARAMS
#define OBJ_NAME_PATH_SEPARATOR
Definition: arcname_tests.c:25
#define FILE_READ_DATA
Definition: nt_native.h:628
PDRIVER_EXTENSION DriverExtension
Definition: iotypes.h:2279
#define PsGetCurrentProcess
Definition: psfuncs.h:17
LIST_ENTRY Link
Definition: io.h:399
PLIST_ENTRY NTAPI ExInterlockedRemoveHeadList(IN OUT PLIST_ENTRY ListHead, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:166
PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance)
Definition: plugplay.c:122
unsigned char BOOLEAN
NTSTATUS FASTCALL IopNormalizeImagePath(_Inout_ _When_(return >=0, _At_(ImagePath->Buffer, _Post_notnull_ __drv_allocatesMem(Mem))) PUNICODE_STRING ImagePath, _In_ PUNICODE_STRING ServiceName)
Definition: driver.c:329
VOID(NTAPI * PDRIVER_REINITIALIZE)(_In_ struct _DRIVER_OBJECT *DriverObject, _In_opt_ PVOID Context, _In_ ULONG Count)
Definition: iotypes.h:4451
const LUID SeLoadDriverPrivilege
Definition: priv.c:27
HANDLE ServiceHandle
Definition: io.h:402
LIST_ENTRY DriverReinitListHead
Definition: driver.c:21
#define _Out_
Definition: no_sal2.h:160
#define IoCompleteRequest
Definition: irp.c:1240
NTSTATUS NTAPI IoCreateDriver(_In_opt_ PUNICODE_STRING DriverName, _In_ PDRIVER_INITIALIZE InitializationFunction)
Definition: driver.c:1507
PDRIVER_OBJECT DriverObject
Definition: io.h:457
Definition: bufpool.h:45
USHORT TagPosition
Definition: io.h:403
void * PVOID
Definition: retypes.h:9
#define SERVICE_FILE_SYSTEM_DRIVER
Definition: cmtypes.h:954
PLOADER_PARAMETER_BLOCK KeLoaderBlock
Definition: krnlinit.c:29
__drv_aliasesMem _In_ PVOID ClientIdentificationAddress
Definition: iofuncs.h:1026
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define TAG_REINIT
Definition: tag.h:73
KEVENT PiEnumerationFinished
Definition: devaction.c:50
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
#define DRVO_UNLOAD_INVOKED
Definition: iotypes.h:2222
NTSTATUS NTAPI ObCreateObject(IN KPROCESSOR_MODE ProbeMode OPTIONAL, IN POBJECT_TYPE Type, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext OPTIONAL, IN ULONG ObjectSize, IN ULONG PagedPoolCharge OPTIONAL, IN ULONG NonPagedPoolCharge OPTIONAL, OUT PVOID *Object)
Definition: oblife.c:952
NTSTATUS NTAPI MmUnloadSystemImage(IN PVOID ImageHandle)
Definition: sysldr.c:912
#define STATUS_ILL_FORMED_SERVICE_ENTRY
Definition: ntstatus.h:588
Status
Definition: gdiplustypes.h:24
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
char serviceName[]
Definition: tftpd.cpp:34
#define _Out_opt_
Definition: no_sal2.h:214
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
static __inline VOID ReleaseCapturedUnicodeString(IN PUNICODE_STRING CapturedString, IN KPROCESSOR_MODE CurrentMode)
Definition: probe.h:239
_In_ KPROCESSOR_MODE PreviousMode
Definition: sefuncs.h:103
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
#define __drv_allocatesMem(kind)
Definition: driverspecs.h:239
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
LPTSTR ServiceName
Definition: ServiceMain.c:15
#define ASSERT(a)
Definition: mode.c:45
#define DOE_UNLOAD_PENDING
Definition: iotypes.h:149
#define TAG_DRIVER_EXTENSION
Definition: tag.h:42
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_In_ WDFCOLLECTION _In_ ULONG Index
LIST_ENTRY PsLoadedModuleList
Definition: sysldr.c:34
PLIST_ENTRY DriverReinitTailEntry
Definition: driver.c:23
NTSTATUS NTAPI MiResolveImageReferences(IN PVOID ImageBase, IN PUNICODE_STRING ImageFileDirectory, IN PUNICODE_STRING NamePrefix OPTIONAL, OUT PCHAR *MissingApi, OUT PWCHAR *MissingDriver, OUT PLOAD_IMPORTS *LoadImports)
Definition: sysldr.c:1001
#define ObDereferenceObject
Definition: obfuncs.h:203
GLuint GLuint num
Definition: glext.h:9618
PLIST_ENTRY IopGroupTable
Definition: driver.c:43
LIST_ENTRY BootDriverListHead
Definition: arc.h:495
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define _Inout_
Definition: no_sal2.h:162
CODE_SEG("INIT")
Definition: fsrtlpc.c:19
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1817
CCHAR KPROCESSOR_MODE
Definition: ketypes.h:7
BOOLEAN IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY BootLdrEntry)
Definition: driver.c:751
VOID NTAPI IopReadyDeviceObjects(IN PDRIVER_OBJECT Driver)
Definition: device.c:34
VOID NTAPI IoRegisterBootDriverReinitialization(IN PDRIVER_OBJECT DriverObject, IN PDRIVER_REINITIALIZE ReinitRoutine, IN PVOID Context)
Definition: driver.c:1698
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define _Post_notnull_
Definition: sal.h:701
PBOOT_DRIVER_LIST_ENTRY DataTableEntry
Definition: io.h:401
NTSYSAPI BOOLEAN NTAPI RtlCreateUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
DRIVER_INITIALIZE * PDRIVER_INITIALIZE
Definition: iotypes.h:2232
NTSTATUS NTAPI NtUnloadDriver(IN PUNICODE_STRING DriverServiceName)
Definition: driver.c:2137
static const WCHAR L[]
Definition: oid.c:1250
NTKERNELAPI volatile KSYSTEM_TIME KeTickCount
Definition: clock.c:19
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
NTSTATUS Status
Definition: driver.c:50
PDRIVER_UNLOAD DriverUnload
Definition: iotypes.h:2285
PVOID NTAPI IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject, IN PVOID ClientIdentificationAddress)
Definition: driver.c:1834
#define OBJ_PERMANENT
Definition: winternl.h:226
#define KeEnterCriticalRegion()
Definition: ke_x.h:83
Definition: btrfs_drv.h:1922
_In_ PNDIS_STRING DeviceInstance
Definition: ndis.h:5202
BOOLEAN SetEvent
Definition: driver.c:55
struct _DRIVER_OBJECT DRIVER_OBJECT
Definition: typedefs.h:119
#define wcsrchr
Definition: compat.h:16
static const WCHAR Cleanup[]
Definition: register.c:80
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
static const WCHAR Backslash[]
Definition: cfgmgr.c:38
PPCI_DRIVER_EXTENSION DriverExtension
Definition: pci.c:41
PLIST_ENTRY DriverBootReinitTailEntry
Definition: driver.c:25
LIST_ENTRY LoadOrderListHead
Definition: arc.h:493
NTSTATUS PiPerformSyncDeviceAction(_In_ PDEVICE_OBJECT DeviceObject, _In_ DEVICE_ACTION Action)
Perfom a device operation synchronously via PiQueueDeviceAction.
Definition: devaction.c:2638
PDRIVER_OBJECT DriverObject
Definition: driver.c:54
#define _In_
Definition: no_sal2.h:158
NTSTATUS NTAPI IopGetRegistryValue(IN HANDLE Handle, IN PWSTR ValueName, OUT PKEY_VALUE_FULL_INFORMATION *Information)
Definition: pnpmgr.c:1607
struct _FileName FileName
Definition: fatprocs.h:893
ERESOURCE IopDriverLoadResource
Definition: driver.c:19
NTSTATUS NTAPI ObInsertObject(IN PVOID Object, IN PACCESS_STATE AccessState OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG ObjectPointerBias, OUT PVOID *NewObject OPTIONAL, OUT PHANDLE Handle)
Definition: obhandle.c:2932
UNICODE_STRING RegistryPath
Definition: arc.h:202
DRIVER_INFORMATION DriverInfo
Definition: main.c:59
#define KeLeaveCriticalRegion()
Definition: ke_x.h:114
PUNICODE_STRING RegistryPath
Definition: driver.c:51
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
NTSTATUS NTAPI IopOpenRegistryKeyEx(PHANDLE KeyHandle, HANDLE ParentKey, PUNICODE_STRING Name, ACCESS_MASK DesiredAccess)
Definition: pnpmgr.c:1456
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
unsigned short USHORT
Definition: pedump.c:61
struct _LDR_DATA_TABLE_ENTRY * LdrEntry
Definition: arc.h:203
VOID NTAPI IopDeleteDriver(IN PVOID ObjectBody)
Definition: driver.c:79
#define _At_(t, a)
Definition: no_sal2.h:40
struct _DRIVER_EXTENSION * PDRIVER_EXTENSION
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
UNICODE_STRING IopHardwareDatabaseKey
Definition: driver.c:29
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
ULONG KSPIN_LOCK
Definition: env_spec_w32.h:72
UNICODE_STRING BaseDllName
Definition: ldrtypes.h:145
#define NULL
Definition: types.h:112
struct _LOAD_UNLOAD_PARAMS * PLOAD_UNLOAD_PARAMS
NTHALAPI VOID NTAPI HalDisplayString(PUCHAR String)
#define IO_TYPE_DRIVER
#define DPRINT1
Definition: precomp.h:8
_In_ const STRING * String2
Definition: rtlfuncs.h:2291
NTSTATUS IopInitializeDriverModule(_In_ PLDR_DATA_TABLE_ENTRY ModuleObject, _In_ HANDLE ServiceHandle, _Out_ PDRIVER_OBJECT *OutDriverObject, _Out_ NTSTATUS *DriverEntryStatus)
Initialize a loaded driver.
Definition: driver.c:403
char TextBuffer[BUFFERLEN]
Definition: combotst.c:45
#define _When_(c, a)
Definition: no_sal2.h:38
struct tagContext Context
Definition: acpixf.h:1034
#define OUT
Definition: typedefs.h:40
BOOLEAN PnPBootDriversLoaded
Definition: pnpinit.c:26
ULONG Flags
Definition: ntddk_ex.h:207
ULONG ERESOURCE
Definition: env_spec_w32.h:594
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:598
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
PDRIVER_REINITIALIZE ReinitRoutine
Definition: io.h:458
#define STATUS_SUCCESS
Definition: shellext.h:65
static const WCHAR ServicesKeyName[]
Definition: driver.c:31
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
PVOID ClientIdentificationAddress
Definition: iotypes.h:824
GLfloat GLfloat p
Definition: glext.h:8902
#define DPRINT
Definition: sndvol32.h:71
NTSTATUS NTAPI IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
Definition: driver.c:1200
#define IoGetDevObjExtension(DeviceObject)
Definition: io.h:125
#define REG_DWORD
Definition: sdbapi.c:596
#define IoGetDrvObjExtension(DriverObject)
Definition: io.h:132
NTSTATUS NTAPI ObReferenceObjectByName(IN PUNICODE_STRING ObjectPath, IN ULONG Attributes, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext, OUT PVOID *ObjectPtr)
Definition: obref.c:411
static SERVICE_STATUS status
Definition: service.c:31
NTSTATUS NTAPI NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
Definition: driver.c:2076
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
USHORT IopGroupIndex
Definition: driver.c:42
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
base of all file and directory entries
Definition: entries.h:82
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
PDRIVER_INITIALIZE DriverInit
Definition: iotypes.h:2283
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
NTSTATUS NTAPI MmLoadSystemImage(IN PUNICODE_STRING FileName, IN PUNICODE_STRING NamePrefix OPTIONAL, IN PUNICODE_STRING LoadedName OPTIONAL, IN ULONG Flags, OUT PVOID *ModuleObject, OUT PVOID *ImageBaseAddress)
Definition: sysldr.c:2819
#define DRIVER_ROOT_NAME
Definition: ldr.h:5
#define PAGED_CODE()
#define DRVO_BOOTREINIT_REGISTERED
Definition: iotypes.h:4467
USHORT NTAPI PipGetDriverTagPriority(IN HANDLE ServiceHandle)
Definition: pnpinit.c:198
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define NT_ASSERT
Definition: rtlfuncs.h:3312
VOID NTAPI ObMakeTemporaryObject(IN PVOID ObjectBody)
Definition: oblife.c:1361
#define REG_SZ
Definition: layer.c:22
NTSTATUS NTAPI LdrProcessDriverModule(PLDR_DATA_TABLE_ENTRY LdrEntry, PUNICODE_STRING FileName, PLDR_DATA_TABLE_ENTRY *ModuleObject)
Definition: driver.c:667
Definition: ps.c:97
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
BOOLEAN NTAPI IopSuffixUnicodeString(IN PCUNICODE_STRING String1, IN PCUNICODE_STRING String2)
Definition: driver.c:256