ReactOS 0.4.15-dev-7924-g5949c20
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{
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
#define DN_HAS_PROBLEM
Definition: cfg.h:128
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Status
Definition: gdiplustypes.h:25
@ PlugPlayControlDeviceStatus
Definition: cmtypes.h:223
#define PNP_GET_DEVICE_STATUS
Definition: cmtypes.h:59
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSTATUS NTAPI NtPlugPlayControl(IN PLUGPLAY_CONTROL_CLASS PlugPlayControlClass, IN OUT PVOID Buffer, IN ULONG BufferLength)
Definition: plugplay.c:1494
UNICODE_STRING DeviceInstance
Definition: cmtypes.h:525

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 */
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}
HANDLE ProcessHeap
Definition: servman.c:15
static HANDLE hDeviceInstallListNotEmpty
Definition: devinst.c:31
static VOID InstallDevice(IN HINF hInf, IN HANDLE hEnum, IN HANDLE hServices, IN LPCWSTR DeviceId)
Definition: devinst.c:221
static HANDLE hServicesKey
Definition: devinst.c:21
static HANDLE hDeviceInstallListMutex
Definition: devinst.c:29
static HANDLE hNoPendingInstalls
Definition: devinst.c:23
static LIST_ENTRY DeviceInstallListHead
Definition: devinst.c:30
static HANDLE hEnumKey
Definition: devinst.c:20
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
#define NULL
Definition: types.h:112
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
HINF hSetupInf
Definition: intl.c:39
NTSTATUS NTAPI NtReleaseMutant(IN HANDLE MutantHandle, IN PLONG PreviousCount OPTIONAL)
Definition: mutant.c:296
NTSYSAPI NTSTATUS NTAPI NtWaitForSingleObject(IN HANDLE hObject, IN BOOLEAN bAlertable, IN PLARGE_INTEGER Timeout)
NTSTATUS NTAPI NtSetEvent(IN HANDLE EventHandle, OUT PLONG PreviousState OPTIONAL)
Definition: event.c:455
NTSTATUS NTAPI NtResetEvent(IN HANDLE EventHandle, OUT PLONG PreviousState OPTIONAL)
Definition: event.c:386
#define STATUS_TIMEOUT
Definition: ntstatus.h:81
static ULONG Timeout
Definition: ping.c:61
Definition: typedefs.h:120
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
_In_ WDFIOTARGET _In_ PWDF_REQUEST_COMPLETION_PARAMS Params
Definition: wdfrequest.h:308
_Inout_opt_ PVOID Parameter
Definition: rtltypes.h:323

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 DPRINT1
Definition: precomp.h:8
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 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

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 */
539
540 return TRUE;
541}
NTSTATUS NTAPI NtResumeThread(IN HANDLE ThreadHandle, OUT PULONG SuspendCount OPTIONAL)
Definition: state.c:290

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);
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
658Failure:
659 if (hPnpThread)
660 {
663 }
665
666 if (hServicesKey)
669
670 if (hEnumKey)
672 hEnumKey = NULL;
673
677
681
685
686 return Status;
687}
static ULONG NTAPI DeviceInstallThread(IN PVOID Parameter)
Definition: devinst.c:360
static ULONG NTAPI PnpEventThread(IN PVOID Parameter)
Definition: devinst.c:406
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define EVENT_ALL_ACCESS
Definition: isotest.c:82
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
NTSTATUS NTAPI NtCreateMutant(OUT PHANDLE MutantHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN BOOLEAN InitialOwner)
Definition: mutant.c:79
#define MUTANT_ALL_ACCESS
Definition: extypes.h:110
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)
NTSYSAPI NTSTATUS NTAPI NtOpenKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: ntapi.c:336
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
NTSTATUS NtTerminateThread(IN HANDLE ThreadHandle OPTIONAL, IN NTSTATUS ExitStatus)
Definition: kill.c:1279
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
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
@ NotificationEvent
@ SynchronizationEvent
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
#define L(x)
Definition: ntvdm.h:50
#define STATUS_SUCCESS
Definition: shellext.h:65
#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{
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,
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,
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;
287 (PUCHAR)HardwareID < pPartialInformation->Data + pPartialInformation->DataLength
288 && *HardwareID
289 && !bDriverInstalled;
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;
342 (PUCHAR)HardwareID < pPartialInformation->Data + pPartialInformation->DataLength
343 && *HardwareID
344 && !bDriverInstalled;
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}
unsigned char BOOLEAN
static BOOLEAN InstallDriver(IN HINF hInf, IN HANDLE hServices, IN HANDLE hDeviceKey, IN LPCWSTR DeviceId, IN LPCWSTR HardwareId)
Definition: devinst.c:64
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
@ KeyValuePartialInformation
Definition: nt_native.h:1182
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)
struct _KEY_VALUE_PARTIAL_INFORMATION * PKEY_VALUE_PARTIAL_INFORMATION
#define KEY_SET_VALUE
Definition: nt_native.h:1017
static UNICODE_STRING HardwareIDU
Definition: pnpmap.c:34
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define DPRINT
Definition: sndvol32.h:71
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_ PCUNICODE_STRING HardwareID
Definition: wdfpdo.h:340
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185

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");
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;
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,
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,
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}
static BOOLEAN AreDriversLoaded(IN PCWSTR DeviceId)
Definition: devinst.c:42
pSpInfFindFirstLine SpInfFindFirstLine
Definition: infsupp.c:87
FORCEINLINE VOID INF_FreeData(IN PCWSTR InfData)
Definition: infsupp.h:157
#define REG_SZ
Definition: layer.c:22
BOOLEAN INF_GetDataField(IN PINFCONTEXT Context, IN ULONG FieldIndex, OUT PCWSTR *Data)
Definition: infsupp.c:42
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Reserved_ ULONG _In_opt_ PUNICODE_STRING _In_ ULONG _Out_opt_ PULONG Disposition
Definition: cmfuncs.h:56
@ PlugPlayControlStartDevice
Definition: cmtypes.h:213
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 REG_CREATED_NEW_KEY
Definition: nt_native.h:1084
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define REG_DWORD
Definition: sdbapi.c:596
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
_Must_inspect_result_ _In_ WDFDRIVER Driver
Definition: wdfcontrol.h:83
#define SERVICE_KERNEL_DRIVER
Definition: cmtypes.h:953
__wchar_t WCHAR
Definition: xmlstorage.h:180

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
505Quit:
506 if (PnpEvent)
507 RtlFreeHeap(ProcessHeap, 0, PnpEvent);
508
510 return Status;
511}
#define InsertTailList(ListHead, Entry)
GLenum GLsizei len
Definition: glext.h:6722
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE, ULONG, PVOID, SIZE_T)
Definition: heap.c:2667
@ PlugPlayControlUserResponse
Definition: cmtypes.h:216
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
NTSTATUS NTAPI NtGetPlugPlayEvent(IN ULONG Reserved1, IN ULONG Reserved2, OUT PPLUGPLAY_EVENT_BLOCK Buffer, IN ULONG BufferSize)
Definition: plugplay.c:1364
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
struct _PLUGPLAY_EVENT_BLOCK::@2393::@2396 TargetDevice
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NtCurrentThread()

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 }
703
704 /* Kill the device installation thread */
706 {
709 }
711
712 /* Close the opened handles */
713
714 if (hServicesKey)
717
718 if (hEnumKey)
720 hEnumKey = NULL;
721
725
729}
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.

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