ReactOS  0.4.15-dev-2361-g32428a3
devinst.c File Reference
#include <usetup.h>
#include <debug.h>
#include <guiddef.h>
#include <libs/umpnpmgr/sysguid.h>
Include dependency graph for devinst.c:

Go to the source code of this file.

Classes

struct  DeviceInstallParams
 

Macros

#define NDEBUG
 
#define INITGUID
 

Functions

static BOOLEAN AreDriversLoaded (IN PCWSTR DeviceId)
 
static BOOLEAN InstallDriver (IN HINF hInf, IN HANDLE hServices, IN HANDLE hDeviceKey, IN LPCWSTR DeviceId, IN LPCWSTR HardwareId)
 
static VOID InstallDevice (IN HINF hInf, IN HANDLE hEnum, IN HANDLE hServices, IN LPCWSTR DeviceId)
 
static ULONG NTAPI DeviceInstallThread (IN PVOID Parameter)
 
static ULONG NTAPI PnpEventThread (IN PVOID Parameter)
 
NTSTATUS WaitNoPendingInstallEvents (IN PLARGE_INTEGER Timeout OPTIONAL)
 
BOOLEAN EnableUserModePnpManager (VOID)
 
BOOLEAN DisableUserModePnpManager (VOID)
 
NTSTATUS InitializeUserModePnpManager (IN HINF *phSetupInf)
 
VOID TerminateUserModePnpManager (VOID)
 

Variables

static HANDLE hEnumKey = NULL
 
static HANDLE hServicesKey = NULL
 
static HANDLE hNoPendingInstalls = NULL
 
static HANDLE hPnpThread = NULL
 
static HANDLE hDeviceInstallThread = NULL
 
static HANDLE hDeviceInstallListMutex = NULL
 
static LIST_ENTRY DeviceInstallListHead
 
static HANDLE hDeviceInstallListNotEmpty = NULL
 

Macro Definition Documentation

◆ INITGUID

#define INITGUID

Definition at line 14 of file devinst.c.

◆ NDEBUG

#define NDEBUG

Definition at line 11 of file devinst.c.

Function Documentation

◆ AreDriversLoaded()

static BOOLEAN AreDriversLoaded ( IN PCWSTR  DeviceId)
static

Definition at line 42 of file devinst.c.

44 {
45  PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
47 
48  RtlInitUnicodeString(&PlugPlayData.DeviceInstance, DeviceId);
49  PlugPlayData.Operation = PNP_GET_DEVICE_STATUS;
50 
51  Status = NtPlugPlayControl(PlugPlayControlDeviceStatus, &PlugPlayData, sizeof(PlugPlayData));
52  if (NT_SUCCESS(Status))
53  {
54  return (_Bool)((PlugPlayData.DeviceStatus & DN_DRIVER_LOADED) &&
55  !(PlugPlayData.DeviceStatus & DN_HAS_PROBLEM));
56  }
57  else
58  {
59  return FALSE;
60  }
61 }
LONG NTSTATUS
Definition: precomp.h:26
#define DN_DRIVER_LOADED
Definition: cfg.h:119
UNICODE_STRING DeviceInstance
Definition: cmtypes.h:525
#define FALSE
Definition: types.h:117
Status
Definition: gdiplustypes.h:24
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define PNP_GET_DEVICE_STATUS
Definition: cmtypes.h:59
#define DN_HAS_PROBLEM
Definition: cfg.h:128
NTSTATUS NTAPI NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass, IN OUT PVOID Buffer, IN ULONG BufferLength)
Definition: plugplay.c:1259
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)

Referenced by InstallDriver().

◆ DeviceInstallThread()

static ULONG NTAPI DeviceInstallThread ( IN PVOID  Parameter)
static

Definition at line 360 of file devinst.c.

