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