Make the prototypes match those defined in the .idl files
[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 unsigned long Admin,
198 unsigned long ProcessId)
199 {
200 HANDLE hProcess;
201
202 UNREFERENCED_PARAMETER(BindingHandle);
203
204 DPRINT1("PNP_ReportLogOn(%lu, %lu) 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 unsigned long 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 unsigned long 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 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 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 unsigned long Branch,
347 unsigned long Index,
348 wchar_t *Buffer,
349 unsigned long Length,
350 unsigned long *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 unsigned long Property,
462 unsigned long *DataType,
463 char *Buffer,
464 unsigned long *TransferLen,
465 unsigned long *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 unsigned long Action,
1320 wchar_t *DeviceId,
1321 unsigned long ProfileId,
1322 unsigned long *Value, // out
1323 unsigned long 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 SetupIsActive)
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 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1498 DeviceInstance);
1499 PlugPlayData.Operation = 0; /* Get status */
1500
1501 /* Get device status */
1502 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1503 (PVOID)&PlugPlayData,
1504 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1505 if (!NT_SUCCESS(Status))
1506 return FALSE;
1507
1508 if ((PlugPlayData.DeviceStatus & (DNF_STARTED | DNF_START_FAILED)) != 0)
1509 /* Device is already started, or disabled due to some problem. Don't install it */
1510 return TRUE;
1511
1512 /* Install device */
1513 SetEnvironmentVariableW(L"USERPROFILE", L"."); /* FIXME: why is it needed? */
1514
1515 hNewDev = LoadLibraryW(L"newdev.dll");
1516 if (!hNewDev)
1517 goto cleanup;
1518
1519 DevInstallW = (PDEV_INSTALL_W)GetProcAddress(hNewDev, (LPCSTR)"DevInstallW");
1520 if (!DevInstallW)
1521 goto cleanup;
1522
1523 if (!DevInstallW(NULL, NULL, DeviceInstance, SetupIsActive ? SW_HIDE : SW_SHOWNOACTIVATE))
1524 goto cleanup;
1525
1526 DeviceInstalled = TRUE;
1527
1528 cleanup:
1529 if (hNewDev != NULL)
1530 FreeLibrary(hNewDev);
1531
1532 return DeviceInstalled;
1533 }
1534
1535
1536 static BOOL
1537 SetupIsActive(VOID)
1538 {
1539 HKEY hKey = NULL;
1540 DWORD regType, active, size;
1541 LONG rc;
1542 BOOL ret = FALSE;
1543
1544 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
1545 if (rc != ERROR_SUCCESS)
1546 goto cleanup;
1547
1548 size = sizeof(DWORD);
1549 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
1550 if (rc != ERROR_SUCCESS)
1551 goto cleanup;
1552 if (regType != REG_DWORD || size != sizeof(DWORD))
1553 goto cleanup;
1554
1555 ret = (active != 0);
1556
1557 cleanup:
1558 if (hKey != NULL)
1559 RegCloseKey(hKey);
1560
1561 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
1562
1563 return ret;
1564 }
1565
1566
1567 /* Loop to install all queued devices installations */
1568 static DWORD WINAPI
1569 DeviceInstallThread(LPVOID lpParameter)
1570 {
1571 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
1572 PSLIST_ENTRY ListEntry;
1573 #else
1574 PLIST_ENTRY ListEntry;
1575 #endif
1576 DeviceInstallParams* Params;
1577 BOOL setupActive;
1578
1579 UNREFERENCED_PARAMETER(lpParameter);
1580
1581 setupActive = SetupIsActive();
1582
1583 SetEnvironmentVariable(L"USERPROFILE", L"."); /* FIXME: why is it needed? */
1584
1585 while (TRUE)
1586 {
1587 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
1588 ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead);
1589 #else
1590 if ((BOOL)IsListEmpty(&DeviceInstallListHead))
1591 ListEntry = NULL;
1592 else
1593 ListEntry = RemoveHeadList(&DeviceInstallListHead);
1594 #endif
1595 if (ListEntry == NULL)
1596 {
1597 SetEvent(hNoPendingInstalls);
1598 WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE);
1599 }
1600 else
1601 {
1602 ResetEvent(hNoPendingInstalls);
1603 Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry);
1604 InstallDevice(Params->DeviceIds, setupActive);
1605 }
1606 }
1607
1608 return 0;
1609 }
1610
1611
1612 static DWORD WINAPI
1613 PnpEventThread(LPVOID lpParameter)
1614 {
1615 PPLUGPLAY_EVENT_BLOCK PnpEvent;
1616 ULONG PnpEventSize;
1617 NTSTATUS Status;
1618 RPC_STATUS RpcStatus;
1619
1620 UNREFERENCED_PARAMETER(lpParameter);
1621
1622 PnpEventSize = 0x1000;
1623 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
1624 if (PnpEvent == NULL)
1625 return ERROR_OUTOFMEMORY;
1626
1627 for (;;)
1628 {
1629 DPRINT("Calling NtGetPlugPlayEvent()\n");
1630
1631 /* Wait for the next pnp event */
1632 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
1633
1634 /* Resize the buffer for the PnP event if it's too small. */
1635 if (Status == STATUS_BUFFER_TOO_SMALL)
1636 {
1637 PnpEventSize += 0x400;
1638 PnpEvent = HeapReAlloc(GetProcessHeap(), 0, PnpEvent, PnpEventSize);
1639 if (PnpEvent == NULL)
1640 return ERROR_OUTOFMEMORY;
1641 continue;
1642 }
1643
1644 if (!NT_SUCCESS(Status))
1645 {
1646 DPRINT("NtPlugPlayEvent() failed (Status %lx)\n", Status);
1647 break;
1648 }
1649
1650 /* Process the pnp event */
1651 DPRINT("Received PnP Event\n");
1652 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
1653 {
1654 DeviceInstallParams* Params;
1655 DWORD len;
1656
1657 DPRINT("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds);
1658
1659 /* Queue device install (will be dequeued by DeviceInstallThread */
1660 len = FIELD_OFFSET(DeviceInstallParams, DeviceIds)
1661 + wcslen(PnpEvent->TargetDevice.DeviceIds) * sizeof(WCHAR) + sizeof(UNICODE_NULL);
1662 Params = HeapAlloc(GetProcessHeap(), 0, len);
1663 if (Params)
1664 {
1665 wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
1666 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
1667 InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry);
1668 #else
1669 InsertTailList(&DeviceInstallListHead, &Params->ListEntry);
1670 #endif
1671 SetEvent(hDeviceInstallListNotEmpty);
1672 }
1673 }
1674 else
1675 {
1676 DPRINT1("Unknown event\n");
1677 }
1678
1679 /* Dequeue the current pnp event and signal the next one */
1680 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
1681 }
1682
1683 HeapFree(GetProcessHeap(), 0, PnpEvent);
1684
1685 return ERROR_SUCCESS;
1686 }
1687
1688
1689 static VOID CALLBACK
1690 ServiceMain(DWORD argc, LPTSTR *argv)
1691 {
1692 HANDLE hThread;
1693 DWORD dwThreadId;
1694
1695 UNREFERENCED_PARAMETER(argc);
1696 UNREFERENCED_PARAMETER(argv);
1697
1698 DPRINT("ServiceMain() called\n");
1699
1700 hNoPendingInstalls = CreateEventW(NULL,
1701 TRUE,
1702 FALSE,
1703 L"Global\\PnP_No_Pending_Install_Events");
1704
1705 hThread = CreateThread(NULL,
1706 0,
1707 PnpEventThread,
1708 NULL,
1709 0,
1710 &dwThreadId);
1711 if (hThread != NULL)
1712 CloseHandle(hThread);
1713
1714 hThread = CreateThread(NULL,
1715 0,
1716 DeviceInstallThread,
1717 NULL,
1718 0,
1719 &dwThreadId);
1720 if (hThread != NULL)
1721 CloseHandle(hThread);
1722
1723 hThread = CreateThread(NULL,
1724 0,
1725 RpcServerThread,
1726 NULL,
1727 0,
1728 &dwThreadId);
1729 if (hThread != NULL)
1730 CloseHandle(hThread);
1731
1732 DPRINT("ServiceMain() done\n");
1733 }
1734
1735
1736 int
1737 main(int argc, char *argv[])
1738 {
1739 DWORD dwError;
1740
1741 UNREFERENCED_PARAMETER(argc);
1742 UNREFERENCED_PARAMETER(argv);
1743
1744 DPRINT("Umpnpmgr: main() started\n");
1745
1746 hInstallEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
1747 if (hInstallEvent == NULL)
1748 {
1749 dwError = GetLastError();
1750 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
1751 return dwError;
1752 }
1753
1754 hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL);
1755 if (hDeviceInstallListNotEmpty == NULL)
1756 {
1757 dwError = GetLastError();
1758 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
1759 return dwError;
1760 }
1761
1762 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
1763 InitializeSListHead(&DeviceInstallListHead);
1764 #else
1765 InitializeListHead(&DeviceInstallListHead);
1766 #endif
1767
1768 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1769 L"System\\CurrentControlSet\\Enum",
1770 0,
1771 KEY_ALL_ACCESS,
1772 &hEnumKey);
1773 if (dwError != ERROR_SUCCESS)
1774 {
1775 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
1776 return dwError;
1777 }
1778
1779 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1780 L"System\\CurrentControlSet\\Control\\Class",
1781 0,
1782 KEY_ALL_ACCESS,
1783 &hClassKey);
1784 if (dwError != ERROR_SUCCESS)
1785 {
1786 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
1787 return dwError;
1788 }
1789
1790 StartServiceCtrlDispatcher(ServiceTable);
1791
1792 DPRINT("Umpnpmgr: main() done\n");
1793
1794 ExitThread(0);
1795
1796 return 0;
1797 }
1798
1799 /* EOF */