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