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
;
672 case CM_DRP_ENUMERATOR_NAME
:
673 PlugPlayData
.Property
= 15; //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 MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination
,
1090 LPWSTR pszDeviceInstanceSource
)
1092 DPRINT("MoveDeviceInstance: not implemented\n");
1094 return CR_CALL_NOT_IMPLEMENTED
;
1099 SetupDeviceInstance(LPWSTR pszDeviceInstance
,
1102 DPRINT("SetupDeviceInstance: not implemented\n");
1104 return CR_CALL_NOT_IMPLEMENTED
;
1109 EnableDeviceInstance(LPWSTR pszDeviceInstance
)
1111 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
1112 CONFIGRET ret
= CR_SUCCESS
;
1115 DPRINT("Enable device instance\n");
1117 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, pszDeviceInstance
);
1118 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
1119 if (!NT_SUCCESS(Status
))
1120 ret
= NtStatusToCrError(Status
);
1127 DisableDeviceInstance(LPWSTR pszDeviceInstance
)
1129 DPRINT("DisableDeviceInstance: not implemented\n");
1131 return CR_CALL_NOT_IMPLEMENTED
;
1136 ReenumerateDeviceInstance(LPWSTR pszDeviceInstance
)
1138 DPRINT("ReenumerateDeviceInstance: not implemented\n");
1140 return CR_CALL_NOT_IMPLEMENTED
;
1145 DWORD
PNP_DeviceInstanceAction(
1149 LPWSTR pszDeviceInstance1
,
1150 LPWSTR pszDeviceInstance2
)
1152 CONFIGRET ret
= CR_SUCCESS
;
1154 UNREFERENCED_PARAMETER(hBinding
);
1156 DPRINT("PNP_DeviceInstanceAction() called\n");
1160 case PNP_DEVINST_MOVE
:
1161 ret
= MoveDeviceInstance(pszDeviceInstance1
,
1162 pszDeviceInstance2
);
1165 case PNP_DEVINST_SETUP
:
1166 ret
= SetupDeviceInstance(pszDeviceInstance1
,
1170 case PNP_DEVINST_ENABLE
:
1171 ret
= EnableDeviceInstance(pszDeviceInstance1
);
1174 case PNP_DEVINST_DISABLE
:
1175 ret
= DisableDeviceInstance(pszDeviceInstance1
);
1178 case PNP_DEVINST_REENUMERATE
:
1179 ret
= ReenumerateDeviceInstance(pszDeviceInstance1
);
1183 DPRINT1("Unknown device action %lu: not implemented\n", ulAction
);
1184 ret
= CR_CALL_NOT_IMPLEMENTED
;
1187 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret
);
1194 DWORD
PNP_GetDeviceStatus(
1201 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData
;
1202 CONFIGRET ret
= CR_SUCCESS
;
1205 UNREFERENCED_PARAMETER(hBinding
);
1206 UNREFERENCED_PARAMETER(ulFlags
);
1208 DPRINT("PNP_GetDeviceStatus() called\n");
1210 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
1212 PlugPlayData
.Operation
= 0; /* Get status */
1214 Status
= NtPlugPlayControl(PlugPlayControlDeviceStatus
,
1215 (PVOID
)&PlugPlayData
,
1216 sizeof(PLUGPLAY_CONTROL_STATUS_DATA
));
1217 if (NT_SUCCESS(Status
))
1219 *pulStatus
= PlugPlayData
.DeviceStatus
;
1220 *pulProblem
= PlugPlayData
.DeviceProblem
;
1224 ret
= NtStatusToCrError(Status
);
1227 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret
);
1234 DWORD
PNP_SetDeviceProblem(
1241 return CR_CALL_NOT_IMPLEMENTED
;
1246 DWORD
PNP_DisableDevInst(
1249 PPNP_VETO_TYPE pVetoType
,
1255 return CR_CALL_NOT_IMPLEMENTED
;
1259 DWORD
PNP_UninstallDevInst(
1265 return CR_CALL_NOT_IMPLEMENTED
;
1270 CheckForDeviceId(LPWSTR lpDeviceIdList
,
1276 lpPtr
= lpDeviceIdList
;
1279 dwLength
= wcslen(lpPtr
);
1280 if (0 == _wcsicmp(lpPtr
, lpDeviceId
))
1283 lpPtr
+= (dwLength
+ 1);
1291 AppendDeviceId(LPWSTR lpDeviceIdList
,
1292 LPDWORD lpDeviceIdListSize
,
1298 dwLen
= wcslen(lpDeviceId
);
1299 dwPos
= (*lpDeviceIdListSize
/ sizeof(WCHAR
)) - 1;
1301 wcscpy(&lpDeviceIdList
[dwPos
], lpDeviceId
);
1303 dwPos
+= (dwLen
+ 1);
1305 lpDeviceIdList
[dwPos
] = 0;
1307 *lpDeviceIdListSize
= dwPos
* sizeof(WCHAR
);
1318 CONFIGRET ret
= CR_SUCCESS
;
1321 DWORD dwDeviceIdListSize
;
1322 DWORD dwNewDeviceIdSize
;
1323 WCHAR
* pszDeviceIdList
= NULL
;
1325 UNREFERENCED_PARAMETER(hBinding
);
1327 DPRINT("PNP_AddID() called\n");
1328 DPRINT(" DeviceInstance: %S\n", pszDeviceID
);
1329 DPRINT(" DeviceId: %S\n", pszID
);
1330 DPRINT(" Flags: %lx\n", ulFlags
);
1332 if (RegOpenKeyExW(hEnumKey
,
1335 KEY_QUERY_VALUE
| KEY_SET_VALUE
,
1336 &hDeviceKey
) != ERROR_SUCCESS
)
1338 DPRINT("Failed to open the device key!\n");
1339 return CR_INVALID_DEVNODE
;
1342 pszSubKey
= (ulFlags
& CM_ADD_ID_COMPATIBLE
) ? L
"CompatibleIDs" : L
"HardwareID";
1344 if (RegQueryValueExW(hDeviceKey
,
1349 &dwDeviceIdListSize
) != ERROR_SUCCESS
)
1351 DPRINT("Failed to query the desired ID string!\n");
1352 ret
= CR_REGISTRY_ERROR
;
1356 dwNewDeviceIdSize
= lstrlenW(pszDeviceID
);
1357 if (!dwNewDeviceIdSize
)
1359 ret
= CR_INVALID_POINTER
;
1363 dwDeviceIdListSize
+= (dwNewDeviceIdSize
+ 2) * sizeof(WCHAR
);
1365 pszDeviceIdList
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDeviceIdListSize
);
1366 if (!pszDeviceIdList
)
1368 DPRINT("Failed to allocate memory for the desired ID string!\n");
1369 ret
= CR_OUT_OF_MEMORY
;
1373 if (RegQueryValueExW(hDeviceKey
,
1377 (LPBYTE
)pszDeviceIdList
,
1378 &dwDeviceIdListSize
) != ERROR_SUCCESS
)
1380 DPRINT("Failed to query the desired ID string!\n");
1381 ret
= CR_REGISTRY_ERROR
;
1385 /* Check whether the device ID is already in use */
1386 if (CheckForDeviceId(pszDeviceIdList
, pszDeviceID
))
1388 DPRINT("Device ID was found in the ID string!\n");
1393 /* Append the Device ID */
1394 AppendDeviceId(pszDeviceIdList
, &dwDeviceIdListSize
, pszID
);
1396 if (RegSetValueExW(hDeviceKey
,
1400 (LPBYTE
)pszDeviceIdList
,
1401 dwDeviceIdListSize
) != ERROR_SUCCESS
)
1403 DPRINT("Failed to set the desired ID string!\n");
1404 ret
= CR_REGISTRY_ERROR
;
1408 RegCloseKey(hDeviceKey
);
1409 if (pszDeviceIdList
)
1410 HeapFree(GetProcessHeap(), 0, pszDeviceIdList
);
1412 DPRINT("PNP_AddID() done (returns %lx)\n", ret
);
1419 DWORD
PNP_RegisterDriver(
1425 return CR_CALL_NOT_IMPLEMENTED
;
1430 DWORD
PNP_QueryRemove(
1433 PPNP_VETO_TYPE pVetoType
,
1439 return CR_CALL_NOT_IMPLEMENTED
;
1444 DWORD
PNP_RequestDeviceEject(
1447 PPNP_VETO_TYPE pVetoType
,
1453 return CR_CALL_NOT_IMPLEMENTED
;
1458 PNP_IsDockStationPresent(handle_t hBinding
,
1465 CONFIGRET ret
= CR_SUCCESS
;
1467 UNREFERENCED_PARAMETER(hBinding
);
1469 DPRINT1("PNP_IsDockStationPresent() called\n");
1473 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG
,
1477 &hKey
) != ERROR_SUCCESS
)
1478 return CR_REGISTRY_ERROR
;
1480 dwSize
= sizeof(DWORD
);
1481 if (RegQueryValueExW(hKey
,
1486 &dwSize
) != ERROR_SUCCESS
)
1487 ret
= CR_REGISTRY_ERROR
;
1491 if (ret
== CR_SUCCESS
)
1493 if (dwType
!= REG_DWORD
|| dwSize
!= sizeof(DWORD
))
1495 ret
= CR_REGISTRY_ERROR
;
1497 else if (dwValue
!= 0)
1503 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret
);
1510 DWORD
PNP_RequestEjectPC(
1514 return CR_CALL_NOT_IMPLEMENTED
;
1519 DWORD
PNP_HwProfFlags(
1525 PPNP_VETO_TYPE pVetoType
,
1530 CONFIGRET ret
= CR_SUCCESS
;
1531 WCHAR szKeyName
[MAX_PATH
];
1536 UNREFERENCED_PARAMETER(hBinding
);
1538 DPRINT("PNP_HwProfFlags() called\n");
1543 L
"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
1548 L
"System\\CurrentControlSet\\HardwareProfiles\\%04u\\System\\CurrentControlSet\\Enum",
1552 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1556 &hKey
) != ERROR_SUCCESS
)
1557 return CR_REGISTRY_ERROR
;
1559 if (ulAction
== PNP_GET_HWPROFFLAGS
)
1561 if (RegOpenKeyExW(hKey
,
1565 &hDeviceKey
) != ERROR_SUCCESS
)
1571 dwSize
= sizeof(DWORD
);
1572 if (!RegQueryValueExW(hDeviceKey
,
1577 &dwSize
) != ERROR_SUCCESS
)
1582 RegCloseKey(hDeviceKey
);
1585 else if (ulAction
== PNP_SET_HWPROFFLAGS
)
1587 /* FIXME: not implemented yet */
1588 ret
= CR_CALL_NOT_IMPLEMENTED
;
1598 DWORD
PNP_GetHwProfInfo(
1601 HWPROFILEINFO
*pHWProfileInfo
,
1602 DWORD ulProfileInfoSize
,
1606 return CR_CALL_NOT_IMPLEMENTED
;
1611 DWORD
PNP_AddEmptyLogConf(
1615 DWORD
*pulLogConfTag
,
1619 return CR_CALL_NOT_IMPLEMENTED
;
1624 DWORD
PNP_FreeLogConf(
1627 DWORD ulLogConfType
,
1632 return CR_CALL_NOT_IMPLEMENTED
;
1637 DWORD
PNP_GetFirstLogConf(
1640 DWORD ulLogConfType
,
1641 DWORD
*pulLogConfTag
,
1645 return CR_CALL_NOT_IMPLEMENTED
;
1650 DWORD
PNP_GetNextLogConf(
1653 DWORD ulLogConfType
,
1659 return CR_CALL_NOT_IMPLEMENTED
;
1664 DWORD
PNP_GetLogConfPriority(
1673 return CR_CALL_NOT_IMPLEMENTED
;
1678 DWORD
PNP_AddResDes(
1682 DWORD ulLogConfType
,
1683 RESOURCEID ResourceID
,
1684 DWORD
*pulResourceTag
,
1686 PNP_RPC_BUFFER_SIZE ResourceLen
,
1690 return CR_CALL_NOT_IMPLEMENTED
;
1695 DWORD
PNP_FreeResDes(
1699 DWORD ulLogConfType
,
1700 RESOURCEID ResourceID
,
1701 DWORD ulResourceTag
,
1702 DWORD
*pulPreviousResType
,
1703 DWORD
*pulPreviousResTag
,
1707 return CR_CALL_NOT_IMPLEMENTED
;
1712 DWORD
PNP_GetNextResDes(
1716 DWORD ulLogConfType
,
1717 RESOURCEID ResourceID
,
1718 DWORD ulResourceTag
,
1719 DWORD
*pulNextResType
,
1720 DWORD
*pulNextResTag
,
1724 return CR_CALL_NOT_IMPLEMENTED
;
1729 DWORD
PNP_GetResDesData(
1733 DWORD ulLogConfType
,
1734 RESOURCEID ResourceID
,
1735 DWORD ulResourceTag
,
1737 PNP_RPC_BUFFER_SIZE BufferLen
,
1741 return CR_CALL_NOT_IMPLEMENTED
;
1746 DWORD
PNP_GetResDesDataSize(
1750 DWORD ulLogConfType
,
1751 RESOURCEID ResourceID
,
1752 DWORD ulResourceTag
,
1757 return CR_CALL_NOT_IMPLEMENTED
;
1762 DWORD
PNP_ModifyResDes(
1766 DWORD ulLogConfType
,
1767 RESOURCEID CurrentResourceID
,
1768 RESOURCEID NewResourceID
,
1769 DWORD ulResourceTag
,
1771 PNP_RPC_BUFFER_SIZE ResourceLen
,
1775 return CR_CALL_NOT_IMPLEMENTED
;
1780 DWORD
PNP_DetectResourceConflict(
1783 RESOURCEID ResourceID
,
1785 PNP_RPC_BUFFER_SIZE ResourceLen
,
1786 BOOL
*pbConflictDetected
,
1790 return CR_CALL_NOT_IMPLEMENTED
;
1795 DWORD
PNP_QueryResConfList(
1798 RESOURCEID ResourceID
,
1800 PNP_RPC_BUFFER_SIZE ResourceLen
,
1802 PNP_RPC_BUFFER_SIZE BufferLen
,
1806 return CR_CALL_NOT_IMPLEMENTED
;
1811 DWORD
PNP_SetHwProf(
1813 DWORD ulHardwareProfile
,
1817 return CR_CALL_NOT_IMPLEMENTED
;
1822 DWORD
PNP_QueryArbitratorFreeData(
1826 return CR_CALL_NOT_IMPLEMENTED
;
1831 DWORD
PNP_QueryArbitratorFreeSize(
1835 return CR_CALL_NOT_IMPLEMENTED
;
1846 return CR_CALL_NOT_IMPLEMENTED
;
1851 DWORD
PNP_RegisterNotification(
1855 return CR_CALL_NOT_IMPLEMENTED
;
1860 DWORD
PNP_UnregisterNotification(
1864 return CR_CALL_NOT_IMPLEMENTED
;
1869 DWORD
PNP_GetCustomDevProp(
1872 LPWSTR CustomPropName
,
1873 DWORD
*pulRegDataType
,
1875 PNP_RPC_STRING_LEN
*pulTransferLen
,
1876 PNP_RPC_STRING_LEN
*pulLength
,
1880 return CR_CALL_NOT_IMPLEMENTED
;
1885 DWORD
PNP_GetVersionInternal(
1890 return CR_CALL_NOT_IMPLEMENTED
;
1895 DWORD
PNP_GetBlockedDriverInfo(
1898 PNP_RPC_BUFFER_SIZE
*pulTransferLen
,
1899 PNP_RPC_BUFFER_SIZE
*pulLength
,
1903 return CR_CALL_NOT_IMPLEMENTED
;
1908 DWORD
PNP_GetServerSideDeviceInstallFlags(
1910 DWORD
*pulSSDIFlags
,
1914 return CR_CALL_NOT_IMPLEMENTED
;
1919 DWORD
PNP_GetObjectPropKeys(
1923 LPWSTR PropertyCultureName
,
1924 PNP_PROP_COUNT
*PropertyCount
,
1925 PNP_PROP_COUNT
*TransferLen
,
1926 DEVPROPKEY
*PropertyKeys
,
1930 return CR_CALL_NOT_IMPLEMENTED
;
1935 DWORD
PNP_GetObjectProp(
1939 LPWSTR PropertyCultureName
,
1940 const DEVPROPKEY
*PropertyKey
,
1941 DEVPROPTYPE
*PropertyType
,
1942 PNP_PROP_SIZE
*PropertySize
,
1943 PNP_PROP_SIZE
*TransferLen
,
1944 BYTE
*PropertyBuffer
,
1948 return CR_CALL_NOT_IMPLEMENTED
;
1953 DWORD
PNP_SetObjectProp(
1957 LPWSTR PropertyCultureName
,
1958 const DEVPROPKEY
*PropertyKey
,
1959 DEVPROPTYPE PropertyType
,
1960 PNP_PROP_SIZE PropertySize
,
1961 BYTE
*PropertyBuffer
,
1965 return CR_CALL_NOT_IMPLEMENTED
;
1970 DWORD
PNP_InstallDevInst(
1974 return CR_CALL_NOT_IMPLEMENTED
;
1979 DWORD
PNP_ApplyPowerSettings(
1983 return CR_CALL_NOT_IMPLEMENTED
;
1988 DWORD
PNP_DriverStoreAddDriverPackage(
1992 return CR_CALL_NOT_IMPLEMENTED
;
1997 DWORD
PNP_DriverStoreDeleteDriverPackage(
2001 return CR_CALL_NOT_IMPLEMENTED
;
2006 DWORD
PNP_RegisterServiceNotification(
2010 return CR_CALL_NOT_IMPLEMENTED
;
2015 DWORD
PNP_SetActiveService(
2019 return CR_CALL_NOT_IMPLEMENTED
;
2024 DWORD
PNP_DeleteServiceDevices(
2028 return CR_CALL_NOT_IMPLEMENTED
;
2033 InstallDevice(PCWSTR DeviceInstance
, BOOL ShowWizard
)
2035 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData
;
2037 BOOL DeviceInstalled
= FALSE
;
2040 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
2041 LPVOID Environment
= NULL
;
2042 PROCESS_INFORMATION ProcessInfo
;
2043 STARTUPINFOW StartupInfo
;
2046 /* The following lengths are constant (see below), they cannot overflow */
2047 WCHAR CommandLine
[116];
2048 WCHAR InstallEventName
[73];
2050 WCHAR UuidString
[39];
2052 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance
, ShowWizard
);
2054 ZeroMemory(&ProcessInfo
, sizeof(ProcessInfo
));
2056 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
2058 PlugPlayData
.Operation
= 0; /* Get status */
2060 /* Get device status */
2061 Status
= NtPlugPlayControl(PlugPlayControlDeviceStatus
,
2062 (PVOID
)&PlugPlayData
,
2063 sizeof(PLUGPLAY_CONTROL_STATUS_DATA
));
2064 if (!NT_SUCCESS(Status
))
2066 DPRINT1("NtPlugPlayControl('%S') failed with status 0x%08lx\n", DeviceInstance
, Status
);
2070 if ((PlugPlayData
.DeviceStatus
& (DNF_STARTED
| DNF_START_FAILED
)) != 0)
2072 /* Device is already started, or disabled due to some problem. Don't install it */
2073 DPRINT("No need to install '%S'\n", DeviceInstance
);
2077 /* Create a random UUID for the named pipe */
2078 UuidCreate(&RandomUuid
);
2079 swprintf(UuidString
, L
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
2080 RandomUuid
.Data1
, RandomUuid
.Data2
, RandomUuid
.Data3
,
2081 RandomUuid
.Data4
[0], RandomUuid
.Data4
[1], RandomUuid
.Data4
[2],
2082 RandomUuid
.Data4
[3], RandomUuid
.Data4
[4], RandomUuid
.Data4
[5],
2083 RandomUuid
.Data4
[6], RandomUuid
.Data4
[7]);
2085 /* Create the named pipe */
2086 wcscpy(PipeName
, L
"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
2087 wcscat(PipeName
, UuidString
);
2088 hPipe
= CreateNamedPipeW(PipeName
, PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_BYTE
, 1, 512, 512, 0, NULL
);
2090 if(hPipe
== INVALID_HANDLE_VALUE
)
2092 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
2096 /* Launch rundll32 to call ClientSideInstallW */
2097 wcscpy(CommandLine
, L
"rundll32.exe newdev.dll,ClientSideInstall ");
2098 wcscat(CommandLine
, PipeName
);
2100 ZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
2101 StartupInfo
.cb
= sizeof(StartupInfo
);
2105 /* newdev has to run under the environment of the current user */
2106 if(!CreateEnvironmentBlock(&Environment
, hUserToken
, FALSE
))
2108 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
2112 if(!CreateProcessAsUserW(hUserToken
, NULL
, CommandLine
, NULL
, NULL
, FALSE
, CREATE_UNICODE_ENVIRONMENT
, Environment
, NULL
, &StartupInfo
, &ProcessInfo
))
2114 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
2120 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
2122 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
2123 (ShowWizard is only set to FALSE for these two modes) */
2124 ASSERT(!ShowWizard
);
2126 if(!CreateProcessW(NULL
, CommandLine
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &StartupInfo
, &ProcessInfo
))
2128 DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
2133 /* Wait for the function to connect to our pipe */
2134 if(!ConnectNamedPipe(hPipe
, NULL
))
2136 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
2140 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
2141 wcscpy(InstallEventName
, L
"Global\\PNP_Device_Install_Event_0.");
2142 wcscat(InstallEventName
, UuidString
);
2144 Value
= sizeof(InstallEventName
);
2145 WriteFile(hPipe
, &Value
, sizeof(Value
), &BytesWritten
, NULL
);
2146 WriteFile(hPipe
, InstallEventName
, Value
, &BytesWritten
, NULL
);
2148 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
2149 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
2150 WriteFile(hPipe
, &ShowWizard
, sizeof(ShowWizard
), &BytesWritten
, NULL
);
2152 Value
= (wcslen(DeviceInstance
) + 1) * sizeof(WCHAR
);
2153 WriteFile(hPipe
, &Value
, sizeof(Value
), &BytesWritten
, NULL
);
2154 WriteFile(hPipe
, DeviceInstance
, Value
, &BytesWritten
, NULL
);
2156 /* Wait for newdev.dll to finish processing */
2157 WaitForSingleObject(ProcessInfo
.hProcess
, INFINITE
);
2159 /* The following check for success is probably not compatible to Windows, but should do its job */
2160 if(!GetExitCodeProcess(ProcessInfo
.hProcess
, &Value
))
2162 DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
2166 DeviceInstalled
= Value
;
2169 if(hPipe
!= INVALID_HANDLE_VALUE
)
2173 DestroyEnvironmentBlock(Environment
);
2175 if(ProcessInfo
.hProcess
)
2176 CloseHandle(ProcessInfo
.hProcess
);
2178 if(ProcessInfo
.hThread
)
2179 CloseHandle(ProcessInfo
.hThread
);
2181 return DeviceInstalled
;
2197 return ERROR_INVALID_PARAMETER
;
2200 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, &dwType
, NULL
, &cbData
);
2201 if (rc
!= ERROR_SUCCESS
)
2203 if (dwType
!= REG_SZ
)
2204 return ERROR_FILE_NOT_FOUND
;
2205 Value
= HeapAlloc(GetProcessHeap(), 0, cbData
+ sizeof(WCHAR
));
2207 return ERROR_NOT_ENOUGH_MEMORY
;
2208 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, NULL
, (LPBYTE
)Value
, &cbData
);
2209 if (rc
!= ERROR_SUCCESS
)
2211 HeapFree(GetProcessHeap(), 0, Value
);
2214 /* NULL-terminate the string */
2215 Value
[cbData
/ sizeof(WCHAR
)] = '\0';
2218 return ERROR_SUCCESS
;
2226 DWORD regType
, active
, size
;
2230 rc
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\Setup", 0, KEY_QUERY_VALUE
, &hKey
);
2231 if (rc
!= ERROR_SUCCESS
)
2234 size
= sizeof(DWORD
);
2235 rc
= RegQueryValueExW(hKey
, L
"SystemSetupInProgress", NULL
, ®Type
, (LPBYTE
)&active
, &size
);
2236 if (rc
!= ERROR_SUCCESS
)
2238 if (regType
!= REG_DWORD
|| size
!= sizeof(DWORD
))
2241 ret
= (active
!= 0);
2247 DPRINT("System setup in progress? %S\n", ret
? L
"YES" : L
"NO");
2256 HKEY ControlKey
= NULL
;
2257 LPWSTR SystemStartOptions
= NULL
;
2258 LPWSTR CurrentOption
, NextOption
; /* Pointers into SystemStartOptions */
2259 BOOL ConsoleBoot
= FALSE
;
2264 L
"SYSTEM\\CurrentControlSet\\Control",
2269 rc
= ReadRegSzKey(ControlKey
, L
"SystemStartOptions", &SystemStartOptions
);
2270 if (rc
!= ERROR_SUCCESS
)
2273 /* Check for CMDCONS in SystemStartOptions */
2274 CurrentOption
= SystemStartOptions
;
2275 while (CurrentOption
)
2277 NextOption
= wcschr(CurrentOption
, L
' ');
2279 *NextOption
= L
'\0';
2280 if (_wcsicmp(CurrentOption
, L
"CONSOLE") == 0)
2282 DPRINT("Found %S. Switching to console boot\n", CurrentOption
);
2286 CurrentOption
= NextOption
? NextOption
+ 1 : NULL
;
2290 if (ControlKey
!= NULL
)
2291 RegCloseKey(ControlKey
);
2292 HeapFree(GetProcessHeap(), 0, SystemStartOptions
);
2297 /* Loop to install all queued devices installations */
2299 DeviceInstallThread(LPVOID lpParameter
)
2301 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2302 PSLIST_ENTRY ListEntry
;
2304 PLIST_ENTRY ListEntry
;
2306 DeviceInstallParams
* Params
;
2309 UNREFERENCED_PARAMETER(lpParameter
);
2311 WaitForSingleObject(hInstallEvent
, INFINITE
);
2313 showWizard
= !SetupIsActive() && !IsConsoleBoot();
2317 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2318 ListEntry
= InterlockedPopEntrySList(&DeviceInstallListHead
);
2320 if ((BOOL
)IsListEmpty(&DeviceInstallListHead
))
2323 ListEntry
= RemoveHeadList(&DeviceInstallListHead
);
2325 if (ListEntry
== NULL
)
2327 SetEvent(hNoPendingInstalls
);
2328 WaitForSingleObject(hDeviceInstallListNotEmpty
, INFINITE
);
2332 ResetEvent(hNoPendingInstalls
);
2333 Params
= CONTAINING_RECORD(ListEntry
, DeviceInstallParams
, ListEntry
);
2334 InstallDevice(Params
->DeviceIds
, showWizard
);
2343 PnpEventThread(LPVOID lpParameter
)
2345 PPLUGPLAY_EVENT_BLOCK PnpEvent
;
2348 RPC_STATUS RpcStatus
;
2350 UNREFERENCED_PARAMETER(lpParameter
);
2352 PnpEventSize
= 0x1000;
2353 PnpEvent
= HeapAlloc(GetProcessHeap(), 0, PnpEventSize
);
2354 if (PnpEvent
== NULL
)
2355 return ERROR_OUTOFMEMORY
;
2359 DPRINT("Calling NtGetPlugPlayEvent()\n");
2361 /* Wait for the next pnp event */
2362 Status
= NtGetPlugPlayEvent(0, 0, PnpEvent
, PnpEventSize
);
2364 /* Resize the buffer for the PnP event if it's too small. */
2365 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2367 PnpEventSize
+= 0x400;
2368 HeapFree(GetProcessHeap(), 0, PnpEvent
);
2369 PnpEvent
= HeapAlloc(GetProcessHeap(), 0, PnpEventSize
);
2370 if (PnpEvent
== NULL
)
2371 return ERROR_OUTOFMEMORY
;
2375 if (!NT_SUCCESS(Status
))
2377 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status
);
2381 /* Process the pnp event */
2382 DPRINT("Received PnP Event\n");
2383 if (UuidEqual(&PnpEvent
->EventGuid
, (UUID
*)&GUID_DEVICE_ENUMERATED
, &RpcStatus
))
2385 DeviceInstallParams
* Params
;
2387 DWORD DeviceIdLength
;
2389 DPRINT("Device enumerated: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
2391 DeviceIdLength
= lstrlenW(PnpEvent
->TargetDevice
.DeviceIds
);
2394 /* Queue device install (will be dequeued by DeviceInstallThread */
2395 len
= FIELD_OFFSET(DeviceInstallParams
, DeviceIds
) + (DeviceIdLength
+ 1) * sizeof(WCHAR
);
2396 Params
= HeapAlloc(GetProcessHeap(), 0, len
);
2399 wcscpy(Params
->DeviceIds
, PnpEvent
->TargetDevice
.DeviceIds
);
2400 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2401 InterlockedPushEntrySList(&DeviceInstallListHead
, &Params
->ListEntry
);
2403 InsertTailList(&DeviceInstallListHead
, &Params
->ListEntry
);
2405 SetEvent(hDeviceInstallListNotEmpty
);
2409 else if (UuidEqual(&PnpEvent
->EventGuid
, (UUID
*)&GUID_DEVICE_ARRIVAL
, &RpcStatus
))
2411 DPRINT("Device arrival: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
2416 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
2417 PnpEvent
->EventGuid
.Data1
, PnpEvent
->EventGuid
.Data2
, PnpEvent
->EventGuid
.Data3
,
2418 PnpEvent
->EventGuid
.Data4
[0], PnpEvent
->EventGuid
.Data4
[1], PnpEvent
->EventGuid
.Data4
[2],
2419 PnpEvent
->EventGuid
.Data4
[3], PnpEvent
->EventGuid
.Data4
[4], PnpEvent
->EventGuid
.Data4
[5],
2420 PnpEvent
->EventGuid
.Data4
[6], PnpEvent
->EventGuid
.Data4
[7]);
2423 /* Dequeue the current pnp event and signal the next one */
2424 NtPlugPlayControl(PlugPlayControlUserResponse
, NULL
, 0);
2427 HeapFree(GetProcessHeap(), 0, PnpEvent
);
2429 return ERROR_SUCCESS
;
2433 static VOID CALLBACK
2434 ServiceMain(DWORD argc
, LPTSTR
*argv
)
2439 UNREFERENCED_PARAMETER(argc
);
2440 UNREFERENCED_PARAMETER(argv
);
2442 DPRINT("ServiceMain() called\n");
2444 hThread
= CreateThread(NULL
,
2450 if (hThread
!= NULL
)
2451 CloseHandle(hThread
);
2453 hThread
= CreateThread(NULL
,
2459 if (hThread
!= NULL
)
2460 CloseHandle(hThread
);
2462 hThread
= CreateThread(NULL
,
2464 DeviceInstallThread
,
2468 if (hThread
!= NULL
)
2469 CloseHandle(hThread
);
2471 DPRINT("ServiceMain() done\n");
2476 wmain(int argc
, WCHAR
*argv
[])
2481 UNREFERENCED_PARAMETER(argc
);
2482 UNREFERENCED_PARAMETER(argv
);
2484 DPRINT("Umpnpmgr: main() started\n");
2486 /* We need this privilege for using CreateProcessAsUserW */
2487 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
, TRUE
, FALSE
, &OldValue
);
2489 hInstallEvent
= CreateEvent(NULL
, TRUE
, SetupIsActive()/*FALSE*/, NULL
);
2490 if (hInstallEvent
== NULL
)
2492 dwError
= GetLastError();
2493 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError
);
2497 hDeviceInstallListNotEmpty
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
2498 if (hDeviceInstallListNotEmpty
== NULL
)
2500 dwError
= GetLastError();
2501 DPRINT1("Could not create the Event! (Error %lu)\n", dwError
);
2505 hNoPendingInstalls
= CreateEventW(NULL
,
2508 L
"Global\\PnP_No_Pending_Install_Events");
2509 if (hNoPendingInstalls
== NULL
)
2511 dwError
= GetLastError();
2512 DPRINT1("Could not create the Event! (Error %lu)\n", dwError
);
2516 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2517 InitializeSListHead(&DeviceInstallListHead
);
2519 InitializeListHead(&DeviceInstallListHead
);
2522 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2523 L
"System\\CurrentControlSet\\Enum",
2527 if (dwError
!= ERROR_SUCCESS
)
2529 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError
);
2533 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2534 L
"System\\CurrentControlSet\\Control\\Class",
2538 if (dwError
!= ERROR_SUCCESS
)
2540 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError
);
2544 StartServiceCtrlDispatcher(ServiceTable
);
2546 DPRINT("Umpnpmgr: main() done\n");