361 {
363  PLIST_ENTRY ListEntry;
366 
367  for (;;)
368  {
369  /* Dequeue the next oldest device-install event */
371  ListEntry = (IsListEmpty(&DeviceInstallListHead)
374 
375  if (ListEntry == NULL)
376  {
377  /*
378  * The list is now empty, but there may be a new enumerated device
379  * that is going to be added to the list soon. In order to avoid
380  * setting the hNoPendingInstalls event to release it soon after,
381  * we wait for maximum 1 second for no PnP enumeration event being
382  * received before declaring that no pending installations are
383  * taking place and setting the corresponding event.
384  */
385  Timeout.QuadPart = -10000000LL; /* Wait for 1 second */
387  {
388  /* We timed out: set the event and do the actual wait */
391  }
392  }
393  else
394  {
396  Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry);
399  }
400  }
401 
402  return 0;
403 }
HINF hSetupInf
Definition: intl.c:39
#define LL
Definition: tui.h:84
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:306
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
_In_ PVOID Parameter
Definition: ldrtypes.h:241
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
static HANDLE hEnumKey
Definition: devinst.c:20
NTSTATUS NTAPI NtResetEvent(IN HANDLE EventHandle, OUT PLONG PreviousState OPTIONAL)
Definition: event.c:385
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define FALSE
Definition: types.h:117
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
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
static HANDLE hServicesKey
Definition: devinst.c:21
NTSTATUS NTAPI NtSetEvent(IN HANDLE EventHandle, OUT PLONG PreviousState OPTIONAL)
Definition: event.c:454
static HANDLE hNoPendingInstalls
Definition: devinst.c:23
Definition: typedefs.h:119
HANDLE ProcessHeap
Definition: servman.c:15
static HANDLE hDeviceInstallListNotEmpty
Definition: devinst.c:31
static LIST_ENTRY DeviceInstallListHead
Definition: devinst.c:30
static ULONG Timeout
Definition: ping.c:61
static VOID InstallDevice(IN HINF hInf, IN HANDLE hEnum, IN HANDLE hServices, IN LPCWSTR DeviceId)
Definition: devinst.c:221
#define NULL
Definition: types.h:112
NTSTATUS NTAPI NtReleaseMutant(IN HANDLE MutantHandle, IN PLONG PreviousCount OPTIONAL)
Definition: mutant.c:295
static HANDLE hDeviceInstallListMutex
Definition: devinst.c:29
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)

Referenced by InitializeUserModePnpManager().

◆ DisableUserModePnpManager()

BOOLEAN DisableUserModePnpManager ( VOID  )

Definition at line 544 of file devinst.c.

545 {
546  /* Wait until all pending installations are done, then freeze the threads */
548  DPRINT1("WaitNoPendingInstallEvents() failed to wait!\n");
549 
550  // TODO: use signalling events
551 
554 
555  return TRUE;
556 }
#define TRUE
Definition: types.h:120
NTSTATUS NTAPI NtSuspendThread(IN HANDLE ThreadHandle, OUT PULONG PreviousSuspendCount OPTIONAL)
Definition: state.c:352
#define STATUS_WAIT_0
Definition: ntstatus.h:237
static HANDLE hPnpThread
Definition: devinst.c:25
static HANDLE hDeviceInstallThread
Definition: devinst.c:26
NTSTATUS WaitNoPendingInstallEvents(IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: devinst.c:514
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8

Referenced by TerminateUserModePnpManager().

◆ EnableUserModePnpManager()

BOOLEAN EnableUserModePnpManager ( VOID  )

Definition at line 521 of file devinst.c.

522 {
524 
525  /* Start the PnP thread */
526  if (hPnpThread != NULL)
528 
529  /*
530  * Wait a little bit so that we get a chance to have some events being
531  * queued by the time the device-installation thread becomes resumed.
532  */
533  Timeout.QuadPart = -10000000LL; /* Wait for 1 second */
535 
536  /* Start the device installation thread */
537  if (hDeviceInstallThread != NULL)
539 
540  return TRUE;
541 }
#define LL
Definition: tui.h:84
#define TRUE
Definition: types.h:120
static HANDLE hPnpThread
Definition: devinst.c:25
#define FALSE
Definition: types.h:117
static HANDLE hDeviceInstallThread
Definition: devinst.c:26
NTSTATUS NTAPI NtResumeThread(IN HANDLE ThreadHandle, OUT PULONG SuspendCount OPTIONAL)
Definition: state.c:290
static HANDLE hDeviceInstallListNotEmpty
Definition: devinst.c:31
static ULONG Timeout
Definition: ping.c:61
#define NULL
Definition: types.h:112
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)

Referenced by SetupStartPage().

◆ InitializeUserModePnpManager()

NTSTATUS InitializeUserModePnpManager ( IN HINF phSetupInf)

Definition at line 559 of file devinst.c.

