cf9ba100f1b76db5effb386bcd04c5832dce4006
[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 ResetDeviceData;
3085 CONFIGRET ret = CR_SUCCESS;
3086 NTSTATUS Status;
3087
3088 DPRINT("Enable device instance %S\n", pszDeviceInstance);
3089
3090 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance,
3091 pszDeviceInstance);
3092 Status = NtPlugPlayControl(PlugPlayControlResetDevice,
3093 &ResetDeviceData,
3094 sizeof(PLUGPLAY_CONTROL_DEVICE_CONTROL_DATA));
3095 if (!NT_SUCCESS(Status))
3096 ret = NtStatusToCrError(Status);
3097
3098 return ret;
3099 }
3100
3101
3102 static CONFIGRET
3103 ReenumerateDeviceInstance(
3104 _In_ LPWSTR pszDeviceInstance,
3105 _In_ ULONG ulMinorAction)
3106 {
3107 PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA EnumerateDeviceData;
3108 CONFIGRET ret = CR_SUCCESS;
3109 NTSTATUS Status;
3110
3111 DPRINT1("ReenumerateDeviceInstance(%S 0x%08lx)\n",
3112 pszDeviceInstance, ulMinorAction);
3113
3114 if (ulMinorAction & ~CM_REENUMERATE_BITS)
3115 return CR_INVALID_FLAG;
3116
3117 if (ulMinorAction & CM_REENUMERATE_RETRY_INSTALLATION)
3118 {
3119 DPRINT1("CM_REENUMERATE_RETRY_INSTALLATION not implemented!\n");
3120 }
3121
3122 RtlInitUnicodeString(&EnumerateDeviceData.DeviceInstance,
3123 pszDeviceInstance);
3124 EnumerateDeviceData.Flags = 0;
3125
3126 Status = NtPlugPlayControl(PlugPlayControlEnumerateDevice,
3127 &EnumerateDeviceData,
3128 sizeof(PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA));
3129 if (!NT_SUCCESS(Status))
3130 ret = NtStatusToCrError(Status);
3131
3132 return ret;
3133 }
3134
3135
3136 /* Function 29 */
3137 DWORD
3138 WINAPI
3139 PNP_DeviceInstanceAction(
3140 handle_t hBinding,
3141 DWORD ulMajorAction,
3142 DWORD ulMinorAction,
3143 LPWSTR pszDeviceInstance1,
3144 LPWSTR pszDeviceInstance2)
3145 {
3146 CONFIGRET ret = CR_SUCCESS;
3147
3148 UNREFERENCED_PARAMETER(hBinding);
3149
3150 DPRINT("PNP_DeviceInstanceAction(%p %lu 0x%08lx %S %S)\n",
3151 hBinding, ulMajorAction, ulMinorAction,
3152 pszDeviceInstance1, pszDeviceInstance2);
3153
3154 switch (ulMajorAction)
3155 {
3156 case PNP_DEVINST_SETUP:
3157 ret = SetupDeviceInstance(pszDeviceInstance1,
3158 ulMinorAction);
3159 break;
3160
3161 case PNP_DEVINST_ENABLE:
3162 ret = EnableDeviceInstance(pszDeviceInstance1);
3163 break;
3164
3165 case PNP_DEVINST_REENUMERATE:
3166 ret = ReenumerateDeviceInstance(pszDeviceInstance1,
3167 ulMinorAction);
3168 break;
3169
3170 default:
3171 DPRINT1("Unknown device action %lu: not implemented\n", ulMajorAction);
3172 ret = CR_CALL_NOT_IMPLEMENTED;
3173 }
3174
3175 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
3176
3177 return ret;
3178 }
3179
3180
3181 /* Function 30 */
3182 DWORD
3183 WINAPI
3184 PNP_GetDeviceStatus(
3185 handle_t hBinding,
3186 LPWSTR pDeviceID,
3187 DWORD *pulStatus,
3188 DWORD *pulProblem,
3189 DWORD ulFlags)
3190 {
3191 UNREFERENCED_PARAMETER(hBinding);
3192 UNREFERENCED_PARAMETER(ulFlags);
3193
3194 DPRINT("PNP_GetDeviceStatus(%p %S %p %p)\n",
3195 hBinding, pDeviceID, pulStatus, pulProblem, ulFlags);
3196
3197 if (!IsValidDeviceInstanceID(pDeviceID))
3198 return CR_INVALID_DEVINST;
3199
3200 return GetDeviceStatus(pDeviceID, pulStatus, pulProblem);
3201 }
3202
3203
3204 /* Function 31 */
3205 DWORD
3206 WINAPI
3207 PNP_SetDeviceProblem(
3208 handle_t hBinding,
3209 LPWSTR pDeviceID,
3210 DWORD ulProblem,
3211 DWORD ulFlags)
3212 {
3213 UNIMPLEMENTED;
3214 return CR_CALL_NOT_IMPLEMENTED;
3215 }
3216
3217
3218 /* Function 32 */
3219 DWORD
3220 WINAPI
3221 PNP_DisableDevInst(
3222 handle_t hBinding,
3223 LPWSTR pDeviceID,
3224 PPNP_VETO_TYPE pVetoType,
3225 LPWSTR pszVetoName,
3226 DWORD ulNameLength,
3227 DWORD ulFlags)
3228 {
3229 UNREFERENCED_PARAMETER(hBinding);
3230
3231 DPRINT1("PNP_DisableDevInst(%p %S %p %p %lu 0x%08lx)\n",
3232 hBinding, pDeviceID, pVetoType, pszVetoName, ulNameLength, ulFlags);
3233
3234 if (ulFlags & ~CM_DISABLE_BITS)
3235 return CR_INVALID_FLAG;
3236
3237 if (!IsValidDeviceInstanceID(pDeviceID) ||
3238 IsRootDeviceInstanceID(pDeviceID))
3239 return CR_INVALID_DEVINST;
3240
3241 return DisableDeviceInstance(pDeviceID,
3242 pVetoType,
3243 pszVetoName,
3244 ulNameLength);
3245 }
3246
3247
3248 /* Function 33 */
3249 DWORD
3250 WINAPI
3251 PNP_UninstallDevInst(
3252 handle_t hBinding,
3253 LPWSTR pDeviceID,
3254 DWORD ulFlags)
3255 {
3256 UNIMPLEMENTED;
3257 return CR_CALL_NOT_IMPLEMENTED;
3258 }
3259
3260
3261 static BOOL
3262 CheckForDeviceId(LPWSTR lpDeviceIdList,
3263 LPWSTR lpDeviceId)
3264 {
3265 LPWSTR lpPtr;
3266 DWORD dwLength;
3267
3268 lpPtr = lpDeviceIdList;
3269 while (*lpPtr != 0)
3270 {
3271 dwLength = wcslen(lpPtr);
3272 if (0 == _wcsicmp(lpPtr, lpDeviceId))
3273 return TRUE;
3274
3275 lpPtr += (dwLength + 1);
3276 }
3277
3278 return FALSE;
3279 }
3280
3281
3282 static VOID
3283 AppendDeviceId(LPWSTR lpDeviceIdList,
3284 LPDWORD lpDeviceIdListSize,
3285 LPWSTR lpDeviceId)
3286 {
3287 DWORD dwLen;
3288 DWORD dwPos;
3289
3290 dwLen = wcslen(lpDeviceId);
3291 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
3292
3293 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
3294
3295 dwPos += (dwLen + 1);
3296
3297 lpDeviceIdList[dwPos] = 0;
3298
3299 *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
3300 }
3301
3302
3303 /* Function 34 */
3304 DWORD
3305 WINAPI
3306 PNP_AddID(
3307 handle_t hBinding,
3308 LPWSTR pszDeviceID,
3309 LPWSTR pszID,
3310 DWORD ulFlags)
3311 {
3312 CONFIGRET ret = CR_SUCCESS;
3313 HKEY hDeviceKey;
3314 LPWSTR pszSubKey;
3315 DWORD dwDeviceIdListSize;
3316 DWORD dwNewDeviceIdSize;
3317 WCHAR * pszDeviceIdList = NULL;
3318
3319 UNREFERENCED_PARAMETER(hBinding);
3320
3321 DPRINT("PNP_AddID(%p %S %S 0x%08lx)\n",
3322 hBinding, pszDeviceID, pszID, ulFlags);
3323
3324 if (RegOpenKeyExW(hEnumKey,
3325 pszDeviceID,
3326 0,
3327 KEY_QUERY_VALUE | KEY_SET_VALUE,
3328 &hDeviceKey) != ERROR_SUCCESS)
3329 {
3330 DPRINT("Failed to open the device key!\n");
3331 return CR_INVALID_DEVNODE;
3332 }
3333
3334 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
3335
3336 if (RegQueryValueExW(hDeviceKey,
3337 pszSubKey,
3338 NULL,
3339 NULL,
3340 NULL,
3341 &dwDeviceIdListSize) != ERROR_SUCCESS)
3342 {
3343 DPRINT("Failed to query the desired ID string!\n");
3344 ret = CR_REGISTRY_ERROR;
3345 goto Done;
3346 }
3347
3348 dwNewDeviceIdSize = lstrlenW(pszDeviceID);
3349 if (!dwNewDeviceIdSize)
3350 {
3351 ret = CR_INVALID_POINTER;
3352 goto Done;
3353 }
3354
3355 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR);
3356
3357 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize);
3358 if (!pszDeviceIdList)
3359 {
3360 DPRINT("Failed to allocate memory for the desired ID string!\n");
3361 ret = CR_OUT_OF_MEMORY;
3362 goto Done;
3363 }
3364
3365 if (RegQueryValueExW(hDeviceKey,
3366 pszSubKey,
3367 NULL,
3368 NULL,
3369 (LPBYTE)pszDeviceIdList,
3370 &dwDeviceIdListSize) != ERROR_SUCCESS)
3371 {
3372 DPRINT("Failed to query the desired ID string!\n");
3373 ret = CR_REGISTRY_ERROR;
3374 goto Done;
3375 }
3376
3377 /* Check whether the device ID is already in use */
3378 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID))
3379 {
3380 DPRINT("Device ID was found in the ID string!\n");
3381 ret = CR_SUCCESS;
3382 goto Done;
3383 }
3384
3385 /* Append the Device ID */
3386 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID);
3387
3388 if (RegSetValueExW(hDeviceKey,
3389 pszSubKey,
3390 0,
3391 REG_MULTI_SZ,
3392 (LPBYTE)pszDeviceIdList,
3393 dwDeviceIdListSize) != ERROR_SUCCESS)
3394 {
3395 DPRINT("Failed to set the desired ID string!\n");
3396 ret = CR_REGISTRY_ERROR;
3397 }
3398
3399 Done:
3400 RegCloseKey(hDeviceKey);
3401 if (pszDeviceIdList)
3402 HeapFree(GetProcessHeap(), 0, pszDeviceIdList);
3403
3404 DPRINT("PNP_AddID() done (returns %lx)\n", ret);
3405
3406 return ret;
3407 }
3408
3409
3410 /* Function 35 */
3411 DWORD
3412 WINAPI
3413 PNP_RegisterDriver(
3414 handle_t hBinding,
3415 LPWSTR pszDeviceID,
3416 DWORD ulFlags)
3417 {
3418 DPRINT("PNP_RegisterDriver(%p %S 0x%lx)\n",
3419 hBinding, pszDeviceID, ulFlags);
3420
3421 if (ulFlags & ~CM_REGISTER_DEVICE_DRIVER_BITS)
3422 return CR_INVALID_FLAG;
3423
3424 if (!IsValidDeviceInstanceID(pszDeviceID))
3425 return CR_INVALID_DEVINST;
3426
3427 SetDeviceStatus(pszDeviceID, 0, 0);
3428
3429 return CR_SUCCESS;
3430 }
3431
3432
3433 /* Function 36 */
3434 DWORD
3435 WINAPI
3436 PNP_QueryRemove(
3437 handle_t hBinding,
3438 LPWSTR pszDeviceID,
3439 PPNP_VETO_TYPE pVetoType,
3440 LPWSTR pszVetoName,
3441 DWORD ulNameLength,
3442 DWORD ulFlags)
3443 {
3444 PLUGPLAY_CONTROL_QUERY_REMOVE_DATA PlugPlayData;
3445 NTSTATUS Status;
3446 DWORD ret = CR_SUCCESS;
3447
3448 DPRINT1("PNP_QueryRemove(%p %S %p %p %lu 0x%lx)\n",
3449 hBinding, pszDeviceID, pVetoType, pszVetoName,
3450 ulNameLength, ulFlags);
3451
3452 if (ulFlags & ~CM_REMOVE_BITS)
3453 return CR_INVALID_FLAG;
3454
3455 if (!IsValidDeviceInstanceID(pszDeviceID) ||
3456 IsRootDeviceInstanceID(pszDeviceID))
3457 return CR_INVALID_DEVINST;
3458
3459 if (pVetoType != NULL)
3460 *pVetoType = PNP_VetoTypeUnknown;
3461
3462 if (pszVetoName != NULL && ulNameLength > 0)
3463 *pszVetoName = UNICODE_NULL;
3464
3465 RtlZeroMemory(&PlugPlayData, sizeof(PlugPlayData));
3466 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
3467 pszDeviceID);
3468 PlugPlayData.VetoName = pszVetoName;
3469 PlugPlayData.NameLength = ulNameLength;
3470 // PlugPlayData.Flags =
3471
3472 Status = NtPlugPlayControl(PlugPlayControlQueryAndRemoveDevice,
3473 &PlugPlayData,
3474 sizeof(PlugPlayData));
3475 if (!NT_SUCCESS(Status))
3476 ret = NtStatusToCrError(Status);
3477
3478 return ret;
3479 }
3480
3481
3482 /* Function 37 */
3483 DWORD
3484 WINAPI
3485 PNP_RequestDeviceEject(
3486 handle_t hBinding,
3487 LPWSTR pszDeviceID,
3488 PPNP_VETO_TYPE pVetoType,
3489 LPWSTR pszVetoName,
3490 DWORD ulNameLength,
3491 DWORD ulFlags)
3492 {
3493 PLUGPLAY_CONTROL_QUERY_REMOVE_DATA PlugPlayData;
3494 NTSTATUS Status;
3495 DWORD ret = CR_SUCCESS;
3496
3497 DPRINT1("PNP_RequestDeviceEject(%p %S %p %p %lu 0x%lx)\n",
3498 hBinding, pszDeviceID, pVetoType, pszVetoName,
3499 ulNameLength, ulFlags);
3500
3501 if (ulFlags != 0)
3502 return CR_INVALID_FLAG;
3503
3504 if (!IsValidDeviceInstanceID(pszDeviceID))
3505 return CR_INVALID_DEVINST;
3506
3507 if (pVetoType != NULL)
3508 *pVetoType = PNP_VetoTypeUnknown;
3509
3510 if (pszVetoName != NULL && ulNameLength > 0)
3511 *pszVetoName = UNICODE_NULL;
3512
3513 RtlZeroMemory(&PlugPlayData, sizeof(PlugPlayData));
3514 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
3515 pszDeviceID);
3516 PlugPlayData.VetoName = pszVetoName;
3517 PlugPlayData.NameLength = ulNameLength;
3518 // PlugPlayData.Flags =
3519
3520 Status = NtPlugPlayControl(PlugPlayControlQueryAndRemoveDevice,
3521 &PlugPlayData,
3522 sizeof(PlugPlayData));
3523 if (!NT_SUCCESS(Status))
3524 ret = NtStatusToCrError(Status);
3525
3526 return ret;
3527 }
3528
3529
3530 /* Function 38 */
3531 CONFIGRET
3532 WINAPI
3533 PNP_IsDockStationPresent(
3534 handle_t hBinding,
3535 BOOL *Present)
3536 {
3537 HKEY hKey;
3538 DWORD dwType;
3539 DWORD dwValue;
3540 DWORD dwSize;
3541 CONFIGRET ret = CR_SUCCESS;
3542
3543 UNREFERENCED_PARAMETER(hBinding);
3544
3545 DPRINT1("PNP_IsDockStationPresent(%p %p)\n",
3546 hBinding, Present);
3547
3548 *Present = FALSE;
3549
3550 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
3551 L"CurrentDockInfo",
3552 0,
3553 KEY_READ,
3554 &hKey) != ERROR_SUCCESS)
3555 return CR_REGISTRY_ERROR;
3556
3557 dwSize = sizeof(DWORD);
3558 if (RegQueryValueExW(hKey,
3559 L"DockingState",
3560 NULL,
3561 &dwType,
3562 (LPBYTE)&dwValue,
3563 &dwSize) != ERROR_SUCCESS)
3564 ret = CR_REGISTRY_ERROR;
3565
3566 RegCloseKey(hKey);
3567
3568 if (ret == CR_SUCCESS)
3569 {
3570 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
3571 {
3572 ret = CR_REGISTRY_ERROR;
3573 }
3574 else if (dwValue != 0)
3575 {
3576 *Present = TRUE;
3577 }
3578 }
3579
3580 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
3581
3582 return ret;
3583 }
3584
3585
3586 /* Function 39 */
3587 DWORD
3588 WINAPI
3589 PNP_RequestEjectPC(
3590 handle_t hBinding)
3591 {
3592 WCHAR szDockDeviceInstance[MAX_DEVICE_ID_LEN];
3593 PLUGPLAY_CONTROL_RETRIEVE_DOCK_DATA DockData;
3594 NTSTATUS Status;
3595
3596 DPRINT("PNP_RequestEjectPC(%p)\n", hBinding);
3597
3598 /* Retrieve the dock device */
3599 DockData.DeviceInstanceLength = ARRAYSIZE(szDockDeviceInstance);
3600 DockData.DeviceInstance = szDockDeviceInstance;
3601
3602 Status = NtPlugPlayControl(PlugPlayControlRetrieveDock,
3603 &DockData,
3604 sizeof(DockData));
3605 if (!NT_SUCCESS(Status))
3606 return NtStatusToCrError(Status);
3607
3608 /* Eject the dock device */
3609 return PNP_RequestDeviceEject(hBinding,
3610 szDockDeviceInstance,
3611 NULL,
3612 NULL,
3613 0,
3614 0);
3615 }
3616
3617
3618 /* Function 40 */
3619 DWORD
3620 WINAPI
3621 PNP_HwProfFlags(
3622 handle_t hBinding,
3623 DWORD ulAction,
3624 LPWSTR pDeviceID,
3625 DWORD ulConfig,
3626 DWORD *pulValue,
3627 PPNP_VETO_TYPE pVetoType,
3628 LPWSTR pszVetoName,
3629 DWORD ulNameLength,
3630 DWORD ulFlags)
3631 {
3632 CONFIGRET ret = CR_SUCCESS;
3633 WCHAR szKeyName[MAX_PATH];
3634 HKEY hKey;
3635 HKEY hDeviceKey;
3636 DWORD dwSize;
3637
3638 UNREFERENCED_PARAMETER(hBinding);
3639
3640 DPRINT("PNP_HwProfFlags() called\n");
3641
3642 if (!IsValidDeviceInstanceID(pDeviceID))
3643 return CR_INVALID_DEVINST;
3644
3645 if (ulConfig == 0)
3646 {
3647 wcscpy(szKeyName,
3648 L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
3649 }
3650 else
3651 {
3652 swprintf(szKeyName,
3653 L"System\\CurrentControlSet\\HardwareProfiles\\%04lu\\System\\CurrentControlSet\\Enum",
3654 ulConfig);
3655 }
3656
3657 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3658 szKeyName,
3659 0,
3660 KEY_QUERY_VALUE,
3661 &hKey) != ERROR_SUCCESS)
3662 return CR_REGISTRY_ERROR;
3663
3664 if (ulAction == PNP_GET_HWPROFFLAGS)
3665 {
3666 if (RegOpenKeyExW(hKey,
3667 pDeviceID,
3668 0,
3669 KEY_QUERY_VALUE,
3670 &hDeviceKey) != ERROR_SUCCESS)
3671 {
3672 *pulValue = 0;
3673 }
3674 else
3675 {
3676 dwSize = sizeof(DWORD);
3677 if (RegQueryValueExW(hDeviceKey,
3678 L"CSConfigFlags",
3679 NULL,
3680 NULL,
3681 (LPBYTE)pulValue,
3682 &dwSize) != ERROR_SUCCESS)
3683 {
3684 *pulValue = 0;
3685 }
3686
3687 RegCloseKey(hDeviceKey);
3688 }
3689 }
3690 else if (ulAction == PNP_SET_HWPROFFLAGS)
3691 {
3692 /* FIXME: not implemented yet */
3693 ret = CR_CALL_NOT_IMPLEMENTED;
3694 }
3695
3696 RegCloseKey(hKey);
3697
3698 return ret;
3699 }
3700
3701
3702 /* Function 41 */
3703 DWORD
3704 WINAPI
3705 PNP_GetHwProfInfo(
3706 handle_t hBinding,
3707 DWORD ulIndex,
3708 HWPROFILEINFO *pHWProfileInfo,
3709 DWORD ulProfileInfoSize,
3710 DWORD ulFlags)
3711 {
3712 WCHAR szProfileName[5];
3713 HKEY hKeyConfig = NULL;
3714 HKEY hKeyProfiles = NULL;
3715 HKEY hKeyProfile = NULL;
3716 DWORD dwDisposition;
3717 DWORD dwSize;
3718 LONG lError;
3719 CONFIGRET ret = CR_SUCCESS;
3720
3721 UNREFERENCED_PARAMETER(hBinding);
3722
3723 DPRINT("PNP_GetHwProfInfo() called\n");
3724
3725 if (ulProfileInfoSize == 0)
3726 {
3727 ret = CR_INVALID_DATA;
3728 goto done;
3729 }
3730
3731 if (ulFlags != 0)
3732 {
3733 ret = CR_INVALID_FLAG;
3734 goto done;
3735 }
3736
3737 /* Initialize the profile information */
3738 pHWProfileInfo->HWPI_ulHWProfile = 0;
3739 pHWProfileInfo->HWPI_szFriendlyName[0] = 0;
3740 pHWProfileInfo->HWPI_dwFlags = 0;
3741
3742 /* Open the 'IDConfigDB' key */
3743 lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
3744 L"System\\CurrentControlSet\\Control\\IDConfigDB",
3745 0,
3746 NULL,
3747 REG_OPTION_NON_VOLATILE,
3748 KEY_QUERY_VALUE,
3749 NULL,
3750 &hKeyConfig,
3751 &dwDisposition);
3752 if (lError != ERROR_SUCCESS)
3753 {
3754 ret = CR_REGISTRY_ERROR;
3755 goto done;
3756 }
3757
3758 /* Open the 'Hardware Profiles' subkey */
3759 lError = RegCreateKeyExW(hKeyConfig,
3760 L"Hardware Profiles",
3761 0,
3762 NULL,
3763 REG_OPTION_NON_VOLATILE,
3764 KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
3765 NULL,
3766 &hKeyProfiles,
3767 &dwDisposition);
3768 if (lError != ERROR_SUCCESS)
3769 {
3770 ret = CR_REGISTRY_ERROR;
3771 goto done;
3772 }
3773
3774 if (ulIndex == (ULONG)-1)
3775 {
3776 dwSize = sizeof(ULONG);
3777 lError = RegQueryValueExW(hKeyConfig,
3778 L"CurrentConfig",
3779 NULL,
3780 NULL,
3781 (LPBYTE)&pHWProfileInfo->HWPI_ulHWProfile,
3782 &dwSize);
3783 if (lError != ERROR_SUCCESS)
3784 {
3785 pHWProfileInfo->HWPI_ulHWProfile = 0;
3786 ret = CR_REGISTRY_ERROR;
3787 goto done;
3788 }
3789 }
3790 else
3791 {
3792 /* FIXME: not implemented yet */
3793 ret = CR_CALL_NOT_IMPLEMENTED;
3794 goto done;
3795 }
3796
3797 swprintf(szProfileName, L"%04lu", pHWProfileInfo->HWPI_ulHWProfile);
3798
3799 lError = RegOpenKeyExW(hKeyProfiles,
3800 szProfileName,
3801 0,
3802 KEY_QUERY_VALUE,
3803 &hKeyProfile);
3804 if (lError != ERROR_SUCCESS)
3805 {
3806 ret = CR_REGISTRY_ERROR;
3807 goto done;
3808 }
3809
3810 dwSize = sizeof(pHWProfileInfo->HWPI_szFriendlyName);
3811 lError = RegQueryValueExW(hKeyProfile,
3812 L"FriendlyName",
3813 NULL,
3814 NULL,
3815 (LPBYTE)&pHWProfileInfo->HWPI_szFriendlyName,
3816 &dwSize);
3817 if (lError != ERROR_SUCCESS)
3818 {
3819 ret = CR_REGISTRY_ERROR;
3820 goto done;
3821 }
3822
3823 done:
3824 if (hKeyProfile != NULL)
3825 RegCloseKey(hKeyProfile);
3826
3827 if (hKeyProfiles != NULL)
3828 RegCloseKey(hKeyProfiles);
3829
3830 if (hKeyConfig != NULL)
3831 RegCloseKey(hKeyConfig);
3832
3833 return ret;
3834 }
3835
3836
3837 /* Function 42 */
3838 DWORD
3839 WINAPI
3840 PNP_AddEmptyLogConf(
3841 handle_t hBinding,
3842 LPWSTR pDeviceID,
3843 DWORD ulPriority,
3844 DWORD *pulLogConfTag,
3845 DWORD ulFlags)
3846 {
3847 UNIMPLEMENTED;
3848 return CR_CALL_NOT_IMPLEMENTED;
3849 }
3850
3851
3852 /* Function 43 */
3853 DWORD
3854 WINAPI
3855 PNP_FreeLogConf(
3856 handle_t hBinding,
3857 LPWSTR pDeviceID,
3858 DWORD ulLogConfType,
3859 DWORD ulLogConfTag,
3860 DWORD ulFlags)
3861 {
3862 UNIMPLEMENTED;
3863 return CR_CALL_NOT_IMPLEMENTED;
3864 }
3865
3866
3867 /* Function 44 */
3868 DWORD
3869 WINAPI
3870 PNP_GetFirstLogConf(
3871 handle_t hBinding,
3872 LPWSTR pDeviceID,
3873 DWORD ulLogConfType,
3874 DWORD *pulLogConfTag,
3875 DWORD ulFlags)
3876 {
3877 HKEY hConfigKey = NULL;
3878 DWORD RegDataType = 0;
3879 ULONG ulDataSize = 0;
3880 LPBYTE lpData = NULL;
3881 CONFIGRET ret = CR_SUCCESS;
3882
3883 DPRINT("PNP_GetFirstLogConf(%p %S %lu %p 0x%08lx)\n",
3884 hBinding, pDeviceID, ulLogConfType, pulLogConfTag, ulFlags);
3885
3886 if (pulLogConfTag == NULL)
3887 return CR_INVALID_POINTER;
3888
3889 *pulLogConfTag = (DWORD)0;
3890
3891 if (ulFlags & ~LOG_CONF_BITS)
3892 return CR_INVALID_FLAG;
3893
3894 if (!IsValidDeviceInstanceID(pDeviceID))
3895 return CR_INVALID_DEVINST;
3896
3897 ret = OpenConfigurationKey(pDeviceID,
3898 &hConfigKey);
3899 if (ret != CR_SUCCESS)
3900 {
3901 DPRINT1("OpenConfigurationKey() failed (Error %lu)\n", ret);
3902 ret = CR_NO_MORE_LOG_CONF;
3903 goto done;
3904 }
3905
3906 ret = GetConfigurationData(hConfigKey,
3907 ulLogConfType,
3908 &RegDataType,
3909 &ulDataSize,
3910 &lpData);
3911 if (ret != CR_SUCCESS)
3912 {
3913 DPRINT1("GetConfigurationData() failed (Error %lu)\n", ret);
3914 ret = CR_NO_MORE_LOG_CONF;
3915 goto done;
3916 }
3917
3918 DPRINT("Data size %lu\n", ulDataSize);
3919 if (ulDataSize == 0 || lpData == NULL)
3920 {
3921 DPRINT1("No config data available!\n");
3922 ret = CR_NO_MORE_LOG_CONF;
3923 goto done;
3924 }
3925
3926 /* Get the first tag */
3927 if (RegDataType == REG_RESOURCE_LIST)
3928 {
3929 DPRINT("REG_RESOURCE_LIST\n");
3930
3931 DPRINT("ResourceList->Count %lu\n", ((PCM_RESOURCE_LIST)lpData)->Count);
3932 if (((PCM_RESOURCE_LIST)lpData)->Count == 0)
3933 {
3934 DPRINT1("No resource descriptors!\n");
3935 ret = CR_NO_MORE_LOG_CONF;
3936 goto done;
3937 }
3938
3939 DPRINT("lpData %p\n", lpData);
3940 DPRINT("&List[0] %p\n", &(((PCM_RESOURCE_LIST)lpData)->List[0]));
3941
3942 *pulLogConfTag = (DWORD)((DWORD_PTR)&(((PCM_RESOURCE_LIST)lpData)->List[0]) - (DWORD_PTR)lpData);
3943 DPRINT("Offset (Tag): 0x%08lx\n", *pulLogConfTag);
3944 }
3945 else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST)
3946 {
3947 DPRINT1("FIXME: REG_RESOURCE_REQUIREMENTS_LIST\n");
3948 /* FIXME */
3949 ret = CR_NO_MORE_LOG_CONF;
3950 goto done;
3951 }
3952
3953 done:
3954 if (lpData != NULL)
3955 HeapFree(GetProcessHeap(), 0, lpData);
3956
3957 if (hConfigKey != NULL)
3958 RegCloseKey(hConfigKey);
3959
3960 DPRINT("PNP_GetFirstLogConf() returns %lu\n", ret);
3961
3962 return ret;
3963 }
3964
3965
3966 /* Function 45 */
3967 DWORD
3968 WINAPI
3969 PNP_GetNextLogConf(
3970 handle_t hBinding,
3971 LPWSTR pDeviceID,
3972 DWORD ulLogConfType,
3973 DWORD ulCurrentTag,
3974 DWORD *pulNextTag,
3975 DWORD ulFlags)
3976 {
3977 HKEY hConfigKey = NULL;
3978 DWORD RegDataType = 0;
3979 ULONG ulDataSize = 0;
3980 LPBYTE lpData = NULL;
3981 CONFIGRET ret = CR_SUCCESS;
3982
3983 DPRINT("PNP_GetNextLogConf(%p %S %lu %ul %p 0x%08lx)\n",
3984 hBinding, pDeviceID, ulLogConfType, ulCurrentTag, pulNextTag, ulFlags);
3985
3986 if (pulNextTag == NULL)
3987 return CR_INVALID_POINTER;
3988
3989 *pulNextTag = (DWORD)0;
3990
3991 if (ulFlags != 0)
3992 return CR_INVALID_FLAG;
3993
3994 if (!IsValidDeviceInstanceID(pDeviceID))
3995 return CR_INVALID_DEVINST;
3996
3997 ret = OpenConfigurationKey(pDeviceID,
3998 &hConfigKey);
3999 if (ret != CR_SUCCESS)
4000 {
4001 DPRINT1("OpenConfigurationKey() failed (Error %lu)\n", ret);
4002 ret = CR_NO_MORE_LOG_CONF;
4003 goto done;
4004 }
4005
4006 ret = GetConfigurationData(hConfigKey,
4007 ulLogConfType,
4008 &RegDataType,
4009 &ulDataSize,
4010 &lpData);
4011 if (ret != CR_SUCCESS)
4012 {
4013 DPRINT1("GetConfigurationData() failed (Error %lu)\n", ret);
4014 ret = CR_NO_MORE_LOG_CONF;
4015 goto done;
4016 }
4017
4018 DPRINT("Data size %lu\n", ulDataSize);
4019
4020 if (ulDataSize == 0 || lpData == NULL)
4021 {
4022 DPRINT1("No config data available!\n");
4023 ret = CR_NO_MORE_LOG_CONF;
4024 goto done;
4025 }
4026
4027 /* FIXME: Get the next tag */
4028 if (RegDataType == REG_RESOURCE_LIST)
4029 {
4030 DPRINT1("FIXME: REG_RESOURCE_LIST\n");
4031 /* FIXME */
4032 ret = CR_NO_MORE_LOG_CONF;
4033 goto done;
4034 }
4035 else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST)
4036 {
4037 DPRINT1("FIXME: REG_RESOURCE_REQUIREMENTS_LIST\n");
4038 /* FIXME */
4039 ret = CR_NO_MORE_LOG_CONF;
4040 goto done;
4041 }
4042
4043 done:
4044 if (lpData != NULL)
4045 HeapFree(GetProcessHeap(), 0, lpData);
4046
4047 if (hConfigKey != NULL)
4048 RegCloseKey(hConfigKey);
4049
4050 DPRINT("PNP_GetNextLogConf() returns %lu\n", ret);
4051
4052 return ret;
4053 }
4054
4055
4056 /* Function 46 */
4057 DWORD
4058 WINAPI
4059 PNP_GetLogConfPriority(
4060 handle_t hBinding,
4061 LPWSTR pDeviceID,
4062 DWORD ulType,
4063 DWORD ulTag,
4064 DWORD *pPriority,
4065 DWORD ulFlags)
4066 {
4067 UNIMPLEMENTED;
4068 return CR_CALL_NOT_IMPLEMENTED;
4069 }
4070
4071
4072 /* Function 47 */
4073 DWORD
4074 WINAPI
4075 PNP_AddResDes(
4076 handle_t hBinding,
4077 LPWSTR pDeviceID,
4078 DWORD ulLogConfTag,
4079 DWORD ulLogConfType,
4080 RESOURCEID ResourceID,
4081 DWORD *pulResourceTag,
4082 BYTE *ResourceData,
4083 PNP_RPC_BUFFER_SIZE ResourceLen,
4084 DWORD ulFlags)
4085 {
4086 UNIMPLEMENTED;
4087 return CR_CALL_NOT_IMPLEMENTED;
4088 }
4089
4090
4091 /* Function 48 */
4092 DWORD
4093 WINAPI
4094 PNP_FreeResDes(
4095 handle_t hBinding,
4096 LPWSTR pDeviceID,
4097 DWORD ulLogConfTag,
4098 DWORD ulLogConfType,
4099 RESOURCEID ResourceID,
4100 DWORD ulResourceTag,
4101 DWORD *pulPreviousResType,
4102 DWORD *pulPreviousResTag,
4103 DWORD ulFlags)
4104 {
4105 UNIMPLEMENTED;
4106 return CR_CALL_NOT_IMPLEMENTED;
4107 }