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 ******************************************************************/
54 static VOID CALLBACK
ServiceMain(DWORD argc
, LPWSTR
*argv
);
55 static WCHAR ServiceName
[] = L
"PlugPlay";
56 static SERVICE_TABLE_ENTRYW ServiceTable
[] =
58 {ServiceName
, ServiceMain
},
62 static SERVICE_STATUS_HANDLE ServiceStatusHandle
;
63 static SERVICE_STATUS ServiceStatus
;
65 static WCHAR szRootDeviceId
[] = L
"HTREE\\ROOT\\0";
67 static HKEY hEnumKey
= NULL
;
68 static HKEY hClassKey
= NULL
;
70 static HANDLE hUserToken
= NULL
;
71 static HANDLE hInstallEvent
= NULL
;
72 static HANDLE hNoPendingInstalls
= NULL
;
74 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
75 static SLIST_HEADER DeviceInstallListHead
;
77 static LIST_ENTRY DeviceInstallListHead
;
79 static HANDLE hDeviceInstallListNotEmpty
;
83 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
84 SLIST_ENTRY ListEntry
;
89 } DeviceInstallParams
;
91 /* FUNCTIONS *****************************************************************/
94 RpcServerThread(LPVOID lpParameter
)
98 UNREFERENCED_PARAMETER(lpParameter
);
100 DPRINT("RpcServerThread() called\n");
102 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
105 NULL
); // Security descriptor
106 if (Status
!= RPC_S_OK
)
108 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
112 Status
= RpcServerRegisterIf(pnp_v1_0_s_ifspec
,
115 if (Status
!= RPC_S_OK
)
117 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
121 Status
= RpcServerListen(1,
124 if (Status
!= RPC_S_OK
)
126 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
130 /* ROS HACK (this should never happen...) */
131 DPRINT1("*** Other devices won't be installed correctly. If something\n");
132 DPRINT1("*** doesn't work, try to reboot to get a new chance.\n");
134 DPRINT("RpcServerThread() done\n");
140 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
142 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
146 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
148 HeapFree(GetProcessHeap(), 0, ptr
);
152 static CONFIGRET WINAPI
153 NtStatusToCrError(NTSTATUS Status
)
157 case STATUS_NO_SUCH_DEVICE
:
158 return CR_NO_SUCH_DEVINST
;
161 /* FIXME: add more mappings */
162 DPRINT1("Unable to map status 0x%08lx\n", Status
);
169 DWORD
PNP_Disconnect(
172 UNREFERENCED_PARAMETER(hBinding
);
174 return CR_CALL_NOT_IMPLEMENTED
;
182 UNREFERENCED_PARAMETER(hBinding
);
184 return CR_CALL_NOT_IMPLEMENTED
;
189 DWORD
PNP_GetVersion(
193 UNREFERENCED_PARAMETER(hBinding
);
201 DWORD
PNP_GetGlobalState(
206 UNREFERENCED_PARAMETER(hBinding
);
207 UNREFERENCED_PARAMETER(ulFlags
);
209 *pulState
= CM_GLOBAL_STATE_CAN_DO_UI
| CM_GLOBAL_STATE_SERVICES_AVAILABLE
;
215 DWORD
PNP_InitDetection(
218 UNREFERENCED_PARAMETER(hBinding
);
220 DPRINT("PNP_InitDetection() called\n");
226 DWORD
PNP_ReportLogOn(
231 DWORD ReturnValue
= CR_FAILURE
;
234 UNREFERENCED_PARAMETER(hBinding
);
235 UNREFERENCED_PARAMETER(Admin
);
237 DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin
, ProcessId
);
239 /* Get the users token */
240 hProcess
= OpenProcess(PROCESS_ALL_ACCESS
, TRUE
, ProcessId
);
244 DPRINT1("OpenProcess failed with error %u\n", GetLastError());
250 CloseHandle(hUserToken
);
254 if(!OpenProcessToken(hProcess
, TOKEN_ASSIGN_PRIMARY
| TOKEN_DUPLICATE
| TOKEN_QUERY
, &hUserToken
))
256 DPRINT1("OpenProcessToken failed with error %u\n", GetLastError());
260 /* Trigger the installer thread */
262 SetEvent(hInstallEvent
);
264 ReturnValue
= CR_SUCCESS
;
268 CloseHandle(hProcess
);
275 DWORD
PNP_ValidateDeviceInstance(
280 CONFIGRET ret
= CR_SUCCESS
;
281 HKEY hDeviceKey
= NULL
;
283 UNREFERENCED_PARAMETER(hBinding
);
284 UNREFERENCED_PARAMETER(ulFlags
);
286 DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
289 if (RegOpenKeyExW(hEnumKey
,
295 DPRINT("Could not open the Device Key!\n");
296 ret
= CR_NO_SUCH_DEVNODE
;
300 /* FIXME: add more tests */
303 if (hDeviceKey
!= NULL
)
304 RegCloseKey(hDeviceKey
);
306 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret
);
313 DWORD
PNP_GetRootDeviceInstance(
316 PNP_RPC_STRING_LEN ulLength
)
318 CONFIGRET ret
= CR_SUCCESS
;
320 UNREFERENCED_PARAMETER(hBinding
);
322 DPRINT("PNP_GetRootDeviceInstance() called\n");
326 ret
= CR_INVALID_POINTER
;
329 if (ulLength
< lstrlenW(szRootDeviceId
) + 1)
331 ret
= CR_BUFFER_SMALL
;
339 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret
);
346 DWORD
PNP_GetRelatedDeviceInstance(
348 DWORD ulRelationship
,
350 LPWSTR pRelatedDeviceId
,
351 PNP_RPC_STRING_LEN
*pulLength
,
354 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData
;
355 CONFIGRET ret
= CR_SUCCESS
;
358 UNREFERENCED_PARAMETER(hBinding
);
359 UNREFERENCED_PARAMETER(ulFlags
);
361 DPRINT("PNP_GetRelatedDeviceInstance() called\n");
362 DPRINT(" Relationship %ld\n", ulRelationship
);
363 DPRINT(" DeviceId %S\n", pDeviceID
);
365 RtlInitUnicodeString(&PlugPlayData
.TargetDeviceInstance
,
368 PlugPlayData
.Relation
= ulRelationship
;
370 PlugPlayData
.RelatedDeviceInstanceLength
= *pulLength
;
371 PlugPlayData
.RelatedDeviceInstance
= pRelatedDeviceId
;
373 Status
= NtPlugPlayControl(PlugPlayControlGetRelatedDevice
,
374 (PVOID
)&PlugPlayData
,
375 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA
));
376 if (!NT_SUCCESS(Status
))
378 ret
= NtStatusToCrError(Status
);
381 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret
);
382 if (ret
== CR_SUCCESS
)
384 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData
.RelatedDeviceInstance
);
392 DWORD
PNP_EnumerateSubKeys(
397 PNP_RPC_STRING_LEN ulLength
,
398 PNP_RPC_STRING_LEN
*pulRequiredLen
,
401 CONFIGRET ret
= CR_SUCCESS
;
405 UNREFERENCED_PARAMETER(hBinding
);
406 UNREFERENCED_PARAMETER(ulFlags
);
408 DPRINT("PNP_EnumerateSubKeys() called\n");
412 case PNP_ENUMERATOR_SUBKEYS
:
416 case PNP_CLASS_SUBKEYS
:
424 *pulRequiredLen
= ulLength
;
425 dwError
= RegEnumKeyExW(hKey
,
433 if (dwError
!= ERROR_SUCCESS
)
435 ret
= (dwError
== ERROR_NO_MORE_ITEMS
) ? CR_NO_SUCH_VALUE
: CR_FAILURE
;
442 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret
);
449 DWORD
PNP_GetDeviceList(
453 PNP_RPC_STRING_LEN
*pulLength
,
457 return CR_CALL_NOT_IMPLEMENTED
;
462 DWORD
PNP_GetDeviceListSize(
465 PNP_RPC_BUFFER_SIZE
*pulLen
,
469 return CR_CALL_NOT_IMPLEMENTED
;
480 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData
;
481 CONFIGRET ret
= CR_SUCCESS
;
484 UNREFERENCED_PARAMETER(hBinding
);
485 UNREFERENCED_PARAMETER(ulFlags
);
487 DPRINT("PNP_GetDepth() called\n");
489 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
492 Status
= NtPlugPlayControl(PlugPlayControlGetDeviceDepth
,
493 (PVOID
)&PlugPlayData
,
494 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA
));
495 if (NT_SUCCESS(Status
))
497 *pulDepth
= PlugPlayData
.Depth
;
501 ret
= NtStatusToCrError(Status
);
504 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret
);
511 DWORD
PNP_GetDeviceRegProp(
515 DWORD
*pulRegDataType
,
517 PNP_PROP_SIZE
*pulTransferLen
,
518 PNP_PROP_SIZE
*pulLength
,
521 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData
;
522 CONFIGRET ret
= CR_SUCCESS
;
523 LPWSTR lpValueName
= NULL
;
527 UNREFERENCED_PARAMETER(hBinding
);
528 UNREFERENCED_PARAMETER(ulFlags
);
530 DPRINT("PNP_GetDeviceRegProp() called\n");
534 case CM_DRP_DEVICEDESC
:
535 lpValueName
= L
"DeviceDesc";
538 case CM_DRP_HARDWAREID
:
539 lpValueName
= L
"HardwareID";
542 case CM_DRP_COMPATIBLEIDS
:
543 lpValueName
= L
"CompatibleIDs";
547 lpValueName
= L
"Service";
551 lpValueName
= L
"Class";
554 case CM_DRP_CLASSGUID
:
555 lpValueName
= L
"ClassGUID";
559 lpValueName
= L
"Driver";
562 case CM_DRP_CONFIGFLAGS
:
563 lpValueName
= L
"ConfigFlags";
567 lpValueName
= L
"Mfg";
570 case CM_DRP_FRIENDLYNAME
:
571 lpValueName
= L
"FriendlyName";
574 case CM_DRP_LOCATION_INFORMATION
:
575 lpValueName
= L
"LocationInformation";
578 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME
:
582 case CM_DRP_CAPABILITIES
:
583 lpValueName
= L
"Capabilities";
586 case CM_DRP_UI_NUMBER
:
590 case CM_DRP_UPPERFILTERS
:
591 lpValueName
= L
"UpperFilters";
594 case CM_DRP_LOWERFILTERS
:
595 lpValueName
= L
"LowerFilters";
598 case CM_DRP_BUSTYPEGUID
:
602 case CM_DRP_LEGACYBUSTYPE
:
606 case CM_DRP_BUSNUMBER
:
610 case CM_DRP_ENUMERATOR_NAME
:
615 return CR_INVALID_PROPERTY
;
618 DPRINT("Value name: %S\n", lpValueName
);
622 /* Retrieve information from the Registry */
623 if (RegOpenKeyExW(hEnumKey
,
628 return CR_INVALID_DEVNODE
;
630 if (RegQueryValueExW(hKey
,
636 ret
= CR_REGISTRY_ERROR
;
638 /* FIXME: Check buffer size */
644 /* Retrieve information from the Device Node */
645 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
647 PlugPlayData
.Buffer
= Buffer
;
648 PlugPlayData
.BufferSize
= *pulTransferLen
;
653 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME
:
654 PlugPlayData
.Property
= DevicePropertyPhysicalDeviceObjectName
;
657 case CM_DRP_UI_NUMBER
:
658 PlugPlayData
.Property
= DevicePropertyUINumber
;
661 case CM_DRP_BUSTYPEGUID
:
662 PlugPlayData
.Property
= DevicePropertyBusTypeGuid
;
665 case CM_DRP_LEGACYBUSTYPE
:
666 PlugPlayData
.Property
= DevicePropertyLegacyBusType
;
669 case CM_DRP_BUSNUMBER
:
670 PlugPlayData
.Property
= DevicePropertyBusNumber
;
674 case CM_DRP_ENUMERATOR_NAME
:
675 PlugPlayData
.Property
= 15; //DevicePropertyEnumeratorName;
679 return CR_INVALID_PROPERTY
;
682 Status
= NtPlugPlayControl(PlugPlayControlProperty
,
683 (PVOID
)&PlugPlayData
,
684 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA
));
685 if (NT_SUCCESS(Status
))
687 *pulLength
= PlugPlayData
.BufferSize
;
691 ret
= NtStatusToCrError(Status
);
695 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret
);
702 DWORD
PNP_SetDeviceRegProp(
708 PNP_PROP_SIZE ulLength
,
711 CONFIGRET ret
= CR_SUCCESS
;
712 LPWSTR lpValueName
= NULL
;
715 UNREFERENCED_PARAMETER(hBinding
);
716 UNREFERENCED_PARAMETER(ulFlags
);
718 DPRINT("PNP_SetDeviceRegProp() called\n");
720 DPRINT("DeviceId: %S\n", pDeviceId
);
721 DPRINT("Property: %lu\n", ulProperty
);
722 DPRINT("DataType: %lu\n", ulDataType
);
723 DPRINT("Length: %lu\n", ulLength
);
727 case CM_DRP_DEVICEDESC
:
728 lpValueName
= L
"DeviceDesc";
731 case CM_DRP_HARDWAREID
:
732 lpValueName
= L
"HardwareID";
735 case CM_DRP_COMPATIBLEIDS
:
736 lpValueName
= L
"CompatibleIDs";
740 lpValueName
= L
"Service";
744 lpValueName
= L
"Class";
747 case CM_DRP_CLASSGUID
:
748 lpValueName
= L
"ClassGUID";
752 lpValueName
= L
"Driver";
755 case CM_DRP_CONFIGFLAGS
:
756 lpValueName
= L
"ConfigFlags";
760 lpValueName
= L
"Mfg";
763 case CM_DRP_FRIENDLYNAME
:
764 lpValueName
= L
"FriendlyName";
767 case CM_DRP_LOCATION_INFORMATION
:
768 lpValueName
= L
"LocationInformation";
771 case CM_DRP_UPPERFILTERS
:
772 lpValueName
= L
"UpperFilters";
775 case CM_DRP_LOWERFILTERS
:
776 lpValueName
= L
"LowerFilters";
780 return CR_INVALID_PROPERTY
;
783 DPRINT("Value name: %S\n", lpValueName
);
785 if (RegOpenKeyExW(hEnumKey
,
788 KEY_ALL_ACCESS
, /* FIXME: so much? */
790 return CR_INVALID_DEVNODE
;
794 if (RegDeleteValueW(hKey
,
796 ret
= CR_REGISTRY_ERROR
;
800 if (RegSetValueExW(hKey
,
806 ret
= CR_REGISTRY_ERROR
;
811 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret
);
818 DWORD
PNP_GetClassInstance(
821 LPWSTR pszClassInstance
,
822 PNP_RPC_STRING_LEN ulLength
)
825 return CR_CALL_NOT_IMPLEMENTED
;
838 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
847 return CR_REGISTRY_ERROR
;
849 /* FIXME: Set security key */
858 DWORD
PNP_DeleteRegistryKey(
866 return CR_CALL_NOT_IMPLEMENTED
;
871 DWORD
PNP_GetClassCount(
873 DWORD
*pulClassCount
,
879 UNREFERENCED_PARAMETER(hBinding
);
880 UNREFERENCED_PARAMETER(ulFlags
);
882 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
887 if (dwError
!= ERROR_SUCCESS
)
888 return CR_INVALID_DATA
;
890 dwError
= RegQueryInfoKeyW(hKey
,
903 if (dwError
!= ERROR_SUCCESS
)
904 return CR_INVALID_DATA
;
911 DWORD
PNP_GetClassName(
915 PNP_RPC_STRING_LEN
*pulLength
,
918 WCHAR szKeyName
[MAX_PATH
];
919 CONFIGRET ret
= CR_SUCCESS
;
923 UNREFERENCED_PARAMETER(hBinding
);
924 UNREFERENCED_PARAMETER(ulFlags
);
926 DPRINT("PNP_GetClassName() called\n");
928 lstrcpyW(szKeyName
, L
"System\\CurrentControlSet\\Control\\Class\\");
929 if(lstrlenW(pszClassGuid
) + 1 < sizeof(szKeyName
)/sizeof(WCHAR
)-(lstrlenW(szKeyName
) * sizeof(WCHAR
)))
930 lstrcatW(szKeyName
, pszClassGuid
);
931 else return CR_INVALID_DATA
;
933 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
938 return CR_REGISTRY_ERROR
;
940 dwSize
= *pulLength
* sizeof(WCHAR
);
941 if (RegQueryValueExW(hKey
,
949 ret
= CR_REGISTRY_ERROR
;
953 *pulLength
= dwSize
/ sizeof(WCHAR
);
958 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret
);
965 DWORD
PNP_DeleteClassKey(
970 CONFIGRET ret
= CR_SUCCESS
;
972 UNREFERENCED_PARAMETER(hBinding
);
974 DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid
, ulFlags
);
976 if (ulFlags
& CM_DELETE_CLASS_SUBKEYS
)
978 if (RegDeleteTreeW(hClassKey
, pszClassGuid
) != ERROR_SUCCESS
)
979 ret
= CR_REGISTRY_ERROR
;
983 if (RegDeleteKeyW(hClassKey
, pszClassGuid
) != ERROR_SUCCESS
)
984 ret
= CR_REGISTRY_ERROR
;
987 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret
);
994 DWORD
PNP_GetInterfaceDeviceAlias(
996 LPWSTR pszInterfaceDevice
,
997 GUID
*AliasInterfaceGuid
,
998 LPWSTR pszAliasInterfaceDevice
,
999 PNP_RPC_STRING_LEN
*pulLength
,
1000 PNP_RPC_STRING_LEN
*pulTransferLen
,
1004 return CR_CALL_NOT_IMPLEMENTED
;
1009 DWORD
PNP_GetInterfaceDeviceList(
1011 GUID
*InterfaceGuid
,
1014 PNP_RPC_BUFFER_SIZE
*pulLength
,
1018 return CR_CALL_NOT_IMPLEMENTED
;
1023 DWORD
PNP_GetInterfaceDeviceListSize(
1025 PNP_RPC_BUFFER_SIZE
*pulLen
,
1026 GUID
*InterfaceGuid
,
1031 return CR_CALL_NOT_IMPLEMENTED
;
1036 DWORD
PNP_RegisterDeviceClassAssociation(
1039 GUID
*InterfaceGuid
,
1040 LPWSTR pszReference
,
1042 PNP_RPC_STRING_LEN
*pulLength
,
1043 PNP_RPC_STRING_LEN
*pulTransferLen
,
1047 return CR_CALL_NOT_IMPLEMENTED
;
1052 DWORD
PNP_UnregisterDeviceClassAssociation(
1054 LPWSTR pszInterfaceDevice
,
1058 return CR_CALL_NOT_IMPLEMENTED
;
1063 DWORD
PNP_GetClassRegProp(
1065 LPWSTR pszClassGuid
,
1067 DWORD
*pulRegDataType
,
1069 PNP_RPC_STRING_LEN
*pulTransferLen
,
1070 PNP_RPC_STRING_LEN
*pulLength
,
1074 return CR_CALL_NOT_IMPLEMENTED
;
1079 DWORD
PNP_SetClassRegProp(
1081 LPWSTR
*pszClassGuid
,
1085 PNP_PROP_SIZE ulLength
,
1089 return CR_CALL_NOT_IMPLEMENTED
;
1094 DWORD
PNP_CreateDevInst(
1097 LPWSTR pszParentDeviceID
,
1098 PNP_RPC_STRING_LEN ulLength
,
1102 return CR_CALL_NOT_IMPLEMENTED
;
1107 MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination
,
1108 LPWSTR pszDeviceInstanceSource
)
1110 DPRINT("MoveDeviceInstance: not implemented\n");
1112 return CR_CALL_NOT_IMPLEMENTED
;
1117 SetupDeviceInstance(LPWSTR pszDeviceInstance
,
1120 DPRINT("SetupDeviceInstance: not implemented\n");
1122 return CR_CALL_NOT_IMPLEMENTED
;
1127 EnableDeviceInstance(LPWSTR pszDeviceInstance
)
1129 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
1130 CONFIGRET ret
= CR_SUCCESS
;
1133 DPRINT("Enable device instance\n");
1135 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, pszDeviceInstance
);
1136 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
1137 if (!NT_SUCCESS(Status
))
1138 ret
= NtStatusToCrError(Status
);
1145 DisableDeviceInstance(LPWSTR pszDeviceInstance
)
1147 DPRINT("DisableDeviceInstance: not implemented\n");
1149 return CR_CALL_NOT_IMPLEMENTED
;
1154 ReenumerateDeviceInstance(LPWSTR pszDeviceInstance
)
1156 DPRINT("ReenumerateDeviceInstance: not implemented\n");
1158 return CR_CALL_NOT_IMPLEMENTED
;
1163 DWORD
PNP_DeviceInstanceAction(
1167 LPWSTR pszDeviceInstance1
,
1168 LPWSTR pszDeviceInstance2
)
1170 CONFIGRET ret
= CR_SUCCESS
;
1172 UNREFERENCED_PARAMETER(hBinding
);
1174 DPRINT("PNP_DeviceInstanceAction() called\n");
1178 case PNP_DEVINST_MOVE
:
1179 ret
= MoveDeviceInstance(pszDeviceInstance1
,
1180 pszDeviceInstance2
);
1183 case PNP_DEVINST_SETUP
:
1184 ret
= SetupDeviceInstance(pszDeviceInstance1
,
1188 case PNP_DEVINST_ENABLE
:
1189 ret
= EnableDeviceInstance(pszDeviceInstance1
);
1192 case PNP_DEVINST_DISABLE
:
1193 ret
= DisableDeviceInstance(pszDeviceInstance1
);
1196 case PNP_DEVINST_REENUMERATE
:
1197 ret
= ReenumerateDeviceInstance(pszDeviceInstance1
);
1201 DPRINT1("Unknown device action %lu: not implemented\n", ulAction
);
1202 ret
= CR_CALL_NOT_IMPLEMENTED
;
1205 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret
);
1212 DWORD
PNP_GetDeviceStatus(
1219 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData
;
1220 CONFIGRET ret
= CR_SUCCESS
;
1223 UNREFERENCED_PARAMETER(hBinding
);
1224 UNREFERENCED_PARAMETER(ulFlags
);
1226 DPRINT("PNP_GetDeviceStatus() called\n");
1228 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
1230 PlugPlayData
.Operation
= 0; /* Get status */
1232 Status
= NtPlugPlayControl(PlugPlayControlDeviceStatus
,
1233 (PVOID
)&PlugPlayData
,
1234 sizeof(PLUGPLAY_CONTROL_STATUS_DATA
));
1235 if (NT_SUCCESS(Status
))
1237 *pulStatus
= PlugPlayData
.DeviceStatus
;
1238 *pulProblem
= PlugPlayData
.DeviceProblem
;
1242 ret
= NtStatusToCrError(Status
);
1245 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret
);
1252 DWORD
PNP_SetDeviceProblem(
1259 return CR_CALL_NOT_IMPLEMENTED
;
1264 DWORD
PNP_DisableDevInst(
1267 PPNP_VETO_TYPE pVetoType
,
1273 return CR_CALL_NOT_IMPLEMENTED
;
1277 DWORD
PNP_UninstallDevInst(
1283 return CR_CALL_NOT_IMPLEMENTED
;
1288 CheckForDeviceId(LPWSTR lpDeviceIdList
,
1294 lpPtr
= lpDeviceIdList
;
1297 dwLength
= wcslen(lpPtr
);
1298 if (0 == _wcsicmp(lpPtr
, lpDeviceId
))
1301 lpPtr
+= (dwLength
+ 1);
1309 AppendDeviceId(LPWSTR lpDeviceIdList
,
1310 LPDWORD lpDeviceIdListSize
,
1316 dwLen
= wcslen(lpDeviceId
);
1317 dwPos
= (*lpDeviceIdListSize
/ sizeof(WCHAR
)) - 1;
1319 wcscpy(&lpDeviceIdList
[dwPos
], lpDeviceId
);
1321 dwPos
+= (dwLen
+ 1);
1323 lpDeviceIdList
[dwPos
] = 0;
1325 *lpDeviceIdListSize
= dwPos
* sizeof(WCHAR
);
1336 CONFIGRET ret
= CR_SUCCESS
;
1339 DWORD dwDeviceIdListSize
;
1340 DWORD dwNewDeviceIdSize
;
1341 WCHAR
* pszDeviceIdList
= NULL
;
1343 UNREFERENCED_PARAMETER(hBinding
);
1345 DPRINT("PNP_AddID() called\n");
1346 DPRINT(" DeviceInstance: %S\n", pszDeviceID
);
1347 DPRINT(" DeviceId: %S\n", pszID
);
1348 DPRINT(" Flags: %lx\n", ulFlags
);
1350 if (RegOpenKeyExW(hEnumKey
,
1353 KEY_QUERY_VALUE
| KEY_SET_VALUE
,
1354 &hDeviceKey
) != ERROR_SUCCESS
)
1356 DPRINT("Failed to open the device key!\n");
1357 return CR_INVALID_DEVNODE
;
1360 pszSubKey
= (ulFlags
& CM_ADD_ID_COMPATIBLE
) ? L
"CompatibleIDs" : L
"HardwareID";
1362 if (RegQueryValueExW(hDeviceKey
,
1367 &dwDeviceIdListSize
) != ERROR_SUCCESS
)
1369 DPRINT("Failed to query the desired ID string!\n");
1370 ret
= CR_REGISTRY_ERROR
;
1374 dwNewDeviceIdSize
= lstrlenW(pszDeviceID
);
1375 if (!dwNewDeviceIdSize
)
1377 ret
= CR_INVALID_POINTER
;
1381 dwDeviceIdListSize
+= (dwNewDeviceIdSize
+ 2) * sizeof(WCHAR
);
1383 pszDeviceIdList
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDeviceIdListSize
);
1384 if (!pszDeviceIdList
)
1386 DPRINT("Failed to allocate memory for the desired ID string!\n");
1387 ret
= CR_OUT_OF_MEMORY
;
1391 if (RegQueryValueExW(hDeviceKey
,
1395 (LPBYTE
)pszDeviceIdList
,
1396 &dwDeviceIdListSize
) != ERROR_SUCCESS
)
1398 DPRINT("Failed to query the desired ID string!\n");
1399 ret
= CR_REGISTRY_ERROR
;
1403 /* Check whether the device ID is already in use */
1404 if (CheckForDeviceId(pszDeviceIdList
, pszDeviceID
))
1406 DPRINT("Device ID was found in the ID string!\n");
1411 /* Append the Device ID */
1412 AppendDeviceId(pszDeviceIdList
, &dwDeviceIdListSize
, pszID
);
1414 if (RegSetValueExW(hDeviceKey
,
1418 (LPBYTE
)pszDeviceIdList
,
1419 dwDeviceIdListSize
) != ERROR_SUCCESS
)
1421 DPRINT("Failed to set the desired ID string!\n");
1422 ret
= CR_REGISTRY_ERROR
;
1426 RegCloseKey(hDeviceKey
);
1427 if (pszDeviceIdList
)
1428 HeapFree(GetProcessHeap(), 0, pszDeviceIdList
);
1430 DPRINT("PNP_AddID() done (returns %lx)\n", ret
);
1437 DWORD
PNP_RegisterDriver(
1443 return CR_CALL_NOT_IMPLEMENTED
;
1448 DWORD
PNP_QueryRemove(
1451 PPNP_VETO_TYPE pVetoType
,
1457 return CR_CALL_NOT_IMPLEMENTED
;
1462 DWORD
PNP_RequestDeviceEject(
1465 PPNP_VETO_TYPE pVetoType
,
1471 return CR_CALL_NOT_IMPLEMENTED
;
1476 PNP_IsDockStationPresent(handle_t hBinding
,
1483 CONFIGRET ret
= CR_SUCCESS
;
1485 UNREFERENCED_PARAMETER(hBinding
);
1487 DPRINT1("PNP_IsDockStationPresent() called\n");
1491 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG
,
1495 &hKey
) != ERROR_SUCCESS
)
1496 return CR_REGISTRY_ERROR
;
1498 dwSize
= sizeof(DWORD
);
1499 if (RegQueryValueExW(hKey
,
1504 &dwSize
) != ERROR_SUCCESS
)
1505 ret
= CR_REGISTRY_ERROR
;
1509 if (ret
== CR_SUCCESS
)
1511 if (dwType
!= REG_DWORD
|| dwSize
!= sizeof(DWORD
))
1513 ret
= CR_REGISTRY_ERROR
;
1515 else if (dwValue
!= 0)
1521 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret
);
1528 DWORD
PNP_RequestEjectPC(
1532 return CR_CALL_NOT_IMPLEMENTED
;
1537 DWORD
PNP_HwProfFlags(
1543 PPNP_VETO_TYPE pVetoType
,
1548 CONFIGRET ret
= CR_SUCCESS
;
1549 WCHAR szKeyName
[MAX_PATH
];
1554 UNREFERENCED_PARAMETER(hBinding
);
1556 DPRINT("PNP_HwProfFlags() called\n");
1561 L
"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
1566 L
"System\\CurrentControlSet\\HardwareProfiles\\%04u\\System\\CurrentControlSet\\Enum",
1570 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1574 &hKey
) != ERROR_SUCCESS
)
1575 return CR_REGISTRY_ERROR
;
1577 if (ulAction
== PNP_GET_HWPROFFLAGS
)
1579 if (RegOpenKeyExW(hKey
,
1583 &hDeviceKey
) != ERROR_SUCCESS
)
1589 dwSize
= sizeof(DWORD
);
1590 if (!RegQueryValueExW(hDeviceKey
,
1595 &dwSize
) != ERROR_SUCCESS
)
1600 RegCloseKey(hDeviceKey
);
1603 else if (ulAction
== PNP_SET_HWPROFFLAGS
)
1605 /* FIXME: not implemented yet */
1606 ret
= CR_CALL_NOT_IMPLEMENTED
;
1616 DWORD
PNP_GetHwProfInfo(
1619 HWPROFILEINFO
*pHWProfileInfo
,
1620 DWORD ulProfileInfoSize
,
1624 return CR_CALL_NOT_IMPLEMENTED
;
1629 DWORD
PNP_AddEmptyLogConf(
1633 DWORD
*pulLogConfTag
,
1637 return CR_CALL_NOT_IMPLEMENTED
;
1642 DWORD
PNP_FreeLogConf(
1645 DWORD ulLogConfType
,
1650 return CR_CALL_NOT_IMPLEMENTED
;
1655 DWORD
PNP_GetFirstLogConf(
1658 DWORD ulLogConfType
,
1659 DWORD
*pulLogConfTag
,
1663 return CR_CALL_NOT_IMPLEMENTED
;
1668 DWORD
PNP_GetNextLogConf(
1671 DWORD ulLogConfType
,
1677 return CR_CALL_NOT_IMPLEMENTED
;
1682 DWORD
PNP_GetLogConfPriority(
1691 return CR_CALL_NOT_IMPLEMENTED
;
1696 DWORD
PNP_AddResDes(
1700 DWORD ulLogConfType
,
1701 RESOURCEID ResourceID
,
1702 DWORD
*pulResourceTag
,
1704 PNP_RPC_BUFFER_SIZE ResourceLen
,
1708 return CR_CALL_NOT_IMPLEMENTED
;
1713 DWORD
PNP_FreeResDes(
1717 DWORD ulLogConfType
,
1718 RESOURCEID ResourceID
,
1719 DWORD ulResourceTag
,
1720 DWORD
*pulPreviousResType
,
1721 DWORD
*pulPreviousResTag
,
1725 return CR_CALL_NOT_IMPLEMENTED
;
1730 DWORD
PNP_GetNextResDes(
1734 DWORD ulLogConfType
,
1735 RESOURCEID ResourceID
,
1736 DWORD ulResourceTag
,
1737 DWORD
*pulNextResType
,
1738 DWORD
*pulNextResTag
,
1742 return CR_CALL_NOT_IMPLEMENTED
;
1747 DWORD
PNP_GetResDesData(
1751 DWORD ulLogConfType
,
1752 RESOURCEID ResourceID
,
1753 DWORD ulResourceTag
,
1755 PNP_RPC_BUFFER_SIZE BufferLen
,
1759 return CR_CALL_NOT_IMPLEMENTED
;
1764 DWORD
PNP_GetResDesDataSize(
1768 DWORD ulLogConfType
,
1769 RESOURCEID ResourceID
,
1770 DWORD ulResourceTag
,
1775 return CR_CALL_NOT_IMPLEMENTED
;
1780 DWORD
PNP_ModifyResDes(
1784 DWORD ulLogConfType
,
1785 RESOURCEID CurrentResourceID
,
1786 RESOURCEID NewResourceID
,
1787 DWORD ulResourceTag
,
1789 PNP_RPC_BUFFER_SIZE ResourceLen
,
1793 return CR_CALL_NOT_IMPLEMENTED
;
1798 DWORD
PNP_DetectResourceConflict(
1801 RESOURCEID ResourceID
,
1803 PNP_RPC_BUFFER_SIZE ResourceLen
,
1804 BOOL
*pbConflictDetected
,
1808 return CR_CALL_NOT_IMPLEMENTED
;
1813 DWORD
PNP_QueryResConfList(
1816 RESOURCEID ResourceID
,
1818 PNP_RPC_BUFFER_SIZE ResourceLen
,
1820 PNP_RPC_BUFFER_SIZE BufferLen
,
1824 return CR_CALL_NOT_IMPLEMENTED
;
1829 DWORD
PNP_SetHwProf(
1831 DWORD ulHardwareProfile
,
1835 return CR_CALL_NOT_IMPLEMENTED
;
1840 DWORD
PNP_QueryArbitratorFreeData(
1844 return CR_CALL_NOT_IMPLEMENTED
;
1849 DWORD
PNP_QueryArbitratorFreeSize(
1853 return CR_CALL_NOT_IMPLEMENTED
;
1864 return CR_CALL_NOT_IMPLEMENTED
;
1869 DWORD
PNP_RegisterNotification(
1873 return CR_CALL_NOT_IMPLEMENTED
;
1878 DWORD
PNP_UnregisterNotification(
1882 return CR_CALL_NOT_IMPLEMENTED
;
1887 DWORD
PNP_GetCustomDevProp(
1890 LPWSTR CustomPropName
,
1891 DWORD
*pulRegDataType
,
1893 PNP_RPC_STRING_LEN
*pulTransferLen
,
1894 PNP_RPC_STRING_LEN
*pulLength
,
1898 return CR_CALL_NOT_IMPLEMENTED
;
1903 DWORD
PNP_GetVersionInternal(
1908 return CR_CALL_NOT_IMPLEMENTED
;
1913 DWORD
PNP_GetBlockedDriverInfo(
1916 PNP_RPC_BUFFER_SIZE
*pulTransferLen
,
1917 PNP_RPC_BUFFER_SIZE
*pulLength
,
1921 return CR_CALL_NOT_IMPLEMENTED
;
1926 DWORD
PNP_GetServerSideDeviceInstallFlags(
1928 DWORD
*pulSSDIFlags
,
1932 return CR_CALL_NOT_IMPLEMENTED
;
1937 DWORD
PNP_GetObjectPropKeys(
1941 LPWSTR PropertyCultureName
,
1942 PNP_PROP_COUNT
*PropertyCount
,
1943 PNP_PROP_COUNT
*TransferLen
,
1944 DEVPROPKEY
*PropertyKeys
,
1948 return CR_CALL_NOT_IMPLEMENTED
;
1953 DWORD
PNP_GetObjectProp(
1957 LPWSTR PropertyCultureName
,
1958 const DEVPROPKEY
*PropertyKey
,
1959 DEVPROPTYPE
*PropertyType
,
1960 PNP_PROP_SIZE
*PropertySize
,
1961 PNP_PROP_SIZE
*TransferLen
,
1962 BYTE
*PropertyBuffer
,
1966 return CR_CALL_NOT_IMPLEMENTED
;
1971 DWORD
PNP_SetObjectProp(
1975 LPWSTR PropertyCultureName
,
1976 const DEVPROPKEY
*PropertyKey
,
1977 DEVPROPTYPE PropertyType
,
1978 PNP_PROP_SIZE PropertySize
,
1979 BYTE
*PropertyBuffer
,
1983 return CR_CALL_NOT_IMPLEMENTED
;
1988 DWORD
PNP_InstallDevInst(
1992 return CR_CALL_NOT_IMPLEMENTED
;
1997 DWORD
PNP_ApplyPowerSettings(
2001 return CR_CALL_NOT_IMPLEMENTED
;
2006 DWORD
PNP_DriverStoreAddDriverPackage(
2010 return CR_CALL_NOT_IMPLEMENTED
;
2015 DWORD
PNP_DriverStoreDeleteDriverPackage(
2019 return CR_CALL_NOT_IMPLEMENTED
;
2024 DWORD
PNP_RegisterServiceNotification(
2028 return CR_CALL_NOT_IMPLEMENTED
;
2033 DWORD
PNP_SetActiveService(
2037 return CR_CALL_NOT_IMPLEMENTED
;
2042 DWORD
PNP_DeleteServiceDevices(
2046 return CR_CALL_NOT_IMPLEMENTED
;
2051 InstallDevice(PCWSTR DeviceInstance
, BOOL ShowWizard
)
2053 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData
;
2055 BOOL DeviceInstalled
= FALSE
;
2058 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
2059 LPVOID Environment
= NULL
;
2060 PROCESS_INFORMATION ProcessInfo
;
2061 STARTUPINFOW StartupInfo
;
2064 /* The following lengths are constant (see below), they cannot overflow */
2065 WCHAR CommandLine
[116];
2066 WCHAR InstallEventName
[73];
2068 WCHAR UuidString
[39];
2070 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance
, ShowWizard
);
2072 ZeroMemory(&ProcessInfo
, sizeof(ProcessInfo
));
2074 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
2076 PlugPlayData
.Operation
= 0; /* Get status */
2078 /* Get device status */
2079 Status
= NtPlugPlayControl(PlugPlayControlDeviceStatus
,
2080 (PVOID
)&PlugPlayData
,
2081 sizeof(PLUGPLAY_CONTROL_STATUS_DATA
));
2082 if (!NT_SUCCESS(Status
))
2084 DPRINT1("NtPlugPlayControl('%S') failed with status 0x%08lx\n", DeviceInstance
, Status
);
2088 if ((PlugPlayData
.DeviceStatus
& (DNF_STARTED
| DNF_START_FAILED
)) != 0)
2090 /* Device is already started, or disabled due to some problem. Don't install it */
2091 DPRINT("No need to install '%S'\n", DeviceInstance
);
2095 /* Create a random UUID for the named pipe */
2096 UuidCreate(&RandomUuid
);
2097 swprintf(UuidString
, L
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
2098 RandomUuid
.Data1
, RandomUuid
.Data2
, RandomUuid
.Data3
,
2099 RandomUuid
.Data4
[0], RandomUuid
.Data4
[1], RandomUuid
.Data4
[2],
2100 RandomUuid
.Data4
[3], RandomUuid
.Data4
[4], RandomUuid
.Data4
[5],
2101 RandomUuid
.Data4
[6], RandomUuid
.Data4
[7]);
2103 /* Create the named pipe */
2104 wcscpy(PipeName
, L
"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
2105 wcscat(PipeName
, UuidString
);
2106 hPipe
= CreateNamedPipeW(PipeName
, PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_BYTE
, 1, 512, 512, 0, NULL
);
2108 if(hPipe
== INVALID_HANDLE_VALUE
)
2110 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
2114 /* Launch rundll32 to call ClientSideInstallW */
2115 wcscpy(CommandLine
, L
"rundll32.exe newdev.dll,ClientSideInstall ");
2116 wcscat(CommandLine
, PipeName
);
2118 ZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
2119 StartupInfo
.cb
= sizeof(StartupInfo
);
2123 /* newdev has to run under the environment of the current user */
2124 if(!CreateEnvironmentBlock(&Environment
, hUserToken
, FALSE
))
2126 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
2130 if(!CreateProcessAsUserW(hUserToken
, NULL
, CommandLine
, NULL
, NULL
, FALSE
, CREATE_UNICODE_ENVIRONMENT
, Environment
, NULL
, &StartupInfo
, &ProcessInfo
))
2132 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
2138 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
2140 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
2141 (ShowWizard is only set to FALSE for these two modes) */
2142 ASSERT(!ShowWizard
);
2144 if(!CreateProcessW(NULL
, CommandLine
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &StartupInfo
, &ProcessInfo
))
2146 DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
2151 /* Wait for the function to connect to our pipe */
2152 if(!ConnectNamedPipe(hPipe
, NULL
))
2154 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
2158 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
2159 wcscpy(InstallEventName
, L
"Global\\PNP_Device_Install_Event_0.");
2160 wcscat(InstallEventName
, UuidString
);
2162 Value
= sizeof(InstallEventName
);
2163 WriteFile(hPipe
, &Value
, sizeof(Value
), &BytesWritten
, NULL
);
2164 WriteFile(hPipe
, InstallEventName
, Value
, &BytesWritten
, NULL
);
2166 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
2167 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
2168 WriteFile(hPipe
, &ShowWizard
, sizeof(ShowWizard
), &BytesWritten
, NULL
);
2170 Value
= (wcslen(DeviceInstance
) + 1) * sizeof(WCHAR
);
2171 WriteFile(hPipe
, &Value
, sizeof(Value
), &BytesWritten
, NULL
);
2172 WriteFile(hPipe
, DeviceInstance
, Value
, &BytesWritten
, NULL
);
2174 /* Wait for newdev.dll to finish processing */
2175 WaitForSingleObject(ProcessInfo
.hProcess
, INFINITE
);
2177 /* The following check for success is probably not compatible to Windows, but should do its job */
2178 if(!GetExitCodeProcess(ProcessInfo
.hProcess
, &Value
))
2180 DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
2184 DeviceInstalled
= Value
;
2187 if(hPipe
!= INVALID_HANDLE_VALUE
)
2191 DestroyEnvironmentBlock(Environment
);
2193 if(ProcessInfo
.hProcess
)
2194 CloseHandle(ProcessInfo
.hProcess
);
2196 if(ProcessInfo
.hThread
)
2197 CloseHandle(ProcessInfo
.hThread
);
2199 return DeviceInstalled
;
2215 return ERROR_INVALID_PARAMETER
;
2218 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, &dwType
, NULL
, &cbData
);
2219 if (rc
!= ERROR_SUCCESS
)
2221 if (dwType
!= REG_SZ
)
2222 return ERROR_FILE_NOT_FOUND
;
2223 Value
= HeapAlloc(GetProcessHeap(), 0, cbData
+ sizeof(WCHAR
));
2225 return ERROR_NOT_ENOUGH_MEMORY
;
2226 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, NULL
, (LPBYTE
)Value
, &cbData
);
2227 if (rc
!= ERROR_SUCCESS
)
2229 HeapFree(GetProcessHeap(), 0, Value
);
2232 /* NULL-terminate the string */
2233 Value
[cbData
/ sizeof(WCHAR
)] = '\0';
2236 return ERROR_SUCCESS
;
2244 DWORD regType
, active
, size
;
2248 rc
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\Setup", 0, KEY_QUERY_VALUE
, &hKey
);
2249 if (rc
!= ERROR_SUCCESS
)
2252 size
= sizeof(DWORD
);
2253 rc
= RegQueryValueExW(hKey
, L
"SystemSetupInProgress", NULL
, ®Type
, (LPBYTE
)&active
, &size
);
2254 if (rc
!= ERROR_SUCCESS
)
2256 if (regType
!= REG_DWORD
|| size
!= sizeof(DWORD
))
2259 ret
= (active
!= 0);
2265 DPRINT("System setup in progress? %S\n", ret
? L
"YES" : L
"NO");
2274 HKEY ControlKey
= NULL
;
2275 LPWSTR SystemStartOptions
= NULL
;
2276 LPWSTR CurrentOption
, NextOption
; /* Pointers into SystemStartOptions */
2277 BOOL ConsoleBoot
= FALSE
;
2282 L
"SYSTEM\\CurrentControlSet\\Control",
2287 rc
= ReadRegSzKey(ControlKey
, L
"SystemStartOptions", &SystemStartOptions
);
2288 if (rc
!= ERROR_SUCCESS
)
2291 /* Check for CMDCONS in SystemStartOptions */
2292 CurrentOption
= SystemStartOptions
;
2293 while (CurrentOption
)
2295 NextOption
= wcschr(CurrentOption
, L
' ');
2297 *NextOption
= L
'\0';
2298 if (_wcsicmp(CurrentOption
, L
"CONSOLE") == 0)
2300 DPRINT("Found %S. Switching to console boot\n", CurrentOption
);
2304 CurrentOption
= NextOption
? NextOption
+ 1 : NULL
;
2308 if (ControlKey
!= NULL
)
2309 RegCloseKey(ControlKey
);
2310 HeapFree(GetProcessHeap(), 0, SystemStartOptions
);
2315 /* Loop to install all queued devices installations */
2317 DeviceInstallThread(LPVOID lpParameter
)
2319 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2320 PSLIST_ENTRY ListEntry
;
2322 PLIST_ENTRY ListEntry
;
2324 DeviceInstallParams
* Params
;
2327 UNREFERENCED_PARAMETER(lpParameter
);
2329 WaitForSingleObject(hInstallEvent
, INFINITE
);
2331 showWizard
= !SetupIsActive() && !IsConsoleBoot();
2335 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2336 ListEntry
= InterlockedPopEntrySList(&DeviceInstallListHead
);
2338 if ((BOOL
)IsListEmpty(&DeviceInstallListHead
))
2341 ListEntry
= RemoveHeadList(&DeviceInstallListHead
);
2343 if (ListEntry
== NULL
)
2345 SetEvent(hNoPendingInstalls
);
2346 WaitForSingleObject(hDeviceInstallListNotEmpty
, INFINITE
);
2350 ResetEvent(hNoPendingInstalls
);
2351 Params
= CONTAINING_RECORD(ListEntry
, DeviceInstallParams
, ListEntry
);
2352 InstallDevice(Params
->DeviceIds
, showWizard
);
2361 PnpEventThread(LPVOID lpParameter
)
2363 PPLUGPLAY_EVENT_BLOCK PnpEvent
;
2366 RPC_STATUS RpcStatus
;
2368 UNREFERENCED_PARAMETER(lpParameter
);
2370 PnpEventSize
= 0x1000;
2371 PnpEvent
= HeapAlloc(GetProcessHeap(), 0, PnpEventSize
);
2372 if (PnpEvent
== NULL
)
2373 return ERROR_OUTOFMEMORY
;
2377 DPRINT("Calling NtGetPlugPlayEvent()\n");
2379 /* Wait for the next pnp event */
2380 Status
= NtGetPlugPlayEvent(0, 0, PnpEvent
, PnpEventSize
);
2382 /* Resize the buffer for the PnP event if it's too small. */
2383 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2385 PnpEventSize
+= 0x400;
2386 HeapFree(GetProcessHeap(), 0, PnpEvent
);
2387 PnpEvent
= HeapAlloc(GetProcessHeap(), 0, PnpEventSize
);
2388 if (PnpEvent
== NULL
)
2389 return ERROR_OUTOFMEMORY
;
2393 if (!NT_SUCCESS(Status
))
2395 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status
);
2399 /* Process the pnp event */
2400 DPRINT("Received PnP Event\n");
2401 if (UuidEqual(&PnpEvent
->EventGuid
, (UUID
*)&GUID_DEVICE_ENUMERATED
, &RpcStatus
))
2403 DeviceInstallParams
* Params
;
2405 DWORD DeviceIdLength
;
2407 DPRINT("Device enumerated: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
2409 DeviceIdLength
= lstrlenW(PnpEvent
->TargetDevice
.DeviceIds
);
2412 /* Queue device install (will be dequeued by DeviceInstallThread */
2413 len
= FIELD_OFFSET(DeviceInstallParams
, DeviceIds
) + (DeviceIdLength
+ 1) * sizeof(WCHAR
);
2414 Params
= HeapAlloc(GetProcessHeap(), 0, len
);
2417 wcscpy(Params
->DeviceIds
, PnpEvent
->TargetDevice
.DeviceIds
);
2418 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2419 InterlockedPushEntrySList(&DeviceInstallListHead
, &Params
->ListEntry
);
2421 InsertTailList(&DeviceInstallListHead
, &Params
->ListEntry
);
2423 SetEvent(hDeviceInstallListNotEmpty
);
2427 else if (UuidEqual(&PnpEvent
->EventGuid
, (UUID
*)&GUID_DEVICE_ARRIVAL
, &RpcStatus
))
2429 DPRINT("Device arrival: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
2434 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
2435 PnpEvent
->EventGuid
.Data1
, PnpEvent
->EventGuid
.Data2
, PnpEvent
->EventGuid
.Data3
,
2436 PnpEvent
->EventGuid
.Data4
[0], PnpEvent
->EventGuid
.Data4
[1], PnpEvent
->EventGuid
.Data4
[2],
2437 PnpEvent
->EventGuid
.Data4
[3], PnpEvent
->EventGuid
.Data4
[4], PnpEvent
->EventGuid
.Data4
[5],
2438 PnpEvent
->EventGuid
.Data4
[6], PnpEvent
->EventGuid
.Data4
[7]);
2441 /* Dequeue the current pnp event and signal the next one */
2442 NtPlugPlayControl(PlugPlayControlUserResponse
, NULL
, 0);
2445 HeapFree(GetProcessHeap(), 0, PnpEvent
);
2447 return ERROR_SUCCESS
;
2452 UpdateServiceStatus(DWORD dwState
)
2454 ServiceStatus
.dwServiceType
= SERVICE_WIN32_OWN_PROCESS
;
2455 ServiceStatus
.dwCurrentState
= dwState
;
2456 ServiceStatus
.dwControlsAccepted
= 0;
2457 ServiceStatus
.dwWin32ExitCode
= 0;
2458 ServiceStatus
.dwServiceSpecificExitCode
= 0;
2459 ServiceStatus
.dwCheckPoint
= 0;
2461 if (dwState
== SERVICE_START_PENDING
||
2462 dwState
== SERVICE_STOP_PENDING
||
2463 dwState
== SERVICE_PAUSE_PENDING
||
2464 dwState
== SERVICE_CONTINUE_PENDING
)
2465 ServiceStatus
.dwWaitHint
= 10000;
2467 ServiceStatus
.dwWaitHint
= 0;
2469 SetServiceStatus(ServiceStatusHandle
,
2475 ServiceControlHandler(DWORD dwControl
,
2480 DPRINT1("ServiceControlHandler() called\n");
2484 case SERVICE_CONTROL_STOP
:
2485 DPRINT1(" SERVICE_CONTROL_STOP received\n");
2486 UpdateServiceStatus(SERVICE_STOPPED
);
2487 return ERROR_SUCCESS
;
2489 case SERVICE_CONTROL_PAUSE
:
2490 DPRINT1(" SERVICE_CONTROL_PAUSE received\n");
2491 UpdateServiceStatus(SERVICE_PAUSED
);
2492 return ERROR_SUCCESS
;
2494 case SERVICE_CONTROL_CONTINUE
:
2495 DPRINT1(" SERVICE_CONTROL_CONTINUE received\n");
2496 UpdateServiceStatus(SERVICE_RUNNING
);
2497 return ERROR_SUCCESS
;
2499 case SERVICE_CONTROL_INTERROGATE
:
2500 DPRINT1(" SERVICE_CONTROL_INTERROGATE received\n");
2501 SetServiceStatus(ServiceStatusHandle
,
2503 return ERROR_SUCCESS
;
2505 case SERVICE_CONTROL_SHUTDOWN
:
2506 DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n");
2507 UpdateServiceStatus(SERVICE_STOPPED
);
2508 return ERROR_SUCCESS
;
2511 DPRINT1(" Control %lu received\n");
2512 return ERROR_CALL_NOT_IMPLEMENTED
;
2517 static VOID CALLBACK
2518 ServiceMain(DWORD argc
, LPTSTR
*argv
)
2523 UNREFERENCED_PARAMETER(argc
);
2524 UNREFERENCED_PARAMETER(argv
);
2526 DPRINT("ServiceMain() called\n");
2528 ServiceStatusHandle
= RegisterServiceCtrlHandlerExW(ServiceName
,
2529 ServiceControlHandler
,
2531 if (!ServiceStatusHandle
)
2533 DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
2537 UpdateServiceStatus(SERVICE_START_PENDING
);
2539 hThread
= CreateThread(NULL
,
2545 if (hThread
!= NULL
)
2546 CloseHandle(hThread
);
2548 hThread
= CreateThread(NULL
,
2554 if (hThread
!= NULL
)
2555 CloseHandle(hThread
);
2557 hThread
= CreateThread(NULL
,
2559 DeviceInstallThread
,
2563 if (hThread
!= NULL
)
2564 CloseHandle(hThread
);
2566 UpdateServiceStatus(SERVICE_RUNNING
);
2568 DPRINT("ServiceMain() done\n");
2573 wmain(int argc
, WCHAR
*argv
[])
2578 UNREFERENCED_PARAMETER(argc
);
2579 UNREFERENCED_PARAMETER(argv
);
2581 DPRINT("Umpnpmgr: main() started\n");
2583 /* We need this privilege for using CreateProcessAsUserW */
2584 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
, TRUE
, FALSE
, &OldValue
);
2586 hInstallEvent
= CreateEvent(NULL
, TRUE
, SetupIsActive()/*FALSE*/, NULL
);
2587 if (hInstallEvent
== NULL
)
2589 dwError
= GetLastError();
2590 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError
);
2594 hDeviceInstallListNotEmpty
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
2595 if (hDeviceInstallListNotEmpty
== NULL
)
2597 dwError
= GetLastError();
2598 DPRINT1("Could not create the Event! (Error %lu)\n", dwError
);
2602 hNoPendingInstalls
= CreateEventW(NULL
,
2605 L
"Global\\PnP_No_Pending_Install_Events");
2606 if (hNoPendingInstalls
== NULL
)
2608 dwError
= GetLastError();
2609 DPRINT1("Could not create the Event! (Error %lu)\n", dwError
);
2613 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2614 InitializeSListHead(&DeviceInstallListHead
);
2616 InitializeListHead(&DeviceInstallListHead
);
2619 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2620 L
"System\\CurrentControlSet\\Enum",
2624 if (dwError
!= ERROR_SUCCESS
)
2626 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError
);
2630 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2631 L
"System\\CurrentControlSet\\Control\\Class",
2635 if (dwError
!= ERROR_SUCCESS
)
2637 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError
);
2641 StartServiceCtrlDispatcher(ServiceTable
);
2643 DPRINT("Umpnpmgr: main() done\n");