ReactOS  0.4.15-dev-1200-gc3b3fcd
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 ResetDevice (IN LPCWSTR 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

◆ DeviceInstallThread()

static ULONG NTAPI DeviceInstallThread ( IN PVOID  Parameter)
static

Definition at line 365 of file devinst.c.

366 {
368  PLIST_ENTRY ListEntry;
369  DeviceInstallParams* Params;
371 
372  for (;;)
373  {
374  /* Dequeue the next oldest device-install event */
376  ListEntry = (IsListEmpty(&DeviceInstallListHead)
379 
380  if (ListEntry == NULL)
381  {
382  /*
383  * The list is now empty, but there may be a new enumerated device
384  * that is going to be added to the list soon. In order to avoid
385  * setting the hNoPendingInstalls event to release it soon after,
386  * we wait for maximum 1 second for no PnP enumeration event being
387  * received before declaring that no pending installations are
388  * taking place and setting the corresponding event.
389  */
390  Timeout.QuadPart = -10000000LL; /* Wait for 1 second */
392  {
393  /* We timed out: set the event and do the actual wait */
396  }
397  }
398  else
399  {
401  Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry);
403  RtlFreeHeap(ProcessHeap, 0, Params);
404  }
405  }
406 
407  return 0;
408 }
HINF hSetupInf
Definition: intl.c:40
#define LL
Definition: tui.h:84
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:389
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:416
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:458
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
WCHAR DeviceIds[ANYSIZE_ARRAY]
Definition: precomp.h:39
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:226
NTSTATUS NTAPI NtReleaseMutant(IN HANDLE MutantHandle, IN PLONG PreviousCount OPTIONAL)
Definition: mutant.c:299
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 549 of file devinst.c.

550 {
551  /* Wait until all pending installations are done, then freeze the threads */
553  DPRINT1("WaitNoPendingInstallEvents() failed to wait!\n");
554 
555  // TODO: use signalling events
556 
559 
560  return TRUE;
561 }
#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
smooth NULL
Definition: ftsmooth.c:416
NTSTATUS WaitNoPendingInstallEvents(IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: devinst.c:519
#define DPRINT1
Definition: precomp.h:8

Referenced by TerminateUserModePnpManager().

◆ EnableUserModePnpManager()

BOOLEAN EnableUserModePnpManager ( VOID  )

Definition at line 526 of file devinst.c.

527 {
529 
530  /* Start the PnP thread */
531  if (hPnpThread != NULL)
533 
534  /*
535  * Wait a little bit so that we get a chance to have some events being
536  * queued by the time the device-installation thread becomes resumed.
537  */
538  Timeout.QuadPart = -10000000LL; /* Wait for 1 second */
540 
541  /* Start the device installation thread */
542  if (hDeviceInstallThread != NULL)
544 
545  return TRUE;
546 }
#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
smooth NULL
Definition: ftsmooth.c:416
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
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 564 of file devinst.c.

566 {
569 
570  UNICODE_STRING EnumU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
571  UNICODE_STRING ServicesU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services");
572 
575  NULL,
577  FALSE);
578  if (!NT_SUCCESS(Status))
579  {
580  DPRINT1("Could not create the Pending-Install Event! (Status 0x%08lx)\n", Status);
581  goto Failure;
582  }
583 
584  /*
585  * Initialize the device-install event list
586  */
587 
590  NULL,
592  FALSE);
593  if (!NT_SUCCESS(Status))
594  {
595  DPRINT1("Could not create the List Event! (Status 0x%08lx)\n", Status);
596  goto Failure;
597  }
598 
601  NULL, FALSE);
602  if (!NT_SUCCESS(Status))
603  {
604  DPRINT1("Could not create the List Mutex! (Status 0x%08lx)\n", Status);
605  goto Failure;
606  }
608 
611  if (!NT_SUCCESS(Status))
612  {
613  DPRINT1("NtOpenKey('%wZ') failed (Status 0x%08lx)\n", &EnumU, Status);
614  goto Failure;
615  }
616 
619  if (!NT_SUCCESS(Status))
620  {
621  DPRINT1("NtCreateKey('%wZ') failed (Status 0x%08lx)\n", &ServicesU, Status);
622  goto Failure;
623  }
624 
625  /* Create the PnP event thread in suspended state */
627  NULL,
628  TRUE,
629  0,
630  0,
631  0,
633  NULL,
634  &hPnpThread,
635  NULL);
636  if (!NT_SUCCESS(Status))
637  {
638  DPRINT1("Failed to create the PnP event thread (Status 0x%08lx)\n", Status);
639  hPnpThread = NULL;
640  goto Failure;
641  }
642 
643  /* Create the device installation thread in suspended state */
645  NULL,
646  TRUE,
647  0,
648  0,
649  0,
651  phSetupInf,
653  NULL);
654  if (!NT_SUCCESS(Status))
655  {
656  DPRINT1("Failed to create the device installation thread (Status 0x%08lx)\n", Status);
658  goto Failure;
659  }
660 
661  return STATUS_SUCCESS;
662 
663 Failure:
664  if (hPnpThread)
665  {
668  }
669  hPnpThread = NULL;
670 
671  if (hServicesKey)
673  hServicesKey = NULL;
674 
675  if (hEnumKey)
676  NtClose(hEnumKey);
677  hEnumKey = NULL;
678 
682 
686 
687  if (hNoPendingInstalls)
690 
691  return Status;
692 }
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:100
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:365
smooth NULL
Definition: ftsmooth.c:416
#define NtCurrentProcess()
Definition: nt_native.h:1657
#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:411
NTSTATUS NTAPI NtCreateMutant(OUT PHANDLE MutantHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN BOOLEAN InitialOwner)
Definition: mutant.c:83
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
Status
Definition: gdiplustypes.h:24
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 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
return STATUS_SUCCESS
Definition: btrfs.c:3014
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 226 of file devinst.c.

