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