561 {
564 
565  UNICODE_STRING EnumU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
566  UNICODE_STRING ServicesU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services");
567 
570  NULL,
572  FALSE);
573  if (!NT_SUCCESS(Status))
574  {
575  DPRINT1("Could not create the Pending-Install Event! (Status 0x%08lx)\n", Status);
576  goto Failure;
577  }
578 
579  /*
580  * Initialize the device-install event list
581  */
582 
585  NULL,
587  FALSE);
588  if (!NT_SUCCESS(Status))
589  {
590  DPRINT1("Could not create the List Event! (Status 0x%08lx)\n", Status);
591  goto Failure;
592  }
593 
596  NULL, FALSE);
597  if (!NT_SUCCESS(Status))
598  {
599  DPRINT1("Could not create the List Mutex! (Status 0x%08lx)\n", Status);
600  goto Failure;
601  }
603 
606  if (!NT_SUCCESS(Status))
607  {
608  DPRINT1("NtOpenKey('%wZ') failed (Status 0x%08lx)\n", &EnumU, Status);
609  goto Failure;
610  }
611 
614  if (!NT_SUCCESS(Status))
615  {
616  DPRINT1("NtCreateKey('%wZ') failed (Status 0x%08lx)\n", &ServicesU, Status);
617  goto Failure;
618  }
619 
620  /* Create the PnP event thread in suspended state */
622  NULL,
623  TRUE,
624  0,
625  0,
626  0,
628  NULL,
629  &hPnpThread,
630  NULL);
631  if (!NT_SUCCESS(Status))
632  {
633  DPRINT1("Failed to create the PnP event thread (Status 0x%08lx)\n", Status);
634  hPnpThread = NULL;
635  goto Failure;
636  }
637 
638  /* Create the device installation thread in suspended state */
640  NULL,
641  TRUE,
642  0,
643  0,
644  0,
646  phSetupInf,
648  NULL);
649  if (!NT_SUCCESS(Status))
650  {
651  DPRINT1("Failed to create the device installation thread (Status 0x%08lx)\n", Status);
653  goto Failure;
654  }
655 
656  return STATUS_SUCCESS;
657 
658 Failure:
659  if (hPnpThread)
660  {
663  }
664  hPnpThread = NULL;
665 
666  if (hServicesKey)
668  hServicesKey = NULL;
669 
670  if (hEnumKey)
671  NtClose(hEnumKey);
672  hEnumKey = NULL;
673 
677 
681 
682  if (hNoPendingInstalls)
685 
686  return Status;
687 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
NTSTATUS NTAPI NtCreateKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL)
Definition: ntapi.c:240
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS NTAPI NtCreateEvent(OUT PHANDLE EventHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN EVENT_TYPE EventType, IN BOOLEAN InitialState)
Definition: event.c:96
static HANDLE hEnumKey
Definition: devinst.c:20
static HANDLE hPnpThread
Definition: devinst.c:25
#define FALSE
Definition: types.h:117
#define MUTANT_ALL_ACCESS
Definition: extypes.h:110
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
static HANDLE hDeviceInstallThread
Definition: devinst.c:26
static ULONG NTAPI DeviceInstallThread(IN PVOID Parameter)
Definition: devinst.c:360
#define NtCurrentProcess()
Definition: nt_native.h:1657
Status
Definition: gdiplustypes.h:24
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
static HANDLE hServicesKey
Definition: devinst.c:21
NTSTATUS NtTerminateThread(IN HANDLE ThreadHandle OPTIONAL, IN NTSTATUS ExitStatus)
Definition: kill.c:1278
static HANDLE hNoPendingInstalls
Definition: devinst.c:23
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static ULONG NTAPI PnpEventThread(IN PVOID Parameter)
Definition: devinst.c:406
NTSTATUS NTAPI NtCreateMutant(OUT PHANDLE MutantHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN BOOLEAN InitialOwner)
Definition: mutant.c:79
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
static const WCHAR L[]
Definition: oid.c:1250
NTSYSAPI NTSTATUS NTAPI RtlCreateUserThread(_In_ PVOID ThreadContext, _Out_ HANDLE *OutThreadHandle, _Reserved_ PVOID Reserved1, _Reserved_ PVOID Reserved2, _Reserved_ PVOID Reserved3, _Reserved_ PVOID Reserved4, _Reserved_ PVOID Reserved5, _Reserved_ PVOID Reserved6, _Reserved_ PVOID Reserved7, _Reserved_ PVOID Reserved8)
static HANDLE hDeviceInstallListNotEmpty
Definition: devinst.c:31
static LIST_ENTRY DeviceInstallListHead
Definition: devinst.c:30
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
NTSYSAPI NTSTATUS NTAPI NtOpenKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: ntapi.c:336
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define STATUS_SUCCESS
Definition: shellext.h:65
static HANDLE hDeviceInstallListMutex
Definition: devinst.c:29
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14

