Implement CM_Add_Empty_Log_Conf[_Ex] and add PNP_AddEmptyLogConf stub.
[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.RelatedDeviceInstanceLength = Length;
302 PlugPlayData.RelatedDeviceInstance = 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 if(lstrlenW(ClassGuid) < sizeof(szKeyName)/sizeof(WCHAR)-lstrlenW(szKeyName))
836 lstrcatW(szKeyName, ClassGuid);
837 else return CR_INVALID_DATA;
838
839 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
840 szKeyName,
841 0,
842 KEY_QUERY_VALUE,
843 &hKey))
844 return CR_REGISTRY_ERROR;
845
846 ulSize = *Length * sizeof(WCHAR);
847 if (RegQueryValueExW(hKey,
848 L"Class",
849 NULL,
850 NULL,
851 (LPBYTE)Buffer,
852 &ulSize))
853 {
854 *Length = 0;
855 ret = CR_REGISTRY_ERROR;
856 }
857 else
858 {
859 *Length = ulSize / sizeof(WCHAR);
860 }
861
862 RegCloseKey(hKey);
863
864 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret);
865
866 return ret;
867 }
868
869
870 /* Function 20 */
871 CONFIGRET
872 PNP_DeleteClassKey(handle_t BindingHandle,
873 wchar_t *ClassGuid,
874 unsigned long Flags)
875 {
876 CONFIGRET ret = CR_SUCCESS;
877
878 DPRINT("PNP_GetClassName(%S, %lx) called\n", ClassGuid, Flags);
879
880 if (Flags & CM_DELETE_CLASS_SUBKEYS)
881 {
882 if (RegDeleteTreeW(hClassKey, ClassGuid) != ERROR_SUCCESS)
883 ret = CR_REGISTRY_ERROR;
884 }
885 else
886 {
887 if (RegDeleteKeyW(hClassKey, ClassGuid) != ERROR_SUCCESS)
888 ret = CR_REGISTRY_ERROR;
889 }
890
891 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret);
892
893 return ret;
894 }
895
896
897 /* Function 28 */
898 CONFIGRET
899 PNP_CreateDevInst(handle_t BindingHandle,
900 wchar_t *DeviceId, /* [in, out, string, size_is(Length)] */
901 wchar_t *ParentDeviceId, /* [in, string] */
902 unsigned long Length, /* [in] */
903 unsigned long Flags) /* [in] */
904 {
905 CONFIGRET ret = CR_CALL_NOT_IMPLEMENTED;
906
907 DPRINT1("PNP_CreateDevInst() called\n");
908
909 DPRINT1("PNP_CreateDevInst() done (returns %lx)\n", ret);
910
911 return ret;
912 }
913
914
915 /* Function 29 */
916 CONFIGRET
917 PNP_DeviceInstanceAction(handle_t BindingHandle,
918 unsigned long MajorAction,
919 unsigned long MinorAction,
920 wchar_t *DeviceInstance1,
921 wchar_t *DeviceInstance2)
922 {
923 CONFIGRET ret = CR_SUCCESS;
924
925 DPRINT("PNP_DeviceInstanceAction() called\n");
926
927 switch (MajorAction)
928 {
929 case 2:
930 DPRINT("Move device instance\n");
931 /* FIXME */
932 ret = CR_CALL_NOT_IMPLEMENTED;
933 break;
934
935 case 3:
936 DPRINT("Setup device instance\n");
937 /* FIXME */
938 ret = CR_CALL_NOT_IMPLEMENTED;
939 break;
940
941 case 4:
942 DPRINT("Enable device instance\n");
943 /* FIXME */
944 ret = CR_CALL_NOT_IMPLEMENTED;
945 break;
946
947 case 5:
948 DPRINT("Disable device instance\n");
949 /* FIXME */
950 ret = CR_CALL_NOT_IMPLEMENTED;
951 break;
952
953 case 7:
954 DPRINT("Reenumerate device instance\n");
955 /* FIXME */
956 ret = CR_CALL_NOT_IMPLEMENTED;
957 break;
958
959 default:
960 DPRINT1("Unknown function %lu\n", MajorAction);
961 ret = CR_CALL_NOT_IMPLEMENTED;
962 }
963
964 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
965
966 return ret;
967 }
968
969
970 /* Function 30 */
971 CONFIGRET
972 PNP_GetDeviceStatus(handle_t BindingHandle,
973 wchar_t *DeviceInstance,
974 unsigned long *pStatus,
975 unsigned long *pProblem,
976 DWORD Flags)
977 {
978 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
979 CONFIGRET ret = CR_SUCCESS;
980 NTSTATUS Status;
981
982 DPRINT("PNP_GetDeviceStatus() called\n");
983
984 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
985 DeviceInstance);
986 PlugPlayData.Operation = 0; /* Get status */
987
988 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
989 (PVOID)&PlugPlayData,
990 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
991 if (NT_SUCCESS(Status))
992 {
993 *pStatus = PlugPlayData.DeviceStatus;
994 *pProblem = PlugPlayData.DeviceProblem;
995 }
996 else
997 {
998 ret = NtStatusToCrError(Status);
999 }
1000
1001 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret);
1002
1003 return ret;
1004 }
1005
1006
1007 /* Function 31 */
1008 CONFIGRET
1009 PNP_SetDeviceProblem(handle_t BindingHandle,
1010 wchar_t *DeviceInstance,
1011 unsigned long Problem,
1012 DWORD Flags)
1013 {
1014 CONFIGRET ret = CR_SUCCESS;
1015
1016 DPRINT1("PNP_SetDeviceProblem() called\n");
1017
1018 /* FIXME */
1019
1020 DPRINT1("PNP_SetDeviceProblem() done (returns %lx)\n", ret);
1021
1022 return ret;
1023 }
1024
1025
1026 /* Function 33 */
1027 CONFIGRET
1028 PNP_UninstallDevInst(handle_t BindingHandle,
1029 wchar_t *DeviceInstance,
1030 DWORD Flags)
1031 {
1032 CONFIGRET ret = CR_SUCCESS;
1033
1034 DPRINT1("PNP_UninstallDevInst() called\n");
1035
1036 /* FIXME */
1037
1038 DPRINT1("PNP_UninstallDevInst() done (returns %lx)\n", ret);
1039
1040 return ret;
1041 }
1042
1043
1044 static BOOL
1045 CheckForDeviceId(LPWSTR lpDeviceIdList,
1046 LPWSTR lpDeviceId)
1047 {
1048 LPWSTR lpPtr;
1049 DWORD dwLength;
1050
1051 lpPtr = lpDeviceIdList;
1052 while (*lpPtr != 0)
1053 {
1054 dwLength = wcslen(lpPtr);
1055 if (!_wcsicmp(lpPtr, lpDeviceId))
1056 return TRUE;
1057
1058 lpPtr += (dwLength + 1);
1059 }
1060
1061 return FALSE;
1062 }
1063
1064
1065 static VOID
1066 AppendDeviceId(LPWSTR lpDeviceIdList,
1067 LPDWORD lpDeviceIdListSize,
1068 LPWSTR lpDeviceId)
1069 {
1070 DWORD dwLen;
1071 DWORD dwPos;
1072
1073 dwLen = wcslen(lpDeviceId);
1074 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
1075
1076 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
1077
1078 dwPos += (dwLen + 1);
1079
1080 lpDeviceIdList[dwPos] = 0;
1081
1082 *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
1083 }
1084
1085
1086 /* Function 34 */
1087 CONFIGRET
1088 PNP_AddID(handle_t BindingHandle,
1089 wchar_t *DeviceInstance,
1090 wchar_t *DeviceId,
1091 DWORD Flags)
1092 {
1093 CONFIGRET ret = CR_SUCCESS;
1094 HKEY hDeviceKey;
1095 LPWSTR pszSubKey;
1096 DWORD dwDeviceIdListSize;
1097 WCHAR szDeviceIdList[512];
1098
1099 DPRINT("PNP_AddID() called\n");
1100 DPRINT(" DeviceInstance: %S\n", DeviceInstance);
1101 DPRINT(" DeviceId: %S\n", DeviceId);
1102 DPRINT(" Flags: %lx\n", Flags);
1103
1104 if (RegOpenKeyExW(hEnumKey,
1105 DeviceInstance,
1106 0,
1107 KEY_QUERY_VALUE | KEY_SET_VALUE,
1108 &hDeviceKey) != ERROR_SUCCESS)
1109 {
1110 DPRINT("Failed to open the device key!\n");
1111 return CR_INVALID_DEVNODE;
1112 }
1113
1114 pszSubKey = (Flags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
1115
1116 dwDeviceIdListSize = 512 * sizeof(WCHAR);
1117 if (RegQueryValueExW(hDeviceKey,
1118 pszSubKey,
1119 NULL,
1120 NULL,
1121 (LPBYTE)szDeviceIdList,
1122 &dwDeviceIdListSize) != ERROR_SUCCESS)
1123 {
1124 DPRINT("Failed to query the desired ID string!\n");
1125 ret = CR_REGISTRY_ERROR;
1126 goto Done;
1127 }
1128
1129 /* Check whether the device ID is already in use */
1130 if (CheckForDeviceId(szDeviceIdList, DeviceId))
1131 {
1132 DPRINT("Device ID was found in the ID string!\n");
1133 ret = CR_SUCCESS;
1134 goto Done;
1135 }
1136
1137 /* Append the Device ID */
1138 AppendDeviceId(szDeviceIdList, &dwDeviceIdListSize, DeviceId);
1139
1140 if (RegSetValueExW(hDeviceKey,
1141 pszSubKey,
1142 0,
1143 REG_MULTI_SZ,
1144 (LPBYTE)szDeviceIdList,
1145 dwDeviceIdListSize) != ERROR_SUCCESS)
1146 {
1147 DPRINT("Failed to set the desired ID string!\n");
1148 ret = CR_REGISTRY_ERROR;
1149 }
1150
1151 Done:
1152 RegCloseKey(hDeviceKey);
1153
1154 DPRINT("PNP_AddID() done (returns %lx)\n", ret);
1155
1156 return ret;
1157 }
1158
1159
1160 /* Function 38 */
1161 CONFIGRET
1162 PNP_IsDockStationPresent(handle_t BindingHandle,
1163 unsigned long *Present)
1164 {
1165 HKEY hKey;
1166 DWORD dwType;
1167 DWORD dwValue;
1168 DWORD dwSize;
1169 CONFIGRET ret = CR_SUCCESS;
1170
1171 DPRINT1("PNP_IsDockStationPresent() called\n");
1172
1173 *Present = FALSE;
1174
1175 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
1176 L"CurrentDockInfo",
1177 0,
1178 KEY_READ,
1179 &hKey) != ERROR_SUCCESS)
1180 return CR_REGISTRY_ERROR;
1181
1182 dwSize = sizeof(DWORD);
1183 if (RegQueryValueExW(hKey,
1184 L"DockingState",
1185 NULL,
1186 &dwType,
1187 (LPBYTE)&dwValue,
1188 &dwSize) != ERROR_SUCCESS)
1189 ret = CR_REGISTRY_ERROR;
1190
1191 RegCloseKey(hKey);
1192
1193 if (ret == CR_SUCCESS)
1194 {
1195 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
1196 {
1197 ret = CR_REGISTRY_ERROR;
1198 }
1199 else if (dwValue != 0)
1200 {
1201 *Present = TRUE;
1202 }
1203 }
1204
1205 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
1206
1207 return ret;
1208 }
1209
1210
1211 /* Function 39 */
1212 CONFIGRET
1213 PNP_RequestEjectPC(handle_t BindingHandle)
1214 {
1215 CONFIGRET ret = CR_SUCCESS;
1216
1217 DPRINT1("PNP_RequestEjectPC() called\n");
1218
1219 ret = CR_FAILURE; /* FIXME */
1220
1221 DPRINT1("PNP_RequestEjectPC() done (returns %lx)\n", ret);
1222
1223 return ret;
1224 }
1225
1226
1227 /* Function 40 */
1228 CONFIGRET
1229 PNP_HwProfFlags(handle_t BindingHandle,
1230 unsigned long Action,
1231 wchar_t *DeviceId,
1232 unsigned long ProfileId,
1233 unsigned long *Value, // out
1234 unsigned long Flags)
1235 {
1236 CONFIGRET ret = CR_SUCCESS;
1237
1238 DPRINT1("PNP_HwProfFlags() called\n");
1239
1240 ret = CR_CALL_NOT_IMPLEMENTED; /* FIXME */
1241
1242 DPRINT1("PNP_HwProfFlags() done (returns %lx)\n", ret);
1243
1244 return ret;
1245 }
1246
1247
1248 /* Function 42 */
1249 CONFIGRET
1250 PNP_AddEmptyLogConf(handle_t BindingHandle,
1251 wchar_t *DeviceInstance,
1252 ULONG ulPriority,
1253 ULONG *ulLogConfTag,
1254 ULONG ulFlags)
1255 {
1256 CONFIGRET ret = CR_SUCCESS;
1257
1258 DPRINT1("PNP_AddEmptyLogConf() called\n");
1259
1260 *ulLogConfTag = 0; /* FIXME */
1261
1262 DPRINT1("PNP_AddEmptyLogConf() done (returns %lx)\n", ret);
1263
1264 return ret;
1265 }
1266
1267
1268 /* Function 58 */
1269 CONFIGRET
1270 PNP_RunDetection(handle_t BindingHandle,
1271 unsigned long Flags)
1272 {
1273 DPRINT("PNP_RunDetection() called\n");
1274 return CR_CALL_NOT_IMPLEMENTED;
1275 }
1276
1277
1278 typedef BOOL (WINAPI *PDEV_INSTALL_W)(HWND, HINSTANCE, LPCWSTR, INT);
1279
1280 static BOOL
1281 InstallDevice(PCWSTR DeviceInstance, BOOL SetupIsActive)
1282 {
1283 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1284 HMODULE hNewDev = NULL;
1285 PDEV_INSTALL_W DevInstallW;
1286 NTSTATUS Status;
1287 BOOL DeviceInstalled = FALSE;
1288
1289 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1290 DeviceInstance);
1291 PlugPlayData.Operation = 0; /* Get status */
1292
1293 /* Get device status */
1294 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1295 (PVOID)&PlugPlayData,
1296 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1297 if (!NT_SUCCESS(Status))
1298 return FALSE;
1299
1300 if (PlugPlayData.DeviceStatus & DNF_STARTED || PlugPlayData.DeviceStatus & DNF_START_FAILED)
1301 /* Device is already started, or disabled due to some problem. Don't install it */
1302 return TRUE;
1303
1304 /* Install device */
1305 SetEnvironmentVariable(L"USERPROFILE", L"."); /* FIXME: why is it needed? */
1306
1307 hNewDev = LoadLibraryW(L"newdev.dll");
1308 if (!hNewDev)
1309 goto cleanup;
1310
1311 DevInstallW = (PDEV_INSTALL_W)GetProcAddress(hNewDev, (LPCSTR)"DevInstallW");
1312 if (!DevInstallW)
1313 goto cleanup;
1314
1315 if (!DevInstallW(NULL, NULL, DeviceInstance, SetupIsActive ? SW_HIDE : SW_SHOWNOACTIVATE))
1316 goto cleanup;
1317
1318 DeviceInstalled = TRUE;
1319
1320 cleanup:
1321 if (hNewDev != NULL)
1322 FreeLibrary(hNewDev);
1323
1324 return DeviceInstalled;
1325 }
1326
1327
1328 static BOOL
1329 SetupIsActive(VOID)
1330 {
1331 HKEY hKey = NULL;
1332 DWORD regType, active, size;
1333 LONG rc;
1334 BOOL ret = FALSE;
1335
1336 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
1337 if (rc != ERROR_SUCCESS)
1338 goto cleanup;
1339
1340 size = sizeof(DWORD);
1341 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
1342 if (rc != ERROR_SUCCESS)
1343 goto cleanup;
1344 if (regType != REG_DWORD || size != sizeof(DWORD))
1345 goto cleanup;
1346
1347 ret = (active != 0);
1348
1349 cleanup:
1350 if (hKey != NULL)
1351 RegCloseKey(hKey);
1352
1353 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
1354
1355 return ret;
1356 }
1357
1358
1359 static DWORD WINAPI
1360 PnpEventThread(LPVOID lpParameter)
1361 {
1362 PPLUGPLAY_EVENT_BLOCK PnpEvent;
1363 ULONG PnpEventSize;
1364 NTSTATUS Status;
1365 RPC_STATUS RpcStatus;
1366 BOOL setupActive;
1367
1368 PnpEventSize = 0x1000;
1369 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
1370 if (PnpEvent == NULL)
1371 return ERROR_OUTOFMEMORY;
1372
1373 setupActive = SetupIsActive();
1374
1375 for (;;)
1376 {
1377 DPRINT("Calling NtGetPlugPlayEvent()\n");
1378
1379 /* Wait for the next pnp event */
1380 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
1381
1382 /* Resize the buffer for the PnP event if it's too small. */
1383 if (Status == STATUS_BUFFER_TOO_SMALL)
1384 {
1385 PnpEventSize += 0x400;
1386 PnpEvent = HeapReAlloc(GetProcessHeap(), 0, PnpEvent, PnpEventSize);
1387 if (PnpEvent == NULL)
1388 return ERROR_OUTOFMEMORY;
1389 continue;
1390 }
1391
1392 if (!NT_SUCCESS(Status))
1393 {
1394 DPRINT("NtPlugPlayEvent() failed (Status %lx)\n", Status);
1395 break;
1396 }
1397
1398 DPRINT("Received PnP Event\n");
1399 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
1400 {
1401 DPRINT("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds);
1402 InstallDevice(PnpEvent->TargetDevice.DeviceIds, setupActive);
1403 }
1404 else
1405 {
1406 DPRINT1("Unknown event\n");
1407 }
1408
1409 /* FIXME: Process the pnp event */
1410
1411 /* Dequeue the current pnp event and signal the next one */
1412 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
1413 }
1414
1415 HeapFree(GetProcessHeap(), 0, PnpEvent);
1416
1417 return ERROR_SUCCESS;
1418 }
1419
1420
1421 static VOID CALLBACK
1422 ServiceMain(DWORD argc, LPTSTR *argv)
1423 {
1424 HANDLE hThread;
1425 DWORD dwThreadId;
1426
1427 DPRINT("ServiceMain() called\n");
1428
1429 hThread = CreateThread(NULL,
1430 0,
1431 PnpEventThread,
1432 NULL,
1433 0,
1434 &dwThreadId);
1435 if (hThread != NULL)
1436 CloseHandle(hThread);
1437
1438 hThread = CreateThread(NULL,
1439 0,
1440 RpcServerThread,
1441 NULL,
1442 0,
1443 &dwThreadId);
1444 if (hThread != NULL)
1445 CloseHandle(hThread);
1446
1447 DPRINT("ServiceMain() done\n");
1448 }
1449
1450
1451 int
1452 main(int argc, char *argv[])
1453 {
1454 DWORD dwError;
1455
1456 DPRINT("Umpnpmgr: main() started\n");
1457
1458 hInstallEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1459 if (hInstallEvent == NULL)
1460 {
1461 dwError = GetLastError();
1462 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
1463 return dwError;
1464 }
1465
1466 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1467 L"System\\CurrentControlSet\\Enum",
1468 0,
1469 KEY_ALL_ACCESS,
1470 &hEnumKey);
1471 if (dwError != ERROR_SUCCESS)
1472 {
1473 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
1474 return dwError;
1475 }
1476
1477 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1478 L"System\\CurrentControlSet\\Control\\Class",
1479 0,
1480 KEY_ALL_ACCESS,
1481 &hClassKey);
1482 if (dwError != ERROR_SUCCESS)
1483 {
1484 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
1485 return dwError;
1486 }
1487
1488 StartServiceCtrlDispatcher(ServiceTable);
1489
1490 DPRINT("Umpnpmgr: main() done\n");
1491
1492 ExitThread(0);
1493
1494 return 0;
1495 }
1496
1497 /* EOF */