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
)
97 BOOLEAN RegisteredProtSeq
= FALSE
;
99 UNREFERENCED_PARAMETER(lpParameter
);
101 DPRINT("RpcServerThread() called\n");
104 /* XP-compatible protocol sequence/endpoint */
105 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
108 NULL
); // Security descriptor
109 if (Status
== RPC_S_OK
)
110 RegisteredProtSeq
= TRUE
;
112 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
115 /* Vista-compatible protocol sequence/endpoint */
116 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
119 NULL
); // Security descriptor
120 if (Status
== RPC_S_OK
)
121 RegisteredProtSeq
= TRUE
;
123 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
125 /* Make sure there's a usable endpoint */
126 if (RegisteredProtSeq
== FALSE
)
129 Status
= RpcServerRegisterIf(pnp_v1_0_s_ifspec
,
132 if (Status
!= RPC_S_OK
)
134 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
138 Status
= RpcServerListen(1,
141 if (Status
!= RPC_S_OK
)
143 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
147 /* ROS HACK (this should never happen...) */
148 DPRINT1("*** Other devices won't be installed correctly. If something\n");
149 DPRINT1("*** doesn't work, try to reboot to get a new chance.\n");
151 DPRINT("RpcServerThread() done\n");
157 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
159 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
163 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
165 HeapFree(GetProcessHeap(), 0, ptr
);
169 static CONFIGRET WINAPI
170 NtStatusToCrError(NTSTATUS Status
)
174 case STATUS_NO_SUCH_DEVICE
:
175 return CR_NO_SUCH_DEVINST
;
178 /* FIXME: add more mappings */
179 DPRINT1("Unable to map status 0x%08lx\n", Status
);
186 DWORD
PNP_Disconnect(
189 UNREFERENCED_PARAMETER(hBinding
);
191 return CR_CALL_NOT_IMPLEMENTED
;
199 UNREFERENCED_PARAMETER(hBinding
);
201 return CR_CALL_NOT_IMPLEMENTED
;
206 DWORD
PNP_GetVersion(
210 UNREFERENCED_PARAMETER(hBinding
);
218 DWORD
PNP_GetGlobalState(
223 UNREFERENCED_PARAMETER(hBinding
);
224 UNREFERENCED_PARAMETER(ulFlags
);
226 *pulState
= CM_GLOBAL_STATE_CAN_DO_UI
| CM_GLOBAL_STATE_SERVICES_AVAILABLE
;
232 DWORD
PNP_InitDetection(
235 UNREFERENCED_PARAMETER(hBinding
);
237 DPRINT("PNP_InitDetection() called\n");
243 DWORD
PNP_ReportLogOn(
248 DWORD ReturnValue
= CR_FAILURE
;
251 UNREFERENCED_PARAMETER(hBinding
);
252 UNREFERENCED_PARAMETER(Admin
);
254 DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin
, ProcessId
);
256 /* Get the users token */
257 hProcess
= OpenProcess(PROCESS_ALL_ACCESS
, TRUE
, ProcessId
);
261 DPRINT1("OpenProcess failed with error %u\n", GetLastError());
267 CloseHandle(hUserToken
);
271 if(!OpenProcessToken(hProcess
, TOKEN_ASSIGN_PRIMARY
| TOKEN_DUPLICATE
| TOKEN_QUERY
, &hUserToken
))
273 DPRINT1("OpenProcessToken failed with error %u\n", GetLastError());
277 /* Trigger the installer thread */
279 SetEvent(hInstallEvent
);
281 ReturnValue
= CR_SUCCESS
;
285 CloseHandle(hProcess
);
292 DWORD
PNP_ValidateDeviceInstance(
297 CONFIGRET ret
= CR_SUCCESS
;
298 HKEY hDeviceKey
= NULL
;
300 UNREFERENCED_PARAMETER(hBinding
);
301 UNREFERENCED_PARAMETER(ulFlags
);
303 DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
306 if (RegOpenKeyExW(hEnumKey
,
312 DPRINT("Could not open the Device Key!\n");
313 ret
= CR_NO_SUCH_DEVNODE
;
317 /* FIXME: add more tests */
320 if (hDeviceKey
!= NULL
)
321 RegCloseKey(hDeviceKey
);
323 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret
);
330 DWORD
PNP_GetRootDeviceInstance(
333 PNP_RPC_STRING_LEN ulLength
)
335 CONFIGRET ret
= CR_SUCCESS
;
337 UNREFERENCED_PARAMETER(hBinding
);
339 DPRINT("PNP_GetRootDeviceInstance() called\n");
343 ret
= CR_INVALID_POINTER
;
346 if (ulLength
< lstrlenW(szRootDeviceId
) + 1)
348 ret
= CR_BUFFER_SMALL
;
356 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret
);
363 DWORD
PNP_GetRelatedDeviceInstance(
365 DWORD ulRelationship
,
367 LPWSTR pRelatedDeviceId
,
368 PNP_RPC_STRING_LEN
*pulLength
,
371 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData
;
372 CONFIGRET ret
= CR_SUCCESS
;
375 UNREFERENCED_PARAMETER(hBinding
);
376 UNREFERENCED_PARAMETER(ulFlags
);
378 DPRINT("PNP_GetRelatedDeviceInstance() called\n");
379 DPRINT(" Relationship %ld\n", ulRelationship
);
380 DPRINT(" DeviceId %S\n", pDeviceID
);
382 RtlInitUnicodeString(&PlugPlayData
.TargetDeviceInstance
,
385 PlugPlayData
.Relation
= ulRelationship
;
387 PlugPlayData
.RelatedDeviceInstanceLength
= *pulLength
;
388 PlugPlayData
.RelatedDeviceInstance
= pRelatedDeviceId
;
390 Status
= NtPlugPlayControl(PlugPlayControlGetRelatedDevice
,
391 (PVOID
)&PlugPlayData
,
392 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA
));
393 if (!NT_SUCCESS(Status
))
395 ret
= NtStatusToCrError(Status
);
398 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret
);
399 if (ret
== CR_SUCCESS
)
401 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData
.RelatedDeviceInstance
);
409 DWORD
PNP_EnumerateSubKeys(
414 PNP_RPC_STRING_LEN ulLength
,
415 PNP_RPC_STRING_LEN
*pulRequiredLen
,
418 CONFIGRET ret
= CR_SUCCESS
;
422 UNREFERENCED_PARAMETER(hBinding
);
423 UNREFERENCED_PARAMETER(ulFlags
);
425 DPRINT("PNP_EnumerateSubKeys() called\n");
429 case PNP_ENUMERATOR_SUBKEYS
:
433 case PNP_CLASS_SUBKEYS
:
441 *pulRequiredLen
= ulLength
;
442 dwError
= RegEnumKeyExW(hKey
,
450 if (dwError
!= ERROR_SUCCESS
)
452 ret
= (dwError
== ERROR_NO_MORE_ITEMS
) ? CR_NO_SUCH_VALUE
: CR_FAILURE
;
459 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret
);
466 DWORD
PNP_GetDeviceList(
470 PNP_RPC_STRING_LEN
*pulLength
,
474 return CR_CALL_NOT_IMPLEMENTED
;
479 DWORD
PNP_GetDeviceListSize(
482 PNP_RPC_BUFFER_SIZE
*pulLen
,
486 return CR_CALL_NOT_IMPLEMENTED
;
497 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData
;
498 CONFIGRET ret
= CR_SUCCESS
;
501 UNREFERENCED_PARAMETER(hBinding
);
502 UNREFERENCED_PARAMETER(ulFlags
);
504 DPRINT("PNP_GetDepth() called\n");
506 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
509 Status
= NtPlugPlayControl(PlugPlayControlGetDeviceDepth
,
510 (PVOID
)&PlugPlayData
,
511 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA
));
512 if (NT_SUCCESS(Status
))
514 *pulDepth
= PlugPlayData
.Depth
;
518 ret
= NtStatusToCrError(Status
);
521 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret
);
528 DWORD
PNP_GetDeviceRegProp(
532 DWORD
*pulRegDataType
,
534 PNP_PROP_SIZE
*pulTransferLen
,
535 PNP_PROP_SIZE
*pulLength
,
538 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData
;
539 CONFIGRET ret
= CR_SUCCESS
;
540 LPWSTR lpValueName
= NULL
;
544 UNREFERENCED_PARAMETER(hBinding
);
545 UNREFERENCED_PARAMETER(ulFlags
);
547 DPRINT("PNP_GetDeviceRegProp() called\n");
551 case CM_DRP_DEVICEDESC
:
552 lpValueName
= L
"DeviceDesc";
555 case CM_DRP_HARDWAREID
:
556 lpValueName
= L
"HardwareID";
559 case CM_DRP_COMPATIBLEIDS
:
560 lpValueName
= L
"CompatibleIDs";
564 lpValueName
= L
"Service";
568 lpValueName
= L
"Class";
571 case CM_DRP_CLASSGUID
:
572 lpValueName
= L
"ClassGUID";
576 lpValueName
= L
"Driver";
579 case CM_DRP_CONFIGFLAGS
:
580 lpValueName
= L
"ConfigFlags";
584 lpValueName
= L
"Mfg";
587 case CM_DRP_FRIENDLYNAME
:
588 lpValueName
= L
"FriendlyName";
591 case CM_DRP_LOCATION_INFORMATION
:
592 lpValueName
= L
"LocationInformation";
595 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME
:
599 case CM_DRP_CAPABILITIES
:
600 lpValueName
= L
"Capabilities";
603 case CM_DRP_UI_NUMBER
:
607 case CM_DRP_UPPERFILTERS
:
608 lpValueName
= L
"UpperFilters";
611 case CM_DRP_LOWERFILTERS
:
612 lpValueName
= L
"LowerFilters";
615 case CM_DRP_BUSTYPEGUID
:
619 case CM_DRP_LEGACYBUSTYPE
:
623 case CM_DRP_BUSNUMBER
:
627 case CM_DRP_ENUMERATOR_NAME
:
632 return CR_INVALID_PROPERTY
;
635 DPRINT("Value name: %S\n", lpValueName
);
639 /* Retrieve information from the Registry */
640 if (RegOpenKeyExW(hEnumKey
,
645 return CR_INVALID_DEVNODE
;
647 if (RegQueryValueExW(hKey
,
653 ret
= CR_REGISTRY_ERROR
;
655 /* FIXME: Check buffer size */
661 /* Retrieve information from the Device Node */
662 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
664 PlugPlayData
.Buffer
= Buffer
;
665 PlugPlayData
.BufferSize
= *pulTransferLen
;
670 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME
:
671 PlugPlayData
.Property
= DevicePropertyPhysicalDeviceObjectName
;
674 case CM_DRP_UI_NUMBER
:
675 PlugPlayData
.Property
= DevicePropertyUINumber
;
678 case CM_DRP_BUSTYPEGUID
:
679 PlugPlayData
.Property
= DevicePropertyBusTypeGuid
;
682 case CM_DRP_LEGACYBUSTYPE
:
683 PlugPlayData
.Property
= DevicePropertyLegacyBusType
;
686 case CM_DRP_BUSNUMBER
:
687 PlugPlayData
.Property
= DevicePropertyBusNumber
;
691 case CM_DRP_ENUMERATOR_NAME
:
692 PlugPlayData
.Property
= 15; //DevicePropertyEnumeratorName;
696 return CR_INVALID_PROPERTY
;
699 Status
= NtPlugPlayControl(PlugPlayControlProperty
,
700 (PVOID
)&PlugPlayData
,
701 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA
));
702 if (NT_SUCCESS(Status
))
704 *pulLength
= PlugPlayData
.BufferSize
;
708 ret
= NtStatusToCrError(Status
);
712 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret
);
719 DWORD
PNP_SetDeviceRegProp(
725 PNP_PROP_SIZE ulLength
,
728 CONFIGRET ret
= CR_SUCCESS
;
729 LPWSTR lpValueName
= NULL
;
732 UNREFERENCED_PARAMETER(hBinding
);
733 UNREFERENCED_PARAMETER(ulFlags
);
735 DPRINT("PNP_SetDeviceRegProp() called\n");
737 DPRINT("DeviceId: %S\n", pDeviceId
);
738 DPRINT("Property: %lu\n", ulProperty
);
739 DPRINT("DataType: %lu\n", ulDataType
);
740 DPRINT("Length: %lu\n", ulLength
);
744 case CM_DRP_DEVICEDESC
:
745 lpValueName
= L
"DeviceDesc";
748 case CM_DRP_HARDWAREID
:
749 lpValueName
= L
"HardwareID";
752 case CM_DRP_COMPATIBLEIDS
:
753 lpValueName
= L
"CompatibleIDs";
757 lpValueName
= L
"Service";
761 lpValueName
= L
"Class";
764 case CM_DRP_CLASSGUID
:
765 lpValueName
= L
"ClassGUID";
769 lpValueName
= L
"Driver";
772 case CM_DRP_CONFIGFLAGS
:
773 lpValueName
= L
"ConfigFlags";
777 lpValueName
= L
"Mfg";
780 case CM_DRP_FRIENDLYNAME
:
781 lpValueName
= L
"FriendlyName";
784 case CM_DRP_LOCATION_INFORMATION
:
785 lpValueName
= L
"LocationInformation";
788 case CM_DRP_UPPERFILTERS
:
789 lpValueName
= L
"UpperFilters";
792 case CM_DRP_LOWERFILTERS
:
793 lpValueName
= L
"LowerFilters";
797 return CR_INVALID_PROPERTY
;
800 DPRINT("Value name: %S\n", lpValueName
);
802 if (RegOpenKeyExW(hEnumKey
,
805 KEY_ALL_ACCESS
, /* FIXME: so much? */
807 return CR_INVALID_DEVNODE
;
811 if (RegDeleteValueW(hKey
,
813 ret
= CR_REGISTRY_ERROR
;
817 if (RegSetValueExW(hKey
,
823 ret
= CR_REGISTRY_ERROR
;
828 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret
);
835 DWORD
PNP_GetClassInstance(
838 LPWSTR pszClassInstance
,
839 PNP_RPC_STRING_LEN ulLength
)
842 return CR_CALL_NOT_IMPLEMENTED
;
855 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
864 return CR_REGISTRY_ERROR
;
866 /* FIXME: Set security key */
875 DWORD
PNP_DeleteRegistryKey(
883 return CR_CALL_NOT_IMPLEMENTED
;
888 DWORD
PNP_GetClassCount(
890 DWORD
*pulClassCount
,
896 UNREFERENCED_PARAMETER(hBinding
);
897 UNREFERENCED_PARAMETER(ulFlags
);
899 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
904 if (dwError
!= ERROR_SUCCESS
)
905 return CR_INVALID_DATA
;
907 dwError
= RegQueryInfoKeyW(hKey
,
920 if (dwError
!= ERROR_SUCCESS
)
921 return CR_INVALID_DATA
;
928 DWORD
PNP_GetClassName(
932 PNP_RPC_STRING_LEN
*pulLength
,
935 WCHAR szKeyName
[MAX_PATH
];
936 CONFIGRET ret
= CR_SUCCESS
;
940 UNREFERENCED_PARAMETER(hBinding
);
941 UNREFERENCED_PARAMETER(ulFlags
);
943 DPRINT("PNP_GetClassName() called\n");
945 lstrcpyW(szKeyName
, L
"System\\CurrentControlSet\\Control\\Class\\");
946 if(lstrlenW(pszClassGuid
) + 1 < sizeof(szKeyName
)/sizeof(WCHAR
)-(lstrlenW(szKeyName
) * sizeof(WCHAR
)))
947 lstrcatW(szKeyName
, pszClassGuid
);
948 else return CR_INVALID_DATA
;
950 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
955 return CR_REGISTRY_ERROR
;
957 dwSize
= *pulLength
* sizeof(WCHAR
);
958 if (RegQueryValueExW(hKey
,
966 ret
= CR_REGISTRY_ERROR
;
970 *pulLength
= dwSize
/ sizeof(WCHAR
);
975 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret
);
982 DWORD
PNP_DeleteClassKey(
987 CONFIGRET ret
= CR_SUCCESS
;
989 UNREFERENCED_PARAMETER(hBinding
);
991 DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid
, ulFlags
);
993 if (ulFlags
& CM_DELETE_CLASS_SUBKEYS
)
995 if (RegDeleteTreeW(hClassKey
, pszClassGuid
) != ERROR_SUCCESS
)
996 ret
= CR_REGISTRY_ERROR
;
1000 if (RegDeleteKeyW(hClassKey
, pszClassGuid
) != ERROR_SUCCESS
)
1001 ret
= CR_REGISTRY_ERROR
;
1004 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret
);
1011 DWORD
PNP_GetInterfaceDeviceAlias(
1013 LPWSTR pszInterfaceDevice
,
1014 GUID
*AliasInterfaceGuid
,
1015 LPWSTR pszAliasInterfaceDevice
,
1016 PNP_RPC_STRING_LEN
*pulLength
,
1017 PNP_RPC_STRING_LEN
*pulTransferLen
,
1021 return CR_CALL_NOT_IMPLEMENTED
;
1026 DWORD
PNP_GetInterfaceDeviceList(
1028 GUID
*InterfaceGuid
,
1031 PNP_RPC_BUFFER_SIZE
*pulLength
,
1035 return CR_CALL_NOT_IMPLEMENTED
;
1040 DWORD
PNP_GetInterfaceDeviceListSize(
1042 PNP_RPC_BUFFER_SIZE
*pulLen
,
1043 GUID
*InterfaceGuid
,
1048 return CR_CALL_NOT_IMPLEMENTED
;
1053 DWORD
PNP_RegisterDeviceClassAssociation(
1056 GUID
*InterfaceGuid
,
1057 LPWSTR pszReference
,
1059 PNP_RPC_STRING_LEN
*pulLength
,
1060 PNP_RPC_STRING_LEN
*pulTransferLen
,
1064 return CR_CALL_NOT_IMPLEMENTED
;
1069 DWORD
PNP_UnregisterDeviceClassAssociation(
1071 LPWSTR pszInterfaceDevice
,
1075 return CR_CALL_NOT_IMPLEMENTED
;
1080 DWORD
PNP_GetClassRegProp(
1082 LPWSTR pszClassGuid
,
1084 DWORD
*pulRegDataType
,
1086 PNP_RPC_STRING_LEN
*pulTransferLen
,
1087 PNP_RPC_STRING_LEN
*pulLength
,
1091 return CR_CALL_NOT_IMPLEMENTED
;
1096 DWORD
PNP_SetClassRegProp(
1098 LPWSTR
*pszClassGuid
,
1102 PNP_PROP_SIZE ulLength
,
1106 return CR_CALL_NOT_IMPLEMENTED
;
1111 DWORD
PNP_CreateDevInst(
1114 LPWSTR pszParentDeviceID
,
1115 PNP_RPC_STRING_LEN ulLength
,
1119 return CR_CALL_NOT_IMPLEMENTED
;
1124 MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination
,
1125 LPWSTR pszDeviceInstanceSource
)
1127 DPRINT("MoveDeviceInstance: not implemented\n");
1129 return CR_CALL_NOT_IMPLEMENTED
;
1134 SetupDeviceInstance(LPWSTR pszDeviceInstance
,
1137 DPRINT("SetupDeviceInstance: not implemented\n");
1139 return CR_CALL_NOT_IMPLEMENTED
;
1144 EnableDeviceInstance(LPWSTR pszDeviceInstance
)
1146 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
1147 CONFIGRET ret
= CR_SUCCESS
;
1150 DPRINT("Enable device instance\n");
1152 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, pszDeviceInstance
);
1153 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
1154 if (!NT_SUCCESS(Status
))
1155 ret
= NtStatusToCrError(Status
);
1162 DisableDeviceInstance(LPWSTR pszDeviceInstance
)
1164 DPRINT("DisableDeviceInstance: not implemented\n");
1166 return CR_CALL_NOT_IMPLEMENTED
;
1171 ReenumerateDeviceInstance(LPWSTR pszDeviceInstance
)
1173 DPRINT("ReenumerateDeviceInstance: not implemented\n");
1175 return CR_CALL_NOT_IMPLEMENTED
;
1180 DWORD
PNP_DeviceInstanceAction(
1184 LPWSTR pszDeviceInstance1
,
1185 LPWSTR pszDeviceInstance2
)
1187 CONFIGRET ret
= CR_SUCCESS
;
1189 UNREFERENCED_PARAMETER(hBinding
);
1191 DPRINT("PNP_DeviceInstanceAction() called\n");
1195 case PNP_DEVINST_MOVE
:
1196 ret
= MoveDeviceInstance(pszDeviceInstance1
,
1197 pszDeviceInstance2
);
1200 case PNP_DEVINST_SETUP
:
1201 ret
= SetupDeviceInstance(pszDeviceInstance1
,
1205 case PNP_DEVINST_ENABLE
:
1206 ret
= EnableDeviceInstance(pszDeviceInstance1
);
1209 case PNP_DEVINST_DISABLE
:
1210 ret
= DisableDeviceInstance(pszDeviceInstance1
);
1213 case PNP_DEVINST_REENUMERATE
:
1214 ret
= ReenumerateDeviceInstance(pszDeviceInstance1
);
1218 DPRINT1("Unknown device action %lu: not implemented\n", ulAction
);
1219 ret
= CR_CALL_NOT_IMPLEMENTED
;
1222 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret
);
1229 DWORD
PNP_GetDeviceStatus(
1236 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData
;
1237 CONFIGRET ret
= CR_SUCCESS
;
1240 UNREFERENCED_PARAMETER(hBinding
);
1241 UNREFERENCED_PARAMETER(ulFlags
);
1243 DPRINT("PNP_GetDeviceStatus() called\n");
1245 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
1247 PlugPlayData
.Operation
= 0; /* Get status */
1249 Status
= NtPlugPlayControl(PlugPlayControlDeviceStatus
,
1250 (PVOID
)&PlugPlayData
,
1251 sizeof(PLUGPLAY_CONTROL_STATUS_DATA
));
1252 if (NT_SUCCESS(Status
))
1254 *pulStatus
= PlugPlayData
.DeviceStatus
;
1255 *pulProblem
= PlugPlayData
.DeviceProblem
;
1259 ret
= NtStatusToCrError(Status
);
1262 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret
);
1269 DWORD
PNP_SetDeviceProblem(
1276 return CR_CALL_NOT_IMPLEMENTED
;
1281 DWORD
PNP_DisableDevInst(
1284 PPNP_VETO_TYPE pVetoType
,
1290 return CR_CALL_NOT_IMPLEMENTED
;
1294 DWORD
PNP_UninstallDevInst(
1300 return CR_CALL_NOT_IMPLEMENTED
;
1305 CheckForDeviceId(LPWSTR lpDeviceIdList
,
1311 lpPtr
= lpDeviceIdList
;
1314 dwLength
= wcslen(lpPtr
);
1315 if (0 == _wcsicmp(lpPtr
, lpDeviceId
))
1318 lpPtr
+= (dwLength
+ 1);
1326 AppendDeviceId(LPWSTR lpDeviceIdList
,
1327 LPDWORD lpDeviceIdListSize
,
1333 dwLen
= wcslen(lpDeviceId
);
1334 dwPos
= (*lpDeviceIdListSize
/ sizeof(WCHAR
)) - 1;
1336 wcscpy(&lpDeviceIdList
[dwPos
], lpDeviceId
);
1338 dwPos
+= (dwLen
+ 1);
1340 lpDeviceIdList
[dwPos
] = 0;
1342 *lpDeviceIdListSize
= dwPos
* sizeof(WCHAR
);
1353 CONFIGRET ret
= CR_SUCCESS
;
1356 DWORD dwDeviceIdListSize
;
1357 DWORD dwNewDeviceIdSize
;
1358 WCHAR
* pszDeviceIdList
= NULL
;
1360 UNREFERENCED_PARAMETER(hBinding
);
1362 DPRINT("PNP_AddID() called\n");
1363 DPRINT(" DeviceInstance: %S\n", pszDeviceID
);
1364 DPRINT(" DeviceId: %S\n", pszID
);
1365 DPRINT(" Flags: %lx\n", ulFlags
);
1367 if (RegOpenKeyExW(hEnumKey
,
1370 KEY_QUERY_VALUE
| KEY_SET_VALUE
,
1371 &hDeviceKey
) != ERROR_SUCCESS
)
1373 DPRINT("Failed to open the device key!\n");
1374 return CR_INVALID_DEVNODE
;
1377 pszSubKey
= (ulFlags
& CM_ADD_ID_COMPATIBLE
) ? L
"CompatibleIDs" : L
"HardwareID";
1379 if (RegQueryValueExW(hDeviceKey
,
1384 &dwDeviceIdListSize
) != ERROR_SUCCESS
)
1386 DPRINT("Failed to query the desired ID string!\n");
1387 ret
= CR_REGISTRY_ERROR
;
1391 dwNewDeviceIdSize
= lstrlenW(pszDeviceID
);
1392 if (!dwNewDeviceIdSize
)
1394 ret
= CR_INVALID_POINTER
;
1398 dwDeviceIdListSize
+= (dwNewDeviceIdSize
+ 2) * sizeof(WCHAR
);
1400 pszDeviceIdList
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDeviceIdListSize
);
1401 if (!pszDeviceIdList
)
1403 DPRINT("Failed to allocate memory for the desired ID string!\n");
1404 ret
= CR_OUT_OF_MEMORY
;
1408 if (RegQueryValueExW(hDeviceKey
,
1412 (LPBYTE
)pszDeviceIdList
,
1413 &dwDeviceIdListSize
) != ERROR_SUCCESS
)
1415 DPRINT("Failed to query the desired ID string!\n");
1416 ret
= CR_REGISTRY_ERROR
;
1420 /* Check whether the device ID is already in use */
1421 if (CheckForDeviceId(pszDeviceIdList
, pszDeviceID
))
1423 DPRINT("Device ID was found in the ID string!\n");
1428 /* Append the Device ID */
1429 AppendDeviceId(pszDeviceIdList
, &dwDeviceIdListSize
, pszID
);
1431 if (RegSetValueExW(hDeviceKey
,
1435 (LPBYTE
)pszDeviceIdList
,
1436 dwDeviceIdListSize
) != ERROR_SUCCESS
)
1438 DPRINT("Failed to set the desired ID string!\n");
1439 ret
= CR_REGISTRY_ERROR
;
1443 RegCloseKey(hDeviceKey
);
1444 if (pszDeviceIdList
)
1445 HeapFree(GetProcessHeap(), 0, pszDeviceIdList
);
1447 DPRINT("PNP_AddID() done (returns %lx)\n", ret
);
1454 DWORD
PNP_RegisterDriver(
1460 return CR_CALL_NOT_IMPLEMENTED
;
1465 DWORD
PNP_QueryRemove(
1468 PPNP_VETO_TYPE pVetoType
,
1474 return CR_CALL_NOT_IMPLEMENTED
;
1479 DWORD
PNP_RequestDeviceEject(
1482 PPNP_VETO_TYPE pVetoType
,
1488 return CR_CALL_NOT_IMPLEMENTED
;
1493 PNP_IsDockStationPresent(handle_t hBinding
,
1500 CONFIGRET ret
= CR_SUCCESS
;
1502 UNREFERENCED_PARAMETER(hBinding
);
1504 DPRINT1("PNP_IsDockStationPresent() called\n");
1508 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG
,
1512 &hKey
) != ERROR_SUCCESS
)
1513 return CR_REGISTRY_ERROR
;
1515 dwSize
= sizeof(DWORD
);
1516 if (RegQueryValueExW(hKey
,
1521 &dwSize
) != ERROR_SUCCESS
)
1522 ret
= CR_REGISTRY_ERROR
;
1526 if (ret
== CR_SUCCESS
)
1528 if (dwType
!= REG_DWORD
|| dwSize
!= sizeof(DWORD
))
1530 ret
= CR_REGISTRY_ERROR
;
1532 else if (dwValue
!= 0)
1538 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret
);
1545 DWORD
PNP_RequestEjectPC(
1549 return CR_CALL_NOT_IMPLEMENTED
;
1554 DWORD
PNP_HwProfFlags(
1560 PPNP_VETO_TYPE pVetoType
,
1565 CONFIGRET ret
= CR_SUCCESS
;
1566 WCHAR szKeyName
[MAX_PATH
];
1571 UNREFERENCED_PARAMETER(hBinding
);
1573 DPRINT("PNP_HwProfFlags() called\n");
1578 L
"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
1583 L
"System\\CurrentControlSet\\HardwareProfiles\\%04u\\System\\CurrentControlSet\\Enum",
1587 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1591 &hKey
) != ERROR_SUCCESS
)
1592 return CR_REGISTRY_ERROR
;
1594 if (ulAction
== PNP_GET_HWPROFFLAGS
)
1596 if (RegOpenKeyExW(hKey
,
1600 &hDeviceKey
) != ERROR_SUCCESS
)
1606 dwSize
= sizeof(DWORD
);
1607 if (!RegQueryValueExW(hDeviceKey
,
1612 &dwSize
) != ERROR_SUCCESS
)
1617 RegCloseKey(hDeviceKey
);
1620 else if (ulAction
== PNP_SET_HWPROFFLAGS
)
1622 /* FIXME: not implemented yet */
1623 ret
= CR_CALL_NOT_IMPLEMENTED
;
1633 DWORD
PNP_GetHwProfInfo(
1636 HWPROFILEINFO
*pHWProfileInfo
,
1637 DWORD ulProfileInfoSize
,
1641 return CR_CALL_NOT_IMPLEMENTED
;
1646 DWORD
PNP_AddEmptyLogConf(
1650 DWORD
*pulLogConfTag
,
1654 return CR_CALL_NOT_IMPLEMENTED
;
1659 DWORD
PNP_FreeLogConf(
1662 DWORD ulLogConfType
,
1667 return CR_CALL_NOT_IMPLEMENTED
;
1672 DWORD
PNP_GetFirstLogConf(
1675 DWORD ulLogConfType
,
1676 DWORD
*pulLogConfTag
,
1680 return CR_CALL_NOT_IMPLEMENTED
;
1685 DWORD
PNP_GetNextLogConf(
1688 DWORD ulLogConfType
,
1694 return CR_CALL_NOT_IMPLEMENTED
;
1699 DWORD
PNP_GetLogConfPriority(
1708 return CR_CALL_NOT_IMPLEMENTED
;
1713 DWORD
PNP_AddResDes(
1717 DWORD ulLogConfType
,
1718 RESOURCEID ResourceID
,
1719 DWORD
*pulResourceTag
,
1721 PNP_RPC_BUFFER_SIZE ResourceLen
,
1725 return CR_CALL_NOT_IMPLEMENTED
;
1730 DWORD
PNP_FreeResDes(
1734 DWORD ulLogConfType
,
1735 RESOURCEID ResourceID
,
1736 DWORD ulResourceTag
,
1737 DWORD
*pulPreviousResType
,
1738 DWORD
*pulPreviousResTag
,
1742 return CR_CALL_NOT_IMPLEMENTED
;
1747 DWORD
PNP_GetNextResDes(
1751 DWORD ulLogConfType
,
1752 RESOURCEID ResourceID
,
1753 DWORD ulResourceTag
,
1754 DWORD
*pulNextResType
,
1755 DWORD
*pulNextResTag
,
1759 return CR_CALL_NOT_IMPLEMENTED
;
1764 DWORD
PNP_GetResDesData(
1768 DWORD ulLogConfType
,
1769 RESOURCEID ResourceID
,
1770 DWORD ulResourceTag
,
1772 PNP_RPC_BUFFER_SIZE BufferLen
,
1776 return CR_CALL_NOT_IMPLEMENTED
;
1781 DWORD
PNP_GetResDesDataSize(
1785 DWORD ulLogConfType
,
1786 RESOURCEID ResourceID
,
1787 DWORD ulResourceTag
,
1792 return CR_CALL_NOT_IMPLEMENTED
;
1797 DWORD
PNP_ModifyResDes(
1801 DWORD ulLogConfType
,
1802 RESOURCEID CurrentResourceID
,
1803 RESOURCEID NewResourceID
,
1804 DWORD ulResourceTag
,
1806 PNP_RPC_BUFFER_SIZE ResourceLen
,
1810 return CR_CALL_NOT_IMPLEMENTED
;
1815 DWORD
PNP_DetectResourceConflict(
1818 RESOURCEID ResourceID
,
1820 PNP_RPC_BUFFER_SIZE ResourceLen
,
1821 BOOL
*pbConflictDetected
,
1825 return CR_CALL_NOT_IMPLEMENTED
;
1830 DWORD
PNP_QueryResConfList(
1833 RESOURCEID ResourceID
,
1835 PNP_RPC_BUFFER_SIZE ResourceLen
,
1837 PNP_RPC_BUFFER_SIZE BufferLen
,
1841 return CR_CALL_NOT_IMPLEMENTED
;
1846 DWORD
PNP_SetHwProf(
1848 DWORD ulHardwareProfile
,
1852 return CR_CALL_NOT_IMPLEMENTED
;
1857 DWORD
PNP_QueryArbitratorFreeData(
1862 RESOURCEID ResourceID
,
1866 return CR_CALL_NOT_IMPLEMENTED
;
1871 DWORD
PNP_QueryArbitratorFreeSize(
1875 RESOURCEID ResourceID
,
1879 return CR_CALL_NOT_IMPLEMENTED
;
1890 return CR_CALL_NOT_IMPLEMENTED
;
1895 DWORD
PNP_RegisterNotification(
1899 return CR_CALL_NOT_IMPLEMENTED
;
1904 DWORD
PNP_UnregisterNotification(
1908 return CR_CALL_NOT_IMPLEMENTED
;
1913 DWORD
PNP_GetCustomDevProp(
1916 LPWSTR CustomPropName
,
1917 DWORD
*pulRegDataType
,
1919 PNP_RPC_STRING_LEN
*pulTransferLen
,
1920 PNP_RPC_STRING_LEN
*pulLength
,
1924 return CR_CALL_NOT_IMPLEMENTED
;
1929 DWORD
PNP_GetVersionInternal(
1934 return CR_CALL_NOT_IMPLEMENTED
;
1939 DWORD
PNP_GetBlockedDriverInfo(
1942 PNP_RPC_BUFFER_SIZE
*pulTransferLen
,
1943 PNP_RPC_BUFFER_SIZE
*pulLength
,
1947 return CR_CALL_NOT_IMPLEMENTED
;
1952 DWORD
PNP_GetServerSideDeviceInstallFlags(
1954 DWORD
*pulSSDIFlags
,
1958 return CR_CALL_NOT_IMPLEMENTED
;
1963 DWORD
PNP_GetObjectPropKeys(
1967 LPWSTR PropertyCultureName
,
1968 PNP_PROP_COUNT
*PropertyCount
,
1969 PNP_PROP_COUNT
*TransferLen
,
1970 DEVPROPKEY
*PropertyKeys
,
1974 return CR_CALL_NOT_IMPLEMENTED
;
1979 DWORD
PNP_GetObjectProp(
1983 LPWSTR PropertyCultureName
,
1984 const DEVPROPKEY
*PropertyKey
,
1985 DEVPROPTYPE
*PropertyType
,
1986 PNP_PROP_SIZE
*PropertySize
,
1987 PNP_PROP_SIZE
*TransferLen
,
1988 BYTE
*PropertyBuffer
,
1992 return CR_CALL_NOT_IMPLEMENTED
;
1997 DWORD
PNP_SetObjectProp(
2001 LPWSTR PropertyCultureName
,
2002 const DEVPROPKEY
*PropertyKey
,
2003 DEVPROPTYPE PropertyType
,
2004 PNP_PROP_SIZE PropertySize
,
2005 BYTE
*PropertyBuffer
,
2009 return CR_CALL_NOT_IMPLEMENTED
;
2014 DWORD
PNP_InstallDevInst(
2018 return CR_CALL_NOT_IMPLEMENTED
;
2023 DWORD
PNP_ApplyPowerSettings(
2027 return CR_CALL_NOT_IMPLEMENTED
;
2032 DWORD
PNP_DriverStoreAddDriverPackage(
2036 return CR_CALL_NOT_IMPLEMENTED
;
2041 DWORD
PNP_DriverStoreDeleteDriverPackage(
2045 return CR_CALL_NOT_IMPLEMENTED
;
2050 DWORD
PNP_RegisterServiceNotification(
2054 return CR_CALL_NOT_IMPLEMENTED
;
2059 DWORD
PNP_SetActiveService(
2063 return CR_CALL_NOT_IMPLEMENTED
;
2068 DWORD
PNP_DeleteServiceDevices(
2072 return CR_CALL_NOT_IMPLEMENTED
;
2077 InstallDevice(PCWSTR DeviceInstance
, BOOL ShowWizard
)
2079 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData
;
2081 BOOL DeviceInstalled
= FALSE
;
2084 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
2085 LPVOID Environment
= NULL
;
2086 PROCESS_INFORMATION ProcessInfo
;
2087 STARTUPINFOW StartupInfo
;
2090 /* The following lengths are constant (see below), they cannot overflow */
2091 WCHAR CommandLine
[116];
2092 WCHAR InstallEventName
[73];
2094 WCHAR UuidString
[39];
2096 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance
, ShowWizard
);
2098 ZeroMemory(&ProcessInfo
, sizeof(ProcessInfo
));
2100 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
2102 PlugPlayData
.Operation
= 0; /* Get status */
2104 /* Get device status */
2105 Status
= NtPlugPlayControl(PlugPlayControlDeviceStatus
,
2106 (PVOID
)&PlugPlayData
,
2107 sizeof(PLUGPLAY_CONTROL_STATUS_DATA
));
2108 if (!NT_SUCCESS(Status
))
2110 DPRINT1("NtPlugPlayControl('%S') failed with status 0x%08lx\n", DeviceInstance
, Status
);
2114 if ((PlugPlayData
.DeviceStatus
& (DNF_STARTED
| DNF_START_FAILED
)) != 0)
2116 /* Device is already started, or disabled due to some problem. Don't install it */
2117 DPRINT("No need to install '%S'\n", DeviceInstance
);
2121 /* Create a random UUID for the named pipe */
2122 UuidCreate(&RandomUuid
);
2123 swprintf(UuidString
, L
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
2124 RandomUuid
.Data1
, RandomUuid
.Data2
, RandomUuid
.Data3
,
2125 RandomUuid
.Data4
[0], RandomUuid
.Data4
[1], RandomUuid
.Data4
[2],
2126 RandomUuid
.Data4
[3], RandomUuid
.Data4
[4], RandomUuid
.Data4
[5],
2127 RandomUuid
.Data4
[6], RandomUuid
.Data4
[7]);
2129 /* Create the named pipe */
2130 wcscpy(PipeName
, L
"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
2131 wcscat(PipeName
, UuidString
);
2132 hPipe
= CreateNamedPipeW(PipeName
, PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_BYTE
, 1, 512, 512, 0, NULL
);
2134 if(hPipe
== INVALID_HANDLE_VALUE
)
2136 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
2140 /* Launch rundll32 to call ClientSideInstallW */
2141 wcscpy(CommandLine
, L
"rundll32.exe newdev.dll,ClientSideInstall ");
2142 wcscat(CommandLine
, PipeName
);
2144 ZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
2145 StartupInfo
.cb
= sizeof(StartupInfo
);
2149 /* newdev has to run under the environment of the current user */
2150 if(!CreateEnvironmentBlock(&Environment
, hUserToken
, FALSE
))
2152 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
2156 if(!CreateProcessAsUserW(hUserToken
, NULL
, CommandLine
, NULL
, NULL
, FALSE
, CREATE_UNICODE_ENVIRONMENT
, Environment
, NULL
, &StartupInfo
, &ProcessInfo
))
2158 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
2164 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
2166 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
2167 (ShowWizard is only set to FALSE for these two modes) */
2168 ASSERT(!ShowWizard
);
2170 if(!CreateProcessW(NULL
, CommandLine
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &StartupInfo
, &ProcessInfo
))
2172 DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
2177 /* Wait for the function to connect to our pipe */
2178 if(!ConnectNamedPipe(hPipe
, NULL
))
2180 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
2184 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
2185 wcscpy(InstallEventName
, L
"Global\\PNP_Device_Install_Event_0.");
2186 wcscat(InstallEventName
, UuidString
);
2188 Value
= sizeof(InstallEventName
);
2189 WriteFile(hPipe
, &Value
, sizeof(Value
), &BytesWritten
, NULL
);
2190 WriteFile(hPipe
, InstallEventName
, Value
, &BytesWritten
, NULL
);
2192 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
2193 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
2194 WriteFile(hPipe
, &ShowWizard
, sizeof(ShowWizard
), &BytesWritten
, NULL
);
2196 Value
= (wcslen(DeviceInstance
) + 1) * sizeof(WCHAR
);
2197 WriteFile(hPipe
, &Value
, sizeof(Value
), &BytesWritten
, NULL
);
2198 WriteFile(hPipe
, DeviceInstance
, Value
, &BytesWritten
, NULL
);
2200 /* Wait for newdev.dll to finish processing */
2201 WaitForSingleObject(ProcessInfo
.hProcess
, INFINITE
);
2203 /* The following check for success is probably not compatible to Windows, but should do its job */
2204 if(!GetExitCodeProcess(ProcessInfo
.hProcess
, &Value
))
2206 DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
2210 DeviceInstalled
= Value
;
2213 if(hPipe
!= INVALID_HANDLE_VALUE
)
2217 DestroyEnvironmentBlock(Environment
);
2219 if(ProcessInfo
.hProcess
)
2220 CloseHandle(ProcessInfo
.hProcess
);
2222 if(ProcessInfo
.hThread
)
2223 CloseHandle(ProcessInfo
.hThread
);
2225 return DeviceInstalled
;
2241 return ERROR_INVALID_PARAMETER
;
2244 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, &dwType
, NULL
, &cbData
);
2245 if (rc
!= ERROR_SUCCESS
)
2247 if (dwType
!= REG_SZ
)
2248 return ERROR_FILE_NOT_FOUND
;
2249 Value
= HeapAlloc(GetProcessHeap(), 0, cbData
+ sizeof(WCHAR
));
2251 return ERROR_NOT_ENOUGH_MEMORY
;
2252 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, NULL
, (LPBYTE
)Value
, &cbData
);
2253 if (rc
!= ERROR_SUCCESS
)
2255 HeapFree(GetProcessHeap(), 0, Value
);
2258 /* NULL-terminate the string */
2259 Value
[cbData
/ sizeof(WCHAR
)] = '\0';
2262 return ERROR_SUCCESS
;
2270 DWORD regType
, active
, size
;
2274 rc
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\Setup", 0, KEY_QUERY_VALUE
, &hKey
);
2275 if (rc
!= ERROR_SUCCESS
)
2278 size
= sizeof(DWORD
);
2279 rc
= RegQueryValueExW(hKey
, L
"SystemSetupInProgress", NULL
, ®Type
, (LPBYTE
)&active
, &size
);
2280 if (rc
!= ERROR_SUCCESS
)
2282 if (regType
!= REG_DWORD
|| size
!= sizeof(DWORD
))
2285 ret
= (active
!= 0);
2291 DPRINT("System setup in progress? %S\n", ret
? L
"YES" : L
"NO");
2300 HKEY ControlKey
= NULL
;
2301 LPWSTR SystemStartOptions
= NULL
;
2302 LPWSTR CurrentOption
, NextOption
; /* Pointers into SystemStartOptions */
2303 BOOL ConsoleBoot
= FALSE
;
2308 L
"SYSTEM\\CurrentControlSet\\Control",
2313 rc
= ReadRegSzKey(ControlKey
, L
"SystemStartOptions", &SystemStartOptions
);
2314 if (rc
!= ERROR_SUCCESS
)
2317 /* Check for CMDCONS in SystemStartOptions */
2318 CurrentOption
= SystemStartOptions
;
2319 while (CurrentOption
)
2321 NextOption
= wcschr(CurrentOption
, L
' ');
2323 *NextOption
= L
'\0';
2324 if (_wcsicmp(CurrentOption
, L
"CONSOLE") == 0)
2326 DPRINT("Found %S. Switching to console boot\n", CurrentOption
);
2330 CurrentOption
= NextOption
? NextOption
+ 1 : NULL
;
2334 if (ControlKey
!= NULL
)
2335 RegCloseKey(ControlKey
);
2336 HeapFree(GetProcessHeap(), 0, SystemStartOptions
);
2341 /* Loop to install all queued devices installations */
2343 DeviceInstallThread(LPVOID lpParameter
)
2345 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2346 PSLIST_ENTRY ListEntry
;
2348 PLIST_ENTRY ListEntry
;
2350 DeviceInstallParams
* Params
;
2353 UNREFERENCED_PARAMETER(lpParameter
);
2355 WaitForSingleObject(hInstallEvent
, INFINITE
);
2357 showWizard
= !SetupIsActive() && !IsConsoleBoot();
2361 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2362 ListEntry
= InterlockedPopEntrySList(&DeviceInstallListHead
);
2364 if ((BOOL
)IsListEmpty(&DeviceInstallListHead
))
2367 ListEntry
= RemoveHeadList(&DeviceInstallListHead
);
2369 if (ListEntry
== NULL
)
2371 SetEvent(hNoPendingInstalls
);
2372 WaitForSingleObject(hDeviceInstallListNotEmpty
, INFINITE
);
2376 ResetEvent(hNoPendingInstalls
);
2377 Params
= CONTAINING_RECORD(ListEntry
, DeviceInstallParams
, ListEntry
);
2378 InstallDevice(Params
->DeviceIds
, showWizard
);
2387 PnpEventThread(LPVOID lpParameter
)
2389 PPLUGPLAY_EVENT_BLOCK PnpEvent
;
2392 RPC_STATUS RpcStatus
;
2394 UNREFERENCED_PARAMETER(lpParameter
);
2396 PnpEventSize
= 0x1000;
2397 PnpEvent
= HeapAlloc(GetProcessHeap(), 0, PnpEventSize
);
2398 if (PnpEvent
== NULL
)
2399 return ERROR_OUTOFMEMORY
;
2403 DPRINT("Calling NtGetPlugPlayEvent()\n");
2405 /* Wait for the next pnp event */
2406 Status
= NtGetPlugPlayEvent(0, 0, PnpEvent
, PnpEventSize
);
2408 /* Resize the buffer for the PnP event if it's too small. */
2409 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2411 PnpEventSize
+= 0x400;
2412 HeapFree(GetProcessHeap(), 0, PnpEvent
);
2413 PnpEvent
= HeapAlloc(GetProcessHeap(), 0, PnpEventSize
);
2414 if (PnpEvent
== NULL
)
2415 return ERROR_OUTOFMEMORY
;
2419 if (!NT_SUCCESS(Status
))
2421 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status
);
2425 /* Process the pnp event */
2426 DPRINT("Received PnP Event\n");
2427 if (UuidEqual(&PnpEvent
->EventGuid
, (UUID
*)&GUID_DEVICE_ENUMERATED
, &RpcStatus
))
2429 DeviceInstallParams
* Params
;
2431 DWORD DeviceIdLength
;
2433 DPRINT("Device enumerated: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
2435 DeviceIdLength
= lstrlenW(PnpEvent
->TargetDevice
.DeviceIds
);
2438 /* Queue device install (will be dequeued by DeviceInstallThread */
2439 len
= FIELD_OFFSET(DeviceInstallParams
, DeviceIds
) + (DeviceIdLength
+ 1) * sizeof(WCHAR
);
2440 Params
= HeapAlloc(GetProcessHeap(), 0, len
);
2443 wcscpy(Params
->DeviceIds
, PnpEvent
->TargetDevice
.DeviceIds
);
2444 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2445 InterlockedPushEntrySList(&DeviceInstallListHead
, &Params
->ListEntry
);
2447 InsertTailList(&DeviceInstallListHead
, &Params
->ListEntry
);
2449 SetEvent(hDeviceInstallListNotEmpty
);
2453 else if (UuidEqual(&PnpEvent
->EventGuid
, (UUID
*)&GUID_DEVICE_ARRIVAL
, &RpcStatus
))
2455 DPRINT("Device arrival: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
2460 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
2461 PnpEvent
->EventGuid
.Data1
, PnpEvent
->EventGuid
.Data2
, PnpEvent
->EventGuid
.Data3
,
2462 PnpEvent
->EventGuid
.Data4
[0], PnpEvent
->EventGuid
.Data4
[1], PnpEvent
->EventGuid
.Data4
[2],
2463 PnpEvent
->EventGuid
.Data4
[3], PnpEvent
->EventGuid
.Data4
[4], PnpEvent
->EventGuid
.Data4
[5],
2464 PnpEvent
->EventGuid
.Data4
[6], PnpEvent
->EventGuid
.Data4
[7]);
2467 /* Dequeue the current pnp event and signal the next one */
2468 NtPlugPlayControl(PlugPlayControlUserResponse
, NULL
, 0);
2471 HeapFree(GetProcessHeap(), 0, PnpEvent
);
2473 return ERROR_SUCCESS
;
2478 UpdateServiceStatus(DWORD dwState
)
2480 ServiceStatus
.dwServiceType
= SERVICE_WIN32_OWN_PROCESS
;
2481 ServiceStatus
.dwCurrentState
= dwState
;
2482 ServiceStatus
.dwControlsAccepted
= 0;
2483 ServiceStatus
.dwWin32ExitCode
= 0;
2484 ServiceStatus
.dwServiceSpecificExitCode
= 0;
2485 ServiceStatus
.dwCheckPoint
= 0;
2487 if (dwState
== SERVICE_START_PENDING
||
2488 dwState
== SERVICE_STOP_PENDING
||
2489 dwState
== SERVICE_PAUSE_PENDING
||
2490 dwState
== SERVICE_CONTINUE_PENDING
)
2491 ServiceStatus
.dwWaitHint
= 10000;
2493 ServiceStatus
.dwWaitHint
= 0;
2495 SetServiceStatus(ServiceStatusHandle
,
2501 ServiceControlHandler(DWORD dwControl
,
2506 DPRINT1("ServiceControlHandler() called\n");
2510 case SERVICE_CONTROL_STOP
:
2511 DPRINT1(" SERVICE_CONTROL_STOP received\n");
2512 UpdateServiceStatus(SERVICE_STOPPED
);
2513 return ERROR_SUCCESS
;
2515 case SERVICE_CONTROL_PAUSE
:
2516 DPRINT1(" SERVICE_CONTROL_PAUSE received\n");
2517 UpdateServiceStatus(SERVICE_PAUSED
);
2518 return ERROR_SUCCESS
;
2520 case SERVICE_CONTROL_CONTINUE
:
2521 DPRINT1(" SERVICE_CONTROL_CONTINUE received\n");
2522 UpdateServiceStatus(SERVICE_RUNNING
);
2523 return ERROR_SUCCESS
;
2525 case SERVICE_CONTROL_INTERROGATE
:
2526 DPRINT1(" SERVICE_CONTROL_INTERROGATE received\n");
2527 SetServiceStatus(ServiceStatusHandle
,
2529 return ERROR_SUCCESS
;
2531 case SERVICE_CONTROL_SHUTDOWN
:
2532 DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n");
2533 UpdateServiceStatus(SERVICE_STOPPED
);
2534 return ERROR_SUCCESS
;
2537 DPRINT1(" Control %lu received\n");
2538 return ERROR_CALL_NOT_IMPLEMENTED
;
2543 static VOID CALLBACK
2544 ServiceMain(DWORD argc
, LPTSTR
*argv
)
2549 UNREFERENCED_PARAMETER(argc
);
2550 UNREFERENCED_PARAMETER(argv
);
2552 DPRINT("ServiceMain() called\n");
2554 ServiceStatusHandle
= RegisterServiceCtrlHandlerExW(ServiceName
,
2555 ServiceControlHandler
,
2557 if (!ServiceStatusHandle
)
2559 DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
2563 UpdateServiceStatus(SERVICE_START_PENDING
);
2565 hThread
= CreateThread(NULL
,
2571 if (hThread
!= NULL
)
2572 CloseHandle(hThread
);
2574 hThread
= CreateThread(NULL
,
2580 if (hThread
!= NULL
)
2581 CloseHandle(hThread
);
2583 hThread
= CreateThread(NULL
,
2585 DeviceInstallThread
,
2589 if (hThread
!= NULL
)
2590 CloseHandle(hThread
);
2592 UpdateServiceStatus(SERVICE_RUNNING
);
2594 DPRINT("ServiceMain() done\n");
2599 wmain(int argc
, WCHAR
*argv
[])
2604 UNREFERENCED_PARAMETER(argc
);
2605 UNREFERENCED_PARAMETER(argv
);
2607 DPRINT("Umpnpmgr: main() started\n");
2609 /* We need this privilege for using CreateProcessAsUserW */
2610 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
, TRUE
, FALSE
, &OldValue
);
2612 hInstallEvent
= CreateEvent(NULL
, TRUE
, SetupIsActive()/*FALSE*/, NULL
);
2613 if (hInstallEvent
== NULL
)
2615 dwError
= GetLastError();
2616 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError
);
2620 hDeviceInstallListNotEmpty
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
2621 if (hDeviceInstallListNotEmpty
== NULL
)
2623 dwError
= GetLastError();
2624 DPRINT1("Could not create the Event! (Error %lu)\n", dwError
);
2628 hNoPendingInstalls
= CreateEventW(NULL
,
2631 L
"Global\\PnP_No_Pending_Install_Events");
2632 if (hNoPendingInstalls
== NULL
)
2634 dwError
= GetLastError();
2635 DPRINT1("Could not create the Event! (Error %lu)\n", dwError
);
2639 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2640 InitializeSListHead(&DeviceInstallListHead
);
2642 InitializeListHead(&DeviceInstallListHead
);
2645 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2646 L
"System\\CurrentControlSet\\Enum",
2650 if (dwError
!= ERROR_SUCCESS
)
2652 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError
);
2656 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2657 L
"System\\CurrentControlSet\\Control\\Class",
2661 if (dwError
!= ERROR_SUCCESS
)
2663 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError
);
2667 StartServiceCtrlDispatcher(ServiceTable
);
2669 DPRINT("Umpnpmgr: main() done\n");