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 CONFIGRET ret
= CR_SUCCESS
;
461 LPWSTR lpValueName
= NULL
;
464 DPRINT1("PNP_GetDeviceRegProp() called\n");
468 case CM_DRP_DEVICEDESC
:
469 lpValueName
= L
"DeviceDesc";
472 case CM_DRP_HARDWAREID
:
473 lpValueName
= L
"HardwareID";
476 case CM_DRP_COMPATIBLEIDS
:
477 lpValueName
= L
"CompatibleIDs";
481 lpValueName
= L
"Service";
485 lpValueName
= L
"Class";
488 case CM_DRP_CLASSGUID
:
489 lpValueName
= L
"ClassGUID";
493 lpValueName
= L
"Driver";
496 case CM_DRP_CONFIGFLAGS
:
497 lpValueName
= L
"ConfigFlags";
501 lpValueName
= L
"Mfg";
504 case CM_DRP_FRIENDLYNAME
:
505 lpValueName
= L
"FriendlyName";
508 case CM_DRP_LOCATION_INFORMATION
:
509 lpValueName
= L
"LocationInformation";
512 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME
:
516 case CM_DRP_CAPABILITIES
:
517 lpValueName
= L
"Capabilities";
520 case CM_DRP_UI_NUMBER
:
523 case CM_DRP_UPPERFILTERS
:
524 lpValueName
= L
"UpperFilters";
527 case CM_DRP_LOWERFILTERS
:
528 lpValueName
= L
"LowerFilters";
531 case CM_DRP_BUSTYPEGUID
:
534 case CM_DRP_LEGACYBUSTYPE
:
537 case CM_DRP_BUSNUMBER
:
540 case CM_DRP_ENUMERATOR_NAME
:
544 return CR_INVALID_PROPERTY
;
547 DPRINT1("Value name: %S\n", lpValueName
);
551 /* Retrieve information from the Registry */
556 /* Retrieve information from the Device Node */
562 memcpy(Buffer
, &Data
, sizeof(ULONG
));
563 *Length
= sizeof(ULONG
);
565 DPRINT1("PNP_GetDeviceRegProp() done (returns %lx)\n", ret
);
572 PNP_GetDeviceStatus(handle_t BindingHandle
,
573 wchar_t *DeviceInstance
,
574 unsigned long *pStatus
,
575 unsigned long *pProblem
,
578 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData
;
579 CONFIGRET ret
= CR_SUCCESS
;
582 DPRINT("PNP_GetDeviceStatus() called\n");
584 RtlInitUnicodeString(&PlugPlayData
.DeviceInstance
,
586 PlugPlayData
.Operation
= 0; /* Get status */
588 Status
= NtPlugPlayControl(PlugPlayControlDeviceStatus
,
589 (PVOID
)&PlugPlayData
,
590 sizeof(PLUGPLAY_CONTROL_STATUS_DATA
));
591 if (NT_SUCCESS(Status
))
593 *pStatus
= PlugPlayData
.DeviceStatus
;
594 *pProblem
= PlugPlayData
.DeviceProblem
;
598 ret
= CR_FAILURE
; /* FIXME */
601 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret
);
608 PNP_SetDeviceProblem(handle_t BindingHandle
,
609 wchar_t *DeviceInstance
,
610 unsigned long Problem
,
613 CONFIGRET ret
= CR_SUCCESS
;
615 DPRINT1("PNP_SetDeviceProblem() called\n");
619 DPRINT1("PNP_SetDeviceProblem() done (returns %lx)\n", ret
);
626 PnpEventThread(LPVOID lpParameter
)
628 PPLUGPLAY_EVENT_BLOCK PnpEvent
;
631 RPC_STATUS RpcStatus
;
633 PnpEventSize
= 0x1000;
634 PnpEvent
= HeapAlloc(GetProcessHeap(), 0, PnpEventSize
);
635 if (PnpEvent
== NULL
)
636 return ERROR_OUTOFMEMORY
;
640 DPRINT("Calling NtGetPlugPlayEvent()\n");
642 /* Wait for the next pnp event */
643 Status
= NtGetPlugPlayEvent(0, 0, PnpEvent
, PnpEventSize
);
645 /* Resize the buffer for the PnP event if it's too small. */
646 if (Status
== STATUS_BUFFER_TOO_SMALL
)
648 PnpEventSize
+= 0x400;
649 PnpEvent
= HeapReAlloc(GetProcessHeap(), 0, PnpEvent
, PnpEventSize
);
650 if (PnpEvent
== NULL
)
651 return ERROR_OUTOFMEMORY
;
655 if (!NT_SUCCESS(Status
))
657 DPRINT("NtPlugPlayEvent() failed (Status %lx)\n", Status
);
661 DPRINT("Received PnP Event\n");
662 if (UuidEqual(&PnpEvent
->EventGuid
, (UUID
*)&GUID_DEVICE_ARRIVAL
, &RpcStatus
))
664 DPRINT1("Device arrival event: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
668 DPRINT1("Unknown event\n");
671 /* FIXME: Process the pnp event */
673 /* Dequeue the current pnp event and signal the next one */
674 NtPlugPlayControl(PlugPlayControlUserResponse
, NULL
, 0);
677 HeapFree(GetProcessHeap(), 0, PnpEvent
);
679 return ERROR_SUCCESS
;
684 ServiceMain(DWORD argc
, LPTSTR
*argv
)
689 DPRINT("ServiceMain() called\n");
691 hThread
= CreateThread(NULL
,
698 CloseHandle(hThread
);
700 hThread
= CreateThread(NULL
,
707 CloseHandle(hThread
);
709 DPRINT("ServiceMain() done\n");
714 main(int argc
, char *argv
[])
718 DPRINT("Umpnpmgr: main() started\n");
720 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
721 L
"System\\CurrentControlSet\\Enum",
725 if (dwError
!= ERROR_SUCCESS
)
727 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError
);
731 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
732 L
"System\\CurrentControlSet\\Control\\Class",
736 if (dwError
!= ERROR_SUCCESS
)
738 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError
);
742 StartServiceCtrlDispatcher(ServiceTable
);
744 DPRINT("Umpnpmgr: main() done\n");