Referenced by RunUSetup().

◆ InstallDevice()

static VOID InstallDevice ( IN HINF  hInf,
IN HANDLE  hEnum,
IN HANDLE  hServices,
IN LPCWSTR  DeviceId 
)
static

Definition at line 221 of file devinst.c.

226 {
227  UNICODE_STRING HardwareIDU = RTL_CONSTANT_STRING(L"HardwareID");
228  UNICODE_STRING CompatibleIDsU = RTL_CONSTANT_STRING(L"CompatibleIDs");
229 
230  UNICODE_STRING DeviceIdU;
233  PKEY_VALUE_PARTIAL_INFORMATION pPartialInformation = NULL;
234  HANDLE hDeviceKey;
235  ULONG ulRequired;
236  BOOLEAN bDriverInstalled = FALSE;
238 
239  RtlInitUnicodeString(&DeviceIdU, DeviceId);
242  if (!NT_SUCCESS(Status))
243  {
244  DPRINT("Unable to open subkey '%S'\n", DeviceId);
245  return;
246  }
247 
249  hDeviceKey,
250  &HardwareIDU,
252  NULL,
253  0,
254  &ulRequired);
256  {
257  pPartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)RtlAllocateHeap(ProcessHeap, 0, ulRequired);
258  if (!pPartialInformation)
259  {
260  DPRINT1("RtlAllocateHeap() failed\n");
261  NtClose(hDeviceKey);
262  return;
263  }
265  hDeviceKey,
266  &HardwareIDU,
268  pPartialInformation,
269  ulRequired,
270  &ulRequired);
271  }
273  {
274  /* Nothing to do */
275  }
276  else if (!NT_SUCCESS(Status))
277  {
278  DPRINT1("NtQueryValueKey() failed with status 0x%08x\n", Status);
279  if (pPartialInformation)
280  RtlFreeHeap(ProcessHeap, 0, pPartialInformation);
281  NtClose(hDeviceKey);
282  return;
283  }
284  else if (pPartialInformation)
285  {
286  for (HardwareID = (LPCWSTR)pPartialInformation->Data;
288  && *HardwareID
289  && !bDriverInstalled;
290  HardwareID += wcslen(HardwareID) + 1)
291  {
292  bDriverInstalled = InstallDriver(hInf, hServices,hDeviceKey, DeviceId, HardwareID);
293  }
294  }
295 
296  if (!bDriverInstalled)
297  {
298  if (pPartialInformation)
299  {
300  RtlFreeHeap(ProcessHeap, 0, pPartialInformation);
301  pPartialInformation = NULL;
302  }
304  hDeviceKey,
305  &CompatibleIDsU,
307  NULL,
308  0,
309  &ulRequired);
311  {
312  pPartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)RtlAllocateHeap(ProcessHeap, 0, ulRequired);
313  if (!pPartialInformation)
314  {
315  DPRINT("RtlAllocateHeap() failed\n");
316  NtClose(hDeviceKey);
317  return;
318  }
320  hDeviceKey,
321  &CompatibleIDsU,
323  pPartialInformation,
324  ulRequired,
325  &ulRequired);
326  }
328  {
329  /* Nothing to do */
330  }
331  else if (!NT_SUCCESS(Status))
332  {
333  if (pPartialInformation)
334  RtlFreeHeap(ProcessHeap, 0, pPartialInformation);
335  NtClose(hDeviceKey);
336  DPRINT1("NtQueryValueKey() failed with status 0x%08x\n", Status);
337  return;
338  }
339  else if (pPartialInformation)
340  {
341  for (HardwareID = (LPCWSTR)pPartialInformation->Data;
343  && *HardwareID
344  && !bDriverInstalled;
345  HardwareID += wcslen(HardwareID) + 1)
346  {
347  bDriverInstalled = InstallDriver(hInf, hServices,hDeviceKey, DeviceId, HardwareID);
348  }
349  }
350  }
351  if (!bDriverInstalled)
352  DPRINT("No driver available for %S\n", DeviceId);
353 
354  RtlFreeHeap(ProcessHeap, 0, pPartialInformation);
355  NtClose(hDeviceKey);
356 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define KEY_SET_VALUE
Definition: nt_native.h:1017
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char * PUCHAR
Definition: retypes.h:3
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define FALSE
Definition: types.h:117
unsigned char BOOLEAN
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
static BOOLEAN InstallDriver(IN HINF hInf, IN HANDLE hServices, IN HANDLE hDeviceKey, IN LPCWSTR DeviceId, IN LPCWSTR HardwareId)
Definition: devinst.c:64
Status
Definition: gdiplustypes.h:24
NTSYSAPI NTSTATUS NTAPI NtQueryValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, IN PVOID KeyValueInformation, IN ULONG Length, IN PULONG ResultLength)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
struct _KEY_VALUE_PARTIAL_INFORMATION * PKEY_VALUE_PARTIAL_INFORMATION
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
static const WCHAR L[]
Definition: oid.c:1250
HANDLE ProcessHeap
Definition: servman.c:15
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define NULL
Definition: types.h:112
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ PCUNICODE_STRING HardwareID
Definition: wdfpdo.h:337
#define DPRINT1
Definition: precomp.h:8
NTSYSAPI NTSTATUS NTAPI NtOpenKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: ntapi.c:336
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define DPRINT
Definition: sndvol32.h:71
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14

