3 * Copyright (C) 2005 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS kernel
22 * FILE: services/umpnpmgr/umpnpmgr.c
23 * PURPOSE: User-mode Plug and Play manager
24 * PROGRAMMER: Eric Kohl
25 * Hervé Poussineau (hpoussin@reactos.org)
26 * Colin Finck (colin@reactos.org)
29 /* INCLUDES *****************************************************************/
30 //#define HAVE_SLIST_ENTRY_IMPLEMENTED
31 #define WIN32_NO_STATUS
38 #include <umpnpmgr/sysguid.h>
52 /* GLOBALS ******************************************************************/
55 ServiceMain(DWORD argc
, LPTSTR
*argv
);
57 static SERVICE_TABLE_ENTRY ServiceTable
[2] =
59 {TEXT("PlugPlay"), ServiceMain
},
63 static WCHAR szRootDeviceId
[] = L
"HTREE\\ROOT\\0";
65 static HKEY hEnumKey
= NULL
;
66 static HKEY hClassKey
= NULL
;
68 static HANDLE hUserToken
= NULL
;
69 static HANDLE hInstallEvent
= NULL
;
70 static HANDLE hNoPendingInstalls
= NULL
;
72 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
73 static SLIST_HEADER DeviceInstallListHead
;
75 static LIST_ENTRY DeviceInstallListHead
;
77 static HANDLE hDeviceInstallListNotEmpty
;
81 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
82 SLIST_ENTRY ListEntry
;
87 } DeviceInstallParams
;
89 /* FUNCTIONS *****************************************************************/
92 RpcServerThread(LPVOID lpParameter
)
96 UNREFERENCED_PARAMETER(lpParameter
);
98 DPRINT("RpcServerThread() called\n");
100 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
103 NULL
); // Security descriptor
104 if (Status
!= RPC_S_OK
)
106 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
110 Status
= RpcServerRegisterIf(pnp_v1_0_s_ifspec
,
113 if (Status
!= RPC_S_OK
)
115 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
119 Status
= RpcServerListen(1,
122 if (Status
!= RPC_S_OK
)
124 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
128 /* ROS HACK (this should never happen...) */
129 DPRINT1("*** Other devices won't be installed correctly. If something\n");
130 DPRINT1("*** doesn't work, try to reboot to get a new chance.\n");
132 DPRINT("RpcServerThread() done\n");
138 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
140 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
144 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
146 HeapFree(GetProcessHeap(), 0, ptr
);
150 static CONFIGRET WINAPI
151 NtStatusToCrError(NTSTATUS Status
)
155 case STATUS_NO_SUCH_DEVICE
:
156 return CR_NO_SUCH_DEVINST
;
159 /* FIXME: add more mappings */
160 DPRINT1("Unable to map status 0x%08lx\n", Status
);
167 DWORD
PNP_Disconnect(
170 UNREFERENCED_PARAMETER(hBinding
);
172 return CR_CALL_NOT_IMPLEMENTED
;
180 UNREFERENCED_PARAMETER(hBinding
);
182 return CR_CALL_NOT_IMPLEMENTED
;
187 DWORD
PNP_GetVersion(
191 UNREFERENCED_PARAMETER(hBinding
);
199 DWORD
PNP_GetGlobalState(
204 UNREFERENCED_PARAMETER(hBinding
);
205 UNREFERENCED_PARAMETER(ulFlags
);
207 *pulState
= CM_GLOBAL_STATE_CAN_DO_UI
| CM_GLOBAL_STATE_SERVICES_AVAILABLE
;
213 DWORD
PNP_InitDetection(
216 UNREFERENCED_PARAMETER(hBinding
);
218 DPRINT("PNP_InitDetection() called\n");
224 DWORD
PNP_ReportLogOn(
229 DWORD ReturnValue
= CR_FAILURE
;
232 UNREFERENCED_PARAMETER(hBinding
);
233 UNREFERENCED_PARAMETER(Admin
);
235 DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin
, ProcessId
);
237 /* Get the users token */
238 hProcess
= OpenProcess(PROCESS_ALL_ACCESS
, TRUE
, ProcessId
);
242 DPRINT1("OpenProcess failed with error %u\n", GetLastError());
248 CloseHandle(hUserToken
);
252 if(!OpenProcessToken(hProcess
, TOKEN_ASSIGN_PRIMARY
| TOKEN_DUPLICATE
| TOKEN_QUERY
, &hUserToken
))
254 DPRINT1("OpenProcessToken failed with error %u\n", GetLastError());
258 /* Trigger the installer thread */
260 SetEvent(hInstallEvent
);
262 ReturnValue
= CR_SUCCESS
;
266 CloseHandle(hProcess
);
273 DWORD
PNP_ValidateDeviceInstance(
278 CONFIGRET ret
= CR_SUCCESS
;
279 HKEY hDeviceKey
= NULL
;
281 UNREFERENCED_PARAMETER(hBinding
);
282 UNREFERENCED_PARAMETER(ulFlags
);
284 DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
287 if (RegOpenKeyExW(hEnumKey
,
293 DPRINT("Could not open the Device Key!\n");
294 ret
= CR_NO_SUCH_DEVNODE
;
298 /* FIXME: add more tests */
301 if (hDeviceKey
!= NULL
)
302 RegCloseKey(hDeviceKey
);
304 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret
);
311 DWORD
PNP_GetRootDeviceInstance(
314 PNP_RPC_STRING_LEN ulLength
)
316 CONFIGRET ret
= CR_SUCCESS
;
318 UNREFERENCED_PARAMETER(hBinding
);
320 DPRINT("PNP_GetRootDeviceInstance() called\n");
324 ret
= CR_INVALID_POINTER
;
327 if (ulLength
< lstrlenW(szRootDeviceId
) + 1)
329 ret
= CR_BUFFER_SMALL
;
337 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret
);
344 DWORD
PNP_GetRelatedDeviceInstance(
346 DWORD ulRelationship
,
348 LPWSTR pRelatedDeviceId
,
349 PNP_RPC_STRING_LEN
*pulLength
,
352 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData
;
353 CONFIGRET ret
= CR_SUCCESS
;
356 UNREFERENCED_PARAMETER(hBinding
);
357 UNREFERENCED_PARAMETER(ulFlags
);
359 DPRINT("PNP_GetRelatedDeviceInstance() called\n");
360 DPRINT(" Relationship %ld\n", ulRelationship
);
361 DPRINT(" DeviceId %S\n", pDeviceID
);
363 RtlInitUnicodeString(&PlugPlayData
.TargetDeviceInstance
,
366 PlugPlayData
.Relation
= ulRelationship
;
368 PlugPlayData
.RelatedDeviceInstanceLength
= *pulLength
;
369 PlugPlayData
.RelatedDeviceInstance
= pRelatedDeviceId
;
371 Status
= NtPlugPlayControl(PlugPlayControlGetRelatedDevice
,
372 (PVOID
)&PlugPlayData
,
373 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA
));
374 if (!NT_SUCCESS(Status
))
376 ret
= NtStatusToCrError(Status
);
379 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret
);
380 if (ret
== CR_SUCCESS
)
382 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData
.RelatedDeviceInstance
);
390 DWORD
PNP_EnumerateSubKeys(
395 PNP_RPC_STRING_LEN ulLength
,
396 PNP_RPC_STRING_LEN
*pulRequiredLen
,
399 CONFIGRET ret
= CR_SUCCESS
;
403 UNREFERENCED_PARAMETER(hBinding
);
404 UNREFERENCED_PARAMETER(ulFlags
);
406 DPRINT("PNP_EnumerateSubKeys() called\n");
410 case PNP_ENUMERATOR_SUBKEYS
:
414 case PNP_CLASS_SUBKEYS
:
422 *pulRequiredLen
= ulLength
;
423 dwError
= RegEnumKeyExW(hKey
,
431 if (dwError
!= ERROR_SUCCESS
)
433 ret
= (dwError
== ERROR_NO_MORE_ITEMS
) ? CR_NO_SUCH_VALUE
: CR_FAILURE
;
440 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret
);
447 DWORD
PNP_GetDeviceList(
451 PNP_RPC_STRING_LEN
*pulLength
,
455 return CR_CALL_NOT_IMPLEMENTED
;
460 DWORD
PNP_GetDeviceListSize(
463 PNP_RPC_BUFFER_SIZE
*pulLen
,
467 return CR_CALL_NOT_IMPLEMENTED
;
478 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData
;
479 CONFIGRET ret
= CR_SUCCESS
;
482 UNREFERENCED_PARAMETER(hBinding
);
483 UNREFERENCED_PARAMETER(ulFlags
);
485 DPRINT("PNP_GetDepth() called\n");
487 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
490 Status
= NtPlugPlayControl(PlugPlayControlGetDeviceDepth
,
491 (PVOID
)&PlugPlayData
,
492 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA
));
493 if (NT_SUCCESS(Status
))
495 *pulDepth
= PlugPlayData
.Depth
;
499 ret
= NtStatusToCrError(Status
);
502 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret
);
509 DWORD
PNP_GetDeviceRegProp(
513 DWORD
*pulRegDataType
,
515 PNP_PROP_SIZE
*pulTransferLen
,
516 PNP_PROP_SIZE
*pulLength
,
519 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData
;
520 CONFIGRET ret
= CR_SUCCESS
;
521 LPWSTR lpValueName
= NULL
;
525 UNREFERENCED_PARAMETER(hBinding
);
526 UNREFERENCED_PARAMETER(ulFlags
);
528 DPRINT("PNP_GetDeviceRegProp() called\n");
532 case CM_DRP_DEVICEDESC
:
533 lpValueName
= L
"DeviceDesc";
536 case CM_DRP_HARDWAREID
:
537 lpValueName
= L
"HardwareID";
540 case CM_DRP_COMPATIBLEIDS
:
541 lpValueName
= L
"CompatibleIDs";
545 lpValueName
= L
"Service";
549 lpValueName
= L
"Class";
552 case CM_DRP_CLASSGUID
:
553 lpValueName
= L
"ClassGUID";
557 lpValueName
= L
"Driver";
560 case CM_DRP_CONFIGFLAGS
:
561 lpValueName
= L
"ConfigFlags";
565 lpValueName
= L
"Mfg";
568 case CM_DRP_FRIENDLYNAME
:
569 lpValueName
= L
"FriendlyName";
572 case CM_DRP_LOCATION_INFORMATION
:
573 lpValueName
= L
"LocationInformation";
576 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME
:
580 case CM_DRP_CAPABILITIES
:
581 lpValueName
= L
"Capabilities";
584 case CM_DRP_UI_NUMBER
:
588 case CM_DRP_UPPERFILTERS
:
589 lpValueName
= L
"UpperFilters";
592 case CM_DRP_LOWERFILTERS
:
593 lpValueName
= L
"LowerFilters";
596 case CM_DRP_BUSTYPEGUID
:
600 case CM_DRP_LEGACYBUSTYPE
:
604 case CM_DRP_BUSNUMBER
:
608 case CM_DRP_ENUMERATOR_NAME
:
613 return CR_INVALID_PROPERTY
;
616 DPRINT("Value name: %S\n", lpValueName
);
620 /* Retrieve information from the Registry */
621 if (RegOpenKeyExW(hEnumKey
,
626 return CR_INVALID_DEVNODE
;
628 if (RegQueryValueExW(hKey
,
634 ret
= CR_REGISTRY_ERROR
;
636 /* FIXME: Check buffer size */
642 /* Retrieve information from the Device Node */
643 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
645 PlugPlayData
.Buffer
= Buffer
;
646 PlugPlayData
.BufferSize
= *pulTransferLen
;
651 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME
:
652 PlugPlayData
.Property
= DevicePropertyPhysicalDeviceObjectName
;
655 case CM_DRP_UI_NUMBER
:
656 PlugPlayData
.Property
= DevicePropertyUINumber
;
659 case CM_DRP_BUSTYPEGUID
:
660 PlugPlayData
.Property
= DevicePropertyBusTypeGuid
;
663 case CM_DRP_LEGACYBUSTYPE
:
664 PlugPlayData
.Property
= DevicePropertyLegacyBusType
;
667 case CM_DRP_BUSNUMBER
:
668 PlugPlayData
.Property
= DevicePropertyBusNumber
;
671 case CM_DRP_ENUMERATOR_NAME
:
672 PlugPlayData
.Property
= DevicePropertyEnumeratorName
;
677 return CR_INVALID_PROPERTY
;
680 Status
= NtPlugPlayControl(PlugPlayControlProperty
,
681 (PVOID
)&PlugPlayData
,
682 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA
));
683 if (NT_SUCCESS(Status
))
685 *pulLength
= PlugPlayData
.BufferSize
;
689 ret
= NtStatusToCrError(Status
);
693 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret
);
700 DWORD
PNP_SetDeviceRegProp(
706 PNP_PROP_SIZE ulLength
,
709 CONFIGRET ret
= CR_SUCCESS
;
710 LPWSTR lpValueName
= NULL
;
713 UNREFERENCED_PARAMETER(hBinding
);
714 UNREFERENCED_PARAMETER(ulFlags
);
716 DPRINT("PNP_SetDeviceRegProp() called\n");
718 DPRINT("DeviceId: %S\n", pDeviceId
);
719 DPRINT("Property: %lu\n", ulProperty
);
720 DPRINT("DataType: %lu\n", ulDataType
);
721 DPRINT("Length: %lu\n", ulLength
);
725 case CM_DRP_DEVICEDESC
:
726 lpValueName
= L
"DeviceDesc";
729 case CM_DRP_HARDWAREID
:
730 lpValueName
= L
"HardwareID";
733 case CM_DRP_COMPATIBLEIDS
:
734 lpValueName
= L
"CompatibleIDs";
738 lpValueName
= L
"Service";
742 lpValueName
= L
"Class";
745 case CM_DRP_CLASSGUID
:
746 lpValueName
= L
"ClassGUID";
750 lpValueName
= L
"Driver";
753 case CM_DRP_CONFIGFLAGS
:
754 lpValueName
= L
"ConfigFlags";
758 lpValueName
= L
"Mfg";
761 case CM_DRP_FRIENDLYNAME
:
762 lpValueName
= L
"FriendlyName";
765 case CM_DRP_LOCATION_INFORMATION
:
766 lpValueName
= L
"LocationInformation";
769 case CM_DRP_UPPERFILTERS
:
770 lpValueName
= L
"UpperFilters";
773 case CM_DRP_LOWERFILTERS
:
774 lpValueName
= L
"LowerFilters";
778 return CR_INVALID_PROPERTY
;
781 DPRINT("Value name: %S\n", lpValueName
);
783 if (RegOpenKeyExW(hEnumKey
,
786 KEY_ALL_ACCESS
, /* FIXME: so much? */
788 return CR_INVALID_DEVNODE
;
792 if (RegDeleteValueW(hKey
,
794 ret
= CR_REGISTRY_ERROR
;
798 if (RegSetValueExW(hKey
,
804 ret
= CR_REGISTRY_ERROR
;
809 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret
);
816 DWORD
PNP_GetClassInstance(
819 LPWSTR pszClassInstance
,
820 PNP_RPC_STRING_LEN ulLength
)
823 return CR_CALL_NOT_IMPLEMENTED
;
835 return CR_CALL_NOT_IMPLEMENTED
;
840 DWORD
PNP_DeleteRegistryKey(
848 return CR_CALL_NOT_IMPLEMENTED
;
853 DWORD
PNP_GetClassCount(
855 DWORD
*pulClassCount
,
861 UNREFERENCED_PARAMETER(hBinding
);
862 UNREFERENCED_PARAMETER(ulFlags
);
864 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
869 if (dwError
!= ERROR_SUCCESS
)
870 return CR_INVALID_DATA
;
872 dwError
= RegQueryInfoKeyW(hKey
,
885 if (dwError
!= ERROR_SUCCESS
)
886 return CR_INVALID_DATA
;
893 DWORD
PNP_GetClassName(
897 PNP_RPC_STRING_LEN
*pulLength
,
900 WCHAR szKeyName
[MAX_PATH
];
901 CONFIGRET ret
= CR_SUCCESS
;
905 UNREFERENCED_PARAMETER(hBinding
);
906 UNREFERENCED_PARAMETER(ulFlags
);
908 DPRINT("PNP_GetClassName() called\n");
910 lstrcpyW(szKeyName
, L
"System\\CurrentControlSet\\Control\\Class\\");
911 if(lstrlenW(pszClassGuid
) + 1 < sizeof(szKeyName
)/sizeof(WCHAR
)-(lstrlenW(szKeyName
) * sizeof(WCHAR
)))
912 lstrcatW(szKeyName
, pszClassGuid
);
913 else return CR_INVALID_DATA
;
915 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
920 return CR_REGISTRY_ERROR
;
922 dwSize
= *pulLength
* sizeof(WCHAR
);
923 if (RegQueryValueExW(hKey
,
931 ret
= CR_REGISTRY_ERROR
;
935 *pulLength
= dwSize
/ sizeof(WCHAR
);
940 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret
);
947 DWORD
PNP_DeleteClassKey(
952 CONFIGRET ret
= CR_SUCCESS
;
954 UNREFERENCED_PARAMETER(hBinding
);
956 DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid
, ulFlags
);
958 if (ulFlags
& CM_DELETE_CLASS_SUBKEYS
)
960 if (RegDeleteTreeW(hClassKey
, pszClassGuid
) != ERROR_SUCCESS
)
961 ret
= CR_REGISTRY_ERROR
;
965 if (RegDeleteKeyW(hClassKey
, pszClassGuid
) != ERROR_SUCCESS
)
966 ret
= CR_REGISTRY_ERROR
;
969 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret
);
976 DWORD
PNP_GetInterfaceDeviceAlias(
978 LPWSTR pszInterfaceDevice
,
979 GUID
*AliasInterfaceGuid
,
980 LPWSTR pszAliasInterfaceDevice
,
981 PNP_RPC_STRING_LEN
*pulLength
,
982 PNP_RPC_STRING_LEN
*pulTransferLen
,
986 return CR_CALL_NOT_IMPLEMENTED
;
991 DWORD
PNP_GetInterfaceDeviceList(
996 PNP_RPC_BUFFER_SIZE
*pulLength
,
1000 return CR_CALL_NOT_IMPLEMENTED
;
1005 DWORD
PNP_GetInterfaceDeviceListSize(
1007 PNP_RPC_BUFFER_SIZE
*pulLen
,
1008 GUID
*InterfaceGuid
,
1013 return CR_CALL_NOT_IMPLEMENTED
;
1018 DWORD
PNP_RegisterDeviceClassAssociation(
1021 GUID
*InterfaceGuid
,
1022 LPWSTR pszReference
,
1024 PNP_RPC_STRING_LEN
*pulLength
,
1025 PNP_RPC_STRING_LEN
*pulTransferLen
,
1029 return CR_CALL_NOT_IMPLEMENTED
;
1034 DWORD
PNP_UnregisterDeviceClassAssociation(
1036 LPWSTR pszInterfaceDevice
,
1040 return CR_CALL_NOT_IMPLEMENTED
;
1045 DWORD
PNP_GetClassRegProp(
1047 LPWSTR pszClassGuid
,
1049 DWORD
*pulRegDataType
,
1051 PNP_RPC_STRING_LEN
*pulTransferLen
,
1052 PNP_RPC_STRING_LEN
*pulLength
,
1056 return CR_CALL_NOT_IMPLEMENTED
;
1061 DWORD
PNP_SetClassRegProp(
1063 LPWSTR
*pszClassGuid
,
1067 PNP_PROP_SIZE ulLength
,
1071 return CR_CALL_NOT_IMPLEMENTED
;
1076 DWORD
PNP_CreateDevInst(
1079 LPWSTR pszParentDeviceID
,
1080 PNP_RPC_STRING_LEN ulLength
,
1084 return CR_CALL_NOT_IMPLEMENTED
;
1089 DWORD
PNP_DeviceInstanceAction(
1091 DWORD ulMajorAction
,
1092 DWORD ulMinorAction
,
1093 LPWSTR pszDeviceInstance1
,
1094 LPWSTR pszDeviceInstance2
)
1096 CONFIGRET ret
= CR_SUCCESS
;
1099 UNREFERENCED_PARAMETER(hBinding
);
1100 UNREFERENCED_PARAMETER(ulMinorAction
);
1101 UNREFERENCED_PARAMETER(pszDeviceInstance2
);
1103 DPRINT("PNP_DeviceInstanceAction() called\n");
1105 switch (ulMajorAction
)
1107 case PNP_DEVINST_SETUP
:
1108 DPRINT("Setup device instance\n");
1110 ret
= CR_CALL_NOT_IMPLEMENTED
;
1113 case PNP_DEVINST_ENABLE
:
1115 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
1116 DPRINT("Enable device instance\n");
1117 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, pszDeviceInstance1
);
1118 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
1119 if (!NT_SUCCESS(Status
))
1120 ret
= NtStatusToCrError(Status
);
1124 case PNP_DEVINST_REENUMERATE
:
1125 DPRINT("Reenumerate device instance\n");
1127 ret
= CR_CALL_NOT_IMPLEMENTED
;
1131 DPRINT1("Unknown function %lu\n", ulMajorAction
);
1132 ret
= CR_CALL_NOT_IMPLEMENTED
;
1135 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret
);
1142 DWORD
PNP_GetDeviceStatus(
1149 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData
;
1150 CONFIGRET ret
= CR_SUCCESS
;
1153 UNREFERENCED_PARAMETER(hBinding
);
1154 UNREFERENCED_PARAMETER(ulFlags
);
1156 DPRINT("PNP_GetDeviceStatus() called\n");
1158 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
1160 PlugPlayData
.Operation
= 0; /* Get status */
1162 Status
= NtPlugPlayControl(PlugPlayControlDeviceStatus
,
1163 (PVOID
)&PlugPlayData
,
1164 sizeof(PLUGPLAY_CONTROL_STATUS_DATA
));
1165 if (NT_SUCCESS(Status
))
1167 *pulStatus
= PlugPlayData
.DeviceStatus
;
1168 *pulProblem
= PlugPlayData
.DeviceProblem
;
1172 ret
= NtStatusToCrError(Status
);
1175 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret
);
1182 DWORD
PNP_SetDeviceProblem(
1189 return CR_CALL_NOT_IMPLEMENTED
;
1194 DWORD
PNP_DisableDevInst(
1197 PPNP_VETO_TYPE pVetoType
,
1203 return CR_CALL_NOT_IMPLEMENTED
;
1207 DWORD
PNP_UninstallDevInst(
1213 return CR_CALL_NOT_IMPLEMENTED
;
1218 CheckForDeviceId(LPWSTR lpDeviceIdList
,
1224 lpPtr
= lpDeviceIdList
;
1227 dwLength
= wcslen(lpPtr
);
1228 if (0 == _wcsicmp(lpPtr
, lpDeviceId
))
1231 lpPtr
+= (dwLength
+ 1);
1239 AppendDeviceId(LPWSTR lpDeviceIdList
,
1240 LPDWORD lpDeviceIdListSize
,
1246 dwLen
= wcslen(lpDeviceId
);
1247 dwPos
= (*lpDeviceIdListSize
/ sizeof(WCHAR
)) - 1;
1249 wcscpy(&lpDeviceIdList
[dwPos
], lpDeviceId
);
1251 dwPos
+= (dwLen
+ 1);
1253 lpDeviceIdList
[dwPos
] = 0;
1255 *lpDeviceIdListSize
= dwPos
* sizeof(WCHAR
);
1266 CONFIGRET ret
= CR_SUCCESS
;
1269 DWORD dwDeviceIdListSize
;
1270 DWORD dwNewDeviceIdSize
;
1271 WCHAR
* pszDeviceIdList
= NULL
;
1273 UNREFERENCED_PARAMETER(hBinding
);
1275 DPRINT("PNP_AddID() called\n");
1276 DPRINT(" DeviceInstance: %S\n", pszDeviceID
);
1277 DPRINT(" DeviceId: %S\n", pszID
);
1278 DPRINT(" Flags: %lx\n", ulFlags
);
1280 if (RegOpenKeyExW(hEnumKey
,
1283 KEY_QUERY_VALUE
| KEY_SET_VALUE
,
1284 &hDeviceKey
) != ERROR_SUCCESS
)
1286 DPRINT("Failed to open the device key!\n");
1287 return CR_INVALID_DEVNODE
;
1290 pszSubKey
= (ulFlags
& CM_ADD_ID_COMPATIBLE
) ? L
"CompatibleIDs" : L
"HardwareID";
1292 if (RegQueryValueExW(hDeviceKey
,
1297 &dwDeviceIdListSize
) != ERROR_SUCCESS
)
1299 DPRINT("Failed to query the desired ID string!\n");
1300 ret
= CR_REGISTRY_ERROR
;
1304 dwNewDeviceIdSize
= lstrlenW(pszDeviceID
);
1305 if (!dwNewDeviceIdSize
)
1307 ret
= CR_INVALID_POINTER
;
1311 dwDeviceIdListSize
+= (dwNewDeviceIdSize
+ 2) * sizeof(WCHAR
);
1313 pszDeviceIdList
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDeviceIdListSize
);
1314 if (!pszDeviceIdList
)
1316 DPRINT("Failed to allocate memory for the desired ID string!\n");
1317 ret
= CR_OUT_OF_MEMORY
;
1321 if (RegQueryValueExW(hDeviceKey
,
1325 (LPBYTE
)pszDeviceIdList
,
1326 &dwDeviceIdListSize
) != ERROR_SUCCESS
)
1328 DPRINT("Failed to query the desired ID string!\n");
1329 ret
= CR_REGISTRY_ERROR
;
1333 /* Check whether the device ID is already in use */
1334 if (CheckForDeviceId(pszDeviceIdList
, pszDeviceID
))
1336 DPRINT("Device ID was found in the ID string!\n");
1341 /* Append the Device ID */
1342 AppendDeviceId(pszDeviceIdList
, &dwDeviceIdListSize
, pszID
);
1344 if (RegSetValueExW(hDeviceKey
,
1348 (LPBYTE
)pszDeviceIdList
,
1349 dwDeviceIdListSize
) != ERROR_SUCCESS
)
1351 DPRINT("Failed to set the desired ID string!\n");
1352 ret
= CR_REGISTRY_ERROR
;
1356 RegCloseKey(hDeviceKey
);
1357 if (pszDeviceIdList
)
1358 HeapFree(GetProcessHeap(), 0, pszDeviceIdList
);
1360 DPRINT("PNP_AddID() done (returns %lx)\n", ret
);
1367 DWORD
PNP_RegisterDriver(
1373 return CR_CALL_NOT_IMPLEMENTED
;
1378 DWORD
PNP_QueryRemove(
1381 PPNP_VETO_TYPE pVetoType
,
1387 return CR_CALL_NOT_IMPLEMENTED
;
1392 DWORD
PNP_RequestDeviceEject(
1395 PPNP_VETO_TYPE pVetoType
,
1401 return CR_CALL_NOT_IMPLEMENTED
;
1406 PNP_IsDockStationPresent(handle_t hBinding
,
1413 CONFIGRET ret
= CR_SUCCESS
;
1415 UNREFERENCED_PARAMETER(hBinding
);
1417 DPRINT1("PNP_IsDockStationPresent() called\n");
1421 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG
,
1425 &hKey
) != ERROR_SUCCESS
)
1426 return CR_REGISTRY_ERROR
;
1428 dwSize
= sizeof(DWORD
);
1429 if (RegQueryValueExW(hKey
,
1434 &dwSize
) != ERROR_SUCCESS
)
1435 ret
= CR_REGISTRY_ERROR
;
1439 if (ret
== CR_SUCCESS
)
1441 if (dwType
!= REG_DWORD
|| dwSize
!= sizeof(DWORD
))
1443 ret
= CR_REGISTRY_ERROR
;
1445 else if (dwValue
!= 0)
1451 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret
);
1458 DWORD
PNP_RequestEjectPC(
1462 return CR_CALL_NOT_IMPLEMENTED
;
1467 DWORD
PNP_HwProfFlags(
1473 PPNP_VETO_TYPE pVetoType
,
1479 return CR_CALL_NOT_IMPLEMENTED
;
1484 DWORD
PNP_GetHwProfInfo(
1487 HWPROFILEINFO
*pHWProfileInfo
,
1488 DWORD ulProfileInfoSize
,
1492 return CR_CALL_NOT_IMPLEMENTED
;
1497 DWORD
PNP_AddEmptyLogConf(
1501 DWORD
*pulLogConfTag
,
1505 return CR_CALL_NOT_IMPLEMENTED
;
1510 DWORD
PNP_FreeLogConf(
1513 DWORD ulLogConfType
,
1518 return CR_CALL_NOT_IMPLEMENTED
;
1523 DWORD
PNP_GetFirstLogConf(
1526 DWORD ulLogConfType
,
1527 DWORD
*pulLogConfTag
,
1531 return CR_CALL_NOT_IMPLEMENTED
;
1536 DWORD
PNP_GetNextLogConf(
1539 DWORD ulLogConfType
,
1545 return CR_CALL_NOT_IMPLEMENTED
;
1550 DWORD
PNP_GetLogConfPriority(
1559 return CR_CALL_NOT_IMPLEMENTED
;
1564 DWORD
PNP_AddResDes(
1568 DWORD ulLogConfType
,
1569 RESOURCEID ResourceID
,
1570 DWORD
*pulResourceTag
,
1572 PNP_RPC_BUFFER_SIZE ResourceLen
,
1576 return CR_CALL_NOT_IMPLEMENTED
;
1581 DWORD
PNP_FreeResDes(
1585 DWORD ulLogConfType
,
1586 RESOURCEID ResourceID
,
1587 DWORD ulResourceTag
,
1588 DWORD
*pulPreviousResType
,
1589 DWORD
*pulPreviousResTag
,
1593 return CR_CALL_NOT_IMPLEMENTED
;
1598 DWORD
PNP_GetNextResDes(
1602 DWORD ulLogConfType
,
1603 RESOURCEID ResourceID
,
1604 DWORD ulResourceTag
,
1605 DWORD
*pulNextResType
,
1606 DWORD
*pulNextResTag
,
1610 return CR_CALL_NOT_IMPLEMENTED
;
1615 DWORD
PNP_GetResDesData(
1619 DWORD ulLogConfType
,
1620 RESOURCEID ResourceID
,
1621 DWORD ulResourceTag
,
1623 PNP_RPC_BUFFER_SIZE BufferLen
,
1627 return CR_CALL_NOT_IMPLEMENTED
;
1632 DWORD
PNP_GetResDesDataSize(
1636 DWORD ulLogConfType
,
1637 RESOURCEID ResourceID
,
1638 DWORD ulResourceTag
,
1643 return CR_CALL_NOT_IMPLEMENTED
;
1648 DWORD
PNP_ModifyResDes(
1652 DWORD ulLogConfType
,
1653 RESOURCEID CurrentResourceID
,
1654 RESOURCEID NewResourceID
,
1655 DWORD ulResourceTag
,
1657 PNP_RPC_BUFFER_SIZE ResourceLen
,
1661 return CR_CALL_NOT_IMPLEMENTED
;
1666 DWORD
PNP_DetectResourceConflict(
1669 RESOURCEID ResourceID
,
1671 PNP_RPC_BUFFER_SIZE ResourceLen
,
1672 BOOL
*pbConflictDetected
,
1676 return CR_CALL_NOT_IMPLEMENTED
;
1681 DWORD
PNP_QueryResConfList(
1684 RESOURCEID ResourceID
,
1686 PNP_RPC_BUFFER_SIZE ResourceLen
,
1688 PNP_RPC_BUFFER_SIZE BufferLen
,
1692 return CR_CALL_NOT_IMPLEMENTED
;
1697 DWORD
PNP_SetHwProf(
1701 return CR_CALL_NOT_IMPLEMENTED
;
1706 DWORD
PNP_QueryArbitratorFreeData(
1710 return CR_CALL_NOT_IMPLEMENTED
;
1715 DWORD
PNP_QueryArbitratorFreeSize(
1719 return CR_CALL_NOT_IMPLEMENTED
;
1730 return CR_CALL_NOT_IMPLEMENTED
;
1735 DWORD
PNP_RegisterNotification(
1739 return CR_CALL_NOT_IMPLEMENTED
;
1744 DWORD
PNP_UnregisterNotification(
1748 return CR_CALL_NOT_IMPLEMENTED
;
1753 DWORD
PNP_GetCustomDevProp(
1756 LPWSTR CustomPropName
,
1757 DWORD
*pulRegDataType
,
1759 PNP_RPC_STRING_LEN
*pulTransferLen
,
1760 PNP_RPC_STRING_LEN
*pulLength
,
1764 return CR_CALL_NOT_IMPLEMENTED
;
1769 DWORD
PNP_GetVersionInternal(
1774 return CR_CALL_NOT_IMPLEMENTED
;
1779 DWORD
PNP_GetBlockedDriverInfo(
1782 PNP_RPC_BUFFER_SIZE
*pulTransferLen
,
1783 PNP_RPC_BUFFER_SIZE
*pulLength
,
1787 return CR_CALL_NOT_IMPLEMENTED
;
1792 DWORD
PNP_GetServerSideDeviceInstallFlags(
1794 DWORD
*pulSSDIFlags
,
1798 return CR_CALL_NOT_IMPLEMENTED
;
1803 DWORD
PNP_GetObjectPropKeys(
1807 LPWSTR PropertyCultureName
,
1808 PNP_PROP_COUNT
*PropertyCount
,
1809 PNP_PROP_COUNT
*TransferLen
,
1810 DEVPROPKEY
*PropertyKeys
,
1814 return CR_CALL_NOT_IMPLEMENTED
;
1819 DWORD
PNP_GetObjectProp(
1823 LPWSTR PropertyCultureName
,
1824 const DEVPROPKEY
*PropertyKey
,
1825 DEVPROPTYPE
*PropertyType
,
1826 PNP_PROP_SIZE
*PropertySize
,
1827 PNP_PROP_SIZE
*TransferLen
,
1828 BYTE
*PropertyBuffer
,
1832 return CR_CALL_NOT_IMPLEMENTED
;
1837 DWORD
PNP_SetObjectProp(
1841 LPWSTR PropertyCultureName
,
1842 const DEVPROPKEY
*PropertyKey
,
1843 DEVPROPTYPE PropertyType
,
1844 PNP_PROP_SIZE PropertySize
,
1845 BYTE
*PropertyBuffer
,
1849 return CR_CALL_NOT_IMPLEMENTED
;
1854 DWORD
PNP_InstallDevInst(
1858 return CR_CALL_NOT_IMPLEMENTED
;
1863 DWORD
PNP_ApplyPowerSettings(
1867 return CR_CALL_NOT_IMPLEMENTED
;
1872 DWORD
PNP_DriverStoreAddDriverPackage(
1876 return CR_CALL_NOT_IMPLEMENTED
;
1881 DWORD
PNP_DriverStoreDeleteDriverPackage(
1885 return CR_CALL_NOT_IMPLEMENTED
;
1890 DWORD
PNP_RegisterServiceNotification(
1894 return CR_CALL_NOT_IMPLEMENTED
;
1899 DWORD
PNP_SetActiveService(
1903 return CR_CALL_NOT_IMPLEMENTED
;
1908 DWORD
PNP_DeleteServiceDevices(
1912 return CR_CALL_NOT_IMPLEMENTED
;
1917 InstallDevice(PCWSTR DeviceInstance
, BOOL ShowWizard
)
1919 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData
;
1921 BOOL DeviceInstalled
= FALSE
;
1924 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
1925 LPVOID Environment
= NULL
;
1926 PROCESS_INFORMATION ProcessInfo
;
1927 STARTUPINFOW StartupInfo
;
1930 /* The following lengths are constant (see below), they cannot overflow */
1931 WCHAR CommandLine
[116];
1932 WCHAR InstallEventName
[73];
1934 WCHAR UuidString
[39];
1936 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance
, ShowWizard
);
1938 ZeroMemory(&ProcessInfo
, sizeof(ProcessInfo
));
1940 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
1942 PlugPlayData
.Operation
= 0; /* Get status */
1944 /* Get device status */
1945 Status
= NtPlugPlayControl(PlugPlayControlDeviceStatus
,
1946 (PVOID
)&PlugPlayData
,
1947 sizeof(PLUGPLAY_CONTROL_STATUS_DATA
));
1948 if (!NT_SUCCESS(Status
))
1950 DPRINT1("NtPlugPlayControl('%S') failed with status 0x%08lx\n", DeviceInstance
, Status
);
1954 if ((PlugPlayData
.DeviceStatus
& (DNF_STARTED
| DNF_START_FAILED
)) != 0)
1956 /* Device is already started, or disabled due to some problem. Don't install it */
1957 DPRINT("No need to install '%S'\n", DeviceInstance
);
1961 /* Create a random UUID for the named pipe */
1962 UuidCreate(&RandomUuid
);
1963 swprintf(UuidString
, L
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
1964 RandomUuid
.Data1
, RandomUuid
.Data2
, RandomUuid
.Data3
,
1965 RandomUuid
.Data4
[0], RandomUuid
.Data4
[1], RandomUuid
.Data4
[2],
1966 RandomUuid
.Data4
[3], RandomUuid
.Data4
[4], RandomUuid
.Data4
[5],
1967 RandomUuid
.Data4
[6], RandomUuid
.Data4
[7]);
1969 /* Create the named pipe */
1970 wcscpy(PipeName
, L
"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
1971 wcscat(PipeName
, UuidString
);
1972 hPipe
= CreateNamedPipeW(PipeName
, PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_BYTE
, 1, 512, 512, 0, NULL
);
1974 if(hPipe
== INVALID_HANDLE_VALUE
)
1976 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
1980 /* Launch rundll32 to call ClientSideInstallW */
1981 wcscpy(CommandLine
, L
"rundll32.exe newdev.dll,ClientSideInstall ");
1982 wcscat(CommandLine
, PipeName
);
1984 ZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
1985 StartupInfo
.cb
= sizeof(StartupInfo
);
1989 /* newdev has to run under the environment of the current user */
1990 if(!CreateEnvironmentBlock(&Environment
, hUserToken
, FALSE
))
1992 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
1996 if(!CreateProcessAsUserW(hUserToken
, NULL
, CommandLine
, NULL
, NULL
, FALSE
, CREATE_UNICODE_ENVIRONMENT
, Environment
, NULL
, &StartupInfo
, &ProcessInfo
))
1998 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
2004 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
2006 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
2007 (ShowWizard is only set to FALSE for these two modes) */
2008 ASSERT(!ShowWizard
);
2010 if(!CreateProcessW(NULL
, CommandLine
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &StartupInfo
, &ProcessInfo
))
2012 DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
2017 /* Wait for the function to connect to our pipe */
2018 if(!ConnectNamedPipe(hPipe
, NULL
))
2020 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
2024 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
2025 wcscpy(InstallEventName
, L
"Global\\PNP_Device_Install_Event_0.");
2026 wcscat(InstallEventName
, UuidString
);
2028 Value
= sizeof(InstallEventName
);
2029 WriteFile(hPipe
, &Value
, sizeof(Value
), &BytesWritten
, NULL
);
2030 WriteFile(hPipe
, InstallEventName
, Value
, &BytesWritten
, NULL
);
2032 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
2033 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
2034 WriteFile(hPipe
, &ShowWizard
, sizeof(ShowWizard
), &BytesWritten
, NULL
);
2036 Value
= (wcslen(DeviceInstance
) + 1) * sizeof(WCHAR
);
2037 WriteFile(hPipe
, &Value
, sizeof(Value
), &BytesWritten
, NULL
);
2038 WriteFile(hPipe
, DeviceInstance
, Value
, &BytesWritten
, NULL
);
2040 /* Wait for newdev.dll to finish processing */
2041 WaitForSingleObject(ProcessInfo
.hProcess
, INFINITE
);
2043 /* The following check for success is probably not compatible to Windows, but should do its job */
2044 if(!GetExitCodeProcess(ProcessInfo
.hProcess
, &Value
))
2046 DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
2050 DeviceInstalled
= Value
;
2053 if(hPipe
!= INVALID_HANDLE_VALUE
)
2057 DestroyEnvironmentBlock(Environment
);
2059 if(ProcessInfo
.hProcess
)
2060 CloseHandle(ProcessInfo
.hProcess
);
2062 if(ProcessInfo
.hThread
)
2063 CloseHandle(ProcessInfo
.hThread
);
2065 return DeviceInstalled
;
2081 return ERROR_INVALID_PARAMETER
;
2084 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, &dwType
, NULL
, &cbData
);
2085 if (rc
!= ERROR_SUCCESS
)
2087 if (dwType
!= REG_SZ
)
2088 return ERROR_FILE_NOT_FOUND
;
2089 Value
= HeapAlloc(GetProcessHeap(), 0, cbData
+ sizeof(WCHAR
));
2091 return ERROR_NOT_ENOUGH_MEMORY
;
2092 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, NULL
, (LPBYTE
)Value
, &cbData
);
2093 if (rc
!= ERROR_SUCCESS
)
2095 HeapFree(GetProcessHeap(), 0, Value
);
2098 /* NULL-terminate the string */
2099 Value
[cbData
/ sizeof(WCHAR
)] = '\0';
2102 return ERROR_SUCCESS
;
2110 DWORD regType
, active
, size
;
2114 rc
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\Setup", 0, KEY_QUERY_VALUE
, &hKey
);
2115 if (rc
!= ERROR_SUCCESS
)
2118 size
= sizeof(DWORD
);
2119 rc
= RegQueryValueExW(hKey
, L
"SystemSetupInProgress", NULL
, ®Type
, (LPBYTE
)&active
, &size
);
2120 if (rc
!= ERROR_SUCCESS
)
2122 if (regType
!= REG_DWORD
|| size
!= sizeof(DWORD
))
2125 ret
= (active
!= 0);
2131 DPRINT("System setup in progress? %S\n", ret
? L
"YES" : L
"NO");
2140 HKEY ControlKey
= NULL
;
2141 LPWSTR SystemStartOptions
= NULL
;
2142 LPWSTR CurrentOption
, NextOption
; /* Pointers into SystemStartOptions */
2143 BOOL ConsoleBoot
= FALSE
;
2148 L
"SYSTEM\\CurrentControlSet\\Control",
2153 rc
= ReadRegSzKey(ControlKey
, L
"SystemStartOptions", &SystemStartOptions
);
2154 if (rc
!= ERROR_SUCCESS
)
2157 /* Check for CMDCONS in SystemStartOptions */
2158 CurrentOption
= SystemStartOptions
;
2159 while (CurrentOption
)
2161 NextOption
= wcschr(CurrentOption
, L
' ');
2163 *NextOption
= L
'\0';
2164 if (_wcsicmp(CurrentOption
, L
"CONSOLE") == 0)
2166 DPRINT("Found %S. Switching to console boot\n", CurrentOption
);
2170 CurrentOption
= NextOption
? NextOption
+ 1 : NULL
;
2174 if (ControlKey
!= NULL
)
2175 RegCloseKey(ControlKey
);
2176 HeapFree(GetProcessHeap(), 0, SystemStartOptions
);
2181 /* Loop to install all queued devices installations */
2183 DeviceInstallThread(LPVOID lpParameter
)
2185 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2186 PSLIST_ENTRY ListEntry
;
2188 PLIST_ENTRY ListEntry
;
2190 DeviceInstallParams
* Params
;
2193 UNREFERENCED_PARAMETER(lpParameter
);
2195 WaitForSingleObject(hInstallEvent
, INFINITE
);
2197 showWizard
= !SetupIsActive() && !IsConsoleBoot();
2201 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2202 ListEntry
= InterlockedPopEntrySList(&DeviceInstallListHead
);
2204 if ((BOOL
)IsListEmpty(&DeviceInstallListHead
))
2207 ListEntry
= RemoveHeadList(&DeviceInstallListHead
);
2209 if (ListEntry
== NULL
)
2211 SetEvent(hNoPendingInstalls
);
2212 WaitForSingleObject(hDeviceInstallListNotEmpty
, INFINITE
);
2216 ResetEvent(hNoPendingInstalls
);
2217 Params
= CONTAINING_RECORD(ListEntry
, DeviceInstallParams
, ListEntry
);
2218 InstallDevice(Params
->DeviceIds
, showWizard
);
2227 PnpEventThread(LPVOID lpParameter
)
2229 PPLUGPLAY_EVENT_BLOCK PnpEvent
;
2232 RPC_STATUS RpcStatus
;
2234 UNREFERENCED_PARAMETER(lpParameter
);
2236 PnpEventSize
= 0x1000;
2237 PnpEvent
= HeapAlloc(GetProcessHeap(), 0, PnpEventSize
);
2238 if (PnpEvent
== NULL
)
2239 return ERROR_OUTOFMEMORY
;
2243 DPRINT("Calling NtGetPlugPlayEvent()\n");
2245 /* Wait for the next pnp event */
2246 Status
= NtGetPlugPlayEvent(0, 0, PnpEvent
, PnpEventSize
);
2248 /* Resize the buffer for the PnP event if it's too small. */
2249 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2251 PnpEventSize
+= 0x400;
2252 HeapFree(GetProcessHeap(), 0, PnpEvent
);
2253 PnpEvent
= HeapAlloc(GetProcessHeap(), 0, PnpEventSize
);
2254 if (PnpEvent
== NULL
)
2255 return ERROR_OUTOFMEMORY
;
2259 if (!NT_SUCCESS(Status
))
2261 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status
);
2265 /* Process the pnp event */
2266 DPRINT("Received PnP Event\n");
2267 if (UuidEqual(&PnpEvent
->EventGuid
, (UUID
*)&GUID_DEVICE_ENUMERATED
, &RpcStatus
))
2269 DeviceInstallParams
* Params
;
2271 DWORD DeviceIdLength
;
2273 DPRINT("Device arrival event: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
2275 DeviceIdLength
= lstrlenW(PnpEvent
->TargetDevice
.DeviceIds
);
2278 /* Queue device install (will be dequeued by DeviceInstallThread */
2279 len
= FIELD_OFFSET(DeviceInstallParams
, DeviceIds
) + (DeviceIdLength
+ 1) * sizeof(WCHAR
);
2280 Params
= HeapAlloc(GetProcessHeap(), 0, len
);
2283 wcscpy(Params
->DeviceIds
, PnpEvent
->TargetDevice
.DeviceIds
);
2284 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2285 InterlockedPushEntrySList(&DeviceInstallListHead
, &Params
->ListEntry
);
2287 InsertTailList(&DeviceInstallListHead
, &Params
->ListEntry
);
2289 SetEvent(hDeviceInstallListNotEmpty
);
2295 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
2296 PnpEvent
->EventGuid
.Data1
, PnpEvent
->EventGuid
.Data2
, PnpEvent
->EventGuid
.Data3
,
2297 PnpEvent
->EventGuid
.Data4
[0], PnpEvent
->EventGuid
.Data4
[1], PnpEvent
->EventGuid
.Data4
[2],
2298 PnpEvent
->EventGuid
.Data4
[3], PnpEvent
->EventGuid
.Data4
[4], PnpEvent
->EventGuid
.Data4
[5],
2299 PnpEvent
->EventGuid
.Data4
[6], PnpEvent
->EventGuid
.Data4
[7]);
2302 /* Dequeue the current pnp event and signal the next one */
2303 NtPlugPlayControl(PlugPlayControlUserResponse
, NULL
, 0);
2306 HeapFree(GetProcessHeap(), 0, PnpEvent
);
2308 return ERROR_SUCCESS
;
2312 static VOID CALLBACK
2313 ServiceMain(DWORD argc
, LPTSTR
*argv
)
2318 UNREFERENCED_PARAMETER(argc
);
2319 UNREFERENCED_PARAMETER(argv
);
2321 DPRINT("ServiceMain() called\n");
2323 hThread
= CreateThread(NULL
,
2329 if (hThread
!= NULL
)
2330 CloseHandle(hThread
);
2332 hThread
= CreateThread(NULL
,
2338 if (hThread
!= NULL
)
2339 CloseHandle(hThread
);
2341 hThread
= CreateThread(NULL
,
2343 DeviceInstallThread
,
2347 if (hThread
!= NULL
)
2348 CloseHandle(hThread
);
2350 DPRINT("ServiceMain() done\n");
2355 wmain(int argc
, WCHAR
*argv
[])
2360 UNREFERENCED_PARAMETER(argc
);
2361 UNREFERENCED_PARAMETER(argv
);
2363 DPRINT("Umpnpmgr: main() started\n");
2365 /* We need this privilege for using CreateProcessAsUserW */
2366 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
, TRUE
, FALSE
, &OldValue
);
2368 hInstallEvent
= CreateEvent(NULL
, TRUE
, SetupIsActive()/*FALSE*/, NULL
);
2369 if (hInstallEvent
== NULL
)
2371 dwError
= GetLastError();
2372 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError
);
2376 hDeviceInstallListNotEmpty
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
2377 if (hDeviceInstallListNotEmpty
== NULL
)
2379 dwError
= GetLastError();
2380 DPRINT1("Could not create the Event! (Error %lu)\n", dwError
);
2384 hNoPendingInstalls
= CreateEventW(NULL
,
2387 L
"Global\\PnP_No_Pending_Install_Events");
2388 if (hNoPendingInstalls
== NULL
)
2390 dwError
= GetLastError();
2391 DPRINT1("Could not create the Event! (Error %lu)\n", dwError
);
2395 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2396 InitializeSListHead(&DeviceInstallListHead
);
2398 InitializeListHead(&DeviceInstallListHead
);
2401 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2402 L
"System\\CurrentControlSet\\Enum",
2406 if (dwError
!= ERROR_SUCCESS
)
2408 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError
);
2412 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2413 L
"System\\CurrentControlSet\\Control\\Class",
2417 if (dwError
!= ERROR_SUCCESS
)
2419 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError
);
2423 StartServiceCtrlDispatcher(ServiceTable
);
2425 DPRINT("Umpnpmgr: main() done\n");