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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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
27 /* INCLUDES *****************************************************************/
30 #define NTOS_MODE_USER
31 #include <ndk/ntndk.h>
32 #include <ndk/sysguid.h>
33 #include <ddk/wdmguid.h>
34 #include <ddk/cfgmgr32.h>
44 /* GLOBALS ******************************************************************/
47 ServiceMain(DWORD argc
, LPTSTR
*argv
);
49 static SERVICE_TABLE_ENTRY ServiceTable
[2] =
51 {TEXT("PlugPlay"), ServiceMain
},
55 static WCHAR szRootDeviceId
[] = L
"HTREE\\ROOT\\0";
57 static HKEY hEnumKey
= NULL
;
58 static HKEY hClassKey
= NULL
;
60 /* FUNCTIONS *****************************************************************/
63 RpcServerThread(LPVOID lpParameter
)
67 DPRINT("RpcServerThread() called\n");
69 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
72 NULL
); // Security descriptor
73 if (Status
!= RPC_S_OK
)
75 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
79 Status
= RpcServerRegisterIf(pnp_v1_0_s_ifspec
,
82 if (Status
!= RPC_S_OK
)
84 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
88 Status
= RpcServerListen(1,
91 if (Status
!= RPC_S_OK
)
93 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
97 DPRINT("RpcServerThread() done\n");
103 void __RPC_FAR
* __RPC_USER
midl_user_allocate(size_t len
)
105 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
109 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
111 HeapFree(GetProcessHeap(), 0, ptr
);
116 PNP_GetVersion(handle_t BindingHandle
,
117 unsigned short *Version
)
125 PNP_GetGlobalState(handle_t BindingHandle
,
126 unsigned long *State
,
129 *State
= CM_GLOBAL_STATE_CAN_DO_UI
| CM_GLOBAL_STATE_SERVICES_AVAILABLE
;
135 PNP_ValidateDeviceInstance(handle_t BindingHandle
,
136 wchar_t *DeviceInstance
,
139 CONFIGRET ret
= CR_SUCCESS
;
140 HKEY hEnumKey
= NULL
;
141 HKEY hDeviceKey
= NULL
;
143 DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
144 DeviceInstance
, Flags
);
146 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
147 L
"System\\CurrentControlSet\\Enum",
152 DPRINT("Could not open the Enum Key!\n");
157 if (RegOpenKeyExW(hEnumKey
,
163 DPRINT("Could not open the Device Key!\n");
164 ret
= CR_NO_SUCH_DEVNODE
;
168 /* FIXME: add more tests */
171 if (hDeviceKey
!= NULL
)
172 RegCloseKey(hDeviceKey
);
174 if (hEnumKey
!= NULL
)
175 RegCloseKey(hEnumKey
);
177 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret
);
184 PNP_GetRootDeviceInstance(handle_t BindingHandle
,
185 wchar_t *DeviceInstance
,
186 unsigned long Length
)
188 CONFIGRET ret
= CR_SUCCESS
;
190 DPRINT("PNP_GetRootDeviceInstance() called\n");
192 if (Length
< lstrlenW(szRootDeviceId
) + 1)
194 ret
= CR_BUFFER_SMALL
;
198 lstrcpyW(DeviceInstance
,
202 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret
);
209 PNP_GetRelatedDeviceInstance(handle_t BindingHandle
,
210 unsigned long Relationship
,
212 wchar_t *RelatedDeviceId
,
213 unsigned long Length
,
216 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData
;
217 CONFIGRET ret
= CR_SUCCESS
;
220 DPRINT("PNP_GetRelatedDeviceInstance() called\n");
221 DPRINT(" Relationship %ld\n", Relationship
);
222 DPRINT(" DeviceId %S\n", DeviceId
);
224 RtlInitUnicodeString(&PlugPlayData
.TargetDeviceInstance
,
227 PlugPlayData
.Relation
= Relationship
;
229 PlugPlayData
.RelatedDeviceInstance
.Length
= 0;
230 PlugPlayData
.RelatedDeviceInstance
.MaximumLength
= Length
;
231 PlugPlayData
.RelatedDeviceInstance
.Buffer
= RelatedDeviceId
;
233 Status
= NtPlugPlayControl(PlugPlayControlGetRelatedDevice
,
234 (PVOID
)&PlugPlayData
,
235 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA
));
236 if (!NT_SUCCESS(Status
))
238 /* FIXME: Map Status to ret */
242 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret
);
243 if (ret
== CR_SUCCESS
)
245 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData
.RelatedDeviceInstance
);
253 PNP_EnumerateSubKeys(handle_t BindingHandle
,
254 unsigned long Branch
,
257 unsigned long Length
,
258 unsigned long *RequiredLength
,
261 CONFIGRET ret
= CR_SUCCESS
;
265 DPRINT1("PNP_EnumerateSubKeys() called\n");
281 *RequiredLength
= Length
;
282 dwError
= RegEnumKeyExW(hKey
,
290 if (dwError
!= ERROR_SUCCESS
)
295 DPRINT1("PNP_EnumerateSubKeys() done (returns %lx)\n", ret
);
296 if (ret
== CR_SUCCESS
)
298 DPRINT1("Sub key: %S\n", Buffer
);
306 PNP_GetDepth(handle_t BindingHandle
,
307 wchar_t *DeviceInstance
,
308 unsigned long *Depth
,
311 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData
;
312 CONFIGRET ret
= CR_SUCCESS
;
315 DPRINT("PNP_GetDepth() called\n");
317 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
320 Status
= NtPlugPlayControl(PlugPlayControlGetDeviceDepth
,
321 (PVOID
)&PlugPlayData
,
322 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA
));
323 if (NT_SUCCESS(Status
))
325 *Depth
= PlugPlayData
.Depth
;
329 ret
= CR_FAILURE
; /* FIXME */
332 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret
);
339 PNP_SetDeviceRegProp(handle_t BindingHandle
,
341 unsigned long Property
,
342 unsigned long DataType
,
344 unsigned long Length
,
347 CONFIGRET ret
= CR_SUCCESS
;
348 LPWSTR lpValueName
= NULL
;
351 DPRINT("PNP_SetDeviceRegProp() called\n");
353 DPRINT("DeviceId: %S\n", DeviceId
);
354 DPRINT("Property: %lu\n", Property
);
355 DPRINT("DataType: %lu\n", DataType
);
356 DPRINT("Length: %lu\n", Length
);
360 case CM_DRP_DEVICEDESC
:
361 lpValueName
= L
"DeviceDesc";
364 case CM_DRP_HARDWAREID
:
365 lpValueName
= L
"HardwareID";
368 case CM_DRP_COMPATIBLEIDS
:
369 lpValueName
= L
"CompatibleIDs";
373 lpValueName
= L
"Service";
377 lpValueName
= L
"Class";
380 case CM_DRP_CLASSGUID
:
381 lpValueName
= L
"ClassGUID";
385 lpValueName
= L
"Driver";
388 case CM_DRP_CONFIGFLAGS
:
389 lpValueName
= L
"ConfigFlags";
393 lpValueName
= L
"Mfg";
396 case CM_DRP_FRIENDLYNAME
:
397 lpValueName
= L
"FriendlyName";
400 case CM_DRP_LOCATION_INFORMATION
:
401 lpValueName
= L
"LocationInformation";
404 case CM_DRP_UPPERFILTERS
:
405 lpValueName
= L
"UpperFilters";
408 case CM_DRP_LOWERFILTERS
:
409 lpValueName
= L
"LowerFilters";
413 return CR_INVALID_PROPERTY
;
416 DPRINT("Value name: %S\n", lpValueName
);
418 if (RegOpenKeyExW(hEnumKey
,
423 return CR_INVALID_DEVNODE
;
427 if (RegDeleteValueW(hKey
,
429 ret
= CR_REGISTRY_ERROR
;
433 if (RegSetValueExW(hKey
,
439 ret
= CR_REGISTRY_ERROR
;
444 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret
);
451 PNP_GetDeviceRegProp(handle_t BindingHandle
,
452 wchar_t *DeviceInstance
,
453 unsigned long Property
,
454 unsigned long *DataType
,
456 unsigned long *TransferLen
,
457 unsigned long *Length
,
460 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData
;
461 CONFIGRET ret
= CR_SUCCESS
;
462 LPWSTR lpValueName
= NULL
;
466 DPRINT("PNP_GetDeviceRegProp() called\n");
470 case CM_DRP_DEVICEDESC
:
471 lpValueName
= L
"DeviceDesc";
474 case CM_DRP_HARDWAREID
:
475 lpValueName
= L
"HardwareID";
478 case CM_DRP_COMPATIBLEIDS
:
479 lpValueName
= L
"CompatibleIDs";
483 lpValueName
= L
"Service";
487 lpValueName
= L
"Class";
490 case CM_DRP_CLASSGUID
:
491 lpValueName
= L
"ClassGUID";
495 lpValueName
= L
"Driver";
498 case CM_DRP_CONFIGFLAGS
:
499 lpValueName
= L
"ConfigFlags";
503 lpValueName
= L
"Mfg";
506 case CM_DRP_FRIENDLYNAME
:
507 lpValueName
= L
"FriendlyName";
510 case CM_DRP_LOCATION_INFORMATION
:
511 lpValueName
= L
"LocationInformation";
514 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME
:
518 case CM_DRP_CAPABILITIES
:
519 lpValueName
= L
"Capabilities";
522 case CM_DRP_UI_NUMBER
:
526 case CM_DRP_UPPERFILTERS
:
527 lpValueName
= L
"UpperFilters";
530 case CM_DRP_LOWERFILTERS
:
531 lpValueName
= L
"LowerFilters";
534 case CM_DRP_BUSTYPEGUID
:
538 case CM_DRP_LEGACYBUSTYPE
:
542 case CM_DRP_BUSNUMBER
:
546 case CM_DRP_ENUMERATOR_NAME
:
551 return CR_INVALID_PROPERTY
;
554 DPRINT("Value name: %S\n", lpValueName
);
558 /* Retrieve information from the Registry */
559 if (RegOpenKeyExW(hEnumKey
,
564 return CR_INVALID_DEVNODE
;
566 if (RegQueryValueExW(hKey
,
572 ret
= CR_REGISTRY_ERROR
;
574 /* FIXME: Check buffer size */
580 /* Retrieve information from the Device Node */
581 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
583 PlugPlayData
.Buffer
= Buffer
;
584 PlugPlayData
.BufferSize
= *TransferLen
;
589 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME
:
590 PlugPlayData
.Property
= DevicePropertyPhysicalDeviceObjectName
;
593 case CM_DRP_UI_NUMBER
:
594 PlugPlayData
.Property
= DevicePropertyUINumber
;
597 case CM_DRP_BUSTYPEGUID
:
598 PlugPlayData
.Property
= DevicePropertyBusTypeGuid
;
601 case CM_DRP_LEGACYBUSTYPE
:
602 PlugPlayData
.Property
= DevicePropertyLegacyBusType
;
605 case CM_DRP_BUSNUMBER
:
606 PlugPlayData
.Property
= DevicePropertyBusNumber
;
609 case CM_DRP_ENUMERATOR_NAME
:
610 PlugPlayData
.Property
= DevicePropertyEnumeratorName
;
615 return CR_INVALID_PROPERTY
;
618 Status
= NtPlugPlayControl(PlugPlayControlProperty
,
619 (PVOID
)&PlugPlayData
,
620 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA
));
621 if (NT_SUCCESS(Status
))
623 *Length
= PlugPlayData
.BufferSize
;
627 ret
= CR_FAILURE
; /* FIXME */
631 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret
);
638 PNP_GetClassName(handle_t BindingHandle
,
639 wchar_t *ClassGuid
, /* in */
640 wchar_t *Buffer
, /* out */
641 unsigned long *Length
, /* in out */
644 WCHAR szKeyName
[MAX_PATH
];
645 CONFIGRET ret
= CR_SUCCESS
;
649 DPRINT1("PNP_GetClassName() called\n");
651 lstrcpyW(szKeyName
, L
"System\\CurrentControlSet\\Control\\Class");
652 lstrcatW(szKeyName
, L
"\\");
653 lstrcatW(szKeyName
, ClassGuid
);
655 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
660 return CR_REGISTRY_ERROR
;
662 ulSize
= *Length
* sizeof(WCHAR
);
663 if (RegQueryValueExW(hKey
,
671 ret
= CR_REGISTRY_ERROR
;
675 *Length
= ulSize
/ sizeof(WCHAR
);
680 DPRINT1("PNP_GetClassName() done (returns %lx)\n", ret
);
687 PNP_GetDeviceStatus(handle_t BindingHandle
,
688 wchar_t *DeviceInstance
,
689 unsigned long *pStatus
,
690 unsigned long *pProblem
,
693 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData
;
694 CONFIGRET ret
= CR_SUCCESS
;
697 DPRINT("PNP_GetDeviceStatus() called\n");
699 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
701 PlugPlayData
.Operation
= 0; /* Get status */
703 Status
= NtPlugPlayControl(PlugPlayControlDeviceStatus
,
704 (PVOID
)&PlugPlayData
,
705 sizeof(PLUGPLAY_CONTROL_STATUS_DATA
));
706 if (NT_SUCCESS(Status
))
708 *pStatus
= PlugPlayData
.DeviceStatus
;
709 *pProblem
= PlugPlayData
.DeviceProblem
;
713 ret
= CR_FAILURE
; /* FIXME */
716 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret
);
723 PNP_SetDeviceProblem(handle_t BindingHandle
,
724 wchar_t *DeviceInstance
,
725 unsigned long Problem
,
728 CONFIGRET ret
= CR_SUCCESS
;
730 DPRINT1("PNP_SetDeviceProblem() called\n");
734 DPRINT1("PNP_SetDeviceProblem() done (returns %lx)\n", ret
);
741 PnpEventThread(LPVOID lpParameter
)
743 PPLUGPLAY_EVENT_BLOCK PnpEvent
;
746 RPC_STATUS RpcStatus
;
748 PnpEventSize
= 0x1000;
749 PnpEvent
= HeapAlloc(GetProcessHeap(), 0, PnpEventSize
);
750 if (PnpEvent
== NULL
)
751 return ERROR_OUTOFMEMORY
;
755 DPRINT("Calling NtGetPlugPlayEvent()\n");
757 /* Wait for the next pnp event */
758 Status
= NtGetPlugPlayEvent(0, 0, PnpEvent
, PnpEventSize
);
760 /* Resize the buffer for the PnP event if it's too small. */
761 if (Status
== STATUS_BUFFER_TOO_SMALL
)
763 PnpEventSize
+= 0x400;
764 PnpEvent
= HeapReAlloc(GetProcessHeap(), 0, PnpEvent
, PnpEventSize
);
765 if (PnpEvent
== NULL
)
766 return ERROR_OUTOFMEMORY
;
770 if (!NT_SUCCESS(Status
))
772 DPRINT("NtPlugPlayEvent() failed (Status %lx)\n", Status
);
776 DPRINT("Received PnP Event\n");
777 if (UuidEqual(&PnpEvent
->EventGuid
, (UUID
*)&GUID_DEVICE_ARRIVAL
, &RpcStatus
))
779 DPRINT("Device arrival event: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
783 DPRINT1("Unknown event\n");
786 /* FIXME: Process the pnp event */
788 /* Dequeue the current pnp event and signal the next one */
789 NtPlugPlayControl(PlugPlayControlUserResponse
, NULL
, 0);
792 HeapFree(GetProcessHeap(), 0, PnpEvent
);
794 return ERROR_SUCCESS
;
799 ServiceMain(DWORD argc
, LPTSTR
*argv
)
804 DPRINT("ServiceMain() called\n");
806 hThread
= CreateThread(NULL
,
813 CloseHandle(hThread
);
815 hThread
= CreateThread(NULL
,
822 CloseHandle(hThread
);
824 DPRINT("ServiceMain() done\n");
829 main(int argc
, char *argv
[])
833 DPRINT("Umpnpmgr: main() started\n");
835 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
836 L
"System\\CurrentControlSet\\Enum",
840 if (dwError
!= ERROR_SUCCESS
)
842 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError
);
846 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
847 L
"System\\CurrentControlSet\\Control\\Class",
851 if (dwError
!= ERROR_SUCCESS
)
853 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError
);
857 StartServiceCtrlDispatcher(ServiceTable
);
859 DPRINT("Umpnpmgr: main() done\n");