231 {
232  UNICODE_STRING HardwareIDU = RTL_CONSTANT_STRING(L"HardwareID");
233  UNICODE_STRING CompatibleIDsU = RTL_CONSTANT_STRING(L"CompatibleIDs");
234 
235  UNICODE_STRING DeviceIdU;
237  LPCWSTR HardwareID;
238  PKEY_VALUE_PARTIAL_INFORMATION pPartialInformation = NULL;
239  HANDLE hDeviceKey;
240  ULONG ulRequired;
241  BOOLEAN bDriverInstalled = FALSE;
243 
244  RtlInitUnicodeString(&DeviceIdU, DeviceId);
247  if (!NT_SUCCESS(Status))
248  {
249  DPRINT("Unable to open subkey '%S'\n", DeviceId);
250  return;
251  }
252 
254  hDeviceKey,
255  &HardwareIDU,
257  NULL,
258  0,
259  &ulRequired);
261  {
262  pPartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)RtlAllocateHeap(ProcessHeap, 0, ulRequired);
263  if (!pPartialInformation)
264  {
265  DPRINT1("RtlAllocateHeap() failed\n");
266  NtClose(hDeviceKey);
267  return;
268  }
270  hDeviceKey,
271  &HardwareIDU,
273  pPartialInformation,
274  ulRequired,
275  &ulRequired);
276  }
278  {
279  /* Nothing to do */
280  }
281  else if (!NT_SUCCESS(Status))
282  {
283  DPRINT1("NtQueryValueKey() failed with status 0x%08x\n", Status);
284  if (pPartialInformation)
285  RtlFreeHeap(ProcessHeap, 0, pPartialInformation);
286  NtClose(hDeviceKey);
287  return;
288  }
289  else if (pPartialInformation)
290  {
291  for (HardwareID = (LPCWSTR)pPartialInformation->Data;
292  (PUCHAR)HardwareID < pPartialInformation->Data + pPartialInformation->DataLength
293  && *HardwareID
294  && !bDriverInstalled;
295  HardwareID += wcslen(HardwareID) + 1)
296  {
297  bDriverInstalled = InstallDriver(hInf, hServices,hDeviceKey, DeviceId, HardwareID);
298  }
299  }
300 
301  if (!bDriverInstalled)
302  {
303  if (pPartialInformation)
304  {
305  RtlFreeHeap(ProcessHeap, 0, pPartialInformation);
306  pPartialInformation = NULL;
307  }
309  hDeviceKey,
310  &CompatibleIDsU,
312  NULL,
313  0,
314  &ulRequired);
316  {
317  pPartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)RtlAllocateHeap(ProcessHeap, 0, ulRequired);
318  if (!pPartialInformation)
319  {
320  DPRINT("RtlAllocateHeap() failed\n");
321  NtClose(hDeviceKey);
322  return;
323  }
325  hDeviceKey,
326  &CompatibleIDsU,
328  pPartialInformation,
329  ulRequired,
330  &ulRequired);
331  }
333  {
334  /* Nothing to do */
335  }
336  else if (!NT_SUCCESS(Status))
337  {
338  if (pPartialInformation)
339  RtlFreeHeap(ProcessHeap, 0, pPartialInformation);
340  NtClose(hDeviceKey);
341  DPRINT1("NtQueryValueKey() failed with status 0x%08x\n", Status);
342  return;
343  }
344  else if (pPartialInformation)
345  {
346  for (HardwareID = (LPCWSTR)pPartialInformation->Data;
347  (PUCHAR)HardwareID < pPartialInformation->Data + pPartialInformation->DataLength
348  && *HardwareID
349  && !bDriverInstalled;
350  HardwareID += wcslen(HardwareID) + 1)
351  {
352  bDriverInstalled = InstallDriver(hInf, hServices,hDeviceKey, DeviceId, HardwareID);
353  }
354  }
355  }
356  if (!bDriverInstalled)
357  DPRINT("No driver available for %S\n", DeviceId);
358 
359  RtlFreeHeap(ProcessHeap, 0, pPartialInformation);
360  NtClose(hDeviceKey);
361 }
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
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
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:59
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
Status
Definition: gdiplustypes.h:24
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 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
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#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 59 of file devinst.c.

