Merge freeldr from amd64 branch:
[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 #include <regstr.h>
39
40 #include <rpc.h>
41 #include <rpcdce.h>
42
43 #include "pnp_s.h"
44
45 #define NDEBUG
46 #include <debug.h>
47
48 /* GLOBALS ******************************************************************/
49
50 static VOID CALLBACK
51 ServiceMain(DWORD argc, LPTSTR *argv);
52
53 static SERVICE_TABLE_ENTRY ServiceTable[2] =
54 {
55 {TEXT("PlugPlay"), ServiceMain},
56 {NULL, NULL}
57 };
58
59 static WCHAR szRootDeviceId[] = L"HTREE\\ROOT\\0";
60
61 static HKEY hEnumKey = NULL;
62 static HKEY hClassKey = NULL;
63
64 static HANDLE hUserToken = NULL;
65 static HANDLE hInstallEvent = NULL;
66 static HANDLE hNoPendingInstalls = NULL;
67
68 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
69 static SLIST_HEADER DeviceInstallListHead;
70 #else
71 static LIST_ENTRY DeviceInstallListHead;
72 #endif
73 static HANDLE hDeviceInstallListNotEmpty;
74
75 typedef struct
76 {
77 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
78 SLIST_ENTRY ListEntry;
79 #else
80 LIST_ENTRY ListEntry;
81 #endif
82 WCHAR DeviceIds[1];
83 } DeviceInstallParams;
84
85 /* FUNCTIONS *****************************************************************/
86
87 static DWORD WINAPI
88 RpcServerThread(LPVOID lpParameter)
89 {
90 RPC_STATUS Status;
91
92 UNREFERENCED_PARAMETER(lpParameter);
93
94 DPRINT("RpcServerThread() called\n");
95
96 Status = RpcServerUseProtseqEpW(L"ncacn_np",
97 20,
98 L"\\pipe\\umpnpmgr",
99 NULL); // Security descriptor
100 if (Status != RPC_S_OK)
101 {
102 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
103 return 0;
104 }
105
106 Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec,
107 NULL,
108 NULL);
109 if (Status != RPC_S_OK)
110 {
111 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
112 return 0;
113 }
114
115 Status = RpcServerListen(1,
116 20,
117 FALSE);
118 if (Status != RPC_S_OK)
119 {
120 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
121 return 0;
122 }
123
124 /* ROS HACK (this should never happen...) */
125 DPRINT1("*** Other devices won't be installed correctly. If something\n");
126 DPRINT1("*** doesn't work, try to reboot to get a new chance.\n");
127
128 DPRINT("RpcServerThread() done\n");
129
130 return 0;
131 }
132
133
134 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
135 {
136 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
137 }
138
139
140 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
141 {
142 HeapFree(GetProcessHeap(), 0, ptr);
143 }
144
145
146 static CONFIGRET WINAPI
147 NtStatusToCrError(NTSTATUS Status)
148 {
149 switch (Status)
150 {
151 case STATUS_NO_SUCH_DEVICE:
152 return CR_NO_SUCH_DEVINST;
153
154 default:
155 /* FIXME: add more mappings */
156 DPRINT1("Unable to map status 0x%08lx\n", Status);
157 return CR_FAILURE;
158 }
159 }
160
161
162 /* Function 0 */
163 DWORD PNP_Disconnect(
164 handle_t hBinding)
165 {
166 UNREFERENCED_PARAMETER(hBinding);
167 UNIMPLEMENTED;
168 return CR_CALL_NOT_IMPLEMENTED;
169 }
170
171
172 /* Function 1 */
173 DWORD PNP_Connect(
174 handle_t hBinding)
175 {
176 UNREFERENCED_PARAMETER(hBinding);
177 UNIMPLEMENTED;
178 return CR_CALL_NOT_IMPLEMENTED;
179 }
180
181
182 /* Function 2 */
183 DWORD PNP_GetVersion(
184 handle_t hBinding,
185 WORD *pVersion)
186 {
187 UNREFERENCED_PARAMETER(hBinding);
188
189 *pVersion = 0x0400;
190 return CR_SUCCESS;
191 }
192
193
194 /* Function 3 */
195 DWORD PNP_GetGlobalState(
196 handle_t hBinding,
197 DWORD *pulState,
198 DWORD ulFlags)
199 {
200 UNREFERENCED_PARAMETER(hBinding);
201 UNREFERENCED_PARAMETER(ulFlags);
202
203 *pulState = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE;
204 return CR_SUCCESS;
205 }
206
207
208 /* Function 4 */
209 DWORD PNP_InitDetection(
210 handle_t hBinding)
211 {
212 UNREFERENCED_PARAMETER(hBinding);
213
214 DPRINT("PNP_InitDetection() called\n");
215 return CR_SUCCESS;
216 }
217
218
219 /* Function 5 */
220 DWORD PNP_ReportLogOn(
221 handle_t hBinding,
222 BOOL Admin,
223 DWORD ProcessId)
224 {
225 HANDLE hProcess;
226
227 UNREFERENCED_PARAMETER(hBinding);
228 UNREFERENCED_PARAMETER(Admin);
229
230 DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin, ProcessId);
231
232 if (hInstallEvent != NULL)
233 SetEvent(hInstallEvent);
234
235 /* Get the users token */
236 hProcess = OpenProcess(PROCESS_ALL_ACCESS,
237 TRUE,
238 ProcessId);
239 if (hProcess != NULL)
240 {
241 if (hUserToken != NULL)
242 {
243 CloseHandle(hUserToken);
244 hUserToken = NULL;
245 }
246
247 OpenProcessToken(hProcess,
248 TOKEN_ALL_ACCESS,
249 &hUserToken);
250 CloseHandle(hProcess);
251 }
252
253 /* Trigger the installer thread */
254 /*if (hInstallEvent != NULL)
255 SetEvent(hInstallEvent);*/
256
257 return CR_SUCCESS;
258 }
259
260
261 /* Function 6 */
262 DWORD PNP_ValidateDeviceInstance(
263 handle_t hBinding,
264 LPWSTR pDeviceID,
265 DWORD ulFlags)
266 {
267 CONFIGRET ret = CR_SUCCESS;
268 HKEY hDeviceKey = NULL;
269
270 UNREFERENCED_PARAMETER(hBinding);
271 UNREFERENCED_PARAMETER(ulFlags);
272
273 DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
274 pDeviceID, ulFlags);
275
276 if (RegOpenKeyExW(hEnumKey,
277 pDeviceID,
278 0,
279 KEY_READ,
280 &hDeviceKey))
281 {
282 DPRINT("Could not open the Device Key!\n");
283 ret = CR_NO_SUCH_DEVNODE;
284 goto Done;
285 }
286
287 /* FIXME: add more tests */
288
289 Done:
290 if (hDeviceKey != NULL)
291 RegCloseKey(hDeviceKey);
292
293 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret);
294
295 return ret;
296 }
297
298
299 /* Function 7 */
300 DWORD PNP_GetRootDeviceInstance(
301 handle_t hBinding,
302 LPWSTR pDeviceID,
303 PNP_RPC_STRING_LEN ulLength)
304 {
305 CONFIGRET ret = CR_SUCCESS;
306
307 UNREFERENCED_PARAMETER(hBinding);
308
309 DPRINT("PNP_GetRootDeviceInstance() called\n");
310
311 if (!pDeviceID)
312 {
313 ret = CR_INVALID_POINTER;
314 goto Done;
315 }
316 if (ulLength < lstrlenW(szRootDeviceId) + 1)
317 {
318 ret = CR_BUFFER_SMALL;
319 goto Done;
320 }
321
322 lstrcpyW(pDeviceID,
323 szRootDeviceId);
324
325 Done:
326 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret);
327
328 return ret;
329 }
330
331
332 /* Function 8 */
333 DWORD PNP_GetRelatedDeviceInstance(
334 handle_t hBinding,
335 DWORD ulRelationship,
336 LPWSTR pDeviceID,
337 LPWSTR pRelatedDeviceId,
338 PNP_RPC_STRING_LEN *pulLength,
339 DWORD ulFlags)
340 {
341 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData;
342 CONFIGRET ret = CR_SUCCESS;
343 NTSTATUS Status;
344
345 UNREFERENCED_PARAMETER(hBinding);
346 UNREFERENCED_PARAMETER(ulFlags);
347
348 DPRINT("PNP_GetRelatedDeviceInstance() called\n");
349 DPRINT(" Relationship %ld\n", ulRelationship);
350 DPRINT(" DeviceId %S\n", pDeviceID);
351
352 RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance,
353 pDeviceID);
354
355 PlugPlayData.Relation = ulRelationship;
356
357 PlugPlayData.RelatedDeviceInstanceLength = *pulLength;
358 PlugPlayData.RelatedDeviceInstance = pRelatedDeviceId;
359
360 Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice,
361 (PVOID)&PlugPlayData,
362 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA));
363 if (!NT_SUCCESS(Status))
364 {
365 ret = NtStatusToCrError(Status);
366 }
367
368 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret);
369 if (ret == CR_SUCCESS)
370 {
371 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance);
372 }
373
374 return ret;
375 }
376
377
378 /* Function 9 */
379 DWORD PNP_EnumerateSubKeys(
380 handle_t hBinding,
381 DWORD ulBranch,
382 DWORD ulIndex,
383 LPWSTR Buffer,
384 PNP_RPC_STRING_LEN ulLength,
385 PNP_RPC_STRING_LEN *pulRequiredLen,
386 DWORD ulFlags)
387 {
388 CONFIGRET ret = CR_SUCCESS;
389 HKEY hKey;
390 DWORD dwError;
391
392 UNREFERENCED_PARAMETER(hBinding);
393 UNREFERENCED_PARAMETER(ulFlags);
394
395 DPRINT("PNP_EnumerateSubKeys() called\n");
396
397 switch (ulBranch)
398 {
399 case PNP_ENUMERATOR_SUBKEYS:
400 hKey = hEnumKey;
401 break;
402
403 case PNP_CLASS_SUBKEYS:
404 hKey = hClassKey;
405 break;
406
407 default:
408 return CR_FAILURE;
409 }
410
411 *pulRequiredLen = ulLength;
412 dwError = RegEnumKeyExW(hKey,
413 ulIndex,
414 Buffer,
415 pulRequiredLen,
416 NULL,
417 NULL,
418 NULL,
419 NULL);
420 if (dwError != ERROR_SUCCESS)
421 {
422 ret = (dwError == ERROR_NO_MORE_ITEMS) ? CR_NO_SUCH_VALUE : CR_FAILURE;
423 }
424 else
425 {
426 (*pulRequiredLen)++;
427 }
428
429 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret);
430
431 return ret;
432 }
433
434
435 /* Function 10 */
436 DWORD PNP_GetDeviceList(
437 handle_t hBinding,
438 LPWSTR pszFilter,
439 LPWSTR Buffer,
440 PNP_RPC_STRING_LEN *pulLength,
441 DWORD ulFlags)
442 {
443 UNIMPLEMENTED;
444 return CR_CALL_NOT_IMPLEMENTED;
445 }
446
447
448 /* Function 11 */
449 DWORD PNP_GetDeviceListSize(
450 handle_t hBinding,
451 LPWSTR pszFilter,
452 PNP_RPC_BUFFER_SIZE *pulLen,
453 DWORD ulFlags)
454 {
455 UNIMPLEMENTED;
456 return CR_CALL_NOT_IMPLEMENTED;
457 }
458
459
460 /* Function 12 */
461 DWORD PNP_GetDepth(
462 handle_t hBinding,
463 LPWSTR pszDeviceID,
464 DWORD *pulDepth,
465 DWORD ulFlags)
466 {
467 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData;
468 CONFIGRET ret = CR_SUCCESS;
469 NTSTATUS Status;
470
471 UNREFERENCED_PARAMETER(hBinding);
472 UNREFERENCED_PARAMETER(ulFlags);
473
474 DPRINT("PNP_GetDepth() called\n");
475
476 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
477 pszDeviceID);
478
479 Status = NtPlugPlayControl(PlugPlayControlGetDeviceDepth,
480 (PVOID)&PlugPlayData,
481 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA));
482 if (NT_SUCCESS(Status))
483 {
484 *pulDepth = PlugPlayData.Depth;
485 }
486 else
487 {
488 ret = NtStatusToCrError(Status);
489 }
490
491 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret);
492
493 return ret;
494 }
495
496
497 /* Function 13 */
498 DWORD PNP_GetDeviceRegProp(
499 handle_t hBinding,
500 LPWSTR pDeviceID,
501 DWORD ulProperty,
502 DWORD *pulRegDataType,
503 BYTE *Buffer,
504 PNP_PROP_SIZE *pulTransferLen,
505 PNP_PROP_SIZE *pulLength,
506 DWORD ulFlags)
507 {
508 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData;
509 CONFIGRET ret = CR_SUCCESS;
510 LPWSTR lpValueName = NULL;
511 HKEY hKey = 0;
512 NTSTATUS Status;
513
514 UNREFERENCED_PARAMETER(hBinding);
515 UNREFERENCED_PARAMETER(ulFlags);
516
517 DPRINT("PNP_GetDeviceRegProp() called\n");
518
519 switch (ulProperty)
520 {
521 case CM_DRP_DEVICEDESC:
522 lpValueName = L"DeviceDesc";
523 break;
524
525 case CM_DRP_HARDWAREID:
526 lpValueName = L"HardwareID";
527 break;
528
529 case CM_DRP_COMPATIBLEIDS:
530 lpValueName = L"CompatibleIDs";
531 break;
532
533 case CM_DRP_SERVICE:
534 lpValueName = L"Service";
535 break;
536
537 case CM_DRP_CLASS:
538 lpValueName = L"Class";
539 break;
540
541 case CM_DRP_CLASSGUID:
542 lpValueName = L"ClassGUID";
543 break;
544
545 case CM_DRP_DRIVER:
546 lpValueName = L"Driver";
547 break;
548
549 case CM_DRP_CONFIGFLAGS:
550 lpValueName = L"ConfigFlags";
551 break;
552
553 case CM_DRP_MFG:
554 lpValueName = L"Mfg";
555 break;
556
557 case CM_DRP_FRIENDLYNAME:
558 lpValueName = L"FriendlyName";
559 break;
560
561 case CM_DRP_LOCATION_INFORMATION:
562 lpValueName = L"LocationInformation";
563 break;
564
565 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
566 lpValueName = NULL;
567 break;
568
569 case CM_DRP_CAPABILITIES:
570 lpValueName = L"Capabilities";
571 break;
572
573 case CM_DRP_UI_NUMBER:
574 lpValueName = NULL;
575 break;
576
577 case CM_DRP_UPPERFILTERS:
578 lpValueName = L"UpperFilters";
579 break;
580
581 case CM_DRP_LOWERFILTERS:
582 lpValueName = L"LowerFilters";
583 break;
584
585 case CM_DRP_BUSTYPEGUID:
586 lpValueName = NULL;
587 break;
588
589 case CM_DRP_LEGACYBUSTYPE:
590 lpValueName = NULL;
591 break;
592
593 case CM_DRP_BUSNUMBER:
594 lpValueName = NULL;
595 break;
596
597 case CM_DRP_ENUMERATOR_NAME:
598 lpValueName = NULL;
599 break;
600
601 default:
602 return CR_INVALID_PROPERTY;
603 }
604
605 DPRINT("Value name: %S\n", lpValueName);
606
607 if (lpValueName)
608 {
609 /* Retrieve information from the Registry */
610 if (RegOpenKeyExW(hEnumKey,
611 pDeviceID,
612 0,
613 KEY_ALL_ACCESS,
614 &hKey))
615 return CR_INVALID_DEVNODE;
616
617 if (RegQueryValueExW(hKey,
618 lpValueName,
619 NULL,
620 pulRegDataType,
621 Buffer,
622 pulLength))
623 ret = CR_REGISTRY_ERROR;
624
625 /* FIXME: Check buffer size */
626
627 RegCloseKey(hKey);
628 }
629 else
630 {
631 /* Retrieve information from the Device Node */
632 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
633 pDeviceID);
634 PlugPlayData.Buffer = Buffer;
635 PlugPlayData.BufferSize = *pulTransferLen;
636
637 switch (ulProperty)
638 {
639 #if 0
640 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
641 PlugPlayData.Property = DevicePropertyPhysicalDeviceObjectName;
642 break;
643
644 case CM_DRP_UI_NUMBER:
645 PlugPlayData.Property = DevicePropertyUINumber;
646 break;
647
648 case CM_DRP_BUSTYPEGUID:
649 PlugPlayData.Property = DevicePropertyBusTypeGuid;
650 break;
651
652 case CM_DRP_LEGACYBUSTYPE:
653 PlugPlayData.Property = DevicePropertyLegacyBusType;
654 break;
655
656 case CM_DRP_BUSNUMBER:
657 PlugPlayData.Property = DevicePropertyBusNumber;
658 break;
659
660 case CM_DRP_ENUMERATOR_NAME:
661 PlugPlayData.Property = DevicePropertyEnumeratorName;
662 break;
663 #endif
664
665 default:
666 return CR_INVALID_PROPERTY;
667 }
668
669 Status = NtPlugPlayControl(PlugPlayControlProperty,
670 (PVOID)&PlugPlayData,
671 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA));
672 if (NT_SUCCESS(Status))
673 {
674 *pulLength = PlugPlayData.BufferSize;
675 }
676 else
677 {
678 ret = NtStatusToCrError(Status);
679 }
680 }
681
682 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret);
683
684 return ret;
685 }
686
687
688 /* Function 14 */
689 DWORD PNP_SetDeviceRegProp(
690 handle_t hBinding,
691 LPWSTR pDeviceId,
692 DWORD ulProperty,
693 DWORD ulDataType,
694 BYTE *Buffer,
695 PNP_PROP_SIZE ulLength,
696 DWORD ulFlags)
697 {
698 CONFIGRET ret = CR_SUCCESS;
699 LPWSTR lpValueName = NULL;
700 HKEY hKey = 0;
701
702 UNREFERENCED_PARAMETER(hBinding);
703 UNREFERENCED_PARAMETER(ulFlags);
704
705 DPRINT("PNP_SetDeviceRegProp() called\n");
706
707 DPRINT("DeviceId: %S\n", pDeviceId);
708 DPRINT("Property: %lu\n", ulProperty);
709 DPRINT("DataType: %lu\n", ulDataType);
710 DPRINT("Length: %lu\n", ulLength);
711
712 switch (ulProperty)
713 {
714 case CM_DRP_DEVICEDESC:
715 lpValueName = L"DeviceDesc";
716 break;
717
718 case CM_DRP_HARDWAREID:
719 lpValueName = L"HardwareID";
720 break;
721
722 case CM_DRP_COMPATIBLEIDS:
723 lpValueName = L"CompatibleIDs";
724 break;
725
726 case CM_DRP_SERVICE:
727 lpValueName = L"Service";
728 break;
729
730 case CM_DRP_CLASS:
731 lpValueName = L"Class";
732 break;
733
734 case CM_DRP_CLASSGUID:
735 lpValueName = L"ClassGUID";
736 break;
737
738 case CM_DRP_DRIVER:
739 lpValueName = L"Driver";
740 break;
741
742 case CM_DRP_CONFIGFLAGS:
743 lpValueName = L"ConfigFlags";
744 break;
745
746 case CM_DRP_MFG:
747 lpValueName = L"Mfg";
748 break;
749
750 case CM_DRP_FRIENDLYNAME:
751 lpValueName = L"FriendlyName";
752 break;
753
754 case CM_DRP_LOCATION_INFORMATION:
755 lpValueName = L"LocationInformation";
756 break;
757
758 case CM_DRP_UPPERFILTERS:
759 lpValueName = L"UpperFilters";
760 break;
761
762 case CM_DRP_LOWERFILTERS:
763 lpValueName = L"LowerFilters";
764 break;
765
766 default:
767 return CR_INVALID_PROPERTY;
768 }
769
770 DPRINT("Value name: %S\n", lpValueName);
771
772 if (RegOpenKeyExW(hEnumKey,
773 pDeviceId,
774 0,
775 KEY_ALL_ACCESS, /* FIXME: so much? */
776 &hKey))
777 return CR_INVALID_DEVNODE;
778
779 if (ulLength == 0)
780 {
781 if (RegDeleteValueW(hKey,
782 lpValueName))
783 ret = CR_REGISTRY_ERROR;
784 }
785 else
786 {
787 if (RegSetValueExW(hKey,
788 lpValueName,
789 0,
790 ulDataType,
791 Buffer,
792 ulLength))
793 ret = CR_REGISTRY_ERROR;
794 }
795
796 RegCloseKey(hKey);
797
798 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret);
799
800 return ret;
801 }
802
803
804 /* Function 15 */
805 DWORD PNP_GetClassInstance(
806 handle_t hBinding,
807 LPWSTR pDeviceId,
808 LPWSTR pszClassInstance,
809 PNP_RPC_STRING_LEN ulLength)
810 {
811 UNIMPLEMENTED;
812 return CR_CALL_NOT_IMPLEMENTED;
813 }
814
815
816 /* Function 16 */
817 DWORD PNP_CreateKey(
818 handle_t hBinding,
819 LPWSTR pszSubKey,
820 DWORD samDesired,
821 DWORD ulFlags)
822 {
823 UNIMPLEMENTED;
824 return CR_CALL_NOT_IMPLEMENTED;
825 }
826
827
828 /* Function 17 */
829 DWORD PNP_DeleteRegistryKey(
830 handle_t hBinding,
831 LPWSTR pszDeviceID,
832 LPWSTR pszParentKey,
833 LPWSTR pszChildKey,
834 DWORD ulFlags)
835 {
836 UNIMPLEMENTED;
837 return CR_CALL_NOT_IMPLEMENTED;
838 }
839
840
841 /* Function 18 */
842 DWORD PNP_GetClassCount(
843 handle_t hBinding,
844 DWORD *pulClassCount,
845 DWORD ulFlags)
846 {
847 HKEY hKey;
848 DWORD dwError;
849
850 UNREFERENCED_PARAMETER(hBinding);
851 UNREFERENCED_PARAMETER(ulFlags);
852
853 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
854 REGSTR_PATH_CLASS,
855 0,
856 KEY_QUERY_VALUE,
857 &hKey);
858 if (dwError != ERROR_SUCCESS)
859 return CR_INVALID_DATA;
860
861 dwError = RegQueryInfoKeyW(hKey,
862 NULL,
863 NULL,
864 NULL,
865 pulClassCount,
866 NULL,
867 NULL,
868 NULL,
869 NULL,
870 NULL,
871 NULL,
872 NULL);
873 RegCloseKey(hKey);
874 if (dwError != ERROR_SUCCESS)
875 return CR_INVALID_DATA;
876
877 return CR_SUCCESS;
878 }
879
880
881 /* Function 19 */
882 DWORD PNP_GetClassName(
883 handle_t hBinding,
884 LPWSTR pszClassGuid,
885 LPWSTR Buffer,
886 PNP_RPC_STRING_LEN *pulLength,
887 DWORD ulFlags)
888 {
889 WCHAR szKeyName[MAX_PATH];
890 CONFIGRET ret = CR_SUCCESS;
891 HKEY hKey;
892 DWORD dwSize;
893
894 UNREFERENCED_PARAMETER(hBinding);
895 UNREFERENCED_PARAMETER(ulFlags);
896
897 DPRINT("PNP_GetClassName() called\n");
898
899 lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\");
900 if(lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR)))
901 lstrcatW(szKeyName, pszClassGuid);
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 = *pulLength * sizeof(WCHAR);
912 if (RegQueryValueExW(hKey,
913 L"Class",
914 NULL,
915 NULL,
916 (LPBYTE)Buffer,
917 &dwSize))
918 {
919 *pulLength = 0;
920 ret = CR_REGISTRY_ERROR;
921 }
922 else
923 {
924 *pulLength = 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 DWORD PNP_DeleteClassKey(
937 handle_t hBinding,
938 LPWSTR pszClassGuid,
939 DWORD ulFlags)
940 {
941 CONFIGRET ret = CR_SUCCESS;
942
943 UNREFERENCED_PARAMETER(hBinding);
944
945 DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid, ulFlags);
946
947 if (ulFlags & CM_DELETE_CLASS_SUBKEYS)
948 {
949 if (RegDeleteTreeW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
950 ret = CR_REGISTRY_ERROR;
951 }
952 else
953 {
954 if (RegDeleteKeyW(hClassKey, pszClassGuid) != 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 21 */
965 DWORD PNP_GetInterfaceDeviceAlias(
966 handle_t hBinding,
967 LPWSTR pszInterfaceDevice,
968 GUID *AliasInterfaceGuid,
969 LPWSTR pszAliasInterfaceDevice,
970 PNP_RPC_STRING_LEN *pulLength,
971 PNP_RPC_STRING_LEN *pulTransferLen,
972 DWORD ulFlags)
973 {
974 UNIMPLEMENTED;
975 return CR_CALL_NOT_IMPLEMENTED;
976 }
977
978
979 /* Function 22 */
980 DWORD PNP_GetInterfaceDeviceList(
981 handle_t hBinding,
982 GUID *InterfaceGuid,
983 LPWSTR pszDeviceID,
984 BYTE *Buffer,
985 PNP_RPC_BUFFER_SIZE *pulLength,
986 DWORD ulFlags)
987 {
988 UNIMPLEMENTED;
989 return CR_CALL_NOT_IMPLEMENTED;
990 }
991
992
993 /* Function 23 */
994 DWORD PNP_GetInterfaceDeviceListSize(
995 handle_t hBinding,
996 PNP_RPC_BUFFER_SIZE *pulLen,
997 GUID *InterfaceGuid,
998 LPWSTR pszDeviceID,
999 DWORD ulFlags)
1000 {
1001 UNIMPLEMENTED;
1002 return CR_CALL_NOT_IMPLEMENTED;
1003 }
1004
1005
1006 /* Function 24 */
1007 DWORD PNP_RegisterDeviceClassAssociation(
1008 handle_t hBinding,
1009 LPWSTR pszDeviceID,
1010 GUID *InterfaceGuid,
1011 LPWSTR pszReference,
1012 LPWSTR pszSymLink,
1013 PNP_RPC_STRING_LEN *pulLength,
1014 PNP_RPC_STRING_LEN *pulTransferLen,
1015 DWORD ulFlags)
1016 {
1017 UNIMPLEMENTED;
1018 return CR_CALL_NOT_IMPLEMENTED;
1019 }
1020
1021
1022 /* Function 25 */
1023 DWORD PNP_UnregisterDeviceClassAssociation(
1024 handle_t hBinding,
1025 LPWSTR pszInterfaceDevice,
1026 DWORD ulFlags)
1027 {
1028 UNIMPLEMENTED;
1029 return CR_CALL_NOT_IMPLEMENTED;
1030 }
1031
1032
1033 /* Function 26 */
1034 DWORD PNP_GetClassRegProp(
1035 handle_t hBinding,
1036 LPWSTR pszClassGuid,
1037 DWORD ulProperty,
1038 DWORD *pulRegDataType,
1039 BYTE *Buffer,
1040 PNP_RPC_STRING_LEN *pulTransferLen,
1041 PNP_RPC_STRING_LEN *pulLength,
1042 DWORD ulFlags)
1043 {
1044 UNIMPLEMENTED;
1045 return CR_CALL_NOT_IMPLEMENTED;
1046 }
1047
1048
1049 /* Function 27 */
1050 DWORD PNP_SetClassRegProp(
1051 handle_t hBinding,
1052 LPWSTR *pszClassGuid,
1053 DWORD ulProperty,
1054 DWORD ulDataType,
1055 BYTE *Buffer,
1056 PNP_PROP_SIZE ulLength,
1057 DWORD ulFlags)
1058 {
1059 UNIMPLEMENTED;
1060 return CR_CALL_NOT_IMPLEMENTED;
1061 }
1062
1063
1064 /* Function 28 */
1065 DWORD PNP_CreateDevInst(
1066 handle_t hBinding,
1067 LPWSTR pszDeviceID,
1068 LPWSTR pszParentDeviceID,
1069 PNP_RPC_STRING_LEN ulLength,
1070 DWORD ulFlags)
1071 {
1072 UNIMPLEMENTED;
1073 return CR_CALL_NOT_IMPLEMENTED;
1074 }
1075
1076
1077 /* Function 29 */
1078 #define PNP_DEVINST_SETUP 0x3
1079 #define PNP_DEVINST_ENABLE 0x4
1080 #define PNP_DEVINST_REENUMERATE 0x7
1081 DWORD PNP_DeviceInstanceAction(
1082 handle_t hBinding,
1083 DWORD ulMajorAction,
1084 DWORD ulMinorAction,
1085 LPWSTR pszDeviceInstance1,
1086 LPWSTR pszDeviceInstance2)
1087 {
1088 CONFIGRET ret = CR_SUCCESS;
1089
1090 UNREFERENCED_PARAMETER(hBinding);
1091 UNREFERENCED_PARAMETER(ulMinorAction);
1092 UNREFERENCED_PARAMETER(pszDeviceInstance1);
1093 UNREFERENCED_PARAMETER(pszDeviceInstance2);
1094
1095 DPRINT("PNP_DeviceInstanceAction() called\n");
1096
1097 switch (ulMajorAction)
1098 {
1099 case PNP_DEVINST_SETUP:
1100 DPRINT("Setup device instance\n");
1101 /* FIXME */
1102 ret = CR_CALL_NOT_IMPLEMENTED;
1103 break;
1104
1105 case PNP_DEVINST_ENABLE:
1106 DPRINT("Enable device instance\n");
1107 /* FIXME */
1108 ret = CR_CALL_NOT_IMPLEMENTED;
1109 break;
1110
1111 case PNP_DEVINST_REENUMERATE:
1112 DPRINT("Reenumerate device instance\n");
1113 /* FIXME */
1114 ret = CR_CALL_NOT_IMPLEMENTED;
1115 break;
1116
1117 default:
1118 DPRINT1("Unknown function %lu\n", ulMajorAction);
1119 ret = CR_CALL_NOT_IMPLEMENTED;
1120 }
1121
1122 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
1123
1124 return ret;
1125 }
1126
1127
1128 /* Function 30 */
1129 DWORD PNP_GetDeviceStatus(
1130 handle_t hBinding,
1131 LPWSTR pDeviceID,
1132 DWORD *pulStatus,
1133 DWORD *pulProblem,
1134 DWORD ulFlags)
1135 {
1136 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1137 CONFIGRET ret = CR_SUCCESS;
1138 NTSTATUS Status;
1139
1140 UNREFERENCED_PARAMETER(hBinding);
1141 UNREFERENCED_PARAMETER(ulFlags);
1142
1143 DPRINT("PNP_GetDeviceStatus() called\n");
1144
1145 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1146 pDeviceID);
1147 PlugPlayData.Operation = 0; /* Get status */
1148
1149 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1150 (PVOID)&PlugPlayData,
1151 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1152 if (NT_SUCCESS(Status))
1153 {
1154 *pulStatus = PlugPlayData.DeviceStatus;
1155 *pulProblem = PlugPlayData.DeviceProblem;
1156 }
1157 else
1158 {
1159 ret = NtStatusToCrError(Status);
1160 }
1161
1162 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret);
1163
1164 return ret;
1165 }
1166
1167
1168 /* Function 31 */
1169 DWORD PNP_SetDeviceProblem(
1170 handle_t hBinding,
1171 LPWSTR pDeviceID,
1172 DWORD ulProblem,
1173 DWORD ulFlags)
1174 {
1175 UNIMPLEMENTED;
1176 return CR_CALL_NOT_IMPLEMENTED;
1177 }
1178
1179
1180 /* Function 32 */
1181 DWORD PNP_DisableDevInst(
1182 handle_t hBinding,
1183 LPWSTR pDeviceID,
1184 PPNP_VETO_TYPE pVetoType,
1185 LPWSTR pszVetoName,
1186 DWORD ulNameLength,
1187 DWORD ulFlags)
1188 {
1189 UNIMPLEMENTED;
1190 return CR_CALL_NOT_IMPLEMENTED;
1191 }
1192
1193 /* Function 33 */
1194 DWORD PNP_UninstallDevInst(
1195 handle_t hBinding,
1196 LPWSTR pDeviceID,
1197 DWORD ulFlags)
1198 {
1199 UNIMPLEMENTED;
1200 return CR_CALL_NOT_IMPLEMENTED;
1201 }
1202
1203
1204 static BOOL
1205 CheckForDeviceId(LPWSTR lpDeviceIdList,
1206 LPWSTR lpDeviceId)
1207 {
1208 LPWSTR lpPtr;
1209 DWORD dwLength;
1210
1211 lpPtr = lpDeviceIdList;
1212 while (*lpPtr != 0)
1213 {
1214 dwLength = wcslen(lpPtr);
1215 if (0 == _wcsicmp(lpPtr, lpDeviceId))
1216 return TRUE;
1217
1218 lpPtr += (dwLength + 1);
1219 }
1220
1221 return FALSE;
1222 }
1223
1224
1225 static VOID
1226 AppendDeviceId(LPWSTR lpDeviceIdList,
1227 LPDWORD lpDeviceIdListSize,
1228 LPWSTR lpDeviceId)
1229 {
1230 DWORD dwLen;
1231 DWORD dwPos;
1232
1233 dwLen = wcslen(lpDeviceId);
1234 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
1235
1236 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
1237
1238 dwPos += (dwLen + 1);
1239
1240 lpDeviceIdList[dwPos] = 0;
1241
1242 *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
1243 }
1244
1245
1246 /* Function 34 */
1247 DWORD PNP_AddID(
1248 handle_t hBinding,
1249 LPWSTR pszDeviceID,
1250 LPWSTR pszID,
1251 DWORD ulFlags)
1252 {
1253 CONFIGRET ret = CR_SUCCESS;
1254 HKEY hDeviceKey;
1255 LPWSTR pszSubKey;
1256 DWORD dwDeviceIdListSize;
1257 DWORD dwNewDeviceIdSize;
1258 WCHAR * pszDeviceIdList = NULL;
1259
1260 UNREFERENCED_PARAMETER(hBinding);
1261
1262 DPRINT("PNP_AddID() called\n");
1263 DPRINT(" DeviceInstance: %S\n", pszDeviceID);
1264 DPRINT(" DeviceId: %S\n", pszID);
1265 DPRINT(" Flags: %lx\n", ulFlags);
1266
1267 if (RegOpenKeyExW(hEnumKey,
1268 pszDeviceID,
1269 0,
1270 KEY_QUERY_VALUE | KEY_SET_VALUE,
1271 &hDeviceKey) != ERROR_SUCCESS)
1272 {
1273 DPRINT("Failed to open the device key!\n");
1274 return CR_INVALID_DEVNODE;
1275 }
1276
1277 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
1278
1279 if (RegQueryValueExW(hDeviceKey,
1280 pszSubKey,
1281 NULL,
1282 NULL,
1283 NULL,
1284 &dwDeviceIdListSize) != ERROR_SUCCESS)
1285 {
1286 DPRINT("Failed to query the desired ID string!\n");
1287 ret = CR_REGISTRY_ERROR;
1288 goto Done;
1289 }
1290
1291 dwNewDeviceIdSize = lstrlenW(pszDeviceID);
1292 if (!dwNewDeviceIdSize)
1293 {
1294 ret = CR_INVALID_POINTER;
1295 goto Done;
1296 }
1297
1298 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR);
1299
1300 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize);
1301 if (!pszDeviceIdList)
1302 {
1303 DPRINT("Failed to allocate memory for the desired ID string!\n");
1304 ret = CR_OUT_OF_MEMORY;
1305 goto Done;
1306 }
1307
1308 if (RegQueryValueExW(hDeviceKey,
1309 pszSubKey,
1310 NULL,
1311 NULL,
1312 (LPBYTE)pszDeviceIdList,
1313 &dwDeviceIdListSize) != ERROR_SUCCESS)
1314 {
1315 DPRINT("Failed to query the desired ID string!\n");
1316 ret = CR_REGISTRY_ERROR;
1317 goto Done;
1318 }
1319
1320 /* Check whether the device ID is already in use */
1321 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID))
1322 {
1323 DPRINT("Device ID was found in the ID string!\n");
1324 ret = CR_SUCCESS;
1325 goto Done;
1326 }
1327
1328 /* Append the Device ID */
1329 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID);
1330
1331 if (RegSetValueExW(hDeviceKey,
1332 pszSubKey,
1333 0,
1334 REG_MULTI_SZ,
1335 (LPBYTE)pszDeviceIdList,
1336 dwDeviceIdListSize) != ERROR_SUCCESS)
1337 {
1338 DPRINT("Failed to set the desired ID string!\n");
1339 ret = CR_REGISTRY_ERROR;
1340 }
1341
1342 Done:
1343 RegCloseKey(hDeviceKey);
1344 if (pszDeviceIdList)
1345 HeapFree(GetProcessHeap(), 0, pszDeviceIdList);
1346
1347 DPRINT("PNP_AddID() done (returns %lx)\n", ret);
1348
1349 return ret;
1350 }
1351
1352
1353 /* Function 35 */
1354 DWORD PNP_RegisterDriver(
1355 handle_t hBinding,
1356 LPWSTR pszDeviceID,
1357 DWORD ulFlags)
1358 {
1359 UNIMPLEMENTED;
1360 return CR_CALL_NOT_IMPLEMENTED;
1361 }
1362
1363
1364 /* Function 36 */
1365 DWORD PNP_QueryRemove(
1366 handle_t hBinding,
1367 LPWSTR pszDeviceID,
1368 PPNP_VETO_TYPE pVetoType,
1369 LPWSTR pszVetoName,
1370 DWORD ulNameLength,
1371 DWORD ulFlags)
1372 {
1373 UNIMPLEMENTED;
1374 return CR_CALL_NOT_IMPLEMENTED;
1375 }
1376
1377
1378 /* Function 37 */
1379 DWORD PNP_RequestDeviceEject(
1380 handle_t hBinding,
1381 LPWSTR pszDeviceID,
1382 PPNP_VETO_TYPE pVetoType,
1383 LPWSTR pszVetoName,
1384 DWORD ulNameLength,
1385 DWORD ulFlags)
1386 {
1387 UNIMPLEMENTED;
1388 return CR_CALL_NOT_IMPLEMENTED;
1389 }
1390
1391 /* Function 38 */
1392 CONFIGRET
1393 PNP_IsDockStationPresent(handle_t hBinding,
1394 BOOL *Present)
1395 {
1396 HKEY hKey;
1397 DWORD dwType;
1398 DWORD dwValue;
1399 DWORD dwSize;
1400 CONFIGRET ret = CR_SUCCESS;
1401
1402 UNREFERENCED_PARAMETER(hBinding);
1403
1404 DPRINT1("PNP_IsDockStationPresent() called\n");
1405
1406 *Present = FALSE;
1407
1408 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
1409 L"CurrentDockInfo",
1410 0,
1411 KEY_READ,
1412 &hKey) != ERROR_SUCCESS)
1413 return CR_REGISTRY_ERROR;
1414
1415 dwSize = sizeof(DWORD);
1416 if (RegQueryValueExW(hKey,
1417 L"DockingState",
1418 NULL,
1419 &dwType,
1420 (LPBYTE)&dwValue,
1421 &dwSize) != ERROR_SUCCESS)
1422 ret = CR_REGISTRY_ERROR;
1423
1424 RegCloseKey(hKey);
1425
1426 if (ret == CR_SUCCESS)
1427 {
1428 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
1429 {
1430 ret = CR_REGISTRY_ERROR;
1431 }
1432 else if (dwValue != 0)
1433 {
1434 *Present = TRUE;
1435 }
1436 }
1437
1438 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
1439
1440 return ret;
1441 }
1442
1443
1444 /* Function 39 */
1445 DWORD PNP_RequestEjectPC(
1446 handle_t hBinding)
1447 {
1448 UNIMPLEMENTED;
1449 return CR_CALL_NOT_IMPLEMENTED;
1450 }
1451
1452
1453 /* Function 40 */
1454 DWORD PNP_HwProfFlags(
1455 handle_t hBinding,
1456 DWORD ulAction,
1457 LPWSTR pDeviceID,
1458 DWORD ulConfig,
1459 DWORD *pulValue,
1460 PPNP_VETO_TYPE pVetoType,
1461 LPWSTR pszVetoName,
1462 DWORD ulNameLength,
1463 DWORD ulFlags)
1464 {
1465 UNIMPLEMENTED;
1466 return CR_CALL_NOT_IMPLEMENTED;
1467 }
1468
1469
1470 /* Function 41 */
1471 DWORD PNP_GetHwProfInfo(
1472 handle_t hBinding,
1473 DWORD ulIndex,
1474 HWPROFILEINFO *pHWProfileInfo,
1475 DWORD ulProfileInfoSize,
1476 DWORD ulFlags)
1477 {
1478 UNIMPLEMENTED;
1479 return CR_CALL_NOT_IMPLEMENTED;
1480 }
1481
1482
1483 /* Function 42 */
1484 DWORD PNP_AddEmptyLogConf(
1485 handle_t hBinding,
1486 LPWSTR pDeviceID,
1487 DWORD ulPriority,
1488 DWORD *pulLogConfTag,
1489 DWORD ulFlags)
1490 {
1491 UNIMPLEMENTED;
1492 return CR_CALL_NOT_IMPLEMENTED;
1493 }
1494
1495
1496 /* Function 43 */
1497 DWORD PNP_FreeLogConf(
1498 handle_t hBinding,
1499 LPWSTR pDeviceID,
1500 DWORD ulLogConfType,
1501 DWORD ulLogConfTag,
1502 DWORD ulFlags)
1503 {
1504 UNIMPLEMENTED;
1505 return CR_CALL_NOT_IMPLEMENTED;
1506 }
1507
1508
1509 /* Function 44 */
1510 DWORD PNP_GetFirstLogConf(
1511 handle_t hBinding,
1512 LPWSTR pDeviceID,
1513 DWORD ulLogConfType,
1514 DWORD *pulLogConfTag,
1515 DWORD ulFlags)
1516 {
1517 UNIMPLEMENTED;
1518 return CR_CALL_NOT_IMPLEMENTED;
1519 }
1520
1521
1522 /* Function 45 */
1523 DWORD PNP_GetNextLogConf(
1524 handle_t hBinding,
1525 LPWSTR pDeviceID,
1526 DWORD ulLogConfType,
1527 DWORD ulCurrentTag,
1528 DWORD *pulNextTag,
1529 DWORD ulFlags)
1530 {
1531 UNIMPLEMENTED;
1532 return CR_CALL_NOT_IMPLEMENTED;
1533 }
1534
1535
1536 /* Function 46 */
1537 DWORD PNP_GetLogConfPriority(
1538 handle_t hBinding,
1539 LPWSTR pDeviceID,
1540 DWORD ulType,
1541 DWORD ulTag,
1542 DWORD *pPriority,
1543 DWORD ulFlags)
1544 {
1545 UNIMPLEMENTED;
1546 return CR_CALL_NOT_IMPLEMENTED;
1547 }
1548
1549
1550 /* Function 47 */
1551 DWORD PNP_AddResDes(
1552 handle_t hBinding,
1553 LPWSTR pDeviceID,
1554 DWORD ulLogConfTag,
1555 DWORD ulLogConfType,
1556 RESOURCEID ResourceID,
1557 DWORD *pulResourceTag,
1558 BYTE *ResourceData,
1559 PNP_RPC_BUFFER_SIZE ResourceLen,
1560 DWORD ulFlags)
1561 {
1562 UNIMPLEMENTED;
1563 return CR_CALL_NOT_IMPLEMENTED;
1564 }
1565
1566
1567 /* Function 48 */
1568 DWORD PNP_FreeResDes(
1569 handle_t hBinding,
1570 LPWSTR pDeviceID,
1571 DWORD ulLogConfTag,
1572 DWORD ulLogConfType,
1573 RESOURCEID ResourceID,
1574 DWORD ulResourceTag,
1575 DWORD *pulPreviousResType,
1576 DWORD *pulPreviousResTag,
1577 DWORD ulFlags)
1578 {
1579 UNIMPLEMENTED;
1580 return CR_CALL_NOT_IMPLEMENTED;
1581 }
1582
1583
1584 /* Function 49 */
1585 DWORD PNP_GetNextResDes(
1586 handle_t hBinding,
1587 LPWSTR pDeviceID,
1588 DWORD ulLogConfTag,
1589 DWORD ulLogConfType,
1590 RESOURCEID ResourceID,
1591 DWORD ulResourceTag,
1592 DWORD *pulNextResType,
1593 DWORD *pulNextResTag,
1594 DWORD ulFlags)
1595 {
1596 UNIMPLEMENTED;
1597 return CR_CALL_NOT_IMPLEMENTED;
1598 }
1599
1600
1601 /* Function 50 */
1602 DWORD PNP_GetResDesData(
1603 handle_t hBinding,
1604 LPWSTR pDeviceID,
1605 DWORD ulLogConfTag,
1606 DWORD ulLogConfType,
1607 RESOURCEID ResourceID,
1608 DWORD ulResourceTag,
1609 BYTE *Buffer,
1610 PNP_RPC_BUFFER_SIZE BufferLen,
1611 DWORD ulFlags)
1612 {
1613 UNIMPLEMENTED;
1614 return CR_CALL_NOT_IMPLEMENTED;
1615 }
1616
1617
1618 /* Function 51 */
1619 DWORD PNP_GetResDesDataSize(
1620 handle_t hBinding,
1621 LPWSTR pDeviceID,
1622 DWORD ulLogConfTag,
1623 DWORD ulLogConfType,
1624 RESOURCEID ResourceID,
1625 DWORD ulResourceTag,
1626 DWORD *pulSize,
1627 DWORD ulFlags)
1628 {
1629 UNIMPLEMENTED;
1630 return CR_CALL_NOT_IMPLEMENTED;
1631 }
1632
1633
1634 /* Function 52 */
1635 DWORD PNP_ModifyResDes(
1636 handle_t hBinding,
1637 LPWSTR pDeviceID,
1638 DWORD ulLogConfTag,
1639 DWORD ulLogConfType,
1640 RESOURCEID CurrentResourceID,
1641 RESOURCEID NewResourceID,
1642 DWORD ulResourceTag,
1643 BYTE *ResourceData,
1644 PNP_RPC_BUFFER_SIZE ResourceLen,
1645 DWORD ulFlags)
1646 {
1647 UNIMPLEMENTED;
1648 return CR_CALL_NOT_IMPLEMENTED;
1649 }
1650
1651
1652 /* Function 53 */
1653 DWORD PNP_DetectResourceConflict(
1654 handle_t hBinding,
1655 LPWSTR pDeviceID,
1656 RESOURCEID ResourceID,
1657 BYTE *ResourceData,
1658 PNP_RPC_BUFFER_SIZE ResourceLen,
1659 BOOL *pbConflictDetected,
1660 DWORD ulFlags)
1661 {
1662 UNIMPLEMENTED;
1663 return CR_CALL_NOT_IMPLEMENTED;
1664 }
1665
1666
1667 /* Function 54 */
1668 DWORD PNP_QueryResConfList(
1669 handle_t hBinding,
1670 LPWSTR pDeviceID,
1671 RESOURCEID ResourceID,
1672 BYTE *ResourceData,
1673 PNP_RPC_BUFFER_SIZE ResourceLen,
1674 BYTE *Buffer,
1675 PNP_RPC_BUFFER_SIZE BufferLen,
1676 DWORD ulFlags)
1677 {
1678 UNIMPLEMENTED;
1679 return CR_CALL_NOT_IMPLEMENTED;
1680 }
1681
1682
1683 /* Function 55 */
1684 DWORD PNP_SetHwProf(
1685 handle_t hBinding)
1686 {
1687 UNIMPLEMENTED;
1688 return CR_CALL_NOT_IMPLEMENTED;
1689 }
1690
1691
1692 /* Function 56 */
1693 DWORD PNP_QueryArbitratorFreeData(
1694 handle_t hBinding)
1695 {
1696 UNIMPLEMENTED;
1697 return CR_CALL_NOT_IMPLEMENTED;
1698 }
1699
1700
1701 /* Function 57 */
1702 DWORD PNP_QueryArbitratorFreeSize(
1703 handle_t hBinding)
1704 {
1705 UNIMPLEMENTED;
1706 return CR_CALL_NOT_IMPLEMENTED;
1707 }
1708
1709
1710 /* Function 58 */
1711 CONFIGRET
1712 PNP_RunDetection(
1713 handle_t hBinding,
1714 DWORD ulFlags)
1715 {
1716 UNIMPLEMENTED;
1717 return CR_CALL_NOT_IMPLEMENTED;
1718 }
1719
1720
1721 /* Function 59 */
1722 DWORD PNP_RegisterNotification(
1723 handle_t hBinding)
1724 {
1725 UNIMPLEMENTED;
1726 return CR_CALL_NOT_IMPLEMENTED;
1727 }
1728
1729
1730 /* Function 60 */
1731 DWORD PNP_UnregisterNotification(
1732 handle_t hBinding)
1733 {
1734 UNIMPLEMENTED;
1735 return CR_CALL_NOT_IMPLEMENTED;
1736 }
1737
1738
1739 /* Function 61 */
1740 DWORD PNP_GetCustomDevProp(
1741 handle_t hBinding,
1742 LPWSTR pDeviceID,
1743 LPWSTR CustomPropName,
1744 DWORD *pulRegDataType,
1745 BYTE *Buffer,
1746 PNP_RPC_STRING_LEN *pulTransferLen,
1747 PNP_RPC_STRING_LEN *pulLength,
1748 DWORD ulFlags)
1749 {
1750 UNIMPLEMENTED;
1751 return CR_CALL_NOT_IMPLEMENTED;
1752 }
1753
1754
1755 /* Function 62 */
1756 DWORD PNP_GetVersionInternal(
1757 handle_t hBinding,
1758 WORD *pwVersion)
1759 {
1760 UNIMPLEMENTED;
1761 return CR_CALL_NOT_IMPLEMENTED;
1762 }
1763
1764
1765 /* Function 63 */
1766 DWORD PNP_GetBlockedDriverInfo(
1767 handle_t hBinding,
1768 BYTE *Buffer,
1769 PNP_RPC_BUFFER_SIZE *pulTransferLen,
1770 PNP_RPC_BUFFER_SIZE *pulLength,
1771 DWORD ulFlags)
1772 {
1773 UNIMPLEMENTED;
1774 return CR_CALL_NOT_IMPLEMENTED;
1775 }
1776
1777
1778 /* Function 64 */
1779 DWORD PNP_GetServerSideDeviceInstallFlags(
1780 handle_t hBinding,
1781 DWORD *pulSSDIFlags,
1782 DWORD ulFlags)
1783 {
1784 UNIMPLEMENTED;
1785 return CR_CALL_NOT_IMPLEMENTED;
1786 }
1787
1788
1789 /* Function 65 */
1790 DWORD PNP_GetObjectPropKeys(
1791 handle_t hBinding,
1792 LPWSTR ObjectName,
1793 DWORD ObjectType,
1794 LPWSTR PropertyCultureName,
1795 PNP_PROP_COUNT *PropertyCount,
1796 PNP_PROP_COUNT *TransferLen,
1797 DEVPROPKEY *PropertyKeys,
1798 DWORD Flags)
1799 {
1800 UNIMPLEMENTED;
1801 return CR_CALL_NOT_IMPLEMENTED;
1802 }
1803
1804
1805 /* Function 66 */
1806 DWORD PNP_GetObjectProp(
1807 handle_t hBinding,
1808 LPWSTR ObjectName,
1809 DWORD ObjectType,
1810 LPWSTR PropertyCultureName,
1811 const DEVPROPKEY *PropertyKey,
1812 DEVPROPTYPE *PropertyType,
1813 PNP_PROP_SIZE *PropertySize,
1814 PNP_PROP_SIZE *TransferLen,
1815 BYTE *PropertyBuffer,
1816 DWORD Flags)
1817 {
1818 UNIMPLEMENTED;
1819 return CR_CALL_NOT_IMPLEMENTED;
1820 }
1821
1822
1823 /* Function 67 */
1824 DWORD PNP_SetObjectProp(
1825 handle_t hBinding,
1826 LPWSTR ObjectName,
1827 DWORD ObjectType,
1828 LPWSTR PropertyCultureName,
1829 const DEVPROPKEY *PropertyKey,
1830 DEVPROPTYPE PropertyType,
1831 PNP_PROP_SIZE PropertySize,
1832 BYTE *PropertyBuffer,
1833 DWORD Flags)
1834 {
1835 UNIMPLEMENTED;
1836 return CR_CALL_NOT_IMPLEMENTED;
1837 }
1838
1839
1840 /* Function 68 */
1841 DWORD PNP_InstallDevInst(
1842 handle_t hBinding)
1843 {
1844 UNIMPLEMENTED;
1845 return CR_CALL_NOT_IMPLEMENTED;
1846 }
1847
1848
1849 /* Function 69 */
1850 DWORD PNP_ApplyPowerSettings(
1851 handle_t hBinding)
1852 {
1853 UNIMPLEMENTED;
1854 return CR_CALL_NOT_IMPLEMENTED;
1855 }
1856
1857
1858 /* Function 70 */
1859 DWORD PNP_DriverStoreAddDriverPackage(
1860 handle_t hBinding)
1861 {
1862 UNIMPLEMENTED;
1863 return CR_CALL_NOT_IMPLEMENTED;
1864 }
1865
1866
1867 /* Function 71 */
1868 DWORD PNP_DriverStoreDeleteDriverPackage(
1869 handle_t hBinding)
1870 {
1871 UNIMPLEMENTED;
1872 return CR_CALL_NOT_IMPLEMENTED;
1873 }
1874
1875
1876 /* Function 72 */
1877 DWORD PNP_RegisterServiceNotification(
1878 handle_t hBinding)
1879 {
1880 UNIMPLEMENTED;
1881 return CR_CALL_NOT_IMPLEMENTED;
1882 }
1883
1884
1885 /* Function 73 */
1886 DWORD PNP_SetActiveService(
1887 handle_t hBinding)
1888 {
1889 UNIMPLEMENTED;
1890 return CR_CALL_NOT_IMPLEMENTED;
1891 }
1892
1893
1894 /* Function 74 */
1895 DWORD PNP_DeleteServiceDevices(
1896 handle_t hBinding)
1897 {
1898 UNIMPLEMENTED;
1899 return CR_CALL_NOT_IMPLEMENTED;
1900 }
1901
1902
1903 typedef BOOL (WINAPI *PDEV_INSTALL_W)(HWND, HINSTANCE, LPCWSTR, INT);
1904
1905 static BOOL
1906 InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
1907 {
1908 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1909 HMODULE hNewDev = NULL;
1910 PDEV_INSTALL_W DevInstallW;
1911 NTSTATUS Status;
1912 BOOL DeviceInstalled = FALSE;
1913
1914 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance, ShowWizard);
1915
1916 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1917 DeviceInstance);
1918 PlugPlayData.Operation = 0; /* Get status */
1919
1920 /* Get device status */
1921 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1922 (PVOID)&PlugPlayData,
1923 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1924 if (!NT_SUCCESS(Status))
1925 {
1926 DPRINT1("NtPlugPlayControl('%S') failed with status 0x%08lx\n", DeviceInstance, Status);
1927 return FALSE;
1928 }
1929
1930 if ((PlugPlayData.DeviceStatus & (DNF_STARTED | DNF_START_FAILED)) != 0)
1931 {
1932 /* Device is already started, or disabled due to some problem. Don't install it */
1933 DPRINT("No need to install '%S'\n", DeviceInstance);
1934 return TRUE;
1935 }
1936
1937 /* Install device */
1938 SetEnvironmentVariableW(L"USERPROFILE", L"."); /* FIXME: why is it needed? */
1939
1940 hNewDev = LoadLibraryW(L"newdev.dll");
1941 if (!hNewDev)
1942 {
1943 DPRINT1("Unable to load newdev.dll\n");
1944 goto cleanup;
1945 }
1946
1947 DevInstallW = (PDEV_INSTALL_W)GetProcAddress(hNewDev, (LPCSTR)"DevInstallW");
1948 if (!DevInstallW)
1949 {
1950 DPRINT1("'DevInstallW' not found in newdev.dll\n");
1951 goto cleanup;
1952 }
1953
1954 if (!DevInstallW(NULL, NULL, DeviceInstance, ShowWizard ? SW_SHOWNOACTIVATE : SW_HIDE))
1955 {
1956 DPRINT1("DevInstallW('%S') failed\n", DeviceInstance);
1957 goto cleanup;
1958 }
1959
1960 DeviceInstalled = TRUE;
1961
1962 cleanup:
1963 if (hNewDev != NULL)
1964 FreeLibrary(hNewDev);
1965
1966 return DeviceInstalled;
1967 }
1968
1969
1970 static LONG
1971 ReadRegSzKey(
1972 IN HKEY hKey,
1973 IN LPCWSTR pszKey,
1974 OUT LPWSTR* pValue)
1975 {
1976 LONG rc;
1977 DWORD dwType;
1978 DWORD cbData = 0;
1979 LPWSTR Value;
1980
1981 if (!pValue)
1982 return ERROR_INVALID_PARAMETER;
1983
1984 *pValue = NULL;
1985 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
1986 if (rc != ERROR_SUCCESS)
1987 return rc;
1988 if (dwType != REG_SZ)
1989 return ERROR_FILE_NOT_FOUND;
1990 Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
1991 if (!Value)
1992 return ERROR_NOT_ENOUGH_MEMORY;
1993 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
1994 if (rc != ERROR_SUCCESS)
1995 {
1996 HeapFree(GetProcessHeap(), 0, Value);
1997 return rc;
1998 }
1999 /* NULL-terminate the string */
2000 Value[cbData / sizeof(WCHAR)] = '\0';
2001
2002 *pValue = Value;
2003 return ERROR_SUCCESS;
2004 }
2005
2006
2007 static BOOL
2008 SetupIsActive(VOID)
2009 {
2010 HKEY hKey = NULL;
2011 DWORD regType, active, size;
2012 LONG rc;
2013 BOOL ret = FALSE;
2014
2015 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
2016 if (rc != ERROR_SUCCESS)
2017 goto cleanup;
2018
2019 size = sizeof(DWORD);
2020 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
2021 if (rc != ERROR_SUCCESS)
2022 goto cleanup;
2023 if (regType != REG_DWORD || size != sizeof(DWORD))
2024 goto cleanup;
2025
2026 ret = (active != 0);
2027
2028 cleanup:
2029 if (hKey != NULL)
2030 RegCloseKey(hKey);
2031
2032 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
2033
2034 return ret;
2035 }
2036
2037
2038 static BOOL
2039 IsConsoleBoot(VOID)
2040 {
2041 HKEY ControlKey = NULL;
2042 LPWSTR SystemStartOptions = NULL;
2043 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
2044 BOOL ConsoleBoot = FALSE;
2045 LONG rc;
2046
2047 rc = RegOpenKeyExW(
2048 HKEY_LOCAL_MACHINE,
2049 L"SYSTEM\\CurrentControlSet\\Control",
2050 0,
2051 KEY_QUERY_VALUE,
2052 &ControlKey);
2053
2054 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
2055 if (rc != ERROR_SUCCESS)
2056 goto cleanup;
2057
2058 /* Check for CMDCONS in SystemStartOptions */
2059 CurrentOption = SystemStartOptions;
2060 while (CurrentOption)
2061 {
2062 NextOption = wcschr(CurrentOption, L' ');
2063 if (NextOption)
2064 *NextOption = L'\0';
2065 if (_wcsicmp(CurrentOption, L"CONSOLE") == 0)
2066 {
2067 DPRINT("Found %S. Switching to console boot\n", CurrentOption);
2068 ConsoleBoot = TRUE;
2069 goto cleanup;
2070 }
2071 CurrentOption = NextOption ? NextOption + 1 : NULL;
2072 }
2073
2074 cleanup:
2075 if (ControlKey != NULL)
2076 RegCloseKey(ControlKey);
2077 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
2078 return ConsoleBoot;
2079 }
2080
2081
2082 /* Loop to install all queued devices installations */
2083 static DWORD WINAPI
2084 DeviceInstallThread(LPVOID lpParameter)
2085 {
2086 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2087 PSLIST_ENTRY ListEntry;
2088 #else
2089 PLIST_ENTRY ListEntry;
2090 #endif
2091 DeviceInstallParams* Params;
2092 BOOL showWizard;
2093
2094 UNREFERENCED_PARAMETER(lpParameter);
2095
2096 WaitForSingleObject(hInstallEvent, INFINITE);
2097
2098 showWizard = !SetupIsActive() && !IsConsoleBoot();
2099
2100 while (TRUE)
2101 {
2102 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2103 ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead);
2104 #else
2105 if ((BOOL)IsListEmpty(&DeviceInstallListHead))
2106 ListEntry = NULL;
2107 else
2108 ListEntry = RemoveHeadList(&DeviceInstallListHead);
2109 #endif
2110 if (ListEntry == NULL)
2111 {
2112 SetEvent(hNoPendingInstalls);
2113 WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE);
2114 }
2115 else
2116 {
2117 ResetEvent(hNoPendingInstalls);
2118 Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry);
2119 InstallDevice(Params->DeviceIds, showWizard);
2120 }
2121 }
2122
2123 return 0;
2124 }
2125
2126
2127 static DWORD WINAPI
2128 PnpEventThread(LPVOID lpParameter)
2129 {
2130 PPLUGPLAY_EVENT_BLOCK PnpEvent;
2131 ULONG PnpEventSize;
2132 NTSTATUS Status;
2133 RPC_STATUS RpcStatus;
2134
2135 UNREFERENCED_PARAMETER(lpParameter);
2136
2137 PnpEventSize = 0x1000;
2138 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
2139 if (PnpEvent == NULL)
2140 return ERROR_OUTOFMEMORY;
2141
2142 for (;;)
2143 {
2144 DPRINT("Calling NtGetPlugPlayEvent()\n");
2145
2146 /* Wait for the next pnp event */
2147 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
2148
2149 /* Resize the buffer for the PnP event if it's too small. */
2150 if (Status == STATUS_BUFFER_TOO_SMALL)
2151 {
2152 PnpEventSize += 0x400;
2153 HeapFree(GetProcessHeap(), 0, PnpEvent);
2154 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
2155 if (PnpEvent == NULL)
2156 return ERROR_OUTOFMEMORY;
2157 continue;
2158 }
2159
2160 if (!NT_SUCCESS(Status))
2161 {
2162 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status);
2163 break;
2164 }
2165
2166 /* Process the pnp event */
2167 DPRINT("Received PnP Event\n");
2168 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ENUMERATED, &RpcStatus))
2169 {
2170 DeviceInstallParams* Params;
2171 DWORD len;
2172 DWORD DeviceIdLength;
2173
2174 DPRINT("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds);
2175
2176 DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds);
2177 if (DeviceIdLength)
2178 {
2179 /* Queue device install (will be dequeued by DeviceInstallThread */
2180 len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
2181 Params = HeapAlloc(GetProcessHeap(), 0, len);
2182 if (Params)
2183 {
2184 wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
2185 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2186 InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry);
2187 #else
2188 InsertTailList(&DeviceInstallListHead, &Params->ListEntry);
2189 #endif
2190 SetEvent(hDeviceInstallListNotEmpty);
2191 }
2192 }
2193 }
2194 else
2195 {
2196 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
2197 PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
2198 PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
2199 PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
2200 PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
2201 }
2202
2203 /* Dequeue the current pnp event and signal the next one */
2204 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
2205 }
2206
2207 HeapFree(GetProcessHeap(), 0, PnpEvent);
2208
2209 return ERROR_SUCCESS;
2210 }
2211
2212
2213 static VOID CALLBACK
2214 ServiceMain(DWORD argc, LPTSTR *argv)
2215 {
2216 HANDLE hThread;
2217 DWORD dwThreadId;
2218
2219 UNREFERENCED_PARAMETER(argc);
2220 UNREFERENCED_PARAMETER(argv);
2221
2222 DPRINT("ServiceMain() called\n");
2223
2224 hThread = CreateThread(NULL,
2225 0,
2226 PnpEventThread,
2227 NULL,
2228 0,
2229 &dwThreadId);
2230 if (hThread != NULL)
2231 CloseHandle(hThread);
2232
2233 hThread = CreateThread(NULL,
2234 0,
2235 RpcServerThread,
2236 NULL,
2237 0,
2238 &dwThreadId);
2239 if (hThread != NULL)
2240 CloseHandle(hThread);
2241
2242 hThread = CreateThread(NULL,
2243 0,
2244 DeviceInstallThread,
2245 NULL,
2246 0,
2247 &dwThreadId);
2248 if (hThread != NULL)
2249 CloseHandle(hThread);
2250
2251 DPRINT("ServiceMain() done\n");
2252 }
2253
2254
2255 int
2256 wmain(int argc, WCHAR *argv[])
2257 {
2258 DWORD dwError;
2259
2260 UNREFERENCED_PARAMETER(argc);
2261 UNREFERENCED_PARAMETER(argv);
2262
2263 DPRINT("Umpnpmgr: main() started\n");
2264
2265 hInstallEvent = CreateEvent(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
2266 if (hInstallEvent == NULL)
2267 {
2268 dwError = GetLastError();
2269 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
2270 return dwError;
2271 }
2272
2273 hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL);
2274 if (hDeviceInstallListNotEmpty == NULL)
2275 {
2276 dwError = GetLastError();
2277 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
2278 return dwError;
2279 }
2280
2281 hNoPendingInstalls = CreateEventW(NULL,
2282 TRUE,
2283 FALSE,
2284 L"Global\\PnP_No_Pending_Install_Events");
2285 if (hNoPendingInstalls == NULL)
2286 {
2287 dwError = GetLastError();
2288 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
2289 return dwError;
2290 }
2291
2292 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2293 InitializeSListHead(&DeviceInstallListHead);
2294 #else
2295 InitializeListHead(&DeviceInstallListHead);
2296 #endif
2297
2298 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2299 L"System\\CurrentControlSet\\Enum",
2300 0,
2301 KEY_ALL_ACCESS,
2302 &hEnumKey);
2303 if (dwError != ERROR_SUCCESS)
2304 {
2305 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
2306 return dwError;
2307 }
2308
2309 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2310 L"System\\CurrentControlSet\\Control\\Class",
2311 0,
2312 KEY_ALL_ACCESS,
2313 &hClassKey);
2314 if (dwError != ERROR_SUCCESS)
2315 {
2316 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
2317 return dwError;
2318 }
2319
2320 StartServiceCtrlDispatcher(ServiceTable);
2321
2322 DPRINT("Umpnpmgr: main() done\n");
2323
2324 ExitThread(0);
2325
2326 return 0;
2327 }
2328
2329 /* EOF */