Synchronize up to trunk's revision r57756.
[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 #include <windows.h>
33 #include <stdio.h>
34 #include <cmtypes.h>
35 #include <cmfuncs.h>
36 #include <rtlfuncs.h>
37 #include <setypes.h>
38 #include <umpnpmgr/sysguid.h>
39 #include <wdmguid.h>
40 #include <cfgmgr32.h>
41 #include <regstr.h>
42 #include <userenv.h>
43
44 #include <rpc.h>
45 #include <rpcdce.h>
46
47 #include "pnp_s.h"
48
49 #define NDEBUG
50 #include <debug.h>
51
52 /* GLOBALS ******************************************************************/
53
54 static VOID CALLBACK ServiceMain(DWORD argc, LPWSTR *argv);
55 static WCHAR ServiceName[] = L"PlugPlay";
56 static SERVICE_TABLE_ENTRYW ServiceTable[] =
57 {
58 {ServiceName, ServiceMain},
59 {NULL, NULL}
60 };
61
62 static SERVICE_STATUS_HANDLE ServiceStatusHandle;
63 static SERVICE_STATUS ServiceStatus;
64
65 static WCHAR szRootDeviceId[] = L"HTREE\\ROOT\\0";
66
67 static HKEY hEnumKey = NULL;
68 static HKEY hClassKey = NULL;
69
70 static HANDLE hUserToken = NULL;
71 static HANDLE hInstallEvent = NULL;
72 static HANDLE hNoPendingInstalls = NULL;
73
74 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
75 static SLIST_HEADER DeviceInstallListHead;
76 #else
77 static LIST_ENTRY DeviceInstallListHead;
78 #endif
79 static HANDLE hDeviceInstallListNotEmpty;
80
81 typedef struct
82 {
83 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
84 SLIST_ENTRY ListEntry;
85 #else
86 LIST_ENTRY ListEntry;
87 #endif
88 WCHAR DeviceIds[1];
89 } DeviceInstallParams;
90
91 /* FUNCTIONS *****************************************************************/
92
93 static DWORD WINAPI
94 RpcServerThread(LPVOID lpParameter)
95 {
96 RPC_STATUS Status;
97 BOOLEAN RegisteredProtSeq = FALSE;
98
99 UNREFERENCED_PARAMETER(lpParameter);
100
101 DPRINT("RpcServerThread() called\n");
102
103 #if 0
104 /* XP-compatible protocol sequence/endpoint */
105 Status = RpcServerUseProtseqEpW(L"ncacn_np",
106 20,
107 L"\\pipe\\ntsvcs",
108 NULL); // Security descriptor
109 if (Status == RPC_S_OK)
110 RegisteredProtSeq = TRUE;
111 else
112 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
113 #endif
114
115 /* Vista-compatible protocol sequence/endpoint */
116 Status = RpcServerUseProtseqEpW(L"ncacn_np",
117 20,
118 L"\\pipe\\plugplay",
119 NULL); // Security descriptor
120 if (Status == RPC_S_OK)
121 RegisteredProtSeq = TRUE;
122 else
123 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
124
125 /* Make sure there's a usable endpoint */
126 if (RegisteredProtSeq == FALSE)
127 return 0;
128
129 Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec,
130 NULL,
131 NULL);
132 if (Status != RPC_S_OK)
133 {
134 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
135 return 0;
136 }
137
138 Status = RpcServerListen(1,
139 20,
140 FALSE);
141 if (Status != RPC_S_OK)
142 {
143 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
144 return 0;
145 }
146
147 /* ROS HACK (this should never happen...) */
148 DPRINT1("*** Other devices won't be installed correctly. If something\n");
149 DPRINT1("*** doesn't work, try to reboot to get a new chance.\n");
150
151 DPRINT("RpcServerThread() done\n");
152
153 return 0;
154 }
155
156
157 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
158 {
159 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
160 }
161
162
163 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
164 {
165 HeapFree(GetProcessHeap(), 0, ptr);
166 }
167
168
169 static CONFIGRET WINAPI
170 NtStatusToCrError(NTSTATUS Status)
171 {
172 switch (Status)
173 {
174 case STATUS_NO_SUCH_DEVICE:
175 return CR_NO_SUCH_DEVINST;
176
177 default:
178 /* FIXME: add more mappings */
179 DPRINT1("Unable to map status 0x%08lx\n", Status);
180 return CR_FAILURE;
181 }
182 }
183
184
185 /* Function 0 */
186 DWORD PNP_Disconnect(
187 handle_t hBinding)
188 {
189 UNREFERENCED_PARAMETER(hBinding);
190 return CR_SUCCESS;
191 }
192
193
194 /* Function 1 */
195 DWORD PNP_Connect(
196 handle_t hBinding)
197 {
198 UNREFERENCED_PARAMETER(hBinding);
199 return CR_SUCCESS;
200 }
201
202
203 /* Function 2 */
204 DWORD PNP_GetVersion(
205 handle_t hBinding,
206 WORD *pVersion)
207 {
208 UNREFERENCED_PARAMETER(hBinding);
209
210 *pVersion = 0x0400;
211 return CR_SUCCESS;
212 }
213
214
215 /* Function 3 */
216 DWORD PNP_GetGlobalState(
217 handle_t hBinding,
218 DWORD *pulState,
219 DWORD ulFlags)
220 {
221 UNREFERENCED_PARAMETER(hBinding);
222 UNREFERENCED_PARAMETER(ulFlags);
223
224 *pulState = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE;
225 return CR_SUCCESS;
226 }
227
228
229 /* Function 4 */
230 DWORD PNP_InitDetection(
231 handle_t hBinding)
232 {
233 UNREFERENCED_PARAMETER(hBinding);
234
235 DPRINT("PNP_InitDetection() called\n");
236 return CR_SUCCESS;
237 }
238
239
240 /* Function 5 */
241 DWORD PNP_ReportLogOn(
242 handle_t hBinding,
243 BOOL Admin,
244 DWORD ProcessId)
245 {
246 DWORD ReturnValue = CR_FAILURE;
247 HANDLE hProcess;
248
249 UNREFERENCED_PARAMETER(hBinding);
250 UNREFERENCED_PARAMETER(Admin);
251
252 DPRINT("PNP_ReportLogOn(%u, %u) called\n", Admin, ProcessId);
253
254 /* Get the users token */
255 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId);
256
257 if(!hProcess)
258 {
259 DPRINT1("OpenProcess failed with error %u\n", GetLastError());
260 goto cleanup;
261 }
262
263 if (hUserToken)
264 {
265 CloseHandle(hUserToken);
266 hUserToken = NULL;
267 }
268
269 if(!OpenProcessToken(hProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY, &hUserToken))
270 {
271 DPRINT1("OpenProcessToken failed with error %u\n", GetLastError());
272 goto cleanup;
273 }
274
275 /* Trigger the installer thread */
276 if (hInstallEvent)
277 SetEvent(hInstallEvent);
278
279 ReturnValue = CR_SUCCESS;
280
281 cleanup:
282 if(hProcess)
283 CloseHandle(hProcess);
284
285 return ReturnValue;
286 }
287
288
289 /* Function 6 */
290 DWORD PNP_ValidateDeviceInstance(
291 handle_t hBinding,
292 LPWSTR pDeviceID,
293 DWORD ulFlags)
294 {
295 CONFIGRET ret = CR_SUCCESS;
296 HKEY hDeviceKey = NULL;
297
298 UNREFERENCED_PARAMETER(hBinding);
299 UNREFERENCED_PARAMETER(ulFlags);
300
301 DPRINT("PNP_ValidateDeviceInstance(%S %lx) called\n",
302 pDeviceID, ulFlags);
303
304 if (RegOpenKeyExW(hEnumKey,
305 pDeviceID,
306 0,
307 KEY_READ,
308 &hDeviceKey))
309 {
310 DPRINT("Could not open the Device Key!\n");
311 ret = CR_NO_SUCH_DEVNODE;
312 goto Done;
313 }
314
315 /* FIXME: add more tests */
316
317 Done:
318 if (hDeviceKey != NULL)
319 RegCloseKey(hDeviceKey);
320
321 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret);
322
323 return ret;
324 }
325
326
327 /* Function 7 */
328 DWORD PNP_GetRootDeviceInstance(
329 handle_t hBinding,
330 LPWSTR pDeviceID,
331 PNP_RPC_STRING_LEN ulLength)
332 {
333 CONFIGRET ret = CR_SUCCESS;
334
335 UNREFERENCED_PARAMETER(hBinding);
336
337 DPRINT("PNP_GetRootDeviceInstance() called\n");
338
339 if (!pDeviceID)
340 {
341 ret = CR_INVALID_POINTER;
342 goto Done;
343 }
344 if (ulLength < lstrlenW(szRootDeviceId) + 1)
345 {
346 ret = CR_BUFFER_SMALL;
347 goto Done;
348 }
349
350 lstrcpyW(pDeviceID,
351 szRootDeviceId);
352
353 Done:
354 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret);
355
356 return ret;
357 }
358
359
360 /* Function 8 */
361 DWORD PNP_GetRelatedDeviceInstance(
362 handle_t hBinding,
363 DWORD ulRelationship,
364 LPWSTR pDeviceID,
365 LPWSTR pRelatedDeviceId,
366 PNP_RPC_STRING_LEN *pulLength,
367 DWORD ulFlags)
368 {
369 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData;
370 CONFIGRET ret = CR_SUCCESS;
371 NTSTATUS Status;
372
373 UNREFERENCED_PARAMETER(hBinding);
374 UNREFERENCED_PARAMETER(ulFlags);
375
376 DPRINT("PNP_GetRelatedDeviceInstance() called\n");
377 DPRINT(" Relationship %ld\n", ulRelationship);
378 DPRINT(" DeviceId %S\n", pDeviceID);
379
380 RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance,
381 pDeviceID);
382
383 PlugPlayData.Relation = ulRelationship;
384
385 PlugPlayData.RelatedDeviceInstanceLength = *pulLength;
386 PlugPlayData.RelatedDeviceInstance = pRelatedDeviceId;
387
388 Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice,
389 (PVOID)&PlugPlayData,
390 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA));
391 if (!NT_SUCCESS(Status))
392 {
393 ret = NtStatusToCrError(Status);
394 }
395
396 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret);
397 if (ret == CR_SUCCESS)
398 {
399 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance);
400 }
401
402 return ret;
403 }
404
405
406 /* Function 9 */
407 DWORD PNP_EnumerateSubKeys(
408 handle_t hBinding,
409 DWORD ulBranch,
410 DWORD ulIndex,
411 LPWSTR Buffer,
412 PNP_RPC_STRING_LEN ulLength,
413 PNP_RPC_STRING_LEN *pulRequiredLen,
414 DWORD ulFlags)
415 {
416 CONFIGRET ret = CR_SUCCESS;
417 HKEY hKey;
418 DWORD dwError;
419
420 UNREFERENCED_PARAMETER(hBinding);
421 UNREFERENCED_PARAMETER(ulFlags);
422
423 DPRINT("PNP_EnumerateSubKeys() called\n");
424
425 switch (ulBranch)
426 {
427 case PNP_ENUMERATOR_SUBKEYS:
428 hKey = hEnumKey;
429 break;
430
431 case PNP_CLASS_SUBKEYS:
432 hKey = hClassKey;
433 break;
434
435 default:
436 return CR_FAILURE;
437 }
438
439 *pulRequiredLen = ulLength;
440 dwError = RegEnumKeyExW(hKey,
441 ulIndex,
442 Buffer,
443 pulRequiredLen,
444 NULL,
445 NULL,
446 NULL,
447 NULL);
448 if (dwError != ERROR_SUCCESS)
449 {
450 ret = (dwError == ERROR_NO_MORE_ITEMS) ? CR_NO_SUCH_VALUE : CR_FAILURE;
451 }
452 else
453 {
454 (*pulRequiredLen)++;
455 }
456
457 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret);
458
459 return ret;
460 }
461
462
463 /* Function 10 */
464 DWORD PNP_GetDeviceList(
465 handle_t hBinding,
466 LPWSTR pszFilter,
467 LPWSTR Buffer,
468 PNP_RPC_STRING_LEN *pulLength,
469 DWORD ulFlags)
470 {
471 UNIMPLEMENTED;
472 return CR_CALL_NOT_IMPLEMENTED;
473 }
474
475
476 /* Function 11 */
477 DWORD PNP_GetDeviceListSize(
478 handle_t hBinding,
479 LPWSTR pszFilter,
480 PNP_RPC_BUFFER_SIZE *pulLen,
481 DWORD ulFlags)
482 {
483 UNIMPLEMENTED;
484 return CR_CALL_NOT_IMPLEMENTED;
485 }
486
487
488 /* Function 12 */
489 DWORD PNP_GetDepth(
490 handle_t hBinding,
491 LPWSTR pszDeviceID,
492 DWORD *pulDepth,
493 DWORD ulFlags)
494 {
495 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData;
496 CONFIGRET ret = CR_SUCCESS;
497 NTSTATUS Status;
498
499 UNREFERENCED_PARAMETER(hBinding);
500 UNREFERENCED_PARAMETER(ulFlags);
501
502 DPRINT("PNP_GetDepth() called\n");
503
504 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
505 pszDeviceID);
506
507 Status = NtPlugPlayControl(PlugPlayControlGetDeviceDepth,
508 (PVOID)&PlugPlayData,
509 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA));
510 if (NT_SUCCESS(Status))
511 {
512 *pulDepth = PlugPlayData.Depth;
513 }
514 else
515 {
516 ret = NtStatusToCrError(Status);
517 }
518
519 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret);
520
521 return ret;
522 }
523
524
525 /* Function 13 */
526 DWORD PNP_GetDeviceRegProp(
527 handle_t hBinding,
528 LPWSTR pDeviceID,
529 DWORD ulProperty,
530 DWORD *pulRegDataType,
531 BYTE *Buffer,
532 PNP_PROP_SIZE *pulTransferLen,
533 PNP_PROP_SIZE *pulLength,
534 DWORD ulFlags)
535 {
536 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData;
537 CONFIGRET ret = CR_SUCCESS;
538 LPWSTR lpValueName = NULL;
539 HKEY hKey = NULL;
540 LONG lError;
541 NTSTATUS Status;
542
543 UNREFERENCED_PARAMETER(hBinding);
544
545 DPRINT("PNP_GetDeviceRegProp() called\n");
546
547 if (pulTransferLen == NULL || pulLength == NULL)
548 {
549 ret = CR_INVALID_POINTER;
550 goto done;
551 }
552
553 if (ulFlags != 0)
554 {
555 ret = CR_INVALID_FLAG;
556 goto done;
557 }
558
559 /* FIXME: Check pDeviceID */
560
561 if (*pulLength < *pulTransferLen)
562 *pulLength = *pulTransferLen;
563
564 *pulTransferLen = 0;
565
566 switch (ulProperty)
567 {
568 case CM_DRP_DEVICEDESC:
569 lpValueName = L"DeviceDesc";
570 break;
571
572 case CM_DRP_HARDWAREID:
573 lpValueName = L"HardwareID";
574 break;
575
576 case CM_DRP_COMPATIBLEIDS:
577 lpValueName = L"CompatibleIDs";
578 break;
579
580 case CM_DRP_SERVICE:
581 lpValueName = L"Service";
582 break;
583
584 case CM_DRP_CLASS:
585 lpValueName = L"Class";
586 break;
587
588 case CM_DRP_CLASSGUID:
589 lpValueName = L"ClassGUID";
590 break;
591
592 case CM_DRP_DRIVER:
593 lpValueName = L"Driver";
594 break;
595
596 case CM_DRP_CONFIGFLAGS:
597 lpValueName = L"ConfigFlags";
598 break;
599
600 case CM_DRP_MFG:
601 lpValueName = L"Mfg";
602 break;
603
604 case CM_DRP_FRIENDLYNAME:
605 lpValueName = L"FriendlyName";
606 break;
607
608 case CM_DRP_LOCATION_INFORMATION:
609 lpValueName = L"LocationInformation";
610 break;
611
612 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
613 lpValueName = NULL;
614 break;
615
616 case CM_DRP_CAPABILITIES:
617 lpValueName = L"Capabilities";
618 break;
619
620 case CM_DRP_UI_NUMBER:
621 lpValueName = NULL;
622 break;
623
624 case CM_DRP_UPPERFILTERS:
625 lpValueName = L"UpperFilters";
626 break;
627
628 case CM_DRP_LOWERFILTERS:
629 lpValueName = L"LowerFilters";
630 break;
631
632 case CM_DRP_BUSTYPEGUID:
633 lpValueName = NULL;
634 break;
635
636 case CM_DRP_LEGACYBUSTYPE:
637 lpValueName = NULL;
638 break;
639
640 case CM_DRP_BUSNUMBER:
641 lpValueName = NULL;
642 break;
643
644 case CM_DRP_ENUMERATOR_NAME:
645 lpValueName = NULL;
646 break;
647
648 case CM_DRP_SECURITY:
649 lpValueName = L"Security";
650 break;
651
652 case CM_DRP_DEVTYPE:
653 lpValueName = L"DeviceType";
654 break;
655
656 case CM_DRP_EXCLUSIVE:
657 lpValueName = L"Exclusive";
658 break;
659
660 case CM_DRP_CHARACTERISTICS:
661 lpValueName = L"DeviceCharacteristics";
662 break;
663
664 case CM_DRP_ADDRESS:
665 lpValueName = NULL;
666 break;
667
668 case CM_DRP_UI_NUMBER_DESC_FORMAT:
669 lpValueName = L"UINumberDescFormat";
670 break;
671
672 case CM_DRP_DEVICE_POWER_DATA:
673 lpValueName = NULL;
674 break;
675
676 case CM_DRP_REMOVAL_POLICY:
677 lpValueName = 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 /* FIXME */
1617 DPRINT1("CM_CREATE_DEVNODE_GENERATE_ID support not implemented yet!\n", ret);
1618 ret = CR_CALL_NOT_IMPLEMENTED;
1619 goto done;
1620 }
1621
1622 /* Create the device instance */
1623 ret = CreateDeviceInstance(pszDeviceID);
1624
1625 done:;
1626 DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret);
1627
1628 return ret;
1629 }
1630
1631
1632 static CONFIGRET
1633 MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination,
1634 LPWSTR pszDeviceInstanceSource)
1635 {
1636 DPRINT("MoveDeviceInstance: not implemented\n");
1637 /* FIXME */
1638 return CR_CALL_NOT_IMPLEMENTED;
1639 }
1640
1641
1642 static CONFIGRET
1643 SetupDeviceInstance(LPWSTR pszDeviceInstance,
1644 DWORD ulFlags)
1645 {
1646 DPRINT("SetupDeviceInstance: not implemented\n");
1647 /* FIXME */
1648 return CR_CALL_NOT_IMPLEMENTED;
1649 }
1650
1651
1652 static CONFIGRET
1653 EnableDeviceInstance(LPWSTR pszDeviceInstance)
1654 {
1655 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
1656 CONFIGRET ret = CR_SUCCESS;
1657 NTSTATUS Status;
1658
1659 DPRINT("Enable device instance\n");
1660
1661 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance);
1662 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
1663 if (!NT_SUCCESS(Status))
1664 ret = NtStatusToCrError(Status);
1665
1666 return ret;
1667 }
1668
1669
1670 static CONFIGRET
1671 DisableDeviceInstance(LPWSTR pszDeviceInstance)
1672 {
1673 DPRINT("DisableDeviceInstance: not implemented\n");
1674 /* FIXME */
1675 return CR_CALL_NOT_IMPLEMENTED;
1676 }
1677
1678
1679 static CONFIGRET
1680 ReenumerateDeviceInstance(LPWSTR pszDeviceInstance)
1681 {
1682 DPRINT("ReenumerateDeviceInstance: not implemented\n");
1683 /* FIXME */
1684 return CR_CALL_NOT_IMPLEMENTED;
1685 }
1686
1687
1688 /* Function 29 */
1689 DWORD PNP_DeviceInstanceAction(
1690 handle_t hBinding,
1691 DWORD ulAction,
1692 DWORD ulFlags,
1693 LPWSTR pszDeviceInstance1,
1694 LPWSTR pszDeviceInstance2)
1695 {
1696 CONFIGRET ret = CR_SUCCESS;
1697
1698 UNREFERENCED_PARAMETER(hBinding);
1699
1700 DPRINT("PNP_DeviceInstanceAction() called\n");
1701
1702 switch (ulAction)
1703 {
1704 case PNP_DEVINST_MOVE:
1705 ret = MoveDeviceInstance(pszDeviceInstance1,
1706 pszDeviceInstance2);
1707 break;
1708
1709 case PNP_DEVINST_SETUP:
1710 ret = SetupDeviceInstance(pszDeviceInstance1,
1711 ulFlags);
1712 break;
1713
1714 case PNP_DEVINST_ENABLE:
1715 ret = EnableDeviceInstance(pszDeviceInstance1);
1716 break;
1717
1718 case PNP_DEVINST_DISABLE:
1719 ret = DisableDeviceInstance(pszDeviceInstance1);
1720 break;
1721
1722 case PNP_DEVINST_REENUMERATE:
1723 ret = ReenumerateDeviceInstance(pszDeviceInstance1);
1724 break;
1725
1726 default:
1727 DPRINT1("Unknown device action %lu: not implemented\n", ulAction);
1728 ret = CR_CALL_NOT_IMPLEMENTED;
1729 }
1730
1731 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
1732
1733 return ret;
1734 }
1735
1736
1737 /* Function 30 */
1738 DWORD PNP_GetDeviceStatus(
1739 handle_t hBinding,
1740 LPWSTR pDeviceID,
1741 DWORD *pulStatus,
1742 DWORD *pulProblem,
1743 DWORD ulFlags)
1744 {
1745 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1746 CONFIGRET ret = CR_SUCCESS;
1747 NTSTATUS Status;
1748
1749 UNREFERENCED_PARAMETER(hBinding);
1750 UNREFERENCED_PARAMETER(ulFlags);
1751
1752 DPRINT("PNP_GetDeviceStatus() called\n");
1753
1754 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1755 pDeviceID);
1756 PlugPlayData.Operation = 0; /* Get status */
1757
1758 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1759 (PVOID)&PlugPlayData,
1760 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1761 if (NT_SUCCESS(Status))
1762 {
1763 *pulStatus = PlugPlayData.DeviceStatus;
1764 *pulProblem = PlugPlayData.DeviceProblem;
1765 }
1766 else
1767 {
1768 ret = NtStatusToCrError(Status);
1769 }
1770
1771 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret);
1772
1773 return ret;
1774 }
1775
1776
1777 /* Function 31 */
1778 DWORD PNP_SetDeviceProblem(
1779 handle_t hBinding,
1780 LPWSTR pDeviceID,
1781 DWORD ulProblem,
1782 DWORD ulFlags)
1783 {
1784 UNIMPLEMENTED;
1785 return CR_CALL_NOT_IMPLEMENTED;
1786 }
1787
1788
1789 /* Function 32 */
1790 DWORD PNP_DisableDevInst(
1791 handle_t hBinding,
1792 LPWSTR pDeviceID,
1793 PPNP_VETO_TYPE pVetoType,
1794 LPWSTR pszVetoName,
1795 DWORD ulNameLength,
1796 DWORD ulFlags)
1797 {
1798 UNIMPLEMENTED;
1799 return CR_CALL_NOT_IMPLEMENTED;
1800 }
1801
1802 /* Function 33 */
1803 DWORD PNP_UninstallDevInst(
1804 handle_t hBinding,
1805 LPWSTR pDeviceID,
1806 DWORD ulFlags)
1807 {
1808 UNIMPLEMENTED;
1809 return CR_CALL_NOT_IMPLEMENTED;
1810 }
1811
1812
1813 static BOOL
1814 CheckForDeviceId(LPWSTR lpDeviceIdList,
1815 LPWSTR lpDeviceId)
1816 {
1817 LPWSTR lpPtr;
1818 DWORD dwLength;
1819
1820 lpPtr = lpDeviceIdList;
1821 while (*lpPtr != 0)
1822 {
1823 dwLength = wcslen(lpPtr);
1824 if (0 == _wcsicmp(lpPtr, lpDeviceId))
1825 return TRUE;
1826
1827 lpPtr += (dwLength + 1);
1828 }
1829
1830 return FALSE;
1831 }
1832
1833
1834 static VOID
1835 AppendDeviceId(LPWSTR lpDeviceIdList,
1836 LPDWORD lpDeviceIdListSize,
1837 LPWSTR lpDeviceId)
1838 {
1839 DWORD dwLen;
1840 DWORD dwPos;
1841
1842 dwLen = wcslen(lpDeviceId);
1843 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
1844
1845 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
1846
1847 dwPos += (dwLen + 1);
1848
1849 lpDeviceIdList[dwPos] = 0;
1850
1851 *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
1852 }
1853
1854
1855 /* Function 34 */
1856 DWORD PNP_AddID(
1857 handle_t hBinding,
1858 LPWSTR pszDeviceID,
1859 LPWSTR pszID,
1860 DWORD ulFlags)
1861 {
1862 CONFIGRET ret = CR_SUCCESS;
1863 HKEY hDeviceKey;
1864 LPWSTR pszSubKey;
1865 DWORD dwDeviceIdListSize;
1866 DWORD dwNewDeviceIdSize;
1867 WCHAR * pszDeviceIdList = NULL;
1868
1869 UNREFERENCED_PARAMETER(hBinding);
1870
1871 DPRINT("PNP_AddID() called\n");
1872 DPRINT(" DeviceInstance: %S\n", pszDeviceID);
1873 DPRINT(" DeviceId: %S\n", pszID);
1874 DPRINT(" Flags: %lx\n", ulFlags);
1875
1876 if (RegOpenKeyExW(hEnumKey,
1877 pszDeviceID,
1878 0,
1879 KEY_QUERY_VALUE | KEY_SET_VALUE,
1880 &hDeviceKey) != ERROR_SUCCESS)
1881 {
1882 DPRINT("Failed to open the device key!\n");
1883 return CR_INVALID_DEVNODE;
1884 }
1885
1886 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
1887
1888 if (RegQueryValueExW(hDeviceKey,
1889 pszSubKey,
1890 NULL,
1891 NULL,
1892 NULL,
1893 &dwDeviceIdListSize) != ERROR_SUCCESS)
1894 {
1895 DPRINT("Failed to query the desired ID string!\n");
1896 ret = CR_REGISTRY_ERROR;
1897 goto Done;
1898 }
1899
1900 dwNewDeviceIdSize = lstrlenW(pszDeviceID);
1901 if (!dwNewDeviceIdSize)
1902 {
1903 ret = CR_INVALID_POINTER;
1904 goto Done;
1905 }
1906
1907 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR);
1908
1909 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize);
1910 if (!pszDeviceIdList)
1911 {
1912 DPRINT("Failed to allocate memory for the desired ID string!\n");
1913 ret = CR_OUT_OF_MEMORY;
1914 goto Done;
1915 }
1916
1917 if (RegQueryValueExW(hDeviceKey,
1918 pszSubKey,
1919 NULL,
1920 NULL,
1921 (LPBYTE)pszDeviceIdList,
1922 &dwDeviceIdListSize) != ERROR_SUCCESS)
1923 {
1924 DPRINT("Failed to query the desired ID string!\n");
1925 ret = CR_REGISTRY_ERROR;
1926 goto Done;
1927 }
1928
1929 /* Check whether the device ID is already in use */
1930 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID))
1931 {
1932 DPRINT("Device ID was found in the ID string!\n");
1933 ret = CR_SUCCESS;
1934 goto Done;
1935 }
1936
1937 /* Append the Device ID */
1938 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID);
1939
1940 if (RegSetValueExW(hDeviceKey,
1941 pszSubKey,
1942 0,
1943 REG_MULTI_SZ,
1944 (LPBYTE)pszDeviceIdList,
1945 dwDeviceIdListSize) != ERROR_SUCCESS)
1946 {
1947 DPRINT("Failed to set the desired ID string!\n");
1948 ret = CR_REGISTRY_ERROR;
1949 }
1950
1951 Done:
1952 RegCloseKey(hDeviceKey);
1953 if (pszDeviceIdList)
1954 HeapFree(GetProcessHeap(), 0, pszDeviceIdList);
1955
1956 DPRINT("PNP_AddID() done (returns %lx)\n", ret);
1957
1958 return ret;
1959 }
1960
1961
1962 /* Function 35 */
1963 DWORD PNP_RegisterDriver(
1964 handle_t hBinding,
1965 LPWSTR pszDeviceID,
1966 DWORD ulFlags)
1967 {
1968 UNIMPLEMENTED;
1969 return CR_CALL_NOT_IMPLEMENTED;
1970 }
1971
1972
1973 /* Function 36 */
1974 DWORD PNP_QueryRemove(
1975 handle_t hBinding,
1976 LPWSTR pszDeviceID,
1977 PPNP_VETO_TYPE pVetoType,
1978 LPWSTR pszVetoName,
1979 DWORD ulNameLength,
1980 DWORD ulFlags)
1981 {
1982 UNIMPLEMENTED;
1983 return CR_CALL_NOT_IMPLEMENTED;
1984 }
1985
1986
1987 /* Function 37 */
1988 DWORD PNP_RequestDeviceEject(
1989 handle_t hBinding,
1990 LPWSTR pszDeviceID,
1991 PPNP_VETO_TYPE pVetoType,
1992 LPWSTR pszVetoName,
1993 DWORD ulNameLength,
1994 DWORD ulFlags)
1995 {
1996 UNIMPLEMENTED;
1997 return CR_CALL_NOT_IMPLEMENTED;
1998 }
1999
2000 /* Function 38 */
2001 CONFIGRET
2002 PNP_IsDockStationPresent(handle_t hBinding,
2003 BOOL *Present)
2004 {
2005 HKEY hKey;
2006 DWORD dwType;
2007 DWORD dwValue;
2008 DWORD dwSize;
2009 CONFIGRET ret = CR_SUCCESS;
2010
2011 UNREFERENCED_PARAMETER(hBinding);
2012
2013 DPRINT1("PNP_IsDockStationPresent() called\n");
2014
2015 *Present = FALSE;
2016
2017 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
2018 L"CurrentDockInfo",
2019 0,
2020 KEY_READ,
2021 &hKey) != ERROR_SUCCESS)
2022 return CR_REGISTRY_ERROR;
2023
2024 dwSize = sizeof(DWORD);
2025 if (RegQueryValueExW(hKey,
2026 L"DockingState",
2027 NULL,
2028 &dwType,
2029 (LPBYTE)&dwValue,
2030 &dwSize) != ERROR_SUCCESS)
2031 ret = CR_REGISTRY_ERROR;
2032
2033 RegCloseKey(hKey);
2034
2035 if (ret == CR_SUCCESS)
2036 {
2037 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
2038 {
2039 ret = CR_REGISTRY_ERROR;
2040 }
2041 else if (dwValue != 0)
2042 {
2043 *Present = TRUE;
2044 }
2045 }
2046
2047 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
2048
2049 return ret;
2050 }
2051
2052
2053 /* Function 39 */
2054 DWORD PNP_RequestEjectPC(
2055 handle_t hBinding)
2056 {
2057 UNIMPLEMENTED;
2058 return CR_CALL_NOT_IMPLEMENTED;
2059 }
2060
2061
2062 /* Function 40 */
2063 DWORD PNP_HwProfFlags(
2064 handle_t hBinding,
2065 DWORD ulAction,
2066 LPWSTR pDeviceID,
2067 DWORD ulConfig,
2068 DWORD *pulValue,
2069 PPNP_VETO_TYPE pVetoType,
2070 LPWSTR pszVetoName,
2071 DWORD ulNameLength,
2072 DWORD ulFlags)
2073 {
2074 CONFIGRET ret = CR_SUCCESS;
2075 WCHAR szKeyName[MAX_PATH];
2076 HKEY hKey;
2077 HKEY hDeviceKey;
2078 DWORD dwSize;
2079
2080 UNREFERENCED_PARAMETER(hBinding);
2081
2082 DPRINT("PNP_HwProfFlags() called\n");
2083
2084 if (ulConfig == 0)
2085 {
2086 wcscpy(szKeyName,
2087 L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
2088 }
2089 else
2090 {
2091 swprintf(szKeyName,
2092 L"System\\CurrentControlSet\\HardwareProfiles\\%04u\\System\\CurrentControlSet\\Enum",
2093 ulConfig);
2094 }
2095
2096 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2097 szKeyName,
2098 0,
2099 KEY_QUERY_VALUE,
2100 &hKey) != ERROR_SUCCESS)
2101 return CR_REGISTRY_ERROR;
2102
2103 if (ulAction == PNP_GET_HWPROFFLAGS)
2104 {
2105 if (RegOpenKeyExW(hKey,
2106 pDeviceID,
2107 0,
2108 KEY_QUERY_VALUE,
2109 &hDeviceKey) != ERROR_SUCCESS)
2110 {
2111 *pulValue = 0;
2112 }
2113 else
2114 {
2115 dwSize = sizeof(DWORD);
2116 if (!RegQueryValueExW(hDeviceKey,
2117 L"CSConfigFlags",
2118 NULL,
2119 NULL,
2120 (LPBYTE)pulValue,
2121 &dwSize) != ERROR_SUCCESS)
2122 {
2123 *pulValue = 0;
2124 }
2125
2126 RegCloseKey(hDeviceKey);
2127 }
2128 }
2129 else if (ulAction == PNP_SET_HWPROFFLAGS)
2130 {
2131 /* FIXME: not implemented yet */
2132 ret = CR_CALL_NOT_IMPLEMENTED;
2133 }
2134
2135 RegCloseKey(hKey);
2136
2137 return ret;
2138 }
2139
2140
2141 /* Function 41 */
2142 DWORD PNP_GetHwProfInfo(
2143 handle_t hBinding,
2144 DWORD ulIndex,
2145 HWPROFILEINFO *pHWProfileInfo,
2146 DWORD ulProfileInfoSize,
2147 DWORD ulFlags)
2148 {
2149 WCHAR szProfileName[5];
2150 HKEY hKeyConfig = NULL;
2151 HKEY hKeyProfiles = NULL;
2152 HKEY hKeyProfile = NULL;
2153 DWORD dwDisposition;
2154 DWORD dwSize;
2155 LONG lError;
2156 CONFIGRET ret = CR_SUCCESS;
2157
2158 UNREFERENCED_PARAMETER(hBinding);
2159
2160 DPRINT("PNP_GetHwProfInfo() called\n");
2161
2162 if (ulProfileInfoSize == 0)
2163 {
2164 ret = CR_INVALID_DATA;
2165 goto done;
2166 }
2167
2168 if (ulFlags != 0)
2169 {
2170 ret = CR_INVALID_FLAG;
2171 goto done;
2172 }
2173
2174 /* Initialize the profile information */
2175 pHWProfileInfo->HWPI_ulHWProfile = 0;
2176 pHWProfileInfo->HWPI_szFriendlyName[0] = 0;
2177 pHWProfileInfo->HWPI_dwFlags = 0;
2178
2179 /* Open the 'IDConfigDB' key */
2180 lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
2181 L"System\\CurrentControlSet\\Control\\IDConfigDB",
2182 0,
2183 NULL,
2184 REG_OPTION_NON_VOLATILE,
2185 KEY_QUERY_VALUE,
2186 NULL,
2187 &hKeyConfig,
2188 &dwDisposition);
2189 if (lError != ERROR_SUCCESS)
2190 {
2191 ret = CR_REGISTRY_ERROR;
2192 goto done;
2193 }
2194
2195 /* Open the 'Hardware Profiles' subkey */
2196 lError = RegCreateKeyExW(hKeyConfig,
2197 L"Hardware Profiles",
2198 0,
2199 NULL,
2200 REG_OPTION_NON_VOLATILE,
2201 KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
2202 NULL,
2203 &hKeyProfiles,
2204 &dwDisposition);
2205 if (lError != ERROR_SUCCESS)
2206 {
2207 ret = CR_REGISTRY_ERROR;
2208 goto done;
2209 }
2210
2211 if (ulIndex == (ULONG)-1)
2212 {
2213 dwSize = sizeof(ULONG);
2214 lError = RegQueryValueExW(hKeyConfig,
2215 L"CurrentConfig",
2216 NULL,
2217 NULL,
2218 (LPBYTE)&pHWProfileInfo->HWPI_ulHWProfile,
2219 &dwSize);
2220 if (lError != ERROR_SUCCESS)
2221 {
2222 pHWProfileInfo->HWPI_ulHWProfile = 0;
2223 ret = CR_REGISTRY_ERROR;
2224 goto done;
2225 }
2226 }
2227 else
2228 {
2229 /* FIXME: not implemented yet */
2230 ret = CR_CALL_NOT_IMPLEMENTED;
2231 goto done;
2232 }
2233
2234 swprintf(szProfileName, L"%04lu", pHWProfileInfo->HWPI_ulHWProfile);
2235
2236 lError = RegOpenKeyExW(hKeyProfiles,
2237 szProfileName,
2238 0,
2239 KEY_QUERY_VALUE,
2240 &hKeyProfile);
2241 if (lError != ERROR_SUCCESS)
2242 {
2243 ret = CR_REGISTRY_ERROR;
2244 goto done;
2245 }
2246
2247 dwSize = sizeof(pHWProfileInfo->HWPI_szFriendlyName);
2248 lError = RegQueryValueExW(hKeyProfile,
2249 L"FriendlyName",
2250 NULL,
2251 NULL,
2252 (LPBYTE)&pHWProfileInfo->HWPI_szFriendlyName,
2253 &dwSize);
2254 if (lError != ERROR_SUCCESS)
2255 {
2256 ret = CR_REGISTRY_ERROR;
2257 goto done;
2258 }
2259
2260 done:
2261 if (hKeyProfile != NULL)
2262 RegCloseKey(hKeyProfile);
2263
2264 if (hKeyProfiles != NULL)
2265 RegCloseKey(hKeyProfiles);
2266
2267 if (hKeyConfig != NULL)
2268 RegCloseKey(hKeyConfig);
2269
2270 return ret;
2271 }
2272
2273
2274 /* Function 42 */
2275 DWORD PNP_AddEmptyLogConf(
2276 handle_t hBinding,
2277 LPWSTR pDeviceID,
2278 DWORD ulPriority,
2279 DWORD *pulLogConfTag,
2280 DWORD ulFlags)
2281 {
2282 UNIMPLEMENTED;
2283 return CR_CALL_NOT_IMPLEMENTED;
2284 }
2285
2286
2287 /* Function 43 */
2288 DWORD PNP_FreeLogConf(
2289 handle_t hBinding,
2290 LPWSTR pDeviceID,
2291 DWORD ulLogConfType,
2292 DWORD ulLogConfTag,
2293 DWORD ulFlags)
2294 {
2295 UNIMPLEMENTED;
2296 return CR_CALL_NOT_IMPLEMENTED;
2297 }
2298
2299
2300 /* Function 44 */
2301 DWORD PNP_GetFirstLogConf(
2302 handle_t hBinding,
2303 LPWSTR pDeviceID,
2304 DWORD ulLogConfType,
2305 DWORD *pulLogConfTag,
2306 DWORD ulFlags)
2307 {
2308 UNIMPLEMENTED;
2309 return CR_CALL_NOT_IMPLEMENTED;
2310 }
2311
2312
2313 /* Function 45 */
2314 DWORD PNP_GetNextLogConf(
2315 handle_t hBinding,
2316 LPWSTR pDeviceID,
2317 DWORD ulLogConfType,
2318 DWORD ulCurrentTag,
2319 DWORD *pulNextTag,
2320 DWORD ulFlags)
2321 {
2322 UNIMPLEMENTED;
2323 return CR_CALL_NOT_IMPLEMENTED;
2324 }
2325
2326
2327 /* Function 46 */
2328 DWORD PNP_GetLogConfPriority(
2329 handle_t hBinding,
2330 LPWSTR pDeviceID,
2331 DWORD ulType,
2332 DWORD ulTag,
2333 DWORD *pPriority,
2334 DWORD ulFlags)
2335 {
2336 UNIMPLEMENTED;
2337 return CR_CALL_NOT_IMPLEMENTED;
2338 }
2339
2340
2341 /* Function 47 */
2342 DWORD PNP_AddResDes(
2343 handle_t hBinding,
2344 LPWSTR pDeviceID,
2345 DWORD ulLogConfTag,
2346 DWORD ulLogConfType,
2347 RESOURCEID ResourceID,
2348 DWORD *pulResourceTag,
2349 BYTE *ResourceData,
2350 PNP_RPC_BUFFER_SIZE ResourceLen,
2351 DWORD ulFlags)
2352 {
2353 UNIMPLEMENTED;
2354 return CR_CALL_NOT_IMPLEMENTED;
2355 }
2356
2357
2358 /* Function 48 */
2359 DWORD PNP_FreeResDes(
2360 handle_t hBinding,
2361 LPWSTR pDeviceID,
2362 DWORD ulLogConfTag,
2363 DWORD ulLogConfType,
2364 RESOURCEID ResourceID,
2365 DWORD ulResourceTag,
2366 DWORD *pulPreviousResType,
2367 DWORD *pulPreviousResTag,
2368 DWORD ulFlags)
2369 {
2370 UNIMPLEMENTED;
2371 return CR_CALL_NOT_IMPLEMENTED;
2372 }
2373
2374
2375 /* Function 49 */
2376 DWORD PNP_GetNextResDes(
2377 handle_t hBinding,
2378 LPWSTR pDeviceID,
2379 DWORD ulLogConfTag,
2380 DWORD ulLogConfType,
2381 RESOURCEID ResourceID,
2382 DWORD ulResourceTag,
2383 DWORD *pulNextResType,
2384 DWORD *pulNextResTag,
2385 DWORD ulFlags)
2386 {
2387 UNIMPLEMENTED;
2388 return CR_CALL_NOT_IMPLEMENTED;
2389 }
2390
2391
2392 /* Function 50 */
2393 DWORD PNP_GetResDesData(
2394 handle_t hBinding,
2395 LPWSTR pDeviceID,
2396 DWORD ulLogConfTag,
2397 DWORD ulLogConfType,
2398 RESOURCEID ResourceID,
2399 DWORD ulResourceTag,
2400 BYTE *Buffer,
2401 PNP_RPC_BUFFER_SIZE BufferLen,
2402 DWORD ulFlags)
2403 {
2404 UNIMPLEMENTED;
2405 return CR_CALL_NOT_IMPLEMENTED;
2406 }
2407
2408
2409 /* Function 51 */
2410 DWORD PNP_GetResDesDataSize(
2411 handle_t hBinding,
2412 LPWSTR pDeviceID,
2413 DWORD ulLogConfTag,
2414 DWORD ulLogConfType,
2415 RESOURCEID ResourceID,
2416 DWORD ulResourceTag,
2417 DWORD *pulSize,
2418 DWORD ulFlags)
2419 {
2420 UNIMPLEMENTED;
2421 return CR_CALL_NOT_IMPLEMENTED;
2422 }
2423
2424
2425 /* Function 52 */
2426 DWORD PNP_ModifyResDes(
2427 handle_t hBinding,
2428 LPWSTR pDeviceID,
2429 DWORD ulLogConfTag,
2430 DWORD ulLogConfType,
2431 RESOURCEID CurrentResourceID,
2432 RESOURCEID NewResourceID,
2433 DWORD ulResourceTag,
2434 BYTE *ResourceData,
2435 PNP_RPC_BUFFER_SIZE ResourceLen,
2436 DWORD ulFlags)
2437 {
2438 UNIMPLEMENTED;
2439 return CR_CALL_NOT_IMPLEMENTED;
2440 }
2441
2442
2443 /* Function 53 */
2444 DWORD PNP_DetectResourceConflict(
2445 handle_t hBinding,
2446 LPWSTR pDeviceID,
2447 RESOURCEID ResourceID,
2448 BYTE *ResourceData,
2449 PNP_RPC_BUFFER_SIZE ResourceLen,
2450 BOOL *pbConflictDetected,
2451 DWORD ulFlags)
2452 {
2453 UNIMPLEMENTED;
2454 return CR_CALL_NOT_IMPLEMENTED;
2455 }
2456
2457
2458 /* Function 54 */
2459 DWORD PNP_QueryResConfList(
2460 handle_t hBinding,
2461 LPWSTR pDeviceID,
2462 RESOURCEID ResourceID,
2463 BYTE *ResourceData,
2464 PNP_RPC_BUFFER_SIZE ResourceLen,
2465 BYTE *Buffer,
2466 PNP_RPC_BUFFER_SIZE BufferLen,
2467 DWORD ulFlags)
2468 {
2469 UNIMPLEMENTED;
2470 return CR_CALL_NOT_IMPLEMENTED;
2471 }
2472
2473
2474 /* Function 55 */
2475 DWORD PNP_SetHwProf(
2476 handle_t hBinding,
2477 DWORD ulHardwareProfile,
2478 DWORD ulFlags)
2479 {
2480 UNIMPLEMENTED;
2481 return CR_CALL_NOT_IMPLEMENTED;
2482 }
2483
2484
2485 /* Function 56 */
2486 DWORD PNP_QueryArbitratorFreeData(
2487 handle_t hBinding,
2488 BYTE *pData,
2489 DWORD DataLen,
2490 LPWSTR pDeviceID,
2491 RESOURCEID ResourceID,
2492 DWORD ulFlags)
2493 {
2494 UNIMPLEMENTED;
2495 return CR_CALL_NOT_IMPLEMENTED;
2496 }
2497
2498
2499 /* Function 57 */
2500 DWORD PNP_QueryArbitratorFreeSize(
2501 handle_t hBinding,
2502 DWORD *pulSize,
2503 LPWSTR pDeviceID,
2504 RESOURCEID ResourceID,
2505 DWORD ulFlags)
2506 {
2507 UNIMPLEMENTED;
2508 return CR_CALL_NOT_IMPLEMENTED;
2509 }
2510
2511
2512 /* Function 58 */
2513 CONFIGRET
2514 PNP_RunDetection(
2515 handle_t hBinding,
2516 DWORD ulFlags)
2517 {
2518 return CR_CALL_NOT_IMPLEMENTED;
2519 }
2520
2521
2522 /* Function 59 */
2523 DWORD PNP_RegisterNotification(
2524 handle_t hBinding)
2525 {
2526 UNIMPLEMENTED;
2527 return CR_CALL_NOT_IMPLEMENTED;
2528 }
2529
2530
2531 /* Function 60 */
2532 DWORD PNP_UnregisterNotification(
2533 handle_t hBinding)
2534 {
2535 UNIMPLEMENTED;
2536 return CR_CALL_NOT_IMPLEMENTED;
2537 }
2538
2539
2540 /* Function 61 */
2541 DWORD PNP_GetCustomDevProp(
2542 handle_t hBinding,
2543 LPWSTR pDeviceID,
2544 LPWSTR CustomPropName,
2545 DWORD *pulRegDataType,
2546 BYTE *Buffer,
2547 PNP_RPC_STRING_LEN *pulTransferLen,
2548 PNP_RPC_STRING_LEN *pulLength,
2549 DWORD ulFlags)
2550 {
2551 HKEY hDeviceKey = NULL;
2552 HKEY hParamKey = NULL;
2553 LONG lError;
2554 CONFIGRET ret = CR_SUCCESS;
2555
2556 UNREFERENCED_PARAMETER(hBinding);
2557
2558 DPRINT("PNP_GetCustomDevProp() called\n");
2559
2560 if (pulTransferLen == NULL || pulLength == NULL)
2561 {
2562 ret = CR_INVALID_POINTER;
2563 goto done;
2564 }
2565
2566 if (ulFlags & ~CM_CUSTOMDEVPROP_BITS)
2567 {
2568 ret = CR_INVALID_FLAG;
2569 goto done;
2570 }
2571
2572 if (*pulLength < *pulTransferLen)
2573 *pulLength = *pulTransferLen;
2574
2575 *pulTransferLen = 0;
2576
2577 lError = RegOpenKeyExW(hEnumKey,
2578 pDeviceID,
2579 0,
2580 KEY_READ,
2581 &hDeviceKey);
2582 if (lError != ERROR_SUCCESS)
2583 {
2584 ret = CR_REGISTRY_ERROR;
2585 goto done;
2586 }
2587
2588 lError = RegOpenKeyExW(hDeviceKey,
2589 L"Device Parameters",
2590 0,
2591 KEY_READ,
2592 &hParamKey);
2593 if (lError != ERROR_SUCCESS)
2594 {
2595 ret = CR_REGISTRY_ERROR;
2596 goto done;
2597 }
2598
2599 lError = RegQueryValueExW(hParamKey,
2600 CustomPropName,
2601 NULL,
2602 pulRegDataType,
2603 Buffer,
2604 pulLength);
2605 if (lError != ERROR_SUCCESS)
2606 {
2607 if (lError == ERROR_MORE_DATA)
2608 {
2609 ret = CR_BUFFER_SMALL;
2610 }
2611 else
2612 {
2613 *pulLength = 0;
2614 ret = CR_NO_SUCH_VALUE;
2615 }
2616 }
2617
2618 done:;
2619 if (ret == CR_SUCCESS)
2620 *pulTransferLen = *pulLength;
2621
2622 if (hParamKey != NULL)
2623 RegCloseKey(hParamKey);
2624
2625 if (hDeviceKey != NULL)
2626 RegCloseKey(hDeviceKey);
2627
2628 DPRINT("PNP_GetCustomDevProp() done (returns %lx)\n", ret);
2629
2630 return ret;
2631 }
2632
2633
2634 /* Function 62 */
2635 DWORD PNP_GetVersionInternal(
2636 handle_t hBinding,
2637 WORD *pwVersion)
2638 {
2639 *pwVersion = 0x501;
2640 return CR_SUCCESS;
2641 UNIMPLEMENTED;
2642 return CR_CALL_NOT_IMPLEMENTED;
2643 }
2644
2645
2646 /* Function 63 */
2647 DWORD PNP_GetBlockedDriverInfo(
2648 handle_t hBinding,
2649 BYTE *Buffer,
2650 PNP_RPC_BUFFER_SIZE *pulTransferLen,
2651 PNP_RPC_BUFFER_SIZE *pulLength,
2652 DWORD ulFlags)
2653 {
2654 UNIMPLEMENTED;
2655 return CR_CALL_NOT_IMPLEMENTED;
2656 }
2657
2658
2659 /* Function 64 */
2660 DWORD PNP_GetServerSideDeviceInstallFlags(
2661 handle_t hBinding,
2662 DWORD *pulSSDIFlags,
2663 DWORD ulFlags)
2664 {
2665 UNIMPLEMENTED;
2666 return CR_CALL_NOT_IMPLEMENTED;
2667 }
2668
2669
2670 /* Function 65 */
2671 DWORD PNP_GetObjectPropKeys(
2672 handle_t hBinding,
2673 LPWSTR ObjectName,
2674 DWORD ObjectType,
2675 LPWSTR PropertyCultureName,
2676 PNP_PROP_COUNT *PropertyCount,
2677 PNP_PROP_COUNT *TransferLen,
2678 DEVPROPKEY *PropertyKeys,
2679 DWORD Flags)
2680 {
2681 UNIMPLEMENTED;
2682 return CR_CALL_NOT_IMPLEMENTED;
2683 }
2684
2685
2686 /* Function 66 */
2687 DWORD PNP_GetObjectProp(
2688 handle_t hBinding,
2689 LPWSTR ObjectName,
2690 DWORD ObjectType,
2691 LPWSTR PropertyCultureName,
2692 const DEVPROPKEY *PropertyKey,
2693 DEVPROPTYPE *PropertyType,
2694 PNP_PROP_SIZE *PropertySize,
2695 PNP_PROP_SIZE *TransferLen,
2696 BYTE *PropertyBuffer,
2697 DWORD Flags)
2698 {
2699 UNIMPLEMENTED;
2700 return CR_CALL_NOT_IMPLEMENTED;
2701 }
2702
2703
2704 /* Function 67 */
2705 DWORD PNP_SetObjectProp(
2706 handle_t hBinding,
2707 LPWSTR ObjectName,
2708 DWORD ObjectType,
2709 LPWSTR PropertyCultureName,
2710 const DEVPROPKEY *PropertyKey,
2711 DEVPROPTYPE PropertyType,
2712 PNP_PROP_SIZE PropertySize,
2713 BYTE *PropertyBuffer,
2714 DWORD Flags)
2715 {
2716 UNIMPLEMENTED;
2717 return CR_CALL_NOT_IMPLEMENTED;
2718 }
2719
2720
2721 /* Function 68 */
2722 DWORD PNP_InstallDevInst(
2723 handle_t hBinding)
2724 {
2725 UNIMPLEMENTED;
2726 return CR_CALL_NOT_IMPLEMENTED;
2727 }
2728
2729
2730 /* Function 69 */
2731 DWORD PNP_ApplyPowerSettings(
2732 handle_t hBinding)
2733 {
2734 UNIMPLEMENTED;
2735 return CR_CALL_NOT_IMPLEMENTED;
2736 }
2737
2738
2739 /* Function 70 */
2740 DWORD PNP_DriverStoreAddDriverPackage(
2741 handle_t hBinding)
2742 {
2743 UNIMPLEMENTED;
2744 return CR_CALL_NOT_IMPLEMENTED;
2745 }
2746
2747
2748 /* Function 71 */
2749 DWORD PNP_DriverStoreDeleteDriverPackage(
2750 handle_t hBinding)
2751 {
2752 UNIMPLEMENTED;
2753 return CR_CALL_NOT_IMPLEMENTED;
2754 }
2755
2756
2757 /* Function 72 */
2758 DWORD PNP_RegisterServiceNotification(
2759 handle_t hBinding)
2760 {
2761 UNIMPLEMENTED;
2762 return CR_CALL_NOT_IMPLEMENTED;
2763 }
2764
2765
2766 /* Function 73 */
2767 DWORD PNP_SetActiveService(
2768 handle_t hBinding)
2769 {
2770 UNIMPLEMENTED;
2771 return CR_CALL_NOT_IMPLEMENTED;
2772 }
2773
2774
2775 /* Function 74 */
2776 DWORD PNP_DeleteServiceDevices(
2777 handle_t hBinding)
2778 {
2779 UNIMPLEMENTED;
2780 return CR_CALL_NOT_IMPLEMENTED;
2781 }
2782
2783
2784 static BOOL
2785 InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
2786 {
2787 BOOL DeviceInstalled = FALSE;
2788 DWORD BytesWritten;
2789 DWORD Value;
2790 HANDLE hPipe = INVALID_HANDLE_VALUE;
2791 LPVOID Environment = NULL;
2792 PROCESS_INFORMATION ProcessInfo;
2793 STARTUPINFOW StartupInfo;
2794 UUID RandomUuid;
2795 HKEY DeviceKey;
2796
2797 /* The following lengths are constant (see below), they cannot overflow */
2798 WCHAR CommandLine[116];
2799 WCHAR InstallEventName[73];
2800 WCHAR PipeName[74];
2801 WCHAR UuidString[39];
2802
2803 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance, ShowWizard);
2804
2805 ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
2806
2807 if (RegOpenKeyExW(hEnumKey,
2808 DeviceInstance,
2809 0,
2810 KEY_QUERY_VALUE,
2811 &DeviceKey) == ERROR_SUCCESS)
2812 {
2813 if (RegQueryValueExW(DeviceKey,
2814 L"Class",
2815 NULL,
2816 NULL,
2817 NULL,
2818 NULL) == ERROR_SUCCESS)
2819 {
2820 DPRINT("No need to install: %S\n", DeviceInstance);
2821 RegCloseKey(DeviceKey);
2822 return TRUE;
2823 }
2824
2825 RegCloseKey(DeviceKey);
2826 }
2827
2828 DPRINT1("Installing: %S\n", DeviceInstance);
2829
2830 /* Create a random UUID for the named pipe */
2831 UuidCreate(&RandomUuid);
2832 swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
2833 RandomUuid.Data1, RandomUuid.Data2, RandomUuid.Data3,
2834 RandomUuid.Data4[0], RandomUuid.Data4[1], RandomUuid.Data4[2],
2835 RandomUuid.Data4[3], RandomUuid.Data4[4], RandomUuid.Data4[5],
2836 RandomUuid.Data4[6], RandomUuid.Data4[7]);
2837
2838 /* Create the named pipe */
2839 wcscpy(PipeName, L"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
2840 wcscat(PipeName, UuidString);
2841 hPipe = CreateNamedPipeW(PipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 512, 512, 0, NULL);
2842
2843 if(hPipe == INVALID_HANDLE_VALUE)
2844 {
2845 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
2846 goto cleanup;
2847 }
2848
2849 /* Launch rundll32 to call ClientSideInstallW */
2850 wcscpy(CommandLine, L"rundll32.exe newdev.dll,ClientSideInstall ");
2851 wcscat(CommandLine, PipeName);
2852
2853 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
2854 StartupInfo.cb = sizeof(StartupInfo);
2855
2856 if(hUserToken)
2857 {
2858 /* newdev has to run under the environment of the current user */
2859 if(!CreateEnvironmentBlock(&Environment, hUserToken, FALSE))
2860 {
2861 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
2862 goto cleanup;
2863 }
2864
2865 if(!CreateProcessAsUserW(hUserToken, NULL, CommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, Environment, NULL, &StartupInfo, &ProcessInfo))
2866 {
2867 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
2868 goto cleanup;
2869 }
2870 }
2871 else
2872 {
2873 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
2874
2875 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
2876 (ShowWizard is only set to FALSE for these two modes) */
2877 ASSERT(!ShowWizard);
2878
2879 if(!CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo))
2880 {
2881 DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
2882 goto cleanup;
2883 }
2884 }
2885
2886 /* Wait for the function to connect to our pipe */
2887 if(!ConnectNamedPipe(hPipe, NULL))
2888 {
2889 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
2890 goto cleanup;
2891 }
2892
2893 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
2894 wcscpy(InstallEventName, L"Global\\PNP_Device_Install_Event_0.");
2895 wcscat(InstallEventName, UuidString);
2896
2897 Value = sizeof(InstallEventName);
2898 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
2899 WriteFile(hPipe, InstallEventName, Value, &BytesWritten, NULL);
2900
2901 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
2902 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
2903 WriteFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesWritten, NULL);
2904
2905 Value = (wcslen(DeviceInstance) + 1) * sizeof(WCHAR);
2906 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
2907 WriteFile(hPipe, DeviceInstance, Value, &BytesWritten, NULL);
2908
2909 /* Wait for newdev.dll to finish processing */
2910 WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
2911
2912 /* The following check for success is probably not compatible to Windows, but should do its job */
2913 if(!GetExitCodeProcess(ProcessInfo.hProcess, &Value))
2914 {
2915 DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
2916 goto cleanup;
2917 }
2918
2919 DeviceInstalled = Value;
2920
2921 cleanup:
2922 if(hPipe != INVALID_HANDLE_VALUE)
2923 CloseHandle(hPipe);
2924
2925 if(Environment)
2926 DestroyEnvironmentBlock(Environment);
2927
2928 if(ProcessInfo.hProcess)
2929 CloseHandle(ProcessInfo.hProcess);
2930
2931 if(ProcessInfo.hThread)
2932 CloseHandle(ProcessInfo.hThread);
2933
2934 DPRINT1("Success? %d\n", DeviceInstalled);
2935
2936 return DeviceInstalled;
2937 }
2938
2939
2940 static LONG
2941 ReadRegSzKey(
2942 IN HKEY hKey,
2943 IN LPCWSTR pszKey,
2944 OUT LPWSTR* pValue)
2945 {
2946 LONG rc;
2947 DWORD dwType;
2948 DWORD cbData = 0;
2949 LPWSTR Value;
2950
2951 if (!pValue)
2952 return ERROR_INVALID_PARAMETER;
2953
2954 *pValue = NULL;
2955 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
2956 if (rc != ERROR_SUCCESS)
2957 return rc;
2958 if (dwType != REG_SZ)
2959 return ERROR_FILE_NOT_FOUND;
2960 Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
2961 if (!Value)
2962 return ERROR_NOT_ENOUGH_MEMORY;
2963 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
2964 if (rc != ERROR_SUCCESS)
2965 {
2966 HeapFree(GetProcessHeap(), 0, Value);
2967 return rc;
2968 }
2969 /* NULL-terminate the string */
2970 Value[cbData / sizeof(WCHAR)] = '\0';
2971
2972 *pValue = Value;
2973 return ERROR_SUCCESS;
2974 }
2975
2976
2977 static BOOL
2978 SetupIsActive(VOID)
2979 {
2980 HKEY hKey = NULL;
2981 DWORD regType, active, size;
2982 LONG rc;
2983 BOOL ret = FALSE;
2984
2985 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
2986 if (rc != ERROR_SUCCESS)
2987 goto cleanup;
2988
2989 size = sizeof(DWORD);
2990 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
2991 if (rc != ERROR_SUCCESS)
2992 goto cleanup;
2993 if (regType != REG_DWORD || size != sizeof(DWORD))
2994 goto cleanup;
2995
2996 ret = (active != 0);
2997
2998 cleanup:
2999 if (hKey != NULL)
3000 RegCloseKey(hKey);
3001
3002 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
3003
3004 return ret;
3005 }
3006
3007
3008 static BOOL
3009 IsConsoleBoot(VOID)
3010 {
3011 HKEY ControlKey = NULL;
3012 LPWSTR SystemStartOptions = NULL;
3013 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
3014 BOOL ConsoleBoot = FALSE;
3015 LONG rc;
3016
3017 rc = RegOpenKeyExW(
3018 HKEY_LOCAL_MACHINE,
3019 L"SYSTEM\\CurrentControlSet\\Control",
3020 0,
3021 KEY_QUERY_VALUE,
3022 &ControlKey);
3023
3024 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
3025 if (rc != ERROR_SUCCESS)
3026 goto cleanup;
3027
3028 /* Check for CONSOLE switch in SystemStartOptions */
3029 CurrentOption = SystemStartOptions;
3030 while (CurrentOption)
3031 {
3032 NextOption = wcschr(CurrentOption, L' ');
3033 if (NextOption)
3034 *NextOption = L'\0';
3035 if (_wcsicmp(CurrentOption, L"CONSOLE") == 0)
3036 {
3037 DPRINT("Found %S. Switching to console boot\n", CurrentOption);
3038 ConsoleBoot = TRUE;
3039 goto cleanup;
3040 }
3041 CurrentOption = NextOption ? NextOption + 1 : NULL;
3042 }
3043
3044 cleanup:
3045 if (ControlKey != NULL)
3046 RegCloseKey(ControlKey);
3047 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
3048 return ConsoleBoot;
3049 }
3050
3051
3052 /* Loop to install all queued devices installations */
3053 static DWORD WINAPI
3054 DeviceInstallThread(LPVOID lpParameter)
3055 {
3056 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
3057 PSLIST_ENTRY ListEntry;
3058 #else
3059 PLIST_ENTRY ListEntry;
3060 #endif
3061 DeviceInstallParams* Params;
3062 BOOL showWizard;
3063
3064 UNREFERENCED_PARAMETER(lpParameter);
3065
3066 WaitForSingleObject(hInstallEvent, INFINITE);
3067
3068 showWizard = !SetupIsActive() && !IsConsoleBoot();
3069
3070 while (TRUE)
3071 {
3072 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
3073 ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead);
3074 #else
3075 if ((BOOL)IsListEmpty(&DeviceInstallListHead))
3076 ListEntry = NULL;
3077 else
3078 ListEntry = RemoveHeadList(&DeviceInstallListHead);
3079 #endif
3080 if (ListEntry == NULL)
3081 {
3082 SetEvent(hNoPendingInstalls);
3083 WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE);
3084 }
3085 else
3086 {
3087 ResetEvent(hNoPendingInstalls);
3088 Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry);
3089 InstallDevice(Params->DeviceIds, showWizard);
3090 }
3091 }
3092
3093 return 0;
3094 }
3095
3096
3097 static DWORD WINAPI
3098 PnpEventThread(LPVOID lpParameter)
3099 {
3100 PPLUGPLAY_EVENT_BLOCK PnpEvent;
3101 ULONG PnpEventSize;
3102 NTSTATUS Status;
3103 RPC_STATUS RpcStatus;
3104
3105 UNREFERENCED_PARAMETER(lpParameter);
3106
3107 PnpEventSize = 0x1000;
3108 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
3109 if (PnpEvent == NULL)
3110 return ERROR_OUTOFMEMORY;
3111
3112 for (;;)
3113 {
3114 DPRINT("Calling NtGetPlugPlayEvent()\n");
3115
3116 /* Wait for the next pnp event */
3117 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
3118
3119 /* Resize the buffer for the PnP event if it's too small. */
3120 if (Status == STATUS_BUFFER_TOO_SMALL)
3121 {
3122 PnpEventSize += 0x400;
3123 HeapFree(GetProcessHeap(), 0, PnpEvent);
3124 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
3125 if (PnpEvent == NULL)
3126 return ERROR_OUTOFMEMORY;
3127 continue;
3128 }
3129
3130 if (!NT_SUCCESS(Status))
3131 {
3132 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status);
3133 break;
3134 }
3135
3136 /* Process the pnp event */
3137 DPRINT("Received PnP Event\n");
3138 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ENUMERATED, &RpcStatus))
3139 {
3140 DeviceInstallParams* Params;
3141 DWORD len;
3142 DWORD DeviceIdLength;
3143
3144 DPRINT("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds);
3145
3146 DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds);
3147 if (DeviceIdLength)
3148 {
3149 /* Queue device install (will be dequeued by DeviceInstallThread */
3150 len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
3151 Params = HeapAlloc(GetProcessHeap(), 0, len);
3152 if (Params)
3153 {
3154 wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
3155 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
3156 InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry);
3157 #else
3158 InsertTailList(&DeviceInstallListHead, &Params->ListEntry);
3159 #endif
3160 SetEvent(hDeviceInstallListNotEmpty);
3161 }
3162 }
3163 }
3164 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
3165 {
3166 DPRINT("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds);
3167 /* FIXME: ? */
3168 }
3169 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_EJECT_VETOED, &RpcStatus))
3170 {
3171 DPRINT1("Eject vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
3172 }
3173 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_KERNEL_INITIATED_EJECT, &RpcStatus))
3174 {
3175 DPRINT1("Kernel initiated eject: %S\n", PnpEvent->TargetDevice.DeviceIds);
3176 }
3177 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SAFE_REMOVAL, &RpcStatus))
3178 {
3179 DPRINT1("Safe removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
3180 }
3181 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_SURPRISE_REMOVAL, &RpcStatus))
3182 {
3183 DPRINT1("Surprise removal: %S\n", PnpEvent->TargetDevice.DeviceIds);
3184 }
3185 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVAL_VETOED, &RpcStatus))
3186 {
3187 DPRINT1("Removal vetoed: %S\n", PnpEvent->TargetDevice.DeviceIds);
3188 }
3189 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_REMOVE_PENDING, &RpcStatus))
3190 {
3191 DPRINT1("Removal pending: %S\n", PnpEvent->TargetDevice.DeviceIds);
3192 }
3193 else
3194 {
3195 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
3196 PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
3197 PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
3198 PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
3199 PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
3200 }
3201
3202 /* Dequeue the current pnp event and signal the next one */
3203 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
3204 }
3205
3206 HeapFree(GetProcessHeap(), 0, PnpEvent);
3207
3208 return ERROR_SUCCESS;
3209 }
3210
3211
3212 static VOID
3213 UpdateServiceStatus(DWORD dwState)
3214 {
3215 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
3216 ServiceStatus.dwCurrentState = dwState;
3217 ServiceStatus.dwControlsAccepted = 0;
3218 ServiceStatus.dwWin32ExitCode = 0;
3219 ServiceStatus.dwServiceSpecificExitCode = 0;
3220 ServiceStatus.dwCheckPoint = 0;
3221
3222 if (dwState == SERVICE_START_PENDING ||
3223 dwState == SERVICE_STOP_PENDING ||
3224 dwState == SERVICE_PAUSE_PENDING ||
3225 dwState == SERVICE_CONTINUE_PENDING)
3226 ServiceStatus.dwWaitHint = 10000;
3227 else
3228 ServiceStatus.dwWaitHint = 0;
3229
3230 SetServiceStatus(ServiceStatusHandle,
3231 &ServiceStatus);
3232 }
3233
3234
3235 static DWORD WINAPI
3236 ServiceControlHandler(DWORD dwControl,
3237 DWORD dwEventType,
3238 LPVOID lpEventData,
3239 LPVOID lpContext)
3240 {
3241 DPRINT1("ServiceControlHandler() called\n");
3242
3243 switch (dwControl)
3244 {
3245 case SERVICE_CONTROL_STOP:
3246 DPRINT1(" SERVICE_CONTROL_STOP received\n");
3247 /* Stop listening to RPC Messages */
3248 RpcMgmtStopServerListening(NULL);
3249 UpdateServiceStatus(SERVICE_STOPPED);
3250 return ERROR_SUCCESS;
3251
3252 case SERVICE_CONTROL_PAUSE:
3253 DPRINT1(" SERVICE_CONTROL_PAUSE received\n");
3254 UpdateServiceStatus(SERVICE_PAUSED);
3255 return ERROR_SUCCESS;
3256
3257 case SERVICE_CONTROL_CONTINUE:
3258 DPRINT1(" SERVICE_CONTROL_CONTINUE received\n");
3259 UpdateServiceStatus(SERVICE_RUNNING);
3260 return ERROR_SUCCESS;
3261
3262 case SERVICE_CONTROL_INTERROGATE:
3263 DPRINT1(" SERVICE_CONTROL_INTERROGATE received\n");
3264 SetServiceStatus(ServiceStatusHandle,
3265 &ServiceStatus);
3266 return ERROR_SUCCESS;
3267
3268 case SERVICE_CONTROL_SHUTDOWN:
3269 DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n");
3270 /* Stop listening to RPC Messages */
3271 RpcMgmtStopServerListening(NULL);
3272 UpdateServiceStatus(SERVICE_STOPPED);
3273 return ERROR_SUCCESS;
3274
3275 default :
3276 DPRINT1(" Control %lu received\n");
3277 return ERROR_CALL_NOT_IMPLEMENTED;
3278 }
3279 }
3280
3281
3282 static VOID CALLBACK
3283 ServiceMain(DWORD argc, LPTSTR *argv)
3284 {
3285 HANDLE hThread;
3286 DWORD dwThreadId;
3287
3288 UNREFERENCED_PARAMETER(argc);
3289 UNREFERENCED_PARAMETER(argv);
3290
3291 DPRINT("ServiceMain() called\n");
3292
3293 ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
3294 ServiceControlHandler,
3295 NULL);
3296 if (!ServiceStatusHandle)
3297 {
3298 DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
3299 return;
3300 }
3301
3302 UpdateServiceStatus(SERVICE_START_PENDING);
3303
3304 hThread = CreateThread(NULL,
3305 0,
3306 PnpEventThread,
3307 NULL,
3308 0,
3309 &dwThreadId);
3310 if (hThread != NULL)
3311 CloseHandle(hThread);
3312
3313 hThread = CreateThread(NULL,
3314 0,
3315 RpcServerThread,
3316 NULL,
3317 0,
3318 &dwThreadId);
3319 if (hThread != NULL)
3320 CloseHandle(hThread);
3321
3322 hThread = CreateThread(NULL,
3323 0,
3324 DeviceInstallThread,
3325 NULL,
3326 0,
3327 &dwThreadId);
3328 if (hThread != NULL)
3329 CloseHandle(hThread);
3330
3331 UpdateServiceStatus(SERVICE_RUNNING);
3332
3333 DPRINT("ServiceMain() done\n");
3334 }
3335
3336
3337 int
3338 wmain(int argc, WCHAR *argv[])
3339 {
3340 BOOLEAN OldValue;
3341 DWORD dwError;
3342
3343 UNREFERENCED_PARAMETER(argc);
3344 UNREFERENCED_PARAMETER(argv);
3345
3346 DPRINT("Umpnpmgr: main() started\n");
3347
3348 /* We need this privilege for using CreateProcessAsUserW */
3349 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue);
3350
3351 hInstallEvent = CreateEvent(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
3352 if (hInstallEvent == NULL)
3353 {
3354 dwError = GetLastError();
3355 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
3356 return dwError;
3357 }
3358
3359 hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL);
3360 if (hDeviceInstallListNotEmpty == NULL)
3361 {
3362 dwError = GetLastError();
3363 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
3364 return dwError;
3365 }
3366
3367 hNoPendingInstalls = CreateEventW(NULL,
3368 TRUE,
3369 FALSE,
3370 L"Global\\PnP_No_Pending_Install_Events");
3371 if (hNoPendingInstalls == NULL)
3372 {
3373 dwError = GetLastError();
3374 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
3375 return dwError;
3376 }
3377
3378 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
3379 InitializeSListHead(&DeviceInstallListHead);
3380 #else
3381 InitializeListHead(&DeviceInstallListHead);
3382 #endif
3383
3384 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3385 L"System\\CurrentControlSet\\Enum",
3386 0,
3387 KEY_ALL_ACCESS,
3388 &hEnumKey);
3389 if (dwError != ERROR_SUCCESS)
3390 {
3391 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
3392 return dwError;
3393 }
3394
3395 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3396 L"System\\CurrentControlSet\\Control\\Class",
3397 0,
3398 KEY_ALL_ACCESS,
3399 &hClassKey);
3400 if (dwError != ERROR_SUCCESS)
3401 {
3402 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
3403 return dwError;
3404 }
3405
3406 StartServiceCtrlDispatcher(ServiceTable);
3407
3408 DPRINT("Umpnpmgr: main() done\n");
3409
3410 ExitThread(0);
3411
3412 return 0;
3413 }
3414
3415 /* EOF */