65 {
66  UNICODE_STRING PathPrefix = RTL_CONSTANT_STRING(L"System32\\DRIVERS\\");
67  UNICODE_STRING ServiceU = RTL_CONSTANT_STRING(L"Service");
68  UNICODE_STRING ErrorControlU = RTL_CONSTANT_STRING(L"ErrorControl");
69  UNICODE_STRING ImagePathU = RTL_CONSTANT_STRING(L"ImagePath");
70  UNICODE_STRING StartU = RTL_CONSTANT_STRING(L"Start");
71  UNICODE_STRING TypeU = RTL_CONSTANT_STRING(L"Type");
72  UNICODE_STRING UpperFiltersU = RTL_CONSTANT_STRING(L"UpperFilters");
73  PWSTR keyboardClass = L"kbdclass\0";
74 
75  UNICODE_STRING StringU;
77  HANDLE hService;
79  PCWSTR Driver, ClassGuid, ImagePath;
80  PWSTR FullImagePath;
81  ULONG dwValue;
84  BOOLEAN deviceInstalled = FALSE;
85 
86  /* Check if we know the hardware */
87  if (!SpInfFindFirstLine(hInf, L"HardwareIdsDatabase", HardwareId, &Context))
88  return FALSE;
89  if (!INF_GetDataField(&Context, 1, &Driver))
90  return FALSE;
91 
92  /* Get associated class GUID (if any) */
93  if (!INF_GetDataField(&Context, 2, &ClassGuid))
94  ClassGuid = NULL;
95 
96  /* Find associated driver name */
97  /* FIXME: check in other sections too! */
98  if (!SpInfFindFirstLine(hInf, L"BootBusExtenders.Load", Driver, &Context)
99  && !SpInfFindFirstLine(hInf, L"BusExtenders.Load", Driver, &Context)
100  && !SpInfFindFirstLine(hInf, L"SCSI.Load", Driver, &Context)
101  && !SpInfFindFirstLine(hInf, L"InputDevicesSupport.Load", Driver, &Context)
102  && !SpInfFindFirstLine(hInf, L"Keyboard.Load", Driver, &Context))
103  {
104  INF_FreeData(ClassGuid);
106  return FALSE;
107  }
108 
109  if (!INF_GetDataField(&Context, 1, &ImagePath))
110  {
111  INF_FreeData(ClassGuid);
113  return FALSE;
114  }
115 
116  /* Prepare full driver path */
117  dwValue = PathPrefix.MaximumLength + wcslen(ImagePath) * sizeof(WCHAR);
118  FullImagePath = (PWSTR)RtlAllocateHeap(ProcessHeap, 0, dwValue);
119  if (!FullImagePath)
120  {
121  DPRINT1("RtlAllocateHeap() failed\n");
122  INF_FreeData(ImagePath);
123  INF_FreeData(ClassGuid);
125  return FALSE;
126  }
127  RtlCopyMemory(FullImagePath, PathPrefix.Buffer, PathPrefix.MaximumLength);
128  ConcatPaths(FullImagePath, dwValue / sizeof(WCHAR), 1, ImagePath);
129 
130  DPRINT1("Using driver '%S' for device '%S'\n", ImagePath, DeviceId);
131 
132  /* Create service key */
133  RtlInitUnicodeString(&StringU, Driver);
136  if (!NT_SUCCESS(Status))
137  {
138  DPRINT1("NtCreateKey('%wZ') failed with status 0x%08x\n", &StringU, Status);
139  RtlFreeHeap(ProcessHeap, 0, FullImagePath);
140  INF_FreeData(ImagePath);
141  INF_FreeData(ClassGuid);
143  return FALSE;
144  }
145 
146  /* Fill service key */
148  {
149  dwValue = 0;
150  NtSetValueKey(hService,
151  &ErrorControlU,
152  0,
153  REG_DWORD,
154  &dwValue,
155  sizeof(dwValue));
156 
157  dwValue = 0;
158  NtSetValueKey(hService,
159  &StartU,
160  0,
161  REG_DWORD,
162  &dwValue,
163  sizeof(dwValue));
164 
165  dwValue = SERVICE_KERNEL_DRIVER;
166  NtSetValueKey(hService,
167  &TypeU,
168  0,
169  REG_DWORD,
170  &dwValue,
171  sizeof(dwValue));
172  }
173  /* HACK: don't put any path in registry */
174  NtSetValueKey(hService,
175  &ImagePathU,
176  0,
177  REG_SZ,
178  (PVOID)ImagePath,
179  (wcslen(ImagePath) + 1) * sizeof(WCHAR));
180 
181  INF_FreeData(ImagePath);
182 
183  if (ClassGuid &&_wcsicmp(ClassGuid, L"{4D36E96B-E325-11CE-BFC1-08002BE10318}") == 0)
184  {
185  DPRINT1("Installing keyboard class driver for '%S'\n", DeviceId);
186  NtSetValueKey(hDeviceKey,
187  &UpperFiltersU,
188  0,
189  REG_MULTI_SZ,
190  keyboardClass,
191  (wcslen(keyboardClass) + 2) * sizeof(WCHAR));
192  }
193 
194  INF_FreeData(ClassGuid);
195 
196  /* Associate device with the service we just filled */
197  Status = NtSetValueKey(hDeviceKey,
198  &ServiceU,
199  0,
200  REG_SZ,
201  (PVOID)Driver,
202  (wcslen(Driver) + 1) * sizeof(WCHAR));
203  if (NT_SUCCESS(Status))
204  {
205  /* Restart the device, so it will use the driver we registered */
206  deviceInstalled = ResetDevice(DeviceId);
207  }
208 
210 
211  /* HACK: Update driver path */
212  NtSetValueKey(hService,
213  &ImagePathU,
214  0,
215  REG_SZ,
216  FullImagePath,
217  (wcslen(FullImagePath) + 1) * sizeof(WCHAR));
218  RtlFreeHeap(ProcessHeap, 0, FullImagePath);
219 
220  NtClose(hService);
221 
222  return deviceInstalled;
223 }
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
const uint16_t * PCWSTR
Definition: typedefs.h:57
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
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
USHORT MaximumLength
Definition: env_spec_w32.h:370
uint16_t * PWSTR
Definition: typedefs.h:56
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
NTSTATUS ConcatPaths(IN OUT PWSTR PathBuffer, IN SIZE_T cchPathSize, IN ULONG NumberOfPathComponents, IN ...)
Definition: filesup.c:659
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
smooth NULL
Definition: ftsmooth.c:416
#define REG_CREATED_NEW_KEY
Definition: nt_native.h:1084
_In_ PCUNICODE_STRING _In_ PVOID Driver
Definition: cmfuncs.h:32
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
#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
Status
Definition: gdiplustypes.h:24
static const WCHAR L[]
Definition: oid.c:1250
static BOOLEAN ResetDevice(IN LPCWSTR DeviceId)
Definition: devinst.c:42
HANDLE ProcessHeap
Definition: servman.c:15
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
#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
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
_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 411 of file devinst.c.

