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