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