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
:
680 case CM_DRP_REMOVAL_POLICY_HW_DEFAULT
:
684 case CM_DRP_REMOVAL_POLICY_OVERRIDE
:
685 lpValueName
= L
"RemovalPolicy";
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 /* FIXME: This property is not supported by IoGetDeviceProperty */
783 case CM_DRP_DEVICE_POWER_DATA
:
786 case CM_DRP_REMOVAL_POLICY
:
787 PlugPlayData
.Property
= 0x12; // DevicePropertyRemovalPolicy
791 /* FIXME: This property is not supported by IoGetDeviceProperty */
792 case CM_DRP_REMOVAL_POLICY_HW_DEFAULT
:
795 case CM_DRP_INSTALL_STATE
:
796 PlugPlayData
.Property
= 0x12; // DevicePropertyInstallState;
800 /* FIXME: This property is not supported by IoGetDeviceProperty */
801 #if (WINVER >= _WIN32_WINNT_WS03)
802 case CM_DRP_LOCATION_PATHS
:
806 #if (WINVER >= _WIN32_WINNT_WIN7)
807 case CM_DRP_BASE_CONTAINERID
:
808 PlugPlayData
.Property
= 0x16; // DevicePropertyContainerID;
813 return CR_INVALID_PROPERTY
;
816 Status
= NtPlugPlayControl(PlugPlayControlProperty
,
817 (PVOID
)&PlugPlayData
,
818 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA
));
819 if (NT_SUCCESS(Status
))
821 *pulLength
= PlugPlayData
.BufferSize
;
825 ret
= NtStatusToCrError(Status
);
830 *pulTransferLen
= (ret
!= CR_SUCCESS
) ? 0 : *pulLength
;
835 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret
);
842 DWORD
PNP_SetDeviceRegProp(
848 PNP_PROP_SIZE ulLength
,
851 CONFIGRET ret
= CR_SUCCESS
;
852 LPWSTR lpValueName
= NULL
;
855 UNREFERENCED_PARAMETER(hBinding
);
856 UNREFERENCED_PARAMETER(ulFlags
);
858 DPRINT("PNP_SetDeviceRegProp() called\n");
860 DPRINT("DeviceId: %S\n", pDeviceId
);
861 DPRINT("Property: %lu\n", ulProperty
);
862 DPRINT("DataType: %lu\n", ulDataType
);
863 DPRINT("Length: %lu\n", ulLength
);
867 case CM_DRP_DEVICEDESC
:
868 lpValueName
= L
"DeviceDesc";
871 case CM_DRP_HARDWAREID
:
872 lpValueName
= L
"HardwareID";
875 case CM_DRP_COMPATIBLEIDS
:
876 lpValueName
= L
"CompatibleIDs";
880 lpValueName
= L
"Service";
884 lpValueName
= L
"Class";
887 case CM_DRP_CLASSGUID
:
888 lpValueName
= L
"ClassGUID";
892 lpValueName
= L
"Driver";
895 case CM_DRP_CONFIGFLAGS
:
896 lpValueName
= L
"ConfigFlags";
900 lpValueName
= L
"Mfg";
903 case CM_DRP_FRIENDLYNAME
:
904 lpValueName
= L
"FriendlyName";
907 case CM_DRP_LOCATION_INFORMATION
:
908 lpValueName
= L
"LocationInformation";
911 case CM_DRP_UPPERFILTERS
:
912 lpValueName
= L
"UpperFilters";
915 case CM_DRP_LOWERFILTERS
:
916 lpValueName
= L
"LowerFilters";
919 case CM_DRP_SECURITY
:
920 lpValueName
= L
"Security";
924 lpValueName
= L
"DeviceType";
927 case CM_DRP_EXCLUSIVE
:
928 lpValueName
= L
"Exclusive";
931 case CM_DRP_CHARACTERISTICS
:
932 lpValueName
= L
"DeviceCharacteristics";
935 case CM_DRP_UI_NUMBER_DESC_FORMAT
:
936 lpValueName
= L
"UINumberDescFormat";
939 case CM_DRP_REMOVAL_POLICY_OVERRIDE
:
940 lpValueName
= L
"RemovalPolicy";
944 return CR_INVALID_PROPERTY
;
947 DPRINT("Value name: %S\n", lpValueName
);
949 if (RegOpenKeyExW(hEnumKey
,
954 return CR_INVALID_DEVNODE
;
958 if (RegDeleteValueW(hKey
,
960 ret
= CR_REGISTRY_ERROR
;
964 if (RegSetValueExW(hKey
,
970 ret
= CR_REGISTRY_ERROR
;
975 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret
);
982 DWORD
PNP_GetClassInstance(
985 LPWSTR pszClassInstance
,
986 PNP_RPC_STRING_LEN ulLength
)
989 return CR_CALL_NOT_IMPLEMENTED
;
1002 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
1011 return CR_REGISTRY_ERROR
;
1013 /* FIXME: Set security key */
1022 DWORD
PNP_DeleteRegistryKey(
1025 LPWSTR pszParentKey
,
1030 return CR_CALL_NOT_IMPLEMENTED
;
1035 DWORD
PNP_GetClassCount(
1037 DWORD
*pulClassCount
,
1043 UNREFERENCED_PARAMETER(hBinding
);
1044 UNREFERENCED_PARAMETER(ulFlags
);
1046 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1051 if (dwError
!= ERROR_SUCCESS
)
1052 return CR_INVALID_DATA
;
1054 dwError
= RegQueryInfoKeyW(hKey
,
1067 if (dwError
!= ERROR_SUCCESS
)
1068 return CR_INVALID_DATA
;
1075 DWORD
PNP_GetClassName(
1077 LPWSTR pszClassGuid
,
1079 PNP_RPC_STRING_LEN
*pulLength
,
1082 WCHAR szKeyName
[MAX_PATH
];
1083 CONFIGRET ret
= CR_SUCCESS
;
1087 UNREFERENCED_PARAMETER(hBinding
);
1088 UNREFERENCED_PARAMETER(ulFlags
);
1090 DPRINT("PNP_GetClassName() called\n");
1092 lstrcpyW(szKeyName
, L
"System\\CurrentControlSet\\Control\\Class\\");
1093 if(lstrlenW(pszClassGuid
) + 1 < sizeof(szKeyName
)/sizeof(WCHAR
)-(lstrlenW(szKeyName
) * sizeof(WCHAR
)))
1094 lstrcatW(szKeyName
, pszClassGuid
);
1095 else return CR_INVALID_DATA
;
1097 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1102 return CR_REGISTRY_ERROR
;
1104 dwSize
= *pulLength
* sizeof(WCHAR
);
1105 if (RegQueryValueExW(hKey
,
1113 ret
= CR_REGISTRY_ERROR
;
1117 *pulLength
= dwSize
/ sizeof(WCHAR
);
1122 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret
);
1129 DWORD
PNP_DeleteClassKey(
1131 LPWSTR pszClassGuid
,
1134 CONFIGRET ret
= CR_SUCCESS
;
1136 UNREFERENCED_PARAMETER(hBinding
);
1138 DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid
, ulFlags
);
1140 if (ulFlags
& CM_DELETE_CLASS_SUBKEYS
)
1142 if (RegDeleteTreeW(hClassKey
, pszClassGuid
) != ERROR_SUCCESS
)
1143 ret
= CR_REGISTRY_ERROR
;
1147 if (RegDeleteKeyW(hClassKey
, pszClassGuid
) != ERROR_SUCCESS
)
1148 ret
= CR_REGISTRY_ERROR
;
1151 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret
);
1158 DWORD
PNP_GetInterfaceDeviceAlias(
1160 LPWSTR pszInterfaceDevice
,
1161 GUID
*AliasInterfaceGuid
,
1162 LPWSTR pszAliasInterfaceDevice
,
1163 PNP_RPC_STRING_LEN
*pulLength
,
1164 PNP_RPC_STRING_LEN
*pulTransferLen
,
1168 return CR_CALL_NOT_IMPLEMENTED
;
1173 DWORD
PNP_GetInterfaceDeviceList(
1175 GUID
*InterfaceGuid
,
1178 PNP_RPC_BUFFER_SIZE
*pulLength
,
1182 return CR_CALL_NOT_IMPLEMENTED
;
1187 DWORD
PNP_GetInterfaceDeviceListSize(
1189 PNP_RPC_BUFFER_SIZE
*pulLen
,
1190 GUID
*InterfaceGuid
,
1195 return CR_CALL_NOT_IMPLEMENTED
;
1200 DWORD
PNP_RegisterDeviceClassAssociation(
1203 GUID
*InterfaceGuid
,
1204 LPWSTR pszReference
,
1206 PNP_RPC_STRING_LEN
*pulLength
,
1207 PNP_RPC_STRING_LEN
*pulTransferLen
,
1211 return CR_CALL_NOT_IMPLEMENTED
;
1216 DWORD
PNP_UnregisterDeviceClassAssociation(
1218 LPWSTR pszInterfaceDevice
,
1222 return CR_CALL_NOT_IMPLEMENTED
;
1227 DWORD
PNP_GetClassRegProp(
1229 LPWSTR pszClassGuid
,
1231 DWORD
*pulRegDataType
,
1233 PNP_RPC_STRING_LEN
*pulTransferLen
,
1234 PNP_RPC_STRING_LEN
*pulLength
,
1238 return CR_CALL_NOT_IMPLEMENTED
;
1243 DWORD
PNP_SetClassRegProp(
1245 LPWSTR
*pszClassGuid
,
1249 PNP_PROP_SIZE ulLength
,
1253 return CR_CALL_NOT_IMPLEMENTED
;
1258 SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID
,
1259 OUT LPWSTR pszEnumerator
,
1260 OUT LPWSTR pszDevice
,
1261 OUT LPWSTR pszInstance
)
1263 WCHAR szLocalDeviceInstanceID
[MAX_DEVICE_ID_LEN
];
1264 LPWSTR lpEnumerator
= NULL
;
1265 LPWSTR lpDevice
= NULL
;
1266 LPWSTR lpInstance
= NULL
;
1269 wcscpy(szLocalDeviceInstanceID
, pszDeviceInstanceID
);
1275 lpEnumerator
= szLocalDeviceInstanceID
;
1277 ptr
= wcschr(lpEnumerator
, L
'\\');
1283 ptr
= wcschr(lpDevice
, L
'\\');
1291 if (lpEnumerator
!= NULL
)
1292 wcscpy(pszEnumerator
, lpEnumerator
);
1294 if (lpDevice
!= NULL
)
1295 wcscpy(pszDevice
, lpDevice
);
1297 if (lpInstance
!= NULL
)
1298 wcscpy(pszInstance
, lpInstance
);
1303 CreateDeviceInstance(LPWSTR pszDeviceID
)
1305 WCHAR szEnumerator
[MAX_DEVICE_ID_LEN
];
1306 WCHAR szDevice
[MAX_DEVICE_ID_LEN
];
1307 WCHAR szInstance
[MAX_DEVICE_ID_LEN
];
1308 HKEY hKeyEnumerator
;
1314 /* Split the instance ID */
1315 SplitDeviceInstanceID(pszDeviceID
,
1320 /* Open or create the enumerator key */
1321 lError
= RegCreateKeyExW(hEnumKey
,
1325 REG_OPTION_NON_VOLATILE
,
1330 if (lError
!= ERROR_SUCCESS
)
1332 return CR_REGISTRY_ERROR
;
1335 /* Open or create the device key */
1336 lError
= RegCreateKeyExW(hKeyEnumerator
,
1340 REG_OPTION_NON_VOLATILE
,
1346 /* Close the enumerator key */
1347 RegCloseKey(hKeyEnumerator
);
1349 if (lError
!= ERROR_SUCCESS
)
1351 return CR_REGISTRY_ERROR
;
1354 /* Try to open the instance key and fail if it exists */
1355 lError
= RegOpenKeyExW(hKeyDevice
,
1360 if (lError
== ERROR_SUCCESS
)
1362 DPRINT1("Instance %S already exists!\n", szInstance
);
1363 RegCloseKey(hKeyInstance
);
1364 RegCloseKey(hKeyDevice
);
1365 return CR_ALREADY_SUCH_DEVINST
;
1368 /* Create a new instance key */
1369 lError
= RegCreateKeyExW(hKeyDevice
,
1373 REG_OPTION_NON_VOLATILE
,
1379 /* Close the device key */
1380 RegCloseKey(hKeyDevice
);
1382 if (lError
!= ERROR_SUCCESS
)
1384 return CR_REGISTRY_ERROR
;
1387 /* Create the 'Control' sub key */
1388 lError
= RegCreateKeyExW(hKeyInstance
,
1392 REG_OPTION_NON_VOLATILE
,
1397 if (lError
== ERROR_SUCCESS
)
1399 RegCloseKey(hKeyControl
);
1402 RegCloseKey(hKeyInstance
);
1404 return (lError
== ERROR_SUCCESS
) ? CR_SUCCESS
: CR_REGISTRY_ERROR
;
1409 DWORD
PNP_CreateDevInst(
1412 LPWSTR pszParentDeviceID
,
1413 PNP_RPC_STRING_LEN ulLength
,
1416 CONFIGRET ret
= CR_SUCCESS
;
1418 DPRINT("PNP_CreateDevInst: %S\n", pszDeviceID
);
1420 if (ulFlags
& CM_CREATE_DEVNODE_GENERATE_ID
)
1423 DPRINT1("CM_CREATE_DEVNODE_GENERATE_ID support not implemented yet!\n", ret
);
1424 ret
= CR_CALL_NOT_IMPLEMENTED
;
1428 /* Create the device instance */
1429 ret
= CreateDeviceInstance(pszDeviceID
);
1432 DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret
);
1439 MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination
,
1440 LPWSTR pszDeviceInstanceSource
)
1442 DPRINT("MoveDeviceInstance: not implemented\n");
1444 return CR_CALL_NOT_IMPLEMENTED
;
1449 SetupDeviceInstance(LPWSTR pszDeviceInstance
,
1452 DPRINT("SetupDeviceInstance: not implemented\n");
1454 return CR_CALL_NOT_IMPLEMENTED
;
1459 EnableDeviceInstance(LPWSTR pszDeviceInstance
)
1461 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
1462 CONFIGRET ret
= CR_SUCCESS
;
1465 DPRINT("Enable device instance\n");
1467 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, pszDeviceInstance
);
1468 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
1469 if (!NT_SUCCESS(Status
))
1470 ret
= NtStatusToCrError(Status
);
1477 DisableDeviceInstance(LPWSTR pszDeviceInstance
)
1479 DPRINT("DisableDeviceInstance: not implemented\n");
1481 return CR_CALL_NOT_IMPLEMENTED
;
1486 ReenumerateDeviceInstance(LPWSTR pszDeviceInstance
)
1488 DPRINT("ReenumerateDeviceInstance: not implemented\n");
1490 return CR_CALL_NOT_IMPLEMENTED
;
1495 DWORD
PNP_DeviceInstanceAction(
1499 LPWSTR pszDeviceInstance1
,
1500 LPWSTR pszDeviceInstance2
)
1502 CONFIGRET ret
= CR_SUCCESS
;
1504 UNREFERENCED_PARAMETER(hBinding
);
1506 DPRINT("PNP_DeviceInstanceAction() called\n");
1510 case PNP_DEVINST_MOVE
:
1511 ret
= MoveDeviceInstance(pszDeviceInstance1
,
1512 pszDeviceInstance2
);
1515 case PNP_DEVINST_SETUP
:
1516 ret
= SetupDeviceInstance(pszDeviceInstance1
,
1520 case PNP_DEVINST_ENABLE
:
1521 ret
= EnableDeviceInstance(pszDeviceInstance1
);
1524 case PNP_DEVINST_DISABLE
:
1525 ret
= DisableDeviceInstance(pszDeviceInstance1
);
1528 case PNP_DEVINST_REENUMERATE
:
1529 ret
= ReenumerateDeviceInstance(pszDeviceInstance1
);
1533 DPRINT1("Unknown device action %lu: not implemented\n", ulAction
);
1534 ret
= CR_CALL_NOT_IMPLEMENTED
;
1537 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret
);
1544 DWORD
PNP_GetDeviceStatus(
1551 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData
;
1552 CONFIGRET ret
= CR_SUCCESS
;
1555 UNREFERENCED_PARAMETER(hBinding
);
1556 UNREFERENCED_PARAMETER(ulFlags
);
1558 DPRINT("PNP_GetDeviceStatus() called\n");
1560 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
1562 PlugPlayData
.Operation
= 0; /* Get status */
1564 Status
= NtPlugPlayControl(PlugPlayControlDeviceStatus
,
1565 (PVOID
)&PlugPlayData
,
1566 sizeof(PLUGPLAY_CONTROL_STATUS_DATA
));
1567 if (NT_SUCCESS(Status
))
1569 *pulStatus
= PlugPlayData
.DeviceStatus
;
1570 *pulProblem
= PlugPlayData
.DeviceProblem
;
1574 ret
= NtStatusToCrError(Status
);
1577 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret
);
1584 DWORD
PNP_SetDeviceProblem(
1591 return CR_CALL_NOT_IMPLEMENTED
;
1596 DWORD
PNP_DisableDevInst(
1599 PPNP_VETO_TYPE pVetoType
,
1605 return CR_CALL_NOT_IMPLEMENTED
;
1609 DWORD
PNP_UninstallDevInst(
1615 return CR_CALL_NOT_IMPLEMENTED
;
1620 CheckForDeviceId(LPWSTR lpDeviceIdList
,
1626 lpPtr
= lpDeviceIdList
;
1629 dwLength
= wcslen(lpPtr
);
1630 if (0 == _wcsicmp(lpPtr
, lpDeviceId
))
1633 lpPtr
+= (dwLength
+ 1);
1641 AppendDeviceId(LPWSTR lpDeviceIdList
,
1642 LPDWORD lpDeviceIdListSize
,
1648 dwLen
= wcslen(lpDeviceId
);
1649 dwPos
= (*lpDeviceIdListSize
/ sizeof(WCHAR
)) - 1;
1651 wcscpy(&lpDeviceIdList
[dwPos
], lpDeviceId
);
1653 dwPos
+= (dwLen
+ 1);
1655 lpDeviceIdList
[dwPos
] = 0;
1657 *lpDeviceIdListSize
= dwPos
* sizeof(WCHAR
);
1668 CONFIGRET ret
= CR_SUCCESS
;
1671 DWORD dwDeviceIdListSize
;
1672 DWORD dwNewDeviceIdSize
;
1673 WCHAR
* pszDeviceIdList
= NULL
;
1675 UNREFERENCED_PARAMETER(hBinding
);
1677 DPRINT("PNP_AddID() called\n");
1678 DPRINT(" DeviceInstance: %S\n", pszDeviceID
);
1679 DPRINT(" DeviceId: %S\n", pszID
);
1680 DPRINT(" Flags: %lx\n", ulFlags
);
1682 if (RegOpenKeyExW(hEnumKey
,
1685 KEY_QUERY_VALUE
| KEY_SET_VALUE
,
1686 &hDeviceKey
) != ERROR_SUCCESS
)
1688 DPRINT("Failed to open the device key!\n");
1689 return CR_INVALID_DEVNODE
;
1692 pszSubKey
= (ulFlags
& CM_ADD_ID_COMPATIBLE
) ? L
"CompatibleIDs" : L
"HardwareID";
1694 if (RegQueryValueExW(hDeviceKey
,
1699 &dwDeviceIdListSize
) != ERROR_SUCCESS
)
1701 DPRINT("Failed to query the desired ID string!\n");
1702 ret
= CR_REGISTRY_ERROR
;
1706 dwNewDeviceIdSize
= lstrlenW(pszDeviceID
);
1707 if (!dwNewDeviceIdSize
)
1709 ret
= CR_INVALID_POINTER
;
1713 dwDeviceIdListSize
+= (dwNewDeviceIdSize
+ 2) * sizeof(WCHAR
);
1715 pszDeviceIdList
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwDeviceIdListSize
);
1716 if (!pszDeviceIdList
)
1718 DPRINT("Failed to allocate memory for the desired ID string!\n");
1719 ret
= CR_OUT_OF_MEMORY
;
1723 if (RegQueryValueExW(hDeviceKey
,
1727 (LPBYTE
)pszDeviceIdList
,
1728 &dwDeviceIdListSize
) != ERROR_SUCCESS
)
1730 DPRINT("Failed to query the desired ID string!\n");
1731 ret
= CR_REGISTRY_ERROR
;
1735 /* Check whether the device ID is already in use */
1736 if (CheckForDeviceId(pszDeviceIdList
, pszDeviceID
))
1738 DPRINT("Device ID was found in the ID string!\n");
1743 /* Append the Device ID */
1744 AppendDeviceId(pszDeviceIdList
, &dwDeviceIdListSize
, pszID
);
1746 if (RegSetValueExW(hDeviceKey
,
1750 (LPBYTE
)pszDeviceIdList
,
1751 dwDeviceIdListSize
) != ERROR_SUCCESS
)
1753 DPRINT("Failed to set the desired ID string!\n");
1754 ret
= CR_REGISTRY_ERROR
;
1758 RegCloseKey(hDeviceKey
);
1759 if (pszDeviceIdList
)
1760 HeapFree(GetProcessHeap(), 0, pszDeviceIdList
);
1762 DPRINT("PNP_AddID() done (returns %lx)\n", ret
);
1769 DWORD
PNP_RegisterDriver(
1775 return CR_CALL_NOT_IMPLEMENTED
;
1780 DWORD
PNP_QueryRemove(
1783 PPNP_VETO_TYPE pVetoType
,
1789 return CR_CALL_NOT_IMPLEMENTED
;
1794 DWORD
PNP_RequestDeviceEject(
1797 PPNP_VETO_TYPE pVetoType
,
1803 return CR_CALL_NOT_IMPLEMENTED
;
1808 PNP_IsDockStationPresent(handle_t hBinding
,
1815 CONFIGRET ret
= CR_SUCCESS
;
1817 UNREFERENCED_PARAMETER(hBinding
);
1819 DPRINT1("PNP_IsDockStationPresent() called\n");
1823 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG
,
1827 &hKey
) != ERROR_SUCCESS
)
1828 return CR_REGISTRY_ERROR
;
1830 dwSize
= sizeof(DWORD
);
1831 if (RegQueryValueExW(hKey
,
1836 &dwSize
) != ERROR_SUCCESS
)
1837 ret
= CR_REGISTRY_ERROR
;
1841 if (ret
== CR_SUCCESS
)
1843 if (dwType
!= REG_DWORD
|| dwSize
!= sizeof(DWORD
))
1845 ret
= CR_REGISTRY_ERROR
;
1847 else if (dwValue
!= 0)
1853 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret
);
1860 DWORD
PNP_RequestEjectPC(
1864 return CR_CALL_NOT_IMPLEMENTED
;
1869 DWORD
PNP_HwProfFlags(
1875 PPNP_VETO_TYPE pVetoType
,
1880 CONFIGRET ret
= CR_SUCCESS
;
1881 WCHAR szKeyName
[MAX_PATH
];
1886 UNREFERENCED_PARAMETER(hBinding
);
1888 DPRINT("PNP_HwProfFlags() called\n");
1893 L
"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
1898 L
"System\\CurrentControlSet\\HardwareProfiles\\%04u\\System\\CurrentControlSet\\Enum",
1902 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1906 &hKey
) != ERROR_SUCCESS
)
1907 return CR_REGISTRY_ERROR
;
1909 if (ulAction
== PNP_GET_HWPROFFLAGS
)
1911 if (RegOpenKeyExW(hKey
,
1915 &hDeviceKey
) != ERROR_SUCCESS
)
1921 dwSize
= sizeof(DWORD
);
1922 if (!RegQueryValueExW(hDeviceKey
,
1927 &dwSize
) != ERROR_SUCCESS
)
1932 RegCloseKey(hDeviceKey
);
1935 else if (ulAction
== PNP_SET_HWPROFFLAGS
)
1937 /* FIXME: not implemented yet */
1938 ret
= CR_CALL_NOT_IMPLEMENTED
;
1948 DWORD
PNP_GetHwProfInfo(
1951 HWPROFILEINFO
*pHWProfileInfo
,
1952 DWORD ulProfileInfoSize
,
1956 return CR_CALL_NOT_IMPLEMENTED
;
1961 DWORD
PNP_AddEmptyLogConf(
1965 DWORD
*pulLogConfTag
,
1969 return CR_CALL_NOT_IMPLEMENTED
;
1974 DWORD
PNP_FreeLogConf(
1977 DWORD ulLogConfType
,
1982 return CR_CALL_NOT_IMPLEMENTED
;
1987 DWORD
PNP_GetFirstLogConf(
1990 DWORD ulLogConfType
,
1991 DWORD
*pulLogConfTag
,
1995 return CR_CALL_NOT_IMPLEMENTED
;
2000 DWORD
PNP_GetNextLogConf(
2003 DWORD ulLogConfType
,
2009 return CR_CALL_NOT_IMPLEMENTED
;
2014 DWORD
PNP_GetLogConfPriority(
2023 return CR_CALL_NOT_IMPLEMENTED
;
2028 DWORD
PNP_AddResDes(
2032 DWORD ulLogConfType
,
2033 RESOURCEID ResourceID
,
2034 DWORD
*pulResourceTag
,
2036 PNP_RPC_BUFFER_SIZE ResourceLen
,
2040 return CR_CALL_NOT_IMPLEMENTED
;
2045 DWORD
PNP_FreeResDes(
2049 DWORD ulLogConfType
,
2050 RESOURCEID ResourceID
,
2051 DWORD ulResourceTag
,
2052 DWORD
*pulPreviousResType
,
2053 DWORD
*pulPreviousResTag
,
2057 return CR_CALL_NOT_IMPLEMENTED
;
2062 DWORD
PNP_GetNextResDes(
2066 DWORD ulLogConfType
,
2067 RESOURCEID ResourceID
,
2068 DWORD ulResourceTag
,
2069 DWORD
*pulNextResType
,
2070 DWORD
*pulNextResTag
,
2074 return CR_CALL_NOT_IMPLEMENTED
;
2079 DWORD
PNP_GetResDesData(
2083 DWORD ulLogConfType
,
2084 RESOURCEID ResourceID
,
2085 DWORD ulResourceTag
,
2087 PNP_RPC_BUFFER_SIZE BufferLen
,
2091 return CR_CALL_NOT_IMPLEMENTED
;
2096 DWORD
PNP_GetResDesDataSize(
2100 DWORD ulLogConfType
,
2101 RESOURCEID ResourceID
,
2102 DWORD ulResourceTag
,
2107 return CR_CALL_NOT_IMPLEMENTED
;
2112 DWORD
PNP_ModifyResDes(
2116 DWORD ulLogConfType
,
2117 RESOURCEID CurrentResourceID
,
2118 RESOURCEID NewResourceID
,
2119 DWORD ulResourceTag
,
2121 PNP_RPC_BUFFER_SIZE ResourceLen
,
2125 return CR_CALL_NOT_IMPLEMENTED
;
2130 DWORD
PNP_DetectResourceConflict(
2133 RESOURCEID ResourceID
,
2135 PNP_RPC_BUFFER_SIZE ResourceLen
,
2136 BOOL
*pbConflictDetected
,
2140 return CR_CALL_NOT_IMPLEMENTED
;
2145 DWORD
PNP_QueryResConfList(
2148 RESOURCEID ResourceID
,
2150 PNP_RPC_BUFFER_SIZE ResourceLen
,
2152 PNP_RPC_BUFFER_SIZE BufferLen
,
2156 return CR_CALL_NOT_IMPLEMENTED
;
2161 DWORD
PNP_SetHwProf(
2163 DWORD ulHardwareProfile
,
2167 return CR_CALL_NOT_IMPLEMENTED
;
2172 DWORD
PNP_QueryArbitratorFreeData(
2177 RESOURCEID ResourceID
,
2181 return CR_CALL_NOT_IMPLEMENTED
;
2186 DWORD
PNP_QueryArbitratorFreeSize(
2190 RESOURCEID ResourceID
,
2194 return CR_CALL_NOT_IMPLEMENTED
;
2204 return CR_CALL_NOT_IMPLEMENTED
;
2209 DWORD
PNP_RegisterNotification(
2213 return CR_CALL_NOT_IMPLEMENTED
;
2218 DWORD
PNP_UnregisterNotification(
2222 return CR_CALL_NOT_IMPLEMENTED
;
2227 DWORD
PNP_GetCustomDevProp(
2230 LPWSTR CustomPropName
,
2231 DWORD
*pulRegDataType
,
2233 PNP_RPC_STRING_LEN
*pulTransferLen
,
2234 PNP_RPC_STRING_LEN
*pulLength
,
2238 return CR_CALL_NOT_IMPLEMENTED
;
2243 DWORD
PNP_GetVersionInternal(
2248 return CR_CALL_NOT_IMPLEMENTED
;
2253 DWORD
PNP_GetBlockedDriverInfo(
2256 PNP_RPC_BUFFER_SIZE
*pulTransferLen
,
2257 PNP_RPC_BUFFER_SIZE
*pulLength
,
2261 return CR_CALL_NOT_IMPLEMENTED
;
2266 DWORD
PNP_GetServerSideDeviceInstallFlags(
2268 DWORD
*pulSSDIFlags
,
2272 return CR_CALL_NOT_IMPLEMENTED
;
2277 DWORD
PNP_GetObjectPropKeys(
2281 LPWSTR PropertyCultureName
,
2282 PNP_PROP_COUNT
*PropertyCount
,
2283 PNP_PROP_COUNT
*TransferLen
,
2284 DEVPROPKEY
*PropertyKeys
,
2288 return CR_CALL_NOT_IMPLEMENTED
;
2293 DWORD
PNP_GetObjectProp(
2297 LPWSTR PropertyCultureName
,
2298 const DEVPROPKEY
*PropertyKey
,
2299 DEVPROPTYPE
*PropertyType
,
2300 PNP_PROP_SIZE
*PropertySize
,
2301 PNP_PROP_SIZE
*TransferLen
,
2302 BYTE
*PropertyBuffer
,
2306 return CR_CALL_NOT_IMPLEMENTED
;
2311 DWORD
PNP_SetObjectProp(
2315 LPWSTR PropertyCultureName
,
2316 const DEVPROPKEY
*PropertyKey
,
2317 DEVPROPTYPE PropertyType
,
2318 PNP_PROP_SIZE PropertySize
,
2319 BYTE
*PropertyBuffer
,
2323 return CR_CALL_NOT_IMPLEMENTED
;
2328 DWORD
PNP_InstallDevInst(
2332 return CR_CALL_NOT_IMPLEMENTED
;
2337 DWORD
PNP_ApplyPowerSettings(
2341 return CR_CALL_NOT_IMPLEMENTED
;
2346 DWORD
PNP_DriverStoreAddDriverPackage(
2350 return CR_CALL_NOT_IMPLEMENTED
;
2355 DWORD
PNP_DriverStoreDeleteDriverPackage(
2359 return CR_CALL_NOT_IMPLEMENTED
;
2364 DWORD
PNP_RegisterServiceNotification(
2368 return CR_CALL_NOT_IMPLEMENTED
;
2373 DWORD
PNP_SetActiveService(
2377 return CR_CALL_NOT_IMPLEMENTED
;
2382 DWORD
PNP_DeleteServiceDevices(
2386 return CR_CALL_NOT_IMPLEMENTED
;
2391 InstallDevice(PCWSTR DeviceInstance
, BOOL ShowWizard
)
2393 BOOL DeviceInstalled
= FALSE
;
2396 HANDLE hPipe
= INVALID_HANDLE_VALUE
;
2397 LPVOID Environment
= NULL
;
2398 PROCESS_INFORMATION ProcessInfo
;
2399 STARTUPINFOW StartupInfo
;
2403 /* The following lengths are constant (see below), they cannot overflow */
2404 WCHAR CommandLine
[116];
2405 WCHAR InstallEventName
[73];
2407 WCHAR UuidString
[39];
2409 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance
, ShowWizard
);
2411 ZeroMemory(&ProcessInfo
, sizeof(ProcessInfo
));
2413 if (RegOpenKeyExW(hEnumKey
,
2417 &DeviceKey
) == ERROR_SUCCESS
)
2419 if (RegQueryValueExW(DeviceKey
,
2424 NULL
) == ERROR_SUCCESS
)
2426 DPRINT("No need to install: %S\n", DeviceInstance
);
2427 RegCloseKey(DeviceKey
);
2431 RegCloseKey(DeviceKey
);
2434 DPRINT1("Installing: %S\n", DeviceInstance
);
2436 /* Create a random UUID for the named pipe */
2437 UuidCreate(&RandomUuid
);
2438 swprintf(UuidString
, L
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
2439 RandomUuid
.Data1
, RandomUuid
.Data2
, RandomUuid
.Data3
,
2440 RandomUuid
.Data4
[0], RandomUuid
.Data4
[1], RandomUuid
.Data4
[2],
2441 RandomUuid
.Data4
[3], RandomUuid
.Data4
[4], RandomUuid
.Data4
[5],
2442 RandomUuid
.Data4
[6], RandomUuid
.Data4
[7]);
2444 /* Create the named pipe */
2445 wcscpy(PipeName
, L
"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
2446 wcscat(PipeName
, UuidString
);
2447 hPipe
= CreateNamedPipeW(PipeName
, PIPE_ACCESS_OUTBOUND
, PIPE_TYPE_BYTE
, 1, 512, 512, 0, NULL
);
2449 if(hPipe
== INVALID_HANDLE_VALUE
)
2451 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
2455 /* Launch rundll32 to call ClientSideInstallW */
2456 wcscpy(CommandLine
, L
"rundll32.exe newdev.dll,ClientSideInstall ");
2457 wcscat(CommandLine
, PipeName
);
2459 ZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
2460 StartupInfo
.cb
= sizeof(StartupInfo
);
2464 /* newdev has to run under the environment of the current user */
2465 if(!CreateEnvironmentBlock(&Environment
, hUserToken
, FALSE
))
2467 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
2471 if(!CreateProcessAsUserW(hUserToken
, NULL
, CommandLine
, NULL
, NULL
, FALSE
, CREATE_UNICODE_ENVIRONMENT
, Environment
, NULL
, &StartupInfo
, &ProcessInfo
))
2473 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
2479 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
2481 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
2482 (ShowWizard is only set to FALSE for these two modes) */
2483 ASSERT(!ShowWizard
);
2485 if(!CreateProcessW(NULL
, CommandLine
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &StartupInfo
, &ProcessInfo
))
2487 DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
2492 /* Wait for the function to connect to our pipe */
2493 if(!ConnectNamedPipe(hPipe
, NULL
))
2495 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
2499 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
2500 wcscpy(InstallEventName
, L
"Global\\PNP_Device_Install_Event_0.");
2501 wcscat(InstallEventName
, UuidString
);
2503 Value
= sizeof(InstallEventName
);
2504 WriteFile(hPipe
, &Value
, sizeof(Value
), &BytesWritten
, NULL
);
2505 WriteFile(hPipe
, InstallEventName
, Value
, &BytesWritten
, NULL
);
2507 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
2508 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
2509 WriteFile(hPipe
, &ShowWizard
, sizeof(ShowWizard
), &BytesWritten
, NULL
);
2511 Value
= (wcslen(DeviceInstance
) + 1) * sizeof(WCHAR
);
2512 WriteFile(hPipe
, &Value
, sizeof(Value
), &BytesWritten
, NULL
);
2513 WriteFile(hPipe
, DeviceInstance
, Value
, &BytesWritten
, NULL
);
2515 /* Wait for newdev.dll to finish processing */
2516 WaitForSingleObject(ProcessInfo
.hProcess
, INFINITE
);
2518 /* The following check for success is probably not compatible to Windows, but should do its job */
2519 if(!GetExitCodeProcess(ProcessInfo
.hProcess
, &Value
))
2521 DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
2525 DeviceInstalled
= Value
;
2528 if(hPipe
!= INVALID_HANDLE_VALUE
)
2532 DestroyEnvironmentBlock(Environment
);
2534 if(ProcessInfo
.hProcess
)
2535 CloseHandle(ProcessInfo
.hProcess
);
2537 if(ProcessInfo
.hThread
)
2538 CloseHandle(ProcessInfo
.hThread
);
2540 DPRINT1("Success? %d\n", DeviceInstalled
);
2542 return DeviceInstalled
;
2558 return ERROR_INVALID_PARAMETER
;
2561 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, &dwType
, NULL
, &cbData
);
2562 if (rc
!= ERROR_SUCCESS
)
2564 if (dwType
!= REG_SZ
)
2565 return ERROR_FILE_NOT_FOUND
;
2566 Value
= HeapAlloc(GetProcessHeap(), 0, cbData
+ sizeof(WCHAR
));
2568 return ERROR_NOT_ENOUGH_MEMORY
;
2569 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, NULL
, (LPBYTE
)Value
, &cbData
);
2570 if (rc
!= ERROR_SUCCESS
)
2572 HeapFree(GetProcessHeap(), 0, Value
);
2575 /* NULL-terminate the string */
2576 Value
[cbData
/ sizeof(WCHAR
)] = '\0';
2579 return ERROR_SUCCESS
;
2587 DWORD regType
, active
, size
;
2591 rc
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\Setup", 0, KEY_QUERY_VALUE
, &hKey
);
2592 if (rc
!= ERROR_SUCCESS
)
2595 size
= sizeof(DWORD
);
2596 rc
= RegQueryValueExW(hKey
, L
"SystemSetupInProgress", NULL
, ®Type
, (LPBYTE
)&active
, &size
);
2597 if (rc
!= ERROR_SUCCESS
)
2599 if (regType
!= REG_DWORD
|| size
!= sizeof(DWORD
))
2602 ret
= (active
!= 0);
2608 DPRINT("System setup in progress? %S\n", ret
? L
"YES" : L
"NO");
2617 HKEY ControlKey
= NULL
;
2618 LPWSTR SystemStartOptions
= NULL
;
2619 LPWSTR CurrentOption
, NextOption
; /* Pointers into SystemStartOptions */
2620 BOOL ConsoleBoot
= FALSE
;
2625 L
"SYSTEM\\CurrentControlSet\\Control",
2630 rc
= ReadRegSzKey(ControlKey
, L
"SystemStartOptions", &SystemStartOptions
);
2631 if (rc
!= ERROR_SUCCESS
)
2634 /* Check for CMDCONS in SystemStartOptions */
2635 CurrentOption
= SystemStartOptions
;
2636 while (CurrentOption
)
2638 NextOption
= wcschr(CurrentOption
, L
' ');
2640 *NextOption
= L
'\0';
2641 if (_wcsicmp(CurrentOption
, L
"CONSOLE") == 0)
2643 DPRINT("Found %S. Switching to console boot\n", CurrentOption
);
2647 CurrentOption
= NextOption
? NextOption
+ 1 : NULL
;
2651 if (ControlKey
!= NULL
)
2652 RegCloseKey(ControlKey
);
2653 HeapFree(GetProcessHeap(), 0, SystemStartOptions
);
2658 /* Loop to install all queued devices installations */
2660 DeviceInstallThread(LPVOID lpParameter
)
2662 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2663 PSLIST_ENTRY ListEntry
;
2665 PLIST_ENTRY ListEntry
;
2667 DeviceInstallParams
* Params
;
2670 UNREFERENCED_PARAMETER(lpParameter
);
2672 WaitForSingleObject(hInstallEvent
, INFINITE
);
2674 showWizard
= !SetupIsActive() && !IsConsoleBoot();
2678 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2679 ListEntry
= InterlockedPopEntrySList(&DeviceInstallListHead
);
2681 if ((BOOL
)IsListEmpty(&DeviceInstallListHead
))
2684 ListEntry
= RemoveHeadList(&DeviceInstallListHead
);
2686 if (ListEntry
== NULL
)
2688 SetEvent(hNoPendingInstalls
);
2689 WaitForSingleObject(hDeviceInstallListNotEmpty
, INFINITE
);
2693 ResetEvent(hNoPendingInstalls
);
2694 Params
= CONTAINING_RECORD(ListEntry
, DeviceInstallParams
, ListEntry
);
2695 InstallDevice(Params
->DeviceIds
, showWizard
);
2704 PnpEventThread(LPVOID lpParameter
)
2706 PPLUGPLAY_EVENT_BLOCK PnpEvent
;
2709 RPC_STATUS RpcStatus
;
2711 UNREFERENCED_PARAMETER(lpParameter
);
2713 PnpEventSize
= 0x1000;
2714 PnpEvent
= HeapAlloc(GetProcessHeap(), 0, PnpEventSize
);
2715 if (PnpEvent
== NULL
)
2716 return ERROR_OUTOFMEMORY
;
2720 DPRINT("Calling NtGetPlugPlayEvent()\n");
2722 /* Wait for the next pnp event */
2723 Status
= NtGetPlugPlayEvent(0, 0, PnpEvent
, PnpEventSize
);
2725 /* Resize the buffer for the PnP event if it's too small. */
2726 if (Status
== STATUS_BUFFER_TOO_SMALL
)
2728 PnpEventSize
+= 0x400;
2729 HeapFree(GetProcessHeap(), 0, PnpEvent
);
2730 PnpEvent
= HeapAlloc(GetProcessHeap(), 0, PnpEventSize
);
2731 if (PnpEvent
== NULL
)
2732 return ERROR_OUTOFMEMORY
;
2736 if (!NT_SUCCESS(Status
))
2738 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status
);
2742 /* Process the pnp event */
2743 DPRINT("Received PnP Event\n");
2744 if (UuidEqual(&PnpEvent
->EventGuid
, (UUID
*)&GUID_DEVICE_ENUMERATED
, &RpcStatus
))
2746 DeviceInstallParams
* Params
;
2748 DWORD DeviceIdLength
;
2750 DPRINT1("Device enumerated: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
2752 DeviceIdLength
= lstrlenW(PnpEvent
->TargetDevice
.DeviceIds
);
2755 /* Queue device install (will be dequeued by DeviceInstallThread */
2756 len
= FIELD_OFFSET(DeviceInstallParams
, DeviceIds
) + (DeviceIdLength
+ 1) * sizeof(WCHAR
);
2757 Params
= HeapAlloc(GetProcessHeap(), 0, len
);
2760 wcscpy(Params
->DeviceIds
, PnpEvent
->TargetDevice
.DeviceIds
);
2761 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2762 InterlockedPushEntrySList(&DeviceInstallListHead
, &Params
->ListEntry
);
2764 InsertTailList(&DeviceInstallListHead
, &Params
->ListEntry
);
2766 SetEvent(hDeviceInstallListNotEmpty
);
2770 else if (UuidEqual(&PnpEvent
->EventGuid
, (UUID
*)&GUID_DEVICE_ARRIVAL
, &RpcStatus
))
2772 DPRINT1("Device arrival: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
2777 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
2778 PnpEvent
->EventGuid
.Data1
, PnpEvent
->EventGuid
.Data2
, PnpEvent
->EventGuid
.Data3
,
2779 PnpEvent
->EventGuid
.Data4
[0], PnpEvent
->EventGuid
.Data4
[1], PnpEvent
->EventGuid
.Data4
[2],
2780 PnpEvent
->EventGuid
.Data4
[3], PnpEvent
->EventGuid
.Data4
[4], PnpEvent
->EventGuid
.Data4
[5],
2781 PnpEvent
->EventGuid
.Data4
[6], PnpEvent
->EventGuid
.Data4
[7]);
2784 /* Dequeue the current pnp event and signal the next one */
2785 NtPlugPlayControl(PlugPlayControlUserResponse
, NULL
, 0);
2788 HeapFree(GetProcessHeap(), 0, PnpEvent
);
2790 return ERROR_SUCCESS
;
2795 UpdateServiceStatus(DWORD dwState
)
2797 ServiceStatus
.dwServiceType
= SERVICE_WIN32_OWN_PROCESS
;
2798 ServiceStatus
.dwCurrentState
= dwState
;
2799 ServiceStatus
.dwControlsAccepted
= 0;
2800 ServiceStatus
.dwWin32ExitCode
= 0;
2801 ServiceStatus
.dwServiceSpecificExitCode
= 0;
2802 ServiceStatus
.dwCheckPoint
= 0;
2804 if (dwState
== SERVICE_START_PENDING
||
2805 dwState
== SERVICE_STOP_PENDING
||
2806 dwState
== SERVICE_PAUSE_PENDING
||
2807 dwState
== SERVICE_CONTINUE_PENDING
)
2808 ServiceStatus
.dwWaitHint
= 10000;
2810 ServiceStatus
.dwWaitHint
= 0;
2812 SetServiceStatus(ServiceStatusHandle
,
2818 ServiceControlHandler(DWORD dwControl
,
2823 DPRINT1("ServiceControlHandler() called\n");
2827 case SERVICE_CONTROL_STOP
:
2828 DPRINT1(" SERVICE_CONTROL_STOP received\n");
2829 UpdateServiceStatus(SERVICE_STOPPED
);
2830 return ERROR_SUCCESS
;
2832 case SERVICE_CONTROL_PAUSE
:
2833 DPRINT1(" SERVICE_CONTROL_PAUSE received\n");
2834 UpdateServiceStatus(SERVICE_PAUSED
);
2835 return ERROR_SUCCESS
;
2837 case SERVICE_CONTROL_CONTINUE
:
2838 DPRINT1(" SERVICE_CONTROL_CONTINUE received\n");
2839 UpdateServiceStatus(SERVICE_RUNNING
);
2840 return ERROR_SUCCESS
;
2842 case SERVICE_CONTROL_INTERROGATE
:
2843 DPRINT1(" SERVICE_CONTROL_INTERROGATE received\n");
2844 SetServiceStatus(ServiceStatusHandle
,
2846 return ERROR_SUCCESS
;
2848 case SERVICE_CONTROL_SHUTDOWN
:
2849 DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n");
2850 UpdateServiceStatus(SERVICE_STOPPED
);
2851 return ERROR_SUCCESS
;
2854 DPRINT1(" Control %lu received\n");
2855 return ERROR_CALL_NOT_IMPLEMENTED
;
2860 static VOID CALLBACK
2861 ServiceMain(DWORD argc
, LPTSTR
*argv
)
2866 UNREFERENCED_PARAMETER(argc
);
2867 UNREFERENCED_PARAMETER(argv
);
2869 DPRINT("ServiceMain() called\n");
2871 ServiceStatusHandle
= RegisterServiceCtrlHandlerExW(ServiceName
,
2872 ServiceControlHandler
,
2874 if (!ServiceStatusHandle
)
2876 DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
2880 UpdateServiceStatus(SERVICE_START_PENDING
);
2882 hThread
= CreateThread(NULL
,
2888 if (hThread
!= NULL
)
2889 CloseHandle(hThread
);
2891 hThread
= CreateThread(NULL
,
2897 if (hThread
!= NULL
)
2898 CloseHandle(hThread
);
2900 hThread
= CreateThread(NULL
,
2902 DeviceInstallThread
,
2906 if (hThread
!= NULL
)
2907 CloseHandle(hThread
);
2909 UpdateServiceStatus(SERVICE_RUNNING
);
2911 DPRINT("ServiceMain() done\n");
2916 wmain(int argc
, WCHAR
*argv
[])
2921 UNREFERENCED_PARAMETER(argc
);
2922 UNREFERENCED_PARAMETER(argv
);
2924 DPRINT("Umpnpmgr: main() started\n");
2926 /* We need this privilege for using CreateProcessAsUserW */
2927 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE
, TRUE
, FALSE
, &OldValue
);
2929 hInstallEvent
= CreateEvent(NULL
, TRUE
, SetupIsActive()/*FALSE*/, NULL
);
2930 if (hInstallEvent
== NULL
)
2932 dwError
= GetLastError();
2933 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError
);
2937 hDeviceInstallListNotEmpty
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
2938 if (hDeviceInstallListNotEmpty
== NULL
)
2940 dwError
= GetLastError();
2941 DPRINT1("Could not create the Event! (Error %lu)\n", dwError
);
2945 hNoPendingInstalls
= CreateEventW(NULL
,
2948 L
"Global\\PnP_No_Pending_Install_Events");
2949 if (hNoPendingInstalls
== NULL
)
2951 dwError
= GetLastError();
2952 DPRINT1("Could not create the Event! (Error %lu)\n", dwError
);
2956 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2957 InitializeSListHead(&DeviceInstallListHead
);
2959 InitializeListHead(&DeviceInstallListHead
);
2962 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2963 L
"System\\CurrentControlSet\\Enum",
2967 if (dwError
!= ERROR_SUCCESS
)
2969 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError
);
2973 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2974 L
"System\\CurrentControlSet\\Control\\Class",
2978 if (dwError
!= ERROR_SUCCESS
)
2980 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError
);
2984 StartServiceCtrlDispatcher(ServiceTable
);
2986 DPRINT("Umpnpmgr: main() done\n");