Fix umpnpmgr build
[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 <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 29 */
897 CONFIGRET
898 PNP_DeviceInstanceAction(handle_t BindingHandle,
899 unsigned long MajorAction,
900 unsigned long MinorAction,
901 wchar_t *DeviceInstance1,
902 wchar_t *DeviceInstance2)
903 {
904 CONFIGRET ret = CR_SUCCESS;
905
906 DPRINT("PNP_DeviceInstanceAction() called\n");
907
908 switch (MajorAction)
909 {
910 case 2:
911 DPRINT("Move device instance\n");
912 /* FIXME */
913 ret = CR_CALL_NOT_IMPLEMENTED;
914 break;
915
916 case 3:
917 DPRINT("Setup device instance\n");
918 /* FIXME */
919 ret = CR_CALL_NOT_IMPLEMENTED;
920 break;
921
922 case 4:
923 DPRINT("Enable device instance\n");
924 /* FIXME */
925 ret = CR_CALL_NOT_IMPLEMENTED;
926 break;
927
928 case 5:
929 DPRINT("Disable device instance\n");
930 /* FIXME */
931 ret = CR_CALL_NOT_IMPLEMENTED;
932 break;
933
934 case 7:
935 DPRINT("Reenumerate device instance\n");
936 /* FIXME */
937 ret = CR_CALL_NOT_IMPLEMENTED;
938 break;
939
940 default:
941 DPRINT1("Unknown function %lu\n", MajorAction);
942 ret = CR_CALL_NOT_IMPLEMENTED;
943 }
944
945 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
946
947 return ret;
948 }
949
950
951 /* Function 30 */
952 CONFIGRET
953 PNP_GetDeviceStatus(handle_t BindingHandle,
954 wchar_t *DeviceInstance,
955 unsigned long *pStatus,
956 unsigned long *pProblem,
957 DWORD Flags)
958 {
959 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
960 CONFIGRET ret = CR_SUCCESS;
961 NTSTATUS Status;
962
963 DPRINT("PNP_GetDeviceStatus() called\n");
964
965 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
966 DeviceInstance);
967 PlugPlayData.Operation = 0; /* Get status */
968
969 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
970 (PVOID)&PlugPlayData,
971 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
972 if (NT_SUCCESS(Status))
973 {
974 *pStatus = PlugPlayData.DeviceStatus;
975 *pProblem = PlugPlayData.DeviceProblem;
976 }
977 else
978 {
979 ret = NtStatusToCrError(Status);
980 }
981
982 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret);
983
984 return ret;
985 }
986
987
988 /* Function 31 */
989 CONFIGRET
990 PNP_SetDeviceProblem(handle_t BindingHandle,
991 wchar_t *DeviceInstance,
992 unsigned long Problem,
993 DWORD Flags)
994 {
995 CONFIGRET ret = CR_SUCCESS;
996
997 DPRINT1("PNP_SetDeviceProblem() called\n");
998
999 /* FIXME */
1000
1001 DPRINT1("PNP_SetDeviceProblem() done (returns %lx)\n", ret);
1002
1003 return ret;
1004 }
1005
1006
1007 /* Function 33 */
1008 CONFIGRET
1009 PNP_UninstallDevInst(handle_t BindingHandle,
1010 wchar_t *DeviceInstance,
1011 DWORD Flags)
1012 {
1013 CONFIGRET ret = CR_SUCCESS;
1014
1015 DPRINT1("PNP_UninstallDevInst() called\n");
1016
1017 /* FIXME */
1018
1019 DPRINT1("PNP_UninstallDevInst() done (returns %lx)\n", ret);
1020
1021 return ret;
1022 }
1023
1024
1025 /* Function 38 */
1026 CONFIGRET
1027 PNP_IsDockStationPresent(handle_t BindingHandle,
1028 unsigned long *Present)
1029 {
1030 HKEY hKey;
1031 DWORD dwType;
1032 DWORD dwValue;
1033 DWORD dwSize;
1034 CONFIGRET ret = CR_SUCCESS;
1035
1036 DPRINT1("PNP_IsDockStationPresent() called\n");
1037
1038 *Present = FALSE;
1039
1040 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
1041 L"CurrentDockInfo",
1042 0,
1043 KEY_READ,
1044 &hKey) != ERROR_SUCCESS)
1045 return CR_REGISTRY_ERROR;
1046
1047 dwSize = sizeof(DWORD);
1048 if (RegQueryValueExW(hKey,
1049 L"DockingState",
1050 NULL,
1051 &dwType,
1052 (LPBYTE)&dwValue,
1053 &dwSize) != ERROR_SUCCESS)
1054 ret = CR_REGISTRY_ERROR;
1055
1056 RegCloseKey(hKey);
1057
1058 if (ret == CR_SUCCESS)
1059 {
1060 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
1061 {
1062 ret = CR_REGISTRY_ERROR;
1063 }
1064 else if (dwValue != 0)
1065 {
1066 *Present = TRUE;
1067 }
1068 }
1069
1070 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
1071
1072 return ret;
1073 }
1074
1075
1076 /* Function 39 */
1077 CONFIGRET
1078 PNP_RequestEjectPC(handle_t BindingHandle)
1079 {
1080 CONFIGRET ret = CR_SUCCESS;
1081
1082 DPRINT1("PNP_RequestEjectPC() called\n");
1083
1084 ret = CR_FAILURE; /* FIXME */
1085
1086 DPRINT1("PNP_RequestEjectPC() done (returns %lx)\n", ret);
1087
1088 return ret;
1089 }
1090
1091
1092 /* Function 58 */
1093 CONFIGRET
1094 PNP_RunDetection(handle_t BindingHandle,
1095 unsigned long Flags)
1096 {
1097 DPRINT("PNP_RunDetection() called\n");
1098 return CR_CALL_NOT_IMPLEMENTED;
1099 }
1100
1101
1102 typedef BOOL (WINAPI *PDEV_INSTALL_W)(HWND, HINSTANCE, LPCWSTR, INT);
1103
1104 static BOOL
1105 InstallDevice(PCWSTR DeviceInstance, BOOL SetupIsActive)
1106 {
1107 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1108 HMODULE hNewDev = NULL;
1109 PDEV_INSTALL_W DevInstallW;
1110 NTSTATUS Status;
1111 BOOL DeviceInstalled = FALSE;
1112
1113 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1114 DeviceInstance);
1115 PlugPlayData.Operation = 0; /* Get status */
1116
1117 /* Get device status */
1118 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1119 (PVOID)&PlugPlayData,
1120 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1121 if (!NT_SUCCESS(Status))
1122 return FALSE;
1123
1124 if (PlugPlayData.DeviceStatus & DNF_STARTED || PlugPlayData.DeviceStatus & DNF_START_FAILED)
1125 /* Device is already started, or disabled due to some problem. Don't install it */
1126 return TRUE;
1127
1128 /* Install device */
1129 SetEnvironmentVariable(L"USERPROFILE", L"."); /* FIXME: why is it needed? */
1130
1131 hNewDev = LoadLibraryW(L"newdev.dll");
1132 if (!hNewDev)
1133 goto cleanup;
1134
1135 DevInstallW = (PDEV_INSTALL_W)GetProcAddress(hNewDev, (LPCSTR)"DevInstallW");
1136 if (!DevInstallW)
1137 goto cleanup;
1138
1139 if (!DevInstallW(NULL, NULL, DeviceInstance, SetupIsActive ? SW_HIDE : SW_SHOWNOACTIVATE))
1140 goto cleanup;
1141
1142 DeviceInstalled = TRUE;
1143
1144 cleanup:
1145 if (hNewDev != NULL)
1146 FreeLibrary(hNewDev);
1147
1148 return DeviceInstalled;
1149 }
1150
1151
1152 static BOOL
1153 SetupIsActive(VOID)
1154 {
1155 HKEY hKey = INVALID_HANDLE_VALUE;
1156 DWORD regType, active, size;
1157 LONG rc;
1158 BOOL ret = FALSE;
1159
1160 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
1161 if (rc != ERROR_SUCCESS)
1162 goto cleanup;
1163
1164 size = sizeof(DWORD);
1165 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
1166 if (rc != ERROR_SUCCESS)
1167 goto cleanup;
1168 if (regType != REG_DWORD || size != sizeof(DWORD))
1169 goto cleanup;
1170
1171 ret = (active != 0);
1172
1173 cleanup:
1174 if (hKey != INVALID_HANDLE_VALUE)
1175 RegCloseKey(hKey);
1176
1177 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
1178
1179 return ret;
1180 }
1181
1182
1183 static DWORD WINAPI
1184 PnpEventThread(LPVOID lpParameter)
1185 {
1186 PPLUGPLAY_EVENT_BLOCK PnpEvent;
1187 ULONG PnpEventSize;
1188 NTSTATUS Status;
1189 RPC_STATUS RpcStatus;
1190 BOOL setupActive;
1191
1192 PnpEventSize = 0x1000;
1193 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
1194 if (PnpEvent == NULL)
1195 return ERROR_OUTOFMEMORY;
1196
1197 setupActive = SetupIsActive();
1198
1199 for (;;)
1200 {
1201 DPRINT("Calling NtGetPlugPlayEvent()\n");
1202
1203 /* Wait for the next pnp event */
1204 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
1205
1206 /* Resize the buffer for the PnP event if it's too small. */
1207 if (Status == STATUS_BUFFER_TOO_SMALL)
1208 {
1209 PnpEventSize += 0x400;
1210 PnpEvent = HeapReAlloc(GetProcessHeap(), 0, PnpEvent, PnpEventSize);
1211 if (PnpEvent == NULL)
1212 return ERROR_OUTOFMEMORY;
1213 continue;
1214 }
1215
1216 if (!NT_SUCCESS(Status))
1217 {
1218 DPRINT("NtPlugPlayEvent() failed (Status %lx)\n", Status);
1219 break;
1220 }
1221
1222 DPRINT("Received PnP Event\n");
1223 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
1224 {
1225 DPRINT("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds);
1226 InstallDevice(PnpEvent->TargetDevice.DeviceIds, setupActive);
1227 }
1228 else
1229 {
1230 DPRINT1("Unknown event\n");
1231 }
1232
1233 /* FIXME: Process the pnp event */
1234
1235 /* Dequeue the current pnp event and signal the next one */
1236 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
1237 }
1238
1239 HeapFree(GetProcessHeap(), 0, PnpEvent);
1240
1241 return ERROR_SUCCESS;
1242 }
1243
1244
1245 static VOID CALLBACK
1246 ServiceMain(DWORD argc, LPTSTR *argv)
1247 {
1248 HANDLE hThread;
1249 DWORD dwThreadId;
1250
1251 DPRINT("ServiceMain() called\n");
1252
1253 hThread = CreateThread(NULL,
1254 0,
1255 PnpEventThread,
1256 NULL,
1257 0,
1258 &dwThreadId);
1259 if (hThread != NULL)
1260 CloseHandle(hThread);
1261
1262 hThread = CreateThread(NULL,
1263 0,
1264 RpcServerThread,
1265 NULL,
1266 0,
1267 &dwThreadId);
1268 if (hThread != NULL)
1269 CloseHandle(hThread);
1270
1271 DPRINT("ServiceMain() done\n");
1272 }
1273
1274
1275 int
1276 main(int argc, char *argv[])
1277 {
1278 DWORD dwError;
1279
1280 DPRINT("Umpnpmgr: main() started\n");
1281
1282 hInstallEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1283 if (hInstallEvent == NULL)
1284 {
1285 dwError = GetLastError();
1286 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
1287 return dwError;
1288 }
1289
1290 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1291 L"System\\CurrentControlSet\\Enum",
1292 0,
1293 KEY_ALL_ACCESS,
1294 &hEnumKey);
1295 if (dwError != ERROR_SUCCESS)
1296 {
1297 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
1298 return dwError;
1299 }
1300
1301 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1302 L"System\\CurrentControlSet\\Control\\Class",
1303 0,
1304 KEY_ALL_ACCESS,
1305 &hClassKey);
1306 if (dwError != ERROR_SUCCESS)
1307 {
1308 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
1309 return dwError;
1310 }
1311
1312 StartServiceCtrlDispatcher(ServiceTable);
1313
1314 DPRINT("Umpnpmgr: main() done\n");
1315
1316 ExitThread(0);
1317
1318 return 0;
1319 }
1320
1321 /* EOF */