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