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