[NTOSKRNL]
[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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 * Colin Finck (colin@reactos.org)
27 */
28
29 /* INCLUDES *****************************************************************/
30 //#define HAVE_SLIST_ENTRY_IMPLEMENTED
31 #define WIN32_NO_STATUS
32 #include <windows.h>
33 #include <stdio.h>
34 #include <cmtypes.h>
35 #include <cmfuncs.h>
36 #include <rtlfuncs.h>
37 #include <setypes.h>
38 #include <umpnpmgr/sysguid.h>
39 #include <wdmguid.h>
40 #include <cfgmgr32.h>
41 #include <regstr.h>
42 #include <userenv.h>
43
44 #include <rpc.h>
45 #include <rpcdce.h>
46
47 #include "pnp_s.h"
48
49 #define NDEBUG
50 #include <debug.h>
51
52 /* GLOBALS ******************************************************************/
53
54 static VOID CALLBACK ServiceMain(DWORD argc, LPWSTR *argv);
55 static WCHAR ServiceName[] = L"PlugPlay";
56 static SERVICE_TABLE_ENTRYW ServiceTable[] =
57 {
58 {ServiceName, ServiceMain},
59 {NULL, NULL}
60 };
61
62 static SERVICE_STATUS_HANDLE ServiceStatusHandle;
63 static SERVICE_STATUS ServiceStatus;
64
65 static WCHAR szRootDeviceId[] = L"HTREE\\ROOT\\0";
66
67 static HKEY hEnumKey = NULL;
68 static HKEY hClassKey = NULL;
69
70 static HANDLE hUserToken = NULL;
71 static HANDLE hInstallEvent = NULL;
72 static HANDLE hNoPendingInstalls = NULL;
73
74 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
75 static SLIST_HEADER DeviceInstallListHead;
76 #else
77 static LIST_ENTRY DeviceInstallListHead;
78 #endif
79 static HANDLE hDeviceInstallListNotEmpty;
80
81 typedef struct
82 {
83 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
84 SLIST_ENTRY ListEntry;
85 #else
86 LIST_ENTRY ListEntry;
87 #endif
88 WCHAR DeviceIds[1];
89 } DeviceInstallParams;
90
91 /* FUNCTIONS *****************************************************************/
92
93 static DWORD WINAPI
94 RpcServerThread(LPVOID lpParameter)
95 {
96 RPC_STATUS Status;
97 BOOLEAN RegisteredProtSeq = FALSE;
98
99 UNREFERENCED_PARAMETER(lpParameter);
100
101 DPRINT("RpcServerThread() called\n");
102
103 #if 0
104 /* XP-compatible protocol sequence/endpoint */
105 Status = RpcServerUseProtseqEpW(L"ncacn_np",
106 20,
107 L"\\pipe\\ntsvcs",
108 NULL); // Security descriptor
109 if (Status == RPC_S_OK)
110 RegisteredProtSeq = TRUE;
111 else
112 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
113 #endif
114
115 /* Vista-compatible protocol sequence/endpoint */
116 Status = RpcServerUseProtseqEpW(L"ncacn_np",
117 20,
118 L"\\pipe\\plugplay",
119 NULL); // Security descriptor
120 if (Status == RPC_S_OK)
121 RegisteredProtSeq = TRUE;
122 else
123 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
124
125 /* Make sure there's a usable endpoint */
126 if (RegisteredProtSeq == FALSE)
127 return 0;
128
129 Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec,
130 NULL,
131 NULL);
132 if (Status != RPC_S_OK)
133 {
134 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
135 return 0;
136 }
137
138 Status = RpcServerListen(1,
139 20,
140 FALSE);
141 if (Status != RPC_S_OK)
142 {
143 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
144 return 0;
145 }
146
147 /* ROS HACK (this should never happen...) */
148 DPRINT1("*** Other devices won't be installed correctly. If something\n");
149 DPRINT1("*** doesn't work, try to reboot to get a new chance.\n");
150
151 DPRINT("RpcServerThread() done\n");
152
153 return 0;
154 }
155
156
157 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
158 {
159 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
160 }
161
162
163 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
164 {
165 HeapFree(GetProcessHeap(), 0, ptr);
166 }
167
168
169 static CONFIGRET WINAPI
170 NtStatusToCrError(NTSTATUS Status)
171 {
172 switch (Status)
173 {
174 case STATUS_NO_SUCH_DEVICE:
175 return CR_NO_SUCH_DEVINST;
176
177 default:
178 /* FIXME: add more mappings */
179 DPRINT1("Unable to map status 0x%08lx\n", Status);
180 return CR_FAILURE;
181 }
182 }
183
184
185 /* Function 0 */
186 DWORD PNP_Disconnect(
187 handle_t hBinding)
188 {
189 UNREFERENCED_PARAMETER(hBinding);
190 return CR_SUCCESS;
191 }
192
193
194 /* Function 1 */
195 DWORD PNP_Connect(
196 handle_t hBinding)
197 {
198 UNREFERENCED_PARAMETER(hBinding);
199 return CR_SUCCESS;
200 }
201
202
203 /* Function 2 */
204 DWORD PNP_GetVersion(
205 handle_t hBinding,
206 WORD *pVersion)
207 {
208 UNREFERENCED_PARAMETER(hBinding);
209
210 *pVersion = 0x0400;
211 return CR_SUCCESS;
212 }
213
214
215 /* Function 3 */
216 DWORD PNP_GetGlobalState(
217 handle_t hBinding,
218 DWORD *pulState,
219 DWORD ulFlags)
220 {
221 UNREFERENCED_PARAMETER(hBinding);
222 UNREFERENCED_PARAMETER(ulFlags);
223
224 *pulState = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE;
225 return CR_SUCCESS;
226 }
227
228
229 /* Function 4 */
230 DWORD PNP_InitDetection(
231 handle_t hBinding)
232 {
233 UNREFERENCED_PARAMETER(hBinding);
234
235 DPRINT("PNP_InitDetection() called\n");
236 return CR_SUCCESS;
237 }
238
239
240 /* Function 5 */
241 DWORD PNP_ReportLogOn(
242 handle_t hBinding,
243 BOOL Admin,
244 DWORD ProcessId)
245 {
246 DWORD ReturnValue = CR_FAILURE;
247 HANDLE hProcess;
248
249 UNREFERENCED_PARAMETER(hBinding);
250 UNREFERENCED_PARAMETER(Admin);
251
252 DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin, ProcessId);
253
254 /* Get the users token */
255 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId);
256
257 if(!hProcess)
258 {
259 DPRINT1("OpenProcess failed with error %u\n", GetLastError());
260 goto cleanup;
261 }
262
263 if (hUserToken)
264 {
265 CloseHandle(hUserToken);
266 hUserToken = NULL;
267 }
268
269 if(!OpenProcessToken(hProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY, &hUserToken))
270 {
271 DPRINT1("OpenProcessToken failed with error %u\n", GetLastError());
272 goto cleanup;
273 }
274
275 /* Trigger the installer thread */
276 if (hInstallEvent)
277 SetEvent(hInstallEvent);
278
279 ReturnValue = CR_SUCCESS;
280
281 cleanup:
282 if(hProcess)
283 CloseHandle(hProcess);
284
285 return ReturnValue;
286 }
287
288
289 /* Function 6 */
290 DWORD PNP_ValidateDeviceInstance(
291 handle_t hBinding,
292 LPWSTR pDeviceID,
293 DWORD ulFlags)
294 {
295 CONFIGRET ret = CR_SUCCESS;
296 HKEY hDeviceKey = NULL;
297
298 UNREFERENCED_PARAMETER(hBinding);
299 UNREFERENCED_PARAMETER(ulFlags);
300
301 DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
302 pDeviceID, ulFlags);
303
304 if (RegOpenKeyExW(hEnumKey,
305 pDeviceID,
306 0,
307 KEY_READ,
308 &hDeviceKey))
309 {
310 DPRINT("Could not open the Device Key!\n");
311 ret = CR_NO_SUCH_DEVNODE;
312 goto Done;
313 }
314
315 /* FIXME: add more tests */
316
317 Done:
318 if (hDeviceKey != NULL)
319 RegCloseKey(hDeviceKey);
320
321 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret);
322
323 return ret;
324 }
325
326
327 /* Function 7 */
328 DWORD PNP_GetRootDeviceInstance(
329 handle_t hBinding,
330 LPWSTR pDeviceID,
331 PNP_RPC_STRING_LEN ulLength)
332 {
333 CONFIGRET ret = CR_SUCCESS;
334
335 UNREFERENCED_PARAMETER(hBinding);
336
337 DPRINT("PNP_GetRootDeviceInstance() called\n");
338
339 if (!pDeviceID)
340 {
341 ret = CR_INVALID_POINTER;
342 goto Done;
343 }
344 if (ulLength < lstrlenW(szRootDeviceId) + 1)
345 {
346 ret = CR_BUFFER_SMALL;
347 goto Done;
348 }
349
350 lstrcpyW(pDeviceID,
351 szRootDeviceId);
352
353 Done:
354 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret);
355
356 return ret;
357 }
358
359
360 /* Function 8 */
361 DWORD PNP_GetRelatedDeviceInstance(
362 handle_t hBinding,
363 DWORD ulRelationship,
364 LPWSTR pDeviceID,
365 LPWSTR pRelatedDeviceId,
366 PNP_RPC_STRING_LEN *pulLength,
367 DWORD ulFlags)
368 {
369 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData;
370 CONFIGRET ret = CR_SUCCESS;
371 NTSTATUS Status;
372
373 UNREFERENCED_PARAMETER(hBinding);
374 UNREFERENCED_PARAMETER(ulFlags);
375
376 DPRINT("PNP_GetRelatedDeviceInstance() called\n");
377 DPRINT(" Relationship %ld\n", ulRelationship);
378 DPRINT(" DeviceId %S\n", pDeviceID);
379
380 RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance,
381 pDeviceID);
382
383 PlugPlayData.Relation = ulRelationship;
384
385 PlugPlayData.RelatedDeviceInstanceLength = *pulLength;
386 PlugPlayData.RelatedDeviceInstance = pRelatedDeviceId;
387
388 Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice,
389 (PVOID)&PlugPlayData,
390 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA));
391 if (!NT_SUCCESS(Status))
392 {
393 ret = NtStatusToCrError(Status);
394 }
395
396 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret);
397 if (ret == CR_SUCCESS)
398 {
399 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance);
400 }
401
402 return ret;
403 }
404
405
406 /* Function 9 */
407 DWORD PNP_EnumerateSubKeys(
408 handle_t hBinding,
409 DWORD ulBranch,
410 DWORD ulIndex,
411 LPWSTR Buffer,
412 PNP_RPC_STRING_LEN ulLength,
413 PNP_RPC_STRING_LEN *pulRequiredLen,
414 DWORD ulFlags)
415 {
416 CONFIGRET ret = CR_SUCCESS;
417 HKEY hKey;
418 DWORD dwError;
419
420 UNREFERENCED_PARAMETER(hBinding);
421 UNREFERENCED_PARAMETER(ulFlags);
422
423 DPRINT("PNP_EnumerateSubKeys() called\n");
424
425 switch (ulBranch)
426 {
427 case PNP_ENUMERATOR_SUBKEYS:
428 hKey = hEnumKey;
429 break;
430
431 case PNP_CLASS_SUBKEYS:
432 hKey = hClassKey;
433 break;
434
435 default:
436 return CR_FAILURE;
437 }
438
439 *pulRequiredLen = ulLength;
440 dwError = RegEnumKeyExW(hKey,
441 ulIndex,
442 Buffer,
443 pulRequiredLen,
444 NULL,
445 NULL,
446 NULL,
447 NULL);
448 if (dwError != ERROR_SUCCESS)
449 {
450 ret = (dwError == ERROR_NO_MORE_ITEMS) ? CR_NO_SUCH_VALUE : CR_FAILURE;
451 }
452 else
453 {
454 (*pulRequiredLen)++;
455 }
456
457 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret);
458
459 return ret;
460 }
461
462
463 /* Function 10 */
464 DWORD PNP_GetDeviceList(
465 handle_t hBinding,
466 LPWSTR pszFilter,
467 LPWSTR Buffer,
468 PNP_RPC_STRING_LEN *pulLength,
469 DWORD ulFlags)
470 {
471 UNIMPLEMENTED;
472 return CR_CALL_NOT_IMPLEMENTED;
473 }
474
475
476 /* Function 11 */
477 DWORD PNP_GetDeviceListSize(
478 handle_t hBinding,
479 LPWSTR pszFilter,
480 PNP_RPC_BUFFER_SIZE *pulLen,
481 DWORD ulFlags)
482 {
483 UNIMPLEMENTED;
484 return CR_CALL_NOT_IMPLEMENTED;
485 }
486
487
488 /* Function 12 */
489 DWORD PNP_GetDepth(
490 handle_t hBinding,
491 LPWSTR pszDeviceID,
492 DWORD *pulDepth,
493 DWORD ulFlags)
494 {
495 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData;
496 CONFIGRET ret = CR_SUCCESS;
497 NTSTATUS Status;
498
499 UNREFERENCED_PARAMETER(hBinding);
500 UNREFERENCED_PARAMETER(ulFlags);
501
502 DPRINT("PNP_GetDepth() called\n");
503
504 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
505 pszDeviceID);
506
507 Status = NtPlugPlayControl(PlugPlayControlGetDeviceDepth,
508 (PVOID)&PlugPlayData,
509 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA));
510 if (NT_SUCCESS(Status))
511 {
512 *pulDepth = PlugPlayData.Depth;
513 }
514 else
515 {
516 ret = NtStatusToCrError(Status);
517 }
518
519 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret);
520
521 return ret;
522 }
523
524
525 /* Function 13 */
526 DWORD PNP_GetDeviceRegProp(
527 handle_t hBinding,
528 LPWSTR pDeviceID,
529 DWORD ulProperty,
530 DWORD *pulRegDataType,
531 BYTE *Buffer,
532 PNP_PROP_SIZE *pulTransferLen,
533 PNP_PROP_SIZE *pulLength,
534 DWORD ulFlags)
535 {
536 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData;
537 CONFIGRET ret = CR_SUCCESS;
538 LPWSTR lpValueName = NULL;
539 HKEY hKey = NULL;
540 LONG lError;
541 NTSTATUS Status;
542
543 UNREFERENCED_PARAMETER(hBinding);
544
545 DPRINT("PNP_GetDeviceRegProp() called\n");
546
547 if (pulTransferLen == NULL || pulLength == NULL)
548 {
549 ret = CR_INVALID_POINTER;
550 goto done;
551 }
552
553 if (ulFlags != 0)
554 {
555 ret = CR_INVALID_FLAG;
556 goto done;
557 }
558
559 /* FIXME: Check pDeviceID */
560
561 if (*pulLength < *pulTransferLen)
562 *pulLength = *pulTransferLen;
563
564 *pulTransferLen = 0;
565
566 switch (ulProperty)
567 {
568 case CM_DRP_DEVICEDESC:
569 lpValueName = L"DeviceDesc";
570 break;
571
572 case CM_DRP_HARDWAREID:
573 lpValueName = L"HardwareID";
574 break;
575
576 case CM_DRP_COMPATIBLEIDS:
577 lpValueName = L"CompatibleIDs";
578 break;
579
580 case CM_DRP_SERVICE:
581 lpValueName = L"Service";
582 break;
583
584 case CM_DRP_CLASS:
585 lpValueName = L"Class";
586 break;
587
588 case CM_DRP_CLASSGUID:
589 lpValueName = L"ClassGUID";
590 break;
591
592 case CM_DRP_DRIVER:
593 lpValueName = L"Driver";
594 break;
595
596 case CM_DRP_CONFIGFLAGS:
597 lpValueName = L"ConfigFlags";
598 break;
599
600 case CM_DRP_MFG:
601 lpValueName = L"Mfg";
602 break;
603
604 case CM_DRP_FRIENDLYNAME:
605 lpValueName = L"FriendlyName";
606 break;
607
608 case CM_DRP_LOCATION_INFORMATION:
609 lpValueName = L"LocationInformation";
610 break;
611
612 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
613 lpValueName = NULL;
614 break;
615
616 case CM_DRP_CAPABILITIES:
617 lpValueName = L"Capabilities";
618 break;
619
620 case CM_DRP_UI_NUMBER:
621 lpValueName = NULL;
622 break;
623
624 case CM_DRP_UPPERFILTERS:
625 lpValueName = L"UpperFilters";
626 break;
627
628 case CM_DRP_LOWERFILTERS:
629 lpValueName = L"LowerFilters";
630 break;
631
632 case CM_DRP_BUSTYPEGUID:
633 lpValueName = NULL;
634 break;
635
636 case CM_DRP_LEGACYBUSTYPE:
637 lpValueName = NULL;
638 break;
639
640 case CM_DRP_BUSNUMBER:
641 lpValueName = NULL;
642 break;
643
644 case CM_DRP_ENUMERATOR_NAME:
645 lpValueName = NULL;
646 break;
647
648 case CM_DRP_SECURITY:
649 lpValueName = L"Security";
650 break;
651
652 case CM_DRP_DEVTYPE:
653 lpValueName = L"DeviceType";
654 break;
655
656 case CM_DRP_EXCLUSIVE:
657 lpValueName = L"Exclusive";
658 break;
659
660 case CM_DRP_CHARACTERISTICS:
661 lpValueName = L"DeviceCharacteristics";
662 break;
663
664 case CM_DRP_ADDRESS:
665 lpValueName = NULL;
666 break;
667
668 case CM_DRP_UI_NUMBER_DESC_FORMAT:
669 lpValueName = L"UINumberDescFormat";
670 break;
671
672 case CM_DRP_DEVICE_POWER_DATA:
673 lpValueName = NULL;
674 break;
675
676 case CM_DRP_REMOVAL_POLICY:
677 lpValueName = L"RemovalPolicy";
678 break;
679
680 case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
681 lpValueName = NULL;
682 break;
683
684 case CM_DRP_REMOVAL_POLICY_OVERRIDE:
685 lpValueName = NULL;
686 break;
687
688 case CM_DRP_INSTALL_STATE:
689 lpValueName = NULL;
690 break;
691
692 #if (WINVER >= _WIN32_WINNT_WS03)
693 case CM_DRP_LOCATION_PATHS:
694 lpValueName = NULL;
695 break;
696 #endif
697
698 #if (WINVER >= _WIN32_WINNT_WIN7)
699 case CM_DRP_BASE_CONTAINERID:
700 lpValueName = NULL;
701 break;
702 #endif
703
704 default:
705 ret = CR_INVALID_PROPERTY;
706 goto done;
707 }
708
709 DPRINT("Value name: %S\n", lpValueName);
710
711 if (lpValueName)
712 {
713 /* Retrieve information from the Registry */
714 lError = RegOpenKeyExW(hEnumKey,
715 pDeviceID,
716 0,
717 KEY_QUERY_VALUE,
718 &hKey);
719 if (lError != ERROR_SUCCESS)
720 {
721 hKey = NULL;
722 *pulLength = 0;
723 ret = CR_INVALID_DEVNODE;
724 goto done;
725 }
726
727 lError = RegQueryValueExW(hKey,
728 lpValueName,
729 NULL,
730 pulRegDataType,
731 Buffer,
732 pulLength);
733 if (lError == ERROR_MORE_DATA)
734 {
735 ret = CR_BUFFER_SMALL;
736 }
737 else
738 {
739 *pulLength = 0;
740 ret = CR_NO_SUCH_VALUE;
741 }
742 }
743 else
744 {
745 /* Retrieve information from the Device Node */
746 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
747 pDeviceID);
748 PlugPlayData.Buffer = Buffer;
749 PlugPlayData.BufferSize = *pulTransferLen;
750
751 switch (ulProperty)
752 {
753 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
754 PlugPlayData.Property = 0xb; // DevicePropertyPhysicalDeviceObjectName;
755 break;
756
757 case CM_DRP_UI_NUMBER:
758 PlugPlayData.Property = 0x11; // DevicePropertyUINumber;
759 break;
760
761 case CM_DRP_BUSTYPEGUID:
762 PlugPlayData.Property = 0xc; // DevicePropertyBusTypeGuid;
763 break;
764
765 case CM_DRP_LEGACYBUSTYPE:
766 PlugPlayData.Property = 0xd; // DevicePropertyLegacyBusType;
767 break;
768
769 case CM_DRP_BUSNUMBER:
770 PlugPlayData.Property = 0xe; // DevicePropertyBusNumber;
771 break;
772
773 case CM_DRP_ENUMERATOR_NAME:
774 PlugPlayData.Property = 0xf; // DevicePropertyEnumeratorName;
775 break;
776
777 case CM_DRP_ADDRESS:
778 PlugPlayData.Property = 0x10; // DevicePropertyAddress;
779 break;
780
781 #if 0
782 /* These properties are not supported by IoGetDeviceProperty */
783 case CM_DRP_DEVICE_POWER_DATA:
784 case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
785 case CM_DRP_REMOVAL_POLICY_OVERRIDE:
786 #endif
787
788 case CM_DRP_INSTALL_STATE:
789 PlugPlayData.Property = 0x12; // DevicePropertyInstallState;
790 break;
791
792 #if 0
793 /* This property is not supported by IoGetDeviceProperty */
794 #if (WINVER >= _WIN32_WINNT_WS03)
795 case CM_DRP_LOCATION_PATHS:
796 #endif
797 #endif
798
799 #if (WINVER >= _WIN32_WINNT_WIN7)
800 case CM_DRP_BASE_CONTAINERID:
801 PlugPlayData.Property = 0x16; // DevicePropertyContainerID;
802 break;
803 #endif
804
805 default:
806 return CR_INVALID_PROPERTY;
807 }
808
809 Status = NtPlugPlayControl(PlugPlayControlProperty,
810 (PVOID)&PlugPlayData,
811 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA));
812 if (NT_SUCCESS(Status))
813 {
814 *pulLength = PlugPlayData.BufferSize;
815 }
816 else
817 {
818 ret = NtStatusToCrError(Status);
819 }
820 }
821
822 done:;
823 *pulTransferLen = (ret != CR_SUCCESS) ? 0 : *pulLength;
824
825 if (hKey != NULL)
826 RegCloseKey(hKey);
827
828 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret);
829
830 return ret;
831 }
832
833
834 /* Function 14 */
835 DWORD PNP_SetDeviceRegProp(
836 handle_t hBinding,
837 LPWSTR pDeviceId,
838 DWORD ulProperty,
839 DWORD ulDataType,
840 BYTE *Buffer,
841 PNP_PROP_SIZE ulLength,
842 DWORD ulFlags)
843 {
844 CONFIGRET ret = CR_SUCCESS;
845 LPWSTR lpValueName = NULL;
846 HKEY hKey = 0;
847
848 UNREFERENCED_PARAMETER(hBinding);
849 UNREFERENCED_PARAMETER(ulFlags);
850
851 DPRINT("PNP_SetDeviceRegProp() called\n");
852
853 DPRINT("DeviceId: %S\n", pDeviceId);
854 DPRINT("Property: %lu\n", ulProperty);
855 DPRINT("DataType: %lu\n", ulDataType);
856 DPRINT("Length: %lu\n", ulLength);
857
858 switch (ulProperty)
859 {
860 case CM_DRP_DEVICEDESC:
861 lpValueName = L"DeviceDesc";
862 break;
863
864 case CM_DRP_HARDWAREID:
865 lpValueName = L"HardwareID";
866 break;
867
868 case CM_DRP_COMPATIBLEIDS:
869 lpValueName = L"CompatibleIDs";
870 break;
871
872 case CM_DRP_SERVICE:
873 lpValueName = L"Service";
874 break;
875
876 case CM_DRP_CLASS:
877 lpValueName = L"Class";
878 break;
879
880 case CM_DRP_CLASSGUID:
881 lpValueName = L"ClassGUID";
882 break;
883
884 case CM_DRP_DRIVER:
885 lpValueName = L"Driver";
886 break;
887
888 case CM_DRP_CONFIGFLAGS:
889 lpValueName = L"ConfigFlags";
890 break;
891
892 case CM_DRP_MFG:
893 lpValueName = L"Mfg";
894 break;
895
896 case CM_DRP_FRIENDLYNAME:
897 lpValueName = L"FriendlyName";
898 break;
899
900 case CM_DRP_LOCATION_INFORMATION:
901 lpValueName = L"LocationInformation";
902 break;
903
904 case CM_DRP_UPPERFILTERS:
905 lpValueName = L"UpperFilters";
906 break;
907
908 case CM_DRP_LOWERFILTERS:
909 lpValueName = L"LowerFilters";
910 break;
911
912 default:
913 return CR_INVALID_PROPERTY;
914 }
915
916 DPRINT("Value name: %S\n", lpValueName);
917
918 if (RegOpenKeyExW(hEnumKey,
919 pDeviceId,
920 0,
921 KEY_ALL_ACCESS, /* FIXME: so much? */
922 &hKey))
923 return CR_INVALID_DEVNODE;
924
925 if (ulLength == 0)
926 {
927 if (RegDeleteValueW(hKey,
928 lpValueName))
929 ret = CR_REGISTRY_ERROR;
930 }
931 else
932 {
933 if (RegSetValueExW(hKey,
934 lpValueName,
935 0,
936 ulDataType,
937 Buffer,
938 ulLength))
939 ret = CR_REGISTRY_ERROR;
940 }
941
942 RegCloseKey(hKey);
943
944 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret);
945
946 return ret;
947 }
948
949
950 /* Function 15 */
951 DWORD PNP_GetClassInstance(
952 handle_t hBinding,
953 LPWSTR pDeviceId,
954 LPWSTR pszClassInstance,
955 PNP_RPC_STRING_LEN ulLength)
956 {
957 UNIMPLEMENTED;
958 return CR_CALL_NOT_IMPLEMENTED;
959 }
960
961
962 /* Function 16 */
963 DWORD PNP_CreateKey(
964 handle_t hBinding,
965 LPWSTR pszSubKey,
966 DWORD samDesired,
967 DWORD ulFlags)
968 {
969 HKEY hKey = 0;
970
971 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
972 pszSubKey,
973 0,
974 NULL,
975 0,
976 KEY_ALL_ACCESS,
977 NULL,
978 &hKey,
979 NULL))
980 return CR_REGISTRY_ERROR;
981
982 /* FIXME: Set security key */
983
984 RegCloseKey(hKey);
985
986 return CR_SUCCESS;
987 }
988
989
990 /* Function 17 */
991 DWORD PNP_DeleteRegistryKey(
992 handle_t hBinding,
993 LPWSTR pszDeviceID,
994 LPWSTR pszParentKey,
995 LPWSTR pszChildKey,
996 DWORD ulFlags)
997 {
998 UNIMPLEMENTED;
999 return CR_CALL_NOT_IMPLEMENTED;
1000 }
1001
1002
1003 /* Function 18 */
1004 DWORD PNP_GetClassCount(
1005 handle_t hBinding,
1006 DWORD *pulClassCount,
1007 DWORD ulFlags)
1008 {
1009 HKEY hKey;
1010 DWORD dwError;
1011
1012 UNREFERENCED_PARAMETER(hBinding);
1013 UNREFERENCED_PARAMETER(ulFlags);
1014
1015 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1016 REGSTR_PATH_CLASS,
1017 0,
1018 KEY_QUERY_VALUE,
1019 &hKey);
1020 if (dwError != ERROR_SUCCESS)
1021 return CR_INVALID_DATA;
1022
1023 dwError = RegQueryInfoKeyW(hKey,
1024 NULL,
1025 NULL,
1026 NULL,
1027 pulClassCount,
1028 NULL,
1029 NULL,
1030 NULL,
1031 NULL,
1032 NULL,
1033 NULL,
1034 NULL);
1035 RegCloseKey(hKey);
1036 if (dwError != ERROR_SUCCESS)
1037 return CR_INVALID_DATA;
1038
1039 return CR_SUCCESS;
1040 }
1041
1042
1043 /* Function 19 */
1044 DWORD PNP_GetClassName(
1045 handle_t hBinding,
1046 LPWSTR pszClassGuid,
1047 LPWSTR Buffer,
1048 PNP_RPC_STRING_LEN *pulLength,
1049 DWORD ulFlags)
1050 {
1051 WCHAR szKeyName[MAX_PATH];
1052 CONFIGRET ret = CR_SUCCESS;
1053 HKEY hKey;
1054 DWORD dwSize;
1055
1056 UNREFERENCED_PARAMETER(hBinding);
1057 UNREFERENCED_PARAMETER(ulFlags);
1058
1059 DPRINT("PNP_GetClassName() called\n");
1060
1061 lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\");
1062 if(lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR)))
1063 lstrcatW(szKeyName, pszClassGuid);
1064 else return CR_INVALID_DATA;
1065
1066 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1067 szKeyName,
1068 0,
1069 KEY_QUERY_VALUE,
1070 &hKey))
1071 return CR_REGISTRY_ERROR;
1072
1073 dwSize = *pulLength * sizeof(WCHAR);
1074 if (RegQueryValueExW(hKey,
1075 L"Class",
1076 NULL,
1077 NULL,
1078 (LPBYTE)Buffer,
1079 &dwSize))
1080 {
1081 *pulLength = 0;
1082 ret = CR_REGISTRY_ERROR;
1083 }
1084 else
1085 {
1086 *pulLength = dwSize / sizeof(WCHAR);
1087 }
1088
1089 RegCloseKey(hKey);
1090
1091 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret);
1092
1093 return ret;
1094 }
1095
1096
1097 /* Function 20 */
1098 DWORD PNP_DeleteClassKey(
1099 handle_t hBinding,
1100 LPWSTR pszClassGuid,
1101 DWORD ulFlags)
1102 {
1103 CONFIGRET ret = CR_SUCCESS;
1104
1105 UNREFERENCED_PARAMETER(hBinding);
1106
1107 DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid, ulFlags);
1108
1109 if (ulFlags & CM_DELETE_CLASS_SUBKEYS)
1110 {
1111 if (RegDeleteTreeW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
1112 ret = CR_REGISTRY_ERROR;
1113 }
1114 else
1115 {
1116 if (RegDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
1117 ret = CR_REGISTRY_ERROR;
1118 }
1119
1120 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret);
1121
1122 return ret;
1123 }
1124
1125
1126 /* Function 21 */
1127 DWORD PNP_GetInterfaceDeviceAlias(
1128 handle_t hBinding,
1129 LPWSTR pszInterfaceDevice,
1130 GUID *AliasInterfaceGuid,
1131 LPWSTR pszAliasInterfaceDevice,
1132 PNP_RPC_STRING_LEN *pulLength,
1133 PNP_RPC_STRING_LEN *pulTransferLen,
1134 DWORD ulFlags)
1135 {
1136 UNIMPLEMENTED;
1137 return CR_CALL_NOT_IMPLEMENTED;
1138 }
1139
1140
1141 /* Function 22 */
1142 DWORD PNP_GetInterfaceDeviceList(
1143 handle_t hBinding,
1144 GUID *InterfaceGuid,
1145 LPWSTR pszDeviceID,
1146 BYTE *Buffer,
1147 PNP_RPC_BUFFER_SIZE *pulLength,
1148 DWORD ulFlags)
1149 {
1150 UNIMPLEMENTED;
1151 return CR_CALL_NOT_IMPLEMENTED;
1152 }
1153
1154
1155 /* Function 23 */
1156 DWORD PNP_GetInterfaceDeviceListSize(
1157 handle_t hBinding,
1158 PNP_RPC_BUFFER_SIZE *pulLen,
1159 GUID *InterfaceGuid,
1160 LPWSTR pszDeviceID,
1161 DWORD ulFlags)
1162 {
1163 UNIMPLEMENTED;
1164 return CR_CALL_NOT_IMPLEMENTED;
1165 }
1166
1167
1168 /* Function 24 */
1169 DWORD PNP_RegisterDeviceClassAssociation(
1170 handle_t hBinding,
1171 LPWSTR pszDeviceID,
1172 GUID *InterfaceGuid,
1173 LPWSTR pszReference,
1174 LPWSTR pszSymLink,
1175 PNP_RPC_STRING_LEN *pulLength,
1176 PNP_RPC_STRING_LEN *pulTransferLen,
1177 DWORD ulFlags)
1178 {
1179 UNIMPLEMENTED;
1180 return CR_CALL_NOT_IMPLEMENTED;
1181 }
1182
1183
1184 /* Function 25 */
1185 DWORD PNP_UnregisterDeviceClassAssociation(
1186 handle_t hBinding,
1187 LPWSTR pszInterfaceDevice,
1188 DWORD ulFlags)
1189 {
1190 UNIMPLEMENTED;
1191 return CR_CALL_NOT_IMPLEMENTED;
1192 }
1193
1194
1195 /* Function 26 */
1196 DWORD PNP_GetClassRegProp(
1197 handle_t hBinding,
1198 LPWSTR pszClassGuid,
1199 DWORD ulProperty,
1200 DWORD *pulRegDataType,
1201 BYTE *Buffer,
1202 PNP_RPC_STRING_LEN *pulTransferLen,
1203 PNP_RPC_STRING_LEN *pulLength,
1204 DWORD ulFlags)
1205 {
1206 UNIMPLEMENTED;
1207 return CR_CALL_NOT_IMPLEMENTED;
1208 }
1209
1210
1211 /* Function 27 */
1212 DWORD PNP_SetClassRegProp(
1213 handle_t hBinding,
1214 LPWSTR *pszClassGuid,
1215 DWORD ulProperty,
1216 DWORD ulDataType,
1217 BYTE *Buffer,
1218 PNP_PROP_SIZE ulLength,
1219 DWORD ulFlags)
1220 {
1221 UNIMPLEMENTED;
1222 return CR_CALL_NOT_IMPLEMENTED;
1223 }
1224
1225
1226 static VOID
1227 SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID,
1228 OUT LPWSTR pszEnumerator,
1229 OUT LPWSTR pszDevice,
1230 OUT LPWSTR pszInstance)
1231 {
1232 WCHAR szLocalDeviceInstanceID[MAX_DEVICE_ID_LEN];
1233 LPWSTR lpEnumerator = NULL;
1234 LPWSTR lpDevice = NULL;
1235 LPWSTR lpInstance = NULL;
1236 LPWSTR ptr;
1237
1238 wcscpy(szLocalDeviceInstanceID, pszDeviceInstanceID);
1239
1240 *pszEnumerator = 0;
1241 *pszDevice = 0;
1242 *pszInstance = 0;
1243
1244 lpEnumerator = szLocalDeviceInstanceID;
1245
1246 ptr = wcschr(lpEnumerator, L'\\');
1247 if (ptr != NULL)
1248 {
1249 *ptr = 0;
1250 lpDevice = ++ptr;
1251
1252 ptr = wcschr(lpDevice, L'\\');
1253 if (ptr != NULL)
1254 {
1255 *ptr = 0;
1256 lpInstance = ++ptr;
1257 }
1258 }
1259
1260 if (lpEnumerator != NULL)
1261 wcscpy(pszEnumerator, lpEnumerator);
1262
1263 if (lpDevice != NULL)
1264 wcscpy(pszDevice, lpDevice);
1265
1266 if (lpInstance != NULL)
1267 wcscpy(pszInstance, lpInstance);
1268 }
1269
1270
1271 static CONFIGRET
1272 CreateDeviceInstance(LPWSTR pszDeviceID)
1273 {
1274 WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
1275 WCHAR szDevice[MAX_DEVICE_ID_LEN];
1276 WCHAR szInstance[MAX_DEVICE_ID_LEN];
1277 HKEY hKeyEnumerator;
1278 HKEY hKeyDevice;
1279 HKEY hKeyInstance;
1280 HKEY hKeyControl;
1281 LONG lError;
1282
1283 /* Split the instance ID */
1284 SplitDeviceInstanceID(pszDeviceID,
1285 szEnumerator,
1286 szDevice,
1287 szInstance);
1288
1289 /* Open or create the enumerator key */
1290 lError = RegCreateKeyExW(hEnumKey,
1291 szEnumerator,
1292 0,
1293 NULL,
1294 REG_OPTION_NON_VOLATILE,
1295 KEY_ALL_ACCESS,
1296 NULL,
1297 &hKeyEnumerator,
1298 NULL);
1299 if (lError != ERROR_SUCCESS)
1300 {
1301 return CR_REGISTRY_ERROR;
1302 }
1303
1304 /* Open or create the device key */
1305 lError = RegCreateKeyExW(hKeyEnumerator,
1306 szDevice,
1307 0,
1308 NULL,
1309 REG_OPTION_NON_VOLATILE,
1310 KEY_ALL_ACCESS,
1311 NULL,
1312 &hKeyDevice,
1313 NULL);
1314
1315 /* Close the enumerator key */
1316 RegCloseKey(hKeyEnumerator);
1317
1318 if (lError != ERROR_SUCCESS)
1319 {
1320 return CR_REGISTRY_ERROR;
1321 }
1322
1323 /* Try to open the instance key and fail if it exists */
1324 lError = RegOpenKeyExW(hKeyDevice,
1325 szInstance,
1326 0,
1327 KEY_SET_VALUE,
1328 &hKeyInstance);
1329 if (lError == ERROR_SUCCESS)
1330 {
1331 DPRINT1("Instance %S already exists!\n", szInstance);
1332 RegCloseKey(hKeyInstance);
1333 RegCloseKey(hKeyDevice);
1334 return CR_ALREADY_SUCH_DEVINST;
1335 }
1336
1337 /* Create a new instance key */
1338 lError = RegCreateKeyExW(hKeyDevice,
1339 szInstance,
1340 0,
1341 NULL,
1342 REG_OPTION_NON_VOLATILE,
1343 KEY_ALL_ACCESS,
1344 NULL,
1345 &hKeyInstance,
1346 NULL);
1347
1348 /* Close the device key */
1349 RegCloseKey(hKeyDevice);
1350
1351 if (lError != ERROR_SUCCESS)
1352 {
1353 return CR_REGISTRY_ERROR;
1354 }
1355
1356 /* Create the 'Control' sub key */
1357 lError = RegCreateKeyExW(hKeyInstance,
1358 L"Control",
1359 0,
1360 NULL,
1361 REG_OPTION_NON_VOLATILE,
1362 KEY_ALL_ACCESS,
1363 NULL,
1364 &hKeyControl,
1365 NULL);
1366 if (lError == ERROR_SUCCESS)
1367 {
1368 RegCloseKey(hKeyControl);
1369 }
1370
1371 RegCloseKey(hKeyInstance);
1372
1373 return (lError == ERROR_SUCCESS) ? CR_SUCCESS : CR_REGISTRY_ERROR;
1374 }
1375
1376
1377 /* Function 28 */
1378 DWORD PNP_CreateDevInst(
1379 handle_t hBinding,
1380 LPWSTR pszDeviceID,
1381 LPWSTR pszParentDeviceID,
1382 PNP_RPC_STRING_LEN ulLength,
1383 DWORD ulFlags)
1384 {
1385 CONFIGRET ret = CR_SUCCESS;
1386
1387 DPRINT("PNP_CreateDevInst: %S\n", pszDeviceID);
1388
1389 if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID)
1390 {
1391 /* FIXME */
1392 DPRINT1("CM_CREATE_DEVNODE_GENERATE_ID support not implemented yet!\n", ret);
1393 ret = CR_CALL_NOT_IMPLEMENTED;
1394 goto done;
1395 }
1396
1397 /* Create the device instance */
1398 ret = CreateDeviceInstance(pszDeviceID);
1399
1400 done:;
1401 DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret);
1402
1403 return ret;
1404 }
1405
1406
1407 static CONFIGRET
1408 MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination,
1409 LPWSTR pszDeviceInstanceSource)
1410 {
1411 DPRINT("MoveDeviceInstance: not implemented\n");
1412 /* FIXME */
1413 return CR_CALL_NOT_IMPLEMENTED;
1414 }
1415
1416
1417 static CONFIGRET
1418 SetupDeviceInstance(LPWSTR pszDeviceInstance,
1419 DWORD ulFlags)
1420 {
1421 DPRINT("SetupDeviceInstance: not implemented\n");
1422 /* FIXME */
1423 return CR_CALL_NOT_IMPLEMENTED;
1424 }
1425
1426
1427 static CONFIGRET
1428 EnableDeviceInstance(LPWSTR pszDeviceInstance)
1429 {
1430 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
1431 CONFIGRET ret = CR_SUCCESS;
1432 NTSTATUS Status;
1433
1434 DPRINT("Enable device instance\n");
1435
1436 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance);
1437 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
1438 if (!NT_SUCCESS(Status))
1439 ret = NtStatusToCrError(Status);
1440
1441 return ret;
1442 }
1443
1444
1445 static CONFIGRET
1446 DisableDeviceInstance(LPWSTR pszDeviceInstance)
1447 {
1448 DPRINT("DisableDeviceInstance: not implemented\n");
1449 /* FIXME */
1450 return CR_CALL_NOT_IMPLEMENTED;
1451 }
1452
1453
1454 static CONFIGRET
1455 ReenumerateDeviceInstance(LPWSTR pszDeviceInstance)
1456 {
1457 DPRINT("ReenumerateDeviceInstance: not implemented\n");
1458 /* FIXME */
1459 return CR_CALL_NOT_IMPLEMENTED;
1460 }
1461
1462
1463 /* Function 29 */
1464 DWORD PNP_DeviceInstanceAction(
1465 handle_t hBinding,
1466 DWORD ulAction,
1467 DWORD ulFlags,
1468 LPWSTR pszDeviceInstance1,
1469 LPWSTR pszDeviceInstance2)
1470 {
1471 CONFIGRET ret = CR_SUCCESS;
1472
1473 UNREFERENCED_PARAMETER(hBinding);
1474
1475 DPRINT("PNP_DeviceInstanceAction() called\n");
1476
1477 switch (ulAction)
1478 {
1479 case PNP_DEVINST_MOVE:
1480 ret = MoveDeviceInstance(pszDeviceInstance1,
1481 pszDeviceInstance2);
1482 break;
1483
1484 case PNP_DEVINST_SETUP:
1485 ret = SetupDeviceInstance(pszDeviceInstance1,
1486 ulFlags);
1487 break;
1488
1489 case PNP_DEVINST_ENABLE:
1490 ret = EnableDeviceInstance(pszDeviceInstance1);
1491 break;
1492
1493 case PNP_DEVINST_DISABLE:
1494 ret = DisableDeviceInstance(pszDeviceInstance1);
1495 break;
1496
1497 case PNP_DEVINST_REENUMERATE:
1498 ret = ReenumerateDeviceInstance(pszDeviceInstance1);
1499 break;
1500
1501 default:
1502 DPRINT1("Unknown device action %lu: not implemented\n", ulAction);
1503 ret = CR_CALL_NOT_IMPLEMENTED;
1504 }
1505
1506 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
1507
1508 return ret;
1509 }
1510
1511
1512 /* Function 30 */
1513 DWORD PNP_GetDeviceStatus(
1514 handle_t hBinding,
1515 LPWSTR pDeviceID,
1516 DWORD *pulStatus,
1517 DWORD *pulProblem,
1518 DWORD ulFlags)
1519 {
1520 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1521 CONFIGRET ret = CR_SUCCESS;
1522 NTSTATUS Status;
1523
1524 UNREFERENCED_PARAMETER(hBinding);
1525 UNREFERENCED_PARAMETER(ulFlags);
1526
1527 DPRINT("PNP_GetDeviceStatus() called\n");
1528
1529 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1530 pDeviceID);
1531 PlugPlayData.Operation = 0; /* Get status */
1532
1533 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1534 (PVOID)&PlugPlayData,
1535 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1536 if (NT_SUCCESS(Status))
1537 {
1538 *pulStatus = PlugPlayData.DeviceStatus;
1539 *pulProblem = PlugPlayData.DeviceProblem;
1540 }
1541 else
1542 {
1543 ret = NtStatusToCrError(Status);
1544 }
1545
1546 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret);
1547
1548 return ret;
1549 }
1550
1551
1552 /* Function 31 */
1553 DWORD PNP_SetDeviceProblem(
1554 handle_t hBinding,
1555 LPWSTR pDeviceID,
1556 DWORD ulProblem,
1557 DWORD ulFlags)
1558 {
1559 UNIMPLEMENTED;
1560 return CR_CALL_NOT_IMPLEMENTED;
1561 }
1562
1563
1564 /* Function 32 */
1565 DWORD PNP_DisableDevInst(
1566 handle_t hBinding,
1567 LPWSTR pDeviceID,
1568 PPNP_VETO_TYPE pVetoType,
1569 LPWSTR pszVetoName,
1570 DWORD ulNameLength,
1571 DWORD ulFlags)
1572 {
1573 UNIMPLEMENTED;
1574 return CR_CALL_NOT_IMPLEMENTED;
1575 }
1576
1577 /* Function 33 */
1578 DWORD PNP_UninstallDevInst(
1579 handle_t hBinding,
1580 LPWSTR pDeviceID,
1581 DWORD ulFlags)
1582 {
1583 UNIMPLEMENTED;
1584 return CR_CALL_NOT_IMPLEMENTED;
1585 }
1586
1587
1588 static BOOL
1589 CheckForDeviceId(LPWSTR lpDeviceIdList,
1590 LPWSTR lpDeviceId)
1591 {
1592 LPWSTR lpPtr;
1593 DWORD dwLength;
1594
1595 lpPtr = lpDeviceIdList;
1596 while (*lpPtr != 0)
1597 {
1598 dwLength = wcslen(lpPtr);
1599 if (0 == _wcsicmp(lpPtr, lpDeviceId))
1600 return TRUE;
1601
1602 lpPtr += (dwLength + 1);
1603 }
1604
1605 return FALSE;
1606 }
1607
1608
1609 static VOID
1610 AppendDeviceId(LPWSTR lpDeviceIdList,
1611 LPDWORD lpDeviceIdListSize,
1612 LPWSTR lpDeviceId)
1613 {
1614 DWORD dwLen;
1615 DWORD dwPos;
1616
1617 dwLen = wcslen(lpDeviceId);
1618 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
1619
1620 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
1621
1622 dwPos += (dwLen + 1);
1623
1624 lpDeviceIdList[dwPos] = 0;
1625
1626 *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
1627 }
1628
1629
1630 /* Function 34 */
1631 DWORD PNP_AddID(
1632 handle_t hBinding,
1633 LPWSTR pszDeviceID,
1634 LPWSTR pszID,
1635 DWORD ulFlags)
1636 {
1637 CONFIGRET ret = CR_SUCCESS;
1638 HKEY hDeviceKey;
1639 LPWSTR pszSubKey;
1640 DWORD dwDeviceIdListSize;
1641 DWORD dwNewDeviceIdSize;
1642 WCHAR * pszDeviceIdList = NULL;
1643
1644 UNREFERENCED_PARAMETER(hBinding);
1645
1646 DPRINT("PNP_AddID() called\n");
1647 DPRINT(" DeviceInstance: %S\n", pszDeviceID);
1648 DPRINT(" DeviceId: %S\n", pszID);
1649 DPRINT(" Flags: %lx\n", ulFlags);
1650
1651 if (RegOpenKeyExW(hEnumKey,
1652 pszDeviceID,
1653 0,
1654 KEY_QUERY_VALUE | KEY_SET_VALUE,
1655 &hDeviceKey) != ERROR_SUCCESS)
1656 {
1657 DPRINT("Failed to open the device key!\n");
1658 return CR_INVALID_DEVNODE;
1659 }
1660
1661 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
1662
1663 if (RegQueryValueExW(hDeviceKey,
1664 pszSubKey,
1665 NULL,
1666 NULL,
1667 NULL,
1668 &dwDeviceIdListSize) != ERROR_SUCCESS)
1669 {
1670 DPRINT("Failed to query the desired ID string!\n");
1671 ret = CR_REGISTRY_ERROR;
1672 goto Done;
1673 }
1674
1675 dwNewDeviceIdSize = lstrlenW(pszDeviceID);
1676 if (!dwNewDeviceIdSize)
1677 {
1678 ret = CR_INVALID_POINTER;
1679 goto Done;
1680 }
1681
1682 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR);
1683
1684 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize);
1685 if (!pszDeviceIdList)
1686 {
1687 DPRINT("Failed to allocate memory for the desired ID string!\n");
1688 ret = CR_OUT_OF_MEMORY;
1689 goto Done;
1690 }
1691
1692 if (RegQueryValueExW(hDeviceKey,
1693 pszSubKey,
1694 NULL,
1695 NULL,
1696 (LPBYTE)pszDeviceIdList,
1697 &dwDeviceIdListSize) != ERROR_SUCCESS)
1698 {
1699 DPRINT("Failed to query the desired ID string!\n");
1700 ret = CR_REGISTRY_ERROR;
1701 goto Done;
1702 }
1703
1704 /* Check whether the device ID is already in use */
1705 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID))
1706 {
1707 DPRINT("Device ID was found in the ID string!\n");
1708 ret = CR_SUCCESS;
1709 goto Done;
1710 }
1711
1712 /* Append the Device ID */
1713 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID);
1714
1715 if (RegSetValueExW(hDeviceKey,
1716 pszSubKey,
1717 0,
1718 REG_MULTI_SZ,
1719 (LPBYTE)pszDeviceIdList,
1720 dwDeviceIdListSize) != ERROR_SUCCESS)
1721 {
1722 DPRINT("Failed to set the desired ID string!\n");
1723 ret = CR_REGISTRY_ERROR;
1724 }
1725
1726 Done:
1727 RegCloseKey(hDeviceKey);
1728 if (pszDeviceIdList)
1729 HeapFree(GetProcessHeap(), 0, pszDeviceIdList);
1730
1731 DPRINT("PNP_AddID() done (returns %lx)\n", ret);
1732
1733 return ret;
1734 }
1735
1736
1737 /* Function 35 */
1738 DWORD PNP_RegisterDriver(
1739 handle_t hBinding,
1740 LPWSTR pszDeviceID,
1741 DWORD ulFlags)
1742 {
1743 UNIMPLEMENTED;
1744 return CR_CALL_NOT_IMPLEMENTED;
1745 }
1746
1747
1748 /* Function 36 */
1749 DWORD PNP_QueryRemove(
1750 handle_t hBinding,
1751 LPWSTR pszDeviceID,
1752 PPNP_VETO_TYPE pVetoType,
1753 LPWSTR pszVetoName,
1754 DWORD ulNameLength,
1755 DWORD ulFlags)
1756 {
1757 UNIMPLEMENTED;
1758 return CR_CALL_NOT_IMPLEMENTED;
1759 }
1760
1761
1762 /* Function 37 */
1763 DWORD PNP_RequestDeviceEject(
1764 handle_t hBinding,
1765 LPWSTR pszDeviceID,
1766 PPNP_VETO_TYPE pVetoType,
1767 LPWSTR pszVetoName,
1768 DWORD ulNameLength,
1769 DWORD ulFlags)
1770 {
1771 UNIMPLEMENTED;
1772 return CR_CALL_NOT_IMPLEMENTED;
1773 }
1774
1775 /* Function 38 */
1776 CONFIGRET
1777 PNP_IsDockStationPresent(handle_t hBinding,
1778 BOOL *Present)
1779 {
1780 HKEY hKey;
1781 DWORD dwType;
1782 DWORD dwValue;
1783 DWORD dwSize;
1784 CONFIGRET ret = CR_SUCCESS;
1785
1786 UNREFERENCED_PARAMETER(hBinding);
1787
1788 DPRINT1("PNP_IsDockStationPresent() called\n");
1789
1790 *Present = FALSE;
1791
1792 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
1793 L"CurrentDockInfo",
1794 0,
1795 KEY_READ,
1796 &hKey) != ERROR_SUCCESS)
1797 return CR_REGISTRY_ERROR;
1798
1799 dwSize = sizeof(DWORD);
1800 if (RegQueryValueExW(hKey,
1801 L"DockingState",
1802 NULL,
1803 &dwType,
1804 (LPBYTE)&dwValue,
1805 &dwSize) != ERROR_SUCCESS)
1806 ret = CR_REGISTRY_ERROR;
1807
1808 RegCloseKey(hKey);
1809
1810 if (ret == CR_SUCCESS)
1811 {
1812 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
1813 {
1814 ret = CR_REGISTRY_ERROR;
1815 }
1816 else if (dwValue != 0)
1817 {
1818 *Present = TRUE;
1819 }
1820 }
1821
1822 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
1823
1824 return ret;
1825 }
1826
1827
1828 /* Function 39 */
1829 DWORD PNP_RequestEjectPC(
1830 handle_t hBinding)
1831 {
1832 UNIMPLEMENTED;
1833 return CR_CALL_NOT_IMPLEMENTED;
1834 }
1835
1836
1837 /* Function 40 */
1838 DWORD PNP_HwProfFlags(
1839 handle_t hBinding,
1840 DWORD ulAction,
1841 LPWSTR pDeviceID,
1842 DWORD ulConfig,
1843 DWORD *pulValue,
1844 PPNP_VETO_TYPE pVetoType,
1845 LPWSTR pszVetoName,
1846 DWORD ulNameLength,
1847 DWORD ulFlags)
1848 {
1849 CONFIGRET ret = CR_SUCCESS;
1850 WCHAR szKeyName[MAX_PATH];
1851 HKEY hKey;
1852 HKEY hDeviceKey;
1853 DWORD dwSize;
1854
1855 UNREFERENCED_PARAMETER(hBinding);
1856
1857 DPRINT("PNP_HwProfFlags() called\n");
1858
1859 if (ulConfig == 0)
1860 {
1861 wcscpy(szKeyName,
1862 L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
1863 }
1864 else
1865 {
1866 swprintf(szKeyName,
1867 L"System\\CurrentControlSet\\HardwareProfiles\\%04u\\System\\CurrentControlSet\\Enum",
1868 ulConfig);
1869 }
1870
1871 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1872 szKeyName,
1873 0,
1874 KEY_QUERY_VALUE,
1875 &hKey) != ERROR_SUCCESS)
1876 return CR_REGISTRY_ERROR;
1877
1878 if (ulAction == PNP_GET_HWPROFFLAGS)
1879 {
1880 if (RegOpenKeyExW(hKey,
1881 pDeviceID,
1882 0,
1883 KEY_QUERY_VALUE,
1884 &hDeviceKey) != ERROR_SUCCESS)
1885 {
1886 *pulValue = 0;
1887 }
1888 else
1889 {
1890 dwSize = sizeof(DWORD);
1891 if (!RegQueryValueExW(hDeviceKey,
1892 L"CSConfigFlags",
1893 NULL,
1894 NULL,
1895 (LPBYTE)pulValue,
1896 &dwSize) != ERROR_SUCCESS)
1897 {
1898 *pulValue = 0;
1899 }
1900
1901 RegCloseKey(hDeviceKey);
1902 }
1903 }
1904 else if (ulAction == PNP_SET_HWPROFFLAGS)
1905 {
1906 /* FIXME: not implemented yet */
1907 ret = CR_CALL_NOT_IMPLEMENTED;
1908 }
1909
1910 RegCloseKey(hKey);
1911
1912 return ret;
1913 }
1914
1915
1916 /* Function 41 */
1917 DWORD PNP_GetHwProfInfo(
1918 handle_t hBinding,
1919 DWORD ulIndex,
1920 HWPROFILEINFO *pHWProfileInfo,
1921 DWORD ulProfileInfoSize,
1922 DWORD ulFlags)
1923 {
1924 UNIMPLEMENTED;
1925 return CR_CALL_NOT_IMPLEMENTED;
1926 }
1927
1928
1929 /* Function 42 */
1930 DWORD PNP_AddEmptyLogConf(
1931 handle_t hBinding,
1932 LPWSTR pDeviceID,
1933 DWORD ulPriority,
1934 DWORD *pulLogConfTag,
1935 DWORD ulFlags)
1936 {
1937 UNIMPLEMENTED;
1938 return CR_CALL_NOT_IMPLEMENTED;
1939 }
1940
1941
1942 /* Function 43 */
1943 DWORD PNP_FreeLogConf(
1944 handle_t hBinding,
1945 LPWSTR pDeviceID,
1946 DWORD ulLogConfType,
1947 DWORD ulLogConfTag,
1948 DWORD ulFlags)
1949 {
1950 UNIMPLEMENTED;
1951 return CR_CALL_NOT_IMPLEMENTED;
1952 }
1953
1954
1955 /* Function 44 */
1956 DWORD PNP_GetFirstLogConf(
1957 handle_t hBinding,
1958 LPWSTR pDeviceID,
1959 DWORD ulLogConfType,
1960 DWORD *pulLogConfTag,
1961 DWORD ulFlags)
1962 {
1963 UNIMPLEMENTED;
1964 return CR_CALL_NOT_IMPLEMENTED;
1965 }
1966
1967
1968 /* Function 45 */
1969 DWORD PNP_GetNextLogConf(
1970 handle_t hBinding,
1971 LPWSTR pDeviceID,
1972 DWORD ulLogConfType,
1973 DWORD ulCurrentTag,
1974 DWORD *pulNextTag,
1975 DWORD ulFlags)
1976 {
1977 UNIMPLEMENTED;
1978 return CR_CALL_NOT_IMPLEMENTED;
1979 }
1980
1981
1982 /* Function 46 */
1983 DWORD PNP_GetLogConfPriority(
1984 handle_t hBinding,
1985 LPWSTR pDeviceID,
1986 DWORD ulType,
1987 DWORD ulTag,
1988 DWORD *pPriority,
1989 DWORD ulFlags)
1990 {
1991 UNIMPLEMENTED;
1992 return CR_CALL_NOT_IMPLEMENTED;
1993 }
1994
1995
1996 /* Function 47 */
1997 DWORD PNP_AddResDes(
1998 handle_t hBinding,
1999 LPWSTR pDeviceID,
2000 DWORD ulLogConfTag,
2001 DWORD ulLogConfType,
2002 RESOURCEID ResourceID,
2003 DWORD *pulResourceTag,
2004 BYTE *ResourceData,
2005 PNP_RPC_BUFFER_SIZE ResourceLen,
2006 DWORD ulFlags)
2007 {
2008 UNIMPLEMENTED;
2009 return CR_CALL_NOT_IMPLEMENTED;
2010 }
2011
2012
2013 /* Function 48 */
2014 DWORD PNP_FreeResDes(
2015 handle_t hBinding,
2016 LPWSTR pDeviceID,
2017 DWORD ulLogConfTag,
2018 DWORD ulLogConfType,
2019 RESOURCEID ResourceID,
2020 DWORD ulResourceTag,
2021 DWORD *pulPreviousResType,
2022 DWORD *pulPreviousResTag,
2023 DWORD ulFlags)
2024 {
2025 UNIMPLEMENTED;
2026 return CR_CALL_NOT_IMPLEMENTED;
2027 }
2028
2029
2030 /* Function 49 */
2031 DWORD PNP_GetNextResDes(
2032 handle_t hBinding,
2033 LPWSTR pDeviceID,
2034 DWORD ulLogConfTag,
2035 DWORD ulLogConfType,
2036 RESOURCEID ResourceID,
2037 DWORD ulResourceTag,
2038 DWORD *pulNextResType,
2039 DWORD *pulNextResTag,
2040 DWORD ulFlags)
2041 {
2042 UNIMPLEMENTED;
2043 return CR_CALL_NOT_IMPLEMENTED;
2044 }
2045
2046
2047 /* Function 50 */
2048 DWORD PNP_GetResDesData(
2049 handle_t hBinding,
2050 LPWSTR pDeviceID,
2051 DWORD ulLogConfTag,
2052 DWORD ulLogConfType,
2053 RESOURCEID ResourceID,
2054 DWORD ulResourceTag,
2055 BYTE *Buffer,
2056 PNP_RPC_BUFFER_SIZE BufferLen,
2057 DWORD ulFlags)
2058 {
2059 UNIMPLEMENTED;
2060 return CR_CALL_NOT_IMPLEMENTED;
2061 }
2062
2063
2064 /* Function 51 */
2065 DWORD PNP_GetResDesDataSize(
2066 handle_t hBinding,
2067 LPWSTR pDeviceID,
2068 DWORD ulLogConfTag,
2069 DWORD ulLogConfType,
2070 RESOURCEID ResourceID,
2071 DWORD ulResourceTag,
2072 DWORD *pulSize,
2073 DWORD ulFlags)
2074 {
2075 UNIMPLEMENTED;
2076 return CR_CALL_NOT_IMPLEMENTED;
2077 }
2078
2079
2080 /* Function 52 */
2081 DWORD PNP_ModifyResDes(
2082 handle_t hBinding,
2083 LPWSTR pDeviceID,
2084 DWORD ulLogConfTag,
2085 DWORD ulLogConfType,
2086 RESOURCEID CurrentResourceID,
2087 RESOURCEID NewResourceID,
2088 DWORD ulResourceTag,
2089 BYTE *ResourceData,
2090 PNP_RPC_BUFFER_SIZE ResourceLen,
2091 DWORD ulFlags)
2092 {
2093 UNIMPLEMENTED;
2094 return CR_CALL_NOT_IMPLEMENTED;
2095 }
2096
2097
2098 /* Function 53 */
2099 DWORD PNP_DetectResourceConflict(
2100 handle_t hBinding,
2101 LPWSTR pDeviceID,
2102 RESOURCEID ResourceID,
2103 BYTE *ResourceData,
2104 PNP_RPC_BUFFER_SIZE ResourceLen,
2105 BOOL *pbConflictDetected,
2106 DWORD ulFlags)
2107 {
2108 UNIMPLEMENTED;
2109 return CR_CALL_NOT_IMPLEMENTED;
2110 }
2111
2112
2113 /* Function 54 */
2114 DWORD PNP_QueryResConfList(
2115 handle_t hBinding,
2116 LPWSTR pDeviceID,
2117 RESOURCEID ResourceID,
2118 BYTE *ResourceData,
2119 PNP_RPC_BUFFER_SIZE ResourceLen,
2120 BYTE *Buffer,
2121 PNP_RPC_BUFFER_SIZE BufferLen,
2122 DWORD ulFlags)
2123 {
2124 UNIMPLEMENTED;
2125 return CR_CALL_NOT_IMPLEMENTED;
2126 }
2127
2128
2129 /* Function 55 */
2130 DWORD PNP_SetHwProf(
2131 handle_t hBinding,
2132 DWORD ulHardwareProfile,
2133 DWORD ulFlags)
2134 {
2135 UNIMPLEMENTED;
2136 return CR_CALL_NOT_IMPLEMENTED;
2137 }
2138
2139
2140 /* Function 56 */
2141 DWORD PNP_QueryArbitratorFreeData(
2142 handle_t hBinding,
2143 BYTE *pData,
2144 DWORD DataLen,
2145 LPWSTR pDeviceID,
2146 RESOURCEID ResourceID,
2147 DWORD ulFlags)
2148 {
2149 UNIMPLEMENTED;
2150 return CR_CALL_NOT_IMPLEMENTED;
2151 }
2152
2153
2154 /* Function 57 */
2155 DWORD PNP_QueryArbitratorFreeSize(
2156 handle_t hBinding,
2157 DWORD *pulSize,
2158 LPWSTR pDeviceID,
2159 RESOURCEID ResourceID,
2160 DWORD ulFlags)
2161 {
2162 UNIMPLEMENTED;
2163 return CR_CALL_NOT_IMPLEMENTED;
2164 }
2165
2166
2167 /* Function 58 */
2168 CONFIGRET
2169 PNP_RunDetection(
2170 handle_t hBinding,
2171 DWORD ulFlags)
2172 {
2173 return CR_CALL_NOT_IMPLEMENTED;
2174 }
2175
2176
2177 /* Function 59 */
2178 DWORD PNP_RegisterNotification(
2179 handle_t hBinding)
2180 {
2181 UNIMPLEMENTED;
2182 return CR_CALL_NOT_IMPLEMENTED;
2183 }
2184
2185
2186 /* Function 60 */
2187 DWORD PNP_UnregisterNotification(
2188 handle_t hBinding)
2189 {
2190 UNIMPLEMENTED;
2191 return CR_CALL_NOT_IMPLEMENTED;
2192 }
2193
2194
2195 /* Function 61 */
2196 DWORD PNP_GetCustomDevProp(
2197 handle_t hBinding,
2198 LPWSTR pDeviceID,
2199 LPWSTR CustomPropName,
2200 DWORD *pulRegDataType,
2201 BYTE *Buffer,
2202 PNP_RPC_STRING_LEN *pulTransferLen,
2203 PNP_RPC_STRING_LEN *pulLength,
2204 DWORD ulFlags)
2205 {
2206 UNIMPLEMENTED;
2207 return CR_CALL_NOT_IMPLEMENTED;
2208 }
2209
2210
2211 /* Function 62 */
2212 DWORD PNP_GetVersionInternal(
2213 handle_t hBinding,
2214 WORD *pwVersion)
2215 {
2216 UNIMPLEMENTED;
2217 return CR_CALL_NOT_IMPLEMENTED;
2218 }
2219
2220
2221 /* Function 63 */
2222 DWORD PNP_GetBlockedDriverInfo(
2223 handle_t hBinding,
2224 BYTE *Buffer,
2225 PNP_RPC_BUFFER_SIZE *pulTransferLen,
2226 PNP_RPC_BUFFER_SIZE *pulLength,
2227 DWORD ulFlags)
2228 {
2229 UNIMPLEMENTED;
2230 return CR_CALL_NOT_IMPLEMENTED;
2231 }
2232
2233
2234 /* Function 64 */
2235 DWORD PNP_GetServerSideDeviceInstallFlags(
2236 handle_t hBinding,
2237 DWORD *pulSSDIFlags,
2238 DWORD ulFlags)
2239 {
2240 UNIMPLEMENTED;
2241 return CR_CALL_NOT_IMPLEMENTED;
2242 }
2243
2244
2245 /* Function 65 */
2246 DWORD PNP_GetObjectPropKeys(
2247 handle_t hBinding,
2248 LPWSTR ObjectName,
2249 DWORD ObjectType,
2250 LPWSTR PropertyCultureName,
2251 PNP_PROP_COUNT *PropertyCount,
2252 PNP_PROP_COUNT *TransferLen,
2253 DEVPROPKEY *PropertyKeys,
2254 DWORD Flags)
2255 {
2256 UNIMPLEMENTED;
2257 return CR_CALL_NOT_IMPLEMENTED;
2258 }
2259
2260
2261 /* Function 66 */
2262 DWORD PNP_GetObjectProp(
2263 handle_t hBinding,
2264 LPWSTR ObjectName,
2265 DWORD ObjectType,
2266 LPWSTR PropertyCultureName,
2267 const DEVPROPKEY *PropertyKey,
2268 DEVPROPTYPE *PropertyType,
2269 PNP_PROP_SIZE *PropertySize,
2270 PNP_PROP_SIZE *TransferLen,
2271 BYTE *PropertyBuffer,
2272 DWORD Flags)
2273 {
2274 UNIMPLEMENTED;
2275 return CR_CALL_NOT_IMPLEMENTED;
2276 }
2277
2278
2279 /* Function 67 */
2280 DWORD PNP_SetObjectProp(
2281 handle_t hBinding,
2282 LPWSTR ObjectName,
2283 DWORD ObjectType,
2284 LPWSTR PropertyCultureName,
2285 const DEVPROPKEY *PropertyKey,
2286 DEVPROPTYPE PropertyType,
2287 PNP_PROP_SIZE PropertySize,
2288 BYTE *PropertyBuffer,
2289 DWORD Flags)
2290 {
2291 UNIMPLEMENTED;
2292 return CR_CALL_NOT_IMPLEMENTED;
2293 }
2294
2295
2296 /* Function 68 */
2297 DWORD PNP_InstallDevInst(
2298 handle_t hBinding)
2299 {
2300 UNIMPLEMENTED;
2301 return CR_CALL_NOT_IMPLEMENTED;
2302 }
2303
2304
2305 /* Function 69 */
2306 DWORD PNP_ApplyPowerSettings(
2307 handle_t hBinding)
2308 {
2309 UNIMPLEMENTED;
2310 return CR_CALL_NOT_IMPLEMENTED;
2311 }
2312
2313
2314 /* Function 70 */
2315 DWORD PNP_DriverStoreAddDriverPackage(
2316 handle_t hBinding)
2317 {
2318 UNIMPLEMENTED;
2319 return CR_CALL_NOT_IMPLEMENTED;
2320 }
2321
2322
2323 /* Function 71 */
2324 DWORD PNP_DriverStoreDeleteDriverPackage(
2325 handle_t hBinding)
2326 {
2327 UNIMPLEMENTED;
2328 return CR_CALL_NOT_IMPLEMENTED;
2329 }
2330
2331
2332 /* Function 72 */
2333 DWORD PNP_RegisterServiceNotification(
2334 handle_t hBinding)
2335 {
2336 UNIMPLEMENTED;
2337 return CR_CALL_NOT_IMPLEMENTED;
2338 }
2339
2340
2341 /* Function 73 */
2342 DWORD PNP_SetActiveService(
2343 handle_t hBinding)
2344 {
2345 UNIMPLEMENTED;
2346 return CR_CALL_NOT_IMPLEMENTED;
2347 }
2348
2349
2350 /* Function 74 */
2351 DWORD PNP_DeleteServiceDevices(
2352 handle_t hBinding)
2353 {
2354 UNIMPLEMENTED;
2355 return CR_CALL_NOT_IMPLEMENTED;
2356 }
2357
2358
2359 static BOOL
2360 InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
2361 {
2362 BOOL DeviceInstalled = FALSE;
2363 DWORD BytesWritten;
2364 DWORD Value;
2365 HANDLE hPipe = INVALID_HANDLE_VALUE;
2366 LPVOID Environment = NULL;
2367 PROCESS_INFORMATION ProcessInfo;
2368 STARTUPINFOW StartupInfo;
2369 UUID RandomUuid;
2370 HKEY DeviceKey;
2371
2372 /* The following lengths are constant (see below), they cannot overflow */
2373 WCHAR CommandLine[116];
2374 WCHAR InstallEventName[73];
2375 WCHAR PipeName[74];
2376 WCHAR UuidString[39];
2377
2378 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance, ShowWizard);
2379
2380 ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
2381
2382 if (RegOpenKeyExW(hEnumKey,
2383 DeviceInstance,
2384 0,
2385 KEY_QUERY_VALUE,
2386 &DeviceKey) == ERROR_SUCCESS)
2387 {
2388 if (RegQueryValueExW(DeviceKey,
2389 L"ClassGUID",
2390 NULL,
2391 NULL,
2392 NULL,
2393 NULL) == ERROR_SUCCESS)
2394 {
2395 DPRINT("No need to install: %S\n", DeviceInstance);
2396 RegCloseKey(DeviceKey);
2397 return TRUE;
2398 }
2399
2400 RegCloseKey(DeviceKey);
2401 }
2402
2403 DPRINT1("Installing: %S\n", DeviceInstance);
2404
2405 /* Create a random UUID for the named pipe */
2406 UuidCreate(&RandomUuid);
2407 swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
2408 RandomUuid.Data1, RandomUuid.Data2, RandomUuid.Data3,
2409 RandomUuid.Data4[0], RandomUuid.Data4[1], RandomUuid.Data4[2],
2410 RandomUuid.Data4[3], RandomUuid.Data4[4], RandomUuid.Data4[5],
2411 RandomUuid.Data4[6], RandomUuid.Data4[7]);
2412
2413 /* Create the named pipe */
2414 wcscpy(PipeName, L"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
2415 wcscat(PipeName, UuidString);
2416 hPipe = CreateNamedPipeW(PipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 512, 512, 0, NULL);
2417
2418 if(hPipe == INVALID_HANDLE_VALUE)
2419 {
2420 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
2421 goto cleanup;
2422 }
2423
2424 /* Launch rundll32 to call ClientSideInstallW */
2425 wcscpy(CommandLine, L"rundll32.exe newdev.dll,ClientSideInstall ");
2426 wcscat(CommandLine, PipeName);
2427
2428 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
2429 StartupInfo.cb = sizeof(StartupInfo);
2430
2431 if(hUserToken)
2432 {
2433 /* newdev has to run under the environment of the current user */
2434 if(!CreateEnvironmentBlock(&Environment, hUserToken, FALSE))
2435 {
2436 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
2437 goto cleanup;
2438 }
2439
2440 if(!CreateProcessAsUserW(hUserToken, NULL, CommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, Environment, NULL, &StartupInfo, &ProcessInfo))
2441 {
2442 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
2443 goto cleanup;
2444 }
2445 }
2446 else
2447 {
2448 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
2449
2450 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
2451 (ShowWizard is only set to FALSE for these two modes) */
2452 ASSERT(!ShowWizard);
2453
2454 if(!CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo))
2455 {
2456 DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
2457 goto cleanup;
2458 }
2459 }
2460
2461 /* Wait for the function to connect to our pipe */
2462 if(!ConnectNamedPipe(hPipe, NULL))
2463 {
2464 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
2465 goto cleanup;
2466 }
2467
2468 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
2469 wcscpy(InstallEventName, L"Global\\PNP_Device_Install_Event_0.");
2470 wcscat(InstallEventName, UuidString);
2471
2472 Value = sizeof(InstallEventName);
2473 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
2474 WriteFile(hPipe, InstallEventName, Value, &BytesWritten, NULL);
2475
2476 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
2477 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
2478 WriteFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesWritten, NULL);
2479
2480 Value = (wcslen(DeviceInstance) + 1) * sizeof(WCHAR);
2481 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
2482 WriteFile(hPipe, DeviceInstance, Value, &BytesWritten, NULL);
2483
2484 /* Wait for newdev.dll to finish processing */
2485 WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
2486
2487 /* The following check for success is probably not compatible to Windows, but should do its job */
2488 if(!GetExitCodeProcess(ProcessInfo.hProcess, &Value))
2489 {
2490 DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
2491 goto cleanup;
2492 }
2493
2494 DeviceInstalled = Value;
2495
2496 cleanup:
2497 if(hPipe != INVALID_HANDLE_VALUE)
2498 CloseHandle(hPipe);
2499
2500 if(Environment)
2501 DestroyEnvironmentBlock(Environment);
2502
2503 if(ProcessInfo.hProcess)
2504 CloseHandle(ProcessInfo.hProcess);
2505
2506 if(ProcessInfo.hThread)
2507 CloseHandle(ProcessInfo.hThread);
2508
2509 DPRINT1("Success? %d\n", DeviceInstalled);
2510
2511 return DeviceInstalled;
2512 }
2513
2514
2515 static LONG
2516 ReadRegSzKey(
2517 IN HKEY hKey,
2518 IN LPCWSTR pszKey,
2519 OUT LPWSTR* pValue)
2520 {
2521 LONG rc;
2522 DWORD dwType;
2523 DWORD cbData = 0;
2524 LPWSTR Value;
2525
2526 if (!pValue)
2527 return ERROR_INVALID_PARAMETER;
2528
2529 *pValue = NULL;
2530 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
2531 if (rc != ERROR_SUCCESS)
2532 return rc;
2533 if (dwType != REG_SZ)
2534 return ERROR_FILE_NOT_FOUND;
2535 Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
2536 if (!Value)
2537 return ERROR_NOT_ENOUGH_MEMORY;
2538 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
2539 if (rc != ERROR_SUCCESS)
2540 {
2541 HeapFree(GetProcessHeap(), 0, Value);
2542 return rc;
2543 }
2544 /* NULL-terminate the string */
2545 Value[cbData / sizeof(WCHAR)] = '\0';
2546
2547 *pValue = Value;
2548 return ERROR_SUCCESS;
2549 }
2550
2551
2552 static BOOL
2553 SetupIsActive(VOID)
2554 {
2555 HKEY hKey = NULL;
2556 DWORD regType, active, size;
2557 LONG rc;
2558 BOOL ret = FALSE;
2559
2560 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
2561 if (rc != ERROR_SUCCESS)
2562 goto cleanup;
2563
2564 size = sizeof(DWORD);
2565 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
2566 if (rc != ERROR_SUCCESS)
2567 goto cleanup;
2568 if (regType != REG_DWORD || size != sizeof(DWORD))
2569 goto cleanup;
2570
2571 ret = (active != 0);
2572
2573 cleanup:
2574 if (hKey != NULL)
2575 RegCloseKey(hKey);
2576
2577 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
2578
2579 return ret;
2580 }
2581
2582
2583 static BOOL
2584 IsConsoleBoot(VOID)
2585 {
2586 HKEY ControlKey = NULL;
2587 LPWSTR SystemStartOptions = NULL;
2588 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
2589 BOOL ConsoleBoot = FALSE;
2590 LONG rc;
2591
2592 rc = RegOpenKeyExW(
2593 HKEY_LOCAL_MACHINE,
2594 L"SYSTEM\\CurrentControlSet\\Control",
2595 0,
2596 KEY_QUERY_VALUE,
2597 &ControlKey);
2598
2599 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
2600 if (rc != ERROR_SUCCESS)
2601 goto cleanup;
2602
2603 /* Check for CMDCONS in SystemStartOptions */
2604 CurrentOption = SystemStartOptions;
2605 while (CurrentOption)
2606 {
2607 NextOption = wcschr(CurrentOption, L' ');
2608 if (NextOption)
2609 *NextOption = L'\0';
2610 if (_wcsicmp(CurrentOption, L"CONSOLE") == 0)
2611 {
2612 DPRINT("Found %S. Switching to console boot\n", CurrentOption);
2613 ConsoleBoot = TRUE;
2614 goto cleanup;
2615 }
2616 CurrentOption = NextOption ? NextOption + 1 : NULL;
2617 }
2618
2619 cleanup:
2620 if (ControlKey != NULL)
2621 RegCloseKey(ControlKey);
2622 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
2623 return ConsoleBoot;
2624 }
2625
2626
2627 /* Loop to install all queued devices installations */
2628 static DWORD WINAPI
2629 DeviceInstallThread(LPVOID lpParameter)
2630 {
2631 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2632 PSLIST_ENTRY ListEntry;
2633 #else
2634 PLIST_ENTRY ListEntry;
2635 #endif
2636 DeviceInstallParams* Params;
2637 BOOL showWizard;
2638
2639 UNREFERENCED_PARAMETER(lpParameter);
2640
2641 WaitForSingleObject(hInstallEvent, INFINITE);
2642
2643 showWizard = !SetupIsActive() && !IsConsoleBoot();
2644
2645 while (TRUE)
2646 {
2647 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2648 ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead);
2649 #else
2650 if ((BOOL)IsListEmpty(&DeviceInstallListHead))
2651 ListEntry = NULL;
2652 else
2653 ListEntry = RemoveHeadList(&DeviceInstallListHead);
2654 #endif
2655 if (ListEntry == NULL)
2656 {
2657 SetEvent(hNoPendingInstalls);
2658 WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE);
2659 }
2660 else
2661 {
2662 ResetEvent(hNoPendingInstalls);
2663 Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry);
2664 InstallDevice(Params->DeviceIds, showWizard);
2665 }
2666 }
2667
2668 return 0;
2669 }
2670
2671
2672 static DWORD WINAPI
2673 PnpEventThread(LPVOID lpParameter)
2674 {
2675 PPLUGPLAY_EVENT_BLOCK PnpEvent;
2676 ULONG PnpEventSize;
2677 NTSTATUS Status;
2678 RPC_STATUS RpcStatus;
2679
2680 UNREFERENCED_PARAMETER(lpParameter);
2681
2682 PnpEventSize = 0x1000;
2683 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
2684 if (PnpEvent == NULL)
2685 return ERROR_OUTOFMEMORY;
2686
2687 for (;;)
2688 {
2689 DPRINT("Calling NtGetPlugPlayEvent()\n");
2690
2691 /* Wait for the next pnp event */
2692 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
2693
2694 /* Resize the buffer for the PnP event if it's too small. */
2695 if (Status == STATUS_BUFFER_TOO_SMALL)
2696 {
2697 PnpEventSize += 0x400;
2698 HeapFree(GetProcessHeap(), 0, PnpEvent);
2699 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
2700 if (PnpEvent == NULL)
2701 return ERROR_OUTOFMEMORY;
2702 continue;
2703 }
2704
2705 if (!NT_SUCCESS(Status))
2706 {
2707 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status);
2708 break;
2709 }
2710
2711 /* Process the pnp event */
2712 DPRINT("Received PnP Event\n");
2713 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ENUMERATED, &RpcStatus))
2714 {
2715 DeviceInstallParams* Params;
2716 DWORD len;
2717 DWORD DeviceIdLength;
2718
2719 DPRINT1("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds);
2720
2721 DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds);
2722 if (DeviceIdLength)
2723 {
2724 /* Queue device install (will be dequeued by DeviceInstallThread */
2725 len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
2726 Params = HeapAlloc(GetProcessHeap(), 0, len);
2727 if (Params)
2728 {
2729 wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
2730 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2731 InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry);
2732 #else
2733 InsertTailList(&DeviceInstallListHead, &Params->ListEntry);
2734 #endif
2735 SetEvent(hDeviceInstallListNotEmpty);
2736 }
2737 }
2738 }
2739 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
2740 {
2741 DPRINT1("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds);
2742 /* FIXME: ? */
2743 }
2744 else
2745 {
2746 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
2747 PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
2748 PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
2749 PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
2750 PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
2751 }
2752
2753 /* Dequeue the current pnp event and signal the next one */
2754 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
2755 }
2756
2757 HeapFree(GetProcessHeap(), 0, PnpEvent);
2758
2759 return ERROR_SUCCESS;
2760 }
2761
2762
2763 static VOID
2764 UpdateServiceStatus(DWORD dwState)
2765 {
2766 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
2767 ServiceStatus.dwCurrentState = dwState;
2768 ServiceStatus.dwControlsAccepted = 0;
2769 ServiceStatus.dwWin32ExitCode = 0;
2770 ServiceStatus.dwServiceSpecificExitCode = 0;
2771 ServiceStatus.dwCheckPoint = 0;
2772
2773 if (dwState == SERVICE_START_PENDING ||
2774 dwState == SERVICE_STOP_PENDING ||
2775 dwState == SERVICE_PAUSE_PENDING ||
2776 dwState == SERVICE_CONTINUE_PENDING)
2777 ServiceStatus.dwWaitHint = 10000;
2778 else
2779 ServiceStatus.dwWaitHint = 0;
2780
2781 SetServiceStatus(ServiceStatusHandle,
2782 &ServiceStatus);
2783 }
2784
2785
2786 static DWORD WINAPI
2787 ServiceControlHandler(DWORD dwControl,
2788 DWORD dwEventType,
2789 LPVOID lpEventData,
2790 LPVOID lpContext)
2791 {
2792 DPRINT1("ServiceControlHandler() called\n");
2793
2794 switch (dwControl)
2795 {
2796 case SERVICE_CONTROL_STOP:
2797 DPRINT1(" SERVICE_CONTROL_STOP received\n");
2798 UpdateServiceStatus(SERVICE_STOPPED);
2799 return ERROR_SUCCESS;
2800
2801 case SERVICE_CONTROL_PAUSE:
2802 DPRINT1(" SERVICE_CONTROL_PAUSE received\n");
2803 UpdateServiceStatus(SERVICE_PAUSED);
2804 return ERROR_SUCCESS;
2805
2806 case SERVICE_CONTROL_CONTINUE:
2807 DPRINT1(" SERVICE_CONTROL_CONTINUE received\n");
2808 UpdateServiceStatus(SERVICE_RUNNING);
2809 return ERROR_SUCCESS;
2810
2811 case SERVICE_CONTROL_INTERROGATE:
2812 DPRINT1(" SERVICE_CONTROL_INTERROGATE received\n");
2813 SetServiceStatus(ServiceStatusHandle,
2814 &ServiceStatus);
2815 return ERROR_SUCCESS;
2816
2817 case SERVICE_CONTROL_SHUTDOWN:
2818 DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n");
2819 UpdateServiceStatus(SERVICE_STOPPED);
2820 return ERROR_SUCCESS;
2821
2822 default :
2823 DPRINT1(" Control %lu received\n");
2824 return ERROR_CALL_NOT_IMPLEMENTED;
2825 }
2826 }
2827
2828
2829 static VOID CALLBACK
2830 ServiceMain(DWORD argc, LPTSTR *argv)
2831 {
2832 HANDLE hThread;
2833 DWORD dwThreadId;
2834
2835 UNREFERENCED_PARAMETER(argc);
2836 UNREFERENCED_PARAMETER(argv);
2837
2838 DPRINT("ServiceMain() called\n");
2839
2840 ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
2841 ServiceControlHandler,
2842 NULL);
2843 if (!ServiceStatusHandle)
2844 {
2845 DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
2846 return;
2847 }
2848
2849 UpdateServiceStatus(SERVICE_START_PENDING);
2850
2851 hThread = CreateThread(NULL,
2852 0,
2853 PnpEventThread,
2854 NULL,
2855 0,
2856 &dwThreadId);
2857 if (hThread != NULL)
2858 CloseHandle(hThread);
2859
2860 hThread = CreateThread(NULL,
2861 0,
2862 RpcServerThread,
2863 NULL,
2864 0,
2865 &dwThreadId);
2866 if (hThread != NULL)
2867 CloseHandle(hThread);
2868
2869 hThread = CreateThread(NULL,
2870 0,
2871 DeviceInstallThread,
2872 NULL,
2873 0,
2874 &dwThreadId);
2875 if (hThread != NULL)
2876 CloseHandle(hThread);
2877
2878 UpdateServiceStatus(SERVICE_RUNNING);
2879
2880 DPRINT("ServiceMain() done\n");
2881 }
2882
2883
2884 int
2885 wmain(int argc, WCHAR *argv[])
2886 {
2887 BOOLEAN OldValue;
2888 DWORD dwError;
2889
2890 UNREFERENCED_PARAMETER(argc);
2891 UNREFERENCED_PARAMETER(argv);
2892
2893 DPRINT("Umpnpmgr: main() started\n");
2894
2895 /* We need this privilege for using CreateProcessAsUserW */
2896 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue);
2897
2898 hInstallEvent = CreateEvent(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
2899 if (hInstallEvent == NULL)
2900 {
2901 dwError = GetLastError();
2902 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
2903 return dwError;
2904 }
2905
2906 hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL);
2907 if (hDeviceInstallListNotEmpty == NULL)
2908 {
2909 dwError = GetLastError();
2910 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
2911 return dwError;
2912 }
2913
2914 hNoPendingInstalls = CreateEventW(NULL,
2915 TRUE,
2916 FALSE,
2917 L"Global\\PnP_No_Pending_Install_Events");
2918 if (hNoPendingInstalls == NULL)
2919 {
2920 dwError = GetLastError();
2921 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
2922 return dwError;
2923 }
2924
2925 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2926 InitializeSListHead(&DeviceInstallListHead);
2927 #else
2928 InitializeListHead(&DeviceInstallListHead);
2929 #endif
2930
2931 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2932 L"System\\CurrentControlSet\\Enum",
2933 0,
2934 KEY_ALL_ACCESS,
2935 &hEnumKey);
2936 if (dwError != ERROR_SUCCESS)
2937 {
2938 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
2939 return dwError;
2940 }
2941
2942 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2943 L"System\\CurrentControlSet\\Control\\Class",
2944 0,
2945 KEY_ALL_ACCESS,
2946 &hClassKey);
2947 if (dwError != ERROR_SUCCESS)
2948 {
2949 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
2950 return dwError;
2951 }
2952
2953 StartServiceCtrlDispatcher(ServiceTable);
2954
2955 DPRINT("Umpnpmgr: main() done\n");
2956
2957 ExitThread(0);
2958
2959 return 0;
2960 }
2961
2962 /* EOF */