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