Referenced by DeviceInstallThread().

◆ InstallDriver()

static BOOLEAN InstallDriver ( IN HINF  hInf,
IN HANDLE  hServices,
IN HANDLE  hDeviceKey,
IN LPCWSTR  DeviceId,
IN LPCWSTR  HardwareId 
)
static

Definition at line 64 of file devinst.c.

70 {
71  UNICODE_STRING ServiceU = RTL_CONSTANT_STRING(L"Service");
72  UNICODE_STRING ErrorControlU = RTL_CONSTANT_STRING(L"ErrorControl");
73  UNICODE_STRING StartU = RTL_CONSTANT_STRING(L"Start");
74  UNICODE_STRING TypeU = RTL_CONSTANT_STRING(L"Type");
75  UNICODE_STRING UpperFiltersU = RTL_CONSTANT_STRING(L"UpperFilters");
76  PWSTR keyboardClass = L"kbdclass\0";
77  PWSTR partMgr = L"partmgr\0";
78 
79  UNICODE_STRING StringU;
81  HANDLE hService;
83  PCWSTR Driver, ClassGuid, ImagePath;
84  ULONG dwValue;
87  BOOLEAN deviceInstalled = FALSE;
88 
89  /* First check if the driver needs any action at all */
90  if (AreDriversLoaded(DeviceId))
91  return TRUE;
92 
93  /* Check if we know the hardware */
94  if (!SpInfFindFirstLine(hInf, L"HardwareIdsDatabase", HardwareId, &Context))
95  return FALSE;
96  if (!INF_GetDataField(&Context, 1, &Driver))
97  return FALSE;
98 
99  /* Get associated class GUID (if any) */
100  if (!INF_GetDataField(&Context, 2, &ClassGuid))
101  ClassGuid = NULL;
102 
103  /* Find associated driver name */
104  /* FIXME: check in other sections too! */
105  if (!SpInfFindFirstLine(hInf, L"BootBusExtenders.Load", Driver, &Context)
106  && !SpInfFindFirstLine(hInf, L"BusExtenders.Load", Driver, &Context)
107  && !SpInfFindFirstLine(hInf, L"SCSI.Load", Driver, &Context)
108  && !SpInfFindFirstLine(hInf, L"InputDevicesSupport.Load", Driver, &Context)
109  && !SpInfFindFirstLine(hInf, L"Keyboard.Load", Driver, &Context))
110  {
111  INF_FreeData(ClassGuid);
113  return FALSE;
114  }
115 
116  if (!INF_GetDataField(&Context, 1, &ImagePath))
117  {
118  INF_FreeData(ClassGuid);
120  return FALSE;
121  }
122 
123  DPRINT1("Using driver '%S' for device '%S'\n", ImagePath, DeviceId);
124 
125  /* Create service key */
126  RtlInitUnicodeString(&StringU, Driver);
129  if (!NT_SUCCESS(Status))
130  {
131  DPRINT1("NtCreateKey('%wZ') failed with status 0x%08x\n", &StringU, Status);
132  INF_FreeData(ImagePath);
133  INF_FreeData(ClassGuid);
135  return FALSE;
136  }
137 
138  /* Fill service key */
140  {
141  dwValue = 0;
142  NtSetValueKey(hService,
143  &ErrorControlU,
144  0,
145  REG_DWORD,
146  &dwValue,
147  sizeof(dwValue));
148 
149  dwValue = 0;
150  NtSetValueKey(hService,
151  &StartU,
152  0,
153  REG_DWORD,
154  &dwValue,
155  sizeof(dwValue));
156 
157  dwValue = SERVICE_KERNEL_DRIVER;
158  NtSetValueKey(hService,
159  &TypeU,
160  0,
161  REG_DWORD,
162  &dwValue,
163  sizeof(dwValue));
164  }
165 
166  INF_FreeData(ImagePath);
167  NtClose(hService);
168 
169  /* Add kbdclass and partmgr upper filters */
170  if (ClassGuid &&_wcsicmp(ClassGuid, L"{4D36E96B-E325-11CE-BFC1-08002BE10318}") == 0)
171  {
172  DPRINT1("Installing keyboard class driver for '%S'\n", DeviceId);
173  NtSetValueKey(hDeviceKey,
174  &UpperFiltersU,
175  0,
176  REG_MULTI_SZ,
177  keyboardClass,
178  (wcslen(keyboardClass) + 2) * sizeof(WCHAR));
179  }
180  else if (ClassGuid && _wcsicmp(ClassGuid, L"{4D36E967-E325-11CE-BFC1-08002BE10318}") == 0)
181  {
182  DPRINT1("Installing partition manager driver for '%S'\n", DeviceId);
183  NtSetValueKey(hDeviceKey,
184  &UpperFiltersU,
185  0,
186  REG_MULTI_SZ,
187  partMgr,
188  (wcslen(partMgr) + 2) * sizeof(WCHAR));
189  }
190 
191  INF_FreeData(ClassGuid);
192 
193  /* Associate device with the service we just filled */
194  Status = NtSetValueKey(hDeviceKey,
195  &ServiceU,
196  0,
197  REG_SZ,
198  (PVOID)Driver,
199  (wcslen(Driver) + 1) * sizeof(WCHAR));
200  if (NT_SUCCESS(Status))
201  {
202  /* We've registered the driver, time to start a device */
204  RtlInitUnicodeString(&ControlData.DeviceInstance, DeviceId);
205 
206  Status = NtPlugPlayControl(PlugPlayControlStartDevice, &ControlData, sizeof(ControlData));
207  if (!NT_SUCCESS(Status))
208  {
209  DPRINT1("NtPlugPlayControl() failed with status 0x%08x\n", Status);
210  }
211 
212  deviceInstalled = NT_SUCCESS(Status);
213  }
214 
216 
217  return deviceInstalled;
218 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
const uint16_t * PCWSTR
Definition: typedefs.h:57
NTSTATUS NTAPI NtCreateKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL)
Definition: ntapi.c:240
#define KEY_SET_VALUE
Definition: nt_native.h:1017
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define TRUE
Definition: types.h:120
uint16_t * PWSTR
Definition: typedefs.h:56
LONG NTSTATUS
Definition: precomp.h:26
pSpInfFindFirstLine SpInfFindFirstLine
Definition: infsupp.c:87
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Reserved_ ULONG _In_opt_ PUNICODE_STRING _In_ ULONG _Out_opt_ PULONG Disposition
Definition: cmfuncs.h:50
#define FALSE
Definition: types.h:117
#define REG_MULTI_SZ
Definition: nt_native.h:1501
unsigned char BOOLEAN
BOOLEAN INF_GetDataField(IN PINFCONTEXT Context, IN ULONG FieldIndex, OUT PCWSTR *Data)
Definition: infsupp.c:42
#define REG_CREATED_NEW_KEY
Definition: nt_native.h:1084
Status
Definition: gdiplustypes.h:24
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
FORCEINLINE VOID INF_FreeData(IN PCWSTR InfData)
Definition: infsupp.h:157
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
static const WCHAR L[]
Definition: oid.c:1250
static BOOLEAN AreDriversLoaded(IN PCWSTR DeviceId)
Definition: devinst.c:42
NTSTATUS NTAPI NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass, IN OUT PVOID Buffer, IN ULONG BufferLength)
Definition: plugplay.c:1259
#define NULL
Definition: types.h:112
NTSYSAPI NTSTATUS NTAPI NtSetValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN ULONG TitleIndex OPTIONAL, IN ULONG Type, IN PVOID Data, IN ULONG DataSize)
Definition: ntapi.c:859
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define DPRINT1
Definition: precomp.h:8
struct tagContext Context
Definition: acpixf.h:1034
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define REG_DWORD
Definition: sdbapi.c:596
_Must_inspect_result_ _In_ WDFDRIVER Driver
Definition: wdfcontrol.h:83
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define SERVICE_KERNEL_DRIVER
Definition: cmtypes.h:953
#define REG_SZ
Definition: layer.c:22

