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
);
198 UNREFERENCED_PARAMETER(hBinding
);
204 DWORD
PNP_GetVersion(
208 UNREFERENCED_PARAMETER(hBinding
);
216 DWORD
PNP_GetGlobalState(
221 UNREFERENCED_PARAMETER(hBinding
);
222 UNREFERENCED_PARAMETER(ulFlags
);
224 *pulState
= CM_GLOBAL_STATE_CAN_DO_UI
| CM_GLOBAL_STATE_SERVICES_AVAILABLE
;
230 DWORD
PNP_InitDetection(
233 UNREFERENCED_PARAMETER(hBinding
);
235 DPRINT("PNP_InitDetection() called\n");
241 DWORD
PNP_ReportLogOn(
246 DWORD ReturnValue
= CR_FAILURE
;
249 UNREFERENCED_PARAMETER(hBinding
);
250 UNREFERENCED_PARAMETER(Admin
);
252 DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin
, ProcessId
);
254 /* Get the users token */
255 hProcess
= OpenProcess(PROCESS_ALL_ACCESS
, TRUE
, ProcessId
);
259 DPRINT1("OpenProcess failed with error %u\n", GetLastError());
265 CloseHandle(hUserToken
);
269 if(!OpenProcessToken(hProcess
, TOKEN_ASSIGN_PRIMARY
| TOKEN_DUPLICATE
| TOKEN_QUERY
, &hUserToken
))
271 DPRINT1("OpenProcessToken failed with error %u\n", GetLastError());
275 /* Trigger the installer thread */
277 SetEvent(hInstallEvent
);
279 ReturnValue
= CR_SUCCESS
;
283 CloseHandle(hProcess
);
290 DWORD
PNP_ValidateDeviceInstance(
295 CONFIGRET ret
= CR_SUCCESS
;
296 HKEY hDeviceKey
= NULL
;
298 UNREFERENCED_PARAMETER(hBinding
);
299 UNREFERENCED_PARAMETER(ulFlags
);
301 DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
304 if (RegOpenKeyExW(hEnumKey
,
310 DPRINT("Could not open the Device Key!\n");
311 ret
= CR_NO_SUCH_DEVNODE
;
315 /* FIXME: add more tests */
318 if (hDeviceKey
!= NULL
)
319 RegCloseKey(hDeviceKey
);
321 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret
);
328 DWORD
PNP_GetRootDeviceInstance(
331 PNP_RPC_STRING_LEN ulLength
)
333 CONFIGRET ret
= CR_SUCCESS
;
335 UNREFERENCED_PARAMETER(hBinding
);
337 DPRINT("PNP_GetRootDeviceInstance() called\n");
341 ret
= CR_INVALID_POINTER
;
344 if (ulLength
< lstrlenW(szRootDeviceId
) + 1)
346 ret
= CR_BUFFER_SMALL
;
354 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret
);
361 DWORD
PNP_GetRelatedDeviceInstance(
363 DWORD ulRelationship
,
365 LPWSTR pRelatedDeviceId
,
366 PNP_RPC_STRING_LEN
*pulLength
,
369 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData
;
370 CONFIGRET ret
= CR_SUCCESS
;
373 UNREFERENCED_PARAMETER(hBinding
);
374 UNREFERENCED_PARAMETER(ulFlags
);
376 DPRINT("PNP_GetRelatedDeviceInstance() called\n");
377 DPRINT(" Relationship %ld\n", ulRelationship
);
378 DPRINT(" DeviceId %S\n", pDeviceID
);
380 RtlInitUnicodeString(&PlugPlayData
.TargetDeviceInstance
,
383 PlugPlayData
.Relation
= ulRelationship
;
385 PlugPlayData
.RelatedDeviceInstanceLength
= *pulLength
;
386 PlugPlayData
.RelatedDeviceInstance
= pRelatedDeviceId
;
388 Status
= NtPlugPlayControl(PlugPlayControlGetRelatedDevice
,
389 (PVOID
)&PlugPlayData
,
390 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA
));
391 if (!NT_SUCCESS(Status
))
393 ret
= NtStatusToCrError(Status
);
396 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret
);
397 if (ret
== CR_SUCCESS
)
399 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData
.RelatedDeviceInstance
);
407 DWORD
PNP_EnumerateSubKeys(
412 PNP_RPC_STRING_LEN ulLength
,
413 PNP_RPC_STRING_LEN
*pulRequiredLen
,
416 CONFIGRET ret
= CR_SUCCESS
;
420 UNREFERENCED_PARAMETER(hBinding
);
421 UNREFERENCED_PARAMETER(ulFlags
);
423 DPRINT("PNP_EnumerateSubKeys() called\n");
427 case PNP_ENUMERATOR_SUBKEYS
:
431 case PNP_CLASS_SUBKEYS
:
439 *pulRequiredLen
= ulLength
;
440 dwError
= RegEnumKeyExW(hKey
,
448 if (dwError
!= ERROR_SUCCESS
)
450 ret
= (dwError
== ERROR_NO_MORE_ITEMS
) ? CR_NO_SUCH_VALUE
: CR_FAILURE
;
457 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret
);
464 DWORD
PNP_GetDeviceList(
468 PNP_RPC_STRING_LEN
*pulLength
,
472 return CR_CALL_NOT_IMPLEMENTED
;
477 DWORD
PNP_GetDeviceListSize(
480 PNP_RPC_BUFFER_SIZE
*pulLen
,
484 return CR_CALL_NOT_IMPLEMENTED
;
495 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData
;
496 CONFIGRET ret
= CR_SUCCESS
;
499 UNREFERENCED_PARAMETER(hBinding
);
500 UNREFERENCED_PARAMETER(ulFlags
);
502 DPRINT("PNP_GetDepth() called\n");
504 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
507 Status
= NtPlugPlayControl(PlugPlayControlGetDeviceDepth
,
508 (PVOID
)&PlugPlayData
,
509 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA
));
510 if (NT_SUCCESS(Status
))
512 *pulDepth
= PlugPlayData
.Depth
;
516 ret
= NtStatusToCrError(Status
);
519 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret
);
526 DWORD
PNP_GetDeviceRegProp(
530 DWORD
*pulRegDataType
,
532 PNP_PROP_SIZE
*pulTransferLen
,
533 PNP_PROP_SIZE
*pulLength
,
536 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData
;
537 CONFIGRET ret
= CR_SUCCESS
;
538 LPWSTR lpValueName
= NULL
;
543 UNREFERENCED_PARAMETER(hBinding
);
545 DPRINT("PNP_GetDeviceRegProp() called\n");
547 if (pulTransferLen
== NULL
|| pulLength
== NULL
)
549 ret
= CR_INVALID_POINTER
;
555 ret
= CR_INVALID_FLAG
;
559 /* FIXME: Check pDeviceID */
561 if (*pulLength
< *pulTransferLen
)
562 *pulLength
= *pulTransferLen
;
568 case CM_DRP_DEVICEDESC
:
569 lpValueName
= L
"DeviceDesc";
572 case CM_DRP_HARDWAREID
:
573 lpValueName
= L
"HardwareID";
576 case CM_DRP_COMPATIBLEIDS
:
577 lpValueName
= L
"CompatibleIDs";
581 lpValueName
= L
"Service";
585 lpValueName
= L
"Class";
588 case CM_DRP_CLASSGUID
:
589 lpValueName
= L
"ClassGUID";
593 lpValueName
= L
"Driver";
596 case CM_DRP_CONFIGFLAGS
:
597 lpValueName
= L
"ConfigFlags";
601 lpValueName
= L
"Mfg";
604 case CM_DRP_FRIENDLYNAME
:
605 lpValueName
= L
"FriendlyName";
608 case CM_DRP_LOCATION_INFORMATION
:
609 lpValueName
= L
"LocationInformation";
612 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME
:
616 case CM_DRP_CAPABILITIES
:
617 lpValueName
= L
"Capabilities";
620 case CM_DRP_UI_NUMBER
:
624 case CM_DRP_UPPERFILTERS
:
625 lpValueName
= L
"UpperFilters";
628 case CM_DRP_LOWERFILTERS
:
629 lpValueName
= L
"LowerFilters";
632 case CM_DRP_BUSTYPEGUID
:
636 case CM_DRP_LEGACYBUSTYPE
:
640 case CM_DRP_BUSNUMBER
:
644 case CM_DRP_ENUMERATOR_NAME
:
648 case CM_DRP_SECURITY
:
649 lpValueName
= L
"Security";
653 lpValueName
= L
"DeviceType";
656 case CM_DRP_EXCLUSIVE
:
657 lpValueName
= L
"Exclusive";
660 case CM_DRP_CHARACTERISTICS
:
661 lpValueName
= L
"DeviceCharacteristics";
668 case CM_DRP_UI_NUMBER_DESC_FORMAT
:
669 lpValueName
= L
"UINumberDescFormat";
672 case CM_DRP_DEVICE_POWER_DATA
:
676 case CM_DRP_REMOVAL_POLICY
:
677 lpValueName
= L
"RemovalPolicy";
680 case CM_DRP_REMOVAL_POLICY_HW_DEFAULT
:
684 case CM_DRP_REMOVAL_POLICY_OVERRIDE
:
688 case CM_DRP_INSTALL_STATE
:
692 #if (WINVER >= _WIN32_WINNT_WS03)
693 case CM_DRP_LOCATION_PATHS
:
698 #if (WINVER >= _WIN32_WINNT_WIN7)
699 case CM_DRP_BASE_CONTAINERID
:
705 ret
= CR_INVALID_PROPERTY
;
709 DPRINT("Value name: %S\n", lpValueName
);
713 /* Retrieve information from the Registry */
714 lError
= RegOpenKeyExW(hEnumKey
,
719 if (lError
!= ERROR_SUCCESS
)
723 ret
= CR_INVALID_DEVNODE
;
727 lError
= RegQueryValueExW(hKey
,
733 if (lError
== ERROR_MORE_DATA
)
735 ret
= CR_BUFFER_SMALL
;
740 ret
= CR_NO_SUCH_VALUE
;
745 /* Retrieve information from the Device Node */
746 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
748 PlugPlayData
.Buffer
= Buffer
;
749 PlugPlayData
.BufferSize
= *pulTransferLen
;
753 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME
:
754 PlugPlayData
.Property
= 0xb; // DevicePropertyPhysicalDeviceObjectName;
757 case CM_DRP_UI_NUMBER
:
758 PlugPlayData
.Property
= 0x11; // DevicePropertyUINumber;
761 case CM_DRP_BUSTYPEGUID
:
762 PlugPlayData
.Property
= 0xc; // DevicePropertyBusTypeGuid;
765 case CM_DRP_LEGACYBUSTYPE
:
766 PlugPlayData
.Property
= 0xd; // DevicePropertyLegacyBusType;
769 case CM_DRP_BUSNUMBER
:
770 PlugPlayData
.Property
= 0xe; // DevicePropertyBusNumber;
773 case CM_DRP_ENUMERATOR_NAME
:
774 PlugPlayData
.Property
= 0xf; // DevicePropertyEnumeratorName;
778 PlugPlayData
.Property
= 0x10; // DevicePropertyAddress;
782 /* These properties are not supported by IoGetDeviceProperty */
783 case CM_DRP_DEVICE_POWER_DATA
:
784 case CM_DRP_REMOVAL_POLICY_HW_DEFAULT
:
785 case CM_DRP_REMOVAL_POLICY_OVERRIDE
:
788 case CM_DRP_INSTALL_STATE
:
789 PlugPlayData
.Property
= 0x12; // DevicePropertyInstallState;
793 /* This property is not supported by IoGetDeviceProperty */
794 #if (WINVER >= _WIN32_WINNT_WS03)
795 case CM_DRP_LOCATION_PATHS
:
799 #if (WINVER >= _WIN32_WINNT_WIN7)
800 case CM_DRP_BASE_CONTAINERID
:
801 PlugPlayData
.Property
= 0x16; // DevicePropertyContainerID;
806 return CR_INVALID_PROPERTY
;
809 Status
= NtPlugPlayControl(PlugPlayControlProperty
,
810 (PVOID
)&PlugPlayData
,
811 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA
));
812 if (NT_SUCCESS(Status
))
814 *pulLength
= PlugPlayData
.BufferSize
;
818 ret
= NtStatusToCrError(Status
);
823 *pulTransferLen
= (ret
!= CR_SUCCESS
) ? 0 : *pulLength
;
828 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret
);
835 DWORD
PNP_SetDeviceRegProp(
841 PNP_PROP_SIZE ulLength
,
844 CONFIGRET ret
= CR_SUCCESS
;
845 LPWSTR lpValueName
= NULL
;
848 UNREFERENCED_PARAMETER(hBinding
);
849 UNREFERENCED_PARAMETER(ulFlags
);
851 DPRINT("PNP_SetDeviceRegProp() called\n");
853 DPRINT("DeviceId: %S\n", pDeviceId
);
854 DPRINT("Property: %lu\n", ulProperty
);
855 DPRINT("DataType: %lu\n", ulDataType
);
856 DPRINT("Length: %lu\n", ulLength
);
860 case CM_DRP_DEVICEDESC
:
861 lpValueName
= L
"DeviceDesc";
864 case CM_DRP_HARDWAREID
:
865 lpValueName
= L
"HardwareID";
868 case CM_DRP_COMPATIBLEIDS
:
869 lpValueName
= L
"CompatibleIDs";
873 lpValueName
= L
"Service";
877 lpValueName
= L
"Class";
880 case CM_DRP_CLASSGUID
:
881 lpValueName
= L
"ClassGUID";
885 lpValueName
= L
"Driver";
888 case CM_DRP_CONFIGFLAGS
:
889 lpValueName
= L
"ConfigFlags";
893 lpValueName
= L
"Mfg";
896 case CM_DRP_FRIENDLYNAME
:
897 lpValueName
= L
"FriendlyName";
900 case CM_DRP_LOCATION_INFORMATION
:
901 lpValueName
= L
"LocationInformation";
904 case CM_DRP_UPPERFILTERS
:
905 lpValueName
= L
"UpperFilters";
908 case CM_DRP_LOWERFILTERS
:
909 lpValueName
= L
"LowerFilters";
913 return CR_INVALID_PROPERTY
;
916 DPRINT("Value name: %S\n", lpValueName
);
918 if (RegOpenKeyExW(hEnumKey
,
921 KEY_ALL_ACCESS
, /* FIXME: so much? */
923 return CR_INVALID_DEVNODE
;
927 if (RegDeleteValueW(hKey
,
929 ret
= CR_REGISTRY_ERROR
;
933 if (RegSetValueExW(hKey
,
939 ret
= CR_REGISTRY_ERROR
;
944 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret
);
951 DWORD
PNP_GetClassInstance(
954 LPWSTR pszClassInstance
,
955 PNP_RPC_STRING_LEN ulLength
)
958 return CR_CALL_NOT_IMPLEMENTED
;
971 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
980 return CR_REGISTRY_ERROR
;
982 /* FIXME: Set security key */
991 DWORD
PNP_DeleteRegistryKey(
999 return CR_CALL_NOT_IMPLEMENTED
;
1004 DWORD
PNP_GetClassCount(
1006 DWORD
*pulClassCount
,
1012 UNREFERENCED_PARAMETER(hBinding
);
1013 UNREFERENCED_PARAMETER(ulFlags
);
1015 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1020 if (dwError
!= ERROR_SUCCESS
)
1021 return CR_INVALID_DATA
;
1023 dwError
= RegQueryInfoKeyW(hKey
,
1036 if (dwError
!= ERROR_SUCCESS
)
1037 return CR_INVALID_DATA
;
1044 DWORD
PNP_GetClassName(
1046 LPWSTR pszClassGuid
,
1048 PNP_RPC_STRING_LEN
*pulLength
,
1051 WCHAR szKeyName
[MAX_PATH
];
1052 CONFIGRET ret
= CR_SUCCESS
;
1056 UNREFERENCED_PARAMETER(hBinding
);
1057 UNREFERENCED_PARAMETER(ulFlags
);
1059 DPRINT("PNP_GetClassName() called\n");
1061 lstrcpyW(szKeyName
, L
"System\\CurrentControlSet\\Control\\Class\\");
1062 if(lstrlenW(pszClassGuid
) + 1 < sizeof(szKeyName
)/sizeof(WCHAR
)-(lstrlenW(szKeyName
) * sizeof(WCHAR
)))
1063 lstrcatW(szKeyName
, pszClassGuid
);
1064 else return CR_INVALID_DATA
;
1066 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1071 return CR_REGISTRY_ERROR
;
1073 dwSize
= *pulLength
* sizeof(WCHAR
);
1074 if (RegQueryValueExW(hKey
,
1082 ret
= CR_REGISTRY_ERROR
;
1086 *pulLength
= dwSize
/ sizeof(WCHAR
);
1091 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret
);
1098 DWORD
PNP_DeleteClassKey(
1100 LPWSTR pszClassGuid
,
1103 CONFIGRET ret
= CR_SUCCESS
;
1105 UNREFERENCED_PARAMETER(hBinding
);
1107 DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid
, ulFlags
);
1109 if (ulFlags
& CM_DELETE_CLASS_SUBKEYS
)
1111 if (RegDeleteTreeW(hClassKey
, pszClassGuid
) != ERROR_SUCCESS
)
1112 ret
= CR_REGISTRY_ERROR
;
1116 if (RegDeleteKeyW(hClassKey
, pszClassGuid
) != ERROR_SUCCESS
)
1117 ret
= CR_REGISTRY_ERROR
;
1120 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret
);
1127 DWORD
PNP_GetInterfaceDeviceAlias(
1129 LPWSTR pszInterfaceDevice
,
1130 GUID
*AliasInterfaceGuid
,
1131 LPWSTR pszAliasInterfaceDevice
,
1132 PNP_RPC_STRING_LEN
*pulLength
,
1133 PNP_RPC_STRING_LEN
*pulTransferLen
,
1137 return CR_CALL_NOT_IMPLEMENTED
;
1142 DWORD
PNP_GetInterfaceDeviceList(
1144 GUID
*InterfaceGuid
,
1147 PNP_RPC_BUFFER_SIZE
*pulLength
,
1151 return CR_CALL_NOT_IMPLEMENTED
;
1156 DWORD
PNP_GetInterfaceDeviceListSize(
1158 PNP_RPC_BUFFER_SIZE
*pulLen
,
1159 GUID
*InterfaceGuid
,
1164 return CR_CALL_NOT_IMPLEMENTED
;
1169 DWORD
PNP_RegisterDeviceClassAssociation(
1172 GUID
*InterfaceGuid
,
1173 LPWSTR pszReference
,
1175 PNP_RPC_STRING_LEN
*pulLength
,
1176 PNP_RPC_STRING_LEN
*pulTransferLen
,
1180 return CR_CALL_NOT_IMPLEMENTED
;
1185 DWORD
PNP_UnregisterDeviceClassAssociation(
1187 LPWSTR pszInterfaceDevice
,
1191 return CR_CALL_NOT_IMPLEMENTED
;
1196 DWORD
PNP_GetClassRegProp(
1198 LPWSTR pszClassGuid
,
1200 DWORD
*pulRegDataType
,
1202 PNP_RPC_STRING_LEN
*pulTransferLen
,
1203 PNP_RPC_STRING_LEN
*pulLength
,
1207 return CR_CALL_NOT_IMPLEMENTED
;
1212 DWORD
PNP_SetClassRegProp(
1214 LPWSTR
*pszClassGuid
,
1218 PNP_PROP_SIZE ulLength
,
1222 return CR_CALL_NOT_IMPLEMENTED
;
1227 SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID
,
1228 OUT LPWSTR pszEnumerator
,
1229 OUT LPWSTR pszDevice
,
1230 OUT LPWSTR pszInstance
)
1232 WCHAR szLocalDeviceInstanceID
[MAX_DEVICE_ID_LEN
];
1233 LPWSTR lpEnumerator
= NULL
;
1234 LPWSTR lpDevice
= NULL
;
1235 LPWSTR lpInstance
= NULL
;
1238 wcscpy(szLocalDeviceInstanceID
, pszDeviceInstanceID
);
1244 lpEnumerator
= szLocalDeviceInstanceID
;
1246 ptr
= wcschr(lpEnumerator
, L
'\\');
1252 ptr
= wcschr(lpDevice
, L
'\\');
1260 if (lpEnumerator
!= NULL
)
1261 wcscpy(pszEnumerator
, lpEnumerator
);
1263 if (lpDevice
!= NULL
)
1264 wcscpy(pszDevice
, lpDevice
);
1266 if (lpInstance
!= NULL
)
1267 wcscpy(pszInstance
, lpInstance
);
1272 CreateDeviceInstance(LPWSTR pszDeviceID
)
1274 WCHAR szEnumerator
[MAX_DEVICE_ID_LEN
];
1275 WCHAR szDevice
[MAX_DEVICE_ID_LEN
];
1276 WCHAR szInstance
[MAX_DEVICE_ID_LEN
];
1277 HKEY hKeyEnumerator
;
1283 /* Split the instance ID */
1284 SplitDeviceInstanceID(pszDeviceID
,
1289 /* Open or create the enumerator key */
1290 lError
= RegCreateKeyExW(hEnumKey
,
1294 REG_OPTION_NON_VOLATILE
,
1299 if (lError
!= ERROR_SUCCESS
)
1301 return CR_REGISTRY_ERROR
;
1304 /* Open or create the device key */
1305 lError
= RegCreateKeyExW(hKeyEnumerator
,
1309 REG_OPTION_NON_VOLATILE
,
1315 /* Close the enumerator key */
1316 RegCloseKey(hKeyEnumerator
);
1318 if (lError
!= ERROR_SUCCESS
)
1320 return CR_REGISTRY_ERROR
;
1323 /* Try to open the instance key and fail if it exists */
1324 lError
= RegOpenKeyExW(hKeyDevice
,
1329 if (lError
== ERROR_SUCCESS
)
1331 DPRINT1("Instance %S already exists!\n", szInstance
);
1332 RegCloseKey(hKeyInstance
);
1333 RegCloseKey(hKeyDevice
);
1334 return CR_ALREADY_SUCH_DEVINST
;
1337 /* Create a new instance key */
1338 lError
= RegCreateKeyExW(hKeyDevice
,
1342 REG_OPTION_NON_VOLATILE
,
1348 /* Close the device key */
1349 RegCloseKey(hKeyDevice
);
1351 if (lError
!= ERROR_SUCCESS
)
1353 return CR_REGISTRY_ERROR
;
1356 /* Create the 'Control' sub key */
1357 lError
= RegCreateKeyExW(hKeyInstance
,
1361 REG_OPTION_NON_VOLATILE
,
1366 if (lError
== ERROR_SUCCESS
)
1368 RegCloseKey(hKeyControl
);
1371 RegCloseKey(hKeyInstance
);
1373 return (lError
== ERROR_SUCCESS
) ? CR_SUCCESS
: CR_REGISTRY_ERROR
;
1378 DWORD
PNP_CreateDevInst(
1381 LPWSTR pszParentDeviceID
,
1382 PNP_RPC_STRING_LEN ulLength
,
1385 CONFIGRET ret
= CR_SUCCESS
;
1387 DPRINT("PNP_CreateDevInst: %S\n", pszDeviceID
);
1389 if (ulFlags
& CM_CREATE_DEVNODE_GENERATE_ID
)
1392 DPRINT1("CM_CREATE_DEVNODE_GENERATE_ID support not implemented yet!\n", ret
);
1393 ret
= CR_CALL_NOT_IMPLEMENTED
;
1397 /* Create the device instance */
1398 ret
= CreateDeviceInstance(pszDeviceID
);
1401 DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret
);
1408 MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination
,
1409 LPWSTR pszDeviceInstanceSource
)
1411 DPRINT("MoveDeviceInstance: not implemented\n");
1413 return CR_CALL_NOT_IMPLEMENTED
;
1418 SetupDeviceInstance(LPWSTR pszDeviceInstance
,
1421 DPRINT("SetupDeviceInstance: not implemented\n");
1423 return CR_CALL_NOT_IMPLEMENTED
;
1428 EnableDeviceInstance(LPWSTR pszDeviceInstance
)
1430 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
1431 CONFIGRET ret
= CR_SUCCESS
;
1434 DPRINT("Enable device instance\n");
1436 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, pszDeviceInstance
);
1437 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
1438 if (!NT_SUCCESS(Status
))
1439 ret
= NtStatusToCrError(Status
);
1446 DisableDeviceInstance(LPWSTR pszDeviceInstance
)
1448 DPRINT("DisableDeviceInstance: not implemented\n");
1450 return CR_CALL_NOT_IMPLEMENTED
;
1455 ReenumerateDeviceInstance(LPWSTR pszDeviceInstance
)
1457 DPRINT("ReenumerateDeviceInstance: not implemented\n");
1459 return CR_CALL_NOT_IMPLEMENTED
;
1464 DWORD
PNP_DeviceInstanceAction(
1468 LPWSTR pszDeviceInstance1
,
1469 LPWSTR pszDeviceInstance2
)
1471 CONFIGRET ret
= CR_SUCCESS
;
1473 UNREFERENCED_PARAMETER(hBinding
);
1475 DPRINT("PNP_DeviceInstanceAction() called\n");
1479 case PNP_DEVINST_MOVE
:
1480 ret
= MoveDeviceInstance(pszDeviceInstance1
,
1481 pszDeviceInstance2
);
1484 case PNP_DEVINST_SETUP
:
1485 ret
= SetupDeviceInstance(pszDeviceInstance1
,
1489 case PNP_DEVINST_ENABLE
:
1490 ret
= EnableDeviceInstance(pszDeviceInstance1
);
1493 case PNP_DEVINST_DISABLE
:
1494 ret
= DisableDeviceInstance(pszDeviceInstance1
);
1497 case PNP_DEVINST_REENUMERATE
:
1498 ret
= ReenumerateDeviceInstance(pszDeviceInstance1
);
1502 DPRINT1("Unknown device action %lu: not implemented\n", ulAction
);
1503 ret
= CR_CALL_NOT_IMPLEMENTED
;
1506 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret
);
1513 DWORD
PNP_GetDeviceStatus(
1520 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData
;
1521 CONFIGRET ret
= CR_SUCCESS
;
1524 UNREFERENCED_PARAMETER(hBinding
);
1525 UNREFERENCED_PARAMETER(ulFlags
);
1527 DPRINT("PNP_GetDeviceStatus() called\n");
1529 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
1531 PlugPlayData
.Operation
= 0; /* Get status */
1533 Status
= NtPlugPlayControl(PlugPlayControlDeviceStatus
,
1534 (PVOID
)&PlugPlayData
,
1535 sizeof(PLUGPLAY_CONTROL_STATUS_DATA
));
1536 if (NT_SUCCESS(Status
))
1538 *pulStatus
= PlugPlayData
.DeviceStatus
;
1539 *pulProblem
= PlugPlayData
.DeviceProblem
;
1543 ret
= NtStatusToCrError(Status
);
1546 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret
);
1553 DWORD
PNP_SetDeviceProblem(
1560 return CR_CALL_NOT_IMPLEMENTED
;
1565 DWORD
PNP_DisableDevInst(
1568 PPNP_VETO_TYPE pVetoType
,
1574 return CR_CALL_NOT_IMPLEMENTED
;
1578 DWORD
PNP_UninstallDevInst(
1584 return CR_CALL_NOT_IMPLEMENTED
;
1589 CheckForDeviceId(LPWSTR lpDeviceIdList
,
1595 lpPtr
= lpDeviceIdList
;
1598 dwLength
= wcslen(lpPtr
);
1599 if (0 == _wcsicmp(lpPtr
, lpDeviceId
))
1602 lpPtr
+= (dwLength
+ 1);
1610 AppendDeviceId(LPWSTR lpDeviceIdList
,
1611 LPDWORD lpDeviceIdListSize
,
1617 dwLen
= wcslen(lpDeviceId
);
1618 dwPos
= (*lpDeviceIdListSize
/ sizeof(WCHAR
)) - 1;
1620 wcscpy(&lpDeviceIdList
[dwPos
], lpDeviceId
);
1622 dwPos
+= (dwLen
+ 1);
1624 lpDeviceIdList
[dwPos
] = 0;
1626 *lpDeviceIdListSize
= dwPos
* sizeof(WCHAR
);
1637 CONFIGRET ret
= CR_SUCCESS
;
1640 DWORD dwDeviceIdListSize
;
1641 DWORD dwNewDeviceIdSize
;
1642 WCHAR
* pszDeviceIdList
= NULL
;
1644 UNREFERENCED_PARAMETER(hBinding
);
1646 DPRINT("PNP_AddID() called\n");
1647 DPRINT(" DeviceInstance: %S\n", pszDeviceID
);
1648 DPRINT(" DeviceId: %S\n", pszID
);
1649 DPRINT(" Flags: %lx\n", ulFlags
);
1651 if (RegOpenKeyExW(hEnumKey
,
1654 KEY_QUERY_VALUE
| KEY_SET_VALUE
,
1655 &hDeviceKey
) != ERROR_SUCCESS
)
1657 DPRINT("Failed to open the device key!\n");
1658 return CR_INVALID_DEVNODE
;
1661 pszSubKey
= (ulFlags
& CM_ADD_ID_COMPATIBLE
) ? L
"CompatibleIDs" : L
"HardwareID";
1663 if (RegQueryValueExW(hDeviceKey
,
1668 &dwDeviceIdListSize
) != ERROR_SUCCESS
)
1670 DPRINT("Failed to query the desired ID string!\n");
1671 ret
= CR_REGISTRY_ERROR
;
1675 dwNewDeviceIdSize
= lstrlenW(pszDeviceID
);
1676 if (!dwNewDeviceIdSize
)
1678 ret
= CR_INVALID_POINTER
;
1682 dwDeviceIdListSize
+= (dwNewDeviceIdSize
+ 2) * sizeof(WCHAR
);
1684 pszDeviceIdList
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDeviceIdListSize
);
1685 if (!pszDeviceIdList
)
1687 DPRINT("Failed to allocate memory for the desired ID string!\n");
1688 ret
= CR_OUT_OF_MEMORY
;
1692 if (RegQueryValueExW(hDeviceKey
,
1696 (LPBYTE
)pszDeviceIdList
,
1697 &dwDeviceIdListSize
) != ERROR_SUCCESS
)
1699 DPRINT("Failed to query the desired ID string!\n");
1700 ret
= CR_REGISTRY_ERROR
;
1704 /* Check whether the device ID is already in use */
1705 if (CheckForDeviceId(pszDeviceIdList
, pszDeviceID
))
1707 DPRINT("Device ID was found in the ID string!\n");
1712 /* Append the Device ID */
1713 AppendDeviceId(pszDeviceIdList
, &dwDeviceIdListSize
, pszID
);
1715 if (RegSetValueExW(hDeviceKey
,
1719 (LPBYTE
)pszDeviceIdList
,
1720 dwDeviceIdListSize
) != ERROR_SUCCESS
)
1722 DPRINT("Failed to set the desired ID string!\n");
1723 ret
= CR_REGISTRY_ERROR
;
1727 RegCloseKey(hDeviceKey
);
1728 if (pszDeviceIdList
)
1729 HeapFree(GetProcessHeap(), 0, pszDeviceIdList
);
1731 DPRINT("PNP_AddID() done (returns %lx)\n", ret
);
1738 DWORD
PNP_RegisterDriver(
1744 return CR_CALL_NOT_IMPLEMENTED
;
1749 DWORD
PNP_QueryRemove(
1752 PPNP_VETO_TYPE pVetoType
,
1758 return CR_CALL_NOT_IMPLEMENTED
;
1763 DWORD
PNP_RequestDeviceEject(
1766 PPNP_VETO_TYPE pVetoType
,
1772 return CR_CALL_NOT_IMPLEMENTED
;
1777 PNP_IsDockStationPresent(handle_t hBinding
,
1784 CONFIGRET ret
= CR_SUCCESS
;
1786 UNREFERENCED_PARAMETER(hBinding
);
1788 DPRINT1("PNP_IsDockStationPresent() called\n");
1792 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG
,
1796 &hKey
) != ERROR_SUCCESS
)
1797 return CR_REGISTRY_ERROR
;
1799 dwSize
= sizeof(DWORD
);
1800 if (RegQueryValueExW(hKey
,
1805 &dwSize
) != ERROR_SUCCESS
)
1806 ret
= CR_REGISTRY_ERROR
;
1810 if (ret
== CR_SUCCESS
)
1812 if (dwType
!= REG_DWORD
|| dwSize
!= sizeof(DWORD
))
1814 ret
= CR_REGISTRY_ERROR
;
1816 else if (dwValue
!= 0)
1822 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret
);
1829 DWORD
PNP_RequestEjectPC(
1833 return CR_CALL_NOT_IMPLEMENTED
;
1838 DWORD
PNP_HwProfFlags(
1844 PPNP_VETO_TYPE pVetoType
,
1849 CONFIGRET ret
= CR_SUCCESS
;
1850 WCHAR szKeyName
[MAX_PATH
];
1855 UNREFERENCED_PARAMETER(hBinding
);
1857 DPRINT("PNP_HwProfFlags() called\n");
1862 L
"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
1867 L
"System\\CurrentControlSet\\HardwareProfiles\\%04u\\System\\CurrentControlSet\\Enum",
1871 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1875 &hKey
) != ERROR_SUCCESS
)
1876 return CR_REGISTRY_ERROR
;
1878 if (ulAction
== PNP_GET_HWPROFFLAGS
)
1880 if (RegOpenKeyExW(hKey
,
1884 &hDeviceKey
) != ERROR_SUCCESS
)
1890 dwSize
= sizeof(DWORD
);
1891 if (!RegQueryValueExW(hDeviceKey
,
1896 &dwSize
) != ERROR_SUCCESS
)
1901 RegCloseKey(hDeviceKey
);
1904 else if (ulAction
== PNP_SET_HWPROFFLAGS
)
1906 /* FIXME: not implemented yet */
1907 ret
= CR_CALL_NOT_IMPLEMENTED
;
1917 DWORD
PNP_GetHwProfInfo(
1920 HWPROFILEINFO
*pHWProfileInfo
,
1921 DWORD ulProfileInfoSize
,
1925 return CR_CALL_NOT_IMPLEMENTED
;
1930 DWORD
PNP_AddEmptyLogConf(
1934 DWORD
*pulLogConfTag
,
1938 return CR_CALL_NOT_IMPLEMENTED
;
1943 DWORD
PNP_FreeLogConf(
1946 DWORD ulLogConfType
,
1951 return CR_CALL_NOT_IMPLEMENTED
;
1956 DWORD
PNP_GetFirstLogConf(
1959 DWORD ulLogConfType
,
1960 DWORD
*pulLogConfTag
,
1964 return CR_CALL_NOT_IMPLEMENTED
;
1969 DWORD
PNP_GetNextLogConf(
1972 DWORD ulLogConfType
,
1978 return CR_CALL_NOT_IMPLEMENTED
;
1983 DWORD
PNP_GetLogConfPriority(
1992 return CR_CALL_NOT_IMPLEMENTED
;
1997 DWORD
PNP_AddResDes(
2001 DWORD ulLogConfType
,
2002 RESOURCEID ResourceID
,
2003 DWORD
*pulResourceTag
,
2005 PNP_RPC_BUFFER_SIZE ResourceLen
,
2009 return CR_CALL_NOT_IMPLEMENTED
;
2014 DWORD
PNP_FreeResDes(
2018 DWORD ulLogConfType
,
2019 RESOURCEID ResourceID
,
2020 DWORD ulResourceTag
,
2021 DWORD
*pulPreviousResType
,
2022 DWORD
*pulPreviousResTag
,
2026 return CR_CALL_NOT_IMPLEMENTED
;
2031 DWORD
PNP_GetNextResDes(
2035 DWORD ulLogConfType
,
2036 RESOURCEID ResourceID
,
2037 DWORD ulResourceTag
,
2038 DWORD
*pulNextResType
,
2039 DWORD
*pulNextResTag
,
2043 return CR_CALL_NOT_IMPLEMENTED
;
2048 DWORD
PNP_GetResDesData(
2052 DWORD ulLogConfType
,
2053 RESOURCEID ResourceID
,
2054 DWORD ulResourceTag
,
2056 PNP_RPC_BUFFER_SIZE BufferLen
,
2060 return CR_CALL_NOT_IMPLEMENTED
;
2065 DWORD
PNP_GetResDesDataSize(
2069 DWORD ulLogConfType
,
2070 RESOURCEID ResourceID
,
2071 DWORD ulResourceTag
,
2076 return CR_CALL_NOT_IMPLEMENTED
;
2081 DWORD
PNP_ModifyResDes(
2085 DWORD ulLogConfType
,
2086 RESOURCEID CurrentResourceID
,
2087 RESOURCEID NewResourceID
,
2088 DWORD ulResourceTag
,
2090 PNP_RPC_BUFFER_SIZE ResourceLen
,
2094 return CR_CALL_NOT_IMPLEMENTED
;
2099 DWORD
PNP_DetectResourceConflict(
2102 RESOURCEID ResourceID
,
2104 PNP_RPC_BUFFER_SIZE ResourceLen
,
2105 BOOL
*pbConflictDetected
,
2109 return CR_CALL_NOT_IMPLEMENTED
;
2114 DWORD
PNP_QueryResConfList(
2117 RESOURCEID ResourceID
,
2119 PNP_RPC_BUFFER_SIZE ResourceLen
,
2121 PNP_RPC_BUFFER_SIZE BufferLen
,
2125 return CR_CALL_NOT_IMPLEMENTED
;
2130 DWORD
PNP_SetHwProf(
2132 DWORD ulHardwareProfile
,
2136 return CR_CALL_NOT_IMPLEMENTED
;
2141 DWORD
PNP_QueryArbitratorFreeData(
2146 RESOURCEID ResourceID
,
2150 return CR_CALL_NOT_IMPLEMENTED
;
2155 DWORD
PNP_QueryArbitratorFreeSize(
2159 RESOURCEID ResourceID
,
2163 return CR_CALL_NOT_IMPLEMENTED
;
2173 return CR_CALL_NOT_IMPLEMENTED
;
2178 DWORD
PNP_RegisterNotification(
2182 return CR_CALL_NOT_IMPLEMENTED
;
2187 DWORD
PNP_UnregisterNotification(
2191 return CR_CALL_NOT_IMPLEMENTED
;
2196 DWORD
PNP_GetCustomDevProp(
2199 LPWSTR CustomPropName
,
2200 DWORD
*pulRegDataType
,
2202 PNP_RPC_STRING_LEN
*pulTransferLen
,
2203 PNP_RPC_STRING_LEN
*pulLength
,
2207 return CR_CALL_NOT_IMPLEMENTED
;
2212 DWORD
PNP_GetVersionInternal(
2217 return CR_CALL_NOT_IMPLEMENTED
;
2222 DWORD
PNP_GetBlockedDriverInfo(
2225 PNP_RPC_BUFFER_SIZE
*pulTransferLen
,
2226 PNP_RPC_BUFFER_SIZE
*pulLength
,
2230 return CR_CALL_NOT_IMPLEMENTED
;
2235 DWORD
PNP_GetServerSideDeviceInstallFlags(
2237 DWORD
*pulSSDIFlags
,
2241 return CR_CALL_NOT_IMPLEMENTED
;
2246 DWORD
PNP_GetObjectPropKeys(
2250 LPWSTR PropertyCultureName
,
2251 PNP_PROP_COUNT
*PropertyCount
,
2252 PNP_PROP_COUNT
*TransferLen
,
2253 DEVPROPKEY
*PropertyKeys
,
2257 return CR_CALL_NOT_IMPLEMENTED
;
2262 DWORD
PNP_GetObjectProp(
2266 LPWSTR PropertyCultureName
,
2267 const DEVPROPKEY
*PropertyKey
,
2268 DEVPROPTYPE
*PropertyType
,
2269 PNP_PROP_SIZE
*PropertySize
,
2270 PNP_PROP_SIZE
*TransferLen
,
2271 BYTE
*PropertyBuffer
,
2275 return CR_CALL_NOT_IMPLEMENTED
;
2280 DWORD
PNP_SetObjectProp(
2284 LPWSTR PropertyCultureName
,
2285 const DEVPROPKEY
*PropertyKey
,
2286 DEVPROPTYPE PropertyType
,
2287 PNP_PROP_SIZE PropertySize
,
2288 BYTE
*PropertyBuffer
,
2292 return CR_CALL_NOT_IMPLEMENTED
;
2297 DWORD
PNP_InstallDevInst(
2301 return CR_CALL_NOT_IMPLEMENTED
;
2306 DWORD
PNP_ApplyPowerSettings(
2310 return CR_CALL_NOT_IMPLEMENTED
;
2315 DWORD
PNP_DriverStoreAddDriverPackage(
2319 return CR_CALL_NOT_IMPLEMENTED
;
2324 DWORD
PNP_DriverStoreDeleteDriverPackage(
2328 return CR_CALL_NOT_IMPLEMENTED
;
2333 DWORD
PNP_RegisterServiceNotification(
2337 return CR_CALL_NOT_IMPLEMENTED
;
2342 DWORD
PNP_SetActiveService(
2346 return CR_CALL_NOT_IMPLEMENTED
;
2351 DWORD
PNP_DeleteServiceDevices(
2355 return CR_CALL_NOT_IMPLEMENTED
;
2360 InstallDevice(PCWSTR DeviceInstance
, BOOL ShowWizard
)
2362 BOOL DeviceInstalled
= FALSE
;
2365 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
2366 LPVOID Environment
= NULL
;
2367 PROCESS_INFORMATION ProcessInfo
;
2368 STARTUPINFOW StartupInfo
;
2372 /* The following lengths are constant (see below), they cannot overflow */
2373 WCHAR CommandLine
[116];
2374 WCHAR InstallEventName
[73];
2376 WCHAR UuidString
[39];
2378 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance
, ShowWizard
);
2380 ZeroMemory(&ProcessInfo
, sizeof(ProcessInfo
));
2382 if (RegOpenKeyExW(hEnumKey
,
2386 &DeviceKey
) == ERROR_SUCCESS
)
2388 if (RegQueryValueExW(DeviceKey
,
2393 NULL
) == ERROR_SUCCESS
)
2395 DPRINT("No need to install: %S\n", DeviceInstance
);
2396 RegCloseKey(DeviceKey
);
2400 RegCloseKey(DeviceKey
);
2403 DPRINT1("Installing: %S\n", DeviceInstance
);
2405 /* Create a random UUID for the named pipe */
2406 UuidCreate(&RandomUuid
);
2407 swprintf(UuidString
, L
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
2408 RandomUuid
.Data1
, RandomUuid
.Data2
, RandomUuid
.Data3
,
2409 RandomUuid
.Data4
[0], RandomUuid
.Data4
[1], RandomUuid
.Data4
[2],
2410 RandomUuid
.Data4
[3], RandomUuid
.Data4
[4], RandomUuid
.Data4
[5],
2411 RandomUuid
.Data4
[6], RandomUuid
.Data4
[7]);
2413 /* Create the named pipe */
2414 wcscpy(PipeName
, L
"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
2415 wcscat(PipeName
, UuidString
);
2416 hPipe
= CreateNamedPipeW(PipeName
, PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_BYTE
, 1, 512, 512, 0, NULL
);
2418 if(hPipe
== INVALID_HANDLE_VALUE
)
2420 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
2424 /* Launch rundll32 to call ClientSideInstallW */
2425 wcscpy(CommandLine
, L
"rundll32.exe newdev.dll,ClientSideInstall ");
2426 wcscat(CommandLine
, PipeName
);
2428 ZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
2429 StartupInfo
.cb
= sizeof(StartupInfo
);
2433 /* newdev has to run under the environment of the current user */
2434 if(!CreateEnvironmentBlock(&Environment
, hUserToken
, FALSE
))
2436 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
2440 if(!CreateProcessAsUserW(hUserToken
, NULL
, CommandLine
, NULL
, NULL
, FALSE
, CREATE_UNICODE_ENVIRONMENT
, Environment
, NULL
, &StartupInfo
, &ProcessInfo
))
2442 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
2448 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
2450 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
2451 (ShowWizard is only set to FALSE for these two modes) */
2452 ASSERT(!ShowWizard
);
2454 if(!CreateProcessW(NULL
, CommandLine
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &StartupInfo
, &ProcessInfo
))
2456 DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
2461 /* Wait for the function to connect to our pipe */
2462 if(!ConnectNamedPipe(hPipe
, NULL
))
2464 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
2468 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
2469 wcscpy(InstallEventName
, L
"Global\\PNP_Device_Install_Event_0.");
2470 wcscat(InstallEventName
, UuidString
);
2472 Value
= sizeof(InstallEventName
);
2473 WriteFile(hPipe
, &Value
, sizeof(Value
), &BytesWritten
, NULL
);
2474 WriteFile(hPipe
, InstallEventName
, Value
, &BytesWritten
, NULL
);
2476 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
2477 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
2478 WriteFile(hPipe
, &ShowWizard
, sizeof(ShowWizard
), &BytesWritten
, NULL
);
2480 Value
= (wcslen(DeviceInstance
) + 1) * sizeof(WCHAR
);
2481 WriteFile(hPipe
, &Value
, sizeof(Value
), &BytesWritten
, NULL
);
2482 WriteFile(hPipe
, DeviceInstance
, Value
, &BytesWritten
, NULL
);
2484 /* Wait for newdev.dll to finish processing */
2485 WaitForSingleObject(ProcessInfo
.hProcess
, INFINITE
);
2487 /* The following check for success is probably not compatible to Windows, but should do its job */
2488 if(!GetExitCodeProcess(ProcessInfo
.hProcess
, &Value
))
2490 DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
2494 DeviceInstalled
= Value
;
2497 if(hPipe
!= INVALID_HANDLE_VALUE
)
2501 DestroyEnvironmentBlock(Environment
);
2503 if(ProcessInfo
.hProcess
)
2504 CloseHandle(ProcessInfo
.hProcess
);
2506 if(ProcessInfo
.hThread
)
2507 CloseHandle(ProcessInfo
.hThread
);
2509 DPRINT1("Success? %d\n", DeviceInstalled
);
2511 return DeviceInstalled
;
2527 return ERROR_INVALID_PARAMETER
;
2530 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, &dwType
, NULL
, &cbData
);
2531 if (rc
!= ERROR_SUCCESS
)
2533 if (dwType
!= REG_SZ
)
2534 return ERROR_FILE_NOT_FOUND
;
2535 Value
= HeapAlloc(GetProcessHeap(), 0, cbData
+ sizeof(WCHAR
));
2537 return ERROR_NOT_ENOUGH_MEMORY
;
2538 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, NULL
, (LPBYTE
)Value
, &cbData
);
2539 if (rc
!= ERROR_SUCCESS
)
2541 HeapFree(GetProcessHeap(), 0, Value
);
2544 /* NULL-terminate the string */
2545 Value
[cbData
/ sizeof(WCHAR
)] = '\0';
2548 return ERROR_SUCCESS
;
2556 DWORD regType
, active
, size
;
2560 rc
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\Setup", 0, KEY_QUERY_VALUE
, &hKey
);
2561 if (rc
!= ERROR_SUCCESS
)
2564 size
= sizeof(DWORD
);
2565 rc
= RegQueryValueExW(hKey
, L
"SystemSetupInProgress", NULL
, ®Type
, (LPBYTE
)&active
, &size
);
2566 if (rc
!= ERROR_SUCCESS
)
2568 if (regType
!= REG_DWORD
|| size
!= sizeof(DWORD
))
2571 ret
= (active
!= 0);
2577 DPRINT("System setup in progress? %S\n", ret
? L
"YES" : L
"NO");
2586 HKEY ControlKey
= NULL
;
2587 LPWSTR SystemStartOptions
= NULL
;
2588 LPWSTR CurrentOption
, NextOption
; /* Pointers into SystemStartOptions */
2589 BOOL ConsoleBoot
= FALSE
;
2594 L
"SYSTEM\\CurrentControlSet\\Control",
2599 rc
= ReadRegSzKey(ControlKey
, L
"SystemStartOptions", &SystemStartOptions
);
2600 if (rc
!= ERROR_SUCCESS
)
2603 /* Check for CMDCONS in SystemStartOptions */
2604 CurrentOption
= SystemStartOptions
;
2605 while (CurrentOption
)
2607 NextOption
= wcschr(CurrentOption
, L
' ');
2609 *NextOption
= L
'\0';
2610 if (_wcsicmp(CurrentOption
, L
"CONSOLE") == 0)
2612 DPRINT("Found %S. Switching to console boot\n", CurrentOption
);
2616 CurrentOption
= NextOption
? NextOption
+ 1 : NULL
;
2620 if (ControlKey
!= NULL
)
2621 RegCloseKey(ControlKey
);
2622 HeapFree(GetProcessHeap(), 0, SystemStartOptions
);
2627 /* Loop to install all queued devices installations */
2629 DeviceInstallThread(LPVOID lpParameter
)
2631 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2632 PSLIST_ENTRY ListEntry
;
2634 PLIST_ENTRY ListEntry
;
2636 DeviceInstallParams
* Params
;
2639 UNREFERENCED_PARAMETER(lpParameter
);
2641 WaitForSingleObject(hInstallEvent
, INFINITE
);
2643 showWizard
= !SetupIsActive() && !IsConsoleBoot();
2647 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2648 ListEntry
= InterlockedPopEntrySList(&DeviceInstallListHead
);
2650 if ((BOOL
)IsListEmpty(&DeviceInstallListHead
))
2653 ListEntry
= RemoveHeadList(&DeviceInstallListHead
);
2655 if (ListEntry
== NULL
)
2657 SetEvent(hNoPendingInstalls
);
2658 WaitForSingleObject(hDeviceInstallListNotEmpty
, INFINITE
);
2662 ResetEvent(hNoPendingInstalls
);
2663 Params
= CONTAINING_RECORD(ListEntry
, DeviceInstallParams
, ListEntry
);
2664 InstallDevice(Params
->DeviceIds
, showWizard
);
2673 PnpEventThread(LPVOID lpParameter
)
2675 PPLUGPLAY_EVENT_BLOCK PnpEvent
;
2678 RPC_STATUS RpcStatus
;
2680 UNREFERENCED_PARAMETER(lpParameter
);
2682 PnpEventSize
= 0x1000;
2683 PnpEvent
= HeapAlloc(GetProcessHeap(), 0, PnpEventSize
);
2684 if (PnpEvent
== NULL
)
2685 return ERROR_OUTOFMEMORY
;
2689 DPRINT("Calling NtGetPlugPlayEvent()\n");
2691 /* Wait for the next pnp event */
2692 Status
= NtGetPlugPlayEvent(0, 0, PnpEvent
, PnpEventSize
);
2694 /* Resize the buffer for the PnP event if it's too small. */
2695 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2697 PnpEventSize
+= 0x400;
2698 HeapFree(GetProcessHeap(), 0, PnpEvent
);
2699 PnpEvent
= HeapAlloc(GetProcessHeap(), 0, PnpEventSize
);
2700 if (PnpEvent
== NULL
)
2701 return ERROR_OUTOFMEMORY
;
2705 if (!NT_SUCCESS(Status
))
2707 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status
);
2711 /* Process the pnp event */
2712 DPRINT("Received PnP Event\n");
2713 if (UuidEqual(&PnpEvent
->EventGuid
, (UUID
*)&GUID_DEVICE_ENUMERATED
, &RpcStatus
))
2715 DeviceInstallParams
* Params
;
2717 DWORD DeviceIdLength
;
2719 DPRINT1("Device enumerated: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
2721 DeviceIdLength
= lstrlenW(PnpEvent
->TargetDevice
.DeviceIds
);
2724 /* Queue device install (will be dequeued by DeviceInstallThread */
2725 len
= FIELD_OFFSET(DeviceInstallParams
, DeviceIds
) + (DeviceIdLength
+ 1) * sizeof(WCHAR
);
2726 Params
= HeapAlloc(GetProcessHeap(), 0, len
);
2729 wcscpy(Params
->DeviceIds
, PnpEvent
->TargetDevice
.DeviceIds
);
2730 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2731 InterlockedPushEntrySList(&DeviceInstallListHead
, &Params
->ListEntry
);
2733 InsertTailList(&DeviceInstallListHead
, &Params
->ListEntry
);
2735 SetEvent(hDeviceInstallListNotEmpty
);
2739 else if (UuidEqual(&PnpEvent
->EventGuid
, (UUID
*)&GUID_DEVICE_ARRIVAL
, &RpcStatus
))
2741 DPRINT1("Device arrival: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
2746 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
2747 PnpEvent
->EventGuid
.Data1
, PnpEvent
->EventGuid
.Data2
, PnpEvent
->EventGuid
.Data3
,
2748 PnpEvent
->EventGuid
.Data4
[0], PnpEvent
->EventGuid
.Data4
[1], PnpEvent
->EventGuid
.Data4
[2],
2749 PnpEvent
->EventGuid
.Data4
[3], PnpEvent
->EventGuid
.Data4
[4], PnpEvent
->EventGuid
.Data4
[5],
2750 PnpEvent
->EventGuid
.Data4
[6], PnpEvent
->EventGuid
.Data4
[7]);
2753 /* Dequeue the current pnp event and signal the next one */
2754 NtPlugPlayControl(PlugPlayControlUserResponse
, NULL
, 0);
2757 HeapFree(GetProcessHeap(), 0, PnpEvent
);
2759 return ERROR_SUCCESS
;
2764 UpdateServiceStatus(DWORD dwState
)
2766 ServiceStatus
.dwServiceType
= SERVICE_WIN32_OWN_PROCESS
;
2767 ServiceStatus
.dwCurrentState
= dwState
;
2768 ServiceStatus
.dwControlsAccepted
= 0;
2769 ServiceStatus
.dwWin32ExitCode
= 0;
2770 ServiceStatus
.dwServiceSpecificExitCode
= 0;
2771 ServiceStatus
.dwCheckPoint
= 0;
2773 if (dwState
== SERVICE_START_PENDING
||
2774 dwState
== SERVICE_STOP_PENDING
||
2775 dwState
== SERVICE_PAUSE_PENDING
||
2776 dwState
== SERVICE_CONTINUE_PENDING
)
2777 ServiceStatus
.dwWaitHint
= 10000;
2779 ServiceStatus
.dwWaitHint
= 0;
2781 SetServiceStatus(ServiceStatusHandle
,
2787 ServiceControlHandler(DWORD dwControl
,
2792 DPRINT1("ServiceControlHandler() called\n");
2796 case SERVICE_CONTROL_STOP
:
2797 DPRINT1(" SERVICE_CONTROL_STOP received\n");
2798 UpdateServiceStatus(SERVICE_STOPPED
);
2799 return ERROR_SUCCESS
;
2801 case SERVICE_CONTROL_PAUSE
:
2802 DPRINT1(" SERVICE_CONTROL_PAUSE received\n");
2803 UpdateServiceStatus(SERVICE_PAUSED
);
2804 return ERROR_SUCCESS
;
2806 case SERVICE_CONTROL_CONTINUE
:
2807 DPRINT1(" SERVICE_CONTROL_CONTINUE received\n");
2808 UpdateServiceStatus(SERVICE_RUNNING
);
2809 return ERROR_SUCCESS
;
2811 case SERVICE_CONTROL_INTERROGATE
:
2812 DPRINT1(" SERVICE_CONTROL_INTERROGATE received\n");
2813 SetServiceStatus(ServiceStatusHandle
,
2815 return ERROR_SUCCESS
;
2817 case SERVICE_CONTROL_SHUTDOWN
:
2818 DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n");
2819 UpdateServiceStatus(SERVICE_STOPPED
);
2820 return ERROR_SUCCESS
;
2823 DPRINT1(" Control %lu received\n");
2824 return ERROR_CALL_NOT_IMPLEMENTED
;
2829 static VOID CALLBACK
2830 ServiceMain(DWORD argc
, LPTSTR
*argv
)
2835 UNREFERENCED_PARAMETER(argc
);
2836 UNREFERENCED_PARAMETER(argv
);
2838 DPRINT("ServiceMain() called\n");
2840 ServiceStatusHandle
= RegisterServiceCtrlHandlerExW(ServiceName
,
2841 ServiceControlHandler
,
2843 if (!ServiceStatusHandle
)
2845 DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
2849 UpdateServiceStatus(SERVICE_START_PENDING
);
2851 hThread
= CreateThread(NULL
,
2857 if (hThread
!= NULL
)
2858 CloseHandle(hThread
);
2860 hThread
= CreateThread(NULL
,
2866 if (hThread
!= NULL
)
2867 CloseHandle(hThread
);
2869 hThread
= CreateThread(NULL
,
2871 DeviceInstallThread
,
2875 if (hThread
!= NULL
)
2876 CloseHandle(hThread
);
2878 UpdateServiceStatus(SERVICE_RUNNING
);
2880 DPRINT("ServiceMain() done\n");
2885 wmain(int argc
, WCHAR
*argv
[])
2890 UNREFERENCED_PARAMETER(argc
);
2891 UNREFERENCED_PARAMETER(argv
);
2893 DPRINT("Umpnpmgr: main() started\n");
2895 /* We need this privilege for using CreateProcessAsUserW */
2896 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
, TRUE
, FALSE
, &OldValue
);
2898 hInstallEvent
= CreateEvent(NULL
, TRUE
, SetupIsActive()/*FALSE*/, NULL
);
2899 if (hInstallEvent
== NULL
)
2901 dwError
= GetLastError();
2902 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError
);
2906 hDeviceInstallListNotEmpty
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
2907 if (hDeviceInstallListNotEmpty
== NULL
)
2909 dwError
= GetLastError();
2910 DPRINT1("Could not create the Event! (Error %lu)\n", dwError
);
2914 hNoPendingInstalls
= CreateEventW(NULL
,
2917 L
"Global\\PnP_No_Pending_Install_Events");
2918 if (hNoPendingInstalls
== NULL
)
2920 dwError
= GetLastError();
2921 DPRINT1("Could not create the Event! (Error %lu)\n", dwError
);
2925 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2926 InitializeSListHead(&DeviceInstallListHead
);
2928 InitializeListHead(&DeviceInstallListHead
);
2931 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2932 L
"System\\CurrentControlSet\\Enum",
2936 if (dwError
!= ERROR_SUCCESS
)
2938 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError
);
2942 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2943 L
"System\\CurrentControlSet\\Control\\Class",
2947 if (dwError
!= ERROR_SUCCESS
)
2949 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError
);
2953 StartServiceCtrlDispatcher(ServiceTable
);
2955 DPRINT("Umpnpmgr: main() done\n");