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