df68197e0224a2a58d1ca502e85964844dcc929b
[reactos.git] / reactos / base / services / umpnpmgr / umpnpmgr.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2005 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /*
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 */
27
28 /* INCLUDES *****************************************************************/
29 #define WIN32_NO_STATUS
30 #include <windows.h>
31 #include <cmtypes.h>
32 #include <cmfuncs.h>
33 #include <rtlfuncs.h>
34 #include <umpnpmgr/sysguid.h>
35 #include <wdmguid.h>
36 #include <cfgmgr32.h>
37
38 #include <rpc.h>
39 #include <rpcdce.h>
40
41 #include "pnp_c.h"
42
43 #define NDEBUG
44 #include <debug.h>
45
46 /* GLOBALS ******************************************************************/
47
48 static VOID CALLBACK
49 ServiceMain(DWORD argc, LPTSTR *argv);
50
51 static SERVICE_TABLE_ENTRY ServiceTable[2] =
52 {
53 {TEXT("PlugPlay"), ServiceMain},
54 {NULL, NULL}
55 };
56
57 static WCHAR szRootDeviceId[] = L"HTREE\\ROOT\\0";
58
59 static HKEY hEnumKey = NULL;
60 static HKEY hClassKey = NULL;
61
62 static HANDLE hUserToken = NULL;
63 static HANDLE hInstallEvent = NULL;
64
65
66 /* FUNCTIONS *****************************************************************/
67
68 static DWORD WINAPI
69 RpcServerThread(LPVOID lpParameter)
70 {
71 RPC_STATUS Status;
72
73 DPRINT("RpcServerThread() called\n");
74
75 Status = RpcServerUseProtseqEpW(L"ncacn_np",
76 20,
77 L"\\pipe\\umpnpmgr",
78 NULL); // Security descriptor
79 if (Status != RPC_S_OK)
80 {
81 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
82 return 0;
83 }
84
85 Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec,
86 NULL,
87 NULL);
88 if (Status != RPC_S_OK)
89 {
90 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
91 return 0;
92 }
93
94 Status = RpcServerListen(1,
95 20,
96 FALSE);
97 if (Status != RPC_S_OK)
98 {
99 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
100 return 0;
101 }
102
103 DPRINT("RpcServerThread() done\n");
104
105 return 0;
106 }
107
108
109 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
110 {
111 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
112 }
113
114
115 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
116 {
117 HeapFree(GetProcessHeap(), 0, ptr);
118 }
119
120
121 static CONFIGRET WINAPI
122 NtStatusToCrError(NTSTATUS Status)
123 {
124 switch (Status)
125 {
126 case STATUS_NO_SUCH_DEVICE:
127 return CR_NO_SUCH_DEVINST;
128
129 default:
130 /* FIXME: add more mappings */
131 DPRINT1("Unable to map status 0x%08lx\n", Status);
132 return CR_FAILURE;
133 }
134 }
135
136
137 /* Function 2 */
138 CONFIGRET
139 PNP_GetVersion(handle_t BindingHandle,
140 unsigned short *Version)
141 {
142 *Version = 0x0400;
143 return CR_SUCCESS;
144 }
145
146
147 /* Function 3 */
148 CONFIGRET
149 PNP_GetGlobalState(handle_t BindingHandle,
150 unsigned long *State,
151 unsigned long Flags)
152 {
153 *State = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE;
154 return CR_SUCCESS;
155 }
156
157
158 /* Function 4 */
159 CONFIGRET
160 PNP_InitDetection(handle_t BindingHandle)
161 {
162 DPRINT("PNP_InitDetection() called\n");
163 return CR_SUCCESS;
164 }
165
166
167 /* Function 5 */
168 CONFIGRET
169 PNP_ReportLogOn(handle_t BindingHandle,
170 unsigned long Admin,
171 unsigned long ProcessId)
172 {
173 HANDLE hProcess;
174
175 DPRINT1("PNP_ReportLogOn(%lu, %lu) called\n", Admin, ProcessId);
176
177 /* Get the users token */
178 hProcess = OpenProcess(PROCESS_ALL_ACCESS,
179 TRUE,
180 ProcessId);
181 if (hProcess != NULL)
182 {
183 if (hUserToken != NULL)
184 {
185 CloseHandle(hUserToken);
186 hUserToken = NULL;
187 }
188
189 OpenProcessToken(hProcess,
190 TOKEN_ALL_ACCESS,
191 &hUserToken);
192 CloseHandle(hProcess);
193 }
194
195 /* Trigger the installer thread */
196 if (hInstallEvent != NULL)
197 SetEvent(hInstallEvent);
198
199 return CR_SUCCESS;
200 }
201
202
203 /* Function 6 */
204 CONFIGRET
205 PNP_ValidateDeviceInstance(handle_t BindingHandle,
206 wchar_t *DeviceInstance,
207 unsigned long Flags)
208 {
209 CONFIGRET ret = CR_SUCCESS;
210 HKEY hEnumKey = NULL;
211 HKEY hDeviceKey = NULL;
212
213 DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
214 DeviceInstance, Flags);
215
216 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
217 L"System\\CurrentControlSet\\Enum",
218 0,
219 KEY_ALL_ACCESS,
220 &hEnumKey))
221 {
222 DPRINT("Could not open the Enum Key!\n");
223 ret = CR_FAILURE;
224 goto Done;
225 }
226
227 if (RegOpenKeyExW(hEnumKey,
228 DeviceInstance,
229 0,
230 KEY_READ,
231 &hDeviceKey))
232 {
233 DPRINT("Could not open the Device Key!\n");
234 ret = CR_NO_SUCH_DEVNODE;
235 goto Done;
236 }
237
238 /* FIXME: add more tests */
239
240 Done:
241 if (hDeviceKey != NULL)
242 RegCloseKey(hDeviceKey);
243
244 if (hEnumKey != NULL)
245 RegCloseKey(hEnumKey);
246
247 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret);
248
249 return ret;
250 }
251
252
253 /* Function 7 */
254 CONFIGRET
255 PNP_GetRootDeviceInstance(handle_t BindingHandle,
256 wchar_t *DeviceInstance,
257 unsigned long Length)
258 {
259 CONFIGRET ret = CR_SUCCESS;
260
261 DPRINT("PNP_GetRootDeviceInstance() called\n");
262
263 if (Length < lstrlenW(szRootDeviceId) + 1)
264 {
265 ret = CR_BUFFER_SMALL;
266 goto Done;
267 }
268
269 lstrcpyW(DeviceInstance,
270 szRootDeviceId);
271
272 Done:
273 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret);
274
275 return ret;
276 }
277
278
279 /* Function 8 */
280 CONFIGRET
281 PNP_GetRelatedDeviceInstance(handle_t BindingHandle,
282 unsigned long Relationship,
283 wchar_t *DeviceId,
284 wchar_t *RelatedDeviceId,
285 unsigned long Length,
286 unsigned long Flags)
287 {
288 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData;
289 CONFIGRET ret = CR_SUCCESS;
290 NTSTATUS Status;
291
292 DPRINT("PNP_GetRelatedDeviceInstance() called\n");
293 DPRINT(" Relationship %ld\n", Relationship);
294 DPRINT(" DeviceId %S\n", DeviceId);
295
296 RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance,
297 DeviceId);
298
299 PlugPlayData.Relation = Relationship;
300
301 PlugPlayData.RelatedDeviceInstance.Length = 0;
302 PlugPlayData.RelatedDeviceInstance.MaximumLength = Length;
303 PlugPlayData.RelatedDeviceInstance.Buffer = RelatedDeviceId;
304
305 Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice,
306 (PVOID)&PlugPlayData,
307 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA));
308 if (!NT_SUCCESS(Status))
309 {
310 ret = NtStatusToCrError(Status);
311 }
312
313 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret);
314 if (ret == CR_SUCCESS)
315 {
316 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance);
317 }
318
319 return ret;
320 }
321
322
323 /* Function 9 */
324 CONFIGRET
325 PNP_EnumerateSubKeys(handle_t BindingHandle,
326 unsigned long Branch,
327 unsigned long Index,
328 wchar_t *Buffer,
329 unsigned long Length,
330 unsigned long *RequiredLength,
331 DWORD Flags)
332 {
333 CONFIGRET ret = CR_SUCCESS;
334 HKEY hKey;
335 DWORD dwError;
336
337 DPRINT("PNP_EnumerateSubKeys() called\n");
338
339 switch (Branch)
340 {
341 case PNP_BRANCH_ENUM:
342 hKey = hEnumKey;
343 break;
344
345 case PNP_BRANCH_CLASS:
346 hKey = hClassKey;
347 break;
348
349 default:
350 return CR_FAILURE;
351 }
352
353 *RequiredLength = Length;
354 dwError = RegEnumKeyExW(hKey,
355 Index,
356 Buffer,
357 RequiredLength,
358 NULL,
359 NULL,
360 NULL,
361 NULL);
362 if (dwError != ERROR_SUCCESS)
363 {
364 ret = (dwError == ERROR_NO_MORE_ITEMS) ? CR_NO_SUCH_VALUE : CR_FAILURE;
365 }
366 else
367 {
368 (*RequiredLength)++;
369 }
370
371 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret);
372
373 return ret;
374 }
375
376
377 /* Function 11 */
378 CONFIGRET
379 PNP_GetDeviceListSize(handle_t BindingHandle,
380 wchar_t *Filter,
381 unsigned long *Length,
382 DWORD Flags)
383 {
384 DPRINT("PNP_GetDeviceListSize() called\n");
385
386 /* FIXME */
387 *Length = 2;
388
389 return CR_SUCCESS;
390 }
391
392
393 /* Function 12 */
394 CONFIGRET
395 PNP_GetDepth(handle_t BindingHandle,
396 wchar_t *DeviceInstance,
397 unsigned long *Depth,
398 DWORD Flags)
399 {
400 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData;
401 CONFIGRET ret = CR_SUCCESS;
402 NTSTATUS Status;
403
404 DPRINT("PNP_GetDepth() called\n");
405
406 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
407 DeviceInstance);
408
409 Status = NtPlugPlayControl(PlugPlayControlGetDeviceDepth,
410 (PVOID)&PlugPlayData,
411 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA));
412 if (NT_SUCCESS(Status))
413 {
414 *Depth = PlugPlayData.Depth;
415 }
416 else
417 {
418 ret = NtStatusToCrError(Status);
419 }
420
421 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret);
422
423 return ret;
424 }
425
426
427 /* Function 13 */
428 CONFIGRET
429 PNP_GetDeviceRegProp(handle_t BindingHandle,
430 wchar_t *DeviceInstance,
431 unsigned long Property,
432 unsigned long *DataType,
433 char *Buffer,
434 unsigned long *TransferLen,
435 unsigned long *Length,
436 DWORD Flags)
437 {
438 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData;
439 CONFIGRET ret = CR_SUCCESS;
440 LPWSTR lpValueName = NULL;
441 HKEY hKey = 0;
442 NTSTATUS Status;
443
444 DPRINT("PNP_GetDeviceRegProp() called\n");
445
446 switch (Property)
447 {
448 case CM_DRP_DEVICEDESC:
449 lpValueName = L"DeviceDesc";
450 break;
451
452 case CM_DRP_HARDWAREID:
453 lpValueName = L"HardwareID";
454 break;
455
456 case CM_DRP_COMPATIBLEIDS:
457 lpValueName = L"CompatibleIDs";
458 break;
459
460 case CM_DRP_SERVICE:
461 lpValueName = L"Service";
462 break;
463
464 case CM_DRP_CLASS:
465 lpValueName = L"Class";
466 break;
467
468 case CM_DRP_CLASSGUID:
469 lpValueName = L"ClassGUID";
470 break;
471
472 case CM_DRP_DRIVER:
473 lpValueName = L"Driver";
474 break;
475
476 case CM_DRP_CONFIGFLAGS:
477 lpValueName = L"ConfigFlags";
478 break;
479
480 case CM_DRP_MFG:
481 lpValueName = L"Mfg";
482 break;
483
484 case CM_DRP_FRIENDLYNAME:
485 lpValueName = L"FriendlyName";
486 break;
487
488 case CM_DRP_LOCATION_INFORMATION:
489 lpValueName = L"LocationInformation";
490 break;
491
492 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
493 lpValueName = NULL;
494 break;
495
496 case CM_DRP_CAPABILITIES:
497 lpValueName = L"Capabilities";
498 break;
499
500 case CM_DRP_UI_NUMBER:
501 lpValueName = NULL;
502 break;
503
504 case CM_DRP_UPPERFILTERS:
505 lpValueName = L"UpperFilters";
506 break;
507
508 case CM_DRP_LOWERFILTERS:
509 lpValueName = L"LowerFilters";
510 break;
511
512 case CM_DRP_BUSTYPEGUID:
513 lpValueName = NULL;
514 break;
515
516 case CM_DRP_LEGACYBUSTYPE:
517 lpValueName = NULL;
518 break;
519
520 case CM_DRP_BUSNUMBER:
521 lpValueName = NULL;
522 break;
523
524 case CM_DRP_ENUMERATOR_NAME:
525 lpValueName = NULL;
526 break;
527
528 default:
529 return CR_INVALID_PROPERTY;
530 }
531
532 DPRINT("Value name: %S\n", lpValueName);
533
534 if (lpValueName)
535 {
536 /* Retrieve information from the Registry */
537 if (RegOpenKeyExW(hEnumKey,
538 DeviceInstance,
539 0,
540 KEY_ALL_ACCESS,
541 &hKey))
542 return CR_INVALID_DEVNODE;
543
544 if (RegQueryValueExW(hKey,
545 lpValueName,
546 NULL,
547 DataType,
548 (LPBYTE)Buffer,
549 Length))
550 ret = CR_REGISTRY_ERROR;
551
552 /* FIXME: Check buffer size */
553
554 RegCloseKey(hKey);
555 }
556 else
557 {
558 /* Retrieve information from the Device Node */
559 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
560 DeviceInstance);
561 PlugPlayData.Buffer = Buffer;
562 PlugPlayData.BufferSize = *TransferLen;
563
564 switch (Property)
565 {
566 #if 0
567 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
568 PlugPlayData.Property = DevicePropertyPhysicalDeviceObjectName;
569 break;
570
571 case CM_DRP_UI_NUMBER:
572 PlugPlayData.Property = DevicePropertyUINumber;
573 break;
574
575 case CM_DRP_BUSTYPEGUID:
576 PlugPlayData.Property = DevicePropertyBusTypeGuid;
577 break;
578
579 case CM_DRP_LEGACYBUSTYPE:
580 PlugPlayData.Property = DevicePropertyLegacyBusType;
581 break;
582
583 case CM_DRP_BUSNUMBER:
584 PlugPlayData.Property = DevicePropertyBusNumber;
585 break;
586
587 case CM_DRP_ENUMERATOR_NAME:
588 PlugPlayData.Property = DevicePropertyEnumeratorName;
589 break;
590 #endif
591
592 default:
593 return CR_INVALID_PROPERTY;
594 }
595
596 Status = NtPlugPlayControl(PlugPlayControlProperty,
597 (PVOID)&PlugPlayData,
598 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA));
599 if (NT_SUCCESS(Status))
600 {
601 *Length = PlugPlayData.BufferSize;
602 }
603 else
604 {
605 ret = NtStatusToCrError(Status);
606 }
607 }
608
609 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret);
610
611 return ret;
612 }
613
614
615 /* Function 14 */
616 CONFIGRET
617 PNP_SetDeviceRegProp(handle_t BindingHandle,
618 wchar_t *DeviceId,
619 unsigned long Property,
620 unsigned long DataType,
621 char *Buffer,
622 unsigned long Length,
623 unsigned long Flags)
624 {
625 CONFIGRET ret = CR_SUCCESS;
626 LPWSTR lpValueName = NULL;
627 HKEY hKey = 0;
628
629 DPRINT("PNP_SetDeviceRegProp() called\n");
630
631 DPRINT("DeviceId: %S\n", DeviceId);
632 DPRINT("Property: %lu\n", Property);
633 DPRINT("DataType: %lu\n", DataType);
634 DPRINT("Length: %lu\n", Length);
635
636 switch (Property)
637 {
638 case CM_DRP_DEVICEDESC:
639 lpValueName = L"DeviceDesc";
640 break;
641
642 case CM_DRP_HARDWAREID:
643 lpValueName = L"HardwareID";
644 break;
645
646 case CM_DRP_COMPATIBLEIDS:
647 lpValueName = L"CompatibleIDs";
648 break;
649
650 case CM_DRP_SERVICE:
651 lpValueName = L"Service";
652 break;
653
654 case CM_DRP_CLASS:
655 lpValueName = L"Class";
656 break;
657
658 case CM_DRP_CLASSGUID:
659 lpValueName = L"ClassGUID";
660 break;
661
662 case CM_DRP_DRIVER:
663 lpValueName = L"Driver";
664 break;
665
666 case CM_DRP_CONFIGFLAGS:
667 lpValueName = L"ConfigFlags";
668 break;
669
670 case CM_DRP_MFG:
671 lpValueName = L"Mfg";
672 break;
673
674 case CM_DRP_FRIENDLYNAME:
675 lpValueName = L"FriendlyName";
676 break;
677
678 case CM_DRP_LOCATION_INFORMATION:
679 lpValueName = L"LocationInformation";
680 break;
681
682 case CM_DRP_UPPERFILTERS:
683 lpValueName = L"UpperFilters";
684 break;
685
686 case CM_DRP_LOWERFILTERS:
687 lpValueName = L"LowerFilters";
688 break;
689
690 default:
691 return CR_INVALID_PROPERTY;
692 }
693
694 DPRINT("Value name: %S\n", lpValueName);
695
696 if (RegOpenKeyExW(hEnumKey,
697 DeviceId,
698 0,
699 KEY_ALL_ACCESS,
700 &hKey))
701 return CR_INVALID_DEVNODE;
702
703 if (Length == 0)
704 {
705 if (RegDeleteValueW(hKey,
706 lpValueName))
707 ret = CR_REGISTRY_ERROR;
708 }
709 else
710 {
711 if (RegSetValueExW(hKey,
712 lpValueName,
713 0,
714 DataType,
715 (const BYTE*)Buffer,
716 Length))
717 ret = CR_REGISTRY_ERROR;
718 }
719
720 RegCloseKey(hKey);
721
722 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret);
723
724 return ret;
725 }
726
727
728 /* Function 15 */
729 CONFIGRET
730 PNP_GetClassInstance(handle_t BindingHandle,
731 wchar_t *DeviceId, /* in */
732 wchar_t *Buffer, /* out */
733 unsigned long Length)
734 {
735 CONFIGRET ret = CR_SUCCESS;
736
737 DPRINT("PNP_Get_Class_Instance() called\n");
738
739 DPRINT("PNP_Get_Class_Instance() done (returns %lx)\n", ret);
740
741 return ret;
742 }
743
744
745 /* Function 16 */
746 CONFIGRET
747 PNP_CreateKey(handle_t BindingHandle,
748 wchar_t *SubKey,
749 unsigned long samDesired,
750 unsigned long Flags)
751 {
752 CONFIGRET ret = CR_SUCCESS;
753
754 DPRINT("PNP_CreateKey() called\n");
755
756 DPRINT("PNP_CreateKey() done (returns %lx)\n", ret);
757
758 return ret;
759 }
760
761
762 /* Function 17 */
763 CONFIGRET
764 PNP_DeleteRegistryKey(handle_t BindingHandle,
765 wchar_t *DeviceId,
766 wchar_t *ParentKey,
767 wchar_t *ChildKey,
768 unsigned long Flags)
769 {
770 CONFIGRET ret = CR_SUCCESS;
771
772 DPRINT("PNP_DeleteRegistryKey() called\n");
773
774 DPRINT("PNP_DeleteRegistryKey() done (returns %lx)\n", ret);
775
776 return ret;
777 }
778
779
780 /* Function 18 */
781 #if 0
782 CONFIGRET
783 PNP_GetClassCount(handle_t BindingHandle,
784 unsigned long *ClassCount,
785 unsigned long Flags)
786 {
787 HANDLE hKey = NULL;
788 DWORD dwError;
789
790 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
791 pszRegPathClass,
792 0,
793 KEY_QUERY_VALUE,
794 &hKey);
795 if (dwError != ERROR_SUCCESS)
796 return CR_INVALID_DATA;
797
798 dwError = RegQueryInfoKeyW(hKey,
799 NULL,
800 NULL,
801 NULL,
802 &ClassCount,
803 NULL,
804 NULL,
805 NULL,
806 NULL,
807 NULL,
808 NULL,
809 NULL);
810 RegCloseKey(hKey);
811 if (dwError != ERROR_SUCCESS)
812 return CR_INVALID_DATA;
813
814 return CR_SUCCESS;
815 }
816 #endif
817
818
819 /* Function 19 */
820 CONFIGRET
821 PNP_GetClassName(handle_t BindingHandle,
822 wchar_t *ClassGuid,
823 wchar_t *Buffer,
824 unsigned long *Length,
825 unsigned long Flags)
826 {
827 WCHAR szKeyName[MAX_PATH];
828 CONFIGRET ret = CR_SUCCESS;
829 HKEY hKey = NULL;
830 ULONG ulSize;
831
832 DPRINT("PNP_GetClassName() called\n");
833
834 lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class");
835 lstrcatW(szKeyName, L"\\");
836 lstrcatW(szKeyName, ClassGuid);
837
838 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
839 szKeyName,
840 0,
841 KEY_QUERY_VALUE,
842 &hKey))
843 return CR_REGISTRY_ERROR;
844
845 ulSize = *Length * sizeof(WCHAR);
846 if (RegQueryValueExW(hKey,
847 L"Class",
848 NULL,
849 NULL,
850 (LPBYTE)Buffer,
851 &ulSize))
852 {
853 *Length = 0;
854 ret = CR_REGISTRY_ERROR;
855 }
856 else
857 {
858 *Length = ulSize / sizeof(WCHAR);
859 }
860
861 RegCloseKey(hKey);
862
863 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret);
864
865 return ret;
866 }
867
868
869 /* Function 20 */
870 CONFIGRET
871 PNP_DeleteClassKey(handle_t BindingHandle,
872 wchar_t *ClassGuid,
873 unsigned long Flags)
874 {
875 CONFIGRET ret = CR_SUCCESS;
876
877 DPRINT("PNP_GetClassName(%S, %lx) called\n", ClassGuid, Flags);
878
879 if (Flags & CM_DELETE_CLASS_SUBKEYS)
880 {
881 if (RegDeleteTreeW(hClassKey, ClassGuid) != ERROR_SUCCESS)
882 ret = CR_REGISTRY_ERROR;
883 }
884 else
885 {
886 if (RegDeleteKeyW(hClassKey, ClassGuid) != ERROR_SUCCESS)
887 ret = CR_REGISTRY_ERROR;
888 }
889
890 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret);
891
892 return ret;
893 }
894
895
896 /* Function 28 */
897 CONFIGRET
898 PNP_CreateDevInst(handle_t BindingHandle,
899 wchar_t *DeviceId, /* [in, out, string, size_is(Length)] */
900 wchar_t *ParentDeviceId, /* [in, string] */
901 unsigned long Length, /* [in] */
902 unsigned long Flags) /* [in] */
903 {
904 CONFIGRET ret = CR_CALL_NOT_IMPLEMENTED;
905
906 DPRINT1("PNP_CreateDevInst() called\n");
907
908 DPRINT1("PNP_CreateDevInst() done (returns %lx)\n", ret);
909
910 return ret;
911 }
912
913
914 /* Function 29 */
915 CONFIGRET
916 PNP_DeviceInstanceAction(handle_t BindingHandle,
917 unsigned long MajorAction,
918 unsigned long MinorAction,
919 wchar_t *DeviceInstance1,
920 wchar_t *DeviceInstance2)
921 {
922 CONFIGRET ret = CR_SUCCESS;
923
924 DPRINT("PNP_DeviceInstanceAction() called\n");
925
926 switch (MajorAction)
927 {
928 case 2:
929 DPRINT("Move device instance\n");
930 /* FIXME */
931 ret = CR_CALL_NOT_IMPLEMENTED;
932 break;
933
934 case 3:
935 DPRINT("Setup device instance\n");
936 /* FIXME */
937 ret = CR_CALL_NOT_IMPLEMENTED;
938 break;
939
940 case 4:
941 DPRINT("Enable device instance\n");
942 /* FIXME */
943 ret = CR_CALL_NOT_IMPLEMENTED;
944 break;
945
946 case 5:
947 DPRINT("Disable device instance\n");
948 /* FIXME */
949 ret = CR_CALL_NOT_IMPLEMENTED;
950 break;
951
952 case 7:
953 DPRINT("Reenumerate device instance\n");
954 /* FIXME */
955 ret = CR_CALL_NOT_IMPLEMENTED;
956 break;
957
958 default:
959 DPRINT1("Unknown function %lu\n", MajorAction);
960 ret = CR_CALL_NOT_IMPLEMENTED;
961 }
962
963 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
964
965 return ret;
966 }
967
968
969 /* Function 30 */
970 CONFIGRET
971 PNP_GetDeviceStatus(handle_t BindingHandle,
972 wchar_t *DeviceInstance,
973 unsigned long *pStatus,
974 unsigned long *pProblem,
975 DWORD Flags)
976 {
977 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
978 CONFIGRET ret = CR_SUCCESS;
979 NTSTATUS Status;
980
981 DPRINT("PNP_GetDeviceStatus() called\n");
982
983 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
984 DeviceInstance);
985 PlugPlayData.Operation = 0; /* Get status */
986
987 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
988 (PVOID)&PlugPlayData,
989 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
990 if (NT_SUCCESS(Status))
991 {
992 *pStatus = PlugPlayData.DeviceStatus;
993 *pProblem = PlugPlayData.DeviceProblem;
994 }
995 else
996 {
997 ret = NtStatusToCrError(Status);
998 }
999
1000 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret);
1001
1002 return ret;
1003 }
1004
1005
1006 /* Function 31 */
1007 CONFIGRET
1008 PNP_SetDeviceProblem(handle_t BindingHandle,
1009 wchar_t *DeviceInstance,
1010 unsigned long Problem,
1011 DWORD Flags)
1012 {
1013 CONFIGRET ret = CR_SUCCESS;
1014
1015 DPRINT1("PNP_SetDeviceProblem() called\n");
1016
1017 /* FIXME */
1018
1019 DPRINT1("PNP_SetDeviceProblem() done (returns %lx)\n", ret);
1020
1021 return ret;
1022 }
1023
1024
1025 /* Function 33 */
1026 CONFIGRET
1027 PNP_UninstallDevInst(handle_t BindingHandle,
1028 wchar_t *DeviceInstance,
1029 DWORD Flags)
1030 {
1031 CONFIGRET ret = CR_SUCCESS;
1032
1033 DPRINT1("PNP_UninstallDevInst() called\n");
1034
1035 /* FIXME */
1036
1037 DPRINT1("PNP_UninstallDevInst() done (returns %lx)\n", ret);
1038
1039 return ret;
1040 }
1041
1042
1043 /* Function 38 */
1044 CONFIGRET
1045 PNP_IsDockStationPresent(handle_t BindingHandle,
1046 unsigned long *Present)
1047 {
1048 HKEY hKey;
1049 DWORD dwType;
1050 DWORD dwValue;
1051 DWORD dwSize;
1052 CONFIGRET ret = CR_SUCCESS;
1053
1054 DPRINT1("PNP_IsDockStationPresent() called\n");
1055
1056 *Present = FALSE;
1057
1058 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
1059 L"CurrentDockInfo",
1060 0,
1061 KEY_READ,
1062 &hKey) != ERROR_SUCCESS)
1063 return CR_REGISTRY_ERROR;
1064
1065 dwSize = sizeof(DWORD);
1066 if (RegQueryValueExW(hKey,
1067 L"DockingState",
1068 NULL,
1069 &dwType,
1070 (LPBYTE)&dwValue,
1071 &dwSize) != ERROR_SUCCESS)
1072 ret = CR_REGISTRY_ERROR;
1073
1074 RegCloseKey(hKey);
1075
1076 if (ret == CR_SUCCESS)
1077 {
1078 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
1079 {
1080 ret = CR_REGISTRY_ERROR;
1081 }
1082 else if (dwValue != 0)
1083 {
1084 *Present = TRUE;
1085 }
1086 }
1087
1088 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
1089
1090 return ret;
1091 }
1092
1093
1094 /* Function 39 */
1095 CONFIGRET
1096 PNP_RequestEjectPC(handle_t BindingHandle)
1097 {
1098 CONFIGRET ret = CR_SUCCESS;
1099
1100 DPRINT1("PNP_RequestEjectPC() called\n");
1101
1102 ret = CR_FAILURE; /* FIXME */
1103
1104 DPRINT1("PNP_RequestEjectPC() done (returns %lx)\n", ret);
1105
1106 return ret;
1107 }
1108
1109
1110 /* Function 58 */
1111 CONFIGRET
1112 PNP_RunDetection(handle_t BindingHandle,
1113 unsigned long Flags)
1114 {
1115 DPRINT("PNP_RunDetection() called\n");
1116 return CR_CALL_NOT_IMPLEMENTED;
1117 }
1118
1119
1120 typedef BOOL (WINAPI *PDEV_INSTALL_W)(HWND, HINSTANCE, LPCWSTR, INT);
1121
1122 static BOOL
1123 InstallDevice(PCWSTR DeviceInstance, BOOL SetupIsActive)
1124 {
1125 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1126 HMODULE hNewDev = NULL;
1127 PDEV_INSTALL_W DevInstallW;
1128 NTSTATUS Status;
1129 BOOL DeviceInstalled = FALSE;
1130
1131 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1132 DeviceInstance);
1133 PlugPlayData.Operation = 0; /* Get status */
1134
1135 /* Get device status */
1136 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1137 (PVOID)&PlugPlayData,
1138 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1139 if (!NT_SUCCESS(Status))
1140 return FALSE;
1141
1142 if (PlugPlayData.DeviceStatus & DNF_STARTED || PlugPlayData.DeviceStatus & DNF_START_FAILED)
1143 /* Device is already started, or disabled due to some problem. Don't install it */
1144 return TRUE;
1145
1146 /* Install device */
1147 SetEnvironmentVariable(L"USERPROFILE", L"."); /* FIXME: why is it needed? */
1148
1149 hNewDev = LoadLibraryW(L"newdev.dll");
1150 if (!hNewDev)
1151 goto cleanup;
1152
1153 DevInstallW = (PDEV_INSTALL_W)GetProcAddress(hNewDev, (LPCSTR)"DevInstallW");
1154 if (!DevInstallW)
1155 goto cleanup;
1156
1157 if (!DevInstallW(NULL, NULL, DeviceInstance, SetupIsActive ? SW_HIDE : SW_SHOWNOACTIVATE))
1158 goto cleanup;
1159
1160 DeviceInstalled = TRUE;
1161
1162 cleanup:
1163 if (hNewDev != NULL)
1164 FreeLibrary(hNewDev);
1165
1166 return DeviceInstalled;
1167 }
1168
1169
1170 static BOOL
1171 SetupIsActive(VOID)
1172 {
1173 HKEY hKey = INVALID_HANDLE_VALUE;
1174 DWORD regType, active, size;
1175 LONG rc;
1176 BOOL ret = FALSE;
1177
1178 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
1179 if (rc != ERROR_SUCCESS)
1180 goto cleanup;
1181
1182 size = sizeof(DWORD);
1183 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
1184 if (rc != ERROR_SUCCESS)
1185 goto cleanup;
1186 if (regType != REG_DWORD || size != sizeof(DWORD))
1187 goto cleanup;
1188
1189 ret = (active != 0);
1190
1191 cleanup:
1192 if (hKey != INVALID_HANDLE_VALUE)
1193 RegCloseKey(hKey);
1194
1195 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
1196
1197 return ret;
1198 }
1199
1200
1201 static DWORD WINAPI
1202 PnpEventThread(LPVOID lpParameter)
1203 {
1204 PPLUGPLAY_EVENT_BLOCK PnpEvent;
1205 ULONG PnpEventSize;
1206 NTSTATUS Status;
1207 RPC_STATUS RpcStatus;
1208 BOOL setupActive;
1209
1210 PnpEventSize = 0x1000;
1211 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
1212 if (PnpEvent == NULL)
1213 return ERROR_OUTOFMEMORY;
1214
1215 setupActive = SetupIsActive();
1216
1217 for (;;)
1218 {
1219 DPRINT("Calling NtGetPlugPlayEvent()\n");
1220
1221 /* Wait for the next pnp event */
1222 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
1223
1224 /* Resize the buffer for the PnP event if it's too small. */
1225 if (Status == STATUS_BUFFER_TOO_SMALL)
1226 {
1227 PnpEventSize += 0x400;
1228 PnpEvent = HeapReAlloc(GetProcessHeap(), 0, PnpEvent, PnpEventSize);
1229 if (PnpEvent == NULL)
1230 return ERROR_OUTOFMEMORY;
1231 continue;
1232 }
1233
1234 if (!NT_SUCCESS(Status))
1235 {
1236 DPRINT("NtPlugPlayEvent() failed (Status %lx)\n", Status);
1237 break;
1238 }
1239
1240 DPRINT("Received PnP Event\n");
1241 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
1242 {
1243 DPRINT("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds);
1244 InstallDevice(PnpEvent->TargetDevice.DeviceIds, setupActive);
1245 }
1246 else
1247 {
1248 DPRINT1("Unknown event\n");
1249 }
1250
1251 /* FIXME: Process the pnp event */
1252
1253 /* Dequeue the current pnp event and signal the next one */
1254 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
1255 }
1256
1257 HeapFree(GetProcessHeap(), 0, PnpEvent);
1258
1259 return ERROR_SUCCESS;
1260 }
1261
1262
1263 static VOID CALLBACK
1264 ServiceMain(DWORD argc, LPTSTR *argv)
1265 {
1266 HANDLE hThread;
1267 DWORD dwThreadId;
1268
1269 DPRINT("ServiceMain() called\n");
1270
1271 hThread = CreateThread(NULL,
1272 0,
1273 PnpEventThread,
1274 NULL,
1275 0,
1276 &dwThreadId);
1277 if (hThread != NULL)
1278 CloseHandle(hThread);
1279
1280 hThread = CreateThread(NULL,
1281 0,
1282 RpcServerThread,
1283 NULL,
1284 0,
1285 &dwThreadId);
1286 if (hThread != NULL)
1287 CloseHandle(hThread);
1288
1289 DPRINT("ServiceMain() done\n");
1290 }
1291
1292
1293 int
1294 main(int argc, char *argv[])
1295 {
1296 DWORD dwError;
1297
1298 DPRINT("Umpnpmgr: main() started\n");
1299
1300 hInstallEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1301 if (hInstallEvent == NULL)
1302 {
1303 dwError = GetLastError();
1304 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
1305 return dwError;
1306 }
1307
1308 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1309 L"System\\CurrentControlSet\\Enum",
1310 0,
1311 KEY_ALL_ACCESS,
1312 &hEnumKey);
1313 if (dwError != ERROR_SUCCESS)
1314 {
1315 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
1316 return dwError;
1317 }
1318
1319 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1320 L"System\\CurrentControlSet\\Control\\Class",
1321 0,
1322 KEY_ALL_ACCESS,
1323 &hClassKey);
1324 if (dwError != ERROR_SUCCESS)
1325 {
1326 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
1327 return dwError;
1328 }
1329
1330 StartServiceCtrlDispatcher(ServiceTable);
1331
1332 DPRINT("Umpnpmgr: main() done\n");
1333
1334 ExitThread(0);
1335
1336 return 0;
1337 }
1338
1339 /* EOF */