Implement basic version of PNP_CreateKey.
[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 HKEY hKey = 0;
835
836 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
837 pszSubKey,
838 0,
839 NULL,
840 0,
841 KEY_ALL_ACCESS,
842 NULL,
843 &hKey,
844 NULL))
845 return CR_REGISTRY_ERROR;
846
847 /* FIXME: Set security key */
848
849 RegCloseKey(hKey);
850
851 return CR_SUCCESS;
852 }
853
854
855 /* Function 17 */
856 DWORD PNP_DeleteRegistryKey(
857 handle_t hBinding,
858 LPWSTR pszDeviceID,
859 LPWSTR pszParentKey,
860 LPWSTR pszChildKey,
861 DWORD ulFlags)
862 {
863 UNIMPLEMENTED;
864 return CR_CALL_NOT_IMPLEMENTED;
865 }
866
867
868 /* Function 18 */
869 DWORD PNP_GetClassCount(
870 handle_t hBinding,
871 DWORD *pulClassCount,
872 DWORD ulFlags)
873 {
874 HKEY hKey;
875 DWORD dwError;
876
877 UNREFERENCED_PARAMETER(hBinding);
878 UNREFERENCED_PARAMETER(ulFlags);
879
880 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
881 REGSTR_PATH_CLASS,
882 0,
883 KEY_QUERY_VALUE,
884 &hKey);
885 if (dwError != ERROR_SUCCESS)
886 return CR_INVALID_DATA;
887
888 dwError = RegQueryInfoKeyW(hKey,
889 NULL,
890 NULL,
891 NULL,
892 pulClassCount,
893 NULL,
894 NULL,
895 NULL,
896 NULL,
897 NULL,
898 NULL,
899 NULL);
900 RegCloseKey(hKey);
901 if (dwError != ERROR_SUCCESS)
902 return CR_INVALID_DATA;
903
904 return CR_SUCCESS;
905 }
906
907
908 /* Function 19 */
909 DWORD PNP_GetClassName(
910 handle_t hBinding,
911 LPWSTR pszClassGuid,
912 LPWSTR Buffer,
913 PNP_RPC_STRING_LEN *pulLength,
914 DWORD ulFlags)
915 {
916 WCHAR szKeyName[MAX_PATH];
917 CONFIGRET ret = CR_SUCCESS;
918 HKEY hKey;
919 DWORD dwSize;
920
921 UNREFERENCED_PARAMETER(hBinding);
922 UNREFERENCED_PARAMETER(ulFlags);
923
924 DPRINT("PNP_GetClassName() called\n");
925
926 lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\");
927 if(lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR)))
928 lstrcatW(szKeyName, pszClassGuid);
929 else return CR_INVALID_DATA;
930
931 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
932 szKeyName,
933 0,
934 KEY_QUERY_VALUE,
935 &hKey))
936 return CR_REGISTRY_ERROR;
937
938 dwSize = *pulLength * sizeof(WCHAR);
939 if (RegQueryValueExW(hKey,
940 L"Class",
941 NULL,
942 NULL,
943 (LPBYTE)Buffer,
944 &dwSize))
945 {
946 *pulLength = 0;
947 ret = CR_REGISTRY_ERROR;
948 }
949 else
950 {
951 *pulLength = dwSize / sizeof(WCHAR);
952 }
953
954 RegCloseKey(hKey);
955
956 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret);
957
958 return ret;
959 }
960
961
962 /* Function 20 */
963 DWORD PNP_DeleteClassKey(
964 handle_t hBinding,
965 LPWSTR pszClassGuid,
966 DWORD ulFlags)
967 {
968 CONFIGRET ret = CR_SUCCESS;
969
970 UNREFERENCED_PARAMETER(hBinding);
971
972 DPRINT("PNP_GetClassName(%S, %lx) called\n", pszClassGuid, ulFlags);
973
974 if (ulFlags & CM_DELETE_CLASS_SUBKEYS)
975 {
976 if (RegDeleteTreeW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
977 ret = CR_REGISTRY_ERROR;
978 }
979 else
980 {
981 if (RegDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
982 ret = CR_REGISTRY_ERROR;
983 }
984
985 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret);
986
987 return ret;
988 }
989
990
991 /* Function 21 */
992 DWORD PNP_GetInterfaceDeviceAlias(
993 handle_t hBinding,
994 LPWSTR pszInterfaceDevice,
995 GUID *AliasInterfaceGuid,
996 LPWSTR pszAliasInterfaceDevice,
997 PNP_RPC_STRING_LEN *pulLength,
998 PNP_RPC_STRING_LEN *pulTransferLen,
999 DWORD ulFlags)
1000 {
1001 UNIMPLEMENTED;
1002 return CR_CALL_NOT_IMPLEMENTED;
1003 }
1004
1005
1006 /* Function 22 */
1007 DWORD PNP_GetInterfaceDeviceList(
1008 handle_t hBinding,
1009 GUID *InterfaceGuid,
1010 LPWSTR pszDeviceID,
1011 BYTE *Buffer,
1012 PNP_RPC_BUFFER_SIZE *pulLength,
1013 DWORD ulFlags)
1014 {
1015 UNIMPLEMENTED;
1016 return CR_CALL_NOT_IMPLEMENTED;
1017 }
1018
1019
1020 /* Function 23 */
1021 DWORD PNP_GetInterfaceDeviceListSize(
1022 handle_t hBinding,
1023 PNP_RPC_BUFFER_SIZE *pulLen,
1024 GUID *InterfaceGuid,
1025 LPWSTR pszDeviceID,
1026 DWORD ulFlags)
1027 {
1028 UNIMPLEMENTED;
1029 return CR_CALL_NOT_IMPLEMENTED;
1030 }
1031
1032
1033 /* Function 24 */
1034 DWORD PNP_RegisterDeviceClassAssociation(
1035 handle_t hBinding,
1036 LPWSTR pszDeviceID,
1037 GUID *InterfaceGuid,
1038 LPWSTR pszReference,
1039 LPWSTR pszSymLink,
1040 PNP_RPC_STRING_LEN *pulLength,
1041 PNP_RPC_STRING_LEN *pulTransferLen,
1042 DWORD ulFlags)
1043 {
1044 UNIMPLEMENTED;
1045 return CR_CALL_NOT_IMPLEMENTED;
1046 }
1047
1048
1049 /* Function 25 */
1050 DWORD PNP_UnregisterDeviceClassAssociation(
1051 handle_t hBinding,
1052 LPWSTR pszInterfaceDevice,
1053 DWORD ulFlags)
1054 {
1055 UNIMPLEMENTED;
1056 return CR_CALL_NOT_IMPLEMENTED;
1057 }
1058
1059
1060 /* Function 26 */
1061 DWORD PNP_GetClassRegProp(
1062 handle_t hBinding,
1063 LPWSTR pszClassGuid,
1064 DWORD ulProperty,
1065 DWORD *pulRegDataType,
1066 BYTE *Buffer,
1067 PNP_RPC_STRING_LEN *pulTransferLen,
1068 PNP_RPC_STRING_LEN *pulLength,
1069 DWORD ulFlags)
1070 {
1071 UNIMPLEMENTED;
1072 return CR_CALL_NOT_IMPLEMENTED;
1073 }
1074
1075
1076 /* Function 27 */
1077 DWORD PNP_SetClassRegProp(
1078 handle_t hBinding,
1079 LPWSTR *pszClassGuid,
1080 DWORD ulProperty,
1081 DWORD ulDataType,
1082 BYTE *Buffer,
1083 PNP_PROP_SIZE ulLength,
1084 DWORD ulFlags)
1085 {
1086 UNIMPLEMENTED;
1087 return CR_CALL_NOT_IMPLEMENTED;
1088 }
1089
1090
1091 /* Function 28 */
1092 DWORD PNP_CreateDevInst(
1093 handle_t hBinding,
1094 LPWSTR pszDeviceID,
1095 LPWSTR pszParentDeviceID,
1096 PNP_RPC_STRING_LEN ulLength,
1097 DWORD ulFlags)
1098 {
1099 UNIMPLEMENTED;
1100 return CR_CALL_NOT_IMPLEMENTED;
1101 }
1102
1103
1104 static CONFIGRET
1105 MoveDeviceInstance(LPWSTR pszDeviceInstanceDestination,
1106 LPWSTR pszDeviceInstanceSource)
1107 {
1108 DPRINT("MoveDeviceInstance: not implemented\n");
1109 /* FIXME */
1110 return CR_CALL_NOT_IMPLEMENTED;
1111 }
1112
1113
1114 static CONFIGRET
1115 SetupDeviceInstance(LPWSTR pszDeviceInstance,
1116 DWORD ulFlags)
1117 {
1118 DPRINT("SetupDeviceInstance: not implemented\n");
1119 /* FIXME */
1120 return CR_CALL_NOT_IMPLEMENTED;
1121 }
1122
1123
1124 static CONFIGRET
1125 EnableDeviceInstance(LPWSTR pszDeviceInstance)
1126 {
1127 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
1128 CONFIGRET ret = CR_SUCCESS;
1129 NTSTATUS Status;
1130
1131 DPRINT("Enable device instance\n");
1132
1133 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance, pszDeviceInstance);
1134 Status = NtPlugPlayControl(PlugPlayControlResetDevice, &ResetDeviceData, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
1135 if (!NT_SUCCESS(Status))
1136 ret = NtStatusToCrError(Status);
1137
1138 return ret;
1139 }
1140
1141
1142 static CONFIGRET
1143 DisableDeviceInstance(LPWSTR pszDeviceInstance)
1144 {
1145 DPRINT("DisableDeviceInstance: not implemented\n");
1146 /* FIXME */
1147 return CR_CALL_NOT_IMPLEMENTED;
1148 }
1149
1150
1151 static CONFIGRET
1152 ReenumerateDeviceInstance(LPWSTR pszDeviceInstance)
1153 {
1154 DPRINT("ReenumerateDeviceInstance: not implemented\n");
1155 /* FIXME */
1156 return CR_CALL_NOT_IMPLEMENTED;
1157 }
1158
1159
1160 /* Function 29 */
1161 DWORD PNP_DeviceInstanceAction(
1162 handle_t hBinding,
1163 DWORD ulAction,
1164 DWORD ulFlags,
1165 LPWSTR pszDeviceInstance1,
1166 LPWSTR pszDeviceInstance2)
1167 {
1168 CONFIGRET ret = CR_SUCCESS;
1169
1170 UNREFERENCED_PARAMETER(hBinding);
1171
1172 DPRINT("PNP_DeviceInstanceAction() called\n");
1173
1174 switch (ulAction)
1175 {
1176 case PNP_DEVINST_MOVE:
1177 ret = MoveDeviceInstance(pszDeviceInstance1,
1178 pszDeviceInstance2);
1179 break;
1180
1181 case PNP_DEVINST_SETUP:
1182 ret = SetupDeviceInstance(pszDeviceInstance1,
1183 ulFlags);
1184 break;
1185
1186 case PNP_DEVINST_ENABLE:
1187 ret = EnableDeviceInstance(pszDeviceInstance1);
1188 break;
1189
1190 case PNP_DEVINST_DISABLE:
1191 ret = DisableDeviceInstance(pszDeviceInstance1);
1192 break;
1193
1194 case PNP_DEVINST_REENUMERATE:
1195 ret = ReenumerateDeviceInstance(pszDeviceInstance1);
1196 break;
1197
1198 default:
1199 DPRINT1("Unknown device action %lu: not implemented\n", ulAction);
1200 ret = CR_CALL_NOT_IMPLEMENTED;
1201 }
1202
1203 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
1204
1205 return ret;
1206 }
1207
1208
1209 /* Function 30 */
1210 DWORD PNP_GetDeviceStatus(
1211 handle_t hBinding,
1212 LPWSTR pDeviceID,
1213 DWORD *pulStatus,
1214 DWORD *pulProblem,
1215 DWORD ulFlags)
1216 {
1217 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
1218 CONFIGRET ret = CR_SUCCESS;
1219 NTSTATUS Status;
1220
1221 UNREFERENCED_PARAMETER(hBinding);
1222 UNREFERENCED_PARAMETER(ulFlags);
1223
1224 DPRINT("PNP_GetDeviceStatus() called\n");
1225
1226 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1227 pDeviceID);
1228 PlugPlayData.Operation = 0; /* Get status */
1229
1230 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
1231 (PVOID)&PlugPlayData,
1232 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
1233 if (NT_SUCCESS(Status))
1234 {
1235 *pulStatus = PlugPlayData.DeviceStatus;
1236 *pulProblem = PlugPlayData.DeviceProblem;
1237 }
1238 else
1239 {
1240 ret = NtStatusToCrError(Status);
1241 }
1242
1243 DPRINT("PNP_GetDeviceStatus() done (returns %lx)\n", ret);
1244
1245 return ret;
1246 }
1247
1248
1249 /* Function 31 */
1250 DWORD PNP_SetDeviceProblem(
1251 handle_t hBinding,
1252 LPWSTR pDeviceID,
1253 DWORD ulProblem,
1254 DWORD ulFlags)
1255 {
1256 UNIMPLEMENTED;
1257 return CR_CALL_NOT_IMPLEMENTED;
1258 }
1259
1260
1261 /* Function 32 */
1262 DWORD PNP_DisableDevInst(
1263 handle_t hBinding,
1264 LPWSTR pDeviceID,
1265 PPNP_VETO_TYPE pVetoType,
1266 LPWSTR pszVetoName,
1267 DWORD ulNameLength,
1268 DWORD ulFlags)
1269 {
1270 UNIMPLEMENTED;
1271 return CR_CALL_NOT_IMPLEMENTED;
1272 }
1273
1274 /* Function 33 */
1275 DWORD PNP_UninstallDevInst(
1276 handle_t hBinding,
1277 LPWSTR pDeviceID,
1278 DWORD ulFlags)
1279 {
1280 UNIMPLEMENTED;
1281 return CR_CALL_NOT_IMPLEMENTED;
1282 }
1283
1284
1285 static BOOL
1286 CheckForDeviceId(LPWSTR lpDeviceIdList,
1287 LPWSTR lpDeviceId)
1288 {
1289 LPWSTR lpPtr;
1290 DWORD dwLength;
1291
1292 lpPtr = lpDeviceIdList;
1293 while (*lpPtr != 0)
1294 {
1295 dwLength = wcslen(lpPtr);
1296 if (0 == _wcsicmp(lpPtr, lpDeviceId))
1297 return TRUE;
1298
1299 lpPtr += (dwLength + 1);
1300 }
1301
1302 return FALSE;
1303 }
1304
1305
1306 static VOID
1307 AppendDeviceId(LPWSTR lpDeviceIdList,
1308 LPDWORD lpDeviceIdListSize,
1309 LPWSTR lpDeviceId)
1310 {
1311 DWORD dwLen;
1312 DWORD dwPos;
1313
1314 dwLen = wcslen(lpDeviceId);
1315 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
1316
1317 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
1318
1319 dwPos += (dwLen + 1);
1320
1321 lpDeviceIdList[dwPos] = 0;
1322
1323 *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
1324 }
1325
1326
1327 /* Function 34 */
1328 DWORD PNP_AddID(
1329 handle_t hBinding,
1330 LPWSTR pszDeviceID,
1331 LPWSTR pszID,
1332 DWORD ulFlags)
1333 {
1334 CONFIGRET ret = CR_SUCCESS;
1335 HKEY hDeviceKey;
1336 LPWSTR pszSubKey;
1337 DWORD dwDeviceIdListSize;
1338 DWORD dwNewDeviceIdSize;
1339 WCHAR * pszDeviceIdList = NULL;
1340
1341 UNREFERENCED_PARAMETER(hBinding);
1342
1343 DPRINT("PNP_AddID() called\n");
1344 DPRINT(" DeviceInstance: %S\n", pszDeviceID);
1345 DPRINT(" DeviceId: %S\n", pszID);
1346 DPRINT(" Flags: %lx\n", ulFlags);
1347
1348 if (RegOpenKeyExW(hEnumKey,
1349 pszDeviceID,
1350 0,
1351 KEY_QUERY_VALUE | KEY_SET_VALUE,
1352 &hDeviceKey) != ERROR_SUCCESS)
1353 {
1354 DPRINT("Failed to open the device key!\n");
1355 return CR_INVALID_DEVNODE;
1356 }
1357
1358 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
1359
1360 if (RegQueryValueExW(hDeviceKey,
1361 pszSubKey,
1362 NULL,
1363 NULL,
1364 NULL,
1365 &dwDeviceIdListSize) != ERROR_SUCCESS)
1366 {
1367 DPRINT("Failed to query the desired ID string!\n");
1368 ret = CR_REGISTRY_ERROR;
1369 goto Done;
1370 }
1371
1372 dwNewDeviceIdSize = lstrlenW(pszDeviceID);
1373 if (!dwNewDeviceIdSize)
1374 {
1375 ret = CR_INVALID_POINTER;
1376 goto Done;
1377 }
1378
1379 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR);
1380
1381 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize);
1382 if (!pszDeviceIdList)
1383 {
1384 DPRINT("Failed to allocate memory for the desired ID string!\n");
1385 ret = CR_OUT_OF_MEMORY;
1386 goto Done;
1387 }
1388
1389 if (RegQueryValueExW(hDeviceKey,
1390 pszSubKey,
1391 NULL,
1392 NULL,
1393 (LPBYTE)pszDeviceIdList,
1394 &dwDeviceIdListSize) != ERROR_SUCCESS)
1395 {
1396 DPRINT("Failed to query the desired ID string!\n");
1397 ret = CR_REGISTRY_ERROR;
1398 goto Done;
1399 }
1400
1401 /* Check whether the device ID is already in use */
1402 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID))
1403 {
1404 DPRINT("Device ID was found in the ID string!\n");
1405 ret = CR_SUCCESS;
1406 goto Done;
1407 }
1408
1409 /* Append the Device ID */
1410 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID);
1411
1412 if (RegSetValueExW(hDeviceKey,
1413 pszSubKey,
1414 0,
1415 REG_MULTI_SZ,
1416 (LPBYTE)pszDeviceIdList,
1417 dwDeviceIdListSize) != ERROR_SUCCESS)
1418 {
1419 DPRINT("Failed to set the desired ID string!\n");
1420 ret = CR_REGISTRY_ERROR;
1421 }
1422
1423 Done:
1424 RegCloseKey(hDeviceKey);
1425 if (pszDeviceIdList)
1426 HeapFree(GetProcessHeap(), 0, pszDeviceIdList);
1427
1428 DPRINT("PNP_AddID() done (returns %lx)\n", ret);
1429
1430 return ret;
1431 }
1432
1433
1434 /* Function 35 */
1435 DWORD PNP_RegisterDriver(
1436 handle_t hBinding,
1437 LPWSTR pszDeviceID,
1438 DWORD ulFlags)
1439 {
1440 UNIMPLEMENTED;
1441 return CR_CALL_NOT_IMPLEMENTED;
1442 }
1443
1444
1445 /* Function 36 */
1446 DWORD PNP_QueryRemove(
1447 handle_t hBinding,
1448 LPWSTR pszDeviceID,
1449 PPNP_VETO_TYPE pVetoType,
1450 LPWSTR pszVetoName,
1451 DWORD ulNameLength,
1452 DWORD ulFlags)
1453 {
1454 UNIMPLEMENTED;
1455 return CR_CALL_NOT_IMPLEMENTED;
1456 }
1457
1458
1459 /* Function 37 */
1460 DWORD PNP_RequestDeviceEject(
1461 handle_t hBinding,
1462 LPWSTR pszDeviceID,
1463 PPNP_VETO_TYPE pVetoType,
1464 LPWSTR pszVetoName,
1465 DWORD ulNameLength,
1466 DWORD ulFlags)
1467 {
1468 UNIMPLEMENTED;
1469 return CR_CALL_NOT_IMPLEMENTED;
1470 }
1471
1472 /* Function 38 */
1473 CONFIGRET
1474 PNP_IsDockStationPresent(handle_t hBinding,
1475 BOOL *Present)
1476 {
1477 HKEY hKey;
1478 DWORD dwType;
1479 DWORD dwValue;
1480 DWORD dwSize;
1481 CONFIGRET ret = CR_SUCCESS;
1482
1483 UNREFERENCED_PARAMETER(hBinding);
1484
1485 DPRINT1("PNP_IsDockStationPresent() called\n");
1486
1487 *Present = FALSE;
1488
1489 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
1490 L"CurrentDockInfo",
1491 0,
1492 KEY_READ,
1493 &hKey) != ERROR_SUCCESS)
1494 return CR_REGISTRY_ERROR;
1495
1496 dwSize = sizeof(DWORD);
1497 if (RegQueryValueExW(hKey,
1498 L"DockingState",
1499 NULL,
1500 &dwType,
1501 (LPBYTE)&dwValue,
1502 &dwSize) != ERROR_SUCCESS)
1503 ret = CR_REGISTRY_ERROR;
1504
1505 RegCloseKey(hKey);
1506
1507 if (ret == CR_SUCCESS)
1508 {
1509 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
1510 {
1511 ret = CR_REGISTRY_ERROR;
1512 }
1513 else if (dwValue != 0)
1514 {
1515 *Present = TRUE;
1516 }
1517 }
1518
1519 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
1520
1521 return ret;
1522 }
1523
1524
1525 /* Function 39 */
1526 DWORD PNP_RequestEjectPC(
1527 handle_t hBinding)
1528 {
1529 UNIMPLEMENTED;
1530 return CR_CALL_NOT_IMPLEMENTED;
1531 }
1532
1533
1534 /* Function 40 */
1535 DWORD PNP_HwProfFlags(
1536 handle_t hBinding,
1537 DWORD ulAction,
1538 LPWSTR pDeviceID,
1539 DWORD ulConfig,
1540 DWORD *pulValue,
1541 PPNP_VETO_TYPE pVetoType,
1542 LPWSTR pszVetoName,
1543 DWORD ulNameLength,
1544 DWORD ulFlags)
1545 {
1546 CONFIGRET ret = CR_SUCCESS;
1547 WCHAR szKeyName[MAX_PATH];
1548 HKEY hKey;
1549 HKEY hDeviceKey;
1550 DWORD dwSize;
1551
1552 UNREFERENCED_PARAMETER(hBinding);
1553
1554 DPRINT("PNP_HwProfFlags() called\n");
1555
1556 if (ulConfig == 0)
1557 {
1558 wcscpy(szKeyName,
1559 L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
1560 }
1561 else
1562 {
1563 swprintf(szKeyName,
1564 L"System\\CurrentControlSet\\HardwareProfiles\\%04u\\System\\CurrentControlSet\\Enum",
1565 ulConfig);
1566 }
1567
1568 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1569 szKeyName,
1570 0,
1571 KEY_QUERY_VALUE,
1572 &hKey) != ERROR_SUCCESS)
1573 return CR_REGISTRY_ERROR;
1574
1575 if (ulAction == PNP_GET_HWPROFFLAGS)
1576 {
1577 if (RegOpenKeyExW(hKey,
1578 pDeviceID,
1579 0,
1580 KEY_QUERY_VALUE,
1581 &hDeviceKey) != ERROR_SUCCESS)
1582 {
1583 *pulValue = 0;
1584 }
1585 else
1586 {
1587 dwSize = sizeof(DWORD);
1588 if (!RegQueryValueExW(hDeviceKey,
1589 L"CSConfigFlags",
1590 NULL,
1591 NULL,
1592 (LPBYTE)pulValue,
1593 &dwSize) != ERROR_SUCCESS)
1594 {
1595 *pulValue = 0;
1596 }
1597
1598 RegCloseKey(hDeviceKey);
1599 }
1600 }
1601 else if (ulAction == PNP_SET_HWPROFFLAGS)
1602 {
1603 /* FIXME: not implemented yet */
1604 ret = CR_CALL_NOT_IMPLEMENTED;
1605 }
1606
1607 RegCloseKey(hKey);
1608
1609 return ret;
1610 }
1611
1612
1613 /* Function 41 */
1614 DWORD PNP_GetHwProfInfo(
1615 handle_t hBinding,
1616 DWORD ulIndex,
1617 HWPROFILEINFO *pHWProfileInfo,
1618 DWORD ulProfileInfoSize,
1619 DWORD ulFlags)
1620 {
1621 UNIMPLEMENTED;
1622 return CR_CALL_NOT_IMPLEMENTED;
1623 }
1624
1625
1626 /* Function 42 */
1627 DWORD PNP_AddEmptyLogConf(
1628 handle_t hBinding,
1629 LPWSTR pDeviceID,
1630 DWORD ulPriority,
1631 DWORD *pulLogConfTag,
1632 DWORD ulFlags)
1633 {
1634 UNIMPLEMENTED;
1635 return CR_CALL_NOT_IMPLEMENTED;
1636 }
1637
1638
1639 /* Function 43 */
1640 DWORD PNP_FreeLogConf(
1641 handle_t hBinding,
1642 LPWSTR pDeviceID,
1643 DWORD ulLogConfType,
1644 DWORD ulLogConfTag,
1645 DWORD ulFlags)
1646 {
1647 UNIMPLEMENTED;
1648 return CR_CALL_NOT_IMPLEMENTED;
1649 }
1650
1651
1652 /* Function 44 */
1653 DWORD PNP_GetFirstLogConf(
1654 handle_t hBinding,
1655 LPWSTR pDeviceID,
1656 DWORD ulLogConfType,
1657 DWORD *pulLogConfTag,
1658 DWORD ulFlags)
1659 {
1660 UNIMPLEMENTED;
1661 return CR_CALL_NOT_IMPLEMENTED;
1662 }
1663
1664
1665 /* Function 45 */
1666 DWORD PNP_GetNextLogConf(
1667 handle_t hBinding,
1668 LPWSTR pDeviceID,
1669 DWORD ulLogConfType,
1670 DWORD ulCurrentTag,
1671 DWORD *pulNextTag,
1672 DWORD ulFlags)
1673 {
1674 UNIMPLEMENTED;
1675 return CR_CALL_NOT_IMPLEMENTED;
1676 }
1677
1678
1679 /* Function 46 */
1680 DWORD PNP_GetLogConfPriority(
1681 handle_t hBinding,
1682 LPWSTR pDeviceID,
1683 DWORD ulType,
1684 DWORD ulTag,
1685 DWORD *pPriority,
1686 DWORD ulFlags)
1687 {
1688 UNIMPLEMENTED;
1689 return CR_CALL_NOT_IMPLEMENTED;
1690 }
1691
1692
1693 /* Function 47 */
1694 DWORD PNP_AddResDes(
1695 handle_t hBinding,
1696 LPWSTR pDeviceID,
1697 DWORD ulLogConfTag,
1698 DWORD ulLogConfType,
1699 RESOURCEID ResourceID,
1700 DWORD *pulResourceTag,
1701 BYTE *ResourceData,
1702 PNP_RPC_BUFFER_SIZE ResourceLen,
1703 DWORD ulFlags)
1704 {
1705 UNIMPLEMENTED;
1706 return CR_CALL_NOT_IMPLEMENTED;
1707 }
1708
1709
1710 /* Function 48 */
1711 DWORD PNP_FreeResDes(
1712 handle_t hBinding,
1713 LPWSTR pDeviceID,
1714 DWORD ulLogConfTag,
1715 DWORD ulLogConfType,
1716 RESOURCEID ResourceID,
1717 DWORD ulResourceTag,
1718 DWORD *pulPreviousResType,
1719 DWORD *pulPreviousResTag,
1720 DWORD ulFlags)
1721 {
1722 UNIMPLEMENTED;
1723 return CR_CALL_NOT_IMPLEMENTED;
1724 }
1725
1726
1727 /* Function 49 */
1728 DWORD PNP_GetNextResDes(
1729 handle_t hBinding,
1730 LPWSTR pDeviceID,
1731 DWORD ulLogConfTag,
1732 DWORD ulLogConfType,
1733 RESOURCEID ResourceID,
1734 DWORD ulResourceTag,
1735 DWORD *pulNextResType,
1736 DWORD *pulNextResTag,
1737 DWORD ulFlags)
1738 {
1739 UNIMPLEMENTED;
1740 return CR_CALL_NOT_IMPLEMENTED;
1741 }
1742
1743
1744 /* Function 50 */
1745 DWORD PNP_GetResDesData(
1746 handle_t hBinding,
1747 LPWSTR pDeviceID,
1748 DWORD ulLogConfTag,
1749 DWORD ulLogConfType,
1750 RESOURCEID ResourceID,
1751 DWORD ulResourceTag,
1752 BYTE *Buffer,
1753 PNP_RPC_BUFFER_SIZE BufferLen,
1754 DWORD ulFlags)
1755 {
1756 UNIMPLEMENTED;
1757 return CR_CALL_NOT_IMPLEMENTED;
1758 }
1759
1760
1761 /* Function 51 */
1762 DWORD PNP_GetResDesDataSize(
1763 handle_t hBinding,
1764 LPWSTR pDeviceID,
1765 DWORD ulLogConfTag,
1766 DWORD ulLogConfType,
1767 RESOURCEID ResourceID,
1768 DWORD ulResourceTag,
1769 DWORD *pulSize,
1770 DWORD ulFlags)
1771 {
1772 UNIMPLEMENTED;
1773 return CR_CALL_NOT_IMPLEMENTED;
1774 }
1775
1776
1777 /* Function 52 */
1778 DWORD PNP_ModifyResDes(
1779 handle_t hBinding,
1780 LPWSTR pDeviceID,
1781 DWORD ulLogConfTag,
1782 DWORD ulLogConfType,
1783 RESOURCEID CurrentResourceID,
1784 RESOURCEID NewResourceID,
1785 DWORD ulResourceTag,
1786 BYTE *ResourceData,
1787 PNP_RPC_BUFFER_SIZE ResourceLen,
1788 DWORD ulFlags)
1789 {
1790 UNIMPLEMENTED;
1791 return CR_CALL_NOT_IMPLEMENTED;
1792 }
1793
1794
1795 /* Function 53 */
1796 DWORD PNP_DetectResourceConflict(
1797 handle_t hBinding,
1798 LPWSTR pDeviceID,
1799 RESOURCEID ResourceID,
1800 BYTE *ResourceData,
1801 PNP_RPC_BUFFER_SIZE ResourceLen,
1802 BOOL *pbConflictDetected,
1803 DWORD ulFlags)
1804 {
1805 UNIMPLEMENTED;
1806 return CR_CALL_NOT_IMPLEMENTED;
1807 }
1808
1809
1810 /* Function 54 */
1811 DWORD PNP_QueryResConfList(
1812 handle_t hBinding,
1813 LPWSTR pDeviceID,
1814 RESOURCEID ResourceID,
1815 BYTE *ResourceData,
1816 PNP_RPC_BUFFER_SIZE ResourceLen,
1817 BYTE *Buffer,
1818 PNP_RPC_BUFFER_SIZE BufferLen,
1819 DWORD ulFlags)
1820 {
1821 UNIMPLEMENTED;
1822 return CR_CALL_NOT_IMPLEMENTED;
1823 }
1824
1825
1826 /* Function 55 */
1827 DWORD PNP_SetHwProf(
1828 handle_t hBinding,
1829 DWORD ulHardwareProfile,
1830 DWORD ulFlags)
1831 {
1832 UNIMPLEMENTED;
1833 return CR_CALL_NOT_IMPLEMENTED;
1834 }
1835
1836
1837 /* Function 56 */
1838 DWORD PNP_QueryArbitratorFreeData(
1839 handle_t hBinding)
1840 {
1841 UNIMPLEMENTED;
1842 return CR_CALL_NOT_IMPLEMENTED;
1843 }
1844
1845
1846 /* Function 57 */
1847 DWORD PNP_QueryArbitratorFreeSize(
1848 handle_t hBinding)
1849 {
1850 UNIMPLEMENTED;
1851 return CR_CALL_NOT_IMPLEMENTED;
1852 }
1853
1854
1855 /* Function 58 */
1856 CONFIGRET
1857 PNP_RunDetection(
1858 handle_t hBinding,
1859 DWORD ulFlags)
1860 {
1861 UNIMPLEMENTED;
1862 return CR_CALL_NOT_IMPLEMENTED;
1863 }
1864
1865
1866 /* Function 59 */
1867 DWORD PNP_RegisterNotification(
1868 handle_t hBinding)
1869 {
1870 UNIMPLEMENTED;
1871 return CR_CALL_NOT_IMPLEMENTED;
1872 }
1873
1874
1875 /* Function 60 */
1876 DWORD PNP_UnregisterNotification(
1877 handle_t hBinding)
1878 {
1879 UNIMPLEMENTED;
1880 return CR_CALL_NOT_IMPLEMENTED;
1881 }
1882
1883
1884 /* Function 61 */
1885 DWORD PNP_GetCustomDevProp(
1886 handle_t hBinding,
1887 LPWSTR pDeviceID,
1888 LPWSTR CustomPropName,
1889 DWORD *pulRegDataType,
1890 BYTE *Buffer,
1891 PNP_RPC_STRING_LEN *pulTransferLen,
1892 PNP_RPC_STRING_LEN *pulLength,
1893 DWORD ulFlags)
1894 {
1895 UNIMPLEMENTED;
1896 return CR_CALL_NOT_IMPLEMENTED;
1897 }
1898
1899
1900 /* Function 62 */
1901 DWORD PNP_GetVersionInternal(
1902 handle_t hBinding,
1903 WORD *pwVersion)
1904 {
1905 UNIMPLEMENTED;
1906 return CR_CALL_NOT_IMPLEMENTED;
1907 }
1908
1909
1910 /* Function 63 */
1911 DWORD PNP_GetBlockedDriverInfo(
1912 handle_t hBinding,
1913 BYTE *Buffer,
1914 PNP_RPC_BUFFER_SIZE *pulTransferLen,
1915 PNP_RPC_BUFFER_SIZE *pulLength,
1916 DWORD ulFlags)
1917 {
1918 UNIMPLEMENTED;
1919 return CR_CALL_NOT_IMPLEMENTED;
1920 }
1921
1922
1923 /* Function 64 */
1924 DWORD PNP_GetServerSideDeviceInstallFlags(
1925 handle_t hBinding,
1926 DWORD *pulSSDIFlags,
1927 DWORD ulFlags)
1928 {
1929 UNIMPLEMENTED;
1930 return CR_CALL_NOT_IMPLEMENTED;
1931 }
1932
1933
1934 /* Function 65 */
1935 DWORD PNP_GetObjectPropKeys(
1936 handle_t hBinding,
1937 LPWSTR ObjectName,
1938 DWORD ObjectType,
1939 LPWSTR PropertyCultureName,
1940 PNP_PROP_COUNT *PropertyCount,
1941 PNP_PROP_COUNT *TransferLen,
1942 DEVPROPKEY *PropertyKeys,
1943 DWORD Flags)
1944 {
1945 UNIMPLEMENTED;
1946 return CR_CALL_NOT_IMPLEMENTED;
1947 }
1948
1949
1950 /* Function 66 */
1951 DWORD PNP_GetObjectProp(
1952 handle_t hBinding,
1953 LPWSTR ObjectName,
1954 DWORD ObjectType,
1955 LPWSTR PropertyCultureName,
1956 const DEVPROPKEY *PropertyKey,
1957 DEVPROPTYPE *PropertyType,
1958 PNP_PROP_SIZE *PropertySize,
1959 PNP_PROP_SIZE *TransferLen,
1960 BYTE *PropertyBuffer,
1961 DWORD Flags)
1962 {
1963 UNIMPLEMENTED;
1964 return CR_CALL_NOT_IMPLEMENTED;
1965 }
1966
1967
1968 /* Function 67 */
1969 DWORD PNP_SetObjectProp(
1970 handle_t hBinding,
1971 LPWSTR ObjectName,
1972 DWORD ObjectType,
1973 LPWSTR PropertyCultureName,
1974 const DEVPROPKEY *PropertyKey,
1975 DEVPROPTYPE PropertyType,
1976 PNP_PROP_SIZE PropertySize,
1977 BYTE *PropertyBuffer,
1978 DWORD Flags)
1979 {
1980 UNIMPLEMENTED;
1981 return CR_CALL_NOT_IMPLEMENTED;
1982 }
1983
1984
1985 /* Function 68 */
1986 DWORD PNP_InstallDevInst(
1987 handle_t hBinding)
1988 {
1989 UNIMPLEMENTED;
1990 return CR_CALL_NOT_IMPLEMENTED;
1991 }
1992
1993
1994 /* Function 69 */
1995 DWORD PNP_ApplyPowerSettings(
1996 handle_t hBinding)
1997 {
1998 UNIMPLEMENTED;
1999 return CR_CALL_NOT_IMPLEMENTED;
2000 }
2001
2002
2003 /* Function 70 */
2004 DWORD PNP_DriverStoreAddDriverPackage(
2005 handle_t hBinding)
2006 {
2007 UNIMPLEMENTED;
2008 return CR_CALL_NOT_IMPLEMENTED;
2009 }
2010
2011
2012 /* Function 71 */
2013 DWORD PNP_DriverStoreDeleteDriverPackage(
2014 handle_t hBinding)
2015 {
2016 UNIMPLEMENTED;
2017 return CR_CALL_NOT_IMPLEMENTED;
2018 }
2019
2020
2021 /* Function 72 */
2022 DWORD PNP_RegisterServiceNotification(
2023 handle_t hBinding)
2024 {
2025 UNIMPLEMENTED;
2026 return CR_CALL_NOT_IMPLEMENTED;
2027 }
2028
2029
2030 /* Function 73 */
2031 DWORD PNP_SetActiveService(
2032 handle_t hBinding)
2033 {
2034 UNIMPLEMENTED;
2035 return CR_CALL_NOT_IMPLEMENTED;
2036 }
2037
2038
2039 /* Function 74 */
2040 DWORD PNP_DeleteServiceDevices(
2041 handle_t hBinding)
2042 {
2043 UNIMPLEMENTED;
2044 return CR_CALL_NOT_IMPLEMENTED;
2045 }
2046
2047
2048 static BOOL
2049 InstallDevice(PCWSTR DeviceInstance, BOOL ShowWizard)
2050 {
2051 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
2052 NTSTATUS Status;
2053 BOOL DeviceInstalled = FALSE;
2054 DWORD BytesWritten;
2055 DWORD Value;
2056 HANDLE hPipe = INVALID_HANDLE_VALUE;
2057 LPVOID Environment = NULL;
2058 PROCESS_INFORMATION ProcessInfo;
2059 STARTUPINFOW StartupInfo;
2060 UUID RandomUuid;
2061
2062 /* The following lengths are constant (see below), they cannot overflow */
2063 WCHAR CommandLine[116];
2064 WCHAR InstallEventName[73];
2065 WCHAR PipeName[74];
2066 WCHAR UuidString[39];
2067
2068 DPRINT("InstallDevice(%S, %d)\n", DeviceInstance, ShowWizard);
2069
2070 ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
2071
2072 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
2073 DeviceInstance);
2074 PlugPlayData.Operation = 0; /* Get status */
2075
2076 /* Get device status */
2077 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
2078 (PVOID)&PlugPlayData,
2079 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
2080 if (!NT_SUCCESS(Status))
2081 {
2082 DPRINT1("NtPlugPlayControl('%S') failed with status 0x%08lx\n", DeviceInstance, Status);
2083 return FALSE;
2084 }
2085
2086 if ((PlugPlayData.DeviceStatus & (DNF_STARTED | DNF_START_FAILED)) != 0)
2087 {
2088 /* Device is already started, or disabled due to some problem. Don't install it */
2089 DPRINT("No need to install '%S'\n", DeviceInstance);
2090 return TRUE;
2091 }
2092
2093 /* Create a random UUID for the named pipe */
2094 UuidCreate(&RandomUuid);
2095 swprintf(UuidString, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
2096 RandomUuid.Data1, RandomUuid.Data2, RandomUuid.Data3,
2097 RandomUuid.Data4[0], RandomUuid.Data4[1], RandomUuid.Data4[2],
2098 RandomUuid.Data4[3], RandomUuid.Data4[4], RandomUuid.Data4[5],
2099 RandomUuid.Data4[6], RandomUuid.Data4[7]);
2100
2101 /* Create the named pipe */
2102 wcscpy(PipeName, L"\\\\.\\pipe\\PNP_Device_Install_Pipe_0.");
2103 wcscat(PipeName, UuidString);
2104 hPipe = CreateNamedPipeW(PipeName, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 512, 512, 0, NULL);
2105
2106 if(hPipe == INVALID_HANDLE_VALUE)
2107 {
2108 DPRINT1("CreateNamedPipeW failed with error %u\n", GetLastError());
2109 goto cleanup;
2110 }
2111
2112 /* Launch rundll32 to call ClientSideInstallW */
2113 wcscpy(CommandLine, L"rundll32.exe newdev.dll,ClientSideInstall ");
2114 wcscat(CommandLine, PipeName);
2115
2116 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
2117 StartupInfo.cb = sizeof(StartupInfo);
2118
2119 if(hUserToken)
2120 {
2121 /* newdev has to run under the environment of the current user */
2122 if(!CreateEnvironmentBlock(&Environment, hUserToken, FALSE))
2123 {
2124 DPRINT1("CreateEnvironmentBlock failed with error %d\n", GetLastError());
2125 goto cleanup;
2126 }
2127
2128 if(!CreateProcessAsUserW(hUserToken, NULL, CommandLine, NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT, Environment, NULL, &StartupInfo, &ProcessInfo))
2129 {
2130 DPRINT1("CreateProcessAsUserW failed with error %u\n", GetLastError());
2131 goto cleanup;
2132 }
2133 }
2134 else
2135 {
2136 /* FIXME: This is probably not correct, I guess newdev should never be run with SYSTEM privileges.
2137
2138 Still, we currently do that in 2nd stage setup and probably Console mode as well, so allow it here.
2139 (ShowWizard is only set to FALSE for these two modes) */
2140 ASSERT(!ShowWizard);
2141
2142 if(!CreateProcessW(NULL, CommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo))
2143 {
2144 DPRINT1("CreateProcessW failed with error %u\n", GetLastError());
2145 goto cleanup;
2146 }
2147 }
2148
2149 /* Wait for the function to connect to our pipe */
2150 if(!ConnectNamedPipe(hPipe, NULL))
2151 {
2152 DPRINT1("ConnectNamedPipe failed with error %u\n", GetLastError());
2153 goto cleanup;
2154 }
2155
2156 /* Pass the data. The following output is partly compatible to Windows XP SP2 (researched using a modified newdev.dll to log this stuff) */
2157 wcscpy(InstallEventName, L"Global\\PNP_Device_Install_Event_0.");
2158 wcscat(InstallEventName, UuidString);
2159
2160 Value = sizeof(InstallEventName);
2161 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
2162 WriteFile(hPipe, InstallEventName, Value, &BytesWritten, NULL);
2163
2164 /* I couldn't figure out what the following value means under WinXP. It's usually 0 in my tests, but was also 5 once.
2165 Therefore the following line is entirely ReactOS-specific. We use the value here to pass the ShowWizard variable. */
2166 WriteFile(hPipe, &ShowWizard, sizeof(ShowWizard), &BytesWritten, NULL);
2167
2168 Value = (wcslen(DeviceInstance) + 1) * sizeof(WCHAR);
2169 WriteFile(hPipe, &Value, sizeof(Value), &BytesWritten, NULL);
2170 WriteFile(hPipe, DeviceInstance, Value, &BytesWritten, NULL);
2171
2172 /* Wait for newdev.dll to finish processing */
2173 WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
2174
2175 /* The following check for success is probably not compatible to Windows, but should do its job */
2176 if(!GetExitCodeProcess(ProcessInfo.hProcess, &Value))
2177 {
2178 DPRINT1("GetExitCodeProcess failed with error %u\n", GetLastError());
2179 goto cleanup;
2180 }
2181
2182 DeviceInstalled = Value;
2183
2184 cleanup:
2185 if(hPipe != INVALID_HANDLE_VALUE)
2186 CloseHandle(hPipe);
2187
2188 if(Environment)
2189 DestroyEnvironmentBlock(Environment);
2190
2191 if(ProcessInfo.hProcess)
2192 CloseHandle(ProcessInfo.hProcess);
2193
2194 if(ProcessInfo.hThread)
2195 CloseHandle(ProcessInfo.hThread);
2196
2197 return DeviceInstalled;
2198 }
2199
2200
2201 static LONG
2202 ReadRegSzKey(
2203 IN HKEY hKey,
2204 IN LPCWSTR pszKey,
2205 OUT LPWSTR* pValue)
2206 {
2207 LONG rc;
2208 DWORD dwType;
2209 DWORD cbData = 0;
2210 LPWSTR Value;
2211
2212 if (!pValue)
2213 return ERROR_INVALID_PARAMETER;
2214
2215 *pValue = NULL;
2216 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
2217 if (rc != ERROR_SUCCESS)
2218 return rc;
2219 if (dwType != REG_SZ)
2220 return ERROR_FILE_NOT_FOUND;
2221 Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
2222 if (!Value)
2223 return ERROR_NOT_ENOUGH_MEMORY;
2224 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
2225 if (rc != ERROR_SUCCESS)
2226 {
2227 HeapFree(GetProcessHeap(), 0, Value);
2228 return rc;
2229 }
2230 /* NULL-terminate the string */
2231 Value[cbData / sizeof(WCHAR)] = '\0';
2232
2233 *pValue = Value;
2234 return ERROR_SUCCESS;
2235 }
2236
2237
2238 static BOOL
2239 SetupIsActive(VOID)
2240 {
2241 HKEY hKey = NULL;
2242 DWORD regType, active, size;
2243 LONG rc;
2244 BOOL ret = FALSE;
2245
2246 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\Setup", 0, KEY_QUERY_VALUE, &hKey);
2247 if (rc != ERROR_SUCCESS)
2248 goto cleanup;
2249
2250 size = sizeof(DWORD);
2251 rc = RegQueryValueExW(hKey, L"SystemSetupInProgress", NULL, &regType, (LPBYTE)&active, &size);
2252 if (rc != ERROR_SUCCESS)
2253 goto cleanup;
2254 if (regType != REG_DWORD || size != sizeof(DWORD))
2255 goto cleanup;
2256
2257 ret = (active != 0);
2258
2259 cleanup:
2260 if (hKey != NULL)
2261 RegCloseKey(hKey);
2262
2263 DPRINT("System setup in progress? %S\n", ret ? L"YES" : L"NO");
2264
2265 return ret;
2266 }
2267
2268
2269 static BOOL
2270 IsConsoleBoot(VOID)
2271 {
2272 HKEY ControlKey = NULL;
2273 LPWSTR SystemStartOptions = NULL;
2274 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
2275 BOOL ConsoleBoot = FALSE;
2276 LONG rc;
2277
2278 rc = RegOpenKeyExW(
2279 HKEY_LOCAL_MACHINE,
2280 L"SYSTEM\\CurrentControlSet\\Control",
2281 0,
2282 KEY_QUERY_VALUE,
2283 &ControlKey);
2284
2285 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
2286 if (rc != ERROR_SUCCESS)
2287 goto cleanup;
2288
2289 /* Check for CMDCONS in SystemStartOptions */
2290 CurrentOption = SystemStartOptions;
2291 while (CurrentOption)
2292 {
2293 NextOption = wcschr(CurrentOption, L' ');
2294 if (NextOption)
2295 *NextOption = L'\0';
2296 if (_wcsicmp(CurrentOption, L"CONSOLE") == 0)
2297 {
2298 DPRINT("Found %S. Switching to console boot\n", CurrentOption);
2299 ConsoleBoot = TRUE;
2300 goto cleanup;
2301 }
2302 CurrentOption = NextOption ? NextOption + 1 : NULL;
2303 }
2304
2305 cleanup:
2306 if (ControlKey != NULL)
2307 RegCloseKey(ControlKey);
2308 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
2309 return ConsoleBoot;
2310 }
2311
2312
2313 /* Loop to install all queued devices installations */
2314 static DWORD WINAPI
2315 DeviceInstallThread(LPVOID lpParameter)
2316 {
2317 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2318 PSLIST_ENTRY ListEntry;
2319 #else
2320 PLIST_ENTRY ListEntry;
2321 #endif
2322 DeviceInstallParams* Params;
2323 BOOL showWizard;
2324
2325 UNREFERENCED_PARAMETER(lpParameter);
2326
2327 WaitForSingleObject(hInstallEvent, INFINITE);
2328
2329 showWizard = !SetupIsActive() && !IsConsoleBoot();
2330
2331 while (TRUE)
2332 {
2333 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2334 ListEntry = InterlockedPopEntrySList(&DeviceInstallListHead);
2335 #else
2336 if ((BOOL)IsListEmpty(&DeviceInstallListHead))
2337 ListEntry = NULL;
2338 else
2339 ListEntry = RemoveHeadList(&DeviceInstallListHead);
2340 #endif
2341 if (ListEntry == NULL)
2342 {
2343 SetEvent(hNoPendingInstalls);
2344 WaitForSingleObject(hDeviceInstallListNotEmpty, INFINITE);
2345 }
2346 else
2347 {
2348 ResetEvent(hNoPendingInstalls);
2349 Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry);
2350 InstallDevice(Params->DeviceIds, showWizard);
2351 }
2352 }
2353
2354 return 0;
2355 }
2356
2357
2358 static DWORD WINAPI
2359 PnpEventThread(LPVOID lpParameter)
2360 {
2361 PPLUGPLAY_EVENT_BLOCK PnpEvent;
2362 ULONG PnpEventSize;
2363 NTSTATUS Status;
2364 RPC_STATUS RpcStatus;
2365
2366 UNREFERENCED_PARAMETER(lpParameter);
2367
2368 PnpEventSize = 0x1000;
2369 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
2370 if (PnpEvent == NULL)
2371 return ERROR_OUTOFMEMORY;
2372
2373 for (;;)
2374 {
2375 DPRINT("Calling NtGetPlugPlayEvent()\n");
2376
2377 /* Wait for the next pnp event */
2378 Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize);
2379
2380 /* Resize the buffer for the PnP event if it's too small. */
2381 if (Status == STATUS_BUFFER_TOO_SMALL)
2382 {
2383 PnpEventSize += 0x400;
2384 HeapFree(GetProcessHeap(), 0, PnpEvent);
2385 PnpEvent = HeapAlloc(GetProcessHeap(), 0, PnpEventSize);
2386 if (PnpEvent == NULL)
2387 return ERROR_OUTOFMEMORY;
2388 continue;
2389 }
2390
2391 if (!NT_SUCCESS(Status))
2392 {
2393 DPRINT("NtGetPlugPlayEvent() failed (Status %lx)\n", Status);
2394 break;
2395 }
2396
2397 /* Process the pnp event */
2398 DPRINT("Received PnP Event\n");
2399 if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ENUMERATED, &RpcStatus))
2400 {
2401 DeviceInstallParams* Params;
2402 DWORD len;
2403 DWORD DeviceIdLength;
2404
2405 DPRINT("Device enumerated: %S\n", PnpEvent->TargetDevice.DeviceIds);
2406
2407 DeviceIdLength = lstrlenW(PnpEvent->TargetDevice.DeviceIds);
2408 if (DeviceIdLength)
2409 {
2410 /* Queue device install (will be dequeued by DeviceInstallThread */
2411 len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR);
2412 Params = HeapAlloc(GetProcessHeap(), 0, len);
2413 if (Params)
2414 {
2415 wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds);
2416 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2417 InterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry);
2418 #else
2419 InsertTailList(&DeviceInstallListHead, &Params->ListEntry);
2420 #endif
2421 SetEvent(hDeviceInstallListNotEmpty);
2422 }
2423 }
2424 }
2425 else if (UuidEqual(&PnpEvent->EventGuid, (UUID*)&GUID_DEVICE_ARRIVAL, &RpcStatus))
2426 {
2427 DPRINT("Device arrival: %S\n", PnpEvent->TargetDevice.DeviceIds);
2428 /* FIXME: ? */
2429 }
2430 else
2431 {
2432 DPRINT1("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n",
2433 PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3,
2434 PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2],
2435 PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5],
2436 PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]);
2437 }
2438
2439 /* Dequeue the current pnp event and signal the next one */
2440 NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0);
2441 }
2442
2443 HeapFree(GetProcessHeap(), 0, PnpEvent);
2444
2445 return ERROR_SUCCESS;
2446 }
2447
2448
2449 static VOID CALLBACK
2450 ServiceMain(DWORD argc, LPTSTR *argv)
2451 {
2452 HANDLE hThread;
2453 DWORD dwThreadId;
2454
2455 UNREFERENCED_PARAMETER(argc);
2456 UNREFERENCED_PARAMETER(argv);
2457
2458 DPRINT("ServiceMain() called\n");
2459
2460 hThread = CreateThread(NULL,
2461 0,
2462 PnpEventThread,
2463 NULL,
2464 0,
2465 &dwThreadId);
2466 if (hThread != NULL)
2467 CloseHandle(hThread);
2468
2469 hThread = CreateThread(NULL,
2470 0,
2471 RpcServerThread,
2472 NULL,
2473 0,
2474 &dwThreadId);
2475 if (hThread != NULL)
2476 CloseHandle(hThread);
2477
2478 hThread = CreateThread(NULL,
2479 0,
2480 DeviceInstallThread,
2481 NULL,
2482 0,
2483 &dwThreadId);
2484 if (hThread != NULL)
2485 CloseHandle(hThread);
2486
2487 DPRINT("ServiceMain() done\n");
2488 }
2489
2490
2491 int
2492 wmain(int argc, WCHAR *argv[])
2493 {
2494 BOOLEAN OldValue;
2495 DWORD dwError;
2496
2497 UNREFERENCED_PARAMETER(argc);
2498 UNREFERENCED_PARAMETER(argv);
2499
2500 DPRINT("Umpnpmgr: main() started\n");
2501
2502 /* We need this privilege for using CreateProcessAsUserW */
2503 RtlAdjustPrivilege(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE, TRUE, FALSE, &OldValue);
2504
2505 hInstallEvent = CreateEvent(NULL, TRUE, SetupIsActive()/*FALSE*/, NULL);
2506 if (hInstallEvent == NULL)
2507 {
2508 dwError = GetLastError();
2509 DPRINT1("Could not create the Install Event! (Error %lu)\n", dwError);
2510 return dwError;
2511 }
2512
2513 hDeviceInstallListNotEmpty = CreateEvent(NULL, FALSE, FALSE, NULL);
2514 if (hDeviceInstallListNotEmpty == NULL)
2515 {
2516 dwError = GetLastError();
2517 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
2518 return dwError;
2519 }
2520
2521 hNoPendingInstalls = CreateEventW(NULL,
2522 TRUE,
2523 FALSE,
2524 L"Global\\PnP_No_Pending_Install_Events");
2525 if (hNoPendingInstalls == NULL)
2526 {
2527 dwError = GetLastError();
2528 DPRINT1("Could not create the Event! (Error %lu)\n", dwError);
2529 return dwError;
2530 }
2531
2532 #ifdef HAVE_SLIST_ENTRY_IMPLEMENTED
2533 InitializeSListHead(&DeviceInstallListHead);
2534 #else
2535 InitializeListHead(&DeviceInstallListHead);
2536 #endif
2537
2538 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2539 L"System\\CurrentControlSet\\Enum",
2540 0,
2541 KEY_ALL_ACCESS,
2542 &hEnumKey);
2543 if (dwError != ERROR_SUCCESS)
2544 {
2545 DPRINT1("Could not open the Enum Key! (Error %lu)\n", dwError);
2546 return dwError;
2547 }
2548
2549 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2550 L"System\\CurrentControlSet\\Control\\Class",
2551 0,
2552 KEY_ALL_ACCESS,
2553 &hClassKey);
2554 if (dwError != ERROR_SUCCESS)
2555 {
2556 DPRINT1("Could not open the Class Key! (Error %lu)\n", dwError);
2557 return dwError;
2558 }
2559
2560 StartServiceCtrlDispatcher(ServiceTable);
2561
2562 DPRINT("Umpnpmgr: main() done\n");
2563
2564 ExitThread(0);
2565
2566 return 0;
2567 }
2568
2569 /* EOF */