Fix PNP_QueryArbitratorFreeData() and PNP_QueryArbitratorFreeSize() prototypes.
[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 BYTE *pData,
1860 DWORD DataLen,
1861 LPWSTR pDeviceID,
1862 RESOURCEID ResourceID,
1863 DWORD ulFlags)
1864 {
1865 UNIMPLEMENTED;
1866 return CR_CALL_NOT_IMPLEMENTED;
1867 }
1868
1869
1870 /* Function 57 */
1871 DWORD PNP_QueryArbitratorFreeSize(
1872 handle_t hBinding,
1873 DWORD *pulSize,
1874 LPWSTR pDeviceID,
1875 RESOURCEID ResourceID,
1876 DWORD ulFlags)
1877 {
1878 UNIMPLEMENTED;
1879 return CR_CALL_NOT_IMPLEMENTED;
1880 }
1881
1882
1883 /* Function 58 */
1884 CONFIGRET
1885 PNP_RunDetection(
1886 handle_t hBinding,
1887 DWORD ulFlags)
1888 {
1889 UNIMPLEMENTED;
1890 return CR_CALL_NOT_IMPLEMENTED;
1891 }
1892
1893
1894 /* Function 59 */
1895 DWORD PNP_RegisterNotification(
1896 handle_t hBinding)
1897 {
1898 UNIMPLEMENTED;
1899 return CR_CALL_NOT_IMPLEMENTED;
1900 }
1901
1902
1903 /* Function 60 */
1904 DWORD PNP_UnregisterNotification(
1905 handle_t hBinding)
1906 {
1907 UNIMPLEMENTED;
1908 return CR_CALL_NOT_IMPLEMENTED;
1909 }
1910
1911
1912 /* Function 61 */
1913 DWORD PNP_GetCustomDevProp(
1914 handle_t hBinding,
1915 LPWSTR pDeviceID,
1916 LPWSTR CustomPropName,
1917 DWORD *pulRegDataType,
1918 BYTE *Buffer,
1919 PNP_RPC_STRING_LEN *pulTransferLen,
1920 PNP_RPC_STRING_LEN *pulLength,
1921 DWORD ulFlags)
1922 {
1923 UNIMPLEMENTED;
1924 return CR_CALL_NOT_IMPLEMENTED;
1925 }
1926
1927
1928 /* Function 62 */
1929 DWORD PNP_GetVersionInternal(
1930 handle_t hBinding,
1931 WORD *pwVersion)
1932 {
1933 UNIMPLEMENTED;
1934 return CR_CALL_NOT_IMPLEMENTED;
1935 }
1936
1937
1938 /* Function 63 */
1939 DWORD PNP_GetBlockedDriverInfo(
1940 handle_t hBinding,
1941 BYTE *Buffer,
1942 PNP_RPC_BUFFER_SIZE *pulTransferLen,
1943 PNP_RPC_BUFFER_SIZE *pulLength,
1944 DWORD ulFlags)
1945 {
1946 UNIMPLEMENTED;
1947 return CR_CALL_NOT_IMPLEMENTED;
1948 }
1949
1950
1951 /* Function 64 */
1952 DWORD PNP_GetServerSideDeviceInstallFlags(
1953 handle_t hBinding,
1954 DWORD *pulSSDIFlags,
1955 DWORD ulFlags)
1956 {
1957 UNIMPLEMENTED;
1958 return CR_CALL_NOT_IMPLEMENTED;
1959 }
1960
1961
1962 /* Function 65 */
1963 DWORD PNP_GetObjectPropKeys(
1964 handle_t hBinding,
1965 LPWSTR ObjectName,
1966 DWORD ObjectType,
1967 LPWSTR PropertyCultureName,
1968 PNP_PROP_COUNT *PropertyCount,
1969 PNP_PROP_COUNT *TransferLen,
1970 DEVPROPKEY *PropertyKeys,
1971 DWORD Flags)
1972 {
1973 UNIMPLEMENTED;
1974 return CR_CALL_NOT_IMPLEMENTED;
1975 }
1976
1977
1978 /* Function 66 */
1979 DWORD PNP_GetObjectProp(
1980 handle_t hBinding,
1981 LPWSTR ObjectName,
1982 DWORD ObjectType,
1983 LPWSTR PropertyCultureName,
1984 const DEVPROPKEY *PropertyKey,
1985 DEVPROPTYPE *PropertyType,
1986 PNP_PROP_SIZE *PropertySize,
1987 PNP_PROP_SIZE *TransferLen,
1988 BYTE *PropertyBuffer,
1989 DWORD Flags)
1990 {
1991 UNIMPLEMENTED;
1992 return CR_CALL_NOT_IMPLEMENTED;
1993 }
1994
1995
1996 /* Function 67 */
1997 DWORD PNP_SetObjectProp(
1998 handle_t hBinding,
1999 LPWSTR ObjectName,
2000 DWORD ObjectType,
2001 LPWSTR PropertyCultureName,
2002 const DEVPROPKEY *PropertyKey,
2003 DEVPROPTYPE PropertyType,
2004 PNP_PROP_SIZE PropertySize,
2005 BYTE *PropertyBuffer,
2006 DWORD Flags)
2007 {
2008 UNIMPLEMENTED;
2009 return CR_CALL_NOT_IMPLEMENTED;
2010 }
2011
2012
2013 /* Function 68 */
2014 DWORD PNP_InstallDevInst(
2015 handle_t hBinding)
2016 {
2017 UNIMPLEMENTED;
2018 return CR_CALL_NOT_IMPLEMENTED;
2019 }
2020
2021
2022 /* Function 69 */
2023 DWORD PNP_ApplyPowerSettings(
2024 handle_t hBinding)
2025 {
2026 UNIMPLEMENTED;
2027 return CR_CALL_NOT_IMPLEMENTED;
2028 }
2029
2030
2031 /* Function 70 */
2032 DWORD PNP_DriverStoreAddDriverPackage(
2033 handle_t hBinding)
2034 {
2035 UNIMPLEMENTED;
2036 return CR_CALL_NOT_IMPLEMENTED;
2037 }
2038
2039
2040 /* Function 71 */
2041 DWORD PNP_DriverStoreDeleteDriverPackage(
2042 handle_t hBinding)
2043 {
2044 UNIMPLEMENTED;
2045 return CR_CALL_NOT_IMPLEMENTED;
2046 }
2047
2048
2049 /* Function 72 */
2050 DWORD PNP_RegisterServiceNotification(
2051 handle_t hBinding)
2052 {
2053 UNIMPLEMENTED;
2054 return CR_CALL_NOT_IMPLEMENTED;
2055 }
2056
2057
2058 /* Function 73 */
2059 DWORD PNP_SetActiveService(
2060 handle_t hBinding)
2061 {
2062 UNIMPLEMENTED;
2063 return CR_CALL_NOT_IMPLEMENTED;
2064 }
2065
2066
2067 /* Function 74 */
2068 DWORD PNP_DeleteServiceDevices(
2069 handle_t hBinding)
2070 {
2071 UNIMPLEMENTED;
2072 return CR_CALL_NOT_IMPLEMENTED;
2073 }
2074
2075
2076 static BOOL
2077 InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
2078 {
2079 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
2080 NTSTATUS Status;
2081 BOOL DeviceInstalled = FALSE;
2082 DWORD BytesWritten;
2083 DWORD Value;
2084 HANDLE hPipe = INVALID_HANDLE_VALUE;
2085 LPVOID Environment = NULL;
2086 PROCESS_INFORMATION ProcessInfo;
2087 STARTUPINFOW StartupInfo;
2088 UUID RandomUuid;
2089
2090 /* The following lengths are constant (see below), they cannot overflow */
2091 WCHAR CommandLine[116];
2092 WCHAR InstallEventName[73];
2093 WCHAR PipeName[74];
2094 WCHAR UuidString[39];
2095
2096 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance, ShowWizard);
2097
2098 ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
2099
2100 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
2101 DeviceInstance);
2102 PlugPlayData.Operation = 0; /* Get status */
2103
2104 /* Get device status */
2105 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
2106 (PVOID)&PlugPlayData,
2107 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
2108 if (!NT_SUCCESS(Status))
2109 {
2110 DPRINT1("NtPlugPlayControl('%S') failed with status 0x%08lx\n", DeviceInstance, Status);
2111 return FALSE;
2112 }
2113
2114 if ((PlugPlayData.DeviceStatus & (DNF_STARTED | DNF_START_FAILED)) != 0)
2115 {
2116 /* Device is already started, or disabled due to some problem. Don't install it */
2117 DPRINT("No need to install '%S'\n", DeviceInstance);
2118 return TRUE;
2119 }
2120
2121 /* Create a random UUID for the named pipe */
2122 UuidCreate(&RandomUuid);
2123 swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
2124 RandomUuid.Data1, RandomUuid.Data2, RandomUuid.Data3,
2125 RandomUuid.Data4[0], RandomUuid.Data4[1], RandomUuid.Data4[2],
2126 RandomUuid.Data4[3], RandomUuid.Data4[4], RandomUuid.Data4[5],
2127 RandomUuid.Data4[6], RandomUuid.Data4[7]);
2128
2129 /* Create the named pipe */
2130 wcscpy(PipeName, L"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
2131 wcscat(PipeName, UuidString);
2132 hPipe = CreateNamedPipeW(PipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 512, 512, 0, NULL);
2133
2134 if(hPipe == INVALID_HANDLE_VALUE)
2135 {
2136 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
2137 goto cleanup;
2138 }
2139
2140 /* Launch rundll32 to call ClientSideInstallW */
2141 wcscpy(CommandLine, L"rundll32.exe newdev.dll,ClientSideInstall ");
2142 wcscat(CommandLine, PipeName);
2143
2144 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
2145 StartupInfo.cb = sizeof(StartupInfo);
2146
2147 if(hUserToken)
2148 {
2149 /* newdev has to run under the environment of the current user */
2150 if(!CreateEnvironmentBlock(&Environment, hUserToken, FALSE))
2151 {
2152 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
2153 goto cleanup;
2154 }
2155
2156 if(!CreateProcessAsUserW(hUserToken, NULL, CommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, Environment, NULL, &StartupInfo, &ProcessInfo))
2157 {
2158 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
2159 goto cleanup;
2160 }
2161 }
2162 else
2163 {
2164 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
2165
2166 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
2167 (ShowWizard is only set to FALSE for these two modes) */
2168 ASSERT(!ShowWizard);
2169
2170 if(!CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo))
2171 {
2172 DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
2173 goto cleanup;
2174 }
2175 }
2176
2177 /* Wait for the function to connect to our pipe */
2178 if(!ConnectNamedPipe(hPipe, NULL))
2179 {
2180 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
2181 goto cleanup;
2182 }
2183
2184 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
2185 wcscpy(InstallEventName, L"Global\\PNP_Device_Install_Event_0.");
2186 wcscat(InstallEventName, UuidString);
2187
2188 Value = sizeof(InstallEventName);
2189 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
2190 WriteFile(hPipe, InstallEventName, Value, &BytesWritten, NULL);
2191
2192 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
2193 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
2194 WriteFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesWritten, NULL);
2195
2196 Value = (wcslen(DeviceInstance) + 1) * sizeof(WCHAR);
2197 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
2198 WriteFile(hPipe, DeviceInstance, Value, &BytesWritten, NULL);
2199
2200 /* Wait for newdev.dll to finish processing */
2201 WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
2202
2203 /* The following check for success is probably not compatible to Windows, but should do its job */
2204 if(!GetExitCodeProcess(ProcessInfo.hProcess, &Value))
2205 {
2206 DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
2207 goto cleanup;
2208 }
2209
2210 DeviceInstalled = Value;
2211
2212 cleanup:
2213 if(hPipe != INVALID_HANDLE_VALUE)
2214 CloseHandle(hPipe);
2215
2216 if(Environment)
2217 DestroyEnvironmentBlock(Environment);
2218
2219 if(ProcessInfo.hProcess)
2220 CloseHandle(ProcessInfo.hProcess);
2221
2222 if(ProcessInfo.hThread)
2223 CloseHandle(ProcessInfo.hThread);
2224
2225 return DeviceInstalled;
2226 }
2227
2228
2229 static LONG
2230 ReadRegSzKey(
2231 IN HKEY hKey,
2232 IN LPCWSTR pszKey,
2233 OUT LPWSTR* pValue)
2234 {
2235 LONG rc;
2236 DWORD dwType;
2237 DWORD cbData = 0;
2238 LPWSTR Value;
2239
2240 if (!pValue)
2241 return ERROR_INVALID_PARAMETER;
2242
2243 *pValue = NULL;
2244 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
2245 if (rc != ERROR_SUCCESS)
2246 return rc;
2247 if (dwType != REG_SZ)
2248 return ERROR_FILE_NOT_FOUND;
2249 Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
2250 if (!Value)
2251 return ERROR_NOT_ENOUGH_MEMORY;
2252 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
2253 if (rc != ERROR_SUCCESS)
2254 {
2255 HeapFree(GetProcessHeap(), 0, Value);
2256 return rc;
2257 }
2258 /* NULL-terminate the string */
2259 Value[cbData / sizeof(WCHAR)] = '\0';
2260
2261 *pValue = Value;
2262 return ERROR_SUCCESS;
2263 }
2264
2265
2266 static BOOL
2267 SetupIsActive(VOID)
2268 {
2269 HKEY hKey = NULL;
2270 DWORD regType, active, size;
2271 LONG rc;
2272 BOOL ret = FALSE;
2273
2274 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
2275 if (rc != ERROR_SUCCESS)
2276 goto cleanup;
2277
2278 size = sizeof(DWORD);
2279 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
2280 if (rc != ERROR_SUCCESS)
2281 goto cleanup;
2282 if (regType != REG_DWORD || size != sizeof(DWORD))
2283 goto cleanup;
2284
2285 ret = (active != 0);
2286
2287 cleanup:
2288 if (hKey != NULL)
2289 RegCloseKey(hKey);
2290
2291 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
2292
2293 return ret;
2294 }
2295
2296
2297 static BOOL
2298 IsConsoleBoot(VOID)
2299 {
2300 HKEY ControlKey = NULL;
2301 LPWSTR SystemStartOptions = NULL;
2302 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
2303 BOOL ConsoleBoot = FALSE;
2304 LONG rc;
2305
2306 rc = RegOpenKeyExW(
2307 HKEY_LOCAL_MACHINE,
2308 L"SYSTEM\\CurrentControlSet\\Control",
2309 0,
2310 KEY_QUERY_VALUE,
2311 &ControlKey);
2312
2313 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
2314 if (rc != ERROR_SUCCESS)
2315 goto cleanup;
2316
2317 /* Check for CMDCONS in SystemStartOptions */
2318 CurrentOption = SystemStartOptions;
2319 while (CurrentOption)
2320 {
2321 NextOption = wcschr(CurrentOption, L' ');
2322 if (NextOption)
2323 *NextOption = L'\0';
2324 if (_wcsicmp(CurrentOption, L"CONSOLE") == 0)
2325 {
2326 DPRINT("Found %S. Switching to console boot\n", CurrentOption);
2327 ConsoleBoot = TRUE;
2328 goto cleanup;
2329 }
2330 CurrentOption = NextOption ? NextOption + 1 : NULL;
2331 }
2332
2333 cleanup:
2334 if (ControlKey != NULL)
2335 RegCloseKey(ControlKey);
2336 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
2337 return ConsoleBoot;
2338 }
2339
2340
2341 /* Loop to install all queued devices installations */
2342 static DWORD WINAPI
2343 DeviceInstallThread(LPVOID lpParameter)
2344 {
2345 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2346 PSLIST_ENTRY ListEntry;
2347 #else
2348 PLIST_ENTRY ListEntry;
2349 #endif
2350 DeviceInstallParams* Params;
2351 BOOL showWizard;
2352
2353 UNREFERENCED_PARAMETER(lpParameter);
2354
2355 WaitForSingleObject(hInstallEvent, INFINITE);
2356
2357 showWizard = !SetupIsActive() && !IsConsoleBoot();
2358
2359 while (TRUE)
2360 {
2361 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2362 ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead);
2363 #else
2364 if ((BOOL)IsListEmpty(&DeviceInstallListHead))
2365 ListEntry = NULL;
2366 else
2367 ListEntry = RemoveHeadList(&DeviceInstallListHead);
2368 #endif
2369 if (ListEntry == NULL)
2370 {
2371 SetEvent(hNoPendingInstalls);
2372 WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE);
2373 }
2374 else
2375 {
2376 ResetEvent(hNoPendingInstalls);
2377 Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry);
2378 InstallDevice(Params->DeviceIds, showWizard);
2379 }
2380 }
2381
2382 return 0;
2383 }
2384
2385
2386 static DWORD WINAPI
2387 PnpEventThread(LPVOID lpParameter)
2388 {
2389 PPLUGPLAY_EVENT_BLOCK PnpEvent;
2390 ULONG PnpEventSize;
2391 NTSTATUS Status;
2392 RPC_STATUS RpcStatus;
2393
2394 UNREFERENCED_PARAMETER(lpParameter);
2395
2396 PnpEventSize = 0x1000;
2397 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
2398 if (PnpEvent == NULL)
2399 return ERROR_OUTOFMEMORY;
2400
2401 for (;;)
2402 {
2403 DPRINT("Calling NtGetPlugPlayEvent()\n");
2404
2405 /* Wait for the next pnp event */
2406 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
2407
2408 /* Resize the buffer for the PnP event if it's too small. */
2409 if (Status == STATUS_BUFFER_TOO_SMALL)
2410 {
2411 PnpEventSize += 0x400;
2412 HeapFree(GetProcessHeap(), 0, PnpEvent);
2413 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
2414 if (PnpEvent == NULL)
2415 return ERROR_OUTOFMEMORY;
2416 continue;
2417 }
2418
2419 if (!NT_SUCCESS(Status))
2420 {
2421 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status);
2422 break;
2423 }
2424
2425 /* Process the pnp event */
2426 DPRINT("Received PnP Event\n");
2427 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ENUMERATED, &RpcStatus))
2428 {
2429 DeviceInstallParams* Params;
2430 DWORD len;
2431 DWORD DeviceIdLength;
2432
2433 DPRINT("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds);
2434
2435 DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds);
2436 if (DeviceIdLength)
2437 {
2438 /* Queue device install (will be dequeued by DeviceInstallThread */
2439 len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
2440 Params = HeapAlloc(GetProcessHeap(), 0, len);
2441 if (Params)
2442 {
2443 wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
2444 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2445 InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry);
2446 #else
2447 InsertTailList(&DeviceInstallListHead, &Params->ListEntry);
2448 #endif
2449 SetEvent(hDeviceInstallListNotEmpty);
2450 }
2451 }
2452 }
2453 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
2454 {
2455 DPRINT("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds);
2456 /* FIXME: ? */
2457 }
2458 else
2459 {
2460 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
2461 PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
2462 PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
2463 PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
2464 PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
2465 }
2466
2467 /* Dequeue the current pnp event and signal the next one */
2468 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
2469 }
2470
2471 HeapFree(GetProcessHeap(), 0, PnpEvent);
2472
2473 return ERROR_SUCCESS;
2474 }
2475
2476
2477 static VOID
2478 UpdateServiceStatus(DWORD dwState)
2479 {
2480 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
2481 ServiceStatus.dwCurrentState = dwState;
2482 ServiceStatus.dwControlsAccepted = 0;
2483 ServiceStatus.dwWin32ExitCode = 0;
2484 ServiceStatus.dwServiceSpecificExitCode = 0;
2485 ServiceStatus.dwCheckPoint = 0;
2486
2487 if (dwState == SERVICE_START_PENDING ||
2488 dwState == SERVICE_STOP_PENDING ||
2489 dwState == SERVICE_PAUSE_PENDING ||
2490 dwState == SERVICE_CONTINUE_PENDING)
2491 ServiceStatus.dwWaitHint = 10000;
2492 else
2493 ServiceStatus.dwWaitHint = 0;
2494
2495 SetServiceStatus(ServiceStatusHandle,
2496 &ServiceStatus);
2497 }
2498
2499
2500 static DWORD WINAPI
2501 ServiceControlHandler(DWORD dwControl,
2502 DWORD dwEventType,
2503 LPVOID lpEventData,
2504 LPVOID lpContext)
2505 {
2506 DPRINT1("ServiceControlHandler() called\n");
2507
2508 switch (dwControl)
2509 {
2510 case SERVICE_CONTROL_STOP:
2511 DPRINT1(" SERVICE_CONTROL_STOP received\n");
2512 UpdateServiceStatus(SERVICE_STOPPED);
2513 return ERROR_SUCCESS;
2514
2515 case SERVICE_CONTROL_PAUSE:
2516 DPRINT1(" SERVICE_CONTROL_PAUSE received\n");
2517 UpdateServiceStatus(SERVICE_PAUSED);
2518 return ERROR_SUCCESS;
2519
2520 case SERVICE_CONTROL_CONTINUE:
2521 DPRINT1(" SERVICE_CONTROL_CONTINUE received\n");
2522 UpdateServiceStatus(SERVICE_RUNNING);
2523 return ERROR_SUCCESS;
2524
2525 case SERVICE_CONTROL_INTERROGATE:
2526 DPRINT1(" SERVICE_CONTROL_INTERROGATE received\n");
2527 SetServiceStatus(ServiceStatusHandle,
2528 &ServiceStatus);
2529 return ERROR_SUCCESS;
2530
2531 case SERVICE_CONTROL_SHUTDOWN:
2532 DPRINT1(" SERVICE_CONTROL_SHUTDOWN received\n");
2533 UpdateServiceStatus(SERVICE_STOPPED);
2534 return ERROR_SUCCESS;
2535
2536 default :
2537 DPRINT1(" Control %lu received\n");
2538 return ERROR_CALL_NOT_IMPLEMENTED;
2539 }
2540 }
2541
2542
2543 static VOID CALLBACK
2544 ServiceMain(DWORD argc, LPTSTR *argv)
2545 {
2546 HANDLE hThread;
2547 DWORD dwThreadId;
2548
2549 UNREFERENCED_PARAMETER(argc);
2550 UNREFERENCED_PARAMETER(argv);
2551
2552 DPRINT("ServiceMain() called\n");
2553
2554 ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName,
2555 ServiceControlHandler,
2556 NULL);
2557 if (!ServiceStatusHandle)
2558 {
2559 DPRINT1("RegisterServiceCtrlHandlerExW() failed! (Error %lu)\n", GetLastError());
2560 return;
2561 }
2562
2563 UpdateServiceStatus(SERVICE_START_PENDING);
2564
2565 hThread = CreateThread(NULL,
2566 0,
2567 PnpEventThread,
2568 NULL,
2569 0,
2570 &dwThreadId);
2571 if (hThread != NULL)
2572 CloseHandle(hThread);
2573
2574 hThread = CreateThread(NULL,
2575 0,
2576 RpcServerThread,
2577 NULL,
2578 0,
2579 &dwThreadId);
2580 if (hThread != NULL)
2581 CloseHandle(hThread);
2582
2583 hThread = CreateThread(NULL,
2584 0,
2585 DeviceInstallThread,
2586 NULL,
2587 0,
2588 &dwThreadId);
2589 if (hThread != NULL)
2590 CloseHandle(hThread);
2591
2592 UpdateServiceStatus(SERVICE_RUNNING);
2593
2594 DPRINT("ServiceMain() done\n");
2595 }
2596
2597
2598 int
2599 wmain(int argc, WCHAR *argv[])
2600 {
2601 BOOLEAN OldValue;
2602 DWORD dwError;
2603
2604 UNREFERENCED_PARAMETER(argc);
2605 UNREFERENCED_PARAMETER(argv);
2606
2607 DPRINT("Umpnpmgr: main() started\n");
2608
2609 /* We need this privilege for using CreateProcessAsUserW */
2610 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue);
2611
2612 hInstallEvent = CreateEvent(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
2613 if (hInstallEvent == NULL)
2614 {
2615 dwError = GetLastError();
2616 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
2617 return dwError;
2618 }
2619
2620 hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL);
2621 if (hDeviceInstallListNotEmpty == NULL)
2622 {
2623 dwError = GetLastError();
2624 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
2625 return dwError;
2626 }
2627
2628 hNoPendingInstalls = CreateEventW(NULL,
2629 TRUE,
2630 FALSE,
2631 L"Global\\PnP_No_Pending_Install_Events");
2632 if (hNoPendingInstalls == NULL)
2633 {
2634 dwError = GetLastError();
2635 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
2636 return dwError;
2637 }
2638
2639 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2640 InitializeSListHead(&DeviceInstallListHead);
2641 #else
2642 InitializeListHead(&DeviceInstallListHead);
2643 #endif
2644
2645 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2646 L"System\\CurrentControlSet\\Enum",
2647 0,
2648 KEY_ALL_ACCESS,
2649 &hEnumKey);
2650 if (dwError != ERROR_SUCCESS)
2651 {
2652 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
2653 return dwError;
2654 }
2655
2656 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2657 L"System\\CurrentControlSet\\Control\\Class",
2658 0,
2659 KEY_ALL_ACCESS,
2660 &hClassKey);
2661 if (dwError != ERROR_SUCCESS)
2662 {
2663 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
2664 return dwError;
2665 }
2666
2667 StartServiceCtrlDispatcher(ServiceTable);
2668
2669 DPRINT("Umpnpmgr: main() done\n");
2670
2671 ExitThread(0);
2672
2673 return 0;
2674 }
2675
2676 /* EOF */