[UMPNPMGR][USETUP] Use PlugPlayControlStartDevice in usetup and umpnpmgr
[reactos.git] / base / services / umpnpmgr / rpcserver.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: base/services/umpnpmgr/rpcserver.c
23 * PURPOSE: RPC server
24 * PROGRAMMER: Eric Kohl (eric.kohl@reactos.org)
25 * Hervé Poussineau (hpoussin@reactos.org)
26 * Colin Finck (colin@reactos.org)
27 */
28
29 /* INCLUDES *****************************************************************/
30
31 #include "precomp.h"
32
33 #define NDEBUG
34 #include <debug.h>
35
36
37 /* GLOBALS ******************************************************************/
38
39 static WCHAR szRootDeviceInstanceID[] = L"HTREE\\ROOT\\0";
40
41
42 /* FUNCTIONS *****************************************************************/
43
44 DWORD WINAPI
45 RpcServerThread(LPVOID lpParameter)
46 {
47 RPC_STATUS Status;
48 BOOLEAN RegisteredProtSeq = FALSE;
49
50 UNREFERENCED_PARAMETER(lpParameter);
51
52 DPRINT("RpcServerThread() called\n");
53
54 #if 0
55 /* 2k/XP/2k3-compatible protocol sequence/endpoint */
56 Status = RpcServerUseProtseqEpW(L"ncacn_np",
57 20,
58 L"\\pipe\\ntsvcs",
59 NULL); // Security descriptor
60 if (Status == RPC_S_OK)
61 RegisteredProtSeq = TRUE;
62 else
63 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
64 #endif
65
66 /* Vista/7-compatible protocol sequence/endpoint */
67 Status = RpcServerUseProtseqEpW(L"ncacn_np",
68 20,
69 L"\\pipe\\plugplay",
70 NULL); // Security descriptor
71 if (Status == RPC_S_OK)
72 RegisteredProtSeq = TRUE;
73 else
74 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
75
76 /* Make sure there's a usable endpoint */
77 if (RegisteredProtSeq == FALSE)
78 return 0;
79
80 Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec,
81 NULL,
82 NULL);
83 if (Status != RPC_S_OK)
84 {
85 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
86 return 0;
87 }
88
89 Status = RpcServerListen(1,
90 20,
91 FALSE);
92 if (Status != RPC_S_OK)
93 {
94 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
95 return 0;
96 }
97
98 /* ROS HACK (this should never happen...) */
99 DPRINT1("*** Other devices won't be installed correctly. If something\n");
100 DPRINT1("*** doesn't work, try to reboot to get a new chance.\n");
101
102 DPRINT("RpcServerThread() done\n");
103
104 return 0;
105 }
106
107
108 void __RPC_FAR * __RPC_USER midl_user_allocate(SIZE_T len)
109 {
110 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
111 }
112
113
114 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
115 {
116 HeapFree(GetProcessHeap(), 0, ptr);
117 }
118
119
120 static CONFIGRET WINAPI
121 NtStatusToCrError(NTSTATUS Status)
122 {
123 switch (Status)
124 {
125 case STATUS_NOT_IMPLEMENTED:
126 return CR_CALL_NOT_IMPLEMENTED;
127
128 case STATUS_INVALID_PARAMETER:
129 return CR_INVALID_DATA;
130
131 case STATUS_NO_SUCH_DEVICE:
132 return CR_NO_SUCH_DEVINST;
133
134 case STATUS_ACCESS_DENIED:
135 return CR_ACCESS_DENIED;
136
137 case STATUS_BUFFER_TOO_SMALL:
138 return CR_BUFFER_SMALL;
139
140 case STATUS_OBJECT_NAME_NOT_FOUND:
141 return CR_NO_SUCH_VALUE;
142
143 default:
144 return CR_FAILURE;
145 }
146 }
147
148
149 static VOID
150 SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID,
151 OUT LPWSTR pszEnumerator,
152 OUT LPWSTR pszDevice,
153 OUT LPWSTR pszInstance)
154 {
155 WCHAR szLocalDeviceInstanceID[MAX_DEVICE_ID_LEN];
156 LPWSTR lpEnumerator = NULL;
157 LPWSTR lpDevice = NULL;
158 LPWSTR lpInstance = NULL;
159 LPWSTR ptr;
160
161 wcscpy(szLocalDeviceInstanceID, pszDeviceInstanceID);
162
163 *pszEnumerator = 0;
164 *pszDevice = 0;
165 *pszInstance = 0;
166
167 lpEnumerator = szLocalDeviceInstanceID;
168
169 ptr = wcschr(lpEnumerator, L'\\');
170 if (ptr != NULL)
171 {
172 *ptr = 0;
173 lpDevice = ++ptr;
174
175 ptr = wcschr(lpDevice, L'\\');
176 if (ptr != NULL)
177 {
178 *ptr = 0;
179 lpInstance = ++ptr;
180 }
181 }
182
183 if (lpEnumerator != NULL)
184 wcscpy(pszEnumerator, lpEnumerator);
185
186 if (lpDevice != NULL)
187 wcscpy(pszDevice, lpDevice);
188
189 if (lpInstance != NULL)
190 wcscpy(pszInstance, lpInstance);
191 }
192
193
194 static
195 CONFIGRET
196 ClearDeviceStatus(
197 _In_ LPWSTR pszDeviceID,
198 _In_ DWORD ulStatus,
199 _In_ DWORD ulProblem)
200 {
201 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
202 CONFIGRET ret = CR_SUCCESS;
203 NTSTATUS Status;
204
205 DPRINT1("ClearDeviceStatus(%S 0x%lx 0x%lx)\n",
206 pszDeviceID, ulStatus, ulProblem);
207
208 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
209 pszDeviceID);
210 PlugPlayData.Operation = PNP_CLEAR_DEVICE_STATUS;
211 PlugPlayData.DeviceStatus = ulStatus;
212 PlugPlayData.DeviceProblem = ulProblem;
213
214 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
215 (PVOID)&PlugPlayData,
216 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
217 if (!NT_SUCCESS(Status))
218 ret = NtStatusToCrError(Status);
219
220 return ret;
221 }
222
223
224 static
225 CONFIGRET
226 GetDeviceStatus(
227 _In_ LPWSTR pszDeviceID,
228 _Out_ DWORD *pulStatus,
229 _Out_ DWORD *pulProblem)
230 {
231 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
232 CONFIGRET ret = CR_SUCCESS;
233 NTSTATUS Status;
234
235 DPRINT("GetDeviceStatus(%S %p %p)\n",
236 pszDeviceID, pulStatus, pulProblem);
237
238 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
239 pszDeviceID);
240 PlugPlayData.Operation = PNP_GET_DEVICE_STATUS;
241
242 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
243 (PVOID)&PlugPlayData,
244 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
245 if (NT_SUCCESS(Status))
246 {
247 *pulStatus = PlugPlayData.DeviceStatus;
248 *pulProblem = PlugPlayData.DeviceProblem;
249 }
250 else
251 {
252 ret = NtStatusToCrError(Status);
253 }
254
255 return ret;
256 }
257
258
259 static
260 CONFIGRET
261 SetDeviceStatus(
262 _In_ LPWSTR pszDeviceID,
263 _In_ DWORD ulStatus,
264 _In_ DWORD ulProblem)
265 {
266 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
267 CONFIGRET ret = CR_SUCCESS;
268 NTSTATUS Status;
269
270 DPRINT1("SetDeviceStatus(%S 0x%lx 0x%lx)\n",
271 pszDeviceID, ulStatus, ulProblem);
272
273 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
274 pszDeviceID);
275 PlugPlayData.Operation = PNP_SET_DEVICE_STATUS;
276 PlugPlayData.DeviceStatus = ulStatus;
277 PlugPlayData.DeviceProblem = ulProblem;
278
279 Status = NtPlugPlayControl(PlugPlayControlDeviceStatus,
280 (PVOID)&PlugPlayData,
281 sizeof(PLUGPLAY_CONTROL_STATUS_DATA));
282 if (!NT_SUCCESS(Status))
283 ret = NtStatusToCrError(Status);
284
285 return ret;
286 }
287
288
289 static
290 CONFIGRET
291 DisableDeviceInstance(
292 _In_ LPWSTR pszDeviceInstance,
293 _Inout_opt_ PPNP_VETO_TYPE pVetoType,
294 _Inout_opt_ LPWSTR pszVetoName,
295 _In_ DWORD ulNameLength)
296 {
297 PLUGPLAY_CONTROL_QUERY_REMOVE_DATA QueryRemoveData;
298 CONFIGRET ret = CR_SUCCESS;
299 NTSTATUS Status;
300
301 DPRINT1("DisableDeviceInstance(%S %p %p %lu)\n",
302 pszDeviceInstance, pVetoType, pszVetoName, ulNameLength);
303
304 RtlInitUnicodeString(&QueryRemoveData.DeviceInstance,
305 pszDeviceInstance);
306
307 QueryRemoveData.Flags = 0;
308 QueryRemoveData.VetoType = 0;
309 QueryRemoveData.VetoName = pszVetoName;
310 QueryRemoveData.NameLength = ulNameLength;
311
312 Status = NtPlugPlayControl(PlugPlayControlQueryAndRemoveDevice,
313 &QueryRemoveData,
314 sizeof(PLUGPLAY_CONTROL_QUERY_REMOVE_DATA));
315 if (Status == STATUS_NO_SUCH_DEVICE)
316 {
317 ret = CR_INVALID_DEVNODE;
318 }
319 else if (Status == STATUS_PLUGPLAY_QUERY_VETOED)
320 {
321 if (pVetoType != NULL)
322 *pVetoType = QueryRemoveData.VetoType;
323
324 ret = CR_REMOVE_VETOED;
325 }
326 else if (!NT_SUCCESS(Status))
327 {
328 ret = NtStatusToCrError(Status);
329 }
330
331 return ret;
332 }
333
334
335 static
336 BOOL
337 IsValidDeviceInstanceID(
338 _In_ PWSTR pszDeviceInstanceID)
339 {
340 INT nPartLength[3] = {0, 0, 0};
341 INT nLength = 0, nParts = 0;
342 PWCHAR p;
343
344 DPRINT("IsValidDeviceInstanceID(%S)\n",
345 pszDeviceInstanceID);
346
347 if (pszDeviceInstanceID == NULL)
348 {
349 DPRINT("Device instance ID is NULL!\n");
350 return FALSE;
351 }
352
353 p = pszDeviceInstanceID;
354 while (*p != UNICODE_NULL)
355 {
356 if (*p == L'\\')
357 {
358 nParts++;
359 if (nParts >= 3)
360 {
361 DPRINT("Too many separators: %d\n", nParts);
362 return FALSE;
363 }
364 }
365 else
366 {
367 nPartLength[nParts]++;
368 }
369
370 nLength++;
371 if (nLength >= MAX_DEVICE_ID_LEN)
372 {
373 DPRINT("Too long: %d\n", nLength);
374 return FALSE;
375 }
376
377 p++;
378 }
379
380 if (nParts != 2)
381 {
382 DPRINT("Invalid number of separtors: %d\n", nParts);
383 return FALSE;
384 }
385
386 if ((nPartLength[0] == 0) ||
387 (nPartLength[1] == 0) ||
388 (nPartLength[2] == 0))
389 {
390 DPRINT("Invalid part lengths: %d %d %d\n",
391 nPartLength[0], nPartLength[1], nPartLength[2]);
392 return FALSE;
393 }
394
395 DPRINT("Valid device instance ID!\n");
396
397 return TRUE;
398 }
399
400
401 static
402 BOOL
403 IsRootDeviceInstanceID(
404 _In_ PWSTR pszDeviceInstanceID)
405 {
406 if (_wcsicmp(pszDeviceInstanceID, szRootDeviceInstanceID) == 0)
407 return TRUE;
408
409 return FALSE;
410 }
411
412
413 static
414 CONFIGRET
415 OpenConfigurationKey(
416 _In_ LPCWSTR pszDeviceID,
417 _Out_ PHKEY phKey)
418 {
419 WCHAR szKeyName[MAX_PATH];
420 HKEY hInstanceKey;
421 DWORD dwError;
422
423 /* Build the full device instance key name */
424 wcscpy(szKeyName, L"System\\CurrentControlSet\\Enum\\");
425 wcscat(szKeyName, pszDeviceID);
426
427 /* Open the device instance key */
428 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
429 szKeyName,
430 0,
431 KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY,
432 &hInstanceKey);
433 if (dwError != ERROR_SUCCESS)
434 return CR_INVALID_DEVINST;
435
436 /* Create or open the LogConf key */
437 dwError = RegCreateKeyExW(hInstanceKey,
438 L"LogConf",
439 0,
440 NULL,
441 REG_OPTION_NON_VOLATILE,
442 KEY_ALL_ACCESS,
443 NULL,
444 phKey,
445 NULL);
446
447 /* Close the device instance key */
448 RegCloseKey(hInstanceKey);
449
450 if (dwError != ERROR_SUCCESS)
451 return CR_REGISTRY_ERROR;
452
453 return CR_SUCCESS;
454 }
455
456
457 static
458 CONFIGRET
459 GetConfigurationData(
460 _In_ HKEY hKey,
461 _In_ ULONG ulLogConfType,
462 _Out_ PULONG pulRegDataType,
463 _Out_ PULONG pulDataSize,
464 _Out_ LPBYTE *ppBuffer)
465 {
466 LPCWSTR pszValueName;
467
468 switch (ulLogConfType)
469 {
470 case BOOT_LOG_CONF:
471 pszValueName = L"BootConfig";
472 *pulRegDataType = REG_RESOURCE_LIST;
473 break;
474
475 case ALLOC_LOG_CONF:
476 pszValueName = L"AllocConfig";
477 *pulRegDataType = REG_RESOURCE_LIST;
478 break;
479
480 case FORCED_LOG_CONF:
481 pszValueName = L"ForcedConfig";
482 *pulRegDataType = REG_RESOURCE_LIST;
483 break;
484
485 case FILTERED_LOG_CONF:
486 pszValueName = L"FilteredConfigVector";
487 *pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
488 break;
489
490 case BASIC_LOG_CONF:
491 pszValueName = L"BasicConfigVector";
492 *pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
493 break;
494
495 case OVERRIDE_LOG_CONF:
496 pszValueName = L"OverrideConfigVector";
497 *pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
498 break;
499
500 default:
501 DPRINT1("Unsupported configuration type!\n");
502 return CR_FAILURE;
503 }
504
505 /* Get the configuration data size */
506 if (RegQueryValueExW(hKey,
507 pszValueName,
508 NULL,
509 NULL,
510 NULL,
511 pulDataSize) != ERROR_SUCCESS)
512 {
513 return CR_INVALID_LOG_CONF;
514 }
515
516 /* Allocate the buffer */
517 *ppBuffer = HeapAlloc(GetProcessHeap(), 0, *pulDataSize);
518 if (*ppBuffer == NULL)
519 {
520 return CR_OUT_OF_MEMORY;
521 }
522
523 /* Retrieve the configuration data */
524 if (RegQueryValueExW(hKey,
525 pszValueName,
526 NULL,
527 NULL,
528 (LPBYTE)*ppBuffer,
529 pulDataSize) != ERROR_SUCCESS)
530 {
531 return CR_INVALID_LOG_CONF;
532 }
533
534 return CR_SUCCESS;
535 }
536
537
538 /* PUBLIC FUNCTIONS **********************************************************/
539
540 /* Function 0 */
541 DWORD
542 WINAPI
543 PNP_Disconnect(
544 handle_t hBinding)
545 {
546 UNREFERENCED_PARAMETER(hBinding);
547 return CR_SUCCESS;
548 }
549
550
551 /* Function 1 */
552 DWORD
553 WINAPI
554 PNP_Connect(
555 handle_t hBinding)
556 {
557 UNREFERENCED_PARAMETER(hBinding);
558 return CR_SUCCESS;
559 }
560
561
562 /* Function 2 */
563 DWORD
564 WINAPI
565 PNP_GetVersion(
566 handle_t hBinding,
567 WORD *pVersion)
568 {
569 UNREFERENCED_PARAMETER(hBinding);
570
571 DPRINT("PNP_GetVersion(%p %p)\n",
572 hBinding, pVersion);
573
574 *pVersion = 0x0400;
575
576 return CR_SUCCESS;
577 }
578
579
580 /* Function 3 */
581 DWORD
582 WINAPI
583 PNP_GetGlobalState(
584 handle_t hBinding,
585 DWORD *pulState,
586 DWORD ulFlags)
587 {
588 UNREFERENCED_PARAMETER(hBinding);
589 UNREFERENCED_PARAMETER(ulFlags);
590
591 DPRINT("PNP_GetGlobalState(%p %p 0x%08lx)\n",
592 hBinding, pulState, ulFlags);
593
594 *pulState = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE;
595
596 return CR_SUCCESS;
597 }
598
599
600 /* Function 4 */
601 DWORD
602 WINAPI
603 PNP_InitDetection(
604 handle_t hBinding)
605 {
606 UNREFERENCED_PARAMETER(hBinding);
607
608 DPRINT("PNP_InitDetection(%p)\n",
609 hBinding);
610
611 return CR_SUCCESS;
612 }
613
614
615 /* Function 5 */
616 DWORD
617 WINAPI
618 PNP_ReportLogOn(
619 handle_t hBinding,
620 BOOL Admin,
621 DWORD ProcessId)
622 {
623 DWORD ReturnValue = CR_FAILURE;
624 HANDLE hProcess;
625
626 UNREFERENCED_PARAMETER(hBinding);
627 UNREFERENCED_PARAMETER(Admin);
628
629 DPRINT("PNP_ReportLogOn(%p %u, %u)\n",
630 hBinding, Admin, ProcessId);
631
632 /* Get the users token */
633 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId);
634
635 if (!hProcess)
636 {
637 DPRINT1("OpenProcess failed with error %u\n", GetLastError());
638 goto cleanup;
639 }
640
641 if (hUserToken)
642 {
643 CloseHandle(hUserToken);
644 hUserToken = NULL;
645 }
646
647 if (!OpenProcessToken(hProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY, &hUserToken))
648 {
649 DPRINT1("OpenProcessToken failed with error %u\n", GetLastError());
650 goto cleanup;
651 }
652
653 /* Trigger the installer thread */
654 if (hInstallEvent)
655 SetEvent(hInstallEvent);
656
657 ReturnValue = CR_SUCCESS;
658
659 cleanup:
660 if (hProcess)
661 CloseHandle(hProcess);
662
663 return ReturnValue;
664 }
665
666
667 /* Function 6 */
668 DWORD
669 WINAPI
670 PNP_ValidateDeviceInstance(
671 handle_t hBinding,
672 LPWSTR pDeviceID,
673 DWORD ulFlags)
674 {
675 CONFIGRET ret = CR_SUCCESS;
676 HKEY hDeviceKey = NULL;
677
678 UNREFERENCED_PARAMETER(hBinding);
679 UNREFERENCED_PARAMETER(ulFlags);
680
681 DPRINT("PNP_ValidateDeviceInstance(%p %S 0x%08lx)\n",
682 hBinding, pDeviceID, ulFlags);
683
684 if (!IsValidDeviceInstanceID(pDeviceID))
685 return CR_INVALID_DEVINST;
686
687 if (RegOpenKeyExW(hEnumKey,
688 pDeviceID,
689 0,
690 KEY_READ,
691 &hDeviceKey))
692 {
693 DPRINT("Could not open the Device Key!\n");
694 ret = CR_NO_SUCH_DEVNODE;
695 goto Done;
696 }
697
698 /* FIXME: add more tests */
699
700 Done:
701 if (hDeviceKey != NULL)
702 RegCloseKey(hDeviceKey);
703
704 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret);
705
706 return ret;
707 }
708
709
710 /* Function 7 */
711 DWORD
712 WINAPI
713 PNP_GetRootDeviceInstance(
714 handle_t hBinding,
715 LPWSTR pDeviceID,
716 PNP_RPC_STRING_LEN ulLength)
717 {
718 CONFIGRET ret = CR_SUCCESS;
719
720 UNREFERENCED_PARAMETER(hBinding);
721
722 DPRINT("PNP_GetRootDeviceInstance(%p %S %lu)\n",
723 hBinding, pDeviceID, ulLength);
724
725 if (!pDeviceID)
726 {
727 ret = CR_INVALID_POINTER;
728 goto Done;
729 }
730
731 if (ulLength < lstrlenW(szRootDeviceInstanceID) + 1)
732 {
733 ret = CR_BUFFER_SMALL;
734 goto Done;
735 }
736
737 lstrcpyW(pDeviceID,
738 szRootDeviceInstanceID);
739
740 Done:
741 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret);
742
743 return ret;
744 }
745
746
747 /* Function 8 */
748 DWORD
749 WINAPI
750 PNP_GetRelatedDeviceInstance(
751 handle_t hBinding,
752 DWORD ulRelationship,
753 LPWSTR pDeviceID,
754 LPWSTR pRelatedDeviceId,
755 PNP_RPC_STRING_LEN *pulLength,
756 DWORD ulFlags)
757 {
758 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData;
759 CONFIGRET ret = CR_SUCCESS;
760 NTSTATUS Status;
761
762 UNREFERENCED_PARAMETER(hBinding);
763 UNREFERENCED_PARAMETER(ulFlags);
764
765 DPRINT("PNP_GetRelatedDeviceInstance(%p %lu %S %p %p 0x%lx)\n",
766 hBinding, ulRelationship, pDeviceID, pRelatedDeviceId,
767 pulLength, ulFlags);
768
769 if (!IsValidDeviceInstanceID(pDeviceID))
770 return CR_INVALID_DEVINST;
771
772 RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance,
773 pDeviceID);
774
775 PlugPlayData.Relation = ulRelationship;
776
777 PlugPlayData.RelatedDeviceInstanceLength = *pulLength;
778 PlugPlayData.RelatedDeviceInstance = pRelatedDeviceId;
779
780 Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice,
781 (PVOID)&PlugPlayData,
782 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA));
783 if (!NT_SUCCESS(Status))
784 {
785 ret = NtStatusToCrError(Status);
786 }
787
788 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret);
789 if (ret == CR_SUCCESS)
790 {
791 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance);
792 }
793
794 return ret;
795 }
796
797
798 /* Function 9 */
799 DWORD
800 WINAPI
801 PNP_EnumerateSubKeys(
802 handle_t hBinding,
803 DWORD ulBranch,
804 DWORD ulIndex,
805 LPWSTR Buffer,
806 PNP_RPC_STRING_LEN ulLength,
807 PNP_RPC_STRING_LEN *pulRequiredLen,
808 DWORD ulFlags)
809 {
810 CONFIGRET ret = CR_SUCCESS;
811 HKEY hKey;
812 DWORD dwError;
813
814 UNREFERENCED_PARAMETER(hBinding);
815 UNREFERENCED_PARAMETER(ulFlags);
816
817 DPRINT("PNP_EnumerateSubKeys(%p %lu %lu %p %lu %p 0x%08lx)\n",
818 hBinding, ulBranch, ulIndex, Buffer, ulLength,
819 pulRequiredLen, ulFlags);
820
821 switch (ulBranch)
822 {
823 case PNP_ENUMERATOR_SUBKEYS:
824 hKey = hEnumKey;
825 break;
826
827 case PNP_CLASS_SUBKEYS:
828 hKey = hClassKey;
829 break;
830
831 default:
832 return CR_FAILURE;
833 }
834
835 *pulRequiredLen = ulLength;
836 dwError = RegEnumKeyExW(hKey,
837 ulIndex,
838 Buffer,
839 pulRequiredLen,
840 NULL,
841 NULL,
842 NULL,
843 NULL);
844 if (dwError != ERROR_SUCCESS)
845 {
846 ret = (dwError == ERROR_NO_MORE_ITEMS) ? CR_NO_SUCH_VALUE : CR_FAILURE;
847 }
848 else
849 {
850 (*pulRequiredLen)++;
851 }
852
853 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret);
854
855 return ret;
856 }
857
858
859 static
860 CONFIGRET
861 GetRelationsInstanceList(
862 _In_ PWSTR pszDevice,
863 _In_ DWORD ulFlags,
864 _Inout_ PWSTR pszBuffer,
865 _Inout_ PDWORD pulLength)
866 {
867 PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData;
868 NTSTATUS Status;
869 CONFIGRET ret = CR_SUCCESS;
870
871 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
872 pszDevice);
873
874 if (ulFlags & CM_GETIDLIST_FILTER_BUSRELATIONS)
875 {
876 PlugPlayData.Relations = 3;
877 }
878 else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS)
879 {
880 PlugPlayData.Relations = 2;
881 }
882 else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS)
883 {
884 PlugPlayData.Relations = 1;
885 }
886 else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS)
887 {
888 PlugPlayData.Relations = 0;
889 }
890
891 PlugPlayData.BufferSize = *pulLength * sizeof(WCHAR);
892 PlugPlayData.Buffer = pszBuffer;
893
894 Status = NtPlugPlayControl(PlugPlayControlQueryDeviceRelations,
895 (PVOID)&PlugPlayData,
896 sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA));
897 if (NT_SUCCESS(Status))
898 {
899 *pulLength = PlugPlayData.BufferSize / sizeof(WCHAR);
900 }
901 else
902 {
903 ret = NtStatusToCrError(Status);
904 }
905
906 return ret;
907 }
908
909
910 static
911 CONFIGRET
912 GetServiceInstanceList(
913 _In_ PWSTR pszService,
914 _Inout_ PWSTR pszBuffer,
915 _Inout_ PDWORD pulLength)
916 {
917 WCHAR szPathBuffer[512];
918 WCHAR szName[16];
919 HKEY hServicesKey = NULL, hServiceKey = NULL, hEnumKey = NULL;
920 DWORD dwValues, dwSize, dwIndex, dwUsedLength, dwPathLength;
921 DWORD dwError;
922 PWSTR pPtr;
923 CONFIGRET ret = CR_SUCCESS;
924
925 /* Open the device key */
926 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
927 L"System\\CurrentControlSet\\Services",
928 0,
929 KEY_READ,
930 &hServicesKey);
931 if (dwError != ERROR_SUCCESS)
932 {
933 DPRINT("Failed to open the services key (Error %lu)\n", dwError);
934 return CR_REGISTRY_ERROR;
935 }
936
937 dwError = RegOpenKeyExW(hServicesKey,
938 pszService,
939 0,
940 KEY_READ,
941 &hServiceKey);
942 if (dwError != ERROR_SUCCESS)
943 {
944 DPRINT("Failed to open the service key (Error %lu)\n", dwError);
945 ret = CR_REGISTRY_ERROR;
946 goto Done;
947 }
948
949 dwError = RegOpenKeyExW(hServiceKey,
950 L"Enum",
951 0,
952 KEY_READ,
953 &hEnumKey);
954 if (dwError != ERROR_SUCCESS)
955 {
956 DPRINT("Failed to open the service enum key (Error %lu)\n", dwError);
957 ret = CR_REGISTRY_ERROR;
958 goto Done;
959 }
960
961 /* Retrieve the number of device instances */
962 dwSize = sizeof(DWORD);
963 dwError = RegQueryValueExW(hEnumKey,
964 L"Count",
965 NULL,
966 NULL,
967 (LPBYTE)&dwValues,
968 &dwSize);
969 if (dwError != ERROR_SUCCESS)
970 {
971 DPRINT("RegQueryValueExW failed (Error %lu)\n", dwError);
972 dwValues = 1;
973 }
974
975 DPRINT("dwValues %lu\n", dwValues);
976
977 dwUsedLength = 0;
978 pPtr = pszBuffer;
979
980 for (dwIndex = 0; dwIndex < dwValues; dwIndex++)
981 {
982 wsprintf(szName, L"%lu", dwIndex);
983
984 dwSize = sizeof(szPathBuffer);
985 dwError = RegQueryValueExW(hEnumKey,
986 szName,
987 NULL,
988 NULL,
989 (LPBYTE)szPathBuffer,
990 &dwSize);
991 if (dwError != ERROR_SUCCESS)
992 break;
993
994 DPRINT("Path: %S\n", szPathBuffer);
995
996 dwPathLength = wcslen(szPathBuffer) + 1;
997 if (dwUsedLength + dwPathLength + 1 > *pulLength)
998 {
999 ret = CR_BUFFER_SMALL;
1000 break;
1001 }
1002
1003 wcscpy(pPtr, szPathBuffer);
1004 dwUsedLength += dwPathLength;
1005 pPtr += dwPathLength;
1006
1007 *pPtr = UNICODE_NULL;
1008 }
1009
1010 Done:
1011 if (hEnumKey != NULL)
1012 RegCloseKey(hEnumKey);
1013
1014 if (hServiceKey != NULL)
1015 RegCloseKey(hServiceKey);
1016
1017 if (hServicesKey != NULL)
1018 RegCloseKey(hServicesKey);
1019
1020 if (ret == CR_SUCCESS)
1021 *pulLength = dwUsedLength + 1;
1022 else
1023 *pulLength = 0;
1024
1025 return ret;
1026 }
1027
1028
1029 static
1030 CONFIGRET
1031 GetDeviceInstanceList(
1032 _In_ PWSTR pszDevice,
1033 _Inout_ PWSTR pszBuffer,
1034 _Inout_ PDWORD pulLength)
1035 {
1036 WCHAR szInstanceBuffer[MAX_DEVICE_ID_LEN];
1037 WCHAR szPathBuffer[512];
1038 HKEY hDeviceKey;
1039 DWORD dwInstanceLength, dwPathLength, dwUsedLength;
1040 DWORD dwIndex, dwError;
1041 PWSTR pPtr;
1042 CONFIGRET ret = CR_SUCCESS;
1043
1044 /* Open the device key */
1045 dwError = RegOpenKeyExW(hEnumKey,
1046 pszDevice,
1047 0,
1048 KEY_ENUMERATE_SUB_KEYS,
1049 &hDeviceKey);
1050 if (dwError != ERROR_SUCCESS)
1051 {
1052 DPRINT("Failed to open the device key (Error %lu)\n", dwError);
1053 return CR_REGISTRY_ERROR;
1054 }
1055
1056 dwUsedLength = 0;
1057 pPtr = pszBuffer;
1058
1059 for (dwIndex = 0; ; dwIndex++)
1060 {
1061 dwInstanceLength = MAX_DEVICE_ID_LEN;
1062 dwError = RegEnumKeyExW(hDeviceKey,
1063 dwIndex,
1064 szInstanceBuffer,
1065 &dwInstanceLength,
1066 NULL,
1067 NULL,
1068 NULL,
1069 NULL);
1070 if (dwError != ERROR_SUCCESS)
1071 break;
1072
1073 wsprintf(szPathBuffer, L"%s\\%s", pszDevice, szInstanceBuffer);
1074 DPRINT("Path: %S\n", szPathBuffer);
1075
1076 dwPathLength = wcslen(szPathBuffer) + 1;
1077 if (dwUsedLength + dwPathLength + 1 > *pulLength)
1078 {
1079 ret = CR_BUFFER_SMALL;
1080 break;
1081 }
1082
1083 wcscpy(pPtr, szPathBuffer);
1084 dwUsedLength += dwPathLength;
1085 pPtr += dwPathLength;
1086
1087 *pPtr = UNICODE_NULL;
1088 }
1089
1090 RegCloseKey(hDeviceKey);
1091
1092 if (ret == CR_SUCCESS)
1093 *pulLength = dwUsedLength + 1;
1094 else
1095 *pulLength = 0;
1096
1097 return ret;
1098 }
1099
1100
1101 CONFIGRET
1102 GetEnumeratorInstanceList(
1103 _In_ PWSTR pszEnumerator,
1104 _Inout_ PWSTR pszBuffer,
1105 _Inout_ PDWORD pulLength)
1106 {
1107 WCHAR szDeviceBuffer[MAX_DEVICE_ID_LEN];
1108 WCHAR szPathBuffer[512];
1109 HKEY hEnumeratorKey;
1110 PWSTR pPtr;
1111 DWORD dwIndex, dwDeviceLength, dwUsedLength, dwRemainingLength, dwPathLength;
1112 DWORD dwError;
1113 CONFIGRET ret = CR_SUCCESS;
1114
1115 /* Open the enumerator key */
1116 dwError = RegOpenKeyExW(hEnumKey,
1117 pszEnumerator,
1118 0,
1119 KEY_ENUMERATE_SUB_KEYS,
1120 &hEnumeratorKey);
1121 if (dwError != ERROR_SUCCESS)
1122 {
1123 DPRINT("Failed to open the enumerator key (Error %lu)\n", dwError);
1124 return CR_REGISTRY_ERROR;
1125 }
1126
1127 dwUsedLength = 0;
1128 dwRemainingLength = *pulLength;
1129 pPtr = pszBuffer;
1130
1131 for (dwIndex = 0; ; dwIndex++)
1132 {
1133 dwDeviceLength = MAX_DEVICE_ID_LEN;
1134 dwError = RegEnumKeyExW(hEnumeratorKey,
1135 dwIndex,
1136 szDeviceBuffer,
1137 &dwDeviceLength,
1138 NULL,
1139 NULL,
1140 NULL,
1141 NULL);
1142 if (dwError != ERROR_SUCCESS)
1143 break;
1144
1145 wsprintf(szPathBuffer, L"%s\\%s", pszEnumerator, szDeviceBuffer);
1146 DPRINT("Path: %S\n", szPathBuffer);
1147
1148 dwPathLength = dwRemainingLength;
1149 ret = GetDeviceInstanceList(szPathBuffer,
1150 pPtr,
1151 &dwPathLength);
1152 if (ret != CR_SUCCESS)
1153 break;
1154
1155 dwUsedLength += dwPathLength - 1;
1156 dwRemainingLength += dwPathLength - 1;
1157 pPtr += dwPathLength - 1;
1158 }
1159
1160 RegCloseKey(hEnumeratorKey);
1161
1162 if (ret == CR_SUCCESS)
1163 *pulLength = dwUsedLength + 1;
1164 else
1165 *pulLength = 0;
1166
1167 return ret;
1168 }
1169
1170
1171 static
1172 CONFIGRET
1173 GetAllInstanceList(
1174 _Inout_ PWSTR pszBuffer,
1175 _Inout_ PDWORD pulLength)
1176 {
1177 WCHAR szEnumeratorBuffer[MAX_DEVICE_ID_LEN];
1178 PWSTR pPtr;
1179 DWORD dwIndex, dwEnumeratorLength, dwUsedLength, dwRemainingLength, dwPathLength;
1180 DWORD dwError;
1181 CONFIGRET ret = CR_SUCCESS;
1182
1183 dwUsedLength = 0;
1184 dwRemainingLength = *pulLength;
1185 pPtr = pszBuffer;
1186
1187 for (dwIndex = 0; ; dwIndex++)
1188 {
1189 dwEnumeratorLength = MAX_DEVICE_ID_LEN;
1190 dwError = RegEnumKeyExW(hEnumKey,
1191 dwIndex,
1192 szEnumeratorBuffer,
1193 &dwEnumeratorLength,
1194 NULL, NULL, NULL, NULL);
1195 if (dwError != ERROR_SUCCESS)
1196 break;
1197
1198 dwPathLength = dwRemainingLength;
1199 ret = GetEnumeratorInstanceList(szEnumeratorBuffer,
1200 pPtr,
1201 &dwPathLength);
1202 if (ret != CR_SUCCESS)
1203 break;
1204
1205 dwUsedLength += dwPathLength - 1;
1206 dwRemainingLength += dwPathLength - 1;
1207 pPtr += dwPathLength - 1;
1208 }
1209
1210 if (ret == CR_SUCCESS)
1211 *pulLength = dwUsedLength + 1;
1212 else
1213 *pulLength = 0;
1214
1215 return ret;
1216 }
1217
1218
1219 /* Function 10 */
1220 DWORD
1221 WINAPI
1222 PNP_GetDeviceList(
1223 handle_t hBinding,
1224 LPWSTR pszFilter,
1225 LPWSTR Buffer,
1226 PNP_RPC_STRING_LEN *pulLength,
1227 DWORD ulFlags)
1228 {
1229 WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
1230 WCHAR szDevice[MAX_DEVICE_ID_LEN];
1231 WCHAR szInstance[MAX_DEVICE_ID_LEN];
1232 CONFIGRET ret = CR_SUCCESS;
1233
1234 DPRINT("PNP_GetDeviceList(%p %S %p %p 0x%08lx)\n",
1235 hBinding, pszFilter, Buffer, pulLength, ulFlags);
1236
1237 if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
1238 return CR_INVALID_FLAG;
1239
1240 if (pulLength == NULL)
1241 return CR_INVALID_POINTER;
1242
1243 if ((ulFlags != CM_GETIDLIST_FILTER_NONE) &&
1244 (pszFilter == NULL))
1245 return CR_INVALID_POINTER;
1246
1247 if (ulFlags &
1248 (CM_GETIDLIST_FILTER_BUSRELATIONS |
1249 CM_GETIDLIST_FILTER_POWERRELATIONS |
1250 CM_GETIDLIST_FILTER_REMOVALRELATIONS |
1251 CM_GETIDLIST_FILTER_EJECTRELATIONS))
1252 {
1253 ret = GetRelationsInstanceList(pszFilter,
1254 ulFlags,
1255 Buffer,
1256 pulLength);
1257 }
1258 else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE)
1259 {
1260 ret = GetServiceInstanceList(pszFilter,
1261 Buffer,
1262 pulLength);
1263 }
1264 else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR)
1265 {
1266 SplitDeviceInstanceID(pszFilter,
1267 szEnumerator,
1268 szDevice,
1269 szInstance);
1270
1271 if (*szEnumerator != UNICODE_NULL && *szDevice != UNICODE_NULL)
1272 {
1273 ret = GetDeviceInstanceList(pszFilter,
1274 Buffer,
1275 pulLength);
1276 }
1277 else
1278 {
1279 ret = GetEnumeratorInstanceList(pszFilter,
1280 Buffer,
1281 pulLength);
1282 }
1283 }
1284 else /* CM_GETIDLIST_FILTER_NONE */
1285 {
1286 ret = GetAllInstanceList(Buffer,
1287 pulLength);
1288 }
1289
1290 return ret;
1291 }
1292
1293
1294 static
1295 CONFIGRET
1296 GetRelationsInstanceListSize(
1297 _In_ PWSTR pszDevice,
1298 _In_ DWORD ulFlags,
1299 _Inout_ PDWORD pulLength)
1300 {
1301 PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData;
1302 NTSTATUS Status;
1303 CONFIGRET ret = CR_SUCCESS;
1304
1305 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1306 pszDevice);
1307
1308 if (ulFlags & CM_GETIDLIST_FILTER_BUSRELATIONS)
1309 {
1310 PlugPlayData.Relations = 3;
1311 }
1312 else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS)
1313 {
1314 PlugPlayData.Relations = 2;
1315 }
1316 else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS)
1317 {
1318 PlugPlayData.Relations = 1;
1319 }
1320 else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS)
1321 {
1322 PlugPlayData.Relations = 0;
1323 }
1324
1325 PlugPlayData.BufferSize = 0;
1326 PlugPlayData.Buffer = NULL;
1327
1328 Status = NtPlugPlayControl(PlugPlayControlQueryDeviceRelations,
1329 (PVOID)&PlugPlayData,
1330 sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA));
1331 if (NT_SUCCESS(Status))
1332 {
1333 *pulLength = PlugPlayData.BufferSize / sizeof(WCHAR);
1334 }
1335 else
1336 {
1337 ret = NtStatusToCrError(Status);
1338 }
1339
1340 return ret;
1341 }
1342
1343
1344 static
1345 CONFIGRET
1346 GetServiceInstanceListSize(
1347 _In_ PWSTR pszService,
1348 _Out_ PDWORD pulLength)
1349 {
1350 HKEY hServicesKey = NULL, hServiceKey = NULL, hEnumKey = NULL;
1351 DWORD dwValues, dwMaxValueLength, dwSize;
1352 DWORD dwError;
1353 CONFIGRET ret = CR_SUCCESS;
1354
1355 /* Open the device key */
1356 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1357 L"System\\CurrentControlSet\\Services",
1358 0,
1359 KEY_READ,
1360 &hServicesKey);
1361 if (dwError != ERROR_SUCCESS)
1362 {
1363 DPRINT("Failed to open the services key (Error %lu)\n", dwError);
1364 return CR_REGISTRY_ERROR;
1365 }
1366
1367 dwError = RegOpenKeyExW(hServicesKey,
1368 pszService,
1369 0,
1370 KEY_READ,
1371 &hServiceKey);
1372 if (dwError != ERROR_SUCCESS)
1373 {
1374 DPRINT("Failed to open the service key (Error %lu)\n", dwError);
1375 ret = CR_REGISTRY_ERROR;
1376 goto Done;
1377 }
1378
1379 dwError = RegOpenKeyExW(hServiceKey,
1380 L"Enum",
1381 0,
1382 KEY_READ,
1383 &hEnumKey);
1384 if (dwError != ERROR_SUCCESS)
1385 {
1386 DPRINT("Failed to open the service enum key (Error %lu)\n", dwError);
1387 ret = CR_REGISTRY_ERROR;
1388 goto Done;
1389 }
1390
1391 /* Retrieve the number of device instances */
1392 dwSize = sizeof(DWORD);
1393 dwError = RegQueryValueExW(hEnumKey,
1394 L"Count",
1395 NULL,
1396 NULL,
1397 (LPBYTE)&dwValues,
1398 &dwSize);
1399 if (dwError != ERROR_SUCCESS)
1400 {
1401 DPRINT("RegQueryValueExW failed (Error %lu)\n", dwError);
1402 dwValues = 1;
1403 }
1404
1405 /* Retrieve the maximum instance name length */
1406 dwError = RegQueryInfoKeyW(hEnumKey,
1407 NULL,
1408 NULL,
1409 NULL,
1410 NULL,
1411 NULL,
1412 NULL,
1413 NULL,
1414 NULL,
1415 &dwMaxValueLength,
1416 NULL,
1417 NULL);
1418 if (dwError != ERROR_SUCCESS)
1419 {
1420 DPRINT("RegQueryInfoKeyW failed (Error %lu)\n", dwError);
1421 dwMaxValueLength = MAX_DEVICE_ID_LEN;
1422 }
1423
1424 DPRINT("dwValues %lu dwMaxValueLength %lu\n", dwValues, dwMaxValueLength / sizeof(WCHAR));
1425
1426 /* Return the largest possible buffer size */
1427 *pulLength = dwValues * dwMaxValueLength / sizeof(WCHAR) + 2;
1428
1429 Done:
1430 if (hEnumKey != NULL)
1431 RegCloseKey(hEnumKey);
1432
1433 if (hServiceKey != NULL)
1434 RegCloseKey(hServiceKey);
1435
1436 if (hServicesKey != NULL)
1437 RegCloseKey(hServicesKey);
1438
1439 return ret;
1440 }
1441
1442
1443 static
1444 CONFIGRET
1445 GetDeviceInstanceListSize(
1446 _In_ LPCWSTR pszDevice,
1447 _Out_ PULONG pulLength)
1448 {
1449 HKEY hDeviceKey;
1450 DWORD dwSubKeys, dwMaxSubKeyLength;
1451 DWORD dwError;
1452
1453 /* Open the device key */
1454 dwError = RegOpenKeyExW(hEnumKey,
1455 pszDevice,
1456 0,
1457 KEY_READ,
1458 &hDeviceKey);
1459 if (dwError != ERROR_SUCCESS)
1460 {
1461 DPRINT("Failed to open the device key (Error %lu)\n", dwError);
1462 return CR_REGISTRY_ERROR;
1463 }
1464
1465 /* Retrieve the number of device instances and the maximum name length */
1466 dwError = RegQueryInfoKeyW(hDeviceKey,
1467 NULL,
1468 NULL,
1469 NULL,
1470 &dwSubKeys,
1471 &dwMaxSubKeyLength,
1472 NULL,
1473 NULL,
1474 NULL,
1475 NULL,
1476 NULL,
1477 NULL);
1478 if (dwError != ERROR_SUCCESS)
1479 {
1480 DPRINT("RegQueryInfoKeyW failed (Error %lu)\n", dwError);
1481 dwSubKeys = 0;
1482 dwMaxSubKeyLength = 0;
1483 }
1484
1485 /* Close the device key */
1486 RegCloseKey(hDeviceKey);
1487
1488 /* Return the largest possible buffer size */
1489 *pulLength = dwSubKeys * (wcslen(pszDevice) + 1 + dwMaxSubKeyLength + 1);
1490
1491 return CR_SUCCESS;
1492 }
1493
1494
1495 static
1496 CONFIGRET
1497 GetEnumeratorInstanceListSize(
1498 _In_ LPCWSTR pszEnumerator,
1499 _Out_ PULONG pulLength)
1500 {
1501 WCHAR szDeviceBuffer[MAX_DEVICE_ID_LEN];
1502 WCHAR szPathBuffer[512];
1503 HKEY hEnumeratorKey;
1504 DWORD dwIndex, dwDeviceLength, dwBufferLength;
1505 DWORD dwError;
1506 CONFIGRET ret = CR_SUCCESS;
1507
1508 *pulLength = 0;
1509
1510 /* Open the enumerator key */
1511 dwError = RegOpenKeyExW(hEnumKey,
1512 pszEnumerator,
1513 0,
1514 KEY_ENUMERATE_SUB_KEYS,
1515 &hEnumeratorKey);
1516 if (dwError != ERROR_SUCCESS)
1517 {
1518 DPRINT("Failed to open the enumerator key (Error %lu)\n", dwError);
1519 return CR_REGISTRY_ERROR;
1520 }
1521
1522 for (dwIndex = 0; ; dwIndex++)
1523 {
1524 dwDeviceLength = MAX_DEVICE_ID_LEN;
1525 dwError = RegEnumKeyExW(hEnumeratorKey,
1526 dwIndex,
1527 szDeviceBuffer,
1528 &dwDeviceLength,
1529 NULL,
1530 NULL,
1531 NULL,
1532 NULL);
1533 if (dwError != ERROR_SUCCESS)
1534 break;
1535
1536 wsprintf(szPathBuffer, L"%s\\%s", pszEnumerator, szDeviceBuffer);
1537 DPRINT("Path: %S\n", szPathBuffer);
1538
1539 ret = GetDeviceInstanceListSize(szPathBuffer, &dwBufferLength);
1540 if (ret != CR_SUCCESS)
1541 {
1542 *pulLength = 0;
1543 break;
1544 }
1545
1546 *pulLength += dwBufferLength;
1547 }
1548
1549 /* Close the enumerator key */
1550 RegCloseKey(hEnumeratorKey);
1551
1552 return ret;
1553 }
1554
1555
1556 static
1557 CONFIGRET
1558 GetAllInstanceListSize(
1559 _Out_ PULONG pulLength)
1560 {
1561 WCHAR szEnumeratorBuffer[MAX_DEVICE_ID_LEN];
1562 DWORD dwIndex, dwEnumeratorLength, dwBufferLength;
1563 DWORD dwError;
1564 CONFIGRET ret = CR_SUCCESS;
1565
1566 for (dwIndex = 0; ; dwIndex++)
1567 {
1568 dwEnumeratorLength = MAX_DEVICE_ID_LEN;
1569 dwError = RegEnumKeyExW(hEnumKey,
1570 dwIndex,
1571 szEnumeratorBuffer,
1572 &dwEnumeratorLength,
1573 NULL, NULL, NULL, NULL);
1574 if (dwError != ERROR_SUCCESS)
1575 break;
1576
1577 /* Get the size of all device instances for the enumerator */
1578 ret = GetEnumeratorInstanceListSize(szEnumeratorBuffer,
1579 &dwBufferLength);
1580 if (ret != CR_SUCCESS)
1581 break;
1582
1583 *pulLength += dwBufferLength;
1584 }
1585
1586 return ret;
1587 }
1588
1589
1590 /* Function 11 */
1591 DWORD
1592 WINAPI
1593 PNP_GetDeviceListSize(
1594 handle_t hBinding,
1595 LPWSTR pszFilter,
1596 PNP_RPC_BUFFER_SIZE *pulLength,
1597 DWORD ulFlags)
1598 {
1599 WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
1600 WCHAR szDevice[MAX_DEVICE_ID_LEN];
1601 WCHAR szInstance[MAX_DEVICE_ID_LEN];
1602 CONFIGRET ret = CR_SUCCESS;
1603
1604 DPRINT("PNP_GetDeviceListSize(%p %S %p 0x%08lx)\n",
1605 hBinding, pszFilter, pulLength, ulFlags);
1606
1607 if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
1608 return CR_INVALID_FLAG;
1609
1610 if (pulLength == NULL)
1611 return CR_INVALID_POINTER;
1612
1613 if ((ulFlags != CM_GETIDLIST_FILTER_NONE) &&
1614 (pszFilter == NULL))
1615 return CR_INVALID_POINTER;
1616
1617 *pulLength = 0;
1618
1619 if (ulFlags &
1620 (CM_GETIDLIST_FILTER_BUSRELATIONS |
1621 CM_GETIDLIST_FILTER_POWERRELATIONS |
1622 CM_GETIDLIST_FILTER_REMOVALRELATIONS |
1623 CM_GETIDLIST_FILTER_EJECTRELATIONS))
1624 {
1625 ret = GetRelationsInstanceListSize(pszFilter,
1626 ulFlags,
1627 pulLength);
1628 }
1629 else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE)
1630 {
1631 ret = GetServiceInstanceListSize(pszFilter,
1632 pulLength);
1633 }
1634 else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR)
1635 {
1636 SplitDeviceInstanceID(pszFilter,
1637 szEnumerator,
1638 szDevice,
1639 szInstance);
1640
1641 if (*szEnumerator != UNICODE_NULL && *szDevice != UNICODE_NULL)
1642 {
1643 ret = GetDeviceInstanceListSize(pszFilter,
1644 pulLength);
1645 }
1646 else
1647 {
1648 ret = GetEnumeratorInstanceListSize(pszFilter,
1649 pulLength);
1650 }
1651 }
1652 else /* CM_GETIDLIST_FILTER_NONE */
1653 {
1654 ret = GetAllInstanceListSize(pulLength);
1655 }
1656
1657 /* Add one character for the terminating double UNICODE_NULL */
1658 if (ret == CR_SUCCESS)
1659 (*pulLength) += 1;
1660
1661 return ret;
1662 }
1663
1664
1665 /* Function 12 */
1666 DWORD
1667 WINAPI
1668 PNP_GetDepth(
1669 handle_t hBinding,
1670 LPWSTR pszDeviceID,
1671 DWORD *pulDepth,
1672 DWORD ulFlags)
1673 {
1674 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData;
1675 CONFIGRET ret = CR_SUCCESS;
1676 NTSTATUS Status;
1677
1678 UNREFERENCED_PARAMETER(hBinding);
1679 UNREFERENCED_PARAMETER(ulFlags);
1680
1681 DPRINT("PNP_GetDepth(%p %S %p 0x%08lx)\n",
1682 hBinding, pszDeviceID, pulDepth, ulFlags);
1683
1684 if (!IsValidDeviceInstanceID(pszDeviceID))
1685 return CR_INVALID_DEVINST;
1686
1687 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1688 pszDeviceID);
1689
1690 Status = NtPlugPlayControl(PlugPlayControlGetDeviceDepth,
1691 (PVOID)&PlugPlayData,
1692 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA));
1693 if (NT_SUCCESS(Status))
1694 {
1695 *pulDepth = PlugPlayData.Depth;
1696 }
1697 else
1698 {
1699 ret = NtStatusToCrError(Status);
1700 }
1701
1702 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret);
1703
1704 return ret;
1705 }
1706
1707
1708 /* Function 13 */
1709 DWORD
1710 WINAPI
1711 PNP_GetDeviceRegProp(
1712 handle_t hBinding,
1713 LPWSTR pDeviceID,
1714 DWORD ulProperty,
1715 DWORD *pulRegDataType,
1716 BYTE *Buffer,
1717 PNP_PROP_SIZE *pulTransferLen,
1718 PNP_PROP_SIZE *pulLength,
1719 DWORD ulFlags)
1720 {
1721 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData;
1722 CONFIGRET ret = CR_SUCCESS;
1723 LPWSTR lpValueName = NULL;
1724 HKEY hKey = NULL;
1725 LONG lError;
1726 NTSTATUS Status;
1727
1728 UNREFERENCED_PARAMETER(hBinding);
1729
1730 DPRINT("PNP_GetDeviceRegProp(%p %S %lu %p %p %p %p 0x%08lx)\n",
1731 hBinding, pDeviceID, ulProperty, pulRegDataType, Buffer,
1732 pulTransferLen, pulLength, ulFlags);
1733
1734 if (pulTransferLen == NULL || pulLength == NULL)
1735 {
1736 ret = CR_INVALID_POINTER;
1737 goto done;
1738 }
1739
1740 if (ulFlags != 0)
1741 {
1742 ret = CR_INVALID_FLAG;
1743 goto done;
1744 }
1745
1746 /* Check pDeviceID */
1747 if (!IsValidDeviceInstanceID(pDeviceID))
1748 {
1749 ret = CR_INVALID_DEVINST;
1750 goto done;
1751 }
1752
1753 if (*pulLength < *pulTransferLen)
1754 *pulLength = *pulTransferLen;
1755
1756 *pulTransferLen = 0;
1757
1758 switch (ulProperty)
1759 {
1760 case CM_DRP_DEVICEDESC:
1761 lpValueName = L"DeviceDesc";
1762 break;
1763
1764 case CM_DRP_HARDWAREID:
1765 lpValueName = L"HardwareID";
1766 break;
1767
1768 case CM_DRP_COMPATIBLEIDS:
1769 lpValueName = L"CompatibleIDs";
1770 break;
1771
1772 case CM_DRP_SERVICE:
1773 lpValueName = L"Service";
1774 break;
1775
1776 case CM_DRP_CLASS:
1777 lpValueName = L"Class";
1778 break;
1779
1780 case CM_DRP_CLASSGUID:
1781 lpValueName = L"ClassGUID";
1782 break;
1783
1784 case CM_DRP_DRIVER:
1785 lpValueName = L"Driver";
1786 break;
1787
1788 case CM_DRP_CONFIGFLAGS:
1789 lpValueName = L"ConfigFlags";
1790 break;
1791
1792 case CM_DRP_MFG:
1793 lpValueName = L"Mfg";
1794 break;
1795
1796 case CM_DRP_FRIENDLYNAME:
1797 lpValueName = L"FriendlyName";
1798 break;
1799
1800 case CM_DRP_LOCATION_INFORMATION:
1801 lpValueName = L"LocationInformation";
1802 break;
1803
1804 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
1805 PlugPlayData.Property = PNP_PROPERTY_PHYSICAL_DEVICE_OBJECT_NAME;
1806 *pulRegDataType = REG_SZ;
1807 break;
1808
1809 case CM_DRP_CAPABILITIES:
1810 lpValueName = L"Capabilities";
1811 break;
1812
1813 case CM_DRP_UI_NUMBER:
1814 PlugPlayData.Property = PNP_PROPERTY_UI_NUMBER;
1815 break;
1816
1817 case CM_DRP_UPPERFILTERS:
1818 lpValueName = L"UpperFilters";
1819 break;
1820
1821 case CM_DRP_LOWERFILTERS:
1822 lpValueName = L"LowerFilters";
1823 break;
1824
1825 case CM_DRP_BUSTYPEGUID:
1826 PlugPlayData.Property = PNP_PROPERTY_BUSTYPEGUID;
1827 *pulRegDataType = REG_BINARY;
1828 break;
1829
1830 case CM_DRP_LEGACYBUSTYPE:
1831 PlugPlayData.Property = PNP_PROPERTY_LEGACYBUSTYPE;
1832 *pulRegDataType = REG_DWORD;
1833 break;
1834
1835 case CM_DRP_BUSNUMBER:
1836 PlugPlayData.Property = PNP_PROPERTY_BUSNUMBER;
1837 *pulRegDataType = REG_DWORD;
1838 break;
1839
1840 case CM_DRP_ENUMERATOR_NAME:
1841 PlugPlayData.Property = PNP_PROPERTY_ENUMERATOR_NAME;
1842 *pulRegDataType = REG_SZ;
1843 break;
1844
1845 case CM_DRP_SECURITY:
1846 lpValueName = L"Security";
1847 break;
1848
1849 case CM_DRP_DEVTYPE:
1850 lpValueName = L"DeviceType";
1851 break;
1852
1853 case CM_DRP_EXCLUSIVE:
1854 lpValueName = L"Exclusive";
1855 break;
1856
1857 case CM_DRP_CHARACTERISTICS:
1858 lpValueName = L"DeviceCharacteristics";
1859 break;
1860
1861 case CM_DRP_ADDRESS:
1862 PlugPlayData.Property = PNP_PROPERTY_ADDRESS;
1863 *pulRegDataType = REG_DWORD;
1864 break;
1865
1866 case CM_DRP_UI_NUMBER_DESC_FORMAT:
1867 lpValueName = L"UINumberDescFormat";
1868 break;
1869
1870 case CM_DRP_DEVICE_POWER_DATA:
1871 PlugPlayData.Property = PNP_PROPERTY_POWER_DATA;
1872 *pulRegDataType = REG_BINARY;
1873 break;
1874
1875 case CM_DRP_REMOVAL_POLICY:
1876 PlugPlayData.Property = PNP_PROPERTY_REMOVAL_POLICY;
1877 *pulRegDataType = REG_DWORD;
1878 break;
1879
1880 case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
1881 PlugPlayData.Property = PNP_PROPERTY_REMOVAL_POLICY_HARDWARE_DEFAULT;
1882 *pulRegDataType = REG_DWORD;
1883 break;
1884
1885 case CM_DRP_REMOVAL_POLICY_OVERRIDE:
1886 lpValueName = L"RemovalPolicy";
1887 *pulRegDataType = REG_DWORD;
1888 break;
1889
1890 case CM_DRP_INSTALL_STATE:
1891 PlugPlayData.Property = PNP_PROPERTY_INSTALL_STATE;
1892 *pulRegDataType = REG_DWORD;
1893 break;
1894
1895 #if (WINVER >= _WIN32_WINNT_WS03)
1896 case CM_DRP_LOCATION_PATHS:
1897 PlugPlayData.Property = PNP_PROPERTY_LOCATION_PATHS;
1898 *pulRegDataType = REG_MULTI_SZ;
1899 break;
1900 #endif
1901
1902 #if (WINVER >= _WIN32_WINNT_WIN7)
1903 case CM_DRP_BASE_CONTAINERID:
1904 PlugPlayData.Property = PNP_PROPERTY_CONTAINERID;
1905 *pulRegDataType = REG_SZ;
1906 break;
1907 #endif
1908
1909 default:
1910 ret = CR_INVALID_PROPERTY;
1911 goto done;
1912 }
1913
1914 DPRINT("Value name: %S\n", lpValueName);
1915
1916 if (lpValueName)
1917 {
1918 /* Retrieve information from the Registry */
1919 lError = RegOpenKeyExW(hEnumKey,
1920 pDeviceID,
1921 0,
1922 KEY_QUERY_VALUE,
1923 &hKey);
1924 if (lError != ERROR_SUCCESS)
1925 {
1926 hKey = NULL;
1927 *pulLength = 0;
1928 ret = CR_INVALID_DEVNODE;
1929 goto done;
1930 }
1931
1932 lError = RegQueryValueExW(hKey,
1933 lpValueName,
1934 NULL,
1935 pulRegDataType,
1936 Buffer,
1937 pulLength);
1938 if (lError != ERROR_SUCCESS)
1939 {
1940 if (lError == ERROR_MORE_DATA)
1941 {
1942 ret = CR_BUFFER_SMALL;
1943 }
1944 else
1945 {
1946 *pulLength = 0;
1947 ret = CR_NO_SUCH_VALUE;
1948 }
1949 }
1950 }
1951 else
1952 {
1953 /* Retrieve information from the Device Node */
1954 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1955 pDeviceID);
1956 PlugPlayData.Buffer = Buffer;
1957 PlugPlayData.BufferSize = *pulLength;
1958
1959 Status = NtPlugPlayControl(PlugPlayControlProperty,
1960 (PVOID)&PlugPlayData,
1961 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA));
1962 if (NT_SUCCESS(Status))
1963 {
1964 *pulLength = PlugPlayData.BufferSize;
1965 }
1966 else
1967 {
1968 ret = NtStatusToCrError(Status);
1969 }
1970 }
1971
1972 done:
1973 if (pulTransferLen)
1974 *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0;
1975
1976 if (hKey != NULL)
1977 RegCloseKey(hKey);
1978
1979 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret);
1980
1981 return ret;
1982 }
1983
1984
1985 /* Function 14 */
1986 DWORD
1987 WINAPI
1988 PNP_SetDeviceRegProp(
1989 handle_t hBinding,
1990 LPWSTR pDeviceId,
1991 DWORD ulProperty,
1992 DWORD ulDataType,
1993 BYTE *Buffer,
1994 PNP_PROP_SIZE ulLength,
1995 DWORD ulFlags)
1996 {
1997 CONFIGRET ret = CR_SUCCESS;
1998 LPWSTR lpValueName = NULL;
1999 HKEY hKey = 0;
2000
2001 UNREFERENCED_PARAMETER(hBinding);
2002 UNREFERENCED_PARAMETER(ulFlags);
2003
2004 DPRINT("PNP_SetDeviceRegProp(%p %S %lu %lu %p %lu 0x%08lx)\n",
2005 hBinding, pDeviceId, ulProperty, ulDataType, Buffer,
2006 ulLength, ulFlags);
2007
2008 if (!IsValidDeviceInstanceID(pDeviceId))
2009 return CR_INVALID_DEVINST;
2010
2011 switch (ulProperty)
2012 {
2013 case CM_DRP_DEVICEDESC:
2014 lpValueName = L"DeviceDesc";
2015 break;
2016
2017 case CM_DRP_HARDWAREID:
2018 lpValueName = L"HardwareID";
2019 break;
2020
2021 case CM_DRP_COMPATIBLEIDS:
2022 lpValueName = L"CompatibleIDs";
2023 break;
2024
2025 case CM_DRP_SERVICE:
2026 lpValueName = L"Service";
2027 break;
2028
2029 case CM_DRP_CLASS:
2030 lpValueName = L"Class";
2031 break;
2032
2033 case CM_DRP_CLASSGUID:
2034 lpValueName = L"ClassGUID";
2035 break;
2036
2037 case CM_DRP_DRIVER:
2038 lpValueName = L"Driver";
2039 break;
2040
2041 case CM_DRP_CONFIGFLAGS:
2042 lpValueName = L"ConfigFlags";
2043 break;
2044
2045 case CM_DRP_MFG:
2046 lpValueName = L"Mfg";
2047 break;
2048
2049 case CM_DRP_FRIENDLYNAME:
2050 lpValueName = L"FriendlyName";
2051 break;
2052
2053 case CM_DRP_LOCATION_INFORMATION:
2054 lpValueName = L"LocationInformation";
2055 break;
2056
2057 case CM_DRP_UPPERFILTERS:
2058 lpValueName = L"UpperFilters";
2059 break;
2060
2061 case CM_DRP_LOWERFILTERS:
2062 lpValueName = L"LowerFilters";
2063 break;
2064
2065 case CM_DRP_SECURITY:
2066 lpValueName = L"Security";
2067 break;
2068
2069 case CM_DRP_DEVTYPE:
2070 lpValueName = L"DeviceType";
2071 break;
2072
2073 case CM_DRP_EXCLUSIVE:
2074 lpValueName = L"Exclusive";
2075 break;
2076
2077 case CM_DRP_CHARACTERISTICS:
2078 lpValueName = L"DeviceCharacteristics";
2079 break;
2080
2081 case CM_DRP_UI_NUMBER_DESC_FORMAT:
2082 lpValueName = L"UINumberDescFormat";
2083 break;
2084
2085 case CM_DRP_REMOVAL_POLICY_OVERRIDE:
2086 lpValueName = L"RemovalPolicy";
2087 break;
2088
2089 default:
2090 return CR_INVALID_PROPERTY;
2091 }
2092
2093 DPRINT("Value name: %S\n", lpValueName);
2094
2095 if (RegOpenKeyExW(hEnumKey,
2096 pDeviceId,
2097 0,
2098 KEY_SET_VALUE,
2099 &hKey))
2100 return CR_INVALID_DEVNODE;
2101
2102 if (ulLength == 0)
2103 {
2104 if (RegDeleteValueW(hKey,
2105 lpValueName))
2106 ret = CR_REGISTRY_ERROR;
2107 }
2108 else
2109 {
2110 if (RegSetValueExW(hKey,
2111 lpValueName,
2112 0,
2113 ulDataType,
2114 Buffer,
2115 ulLength))
2116 ret = CR_REGISTRY_ERROR;
2117 }
2118
2119 RegCloseKey(hKey);
2120
2121 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret);
2122
2123 return ret;
2124 }
2125
2126
2127 /* Function 15 */
2128 DWORD
2129 WINAPI
2130 PNP_GetClassInstance(
2131 handle_t hBinding,
2132 LPWSTR pDeviceId,
2133 LPWSTR pszClassInstance,
2134 PNP_RPC_STRING_LEN ulLength)
2135 {
2136 WCHAR szClassGuid[40];
2137 WCHAR szClassInstance[5];
2138 HKEY hDeviceClassKey = NULL;
2139 HKEY hClassInstanceKey;
2140 ULONG ulTransferLength, ulDataLength;
2141 DWORD dwDataType, dwDisposition, i;
2142 DWORD dwError;
2143 CONFIGRET ret = CR_SUCCESS;
2144
2145 DPRINT("PNP_GetClassInstance(%p %S %p %lu)\n",
2146 hBinding, pDeviceId, pszClassInstance, ulLength);
2147
2148 if (!IsValidDeviceInstanceID(pDeviceId))
2149 return CR_INVALID_DEVINST;
2150
2151 ulTransferLength = ulLength;
2152 ret = PNP_GetDeviceRegProp(hBinding,
2153 pDeviceId,
2154 CM_DRP_DRIVER,
2155 &dwDataType,
2156 (BYTE *)pszClassInstance,
2157 &ulTransferLength,
2158 &ulLength,
2159 0);
2160 if (ret == CR_SUCCESS)
2161 return ret;
2162
2163 ulTransferLength = sizeof(szClassGuid);
2164 ulDataLength = sizeof(szClassGuid);
2165 ret = PNP_GetDeviceRegProp(hBinding,
2166 pDeviceId,
2167 CM_DRP_CLASSGUID,
2168 &dwDataType,
2169 (BYTE *)szClassGuid,
2170 &ulTransferLength,
2171 &ulDataLength,
2172 0);
2173 if (ret != CR_SUCCESS)
2174 {
2175 DPRINT1("PNP_GetDeviceRegProp() failed (Error %lu)\n", ret);
2176 goto done;
2177 }
2178
2179 dwError = RegOpenKeyExW(hClassKey,
2180 szClassGuid,
2181 0,
2182 KEY_READ,
2183 &hDeviceClassKey);
2184 if (dwError != ERROR_SUCCESS)
2185 {
2186 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError);
2187 ret = CR_FAILURE;
2188 goto done;
2189 }
2190
2191 for (i = 0; i < 10000; i++)
2192 {
2193 wsprintf(szClassInstance, L"%04lu", i);
2194
2195 dwError = RegCreateKeyExW(hDeviceClassKey,
2196 szClassInstance,
2197 0,
2198 NULL,
2199 REG_OPTION_NON_VOLATILE,
2200 KEY_ALL_ACCESS,
2201 NULL,
2202 &hClassInstanceKey,
2203 &dwDisposition);
2204 if (dwError == ERROR_SUCCESS)
2205 {
2206 RegCloseKey(hClassInstanceKey);
2207
2208 if (dwDisposition == REG_CREATED_NEW_KEY)
2209 {
2210 wsprintf(pszClassInstance,
2211 L"%s\\%s",
2212 szClassGuid,
2213 szClassInstance);
2214
2215 ulDataLength = (wcslen(pszClassInstance) + 1) * sizeof(WCHAR);
2216 ret = PNP_SetDeviceRegProp(hBinding,
2217 pDeviceId,
2218 CM_DRP_DRIVER,
2219 REG_SZ,
2220 (BYTE *)pszClassInstance,
2221 ulDataLength,
2222 0);
2223 if (ret != CR_SUCCESS)
2224 {
2225 DPRINT1("PNP_SetDeviceRegProp() failed (Error %lu)\n", ret);
2226 RegDeleteKeyW(hDeviceClassKey,
2227 szClassInstance);
2228 }
2229
2230 break;
2231 }
2232 }
2233 }
2234
2235 done:
2236 if (hDeviceClassKey != NULL)
2237 RegCloseKey(hDeviceClassKey);
2238
2239 return ret;
2240 }
2241
2242
2243 /* Function 16 */
2244 DWORD
2245 WINAPI
2246 PNP_CreateKey(
2247 handle_t hBinding,
2248 LPWSTR pszSubKey,
2249 DWORD samDesired,
2250 DWORD ulFlags)
2251 {
2252 HKEY hDeviceKey = NULL, hParametersKey = NULL;
2253 DWORD dwError;
2254 CONFIGRET ret = CR_SUCCESS;
2255
2256 UNREFERENCED_PARAMETER(hBinding);
2257 UNREFERENCED_PARAMETER(samDesired);
2258
2259 DPRINT("PNP_CreateKey(%p %S 0x%lx 0x%08lx)\n",
2260 hBinding, pszSubKey, samDesired, ulFlags);
2261
2262 if (ulFlags != 0)
2263 return CR_INVALID_FLAG;
2264
2265 if (!IsValidDeviceInstanceID(pszSubKey))
2266 return CR_INVALID_DEVINST;
2267
2268 dwError = RegOpenKeyExW(hEnumKey,
2269 pszSubKey,
2270 0,
2271 KEY_WRITE,
2272 &hDeviceKey);
2273 if (dwError != ERROR_SUCCESS)
2274 {
2275 ret = CR_INVALID_DEVNODE;
2276 goto done;
2277 }
2278
2279 dwError = RegCreateKeyExW(hDeviceKey,
2280 L"Device Parameters",
2281 0,
2282 NULL,
2283 REG_OPTION_NON_VOLATILE,
2284 KEY_ALL_ACCESS,
2285 NULL,
2286 &hParametersKey,
2287 NULL);
2288 if (dwError != ERROR_SUCCESS)
2289 {
2290 ret = CR_REGISTRY_ERROR;
2291 goto done;
2292 }
2293
2294 /* FIXME: Set key security */
2295
2296 done:
2297 if (hParametersKey != NULL)
2298 RegCloseKey(hParametersKey);
2299
2300 if (hDeviceKey != NULL)
2301 RegCloseKey(hDeviceKey);
2302
2303 return ret;
2304 }
2305
2306
2307 /* Function 17 */
2308 DWORD
2309 WINAPI
2310 PNP_DeleteRegistryKey(
2311 handle_t hBinding,
2312 LPWSTR pszDeviceID,
2313 LPWSTR pszParentKey,
2314 LPWSTR pszChildKey,
2315 DWORD ulFlags)
2316 {
2317 UNIMPLEMENTED;
2318 return CR_CALL_NOT_IMPLEMENTED;
2319 }
2320
2321
2322 /* Function 18 */
2323 DWORD
2324 WINAPI
2325 PNP_GetClassCount(
2326 handle_t hBinding,
2327 DWORD *pulClassCount,
2328 DWORD ulFlags)
2329 {
2330 HKEY hKey;
2331 DWORD dwError;
2332
2333 UNREFERENCED_PARAMETER(hBinding);
2334 UNREFERENCED_PARAMETER(ulFlags);
2335
2336 DPRINT("PNP_GetClassCount(%p %p 0x%08lx)\n",
2337 hBinding, pulClassCount, ulFlags);
2338
2339 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2340 REGSTR_PATH_CLASS,
2341 0,
2342 KEY_QUERY_VALUE,
2343 &hKey);
2344 if (dwError != ERROR_SUCCESS)
2345 return CR_INVALID_DATA;
2346
2347 dwError = RegQueryInfoKeyW(hKey,
2348 NULL,
2349 NULL,
2350 NULL,
2351 pulClassCount,
2352 NULL,
2353 NULL,
2354 NULL,
2355 NULL,
2356 NULL,
2357 NULL,
2358 NULL);
2359 RegCloseKey(hKey);
2360 if (dwError != ERROR_SUCCESS)
2361 return CR_INVALID_DATA;
2362
2363 return CR_SUCCESS;
2364 }
2365
2366
2367 /* Function 19 */
2368 DWORD
2369 WINAPI
2370 PNP_GetClassName(
2371 handle_t hBinding,
2372 LPWSTR pszClassGuid,
2373 LPWSTR Buffer,
2374 PNP_RPC_STRING_LEN *pulLength,
2375 DWORD ulFlags)
2376 {
2377 WCHAR szKeyName[MAX_PATH];
2378 CONFIGRET ret = CR_SUCCESS;
2379 HKEY hKey;
2380 DWORD dwSize;
2381
2382 UNREFERENCED_PARAMETER(hBinding);
2383 UNREFERENCED_PARAMETER(ulFlags);
2384
2385 DPRINT("PNP_GetClassName(%p %S %p %p 0x%08lx)\n",
2386 hBinding, pszClassGuid, Buffer, pulLength, ulFlags);
2387
2388 lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\");
2389 if (lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR)))
2390 lstrcatW(szKeyName, pszClassGuid);
2391 else
2392 return CR_INVALID_DATA;
2393
2394 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2395 szKeyName,
2396 0,
2397 KEY_QUERY_VALUE,
2398 &hKey))
2399 return CR_REGISTRY_ERROR;
2400
2401 dwSize = *pulLength * sizeof(WCHAR);
2402 if (RegQueryValueExW(hKey,
2403 L"Class",
2404 NULL,
2405 NULL,
2406 (LPBYTE)Buffer,
2407 &dwSize))
2408 {
2409 *pulLength = 0;
2410 ret = CR_REGISTRY_ERROR;
2411 }
2412 else
2413 {
2414 *pulLength = dwSize / sizeof(WCHAR);
2415 }
2416
2417 RegCloseKey(hKey);
2418
2419 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret);
2420
2421 return ret;
2422 }
2423
2424
2425 /* Function 20 */
2426 DWORD
2427 WINAPI
2428 PNP_DeleteClassKey(
2429 handle_t hBinding,
2430 LPWSTR pszClassGuid,
2431 DWORD ulFlags)
2432 {
2433 CONFIGRET ret = CR_SUCCESS;
2434
2435 UNREFERENCED_PARAMETER(hBinding);
2436
2437 DPRINT("PNP_DeleteClassKey(%p %S 0x%08lx)\n",
2438 hBinding, pszClassGuid, ulFlags);
2439
2440 if (ulFlags & CM_DELETE_CLASS_SUBKEYS)
2441 {
2442 if (SHDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
2443 ret = CR_REGISTRY_ERROR;
2444 }
2445 else
2446 {
2447 if (RegDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
2448 ret = CR_REGISTRY_ERROR;
2449 }
2450
2451 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret);
2452
2453 return ret;
2454 }
2455
2456
2457 /* Function 21 */
2458 DWORD
2459 WINAPI
2460 PNP_GetInterfaceDeviceAlias(
2461 handle_t hBinding,
2462 LPWSTR pszInterfaceDevice,
2463 GUID *AliasInterfaceGuid,
2464 LPWSTR pszAliasInterfaceDevice,
2465 PNP_RPC_STRING_LEN *pulLength,
2466 PNP_RPC_STRING_LEN *pulTransferLen,
2467 DWORD ulFlags)
2468 {
2469 UNIMPLEMENTED;
2470 return CR_CALL_NOT_IMPLEMENTED;
2471 }
2472
2473
2474 /* Function 22 */
2475 DWORD
2476 WINAPI
2477 PNP_GetInterfaceDeviceList(
2478 handle_t hBinding,
2479 GUID *InterfaceGuid,
2480 LPWSTR pszDeviceID,
2481 BYTE *Buffer,
2482 PNP_RPC_BUFFER_SIZE *pulLength,
2483 DWORD ulFlags)
2484 {
2485 NTSTATUS Status;
2486 PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA PlugPlayData;
2487 DWORD ret = CR_SUCCESS;
2488
2489 UNREFERENCED_PARAMETER(hBinding);
2490
2491 DPRINT("PNP_GetInterfaceDeviceList(%p %p %S %p %p 0x%08lx)\n",
2492 hBinding, InterfaceGuid, pszDeviceID, Buffer, pulLength, ulFlags);
2493
2494 if (!IsValidDeviceInstanceID(pszDeviceID))
2495 return CR_INVALID_DEVINST;
2496
2497 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
2498 pszDeviceID);
2499
2500 PlugPlayData.Flags = ulFlags;
2501 PlugPlayData.FilterGuid = InterfaceGuid;
2502 PlugPlayData.Buffer = Buffer;
2503 PlugPlayData.BufferSize = *pulLength;
2504
2505 Status = NtPlugPlayControl(PlugPlayControlGetInterfaceDeviceList,
2506 (PVOID)&PlugPlayData,
2507 sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA));
2508 if (NT_SUCCESS(Status))
2509 {
2510 *pulLength = PlugPlayData.BufferSize;
2511 }
2512 else
2513 {
2514 ret = NtStatusToCrError(Status);
2515 }
2516
2517 DPRINT("PNP_GetInterfaceDeviceList() done (returns %lx)\n", ret);
2518 return ret;
2519 }
2520
2521
2522 /* Function 23 */
2523 DWORD
2524 WINAPI
2525 PNP_GetInterfaceDeviceListSize(
2526 handle_t hBinding,
2527 PNP_RPC_BUFFER_SIZE *pulLen,
2528 GUID *InterfaceGuid,
2529 LPWSTR pszDeviceID,
2530 DWORD ulFlags)
2531 {
2532 NTSTATUS Status;
2533 PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA PlugPlayData;
2534 DWORD ret = CR_SUCCESS;
2535
2536 UNREFERENCED_PARAMETER(hBinding);
2537
2538 DPRINT("PNP_GetInterfaceDeviceListSize(%p %p %p %S 0x%08lx)\n",
2539 hBinding, pulLen, InterfaceGuid, pszDeviceID, ulFlags);
2540
2541 if (!IsValidDeviceInstanceID(pszDeviceID))
2542 return CR_INVALID_DEVINST;
2543
2544 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
2545 pszDeviceID);
2546
2547 PlugPlayData.FilterGuid = InterfaceGuid;
2548 PlugPlayData.Buffer = NULL;
2549 PlugPlayData.BufferSize = 0;
2550 PlugPlayData.Flags = ulFlags;
2551
2552 Status = NtPlugPlayControl(PlugPlayControlGetInterfaceDeviceList,
2553 (PVOID)&PlugPlayData,
2554 sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA));
2555 if (NT_SUCCESS(Status))
2556 {
2557 *pulLen = PlugPlayData.BufferSize;
2558 }
2559 else
2560 {
2561 ret = NtStatusToCrError(Status);
2562 }
2563
2564 DPRINT("PNP_GetInterfaceDeviceListSize() done (returns %lx)\n", ret);
2565 return ret;
2566 }
2567
2568
2569 /* Function 24 */
2570 DWORD
2571 WINAPI
2572 PNP_RegisterDeviceClassAssociation(
2573 handle_t hBinding,
2574 LPWSTR pszDeviceID,
2575 GUID *InterfaceGuid,
2576 LPWSTR pszReference,
2577 LPWSTR pszSymLink,
2578 PNP_RPC_STRING_LEN *pulLength,
2579 PNP_RPC_STRING_LEN *pulTransferLen,
2580 DWORD ulFlags)
2581 {
2582 UNIMPLEMENTED;
2583 return CR_CALL_NOT_IMPLEMENTED;
2584 }
2585
2586
2587 /* Function 25 */
2588 DWORD
2589 WINAPI
2590 PNP_UnregisterDeviceClassAssociation(
2591 handle_t hBinding,
2592 LPWSTR pszInterfaceDevice,
2593 DWORD ulFlags)
2594 {
2595 UNIMPLEMENTED;
2596 return CR_CALL_NOT_IMPLEMENTED;
2597 }
2598
2599
2600 /* Function 26 */
2601 DWORD
2602 WINAPI
2603 PNP_GetClassRegProp(
2604 handle_t hBinding,
2605 LPWSTR pszClassGuid,
2606 DWORD ulProperty,
2607 DWORD *pulRegDataType,
2608 BYTE *Buffer,
2609 PNP_RPC_STRING_LEN *pulTransferLen,
2610 PNP_RPC_STRING_LEN *pulLength,
2611 DWORD ulFlags)
2612 {
2613 CONFIGRET ret = CR_SUCCESS;
2614 LPWSTR lpValueName = NULL;
2615 HKEY hInstKey = NULL;
2616 HKEY hPropKey = NULL;
2617 LONG lError;
2618
2619 UNREFERENCED_PARAMETER(hBinding);
2620
2621 DPRINT("PNP_GetClassRegProp(%p %S %lu %p %p %p %p 0x%08lx)\n",
2622 hBinding, pszClassGuid, ulProperty, pulRegDataType,
2623 Buffer, pulTransferLen, pulLength, ulFlags);
2624
2625 if (pulTransferLen == NULL || pulLength == NULL)
2626 {
2627 ret = CR_INVALID_POINTER;
2628 goto done;
2629 }
2630
2631 if (ulFlags != 0)
2632 {
2633 ret = CR_INVALID_FLAG;
2634 goto done;
2635 }
2636
2637 if (*pulLength < *pulTransferLen)
2638 *pulLength = *pulTransferLen;
2639
2640 *pulTransferLen = 0;
2641
2642 switch (ulProperty)
2643 {
2644 case CM_CRP_SECURITY:
2645 lpValueName = L"Security";
2646 break;
2647
2648 case CM_CRP_DEVTYPE:
2649 lpValueName = L"DeviceType";
2650 break;
2651
2652 case CM_CRP_EXCLUSIVE:
2653 lpValueName = L"Exclusive";
2654 break;
2655
2656 case CM_CRP_CHARACTERISTICS:
2657 lpValueName = L"DeviceCharacteristics";
2658 break;
2659
2660 default:
2661 ret = CR_INVALID_PROPERTY;
2662 goto done;
2663 }
2664
2665 DPRINT("Value name: %S\n", lpValueName);
2666
2667 lError = RegOpenKeyExW(hClassKey,
2668 pszClassGuid,
2669 0,
2670 KEY_READ,
2671 &hInstKey);
2672 if (lError != ERROR_SUCCESS)
2673 {
2674 *pulLength = 0;
2675 ret = CR_NO_SUCH_REGISTRY_KEY;
2676 goto done;
2677 }
2678
2679 lError = RegOpenKeyExW(hInstKey,
2680 L"Properties",
2681 0,
2682 KEY_READ,
2683 &hPropKey);
2684 if (lError != ERROR_SUCCESS)
2685 {
2686 *pulLength = 0;
2687 ret = CR_NO_SUCH_REGISTRY_KEY;
2688 goto done;
2689 }
2690
2691 lError = RegQueryValueExW(hPropKey,
2692 lpValueName,
2693 NULL,
2694 pulRegDataType,
2695 Buffer,
2696 pulLength);
2697 if (lError != ERROR_SUCCESS)
2698 {
2699 if (lError == ERROR_MORE_DATA)
2700 {
2701 ret = CR_BUFFER_SMALL;
2702 }
2703 else
2704 {
2705 *pulLength = 0;
2706 ret = CR_NO_SUCH_VALUE;
2707 }
2708 }
2709
2710 done:
2711 if (ret == CR_SUCCESS)
2712 *pulTransferLen = *pulLength;
2713
2714 if (hPropKey != NULL)
2715 RegCloseKey(hPropKey);
2716
2717 if (hInstKey != NULL)
2718 RegCloseKey(hInstKey);
2719
2720 DPRINT("PNP_GetClassRegProp() done (returns %lx)\n", ret);
2721
2722 return ret;
2723 }
2724
2725
2726 /* Function 27 */
2727 DWORD
2728 WINAPI
2729 PNP_SetClassRegProp(
2730 handle_t hBinding,
2731 LPWSTR pszClassGuid,
2732 DWORD ulProperty,
2733 DWORD ulDataType,
2734 BYTE *Buffer,
2735 PNP_PROP_SIZE ulLength,
2736 DWORD ulFlags)
2737 {
2738 CONFIGRET ret = CR_SUCCESS;
2739 LPWSTR lpValueName = NULL;
2740 HKEY hInstKey = 0;
2741 HKEY hPropKey = 0;
2742 LONG lError;
2743
2744 UNREFERENCED_PARAMETER(hBinding);
2745
2746 DPRINT("PNP_SetClassRegProp(%p %S %lu %lu %p %lu 0x%08lx)\n",
2747 hBinding, pszClassGuid, ulProperty, ulDataType,
2748 Buffer, ulLength, ulFlags);
2749
2750 if (ulFlags != 0)
2751 return CR_INVALID_FLAG;
2752
2753 switch (ulProperty)
2754 {
2755 case CM_CRP_SECURITY:
2756 lpValueName = L"Security";
2757 break;
2758
2759 case CM_CRP_DEVTYPE:
2760 lpValueName = L"DeviceType";
2761 break;
2762
2763 case CM_CRP_EXCLUSIVE:
2764 lpValueName = L"Exclusive";
2765 break;
2766
2767 case CM_CRP_CHARACTERISTICS:
2768 lpValueName = L"DeviceCharacteristics";
2769 break;
2770
2771 default:
2772 return CR_INVALID_PROPERTY;
2773 }
2774
2775 lError = RegOpenKeyExW(hClassKey,
2776 pszClassGuid,
2777 0,
2778 KEY_WRITE,
2779 &hInstKey);
2780 if (lError != ERROR_SUCCESS)
2781 {
2782 ret = CR_NO_SUCH_REGISTRY_KEY;
2783 goto done;
2784 }
2785
2786 /* FIXME: Set security descriptor */
2787 lError = RegCreateKeyExW(hInstKey,
2788 L"Properties",
2789 0,
2790 NULL,
2791 REG_OPTION_NON_VOLATILE,
2792 KEY_ALL_ACCESS,
2793 NULL,
2794 &hPropKey,
2795 NULL);
2796 if (lError != ERROR_SUCCESS)
2797 {
2798 ret = CR_REGISTRY_ERROR;
2799 goto done;
2800 }
2801
2802 if (ulLength == 0)
2803 {
2804 if (RegDeleteValueW(hPropKey,
2805 lpValueName))
2806 ret = CR_REGISTRY_ERROR;
2807 }
2808 else
2809 {
2810 if (RegSetValueExW(hPropKey,
2811 lpValueName,
2812 0,
2813 ulDataType,
2814 Buffer,
2815 ulLength))
2816 ret = CR_REGISTRY_ERROR;
2817 }
2818
2819 done:
2820 if (hPropKey != NULL)
2821 RegCloseKey(hPropKey);
2822
2823 if (hInstKey != NULL)
2824 RegCloseKey(hInstKey);
2825
2826 return ret;
2827 }
2828
2829
2830 static CONFIGRET
2831 CreateDeviceInstance(LPWSTR pszDeviceID)
2832 {
2833 WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
2834 WCHAR szDevice[MAX_DEVICE_ID_LEN];
2835 WCHAR szInstance[MAX_DEVICE_ID_LEN];
2836 HKEY hKeyEnumerator;
2837 HKEY hKeyDevice;
2838 HKEY hKeyInstance;
2839 HKEY hKeyControl;
2840 LONG lError;
2841
2842 /* Split the instance ID */
2843 SplitDeviceInstanceID(pszDeviceID,
2844 szEnumerator,
2845 szDevice,
2846 szInstance);
2847
2848 /* Open or create the enumerator key */
2849 lError = RegCreateKeyExW(hEnumKey,
2850 szEnumerator,
2851 0,
2852 NULL,
2853 REG_OPTION_NON_VOLATILE,
2854 KEY_ALL_ACCESS,
2855 NULL,
2856 &hKeyEnumerator,
2857 NULL);
2858 if (lError != ERROR_SUCCESS)
2859 {
2860 return CR_REGISTRY_ERROR;
2861 }
2862
2863 /* Open or create the device key */
2864 lError = RegCreateKeyExW(hKeyEnumerator,
2865 szDevice,
2866 0,
2867 NULL,
2868 REG_OPTION_NON_VOLATILE,
2869 KEY_ALL_ACCESS,
2870 NULL,
2871 &hKeyDevice,
2872 NULL);
2873
2874 /* Close the enumerator key */
2875 RegCloseKey(hKeyEnumerator);
2876
2877 if (lError != ERROR_SUCCESS)
2878 {
2879 return CR_REGISTRY_ERROR;
2880 }
2881
2882 /* Try to open the instance key and fail if it exists */
2883 lError = RegOpenKeyExW(hKeyDevice,
2884 szInstance,
2885 0,
2886 KEY_SET_VALUE,
2887 &hKeyInstance);
2888 if (lError == ERROR_SUCCESS)
2889 {
2890 DPRINT1("Instance %S already exists!\n", szInstance);
2891 RegCloseKey(hKeyInstance);
2892 RegCloseKey(hKeyDevice);
2893 return CR_ALREADY_SUCH_DEVINST;
2894 }
2895
2896 /* Create a new instance key */
2897 lError = RegCreateKeyExW(hKeyDevice,
2898 szInstance,
2899 0,
2900 NULL,
2901 REG_OPTION_NON_VOLATILE,
2902 KEY_ALL_ACCESS,
2903 NULL,
2904 &hKeyInstance,
2905 NULL);
2906
2907 /* Close the device key */
2908 RegCloseKey(hKeyDevice);
2909
2910 if (lError != ERROR_SUCCESS)
2911 {
2912 return CR_REGISTRY_ERROR;
2913 }
2914
2915 /* Create the 'Control' sub key */
2916 lError = RegCreateKeyExW(hKeyInstance,
2917 L"Control",
2918 0,
2919 NULL,
2920 REG_OPTION_NON_VOLATILE,
2921 KEY_ALL_ACCESS,
2922 NULL,
2923 &hKeyControl,
2924 NULL);
2925 if (lError == ERROR_SUCCESS)
2926 {
2927 RegCloseKey(hKeyControl);
2928 }
2929
2930 RegCloseKey(hKeyInstance);
2931
2932 return (lError == ERROR_SUCCESS) ? CR_SUCCESS : CR_REGISTRY_ERROR;
2933 }
2934
2935
2936 /* Function 28 */
2937 DWORD
2938 WINAPI
2939 PNP_CreateDevInst(
2940 handle_t hBinding,
2941 LPWSTR pszDeviceID,
2942 LPWSTR pszParentDeviceID,
2943 PNP_RPC_STRING_LEN ulLength,
2944 DWORD ulFlags)
2945 {
2946 CONFIGRET ret = CR_SUCCESS;
2947
2948 DPRINT("PNP_CreateDevInst(%p %S %S %lu 0x%08lx)\n",
2949 hBinding, pszParentDeviceID, pszDeviceID, ulLength, ulFlags);
2950
2951 if (ulFlags & ~CM_CREATE_DEVNODE_BITS)
2952 return CR_INVALID_FLAG;
2953
2954 if (pszDeviceID == NULL || pszParentDeviceID == NULL)
2955 return CR_INVALID_POINTER;
2956
2957 /* Fail, if the parent device is not the root device */
2958 if (!IsRootDeviceInstanceID(pszParentDeviceID))
2959 return CR_INVALID_DEVINST;
2960
2961 if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID)
2962 {
2963 WCHAR szGeneratedInstance[MAX_DEVICE_ID_LEN];
2964 DWORD dwInstanceNumber;
2965
2966 /* Generated ID is: Root\<Device ID>\<Instance number> */
2967 dwInstanceNumber = 0;
2968 do
2969 {
2970 swprintf(szGeneratedInstance, L"Root\\%ls\\%04lu",
2971 pszDeviceID, dwInstanceNumber);
2972
2973 /* Try to create a device instance with this ID */
2974 ret = CreateDeviceInstance(szGeneratedInstance);
2975
2976 dwInstanceNumber++;
2977 }
2978 while (ret == CR_ALREADY_SUCH_DEVINST);
2979
2980 if (ret == CR_SUCCESS)
2981 {
2982 /* pszDeviceID is an out parameter too for generated IDs */
2983 if (wcslen(szGeneratedInstance) > ulLength)
2984 {
2985 ret = CR_BUFFER_SMALL;
2986 }
2987 else
2988 {
2989 wcscpy(pszDeviceID, szGeneratedInstance);
2990 }
2991 }
2992 }
2993 else
2994 {
2995 /* Create the device instance */
2996 ret = CreateDeviceInstance(pszDeviceID);
2997 }
2998
2999 DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret);
3000
3001 return ret;
3002 }
3003
3004
3005 static CONFIGRET
3006 SetupDeviceInstance(
3007 _In_ LPWSTR pszDeviceInstance,
3008 _In_ DWORD ulMinorAction)
3009 {
3010 HKEY hDeviceKey = NULL;
3011 DWORD dwDisableCount, dwSize;
3012 DWORD ulStatus, ulProblem;
3013 DWORD dwError;
3014 CONFIGRET ret = CR_SUCCESS;
3015
3016 DPRINT1("SetupDeviceInstance(%S 0x%08lx)\n",
3017 pszDeviceInstance, ulMinorAction);
3018
3019 if (IsRootDeviceInstanceID(pszDeviceInstance))
3020 return CR_INVALID_DEVINST;
3021
3022 if (ulMinorAction & ~CM_SETUP_BITS)
3023 return CR_INVALID_FLAG;
3024
3025 if ((ulMinorAction == CM_SETUP_DOWNLOAD) ||
3026 (ulMinorAction == CM_SETUP_WRITE_LOG_CONFS))
3027 return CR_SUCCESS;
3028
3029 dwError = RegOpenKeyExW(hEnumKey,
3030 pszDeviceInstance,
3031 0,
3032 KEY_READ,
3033 &hDeviceKey);
3034 if (dwError != ERROR_SUCCESS)
3035 return CR_INVALID_DEVNODE;
3036
3037 dwSize = sizeof(dwDisableCount);
3038 dwError = RegQueryValueExW(hDeviceKey,
3039 L"DisableCount",
3040 NULL,
3041 NULL,
3042 (LPBYTE)&dwDisableCount,
3043 &dwSize);
3044 if ((dwError == ERROR_SUCCESS) &&
3045 (dwDisableCount > 0))
3046 {
3047 goto done;
3048 }
3049
3050 GetDeviceStatus(pszDeviceInstance,
3051 &ulStatus,
3052 &ulProblem);
3053
3054 if (ulStatus & DN_STARTED)
3055 {
3056 goto done;
3057 }
3058
3059 if (ulStatus & DN_HAS_PROBLEM)
3060 {
3061 ret = ClearDeviceStatus(pszDeviceInstance,
3062 DN_HAS_PROBLEM,
3063 ulProblem);
3064 }
3065
3066 if (ret != CR_SUCCESS)
3067 goto done;
3068
3069
3070 /* FIXME: Start the device */
3071
3072 done:
3073 if (hDeviceKey != NULL)
3074 RegCloseKey(hDeviceKey);
3075
3076 return ret;
3077 }
3078
3079
3080 static CONFIGRET
3081 EnableDeviceInstance(
3082 _In_ LPWSTR pszDeviceInstance)
3083 {
3084 PLUGPLAY_CONTROL_DEVICE_CONTROL_DATA ControlData;
3085 CONFIGRET ret = CR_SUCCESS;
3086 NTSTATUS Status;
3087
3088 DPRINT("Enable device instance %S\n", pszDeviceInstance);
3089
3090 RtlInitUnicodeString(&ControlData.DeviceInstance, pszDeviceInstance);
3091 Status = NtPlugPlayControl(PlugPlayControlStartDevice, &ControlData, sizeof(ControlData));
3092 if (!NT_SUCCESS(Status))
3093 ret = NtStatusToCrError(Status);
3094
3095 return ret;
3096 }
3097
3098
3099 static CONFIGRET
3100 ReenumerateDeviceInstance(
3101 _In_ LPWSTR pszDeviceInstance,
3102 _In_ ULONG ulMinorAction)
3103 {
3104 PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA EnumerateDeviceData;
3105 CONFIGRET ret = CR_SUCCESS;
3106 NTSTATUS Status;
3107
3108 DPRINT1("ReenumerateDeviceInstance(%S 0x%08lx)\n",
3109 pszDeviceInstance, ulMinorAction);
3110
3111 if (ulMinorAction & ~CM_REENUMERATE_BITS)
3112 return CR_INVALID_FLAG;
3113
3114 if (ulMinorAction & CM_REENUMERATE_RETRY_INSTALLATION)
3115 {
3116 DPRINT1("CM_REENUMERATE_RETRY_INSTALLATION not implemented!\n");
3117 }
3118
3119 RtlInitUnicodeString(&EnumerateDeviceData.DeviceInstance,
3120 pszDeviceInstance);
3121 EnumerateDeviceData.Flags = 0;
3122
3123 Status = NtPlugPlayControl(PlugPlayControlEnumerateDevice,
3124 &EnumerateDeviceData,
3125 sizeof(PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA));
3126 if (!NT_SUCCESS(Status))
3127 ret = NtStatusToCrError(Status);
3128
3129 return ret;
3130 }
3131
3132
3133 /* Function 29 */
3134 DWORD
3135 WINAPI
3136 PNP_DeviceInstanceAction(
3137 handle_t hBinding,
3138 DWORD ulMajorAction,
3139 DWORD ulMinorAction,
3140 LPWSTR pszDeviceInstance1,
3141 LPWSTR pszDeviceInstance2)
3142 {
3143 CONFIGRET ret = CR_SUCCESS;
3144
3145 UNREFERENCED_PARAMETER(hBinding);
3146
3147 DPRINT("PNP_DeviceInstanceAction(%p %lu 0x%08lx %S %S)\n",
3148 hBinding, ulMajorAction, ulMinorAction,
3149 pszDeviceInstance1, pszDeviceInstance2);
3150
3151 switch (ulMajorAction)
3152 {
3153 case PNP_DEVINST_SETUP:
3154 ret = SetupDeviceInstance(pszDeviceInstance1,
3155 ulMinorAction);
3156 break;
3157
3158 case PNP_DEVINST_ENABLE:
3159 ret = EnableDeviceInstance(pszDeviceInstance1);
3160 break;
3161
3162 case PNP_DEVINST_REENUMERATE:
3163 ret = ReenumerateDeviceInstance(pszDeviceInstance1,
3164 ulMinorAction);
3165 break;
3166
3167 default:
3168 DPRINT1("Unknown device action %lu: not implemented\n", ulMajorAction);
3169 ret = CR_CALL_NOT_IMPLEMENTED;
3170 }
3171
3172 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
3173
3174 return ret;
3175 }
3176
3177
3178 /* Function 30 */
3179 DWORD
3180 WINAPI
3181 PNP_GetDeviceStatus(
3182 handle_t hBinding,
3183 LPWSTR pDeviceID,
3184 DWORD *pulStatus,
3185 DWORD *pulProblem,
3186 DWORD ulFlags)
3187 {
3188 UNREFERENCED_PARAMETER(hBinding);
3189 UNREFERENCED_PARAMETER(ulFlags);
3190
3191 DPRINT("PNP_GetDeviceStatus(%p %S %p %p)\n",
3192 hBinding, pDeviceID, pulStatus, pulProblem, ulFlags);
3193
3194 if (!IsValidDeviceInstanceID(pDeviceID))
3195 return CR_INVALID_DEVINST;
3196
3197 return GetDeviceStatus(pDeviceID, pulStatus, pulProblem);
3198 }
3199
3200
3201 /* Function 31 */
3202 DWORD
3203 WINAPI
3204 PNP_SetDeviceProblem(
3205 handle_t hBinding,
3206 LPWSTR pDeviceID,
3207 DWORD ulProblem,
3208 DWORD ulFlags)
3209 {
3210 UNIMPLEMENTED;
3211 return CR_CALL_NOT_IMPLEMENTED;
3212 }
3213
3214
3215 /* Function 32 */
3216 DWORD
3217 WINAPI
3218 PNP_DisableDevInst(
3219 handle_t hBinding,
3220 LPWSTR pDeviceID,
3221 PPNP_VETO_TYPE pVetoType,
3222 LPWSTR pszVetoName,
3223 DWORD ulNameLength,
3224 DWORD ulFlags)
3225 {
3226 UNREFERENCED_PARAMETER(hBinding);
3227
3228 DPRINT1("PNP_DisableDevInst(%p %S %p %p %lu 0x%08lx)\n",
3229 hBinding, pDeviceID, pVetoType, pszVetoName, ulNameLength, ulFlags);
3230
3231 if (ulFlags & ~CM_DISABLE_BITS)
3232 return CR_INVALID_FLAG;
3233
3234 if (!IsValidDeviceInstanceID(pDeviceID) ||
3235 IsRootDeviceInstanceID(pDeviceID))
3236 return CR_INVALID_DEVINST;
3237
3238 return DisableDeviceInstance(pDeviceID,
3239 pVetoType,
3240 pszVetoName,
3241 ulNameLength);
3242 }
3243
3244
3245 /* Function 33 */
3246 DWORD
3247 WINAPI
3248 PNP_UninstallDevInst(
3249 handle_t hBinding,
3250 LPWSTR pDeviceID,
3251 DWORD ulFlags)
3252 {
3253 UNIMPLEMENTED;
3254 return CR_CALL_NOT_IMPLEMENTED;
3255 }
3256
3257
3258 static BOOL
3259 CheckForDeviceId(LPWSTR lpDeviceIdList,
3260 LPWSTR lpDeviceId)
3261 {
3262 LPWSTR lpPtr;
3263 DWORD dwLength;
3264
3265 lpPtr = lpDeviceIdList;
3266 while (*lpPtr != 0)
3267 {
3268 dwLength = wcslen(lpPtr);
3269 if (0 == _wcsicmp(lpPtr, lpDeviceId))
3270 return TRUE;
3271
3272 lpPtr += (dwLength + 1);
3273 }
3274
3275 return FALSE;
3276 }
3277
3278
3279 static VOID
3280 AppendDeviceId(LPWSTR lpDeviceIdList,
3281 LPDWORD lpDeviceIdListSize,
3282 LPWSTR lpDeviceId)
3283 {
3284 DWORD dwLen;
3285 DWORD dwPos;
3286
3287 dwLen = wcslen(lpDeviceId);
3288 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
3289
3290 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
3291
3292 dwPos += (dwLen + 1);
3293
3294 lpDeviceIdList[dwPos] = 0;
3295
3296 *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
3297 }
3298
3299
3300 /* Function 34 */
3301 DWORD
3302 WINAPI
3303 PNP_AddID(
3304 handle_t hBinding,
3305 LPWSTR pszDeviceID,
3306 LPWSTR pszID,
3307 DWORD ulFlags)
3308 {
3309 CONFIGRET ret = CR_SUCCESS;
3310 HKEY hDeviceKey;
3311 LPWSTR pszSubKey;
3312 DWORD dwDeviceIdListSize;
3313 DWORD dwNewDeviceIdSize;
3314 WCHAR * pszDeviceIdList = NULL;
3315
3316 UNREFERENCED_PARAMETER(hBinding);
3317
3318 DPRINT("PNP_AddID(%p %S %S 0x%08lx)\n",
3319 hBinding, pszDeviceID, pszID, ulFlags);
3320
3321 if (RegOpenKeyExW(hEnumKey,
3322 pszDeviceID,
3323 0,
3324 KEY_QUERY_VALUE | KEY_SET_VALUE,
3325 &hDeviceKey) != ERROR_SUCCESS)
3326 {
3327 DPRINT("Failed to open the device key!\n");
3328 return CR_INVALID_DEVNODE;
3329 }
3330
3331 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
3332
3333 if (RegQueryValueExW(hDeviceKey,
3334 pszSubKey,
3335 NULL,
3336 NULL,
3337 NULL,
3338 &dwDeviceIdListSize) != ERROR_SUCCESS)
3339 {
3340 DPRINT("Failed to query the desired ID string!\n");
3341 ret = CR_REGISTRY_ERROR;
3342 goto Done;
3343 }
3344
3345 dwNewDeviceIdSize = lstrlenW(pszDeviceID);
3346 if (!dwNewDeviceIdSize)
3347 {
3348 ret = CR_INVALID_POINTER;
3349 goto Done;
3350 }
3351
3352 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR);
3353
3354 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize);
3355 if (!pszDeviceIdList)
3356 {
3357 DPRINT("Failed to allocate memory for the desired ID string!\n");
3358 ret = CR_OUT_OF_MEMORY;
3359 goto Done;
3360 }
3361
3362 if (RegQueryValueExW(hDeviceKey,
3363 pszSubKey,
3364 NULL,
3365 NULL,
3366 (LPBYTE)pszDeviceIdList,
3367 &dwDeviceIdListSize) != ERROR_SUCCESS)
3368 {
3369 DPRINT("Failed to query the desired ID string!\n");
3370 ret = CR_REGISTRY_ERROR;
3371 goto Done;
3372 }
3373
3374 /* Check whether the device ID is already in use */
3375 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID))
3376 {
3377 DPRINT("Device ID was found in the ID string!\n");
3378 ret = CR_SUCCESS;
3379 goto Done;
3380 }
3381
3382 /* Append the Device ID */
3383 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID);
3384
3385 if (RegSetValueExW(hDeviceKey,
3386 pszSubKey,
3387 0,
3388 REG_MULTI_SZ,
3389 (LPBYTE)pszDeviceIdList,
3390 dwDeviceIdListSize) != ERROR_SUCCESS)
3391 {
3392 DPRINT("Failed to set the desired ID string!\n");
3393 ret = CR_REGISTRY_ERROR;
3394 }
3395
3396 Done:
3397 RegCloseKey(hDeviceKey);
3398 if (pszDeviceIdList)
3399 HeapFree(GetProcessHeap(), 0, pszDeviceIdList);
3400
3401 DPRINT("PNP_AddID() done (returns %lx)\n", ret);
3402
3403 return ret;
3404 }
3405
3406
3407 /* Function 35 */
3408 DWORD
3409 WINAPI
3410 PNP_RegisterDriver(
3411 handle_t hBinding,
3412 LPWSTR pszDeviceID,
3413 DWORD ulFlags)
3414 {
3415 DPRINT("PNP_RegisterDriver(%p %S 0x%lx)\n",
3416 hBinding, pszDeviceID, ulFlags);
3417
3418 if (ulFlags & ~CM_REGISTER_DEVICE_DRIVER_BITS)
3419 return CR_INVALID_FLAG;
3420
3421 if (!IsValidDeviceInstanceID(pszDeviceID))
3422 return CR_INVALID_DEVINST;
3423
3424 SetDeviceStatus(pszDeviceID, 0, 0);
3425
3426 return CR_SUCCESS;
3427 }
3428
3429
3430 /* Function 36 */
3431 DWORD
3432 WINAPI
3433 PNP_QueryRemove(
3434 handle_t hBinding,
3435 LPWSTR pszDeviceID,
3436 PPNP_VETO_TYPE pVetoType,
3437 LPWSTR pszVetoName,
3438 DWORD ulNameLength,
3439 DWORD ulFlags)
3440 {
3441 PLUGPLAY_CONTROL_QUERY_REMOVE_DATA PlugPlayData;
3442 NTSTATUS Status;
3443 DWORD ret = CR_SUCCESS;
3444
3445 DPRINT1("PNP_QueryRemove(%p %S %p %p %lu 0x%lx)\n",
3446 hBinding, pszDeviceID, pVetoType, pszVetoName,
3447 ulNameLength, ulFlags);
3448
3449 if (ulFlags & ~CM_REMOVE_BITS)
3450 return CR_INVALID_FLAG;
3451
3452 if (!IsValidDeviceInstanceID(pszDeviceID) ||
3453 IsRootDeviceInstanceID(pszDeviceID))
3454 return CR_INVALID_DEVINST;
3455
3456 if (pVetoType != NULL)
3457 *pVetoType = PNP_VetoTypeUnknown;
3458
3459 if (pszVetoName != NULL && ulNameLength > 0)
3460 *pszVetoName = UNICODE_NULL;
3461
3462 RtlZeroMemory(&PlugPlayData, sizeof(PlugPlayData));
3463 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
3464 pszDeviceID);
3465 PlugPlayData.VetoName = pszVetoName;
3466 PlugPlayData.NameLength = ulNameLength;
3467 // PlugPlayData.Flags =
3468
3469 Status = NtPlugPlayControl(PlugPlayControlQueryAndRemoveDevice,
3470 &PlugPlayData,
3471 sizeof(PlugPlayData));
3472 if (!NT_SUCCESS(Status))
3473 ret = NtStatusToCrError(Status);
3474
3475 return ret;
3476 }
3477
3478
3479 /* Function 37 */
3480 DWORD
3481 WINAPI
3482 PNP_RequestDeviceEject(
3483 handle_t hBinding,
3484 LPWSTR pszDeviceID,
3485 PPNP_VETO_TYPE pVetoType,
3486 LPWSTR pszVetoName,
3487 DWORD ulNameLength,
3488 DWORD ulFlags)
3489 {
3490 PLUGPLAY_CONTROL_QUERY_REMOVE_DATA PlugPlayData;
3491 NTSTATUS Status;
3492 DWORD ret = CR_SUCCESS;
3493
3494 DPRINT1("PNP_RequestDeviceEject(%p %S %p %p %lu 0x%lx)\n",
3495 hBinding, pszDeviceID, pVetoType, pszVetoName,
3496 ulNameLength, ulFlags);
3497
3498 if (ulFlags != 0)
3499 return CR_INVALID_FLAG;
3500
3501 if (!IsValidDeviceInstanceID(pszDeviceID))
3502 return CR_INVALID_DEVINST;