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