Referenced by InstallDevice().

◆ PnpEventThread()

static ULONG NTAPI PnpEventThread ( IN PVOID  Parameter)
static

Definition at line 406 of file devinst.c.

407 {
409  PLUGPLAY_CONTROL_USER_RESPONSE_DATA ResponseData = {0, 0, 0, 0};
410  PPLUGPLAY_EVENT_BLOCK PnpEvent, NewPnpEvent;
411  ULONG PnpEventSize;
412 
414 
415  PnpEventSize = 0x1000;
416  PnpEvent = RtlAllocateHeap(ProcessHeap, 0, PnpEventSize);
417  if (PnpEvent == NULL)
418  {
420  goto Quit;
421  }
422 
423  for (;;)
424  {
425  DPRINT("Calling NtGetPlugPlayEvent()\n");
426 
427  /* Wait for the next PnP event */
428  Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
429 
430  /* Resize the buffer for the PnP event if it's too small */
432  {
433  PnpEventSize += 0x400;
434  NewPnpEvent = RtlReAllocateHeap(ProcessHeap, 0, PnpEvent, PnpEventSize);
435  if (NewPnpEvent == NULL)
436  {
438  goto Quit;
439  }
440  PnpEvent = NewPnpEvent;
441  continue;
442  }
443 
444  if (!NT_SUCCESS(Status))
445  {
446  DPRINT1("NtGetPlugPlayEvent() failed (Status 0x%08lx)\n", Status);
447  goto Quit;
448  }
449 
450  /* Process the PnP event */
451  DPRINT("Received PnP Event\n");
452  if (IsEqualGUID(&PnpEvent->EventGuid, &GUID_DEVICE_ENUMERATED))
453  {
455  ULONG len;
456  ULONG DeviceIdLength;
457 
458  DPRINT("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds);
459 
460  DeviceIdLength = wcslen(PnpEvent->TargetDevice.DeviceIds);
461  if (DeviceIdLength)
462  {
463  /* Allocate a new device-install event */
464  len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
466  if (Params)
467  {
468  wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
469 
470  /* Queue the event (will be dequeued by DeviceInstallThread) */
474 
476  }
477  else
478  {
479  DPRINT1("Not enough memory (size %lu)\n", len);
480  }
481  }
482  }
483  else
484  {
485  DPRINT("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
486  PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
487  PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
488  PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
489  PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
490  }
491 
492  /* Dequeue the current PnP event and signal the next one */
494  &ResponseData,
495  sizeof(ResponseData));
496  if (!NT_SUCCESS(Status))
497  {
498  DPRINT1("NtPlugPlayControl(PlugPlayControlUserResponse) failed (Status 0x%08lx)\n", Status);
499  goto Quit;
500  }
501  }
502 
504 
505 Quit:
506  if (PnpEvent)
507  RtlFreeHeap(ProcessHeap, 0, PnpEvent);
508 
510  return Status;
511 }
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:306
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
#define NtCurrentThread()
_In_ PVOID Parameter
Definition: ldrtypes.h:241
#define InsertTailList(ListHead, Entry)
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define FALSE
Definition: types.h:117
NTSTATUS NTAPI NtGetPlugPlayEvent(IN ULONG Reserved1, IN ULONG Reserved2, OUT PPLUGPLAY_EVENT_BLOCK Buffer, IN ULONG BufferSize)
Definition: plugplay.c:1129
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
Status
Definition: gdiplustypes.h:24
NTSTATUS NtTerminateThread(IN HANDLE ThreadHandle OPTIONAL, IN NTSTATUS ExitStatus)
Definition: kill.c:1278
NTSTATUS NTAPI NtSetEvent(IN HANDLE EventHandle, OUT PLONG PreviousState OPTIONAL)
Definition: event.c:454
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
GLenum GLsizei len
Definition: glext.h:6722
HANDLE ProcessHeap
Definition: servman.c:15
static HANDLE hDeviceInstallListNotEmpty
Definition: devinst.c:31
static LIST_ENTRY DeviceInstallListHead
Definition: devinst.c:30
NTSTATUS NTAPI NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass, IN OUT PVOID Buffer, IN ULONG BufferLength)
Definition: plugplay.c:1259
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NULL
Definition: types.h:112
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE, ULONG, PVOID, SIZE_T)
Definition: heap.c:2667
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
NTSTATUS NTAPI NtReleaseMutant(IN HANDLE MutantHandle, IN PLONG PreviousCount OPTIONAL)
Definition: mutant.c:295
static HANDLE hDeviceInstallListMutex
Definition: devinst.c:29
struct _PLUGPLAY_EVENT_BLOCK::@2346::@2349 TargetDevice
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)

