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