412 {
414  PLUGPLAY_CONTROL_USER_RESPONSE_DATA ResponseData = {0, 0, 0, 0};
415  PPLUGPLAY_EVENT_BLOCK PnpEvent, NewPnpEvent;
416  ULONG PnpEventSize;
417 
419 
420  PnpEventSize = 0x1000;
421  PnpEvent = RtlAllocateHeap(ProcessHeap, 0, PnpEventSize);
422  if (PnpEvent == NULL)
423  {
425  goto Quit;
426  }
427 
428  for (;;)
429  {
430  DPRINT("Calling NtGetPlugPlayEvent()\n");
431 
432  /* Wait for the next PnP event */
433  Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
434 
435  /* Resize the buffer for the PnP event if it's too small */
437  {
438  PnpEventSize += 0x400;
439  NewPnpEvent = RtlReAllocateHeap(ProcessHeap, 0, PnpEvent, PnpEventSize);
440  if (NewPnpEvent == NULL)
441  {
443  goto Quit;
444  }
445  PnpEvent = NewPnpEvent;
446  continue;
447  }
448 
449  if (!NT_SUCCESS(Status))
450  {
451  DPRINT1("NtGetPlugPlayEvent() failed (Status 0x%08lx)\n", Status);
452  goto Quit;
453  }
454 
455  /* Process the PnP event */
456  DPRINT("Received PnP Event\n");
457  if (IsEqualGUID(&PnpEvent->EventGuid, &GUID_DEVICE_ENUMERATED))
458  {
459  DeviceInstallParams* Params;
460  ULONG len;
461  ULONG DeviceIdLength;
462 
463  DPRINT("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds);
464 
465  DeviceIdLength = wcslen(PnpEvent->TargetDevice.DeviceIds);
466  if (DeviceIdLength)
467  {
468  /* Allocate a new device-install event */
469  len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
470  Params = RtlAllocateHeap(ProcessHeap, 0, len);
471  if (Params)
472  {
473  wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
474 
475  /* Queue the event (will be dequeued by DeviceInstallThread) */
479 
481  }
482  else
483  {
484  DPRINT1("Not enough memory (size %lu)\n", len);
485  }
486  }
487  }
488  else
489  {
490  DPRINT("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
491  PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
492  PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
493  PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
494  PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
495  }
496 
497  /* Dequeue the current PnP event and signal the next one */
499  &ResponseData,
500  sizeof(ResponseData));
501  if (!NT_SUCCESS(Status))
502  {
503  DPRINT1("NtPlugPlayControl(PlugPlayControlUserResponse) failed (Status 0x%08lx)\n", Status);
504  goto Quit;
505  }
506  }
507 
509 
510 Quit:
511  if (PnpEvent)
512  RtlFreeHeap(ProcessHeap, 0, PnpEvent);
513 
515  return Status;
516 }
#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:1132
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
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:458
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
LIST_ENTRY ListEntry
Definition: precomp.h:38
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
Status
Definition: gdiplustypes.h:24
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
WCHAR DeviceIds[ANYSIZE_ARRAY]
Definition: precomp.h:39
NTSTATUS NTAPI NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass, IN OUT PVOID Buffer, IN ULONG BufferLength)
Definition: plugplay.c:1262
struct _PLUGPLAY_EVENT_BLOCK::@2344::@2347 TargetDevice
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
BOOL WINAPI IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
Definition: compobj.c:4112
#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:2622
return STATUS_SUCCESS
Definition: btrfs.c:3014
NTSTATUS NTAPI NtReleaseMutant(IN HANDLE MutantHandle, IN PLONG PreviousCount OPTIONAL)
Definition: mutant.c:299
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
static HANDLE hDeviceInstallListMutex
Definition: devinst.c:29
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)

