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