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(
1861 return CR_CALL_NOT_IMPLEMENTED
;
1866 DWORD
PNP_QueryArbitratorFreeSize(
1870 return CR_CALL_NOT_IMPLEMENTED
;
1881 return CR_CALL_NOT_IMPLEMENTED
;
1886 DWORD
PNP_RegisterNotification(
1890 return CR_CALL_NOT_IMPLEMENTED
;
1895 DWORD
PNP_UnregisterNotification(
1899 return CR_CALL_NOT_IMPLEMENTED
;
1904 DWORD
PNP_GetCustomDevProp(
1907 LPWSTR CustomPropName
,
1908 DWORD
*pulRegDataType
,
1910 PNP_RPC_STRING_LEN
*pulTransferLen
,
1911 PNP_RPC_STRING_LEN
*pulLength
,
1915 return CR_CALL_NOT_IMPLEMENTED
;
1920 DWORD
PNP_GetVersionInternal(
1925 return CR_CALL_NOT_IMPLEMENTED
;
1930 DWORD
PNP_GetBlockedDriverInfo(
1933 PNP_RPC_BUFFER_SIZE
*pulTransferLen
,
1934 PNP_RPC_BUFFER_SIZE
*pulLength
,
1938 return CR_CALL_NOT_IMPLEMENTED
;
1943 DWORD
PNP_GetServerSideDeviceInstallFlags(
1945 DWORD
*pulSSDIFlags
,
1949 return CR_CALL_NOT_IMPLEMENTED
;
1954 DWORD
PNP_GetObjectPropKeys(
1958 LPWSTR PropertyCultureName
,
1959 PNP_PROP_COUNT
*PropertyCount
,
1960 PNP_PROP_COUNT
*TransferLen
,
1961 DEVPROPKEY
*PropertyKeys
,
1965 return CR_CALL_NOT_IMPLEMENTED
;
1970 DWORD
PNP_GetObjectProp(
1974 LPWSTR PropertyCultureName
,
1975 const DEVPROPKEY
*PropertyKey
,
1976 DEVPROPTYPE
*PropertyType
,
1977 PNP_PROP_SIZE
*PropertySize
,
1978 PNP_PROP_SIZE
*TransferLen
,
1979 BYTE
*PropertyBuffer
,
1983 return CR_CALL_NOT_IMPLEMENTED
;
1988 DWORD
PNP_SetObjectProp(
1992 LPWSTR PropertyCultureName
,
1993 const DEVPROPKEY
*PropertyKey
,
1994 DEVPROPTYPE PropertyType
,
1995 PNP_PROP_SIZE PropertySize
,
1996 BYTE
*PropertyBuffer
,
2000 return CR_CALL_NOT_IMPLEMENTED
;
2005 DWORD
PNP_InstallDevInst(
2009 return CR_CALL_NOT_IMPLEMENTED
;
2014 DWORD
PNP_ApplyPowerSettings(
2018 return CR_CALL_NOT_IMPLEMENTED
;
2023 DWORD
PNP_DriverStoreAddDriverPackage(
2027 return CR_CALL_NOT_IMPLEMENTED
;
2032 DWORD
PNP_DriverStoreDeleteDriverPackage(
2036 return CR_CALL_NOT_IMPLEMENTED
;
2041 DWORD
PNP_RegisterServiceNotification(
2045 return CR_CALL_NOT_IMPLEMENTED
;
2050 DWORD
PNP_SetActiveService(
2054 return CR_CALL_NOT_IMPLEMENTED
;
2059 DWORD
PNP_DeleteServiceDevices(
2063 return CR_CALL_NOT_IMPLEMENTED
;
2068 InstallDevice(PCWSTR DeviceInstance
, BOOL ShowWizard
)
2070 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData
;
2072 BOOL DeviceInstalled
= FALSE
;
2075 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
2076 LPVOID Environment
= NULL
;
2077 PROCESS_INFORMATION ProcessInfo
;
2078 STARTUPINFOW StartupInfo
;
2081 /* The following lengths are constant (see below), they cannot overflow */
2082 WCHAR CommandLine
[116];
2083 WCHAR InstallEventName
[73];
2085 WCHAR UuidString
[39];
2087 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance
, ShowWizard
);
2089 ZeroMemory(&ProcessInfo
, sizeof(ProcessInfo
));
2091 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
2093 PlugPlayData
.Operation
= 0; /* Get status */
2095 /* Get device status */
2096 Status
= NtPlugPlayControl(PlugPlayControlDeviceStatus
,
2097 (PVOID
)&PlugPlayData
,
2098 sizeof(PLUGPLAY_CONTROL_STATUS_DATA
));
2099 if (!NT_SUCCESS(Status
))
2101 DPRINT1("NtPlugPlayControl('%S') failed with status 0x%08lx\n", DeviceInstance
, Status
);
2105 if ((PlugPlayData
.DeviceStatus
& (DNF_STARTED
| DNF_START_FAILED
)) != 0)
2107 /* Device is already started, or disabled due to some problem. Don't install it */
2108 DPRINT("No need to install '%S'\n", DeviceInstance
);
2112 /* Create a random UUID for the named pipe */
2113 UuidCreate(&RandomUuid
);
2114 swprintf(UuidString
, L
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
2115 RandomUuid
.Data1
, RandomUuid
.Data2
, RandomUuid
.Data3
,
2116 RandomUuid
.Data4
[0], RandomUuid
.Data4
[1], RandomUuid
.Data4
[2],
2117 RandomUuid
.Data4
[3], RandomUuid
.Data4
[4], RandomUuid
.Data4
[5],
2118 RandomUuid
.Data4
[6], RandomUuid
.Data4
[7]);
2120 /* Create the named pipe */
2121 wcscpy(PipeName
, L
"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
2122 wcscat(PipeName
, UuidString
);
2123 hPipe
= CreateNamedPipeW(PipeName
, PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_BYTE
, 1, 512, 512, 0, NULL
);
2125 if(hPipe
== INVALID_HANDLE_VALUE
)
2127 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
2131 /* Launch rundll32 to call ClientSideInstallW */
2132 wcscpy(CommandLine
, L
"rundll32.exe newdev.dll,ClientSideInstall ");
2133 wcscat(CommandLine
, PipeName
);
2135 ZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
2136 StartupInfo
.cb
= sizeof(StartupInfo
);
2140 /* newdev has to run under the environment of the current user */
2141 if(!CreateEnvironmentBlock(&Environment
, hUserToken
, FALSE
))
2143 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
2147 if(!CreateProcessAsUserW(hUserToken
, NULL
, CommandLine
, NULL
, NULL
, FALSE
, CREATE_UNICODE_ENVIRONMENT
, Environment
, NULL
, &StartupInfo
, &ProcessInfo
))
2149 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
2155 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
2157 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
2158 (ShowWizard is only set to FALSE for these two modes) */
2159 ASSERT(!ShowWizard
);
2161 if(!CreateProcessW(NULL
, CommandLine
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &StartupInfo
, &ProcessInfo
))
2163 DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
2168 /* Wait for the function to connect to our pipe */
2169 if(!ConnectNamedPipe(hPipe
, NULL
))
2171 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
2175 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
2176 wcscpy(InstallEventName
, L
"Global\\PNP_Device_Install_Event_0.");
2177 wcscat(InstallEventName
, UuidString
);
2179 Value
= sizeof(InstallEventName
);
2180 WriteFile(hPipe
, &Value
, sizeof(Value
), &BytesWritten
, NULL
);
2181 WriteFile(hPipe
, InstallEventName
, Value
, &BytesWritten
, NULL
);
2183 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
2184 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
2185 WriteFile(hPipe
, &ShowWizard
, sizeof(ShowWizard
), &BytesWritten
, NULL
);
2187 Value
= (wcslen(DeviceInstance
) + 1) * sizeof(WCHAR
);
2188 WriteFile(hPipe
, &Value
, sizeof(Value
), &BytesWritten
, NULL
);
2189 WriteFile(hPipe
, DeviceInstance
, Value
, &BytesWritten
, NULL
);
2191 /* Wait for newdev.dll to finish processing */
2192 WaitForSingleObject(ProcessInfo
.hProcess
, INFINITE
);
2194 /* The following check for success is probably not compatible to Windows, but should do its job */
2195 if(!GetExitCodeProcess(ProcessInfo
.hProcess
, &Value
))
2197 DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
2201 DeviceInstalled
= Value
;
2204 if(hPipe
!= INVALID_HANDLE_VALUE
)
2208 DestroyEnvironmentBlock(Environment
);
2210 if(ProcessInfo
.hProcess
)
2211 CloseHandle(ProcessInfo
.hProcess
);
2213 if(ProcessInfo
.hThread
)
2214 CloseHandle(ProcessInfo
.hThread
);
2216 return DeviceInstalled
;
2232 return ERROR_INVALID_PARAMETER
;
2235 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, &dwType
, NULL
, &cbData
);
2236 if (rc
!= ERROR_SUCCESS
)
2238 if (dwType
!= REG_SZ
)
2239 return ERROR_FILE_NOT_FOUND
;
2240 Value
= HeapAlloc(GetProcessHeap(), 0, cbData
+ sizeof(WCHAR
));
2242 return ERROR_NOT_ENOUGH_MEMORY
;
2243 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, NULL
, (LPBYTE
)Value
, &cbData
);
2244 if (rc
!= ERROR_SUCCESS
)
2246 HeapFree(GetProcessHeap(), 0, Value
);
2249 /* NULL-terminate the string */
2250 Value
[cbData
/ sizeof(WCHAR
)] = '\0';
2253 return ERROR_SUCCESS
;
2261 DWORD regType
, active
, size
;
2265 rc
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\Setup", 0, KEY_QUERY_VALUE
, &hKey
);
2266 if (rc
!= ERROR_SUCCESS
)
2269 size
= sizeof(DWORD
);
2270 rc
= RegQueryValueExW(hKey
, L
"SystemSetupInProgress", NULL
, ®Type
, (LPBYTE
)&active
, &size
);
2271 if (rc
!= ERROR_SUCCESS
)
2273 if (regType
!= REG_DWORD
|| size
!= sizeof(DWORD
))
2276 ret
= (active
!= 0);
2282 DPRINT("System setup in progress? %S\n", ret
? L
"YES" : L
"NO");
2291 HKEY ControlKey
= NULL
;
2292 LPWSTR SystemStartOptions
= NULL
;
2293 LPWSTR CurrentOption
, NextOption
; /* Pointers into SystemStartOptions */
2294 BOOL ConsoleBoot
= FALSE
;
2299 L
"SYSTEM\\CurrentControlSet\\Control",
2304 rc
= ReadRegSzKey(ControlKey
, L
"SystemStartOptions", &SystemStartOptions
);
2305 if (rc
!= ERROR_SUCCESS
)
2308 /* Check for CMDCONS in SystemStartOptions */
2309 CurrentOption
= SystemStartOptions
;
2310 while (CurrentOption
)
2312 NextOption
= wcschr(CurrentOption
, L
' ');
2314 *NextOption
= L
'\0';
2315 if (_wcsicmp(CurrentOption
, L
"CONSOLE") == 0)
2317 DPRINT("Found %S. Switching to console boot\n", CurrentOption
);
2321 CurrentOption
= NextOption
? NextOption
+ 1 : NULL
;
2325 if (ControlKey
!= NULL
)
2326 RegCloseKey(ControlKey
);
2327 HeapFree(GetProcessHeap(), 0, SystemStartOptions
);
2332 /* Loop to install all queued devices installations */
2334 DeviceInstallThread(LPVOID lpParameter
)
2336 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2337 PSLIST_ENTRY ListEntry
;
2339 PLIST_ENTRY ListEntry
;
2341 DeviceInstallParams
* Params
;
2344 UNREFERENCED_PARAMETER(lpParameter
);
2346 WaitForSingleObject(hInstallEvent
, INFINITE
);
2348 showWizard
= !SetupIsActive() && !IsConsoleBoot();
2352 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2353 ListEntry
= InterlockedPopEntrySList(&DeviceInstallListHead
);
2355 if ((BOOL
)IsListEmpty(&DeviceInstallListHead
))
2358 ListEntry
= RemoveHeadList(&DeviceInstallListHead
);
2360 if (ListEntry
== NULL
)
2362 SetEvent(hNoPendingInstalls
);
2363 WaitForSingleObject(hDeviceInstallListNotEmpty
, INFINITE
);
2367 ResetEvent(hNoPendingInstalls
);
2368 Params
= CONTAINING_RECORD(ListEntry
, DeviceInstallParams
, ListEntry
);
2369 InstallDevice(Params
->DeviceIds
, showWizard
);
2378 PnpEventThread(LPVOID lpParameter
)
2380 PPLUGPLAY_EVENT_BLOCK PnpEvent
;
2383 RPC_STATUS RpcStatus
;
2385 UNREFERENCED_PARAMETER(lpParameter
);
2387 PnpEventSize
= 0x1000;
2388 PnpEvent
= HeapAlloc(GetProcessHeap(), 0, PnpEventSize
);
2389 if (PnpEvent
== NULL
)
2390 return ERROR_OUTOFMEMORY
;
2394 DPRINT("Calling NtGetPlugPlayEvent()\n");
2396 /* Wait for the next pnp event */
2397 Status
= NtGetPlugPlayEvent(0, 0, PnpEvent
, PnpEventSize
);
2399 /* Resize the buffer for the PnP event if it's too small. */
2400 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2402 PnpEventSize
+= 0x400;
2403 HeapFree(GetProcessHeap(), 0, PnpEvent
);
2404 PnpEvent
= HeapAlloc(GetProcessHeap(), 0, PnpEventSize
);
2405 if (PnpEvent
== NULL
)
2406 return ERROR_OUTOFMEMORY
;
2410 if (!NT_SUCCESS(Status
))
2412 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status
);
2416 /* Process the pnp event */
2417 DPRINT("Received PnP Event\n");
2418 if (UuidEqual(&PnpEvent
->EventGuid
, (UUID
*)&GUID_DEVICE_ENUMERATED
, &RpcStatus
))
2420 DeviceInstallParams
* Params
;
2422 DWORD DeviceIdLength
;
2424 DPRINT("Device enumerated: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
2426 DeviceIdLength
= lstrlenW(PnpEvent
->TargetDevice
.DeviceIds
);
2429 /* Queue device install (will be dequeued by DeviceInstallThread */
2430 len
= FIELD_OFFSET(DeviceInstallParams
, DeviceIds
) + (DeviceIdLength
+ 1) * sizeof(WCHAR
);
2431 Params
= HeapAlloc(GetProcessHeap(), 0, len
);
2434 wcscpy(Params
->DeviceIds
, PnpEvent
->TargetDevice
.DeviceIds
);
2435 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2436 InterlockedPushEntrySList(&DeviceInstallListHead
, &Params
->ListEntry
);
2438 InsertTailList(&DeviceInstallListHead
, &Params
->ListEntry
);
2440 SetEvent(hDeviceInstallListNotEmpty
);
2444 else if (UuidEqual(&PnpEvent
->EventGuid
, (UUID
*)&GUID_DEVICE_ARRIVAL
, &RpcStatus
))
2446 DPRINT("Device arrival: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
2451 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
2452 PnpEvent
->EventGuid
.Data1
, PnpEvent
->EventGuid
.Data2
, PnpEvent
->EventGuid
.Data3
,
2453 PnpEvent
->EventGuid
.Data4
[0], PnpEvent
->EventGuid
.Data4
[1], PnpEvent
->EventGuid
.Data4
[2],
2454 PnpEvent
->EventGuid
.Data4
[3], PnpEvent
->EventGuid
.Data4
[4], PnpEvent
->EventGuid
.Data4
[5],
2455 PnpEvent
->EventGuid
.Data4
[6], PnpEvent
->EventGuid
.Data4
[7]);
2458 /* Dequeue the current pnp event and signal the next one */
2459 NtPlugPlayControl(PlugPlayControlUserResponse
, NULL
, 0);
2462 HeapFree(GetProcessHeap(), 0, PnpEvent
);
2464 return ERROR_SUCCESS
;
2469 UpdateServiceStatus(DWORD dwState
)
2471 ServiceStatus
.dwServiceType
= SERVICE_WIN32_OWN_PROCESS
;
2472 ServiceStatus
.dwCurrentState
= dwState
;
2473 ServiceStatus
.dwControlsAccepted
= 0;
2474 ServiceStatus
.dwWin32ExitCode
= 0;
2475 ServiceStatus
.dwServiceSpecificExitCode
= 0;
2476 ServiceStatus
.dwCheckPoint
= 0;
2478 if (dwState
== SERVICE_START_PENDING
||
2479 dwState
== SERVICE_STOP_PENDING
||
2480 dwState
== SERVICE_PAUSE_PENDING
||
2481 dwState
== SERVICE_CONTINUE_PENDING
)
2482 ServiceStatus
.dwWaitHint
= 10000;
2484 ServiceStatus
.dwWaitHint
= 0;
2486 SetServiceStatus(ServiceStatusHandle
,
2492 ServiceControlHandler(DWORD dwControl
,
2497 DPRINT1("ServiceControlHandler() called\n");
2501 case SERVICE_CONTROL_STOP
:
2502 DPRINT1(" SERVICE_CONTROL_STOP received\n");
2503 UpdateServiceStatus(SERVICE_STOPPED
);
2504 return ERROR_SUCCESS
;
2506 case SERVICE_CONTROL_PAUSE
:
2507 DPRINT1(" SERVICE_CONTROL_PAUSE received\n");
2508 UpdateServiceStatus(SERVICE_PAUSED
);
2509 return ERROR_SUCCESS
;
2511 case SERVICE_CONTROL_CONTINUE
:
2512 DPRINT1(" SERVICE_CONTROL_CONTINUE received\n");
2513 UpdateServiceStatus(SERVICE_RUNNING
);
2514 return ERROR_SUCCESS
;
2516 case SERVICE_CONTROL_INTERROGATE
:
2517 DPRINT1(" SERVICE_CONTROL_INTERROGATE received\n");
2518 SetServiceStatus(ServiceStatusHandle
,
2520 return ERROR_SUCCESS
;
2522 case SERVICE_CONTROL_SHUTDOWN
:
2523 DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n");
2524 UpdateServiceStatus(SERVICE_STOPPED
);
2525 return ERROR_SUCCESS
;
2528 DPRINT1(" Control %lu received\n");
2529 return ERROR_CALL_NOT_IMPLEMENTED
;
2534 static VOID CALLBACK
2535 ServiceMain(DWORD argc
, LPTSTR
*argv
)
2540 UNREFERENCED_PARAMETER(argc
);
2541 UNREFERENCED_PARAMETER(argv
);
2543 DPRINT("ServiceMain() called\n");
2545 ServiceStatusHandle
= RegisterServiceCtrlHandlerExW(ServiceName
,
2546 ServiceControlHandler
,
2548 if (!ServiceStatusHandle
)
2550 DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
2554 UpdateServiceStatus(SERVICE_START_PENDING
);
2556 hThread
= CreateThread(NULL
,
2562 if (hThread
!= NULL
)
2563 CloseHandle(hThread
);
2565 hThread
= CreateThread(NULL
,
2571 if (hThread
!= NULL
)
2572 CloseHandle(hThread
);
2574 hThread
= CreateThread(NULL
,
2576 DeviceInstallThread
,
2580 if (hThread
!= NULL
)
2581 CloseHandle(hThread
);
2583 UpdateServiceStatus(SERVICE_RUNNING
);
2585 DPRINT("ServiceMain() done\n");
2590 wmain(int argc
, WCHAR
*argv
[])
2595 UNREFERENCED_PARAMETER(argc
);
2596 UNREFERENCED_PARAMETER(argv
);
2598 DPRINT("Umpnpmgr: main() started\n");
2600 /* We need this privilege for using CreateProcessAsUserW */
2601 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
, TRUE
, FALSE
, &OldValue
);
2603 hInstallEvent
= CreateEvent(NULL
, TRUE
, SetupIsActive()/*FALSE*/, NULL
);
2604 if (hInstallEvent
== NULL
)
2606 dwError
= GetLastError();
2607 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError
);
2611 hDeviceInstallListNotEmpty
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
2612 if (hDeviceInstallListNotEmpty
== NULL
)
2614 dwError
= GetLastError();
2615 DPRINT1("Could not create the Event! (Error %lu)\n", dwError
);
2619 hNoPendingInstalls
= CreateEventW(NULL
,
2622 L
"Global\\PnP_No_Pending_Install_Events");
2623 if (hNoPendingInstalls
== NULL
)
2625 dwError
= GetLastError();
2626 DPRINT1("Could not create the Event! (Error %lu)\n", dwError
);
2630 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2631 InitializeSListHead(&DeviceInstallListHead
);
2633 InitializeListHead(&DeviceInstallListHead
);
2636 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2637 L
"System\\CurrentControlSet\\Enum",
2641 if (dwError
!= ERROR_SUCCESS
)
2643 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError
);
2647 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2648 L
"System\\CurrentControlSet\\Control\\Class",
2652 if (dwError
!= ERROR_SUCCESS
)
2654 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError
);
2658 StartServiceCtrlDispatcher(ServiceTable
);
2660 DPRINT("Umpnpmgr: main() done\n");