Referenced by InitializeUserModePnpManager().

◆ ResetDevice()

static BOOLEAN ResetDevice ( IN LPCWSTR  DeviceId)
static

Definition at line 42 of file devinst.c.

44 {
45  PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
47 
48  RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, DeviceId);
50  if (!NT_SUCCESS(Status))
51  {
52  DPRINT1("NtPlugPlayControl() failed with status 0x%08x\n", Status);
53  return FALSE;
54  }
55  return TRUE;
56 }
#define TRUE
Definition: types.h:120
LONG NTSTATUS
Definition: precomp.h:26
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Status
Definition: gdiplustypes.h:24
NTSTATUS NTAPI NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass, IN OUT PVOID Buffer, IN ULONG BufferLength)
Definition: plugplay.c:1262
#define DPRINT1
Definition: precomp.h:8
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)

Referenced by InstallDriver().

◆ TerminateUserModePnpManager()

VOID TerminateUserModePnpManager ( VOID  )

Definition at line 695 of file devinst.c.

696 {
698 
699  // TODO: use signalling events
700 
701  /* Kill the PnP thread as it blocks inside the NtGetPlugPlayEvent() call */
702  if (hPnpThread)
703  {
706  }
707  hPnpThread = NULL;
708 
709  /* Kill the device installation thread */
711  {
714  }
716 
717  /* Close the opened handles */
718 
719  if (hServicesKey)
721  hServicesKey = NULL;
722 
723  if (hEnumKey)
724  NtClose(hEnumKey);
725  hEnumKey = NULL;
726 
727  if (hNoPendingInstalls)
730 
734 }
static HANDLE hEnumKey
Definition: devinst.c:20
static HANDLE hPnpThread
Definition: devinst.c:25
static HANDLE hDeviceInstallThread
Definition: devinst.c:26
smooth NULL
Definition: ftsmooth.c:416
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
BOOLEAN DisableUserModePnpManager(VOID)
Definition: devinst.c:549
return STATUS_SUCCESS
Definition: btrfs.c:3014

Referenced by RunUSetup().

◆ WaitNoPendingInstallEvents()

NTSTATUS WaitNoPendingInstallEvents ( IN PLARGE_INTEGER Timeout  OPTIONAL)

Definition at line 519 of file devinst.c.

521 {
523 }
#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