Add traces
[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 HAVE_SLIST_ENTRY_IMPLEMENTED
30 #define WIN32_NO_STATUS
31 #include <windows.h>
32 #include <cmtypes.h>
33 #include <cmfuncs.h>
34 #include <rtlfuncs.h>
35 #include <umpnpmgr/sysguid.h>
36 #include <wdmguid.h>
37 #include <cfgmgr32.h>
38
39 #include <rpc.h>
40 #include <rpcdce.h>
41
42 #include "pnp_c.h"
43
44 #define NDEBUG
45 #include <debug.h>
46
47 /* GLOBALS ******************************************************************/
48
49 static VOID CALLBACK
50 ServiceMain(DWORD argc, LPTSTR *argv);
51
52 static SERVICE_TABLE_ENTRY ServiceTable[2] =
53 {
54 {TEXT("PlugPlay"), ServiceMain},
55 {NULL, NULL}
56 };
57
58 static WCHAR szRootDeviceId[] = L"HTREE\\ROOT\\0";
59
60 static HKEY hEnumKey = NULL;
61 static HKEY hClassKey = NULL;
62
63 static HANDLE hUserToken = NULL;
64 static HANDLE hInstallEvent = NULL;
65 static HANDLE hNoPendingInstalls = NULL;
66
67 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
68 static SLIST_HEADER DeviceInstallListHead;
69 #else
70 static LIST_ENTRY DeviceInstallListHead;
71 #endif
72 static HANDLE hDeviceInstallListNotEmpty;
73
74 typedef struct
75 {
76 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
77 SLIST_ENTRY ListEntry;
78 #else
79 LIST_ENTRY ListEntry;
80 #endif
81 WCHAR DeviceIds[1];
82 } DeviceInstallParams;
83
84 /* FUNCTIONS *****************************************************************/
85
86 static DWORD WINAPI
87 RpcServerThread(LPVOID lpParameter)
88 {
89 RPC_STATUS Status;
90
91 UNREFERENCED_PARAMETER(lpParameter);
92
93 DPRINT("RpcServerThread() called\n");
94
95 Status = RpcServerUseProtseqEpW(L"ncacn_np",
96 20,
97 L"\\pipe\\umpnpmgr",
98 NULL); // Security descriptor
99 if (Status != RPC_S_OK)
100 {
101 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
102 return 0;
103 }
104
105 Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec,
106 NULL,
107 NULL);
108 if (Status != RPC_S_OK)
109 {
110 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
111 return 0;
112 }
113
114 Status = RpcServerListen(1,
115 20,
116 FALSE);
117 if (Status != RPC_S_OK)
118 {
119 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
120 return 0;
121 }
122
123 DPRINT("RpcServerThread() done\n");
124
125 return 0;
126 }
127
128
129 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
130 {
131 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
132 }
133
134
135 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
136 {
137 HeapFree(GetProcessHeap(), 0, ptr);
138 }
139
140
141 static CONFIGRET WINAPI
142 NtStatusToCrError(NTSTATUS Status)
143 {
144 switch (Status)
145 {
146 case STATUS_NO_SUCH_DEVICE:
147 return CR_NO_SUCH_DEVINST;
148
149 default:
150 /* FIXME: add more mappings */
151 DPRINT1("Unable to map status 0x%08lx\n", Status);
152 return CR_FAILURE;
153 }
154 }
155
156
157 /* Function 2 */
158 CONFIGRET
159 PNP_GetVersion(handle_t BindingHandle,
160 unsigned short *Version)
161 {
162 UNREFERENCED_PARAMETER(BindingHandle);
163
164 *Version = 0x0400;
165 return CR_SUCCESS;
166 }
167
168
169 /* Function 3 */
170 CONFIGRET
171 PNP_GetGlobalState(handle_t BindingHandle,
172 unsigned long *State,
173 unsigned long Flags)
174 {
175 UNREFERENCED_PARAMETER(BindingHandle);
176 UNREFERENCED_PARAMETER(Flags);
177
178 *State = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE;
179 return CR_SUCCESS;
180 }
181
182
183 /* Function 4 */
184 CONFIGRET
185 PNP_InitDetection(handle_t BindingHandle)
186 {
187 UNREFERENCED_PARAMETER(BindingHandle);
188
189 DPRINT("PNP_InitDetection() called\n");
190 return CR_SUCCESS;
191 }
192
193
194 /* Function 5 */
195 CONFIGRET
196 PNP_ReportLogOn(handle_t BindingHandle,
197 BOOL Admin,
198 DWORD ProcessId)
199 {
200 HANDLE hProcess;
201
202 UNREFERENCED_PARAMETER(BindingHandle);
203
204 DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin, ProcessId);
205
206 /* Get the users token */
207 hProcess = OpenProcess(PROCESS_ALL_ACCESS,
208 TRUE,
209 ProcessId);
210 if (hProcess != NULL)
211 {
212 if (hUserToken != NULL)
213 {
214 CloseHandle(hUserToken);
215 hUserToken = NULL;
216 }
217
218 OpenProcessToken(hProcess,
219 TOKEN_ALL_ACCESS,
220 &hUserToken);
221 CloseHandle(hProcess);
222 }
223
224 /* Trigger the installer thread */
225 if (hInstallEvent != NULL)
226 SetEvent(hInstallEvent);
227
228 return CR_SUCCESS;
229 }
230
231
232 /* Function 6 */
233 CONFIGRET
234 PNP_ValidateDeviceInstance(handle_t BindingHandle,
235 wchar_t *DeviceInstance,
236 DWORD Flags)
237 {
238 CONFIGRET ret = CR_SUCCESS;
239 HKEY hDeviceKey = NULL;
240
241 UNREFERENCED_PARAMETER(BindingHandle);
242
243 DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
244 DeviceInstance, Flags);
245
246 if (RegOpenKeyExW(hEnumKey,
247 DeviceInstance,
248 0,
249 KEY_READ,
250 &hDeviceKey))
251 {
252 DPRINT("Could not open the Device Key!\n");
253 ret = CR_NO_SUCH_DEVNODE;
254 goto Done;
255 }
256
257 /* FIXME: add more tests */
258
259 Done:
260 if (hDeviceKey != NULL)
261 RegCloseKey(hDeviceKey);
262
263 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret);
264
265 return ret;
266 }
267
268
269 /* Function 7 */
270 CONFIGRET
271 PNP_GetRootDeviceInstance(handle_t BindingHandle,
272 wchar_t *DeviceInstance,
273 DWORD Length)
274 {
275 CONFIGRET ret = CR_SUCCESS;
276
277 UNREFERENCED_PARAMETER(BindingHandle);
278
279 DPRINT("PNP_GetRootDeviceInstance() called\n");
280
281 if (Length < lstrlenW(szRootDeviceId) + 1)
282 {
283 ret = CR_BUFFER_SMALL;
284 goto Done;
285 }
286
287 lstrcpyW(DeviceInstance,
288 szRootDeviceId);
289
290 Done:
291 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret);
292
293 return ret;
294 }
295
296
297 /* Function 8 */
298 CONFIGRET
299 PNP_GetRelatedDeviceInstance(handle_t BindingHandle,
300 DWORD Relationship,
301 wchar_t *DeviceId,
302 wchar_t *RelatedDeviceId,
303 DWORD Length,
304 DWORD Flags)
305 {
306 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData;
307 CONFIGRET ret = CR_SUCCESS;
308 NTSTATUS Status;
309
310 UNREFERENCED_PARAMETER(BindingHandle);
311 UNREFERENCED_PARAMETER(Flags);
312
313 DPRINT("PNP_GetRelatedDeviceInstance() called\n");
314 DPRINT(" Relationship %ld\n", Relationship);
315 DPRINT(" DeviceId %S\n", DeviceId);
316
317 RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance,
318 DeviceId);
319
320 PlugPlayData.Relation = Relationship;
321
322 PlugPlayData.RelatedDeviceInstanceLength = Length;
323 PlugPlayData.RelatedDeviceInstance = RelatedDeviceId;
324
325 Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice,
326 (PVOID)&PlugPlayData,
327 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA));
328 if (!NT_SUCCESS(Status))
329 {
330 ret = NtStatusToCrError(Status);
331 }
332
333 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret);
334 if (ret == CR_SUCCESS)
335 {
336 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance);
337 }
338
339 return ret;
340 }
341
342
343 /* Function 9 */
344 CONFIGRET
345 PNP_EnumerateSubKeys(handle_t BindingHandle,
346 DWORD Branch,
347 DWORD Index,
348 wchar_t *Buffer,
349 DWORD Length,
350 DWORD *RequiredLength,
351 DWORD Flags)
352 {
353 CONFIGRET ret = CR_SUCCESS;
354 HKEY hKey;
355 DWORD dwError;
356
357 UNREFERENCED_PARAMETER(BindingHandle);
358 UNREFERENCED_PARAMETER(Flags);
359
360 DPRINT("PNP_EnumerateSubKeys() called\n");
361
362 switch (Branch)
363 {
364 case PNP_BRANCH_ENUM:
365 hKey = hEnumKey;
366 break;
367
368 case PNP_BRANCH_CLASS:
369 hKey = hClassKey;
370 break;
371
372 default:
373 return CR_FAILURE;
374 }
375
376 *RequiredLength = Length;
377 dwError = RegEnumKeyExW(hKey,
378 Index,
379 Buffer,
380 RequiredLength,
381 NULL,
382 NULL,
383 NULL,
384 NULL);
385 if (dwError != ERROR_SUCCESS)
386 {
387 ret = (dwError == ERROR_NO_MORE_ITEMS) ? CR_NO_SUCH_VALUE : CR_FAILURE;
388 }
389 else
390 {
391 (*RequiredLength)++;
392 }
393
394 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret);
395
396 return ret;
397 }
398
399
400 /* Function 11 */
401 CONFIGRET
402 PNP_GetDeviceListSize(handle_t BindingHandle,
403 wchar_t *Filter,
404 unsigned long *Length,
405 DWORD Flags)
406 {
407 UNREFERENCED_PARAMETER(BindingHandle);
408 UNREFERENCED_PARAMETER(Filter);
409 UNREFERENCED_PARAMETER(Flags);
410
411 DPRINT("PNP_GetDeviceListSize() called\n");
412
413 /* FIXME */
414 *Length = 2;
415
416 return CR_SUCCESS;
417 }
418
419
420 /* Function 12 */
421 CONFIGRET
422 PNP_GetDepth(handle_t BindingHandle,
423 wchar_t *DeviceInstance,
424 unsigned long *Depth,
425 DWORD Flags)
426 {
427 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData;
428 CONFIGRET ret = CR_SUCCESS;
429 NTSTATUS Status;
430
431 UNREFERENCED_PARAMETER(BindingHandle);
432 UNREFERENCED_PARAMETER(Flags);
433
434 DPRINT("PNP_GetDepth() called\n");
435
436 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
437 DeviceInstance);
438
439 Status = NtPlugPlayControl(PlugPlayControlGetDeviceDepth,
440 (PVOID)&PlugPlayData,
441 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA));
442 if (NT_SUCCESS(Status))
443 {
444 *Depth = PlugPlayData.Depth;
445 }
446 else
447 {
448 ret = NtStatusToCrError(Status);
449 }
450
451 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret);
452
453 return ret;
454 }
455
456
457 /* Function 13 */
458 CONFIGRET
459 PNP_GetDeviceRegProp(handle_t BindingHandle,
460 wchar_t *DeviceInstance,
461 DWORD Property,
462 DWORD *DataType,
463 char *Buffer,
464 DWORD *TransferLen,
465 DWORD *Length,
466 DWORD Flags)
467 {
468 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData;
469 CONFIGRET ret = CR_SUCCESS;
470 LPWSTR lpValueName = NULL;
471 HKEY hKey = 0;
472 NTSTATUS Status;
473
474 UNREFERENCED_PARAMETER(BindingHandle);
475 UNREFERENCED_PARAMETER(Flags);
476
477 DPRINT("PNP_GetDeviceRegProp() called\n");
478
479 switch (Property)
480 {
481 case CM_DRP_DEVICEDESC:
482 lpValueName = L"DeviceDesc";
483 break;
484
485 case CM_DRP_HARDWAREID:
486 lpValueName = L"HardwareID";
487 break;
488
489 case CM_DRP_COMPATIBLEIDS:
490 lpValueName = L"CompatibleIDs";
491 break;
492
493 case CM_DRP_SERVICE:
494 lpValueName = L"Service";
495 break;
496
497 case CM_DRP_CLASS:
498 lpValueName = L"Class";
499 break;
500
501 case CM_DRP_CLASSGUID:
502 lpValueName = L"ClassGUID";
503 break;
504
505 case CM_DRP_DRIVER:
506 lpValueName = L"Driver";
507 break;
508
509 case CM_DRP_CONFIGFLAGS:
510 lpValueName = L"ConfigFlags";
511 break;
512
513 case CM_DRP_MFG:
514 lpValueName = L"Mfg";
515 break;
516
517 case CM_DRP_FRIENDLYNAME:
518 lpValueName = L"FriendlyName";
519 break;
520
521 case CM_DRP_LOCATION_INFORMATION:
522 lpValueName = L"LocationInformation";
523 break;
524
525 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
526 lpValueName = NULL;
527 break;
528
529 case CM_DRP_CAPABILITIES:
530 lpValueName = L"Capabilities";
531 break;
532
533 case CM_DRP_UI_NUMBER:
534 lpValueName = NULL;
535 break;
536
537 case CM_DRP_UPPERFILTERS:
538 lpValueName = L"UpperFilters";
539 break;
540
541 case CM_DRP_LOWERFILTERS:
542 lpValueName = L"LowerFilters";
543 break;
544
545 case CM_DRP_BUSTYPEGUID:
546 lpValueName = NULL;
547 break;
548
549 case CM_DRP_LEGACYBUSTYPE:
550 lpValueName = NULL;
551 break;
552
553 case CM_DRP_BUSNUMBER:
554 lpValueName = NULL;
555 break;
556
557 case CM_DRP_ENUMERATOR_NAME:
558 lpValueName = NULL;
559 break;
560
561 default:
562 return CR_INVALID_PROPERTY;
563 }
564
565 DPRINT("Value name: %S\n", lpValueName);
566
567 if (lpValueName)
568 {
569 /* Retrieve information from the Registry */
570 if (RegOpenKeyExW(hEnumKey,
571 DeviceInstance,
572 0,
573 KEY_ALL_ACCESS,
574 &hKey))
575 return CR_INVALID_DEVNODE;
576
577 if (RegQueryValueExW(hKey,
578 lpValueName,
579 NULL,
580 DataType,
581 (LPBYTE)Buffer,
582 Length))
583 ret = CR_REGISTRY_ERROR;
584
585 /* FIXME: Check buffer size */
586
587 RegCloseKey(hKey);
588 }
589 else
590 {
591 /* Retrieve information from the Device Node */
592 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
593 DeviceInstance);
594 PlugPlayData.Buffer = Buffer;
595 PlugPlayData.BufferSize = *TransferLen;
596
597 switch (Property)
598 {
599 #if 0
600 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
601 PlugPlayData.Property = DevicePropertyPhysicalDeviceObjectName;
602 break;
603
604 case CM_DRP_UI_NUMBER:
605 PlugPlayData.Property = DevicePropertyUINumber;
606 break;
607
608 case CM_DRP_BUSTYPEGUID:
609 PlugPlayData.Property = DevicePropertyBusTypeGuid;
610 break;
611
612 case CM_DRP_LEGACYBUSTYPE:
613 PlugPlayData.Property = DevicePropertyLegacyBusType;
614 break;
615
616 case CM_DRP_BUSNUMBER:
617 PlugPlayData.Property = DevicePropertyBusNumber;
618 break;
619
620 case CM_DRP_ENUMERATOR_NAME:
621 PlugPlayData.Property = DevicePropertyEnumeratorName;
622 break;
623 #endif
624
625 default:
626 return CR_INVALID_PROPERTY;
627 }
628
629 Status = NtPlugPlayControl(PlugPlayControlProperty,
630 (PVOID)&PlugPlayData,
631 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA));
632 if (NT_SUCCESS(Status))
633 {
634 *Length = PlugPlayData.BufferSize;
635 }
636 else
637 {
638 ret = NtStatusToCrError(Status);
639 }
640 }
641
642 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret);
643
644 return ret;
645 }
646
647
648 /* Function 14 */
649 CONFIGRET
650 PNP_SetDeviceRegProp(handle_t BindingHandle,
651 wchar_t *DeviceId,
652 unsigned long Property,
653 unsigned long DataType,
654 char *Buffer,
655 unsigned long Length,
656 unsigned long Flags)
657 {
658 CONFIGRET ret = CR_SUCCESS;
659 LPWSTR lpValueName = NULL;
660 HKEY hKey = 0;
661
662 UNREFERENCED_PARAMETER(BindingHandle);
663 UNREFERENCED_PARAMETER(Flags);
664
665 DPRINT("PNP_SetDeviceRegProp() called\n");
666
667 DPRINT("DeviceId: %S\n", DeviceId);
668 DPRINT("Property: %lu\n", Property);
669 DPRINT("DataType: %lu\n", DataType);
670 DPRINT("Length: %lu\n", Length);
671
672 switch (Property)
673 {
674 case CM_DRP_DEVICEDESC:
675 lpValueName = L"DeviceDesc";
676 break;
677
678 case CM_DRP_HARDWAREID:
679 lpValueName = L"HardwareID";
680 break;
681
682 case CM_DRP_COMPATIBLEIDS:
683 lpValueName = L"CompatibleIDs";
684 break;
685
686 case CM_DRP_SERVICE:
687 lpValueName = L"Service";
688 break;
689
690 case CM_DRP_CLASS:
691 lpValueName = L"Class";
692 break;
693
694 case CM_DRP_CLASSGUID:
695 lpValueName = L"ClassGUID";
696 break;
697
698 case CM_DRP_DRIVER:
699 lpValueName = L"Driver";
700 break;
701
702 case CM_DRP_CONFIGFLAGS:
703 lpValueName = L"ConfigFlags";
704 break;
705
706 case CM_DRP_MFG:
707 lpValueName = L"Mfg";
708 break;
709
710 case CM_DRP_FRIENDLYNAME:
711 lpValueName = L"FriendlyName";
712 break;
713
714 case CM_DRP_LOCATION_INFORMATION:
715 lpValueName = L"LocationInformation";
716 break;
717
718 case CM_DRP_UPPERFILTERS:
719 lpValueName = L"UpperFilters";
720 break;
721
722 case CM_DRP_LOWERFILTERS:
723 lpValueName = L"LowerFilters";
724 break;
725
726 default:
727 return CR_INVALID_PROPERTY;
728 }
729
730 DPRINT("Value name: %S\n", lpValueName);
731
732 if (RegOpenKeyExW(hEnumKey,
733 DeviceId,
734 0,
735 KEY_ALL_ACCESS,
736 &hKey))
737 return CR_INVALID_DEVNODE;
738
739 if (Length == 0)
740 {
741 if (RegDeleteValueW(hKey,
742 lpValueName))
743 ret = CR_REGISTRY_ERROR;
744 }
745 else
746 {
747 if (RegSetValueExW(hKey,
748 lpValueName,
749 0,
750 DataType,
751 (const BYTE*)Buffer,
752 Length))
753 ret = CR_REGISTRY_ERROR;
754 }
755
756 RegCloseKey(hKey);
757
758 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret);
759
760 return ret;
761 }
762
763
764 /* Function 15 */
765 CONFIGRET
766 PNP_GetClassInstance(handle_t BindingHandle,
767 wchar_t *DeviceId, /* in */
768 wchar_t *Buffer, /* out */
769 unsigned long Length)
770 {
771 CONFIGRET ret = CR_SUCCESS;
772
773 UNREFERENCED_PARAMETER(BindingHandle);
774 UNREFERENCED_PARAMETER(DeviceId);
775 UNREFERENCED_PARAMETER(Buffer);
776 UNREFERENCED_PARAMETER(Length);
777
778 DPRINT("PNP_Get_Class_Instance() called\n");
779
780 DPRINT("PNP_Get_Class_Instance() done (returns %lx)\n", ret);
781
782 return ret;
783 }
784
785
786 /* Function 16 */
787 CONFIGRET
788 PNP_CreateKey(handle_t BindingHandle,
789 wchar_t *SubKey,
790 unsigned long samDesired,
791 unsigned long Flags)
792 {
793 CONFIGRET ret = CR_SUCCESS;
794
795 UNREFERENCED_PARAMETER(BindingHandle);
796 UNREFERENCED_PARAMETER(SubKey);
797 UNREFERENCED_PARAMETER(samDesired);
798 UNREFERENCED_PARAMETER(Flags);
799
800 DPRINT("PNP_CreateKey() called\n");
801
802 DPRINT("PNP_CreateKey() done (returns %lx)\n", ret);
803
804 return ret;
805 }
806
807
808 /* Function 17 */
809 CONFIGRET
810 PNP_DeleteRegistryKey(handle_t BindingHandle,
811 wchar_t *DeviceId,
812 wchar_t *ParentKey,
813 wchar_t *ChildKey,
814 unsigned long Flags)
815 {
816 CONFIGRET ret = CR_SUCCESS;
817
818 UNREFERENCED_PARAMETER(BindingHandle);
819 UNREFERENCED_PARAMETER(DeviceId);
820 UNREFERENCED_PARAMETER(ParentKey);
821 UNREFERENCED_PARAMETER(ChildKey);
822 UNREFERENCED_PARAMETER(Flags);
823
824 DPRINT("PNP_DeleteRegistryKey() called\n");
825
826 DPRINT("PNP_DeleteRegistryKey() done (returns %lx)\n", ret);
827
828 return ret;
829 }
830
831
832 /* Function 18 */
833 #if 0
834 CONFIGRET
835 PNP_GetClassCount(handle_t BindingHandle,
836 unsigned long *ClassCount,
837 unsigned long Flags)
838 {
839 HANDLE hKey = NULL;
840 DWORD dwError;
841
842 UNREFERENCED_PARAMETER(BindingHandle);
843
844 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
845 pszRegPathClass,
846 0,
847 KEY_QUERY_VALUE,
848 &hKey);
849 if (dwError != ERROR_SUCCESS)
850 return CR_INVALID_DATA;
851
852 dwError = RegQueryInfoKeyW(hKey,
853 NULL,
854 NULL,
855 NULL,
856 &ClassCount,
857 NULL,
858 NULL,
859 NULL,
860 NULL,
861 NULL,
862 NULL,
863 NULL);
864 RegCloseKey(hKey);
865 if (dwError != ERROR_SUCCESS)
866 return CR_INVALID_DATA;
867
868 return CR_SUCCESS;
869 }
870 #endif
871
872
873 /* Function 19 */
874 CONFIGRET
875 PNP_GetClassName(handle_t BindingHandle,
876 wchar_t *ClassGuid,
877 wchar_t *Buffer,
878 unsigned long *Length,
879 unsigned long Flags)
880 {
881 WCHAR szKeyName[MAX_PATH];
882 CONFIGRET ret = CR_SUCCESS;
883 HKEY hKey = NULL;
884 DWORD dwSize;
885
886 UNREFERENCED_PARAMETER(BindingHandle);
887 UNREFERENCED_PARAMETER(Flags);
888
889 DPRINT("PNP_GetClassName() called\n");
890
891 lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class");
892 lstrcatW(szKeyName, L"\\");
893 if(lstrlenW(ClassGuid) < sizeof(szKeyName)/sizeof(WCHAR)-lstrlenW(szKeyName))
894 lstrcatW(szKeyName, ClassGuid);
895 else return CR_INVALID_DATA;
896
897 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
898 szKeyName,
899 0,
900 KEY_QUERY_VALUE,
901 &hKey))
902 return CR_REGISTRY_ERROR;
903
904 dwSize = *Length * sizeof(WCHAR);
905 if (RegQueryValueExW(hKey,
906 L"Class",
907 NULL,
908 NULL,
909 (LPBYTE)Buffer,
910 &dwSize))
911 {
912 *Length = 0;
913 ret = CR_REGISTRY_ERROR;
914 }
915 else
916 {
917 *Length = dwSize / sizeof(WCHAR);
918 }
919
920 RegCloseKey(hKey);
921
922 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret);
923
924 return ret;
925 }
926
927
928 /* Function 20 */
929 CONFIGRET
930 PNP_DeleteClassKey(handle_t BindingHandle,
931 wchar_t *ClassGuid,
932 unsigned long Flags)
933 {
934 CONFIGRET ret = CR_SUCCESS;
935
936 UNREFERENCED_PARAMETER(BindingHandle);
937
938 DPRINT("PNP_GetClassName(%S, %lx) called\n", ClassGuid, Flags);
939
940 if (Flags & CM_DELETE_CLASS_SUBKEYS)
941 {
942 if (RegDeleteTreeW(hClassKey, ClassGuid) != ERROR_SUCCESS)
943 ret = CR_REGISTRY_ERROR;
944 }
945 else
946 {
947 if (RegDeleteKeyW(hClassKey, ClassGuid) != ERROR_SUCCESS)
948 ret = CR_REGISTRY_ERROR;
949 }
950
951 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret);
952
953 return ret;
954 }
955
956
957 /* Function 28 */
958 CONFIGRET
959 PNP_CreateDevInst(handle_t BindingHandle,
960 wchar_t *DeviceId, /* [in, out, string, size_is(Length)] */
961 wchar_t *ParentDeviceId, /* [in, string] */
962 unsigned long Length, /* [in] */
963 unsigned long Flags) /* [in] */
964 {
965 CONFIGRET ret = CR_CALL_NOT_IMPLEMENTED;
966
967 UNREFERENCED_PARAMETER(BindingHandle);
968 UNREFERENCED_PARAMETER(DeviceId);
969 UNREFERENCED_PARAMETER(ParentDeviceId);
970 UNREFERENCED_PARAMETER(Length);
971 UNREFERENCED_PARAMETER(Flags);
972
973 DPRINT1("PNP_CreateDevInst() called\n");
974
975 DPRINT1("PNP_CreateDevInst() done (returns %lx)\n", ret);
976
977 return ret;
978 }
979
980
981 /* Function 29 */
982 CONFIGRET
983 PNP_DeviceInstanceAction(handle_t BindingHandle,
984 unsigned long MajorAction,
985 unsigned long MinorAction,
986 wchar_t *DeviceInstance1,
987 wchar_t *DeviceInstance2)
988 {
989 CONFIGRET ret = CR_SUCCESS;
990
991 UNREFERENCED_PARAMETER(BindingHandle);
992 UNREFERENCED_PARAMETER(MinorAction);
993 UNREFERENCED_PARAMETER(DeviceInstance1);
994 UNREFERENCED_PARAMETER(DeviceInstance2);
995
996 DPRINT("PNP_DeviceInstanceAction() called\n");
997
998 switch (MajorAction)
999 {
1000 case 2:
1001 DPRINT("Move device instance\n");
1002 /* FIXME */
1003 ret = CR_CALL_NOT_IMPLEMENTED;
1004 break;
1005
1006 case 3:
1007 DPRINT("Setup device instance\n");
1008 /* FIXME */
1009 ret = CR_CALL_NOT_IMPLEMENTED;
1010 break;
1011
1012 case 4:
1013 DPRINT("Enable device instance\n");
1014 /* FIXME */
1015 ret = CR_CALL_NOT_IMPLEMENTED;
1016 break;
1017
1018 case 5:
1019 DPRINT("Disable device instance\n");
1020 /* FIXME */
1021 ret = CR_CALL_NOT_IMPLEMENTED;
1022 break;
1023
1024 case 7:
1025 DPRINT("Reenumerate device instance\n");
1026 /* FIXME */
1027 ret = CR_CALL_NOT_IMPLEMENTED;
1028 break;
1029
1030 default:
1031 DPRINT1("Unknown function %lu\n", MajorAction);
1032 ret = CR_CALL_NOT_IMPLEMENTED;
1033 }
1034
1035 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
1036
1037 return ret;
1038 }
1039
1040
1041 /* Function 30 */
1042 CONFIGRET
1043 PNP_GetDeviceStatus(handle_t BindingHandle,
1044 wchar_t *DeviceInstance,
1045 unsigned long *pStatus,
1046 unsigned long *pProblem,
1047 DWORD Flags)
1048 {
1049 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1050 CONFIGRET ret = CR_SUCCESS;
1051 NTSTATUS Status;
1052
1053 UNREFERENCED_PARAMETER(BindingHandle);
1054 UNREFERENCED_PARAMETER(Flags);
1055
1056 DPRINT("PNP_GetDeviceStatus() called\n");
1057
1058 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1059 DeviceInstance);
1060 PlugPlayData.Operation = 0; /* Get status */
1061
1062 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1063 (PVOID)&PlugPlayData,
1064 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1065 if (NT_SUCCESS(Status))
1066 {
1067 *pStatus = PlugPlayData.DeviceStatus;
1068 *pProblem = PlugPlayData.DeviceProblem;
1069 }
1070 else
1071 {
1072 ret = NtStatusToCrError(Status);
1073 }
1074
1075 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret);
1076
1077 return ret;
1078 }
1079
1080
1081 /* Function 31 */
1082 CONFIGRET
1083 PNP_SetDeviceProblem(handle_t BindingHandle,
1084 wchar_t *DeviceInstance,
1085 unsigned long Problem,
1086 DWORD Flags)
1087 {
1088 CONFIGRET ret = CR_SUCCESS;
1089
1090 UNREFERENCED_PARAMETER(BindingHandle);
1091 UNREFERENCED_PARAMETER(DeviceInstance);
1092 UNREFERENCED_PARAMETER(Problem);
1093 UNREFERENCED_PARAMETER(Flags);
1094
1095 DPRINT1("PNP_SetDeviceProblem() called\n");
1096
1097 /* FIXME */
1098
1099 DPRINT1("PNP_SetDeviceProblem() done (returns %lx)\n", ret);
1100
1101 return ret;
1102 }
1103
1104
1105 /* Function 33 */
1106 CONFIGRET
1107 PNP_UninstallDevInst(handle_t BindingHandle,
1108 wchar_t *DeviceInstance,
1109 DWORD Flags)
1110 {
1111 CONFIGRET ret = CR_SUCCESS;
1112
1113 UNREFERENCED_PARAMETER(BindingHandle);
1114 UNREFERENCED_PARAMETER(DeviceInstance);
1115 UNREFERENCED_PARAMETER(Flags);
1116
1117 DPRINT1("PNP_UninstallDevInst() called\n");
1118
1119 /* FIXME */
1120
1121 DPRINT1("PNP_UninstallDevInst() done (returns %lx)\n", ret);
1122
1123 return ret;
1124 }
1125
1126
1127 static BOOL
1128 CheckForDeviceId(LPWSTR lpDeviceIdList,
1129 LPWSTR lpDeviceId)
1130 {
1131 LPWSTR lpPtr;
1132 DWORD dwLength;
1133
1134 lpPtr = lpDeviceIdList;
1135 while (*lpPtr != 0)
1136 {
1137 dwLength = wcslen(lpPtr);
1138 if (0 == _wcsicmp(lpPtr, lpDeviceId))
1139 return TRUE;
1140
1141 lpPtr += (dwLength + 1);
1142 }
1143
1144 return FALSE;
1145 }
1146
1147
1148 static VOID
1149 AppendDeviceId(LPWSTR lpDeviceIdList,
1150 LPDWORD lpDeviceIdListSize,
1151 LPWSTR lpDeviceId)
1152 {
1153 DWORD dwLen;
1154 DWORD dwPos;
1155
1156 dwLen = wcslen(lpDeviceId);
1157 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
1158
1159 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
1160
1161 dwPos += (dwLen + 1);
1162
1163 lpDeviceIdList[dwPos] = 0;
1164
1165 *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
1166 }
1167
1168
1169 /* Function 34 */
1170 CONFIGRET
1171 PNP_AddID(handle_t BindingHandle,
1172 wchar_t *DeviceInstance,
1173 wchar_t *DeviceId,
1174 DWORD Flags)
1175 {
1176 CONFIGRET ret = CR_SUCCESS;
1177 HKEY hDeviceKey;
1178 LPWSTR pszSubKey;
1179 DWORD dwDeviceIdListSize;
1180 WCHAR szDeviceIdList[512];
1181
1182 UNREFERENCED_PARAMETER(BindingHandle);
1183
1184 DPRINT("PNP_AddID() called\n");
1185 DPRINT(" DeviceInstance: %S\n", DeviceInstance);
1186 DPRINT(" DeviceId: %S\n", DeviceId);
1187 DPRINT(" Flags: %lx\n", Flags);
1188
1189 if (RegOpenKeyExW(hEnumKey,
1190 DeviceInstance,
1191 0,
1192 KEY_QUERY_VALUE | KEY_SET_VALUE,
1193 &hDeviceKey) != ERROR_SUCCESS)
1194 {
1195 DPRINT("Failed to open the device key!\n");
1196 return CR_INVALID_DEVNODE;
1197 }
1198
1199 pszSubKey = (Flags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
1200
1201 dwDeviceIdListSize = 512 * sizeof(WCHAR);
1202 if (RegQueryValueExW(hDeviceKey,
1203 pszSubKey,
1204 NULL,
1205 NULL,
1206 (LPBYTE)szDeviceIdList,
1207 &dwDeviceIdListSize) != ERROR_SUCCESS)
1208 {
1209 DPRINT("Failed to query the desired ID string!\n");
1210 ret = CR_REGISTRY_ERROR;
1211 goto Done;
1212 }
1213
1214 /* Check whether the device ID is already in use */
1215 if (CheckForDeviceId(szDeviceIdList, DeviceId))
1216 {
1217 DPRINT("Device ID was found in the ID string!\n");
1218 ret = CR_SUCCESS;
1219 goto Done;
1220 }
1221
1222 /* Append the Device ID */
1223 AppendDeviceId(szDeviceIdList, &dwDeviceIdListSize, DeviceId);
1224
1225 if (RegSetValueExW(hDeviceKey,
1226 pszSubKey,
1227 0,
1228 REG_MULTI_SZ,
1229 (LPBYTE)szDeviceIdList,
1230 dwDeviceIdListSize) != ERROR_SUCCESS)
1231 {
1232 DPRINT("Failed to set the desired ID string!\n");
1233 ret = CR_REGISTRY_ERROR;
1234 }
1235
1236 Done:
1237 RegCloseKey(hDeviceKey);
1238
1239 DPRINT("PNP_AddID() done (returns %lx)\n", ret);
1240
1241 return ret;
1242 }
1243
1244
1245 /* Function 38 */
1246 CONFIGRET
1247 PNP_IsDockStationPresent(handle_t BindingHandle,
1248 unsigned long *Present)
1249 {
1250 HKEY hKey;
1251 DWORD dwType;
1252 DWORD dwValue;
1253 DWORD dwSize;
1254 CONFIGRET ret = CR_SUCCESS;
1255
1256 UNREFERENCED_PARAMETER(BindingHandle);
1257
1258 DPRINT1("PNP_IsDockStationPresent() called\n");
1259
1260 *Present = FALSE;
1261
1262 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
1263 L"CurrentDockInfo",
1264 0,
1265 KEY_READ,
1266 &hKey) != ERROR_SUCCESS)
1267 return CR_REGISTRY_ERROR;
1268
1269 dwSize = sizeof(DWORD);
1270 if (RegQueryValueExW(hKey,
1271 L"DockingState",
1272 NULL,
1273 &dwType,
1274 (LPBYTE)&dwValue,
1275 &dwSize) != ERROR_SUCCESS)
1276 ret = CR_REGISTRY_ERROR;
1277
1278 RegCloseKey(hKey);
1279
1280 if (ret == CR_SUCCESS)
1281 {
1282 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
1283 {
1284 ret = CR_REGISTRY_ERROR;
1285 }
1286 else if (dwValue != 0)
1287 {
1288 *Present = TRUE;
1289 }
1290 }
1291
1292 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
1293
1294 return ret;
1295 }
1296
1297
1298 /* Function 39 */
1299 CONFIGRET
1300 PNP_RequestEjectPC(handle_t BindingHandle)
1301 {
1302 CONFIGRET ret = CR_SUCCESS;
1303
1304 UNREFERENCED_PARAMETER(BindingHandle);
1305
1306 DPRINT1("PNP_RequestEjectPC() called\n");
1307
1308 ret = CR_FAILURE; /* FIXME */
1309
1310 DPRINT1("PNP_RequestEjectPC() done (returns %lx)\n", ret);
1311
1312 return ret;
1313 }
1314
1315
1316 /* Function 40 */
1317 CONFIGRET
1318 PNP_HwProfFlags(handle_t BindingHandle,
1319 DWORD Action,
1320 wchar_t *DeviceId,
1321 DWORD ProfileId,
1322 DWORD *Value, // out
1323 DWORD Flags)
1324 {
1325 CONFIGRET ret = CR_SUCCESS;
1326
1327 UNREFERENCED_PARAMETER(BindingHandle);
1328 UNREFERENCED_PARAMETER(Action);
1329 UNREFERENCED_PARAMETER(DeviceId);
1330 UNREFERENCED_PARAMETER(ProfileId);
1331 UNREFERENCED_PARAMETER(Value);
1332 UNREFERENCED_PARAMETER(Flags);
1333
1334 DPRINT1("PNP_HwProfFlags() called\n");
1335
1336 ret = CR_CALL_NOT_IMPLEMENTED; /* FIXME */
1337
1338 DPRINT1("PNP_HwProfFlags() done (returns %lx)\n", ret);
1339
1340 return ret;
1341 }
1342
1343
1344 /* Function 42 */
1345 CONFIGRET
1346 PNP_AddEmptyLogConf(handle_t BindingHandle,
1347 wchar_t *DeviceInstance,
1348 unsigned long ulPriority,
1349 unsigned long *pulLogConfTag,
1350 unsigned long ulFlags)
1351 {
1352 CONFIGRET ret = CR_SUCCESS;
1353
1354 UNREFERENCED_PARAMETER(BindingHandle);
1355 UNREFERENCED_PARAMETER(DeviceInstance);
1356 UNREFERENCED_PARAMETER(ulPriority);
1357 UNREFERENCED_PARAMETER(ulFlags);
1358
1359 DPRINT1("PNP_AddEmptyLogConf() called\n");
1360
1361 *pulLogConfTag = 0; /* FIXME */
1362
1363 DPRINT1("PNP_AddEmptyLogConf() done (returns %lx)\n", ret);
1364
1365 return ret;
1366 }
1367
1368
1369 /* Function 43 */
1370 CONFIGRET
1371 PNP_FreeLogConf(handle_t BindingHandle,
1372 wchar_t *DeviceInstance,
1373 unsigned long ulType,
1374 unsigned long ulLogConfTag,
1375 unsigned long ulFlags)
1376 {
1377 CONFIGRET ret = CR_SUCCESS;
1378
1379 UNREFERENCED_PARAMETER(BindingHandle);
1380 UNREFERENCED_PARAMETER(DeviceInstance);
1381 UNREFERENCED_PARAMETER(ulType);
1382 UNREFERENCED_PARAMETER(ulLogConfTag);
1383 UNREFERENCED_PARAMETER(ulFlags);
1384
1385 DPRINT1("PNP_FreeLogConf() called\n");
1386
1387
1388 DPRINT1("PNP_FreeLogConf() done (returns %lx)\n", ret);
1389
1390 return ret;
1391 }
1392
1393
1394 /* Function 44 */
1395 CONFIGRET
1396 PNP_GetFirstLogConf(handle_t BindingHandle,
1397 wchar_t *DeviceInstance,
1398 unsigned long ulPriority,
1399 unsigned long *pulLogConfTag,
1400 unsigned long ulFlags)
1401 {
1402 CONFIGRET ret = CR_SUCCESS;
1403
1404 UNREFERENCED_PARAMETER(BindingHandle);
1405 UNREFERENCED_PARAMETER(DeviceInstance);
1406 UNREFERENCED_PARAMETER(ulPriority);
1407 UNREFERENCED_PARAMETER(ulFlags);
1408
1409 DPRINT1("PNP_GetFirstLogConf() called\n");
1410
1411 *pulLogConfTag = 0; /* FIXME */
1412
1413 DPRINT1("PNP_GetFirstLogConf() done (returns %lx)\n", ret);
1414
1415 return ret;
1416 }
1417
1418
1419 /* Function 45 */
1420 CONFIGRET
1421 PNP_GetNextLogConf(handle_t BindingHandle,
1422 wchar_t *DeviceInstance,
1423 unsigned long ulLogConfType,
1424 unsigned long ulCurrentTag,
1425 unsigned long *pulNextTag,
1426 unsigned long ulFlags)
1427 {
1428 CONFIGRET ret = CR_SUCCESS;
1429
1430 UNREFERENCED_PARAMETER(BindingHandle);
1431 UNREFERENCED_PARAMETER(DeviceInstance);
1432 UNREFERENCED_PARAMETER(ulLogConfType);
1433 UNREFERENCED_PARAMETER(ulCurrentTag);
1434 UNREFERENCED_PARAMETER(ulFlags);
1435
1436 DPRINT1("PNP_GetNextLogConf() called\n");
1437
1438 *pulNextTag = 0; /* FIXME */
1439
1440 DPRINT1("PNP_GetNextLogConf() done (returns %lx)\n", ret);
1441
1442 return ret;
1443 }
1444
1445
1446 /* Function 46 */
1447 CONFIGRET
1448 PNP_GetLogConfPriority(handle_t BindingHandle,
1449 wchar_t *DeviceInstance,
1450 unsigned long ulLogConfType,
1451 unsigned long ulCurrentTag,
1452 unsigned long *pPriority,
1453 unsigned long ulFlags)
1454 {
1455 CONFIGRET ret = CR_SUCCESS;
1456
1457 UNREFERENCED_PARAMETER(BindingHandle);
1458 UNREFERENCED_PARAMETER(DeviceInstance);
1459 UNREFERENCED_PARAMETER(ulLogConfType);
1460 UNREFERENCED_PARAMETER(ulCurrentTag);
1461 UNREFERENCED_PARAMETER(ulFlags);
1462
1463 DPRINT1("PNP_GetLogConfPriority() called\n");
1464
1465 *pPriority = 0; /* FIXME */
1466
1467 DPRINT1("PNP_GetLogConfPriority() done (returns %lx)\n", ret);
1468
1469 return ret;
1470 }
1471
1472
1473 /* Function 58 */
1474 CONFIGRET
1475 PNP_RunDetection(handle_t BindingHandle,
1476 unsigned long Flags)
1477 {
1478 UNREFERENCED_PARAMETER(BindingHandle);
1479 UNREFERENCED_PARAMETER(Flags);
1480
1481 DPRINT("PNP_RunDetection() called\n");
1482 return CR_CALL_NOT_IMPLEMENTED;
1483 }
1484
1485
1486 typedef BOOL (WINAPI *PDEV_INSTALL_W)(HWND, HINSTANCE, LPCWSTR, INT);
1487
1488 static BOOL
1489 InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
1490 {
1491 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1492 HMODULE hNewDev = NULL;
1493 PDEV_INSTALL_W DevInstallW;
1494 NTSTATUS Status;
1495 BOOL DeviceInstalled = FALSE;
1496
1497 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance, ShowWizard);
1498
1499 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1500 DeviceInstance);
1501 PlugPlayData.Operation = 0; /* Get status */
1502
1503 /* Get device status */
1504 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1505 (PVOID)&PlugPlayData,
1506 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1507 if (!NT_SUCCESS(Status))
1508 {
1509 DPRINT1("NtPlugPlayControl('%S') failed with status 0x%08lx\n", DeviceInstance, Status);
1510 return FALSE;
1511 }
1512
1513 if ((PlugPlayData.DeviceStatus & (DNF_STARTED | DNF_START_FAILED)) != 0)
1514 {
1515 /* Device is already started, or disabled due to some problem. Don't install it */
1516 DPRINT("No need to install '%S'\n", DeviceInstance);
1517 return TRUE;
1518 }
1519
1520 /* Install device */
1521 SetEnvironmentVariableW(L"USERPROFILE", L"."); /* FIXME: why is it needed? */
1522
1523 hNewDev = LoadLibraryW(L"newdev.dll");
1524 if (!hNewDev)
1525 {
1526 DPRINT1("Unable to load newdev.dll\n");
1527 goto cleanup;
1528 }
1529
1530 DevInstallW = (PDEV_INSTALL_W)GetProcAddress(hNewDev, (LPCSTR)"DevInstallW");
1531 if (!DevInstallW)
1532 {
1533 DPRINT1("'DevInstallW' not found in newdev.dll\n");
1534 goto cleanup;
1535 }
1536
1537 if (!DevInstallW(NULL, NULL, DeviceInstance, ShowWizard ? SW_SHOWNOACTIVATE : SW_HIDE))
1538 {
1539 DPRINT1("DevInstallW('%S') failed\n", DeviceInstance);
1540 goto cleanup;
1541 }
1542
1543 DeviceInstalled = TRUE;
1544
1545 cleanup:
1546 if (hNewDev != NULL)
1547 FreeLibrary(hNewDev);
1548
1549 return DeviceInstalled;
1550 }
1551
1552
1553 static LONG
1554 ReadRegSzKey(
1555 IN HKEY hKey,
1556 IN LPCWSTR pszKey,
1557 OUT LPWSTR* pValue)
1558 {
1559 LONG rc;
1560 DWORD dwType;
1561 DWORD cbData = 0;
1562 LPWSTR Value;
1563
1564 if (!pValue)
1565 return ERROR_INVALID_PARAMETER;
1566
1567 *pValue = NULL;
1568 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
1569 if (rc != ERROR_SUCCESS)
1570 return rc;
1571 if (dwType != REG_SZ)
1572 return ERROR_FILE_NOT_FOUND;
1573 Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
1574 if (!Value)
1575 return ERROR_NOT_ENOUGH_MEMORY;
1576 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
1577 if (rc != ERROR_SUCCESS)
1578 {
1579 HeapFree(GetProcessHeap(), 0, Value);
1580 return rc;
1581 }
1582 /* NULL-terminate the string */
1583 Value[cbData / sizeof(WCHAR)] = '\0';
1584
1585 *pValue = Value;
1586 return ERROR_SUCCESS;
1587 }
1588
1589
1590 static BOOL
1591 SetupIsActive(VOID)
1592 {
1593 HKEY hKey = NULL;
1594 DWORD regType, active, size;
1595 LONG rc;
1596 BOOL ret = FALSE;
1597
1598 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
1599 if (rc != ERROR_SUCCESS)
1600 goto cleanup;
1601
1602 size = sizeof(DWORD);
1603 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
1604 if (rc != ERROR_SUCCESS)
1605 goto cleanup;
1606 if (regType != REG_DWORD || size != sizeof(DWORD))
1607 goto cleanup;
1608
1609 ret = (active != 0);
1610
1611 cleanup:
1612 if (hKey != NULL)
1613 RegCloseKey(hKey);
1614
1615 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
1616
1617 return ret;
1618 }
1619
1620
1621 static BOOL
1622 IsConsoleBoot(VOID)
1623 {
1624 HKEY ControlKey = NULL;
1625 LPWSTR SystemStartOptions = NULL;
1626 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
1627 BOOL ConsoleBoot = FALSE;
1628 LONG rc;
1629
1630 rc = RegOpenKeyExW(
1631 HKEY_LOCAL_MACHINE,
1632 L"SYSTEM\\CurrentControlSet\\Control",
1633 0,
1634 KEY_QUERY_VALUE,
1635 &ControlKey);
1636
1637 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
1638 if (rc != ERROR_SUCCESS)
1639 goto cleanup;
1640
1641 /* Check for CMDCONS in SystemStartOptions */
1642 CurrentOption = SystemStartOptions;
1643 while (CurrentOption)
1644 {
1645 NextOption = wcschr(CurrentOption, L' ');
1646 if (NextOption)
1647 *NextOption = L'\0';
1648 if (wcsicmp(CurrentOption, L"CONSOLE") == 0)
1649 {
1650 DPRINT("Found %S. Switching to console boot\n", CurrentOption);
1651 ConsoleBoot = TRUE;
1652 goto cleanup;
1653 }
1654 CurrentOption = NextOption ? NextOption + 1 : NULL;
1655 }
1656
1657 cleanup:
1658 if (ControlKey != NULL)
1659 RegCloseKey(ControlKey);
1660 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
1661 return ConsoleBoot;
1662 }
1663
1664
1665 /* Loop to install all queued devices installations */
1666 static DWORD WINAPI
1667 DeviceInstallThread(LPVOID lpParameter)
1668 {
1669 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
1670 PSLIST_ENTRY ListEntry;
1671 #else
1672 PLIST_ENTRY ListEntry;
1673 #endif
1674 DeviceInstallParams* Params;
1675 BOOL showWizard;
1676
1677 UNREFERENCED_PARAMETER(lpParameter);
1678
1679 showWizard = !SetupIsActive() && !IsConsoleBoot();
1680
1681 while (TRUE)
1682 {
1683 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
1684 ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead);
1685 #else
1686 if ((BOOL)IsListEmpty(&DeviceInstallListHead))
1687 ListEntry = NULL;
1688 else
1689 ListEntry = RemoveHeadList(&DeviceInstallListHead);
1690 #endif
1691 if (ListEntry == NULL)
1692 {
1693 SetEvent(hNoPendingInstalls);
1694 WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE);
1695 }
1696 else
1697 {
1698 ResetEvent(hNoPendingInstalls);
1699 Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry);
1700 InstallDevice(Params->DeviceIds, showWizard);
1701 }
1702 }
1703
1704 return 0;
1705 }
1706
1707
1708 static DWORD WINAPI
1709 PnpEventThread(LPVOID lpParameter)
1710 {
1711 PPLUGPLAY_EVENT_BLOCK PnpEvent;
1712 ULONG PnpEventSize;
1713 NTSTATUS Status;
1714 RPC_STATUS RpcStatus;
1715
1716 UNREFERENCED_PARAMETER(lpParameter);
1717
1718 PnpEventSize = 0x1000;
1719 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
1720 if (PnpEvent == NULL)
1721 return ERROR_OUTOFMEMORY;
1722
1723 for (;;)
1724 {
1725 DPRINT("Calling NtGetPlugPlayEvent()\n");
1726
1727 /* Wait for the next pnp event */
1728 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
1729
1730 /* Resize the buffer for the PnP event if it's too small. */
1731 if (Status == STATUS_BUFFER_TOO_SMALL)
1732 {
1733 PnpEventSize += 0x400;
1734 PnpEvent = HeapReAlloc(GetProcessHeap(), 0, PnpEvent, PnpEventSize);
1735 if (PnpEvent == NULL)
1736 return ERROR_OUTOFMEMORY;
1737 continue;
1738 }
1739
1740 if (!NT_SUCCESS(Status))
1741 {
1742 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status);
1743 break;
1744 }
1745
1746 /* Process the pnp event */
1747 DPRINT("Received PnP Event\n");
1748 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
1749 {
1750 DeviceInstallParams* Params;
1751 DWORD len;
1752
1753 DPRINT("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds);
1754
1755 /* Queue device install (will be dequeued by DeviceInstallThread */
1756 len = FIELD_OFFSET(DeviceInstallParams, DeviceIds)
1757 + wcslen(PnpEvent->TargetDevice.DeviceIds) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
1758 Params = HeapAlloc(GetProcessHeap(), 0, len);
1759 if (Params)
1760 {
1761 wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
1762 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
1763 InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry);
1764 #else
1765 InsertTailList(&DeviceInstallListHead, &Params->ListEntry);
1766 #endif
1767 SetEvent(hDeviceInstallListNotEmpty);
1768 }
1769 }
1770 else
1771 {
1772 DPRINT1("Unknown event\n");
1773 }
1774
1775 /* Dequeue the current pnp event and signal the next one */
1776 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
1777 }
1778
1779 HeapFree(GetProcessHeap(), 0, PnpEvent);
1780
1781 return ERROR_SUCCESS;
1782 }
1783
1784
1785 static VOID CALLBACK
1786 ServiceMain(DWORD argc, LPTSTR *argv)
1787 {
1788 HANDLE hThread;
1789 DWORD dwThreadId;
1790
1791 UNREFERENCED_PARAMETER(argc);
1792 UNREFERENCED_PARAMETER(argv);
1793
1794 DPRINT("ServiceMain() called\n");
1795
1796 hNoPendingInstalls = CreateEventW(NULL,
1797 TRUE,
1798 FALSE,
1799 L"Global\\PnP_No_Pending_Install_Events");
1800
1801 hThread = CreateThread(NULL,
1802 0,
1803 PnpEventThread,
1804 NULL,
1805 0,
1806 &dwThreadId);
1807 if (hThread != NULL)
1808 CloseHandle(hThread);
1809
1810 hThread = CreateThread(NULL,
1811 0,
1812 DeviceInstallThread,
1813 NULL,
1814 0,
1815 &dwThreadId);
1816 if (hThread != NULL)
1817 CloseHandle(hThread);
1818
1819 hThread = CreateThread(NULL,
1820 0,
1821 RpcServerThread,
1822 NULL,
1823 0,
1824 &dwThreadId);
1825 if (hThread != NULL)
1826 CloseHandle(hThread);
1827
1828 DPRINT("ServiceMain() done\n");
1829 }
1830
1831
1832 int
1833 main(int argc, char *argv[])
1834 {
1835 DWORD dwError;
1836
1837 UNREFERENCED_PARAMETER(argc);
1838 UNREFERENCED_PARAMETER(argv);
1839
1840 DPRINT("Umpnpmgr: main() started\n");
1841
1842 hInstallEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1843 if (hInstallEvent == NULL)
1844 {
1845 dwError = GetLastError();
1846 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
1847 return dwError;
1848 }
1849
1850 hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL);
1851 if (hDeviceInstallListNotEmpty == NULL)
1852 {
1853 dwError = GetLastError();
1854 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
1855 return dwError;
1856 }
1857
1858 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
1859 InitializeSListHead(&DeviceInstallListHead);
1860 #else
1861 InitializeListHead(&DeviceInstallListHead);
1862 #endif
1863
1864 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1865 L"System\\CurrentControlSet\\Enum",
1866 0,
1867 KEY_ALL_ACCESS,
1868 &hEnumKey);
1869 if (dwError != ERROR_SUCCESS)
1870 {
1871 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
1872 return dwError;
1873 }
1874
1875 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1876 L"System\\CurrentControlSet\\Control\\Class",
1877 0,
1878 KEY_ALL_ACCESS,
1879 &hClassKey);
1880 if (dwError != ERROR_SUCCESS)
1881 {
1882 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
1883 return dwError;
1884 }
1885
1886 StartServiceCtrlDispatcher(ServiceTable);
1887
1888 DPRINT("Umpnpmgr: main() done\n");
1889
1890 ExitThread(0);
1891
1892 return 0;
1893 }
1894
1895 /* EOF */