Referenced by InitializeUserModePnpManager().

◆ TerminateUserModePnpManager()

VOID TerminateUserModePnpManager ( VOID  )

Definition at line 690 of file devinst.c.

691 {
693 
694  // TODO: use signalling events
695 
696  /* Kill the PnP thread as it blocks inside the NtGetPlugPlayEvent() call */
697  if (hPnpThread)
698  {
701  }
702  hPnpThread = NULL;
703 
704  /* Kill the device installation thread */
706  {
709  }
711 
712  /* Close the opened handles */
713 
714  if (hServicesKey)
716  hServicesKey = NULL;
717 
718  if (hEnumKey)
719  NtClose(hEnumKey);
720  hEnumKey = NULL;
721 
722  if (hNoPendingInstalls)
725 
729 }
static HANDLE hEnumKey
Definition: devinst.c:20
static HANDLE hPnpThread
Definition: devinst.c:25
static HANDLE hDeviceInstallThread
Definition: devinst.c:26
static HANDLE hServicesKey
Definition: devinst.c:21
NTSTATUS NtTerminateThread(IN HANDLE ThreadHandle OPTIONAL, IN NTSTATUS ExitStatus)
Definition: kill.c:1278
static HANDLE hNoPendingInstalls
Definition: devinst.c:23
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
static HANDLE hDeviceInstallListNotEmpty
Definition: devinst.c:31
#define NULL
Definition: types.h:112
#define STATUS_SUCCESS
Definition: shellext.h:65
BOOLEAN DisableUserModePnpManager(VOID)
Definition: devinst.c:544

Referenced by RunUSetup().

◆ WaitNoPendingInstallEvents()

NTSTATUS WaitNoPendingInstallEvents ( IN PLARGE_INTEGER Timeout  OPTIONAL)

Definition at line 514 of file devinst.c.

516 {
518 }
#define FALSE
Definition: types.h:117
static HANDLE hNoPendingInstalls
Definition: devinst.c:23
static ULONG Timeout
Definition: ping.c:61
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)

Referenced by DisableUserModePnpManager(), and SetupStartPage().

Variable Documentation

◆ DeviceInstallListHead

LIST_ENTRY DeviceInstallListHead
static

Definition at line 30 of file devinst.c.

Referenced by DeviceInstallThread(), InitializeUserModePnpManager(), and PnpEventThread().

◆ hDeviceInstallListMutex

HANDLE hDeviceInstallListMutex = NULL
static

Definition at line 29 of file devinst.c.

Referenced by DeviceInstallThread(), InitializeUserModePnpManager(), and PnpEventThread().

◆ hDeviceInstallListNotEmpty

HANDLE hDeviceInstallListNotEmpty = NULL
static

◆ hDeviceInstallThread

HANDLE hDeviceInstallThread = NULL
static

◆ hEnumKey

◆ hNoPendingInstalls

HANDLE hNoPendingInstalls = NULL
static

◆ hPnpThread

◆ hServicesKey