[UMPNPMGR] rpcserver.c: Fix debug message copypastas (#2426)
[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 /* PUBLIC FUNCTIONS **********************************************************/
414
415 /* Function 0 */
416 DWORD
417 WINAPI
418 PNP_Disconnect(
419 handle_t hBinding)
420 {
421 UNREFERENCED_PARAMETER(hBinding);
422 return CR_SUCCESS;
423 }
424
425
426 /* Function 1 */
427 DWORD
428 WINAPI
429 PNP_Connect(
430 handle_t hBinding)
431 {
432 UNREFERENCED_PARAMETER(hBinding);
433 return CR_SUCCESS;
434 }
435
436
437 /* Function 2 */
438 DWORD
439 WINAPI
440 PNP_GetVersion(
441 handle_t hBinding,
442 WORD *pVersion)
443 {
444 UNREFERENCED_PARAMETER(hBinding);
445
446 DPRINT("PNP_GetVersion(%p %p)\n",
447 hBinding, pVersion);
448
449 *pVersion = 0x0400;
450
451 return CR_SUCCESS;
452 }
453
454
455 /* Function 3 */
456 DWORD
457 WINAPI
458 PNP_GetGlobalState(
459 handle_t hBinding,
460 DWORD *pulState,
461 DWORD ulFlags)
462 {
463 UNREFERENCED_PARAMETER(hBinding);
464 UNREFERENCED_PARAMETER(ulFlags);
465
466 DPRINT("PNP_GetGlobalState(%p %p 0x%08lx)\n",
467 hBinding, pulState, ulFlags);
468
469 *pulState = CM_GLOBAL_STATE_CAN_DO_UI | CM_GLOBAL_STATE_SERVICES_AVAILABLE;
470
471 return CR_SUCCESS;
472 }
473
474
475 /* Function 4 */
476 DWORD
477 WINAPI
478 PNP_InitDetection(
479 handle_t hBinding)
480 {
481 UNREFERENCED_PARAMETER(hBinding);
482
483 DPRINT("PNP_InitDetection(%p)\n",
484 hBinding);
485
486 return CR_SUCCESS;
487 }
488
489
490 /* Function 5 */
491 DWORD
492 WINAPI
493 PNP_ReportLogOn(
494 handle_t hBinding,
495 BOOL Admin,
496 DWORD ProcessId)
497 {
498 DWORD ReturnValue = CR_FAILURE;
499 HANDLE hProcess;
500
501 UNREFERENCED_PARAMETER(hBinding);
502 UNREFERENCED_PARAMETER(Admin);
503
504 DPRINT("PNP_ReportLogOn(%p %u, %u)\n",
505 hBinding, Admin, ProcessId);
506
507 /* Get the users token */
508 hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ProcessId);
509
510 if (!hProcess)
511 {
512 DPRINT1("OpenProcess failed with error %u\n", GetLastError());
513 goto cleanup;
514 }
515
516 if (hUserToken)
517 {
518 CloseHandle(hUserToken);
519 hUserToken = NULL;
520 }
521
522 if (!OpenProcessToken(hProcess, TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_QUERY, &hUserToken))
523 {
524 DPRINT1("OpenProcessToken failed with error %u\n", GetLastError());
525 goto cleanup;
526 }
527
528 /* Trigger the installer thread */
529 if (hInstallEvent)
530 SetEvent(hInstallEvent);
531
532 ReturnValue = CR_SUCCESS;
533
534 cleanup:
535 if (hProcess)
536 CloseHandle(hProcess);
537
538 return ReturnValue;
539 }
540
541
542 /* Function 6 */
543 DWORD
544 WINAPI
545 PNP_ValidateDeviceInstance(
546 handle_t hBinding,
547 LPWSTR pDeviceID,
548 DWORD ulFlags)
549 {
550 CONFIGRET ret = CR_SUCCESS;
551 HKEY hDeviceKey = NULL;
552
553 UNREFERENCED_PARAMETER(hBinding);
554 UNREFERENCED_PARAMETER(ulFlags);
555
556 DPRINT("PNP_ValidateDeviceInstance(%p %S 0x%08lx)\n",
557 hBinding, pDeviceID, ulFlags);
558
559 if (!IsValidDeviceInstanceID(pDeviceID))
560 return CR_INVALID_DEVINST;
561
562 if (RegOpenKeyExW(hEnumKey,
563 pDeviceID,
564 0,
565 KEY_READ,
566 &hDeviceKey))
567 {
568 DPRINT("Could not open the Device Key!\n");
569 ret = CR_NO_SUCH_DEVNODE;
570 goto Done;
571 }
572
573 /* FIXME: add more tests */
574
575 Done:
576 if (hDeviceKey != NULL)
577 RegCloseKey(hDeviceKey);
578
579 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret);
580
581 return ret;
582 }
583
584
585 /* Function 7 */
586 DWORD
587 WINAPI
588 PNP_GetRootDeviceInstance(
589 handle_t hBinding,
590 LPWSTR pDeviceID,
591 PNP_RPC_STRING_LEN ulLength)
592 {
593 CONFIGRET ret = CR_SUCCESS;
594
595 UNREFERENCED_PARAMETER(hBinding);
596
597 DPRINT("PNP_GetRootDeviceInstance(%p %S %lu)\n",
598 hBinding, pDeviceID, ulLength);
599
600 if (!pDeviceID)
601 {
602 ret = CR_INVALID_POINTER;
603 goto Done;
604 }
605
606 if (ulLength < lstrlenW(szRootDeviceInstanceID) + 1)
607 {
608 ret = CR_BUFFER_SMALL;
609 goto Done;
610 }
611
612 lstrcpyW(pDeviceID,
613 szRootDeviceInstanceID);
614
615 Done:
616 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret);
617
618 return ret;
619 }
620
621
622 /* Function 8 */
623 DWORD
624 WINAPI
625 PNP_GetRelatedDeviceInstance(
626 handle_t hBinding,
627 DWORD ulRelationship,
628 LPWSTR pDeviceID,
629 LPWSTR pRelatedDeviceId,
630 PNP_RPC_STRING_LEN *pulLength,
631 DWORD ulFlags)
632 {
633 PLUGPLAY_CONTROL_RELATED_DEVICE_DATA PlugPlayData;
634 CONFIGRET ret = CR_SUCCESS;
635 NTSTATUS Status;
636
637 UNREFERENCED_PARAMETER(hBinding);
638 UNREFERENCED_PARAMETER(ulFlags);
639
640 DPRINT("PNP_GetRelatedDeviceInstance(%p %lu %S %p %p 0x%lx)\n",
641 hBinding, ulRelationship, pDeviceID, pRelatedDeviceId,
642 pulLength, ulFlags);
643
644 if (!IsValidDeviceInstanceID(pDeviceID))
645 return CR_INVALID_DEVINST;
646
647 RtlInitUnicodeString(&PlugPlayData.TargetDeviceInstance,
648 pDeviceID);
649
650 PlugPlayData.Relation = ulRelationship;
651
652 PlugPlayData.RelatedDeviceInstanceLength = *pulLength;
653 PlugPlayData.RelatedDeviceInstance = pRelatedDeviceId;
654
655 Status = NtPlugPlayControl(PlugPlayControlGetRelatedDevice,
656 (PVOID)&PlugPlayData,
657 sizeof(PLUGPLAY_CONTROL_RELATED_DEVICE_DATA));
658 if (!NT_SUCCESS(Status))
659 {
660 ret = NtStatusToCrError(Status);
661 }
662
663 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret);
664 if (ret == CR_SUCCESS)
665 {
666 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance);
667 }
668
669 return ret;
670 }
671
672
673 /* Function 9 */
674 DWORD
675 WINAPI
676 PNP_EnumerateSubKeys(
677 handle_t hBinding,
678 DWORD ulBranch,
679 DWORD ulIndex,
680 LPWSTR Buffer,
681 PNP_RPC_STRING_LEN ulLength,
682 PNP_RPC_STRING_LEN *pulRequiredLen,
683 DWORD ulFlags)
684 {
685 CONFIGRET ret = CR_SUCCESS;
686 HKEY hKey;
687 DWORD dwError;
688
689 UNREFERENCED_PARAMETER(hBinding);
690 UNREFERENCED_PARAMETER(ulFlags);
691
692 DPRINT("PNP_EnumerateSubKeys(%p %lu %lu %p %lu %p 0x%08lx)\n",
693 hBinding, ulBranch, ulIndex, Buffer, ulLength,
694 pulRequiredLen, ulFlags);
695
696 switch (ulBranch)
697 {
698 case PNP_ENUMERATOR_SUBKEYS:
699 hKey = hEnumKey;
700 break;
701
702 case PNP_CLASS_SUBKEYS:
703 hKey = hClassKey;
704 break;
705
706 default:
707 return CR_FAILURE;
708 }
709
710 *pulRequiredLen = ulLength;
711 dwError = RegEnumKeyExW(hKey,
712 ulIndex,
713 Buffer,
714 pulRequiredLen,
715 NULL,
716 NULL,
717 NULL,
718 NULL);
719 if (dwError != ERROR_SUCCESS)
720 {
721 ret = (dwError == ERROR_NO_MORE_ITEMS) ? CR_NO_SUCH_VALUE : CR_FAILURE;
722 }
723 else
724 {
725 (*pulRequiredLen)++;
726 }
727
728 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret);
729
730 return ret;
731 }
732
733
734 static
735 CONFIGRET
736 GetRelationsInstanceList(
737 _In_ PWSTR pszDevice,
738 _In_ DWORD ulFlags,
739 _Inout_ PWSTR pszBuffer,
740 _Inout_ PDWORD pulLength)
741 {
742 PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData;
743 NTSTATUS Status;
744 CONFIGRET ret = CR_SUCCESS;
745
746 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
747 pszDevice);
748
749 if (ulFlags & CM_GETIDLIST_FILTER_BUSRELATIONS)
750 {
751 PlugPlayData.Relations = 3;
752 }
753 else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS)
754 {
755 PlugPlayData.Relations = 2;
756 }
757 else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS)
758 {
759 PlugPlayData.Relations = 1;
760 }
761 else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS)
762 {
763 PlugPlayData.Relations = 0;
764 }
765
766 PlugPlayData.BufferSize = *pulLength * sizeof(WCHAR);
767 PlugPlayData.Buffer = pszBuffer;
768
769 Status = NtPlugPlayControl(PlugPlayControlQueryDeviceRelations,
770 (PVOID)&PlugPlayData,
771 sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA));
772 if (NT_SUCCESS(Status))
773 {
774 *pulLength = PlugPlayData.BufferSize / sizeof(WCHAR);
775 }
776 else
777 {
778 ret = NtStatusToCrError(Status);
779 }
780
781 return ret;
782 }
783
784
785 static
786 CONFIGRET
787 GetServiceInstanceList(
788 _In_ PWSTR pszService,
789 _Inout_ PWSTR pszBuffer,
790 _Inout_ PDWORD pulLength)
791 {
792 WCHAR szPathBuffer[512];
793 WCHAR szName[16];
794 HKEY hServicesKey = NULL, hServiceKey = NULL, hEnumKey = NULL;
795 DWORD dwValues, dwSize, dwIndex, dwUsedLength, dwPathLength;
796 DWORD dwError;
797 PWSTR pPtr;
798 CONFIGRET ret = CR_SUCCESS;
799
800 /* Open the device key */
801 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
802 L"System\\CurrentControlSet\\Services",
803 0,
804 KEY_READ,
805 &hServicesKey);
806 if (dwError != ERROR_SUCCESS)
807 {
808 DPRINT("Failed to open the services key (Error %lu)\n", dwError);
809 return CR_REGISTRY_ERROR;
810 }
811
812 dwError = RegOpenKeyExW(hServicesKey,
813 pszService,
814 0,
815 KEY_READ,
816 &hServiceKey);
817 if (dwError != ERROR_SUCCESS)
818 {
819 DPRINT("Failed to open the service key (Error %lu)\n", dwError);
820 ret = CR_REGISTRY_ERROR;
821 goto Done;
822 }
823
824 dwError = RegOpenKeyExW(hServiceKey,
825 L"Enum",
826 0,
827 KEY_READ,
828 &hEnumKey);
829 if (dwError != ERROR_SUCCESS)
830 {
831 DPRINT("Failed to open the service enum key (Error %lu)\n", dwError);
832 ret = CR_REGISTRY_ERROR;
833 goto Done;
834 }
835
836 /* Retrieve the number of device instances */
837 dwSize = sizeof(DWORD);
838 dwError = RegQueryValueExW(hEnumKey,
839 L"Count",
840 NULL,
841 NULL,
842 (LPBYTE)&dwValues,
843 &dwSize);
844 if (dwError != ERROR_SUCCESS)
845 {
846 DPRINT("RegQueryValueExW failed (Error %lu)\n", dwError);
847 dwValues = 1;
848 }
849
850 DPRINT("dwValues %lu\n", dwValues);
851
852 dwUsedLength = 0;
853 pPtr = pszBuffer;
854
855 for (dwIndex = 0; dwIndex < dwValues; dwIndex++)
856 {
857 wsprintf(szName, L"%lu", dwIndex);
858
859 dwSize = sizeof(szPathBuffer);
860 dwError = RegQueryValueExW(hEnumKey,
861 szName,
862 NULL,
863 NULL,
864 (LPBYTE)szPathBuffer,
865 &dwSize);
866 if (dwError != ERROR_SUCCESS)
867 break;
868
869 DPRINT("Path: %S\n", szPathBuffer);
870
871 dwPathLength = wcslen(szPathBuffer) + 1;
872 if (dwUsedLength + dwPathLength + 1 > *pulLength)
873 {
874 ret = CR_BUFFER_SMALL;
875 break;
876 }
877
878 wcscpy(pPtr, szPathBuffer);
879 dwUsedLength += dwPathLength;
880 pPtr += dwPathLength;
881
882 *pPtr = UNICODE_NULL;
883 }
884
885 Done:
886 if (hEnumKey != NULL)
887 RegCloseKey(hEnumKey);
888
889 if (hServiceKey != NULL)
890 RegCloseKey(hServiceKey);
891
892 if (hServicesKey != NULL)
893 RegCloseKey(hServicesKey);
894
895 if (ret == CR_SUCCESS)
896 *pulLength = dwUsedLength + 1;
897 else
898 *pulLength = 0;
899
900 return ret;
901 }
902
903
904 static
905 CONFIGRET
906 GetDeviceInstanceList(
907 _In_ PWSTR pszDevice,
908 _Inout_ PWSTR pszBuffer,
909 _Inout_ PDWORD pulLength)
910 {
911 WCHAR szInstanceBuffer[MAX_DEVICE_ID_LEN];
912 WCHAR szPathBuffer[512];
913 HKEY hDeviceKey;
914 DWORD dwInstanceLength, dwPathLength, dwUsedLength;
915 DWORD dwIndex, dwError;
916 PWSTR pPtr;
917 CONFIGRET ret = CR_SUCCESS;
918
919 /* Open the device key */
920 dwError = RegOpenKeyExW(hEnumKey,
921 pszDevice,
922 0,
923 KEY_ENUMERATE_SUB_KEYS,
924 &hDeviceKey);
925 if (dwError != ERROR_SUCCESS)
926 {
927 DPRINT("Failed to open the device key (Error %lu)\n", dwError);
928 return CR_REGISTRY_ERROR;
929 }
930
931 dwUsedLength = 0;
932 pPtr = pszBuffer;
933
934 for (dwIndex = 0; ; dwIndex++)
935 {
936 dwInstanceLength = MAX_DEVICE_ID_LEN;
937 dwError = RegEnumKeyExW(hDeviceKey,
938 dwIndex,
939 szInstanceBuffer,
940 &dwInstanceLength,
941 NULL,
942 NULL,
943 NULL,
944 NULL);
945 if (dwError != ERROR_SUCCESS)
946 break;
947
948 wsprintf(szPathBuffer, L"%s\\%s", pszDevice, szInstanceBuffer);
949 DPRINT("Path: %S\n", szPathBuffer);
950
951 dwPathLength = wcslen(szPathBuffer) + 1;
952 if (dwUsedLength + dwPathLength + 1 > *pulLength)
953 {
954 ret = CR_BUFFER_SMALL;
955 break;
956 }
957
958 wcscpy(pPtr, szPathBuffer);
959 dwUsedLength += dwPathLength;
960 pPtr += dwPathLength;
961
962 *pPtr = UNICODE_NULL;
963 }
964
965 RegCloseKey(hDeviceKey);
966
967 if (ret == CR_SUCCESS)
968 *pulLength = dwUsedLength + 1;
969 else
970 *pulLength = 0;
971
972 return ret;
973 }
974
975
976 CONFIGRET
977 GetEnumeratorInstanceList(
978 _In_ PWSTR pszEnumerator,
979 _Inout_ PWSTR pszBuffer,
980 _Inout_ PDWORD pulLength)
981 {
982 WCHAR szDeviceBuffer[MAX_DEVICE_ID_LEN];
983 WCHAR szPathBuffer[512];
984 HKEY hEnumeratorKey;
985 PWSTR pPtr;
986 DWORD dwIndex, dwDeviceLength, dwUsedLength, dwRemainingLength, dwPathLength;
987 DWORD dwError;
988 CONFIGRET ret = CR_SUCCESS;
989
990 /* Open the enumerator key */
991 dwError = RegOpenKeyExW(hEnumKey,
992 pszEnumerator,
993 0,
994 KEY_ENUMERATE_SUB_KEYS,
995 &hEnumeratorKey);
996 if (dwError != ERROR_SUCCESS)
997 {
998 DPRINT("Failed to open the enumerator key (Error %lu)\n", dwError);
999 return CR_REGISTRY_ERROR;
1000 }
1001
1002 dwUsedLength = 0;
1003 dwRemainingLength = *pulLength;
1004 pPtr = pszBuffer;
1005
1006 for (dwIndex = 0; ; dwIndex++)
1007 {
1008 dwDeviceLength = MAX_DEVICE_ID_LEN;
1009 dwError = RegEnumKeyExW(hEnumeratorKey,
1010 dwIndex,
1011 szDeviceBuffer,
1012 &dwDeviceLength,
1013 NULL,
1014 NULL,
1015 NULL,
1016 NULL);
1017 if (dwError != ERROR_SUCCESS)
1018 break;
1019
1020 wsprintf(szPathBuffer, L"%s\\%s", pszEnumerator, szDeviceBuffer);
1021 DPRINT("Path: %S\n", szPathBuffer);
1022
1023 dwPathLength = dwRemainingLength;
1024 ret = GetDeviceInstanceList(szPathBuffer,
1025 pPtr,
1026 &dwPathLength);
1027 if (ret != CR_SUCCESS)
1028 break;
1029
1030 dwUsedLength += dwPathLength - 1;
1031 dwRemainingLength += dwPathLength - 1;
1032 pPtr += dwPathLength - 1;
1033 }
1034
1035 RegCloseKey(hEnumeratorKey);
1036
1037 if (ret == CR_SUCCESS)
1038 *pulLength = dwUsedLength + 1;
1039 else
1040 *pulLength = 0;
1041
1042 return ret;
1043 }
1044
1045
1046 static
1047 CONFIGRET
1048 GetAllInstanceList(
1049 _Inout_ PWSTR pszBuffer,
1050 _Inout_ PDWORD pulLength)
1051 {
1052 WCHAR szEnumeratorBuffer[MAX_DEVICE_ID_LEN];
1053 PWSTR pPtr;
1054 DWORD dwIndex, dwEnumeratorLength, dwUsedLength, dwRemainingLength, dwPathLength;
1055 DWORD dwError;
1056 CONFIGRET ret = CR_SUCCESS;
1057
1058 dwUsedLength = 0;
1059 dwRemainingLength = *pulLength;
1060 pPtr = pszBuffer;
1061
1062 for (dwIndex = 0; ; dwIndex++)
1063 {
1064 dwEnumeratorLength = MAX_DEVICE_ID_LEN;
1065 dwError = RegEnumKeyExW(hEnumKey,
1066 dwIndex,
1067 szEnumeratorBuffer,
1068 &dwEnumeratorLength,
1069 NULL, NULL, NULL, NULL);
1070 if (dwError != ERROR_SUCCESS)
1071 break;
1072
1073 dwPathLength = dwRemainingLength;
1074 ret = GetEnumeratorInstanceList(szEnumeratorBuffer,
1075 pPtr,
1076 &dwPathLength);
1077 if (ret != CR_SUCCESS)
1078 break;
1079
1080 dwUsedLength += dwPathLength - 1;
1081 dwRemainingLength += dwPathLength - 1;
1082 pPtr += dwPathLength - 1;
1083 }
1084
1085 if (ret == CR_SUCCESS)
1086 *pulLength = dwUsedLength + 1;
1087 else
1088 *pulLength = 0;
1089
1090 return ret;
1091 }
1092
1093
1094 /* Function 10 */
1095 DWORD
1096 WINAPI
1097 PNP_GetDeviceList(
1098 handle_t hBinding,
1099 LPWSTR pszFilter,
1100 LPWSTR Buffer,
1101 PNP_RPC_STRING_LEN *pulLength,
1102 DWORD ulFlags)
1103 {
1104 WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
1105 WCHAR szDevice[MAX_DEVICE_ID_LEN];
1106 WCHAR szInstance[MAX_DEVICE_ID_LEN];
1107 CONFIGRET ret = CR_SUCCESS;
1108
1109 DPRINT("PNP_GetDeviceList(%p %S %p %p 0x%08lx)\n",
1110 hBinding, pszFilter, Buffer, pulLength, ulFlags);
1111
1112 if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
1113 return CR_INVALID_FLAG;
1114
1115 if (pulLength == NULL)
1116 return CR_INVALID_POINTER;
1117
1118 if ((ulFlags != CM_GETIDLIST_FILTER_NONE) &&
1119 (pszFilter == NULL))
1120 return CR_INVALID_POINTER;
1121
1122 if (ulFlags &
1123 (CM_GETIDLIST_FILTER_BUSRELATIONS |
1124 CM_GETIDLIST_FILTER_POWERRELATIONS |
1125 CM_GETIDLIST_FILTER_REMOVALRELATIONS |
1126 CM_GETIDLIST_FILTER_EJECTRELATIONS))
1127 {
1128 ret = GetRelationsInstanceList(pszFilter,
1129 ulFlags,
1130 Buffer,
1131 pulLength);
1132 }
1133 else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE)
1134 {
1135 ret = GetServiceInstanceList(pszFilter,
1136 Buffer,
1137 pulLength);
1138 }
1139 else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR)
1140 {
1141 SplitDeviceInstanceID(pszFilter,
1142 szEnumerator,
1143 szDevice,
1144 szInstance);
1145
1146 if (*szEnumerator != UNICODE_NULL && *szDevice != UNICODE_NULL)
1147 {
1148 ret = GetDeviceInstanceList(pszFilter,
1149 Buffer,
1150 pulLength);
1151 }
1152 else
1153 {
1154 ret = GetEnumeratorInstanceList(pszFilter,
1155 Buffer,
1156 pulLength);
1157 }
1158 }
1159 else /* CM_GETIDLIST_FILTER_NONE */
1160 {
1161 ret = GetAllInstanceList(Buffer,
1162 pulLength);
1163 }
1164
1165 return ret;
1166 }
1167
1168
1169 static
1170 CONFIGRET
1171 GetRelationsInstanceListSize(
1172 _In_ PWSTR pszDevice,
1173 _In_ DWORD ulFlags,
1174 _Inout_ PDWORD pulLength)
1175 {
1176 PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA PlugPlayData;
1177 NTSTATUS Status;
1178 CONFIGRET ret = CR_SUCCESS;
1179
1180 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1181 pszDevice);
1182
1183 if (ulFlags & CM_GETIDLIST_FILTER_BUSRELATIONS)
1184 {
1185 PlugPlayData.Relations = 3;
1186 }
1187 else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS)
1188 {
1189 PlugPlayData.Relations = 2;
1190 }
1191 else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS)
1192 {
1193 PlugPlayData.Relations = 1;
1194 }
1195 else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS)
1196 {
1197 PlugPlayData.Relations = 0;
1198 }
1199
1200 PlugPlayData.BufferSize = 0;
1201 PlugPlayData.Buffer = NULL;
1202
1203 Status = NtPlugPlayControl(PlugPlayControlQueryDeviceRelations,
1204 (PVOID)&PlugPlayData,
1205 sizeof(PLUGPLAY_CONTROL_DEVICE_RELATIONS_DATA));
1206 if (NT_SUCCESS(Status))
1207 {
1208 *pulLength = PlugPlayData.BufferSize / sizeof(WCHAR);
1209 }
1210 else
1211 {
1212 ret = NtStatusToCrError(Status);
1213 }
1214
1215 return ret;
1216 }
1217
1218
1219 static
1220 CONFIGRET
1221 GetServiceInstanceListSize(
1222 _In_ PWSTR pszService,
1223 _Out_ PDWORD pulLength)
1224 {
1225 HKEY hServicesKey = NULL, hServiceKey = NULL, hEnumKey = NULL;
1226 DWORD dwValues, dwMaxValueLength, dwSize;
1227 DWORD dwError;
1228 CONFIGRET ret = CR_SUCCESS;
1229
1230 /* Open the device key */
1231 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1232 L"System\\CurrentControlSet\\Services",
1233 0,
1234 KEY_READ,
1235 &hServicesKey);
1236 if (dwError != ERROR_SUCCESS)
1237 {
1238 DPRINT("Failed to open the services key (Error %lu)\n", dwError);
1239 return CR_REGISTRY_ERROR;
1240 }
1241
1242 dwError = RegOpenKeyExW(hServicesKey,
1243 pszService,
1244 0,
1245 KEY_READ,
1246 &hServiceKey);
1247 if (dwError != ERROR_SUCCESS)
1248 {
1249 DPRINT("Failed to open the service key (Error %lu)\n", dwError);
1250 ret = CR_REGISTRY_ERROR;
1251 goto Done;
1252 }
1253
1254 dwError = RegOpenKeyExW(hServiceKey,
1255 L"Enum",
1256 0,
1257 KEY_READ,
1258 &hEnumKey);
1259 if (dwError != ERROR_SUCCESS)
1260 {
1261 DPRINT("Failed to open the service enum key (Error %lu)\n", dwError);
1262 ret = CR_REGISTRY_ERROR;
1263 goto Done;
1264 }
1265
1266 /* Retrieve the number of device instances */
1267 dwSize = sizeof(DWORD);
1268 dwError = RegQueryValueExW(hEnumKey,
1269 L"Count",
1270 NULL,
1271 NULL,
1272 (LPBYTE)&dwValues,
1273 &dwSize);
1274 if (dwError != ERROR_SUCCESS)
1275 {
1276 DPRINT("RegQueryValueExW failed (Error %lu)\n", dwError);
1277 dwValues = 1;
1278 }
1279
1280 /* Retrieve the maximum instance name length */
1281 dwError = RegQueryInfoKeyW(hEnumKey,
1282 NULL,
1283 NULL,
1284 NULL,
1285 NULL,
1286 NULL,
1287 NULL,
1288 NULL,
1289 NULL,
1290 &dwMaxValueLength,
1291 NULL,
1292 NULL);
1293 if (dwError != ERROR_SUCCESS)
1294 {
1295 DPRINT("RegQueryInfoKeyW failed (Error %lu)\n", dwError);
1296 dwMaxValueLength = MAX_DEVICE_ID_LEN;
1297 }
1298
1299 DPRINT("dwValues %lu dwMaxValueLength %lu\n", dwValues, dwMaxValueLength / sizeof(WCHAR));
1300
1301 /* Return the largest possible buffer size */
1302 *pulLength = dwValues * dwMaxValueLength / sizeof(WCHAR) + 2;
1303
1304 Done:
1305 if (hEnumKey != NULL)
1306 RegCloseKey(hEnumKey);
1307
1308 if (hServiceKey != NULL)
1309 RegCloseKey(hServiceKey);
1310
1311 if (hServicesKey != NULL)
1312 RegCloseKey(hServicesKey);
1313
1314 return ret;
1315 }
1316
1317
1318 static
1319 CONFIGRET
1320 GetDeviceInstanceListSize(
1321 _In_ LPCWSTR pszDevice,
1322 _Out_ PULONG pulLength)
1323 {
1324 HKEY hDeviceKey;
1325 DWORD dwSubKeys, dwMaxSubKeyLength;
1326 DWORD dwError;
1327
1328 /* Open the device key */
1329 dwError = RegOpenKeyExW(hEnumKey,
1330 pszDevice,
1331 0,
1332 KEY_READ,
1333 &hDeviceKey);
1334 if (dwError != ERROR_SUCCESS)
1335 {
1336 DPRINT("Failed to open the device key (Error %lu)\n", dwError);
1337 return CR_REGISTRY_ERROR;
1338 }
1339
1340 /* Retrieve the number of device instances and the maximum name length */
1341 dwError = RegQueryInfoKeyW(hDeviceKey,
1342 NULL,
1343 NULL,
1344 NULL,
1345 &dwSubKeys,
1346 &dwMaxSubKeyLength,
1347 NULL,
1348 NULL,
1349 NULL,
1350 NULL,
1351 NULL,
1352 NULL);
1353 if (dwError != ERROR_SUCCESS)
1354 {
1355 DPRINT("RegQueryInfoKeyW failed (Error %lu)\n", dwError);
1356 dwSubKeys = 0;
1357 dwMaxSubKeyLength = 0;
1358 }
1359
1360 /* Close the device key */
1361 RegCloseKey(hDeviceKey);
1362
1363 /* Return the largest possible buffer size */
1364 *pulLength = dwSubKeys * (wcslen(pszDevice) + 1 + dwMaxSubKeyLength + 1);
1365
1366 return CR_SUCCESS;
1367 }
1368
1369
1370 static
1371 CONFIGRET
1372 GetEnumeratorInstanceListSize(
1373 _In_ LPCWSTR pszEnumerator,
1374 _Out_ PULONG pulLength)
1375 {
1376 WCHAR szDeviceBuffer[MAX_DEVICE_ID_LEN];
1377 WCHAR szPathBuffer[512];
1378 HKEY hEnumeratorKey;
1379 DWORD dwIndex, dwDeviceLength, dwBufferLength;
1380 DWORD dwError;
1381 CONFIGRET ret = CR_SUCCESS;
1382
1383 *pulLength = 0;
1384
1385 /* Open the enumerator key */
1386 dwError = RegOpenKeyExW(hEnumKey,
1387 pszEnumerator,
1388 0,
1389 KEY_ENUMERATE_SUB_KEYS,
1390 &hEnumeratorKey);
1391 if (dwError != ERROR_SUCCESS)
1392 {
1393 DPRINT("Failed to open the enumerator key (Error %lu)\n", dwError);
1394 return CR_REGISTRY_ERROR;
1395 }
1396
1397 for (dwIndex = 0; ; dwIndex++)
1398 {
1399 dwDeviceLength = MAX_DEVICE_ID_LEN;
1400 dwError = RegEnumKeyExW(hEnumeratorKey,
1401 dwIndex,
1402 szDeviceBuffer,
1403 &dwDeviceLength,
1404 NULL,
1405 NULL,
1406 NULL,
1407 NULL);
1408 if (dwError != ERROR_SUCCESS)
1409 break;
1410
1411 wsprintf(szPathBuffer, L"%s\\%s", pszEnumerator, szDeviceBuffer);
1412 DPRINT("Path: %S\n", szPathBuffer);
1413
1414 ret = GetDeviceInstanceListSize(szPathBuffer, &dwBufferLength);
1415 if (ret != CR_SUCCESS)
1416 {
1417 *pulLength = 0;
1418 break;
1419 }
1420
1421 *pulLength += dwBufferLength;
1422 }
1423
1424 /* Close the enumerator key */
1425 RegCloseKey(hEnumeratorKey);
1426
1427 return ret;
1428 }
1429
1430
1431 static
1432 CONFIGRET
1433 GetAllInstanceListSize(
1434 _Out_ PULONG pulLength)
1435 {
1436 WCHAR szEnumeratorBuffer[MAX_DEVICE_ID_LEN];
1437 DWORD dwIndex, dwEnumeratorLength, dwBufferLength;
1438 DWORD dwError;
1439 CONFIGRET ret = CR_SUCCESS;
1440
1441 for (dwIndex = 0; ; dwIndex++)
1442 {
1443 dwEnumeratorLength = MAX_DEVICE_ID_LEN;
1444 dwError = RegEnumKeyExW(hEnumKey,
1445 dwIndex,
1446 szEnumeratorBuffer,
1447 &dwEnumeratorLength,
1448 NULL, NULL, NULL, NULL);
1449 if (dwError != ERROR_SUCCESS)
1450 break;
1451
1452 /* Get the size of all device instances for the enumerator */
1453 ret = GetEnumeratorInstanceListSize(szEnumeratorBuffer,
1454 &dwBufferLength);
1455 if (ret != CR_SUCCESS)
1456 break;
1457
1458 *pulLength += dwBufferLength;
1459 }
1460
1461 return ret;
1462 }
1463
1464
1465 /* Function 11 */
1466 DWORD
1467 WINAPI
1468 PNP_GetDeviceListSize(
1469 handle_t hBinding,
1470 LPWSTR pszFilter,
1471 PNP_RPC_BUFFER_SIZE *pulLength,
1472 DWORD ulFlags)
1473 {
1474 WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
1475 WCHAR szDevice[MAX_DEVICE_ID_LEN];
1476 WCHAR szInstance[MAX_DEVICE_ID_LEN];
1477 CONFIGRET ret = CR_SUCCESS;
1478
1479 DPRINT("PNP_GetDeviceListSize(%p %S %p 0x%08lx)\n",
1480 hBinding, pszFilter, pulLength, ulFlags);
1481
1482 if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
1483 return CR_INVALID_FLAG;
1484
1485 if (pulLength == NULL)
1486 return CR_INVALID_POINTER;
1487
1488 if ((ulFlags != CM_GETIDLIST_FILTER_NONE) &&
1489 (pszFilter == NULL))
1490 return CR_INVALID_POINTER;
1491
1492 *pulLength = 0;
1493
1494 if (ulFlags &
1495 (CM_GETIDLIST_FILTER_BUSRELATIONS |
1496 CM_GETIDLIST_FILTER_POWERRELATIONS |
1497 CM_GETIDLIST_FILTER_REMOVALRELATIONS |
1498 CM_GETIDLIST_FILTER_EJECTRELATIONS))
1499 {
1500 ret = GetRelationsInstanceListSize(pszFilter,
1501 ulFlags,
1502 pulLength);
1503 }
1504 else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE)
1505 {
1506 ret = GetServiceInstanceListSize(pszFilter,
1507 pulLength);
1508 }
1509 else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR)
1510 {
1511 SplitDeviceInstanceID(pszFilter,
1512 szEnumerator,
1513 szDevice,
1514 szInstance);
1515
1516 if (*szEnumerator != UNICODE_NULL && *szDevice != UNICODE_NULL)
1517 {
1518 ret = GetDeviceInstanceListSize(pszFilter,
1519 pulLength);
1520 }
1521 else
1522 {
1523 ret = GetEnumeratorInstanceListSize(pszFilter,
1524 pulLength);
1525 }
1526 }
1527 else /* CM_GETIDLIST_FILTER_NONE */
1528 {
1529 ret = GetAllInstanceListSize(pulLength);
1530 }
1531
1532 /* Add one character for the terminating double UNICODE_NULL */
1533 if (ret == CR_SUCCESS)
1534 (*pulLength) += 1;
1535
1536 return ret;
1537 }
1538
1539
1540 /* Function 12 */
1541 DWORD
1542 WINAPI
1543 PNP_GetDepth(
1544 handle_t hBinding,
1545 LPWSTR pszDeviceID,
1546 DWORD *pulDepth,
1547 DWORD ulFlags)
1548 {
1549 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData;
1550 CONFIGRET ret = CR_SUCCESS;
1551 NTSTATUS Status;
1552
1553 UNREFERENCED_PARAMETER(hBinding);
1554 UNREFERENCED_PARAMETER(ulFlags);
1555
1556 DPRINT("PNP_GetDepth(%p %S %p 0x%08lx)\n",
1557 hBinding, pszDeviceID, pulDepth, ulFlags);
1558
1559 if (!IsValidDeviceInstanceID(pszDeviceID))
1560 return CR_INVALID_DEVINST;
1561
1562 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1563 pszDeviceID);
1564
1565 Status = NtPlugPlayControl(PlugPlayControlGetDeviceDepth,
1566 (PVOID)&PlugPlayData,
1567 sizeof(PLUGPLAY_CONTROL_DEPTH_DATA));
1568 if (NT_SUCCESS(Status))
1569 {
1570 *pulDepth = PlugPlayData.Depth;
1571 }
1572 else
1573 {
1574 ret = NtStatusToCrError(Status);
1575 }
1576
1577 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret);
1578
1579 return ret;
1580 }
1581
1582
1583 /* Function 13 */
1584 DWORD
1585 WINAPI
1586 PNP_GetDeviceRegProp(
1587 handle_t hBinding,
1588 LPWSTR pDeviceID,
1589 DWORD ulProperty,
1590 DWORD *pulRegDataType,
1591 BYTE *Buffer,
1592 PNP_PROP_SIZE *pulTransferLen,
1593 PNP_PROP_SIZE *pulLength,
1594 DWORD ulFlags)
1595 {
1596 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData;
1597 CONFIGRET ret = CR_SUCCESS;
1598 LPWSTR lpValueName = NULL;
1599 HKEY hKey = NULL;
1600 LONG lError;
1601 NTSTATUS Status;
1602
1603 UNREFERENCED_PARAMETER(hBinding);
1604
1605 DPRINT("PNP_GetDeviceRegProp(%p %S %lu %p %p %p %p 0x%08lx)\n",
1606 hBinding, pDeviceID, ulProperty, pulRegDataType, Buffer,
1607 pulTransferLen, pulLength, ulFlags);
1608
1609 if (pulTransferLen == NULL || pulLength == NULL)
1610 {
1611 ret = CR_INVALID_POINTER;
1612 goto done;
1613 }
1614
1615 if (ulFlags != 0)
1616 {
1617 ret = CR_INVALID_FLAG;
1618 goto done;
1619 }
1620
1621 /* Check pDeviceID */
1622 if (!IsValidDeviceInstanceID(pDeviceID))
1623 {
1624 ret = CR_INVALID_DEVINST;
1625 goto done;
1626 }
1627
1628 if (*pulLength < *pulTransferLen)
1629 *pulLength = *pulTransferLen;
1630
1631 *pulTransferLen = 0;
1632
1633 switch (ulProperty)
1634 {
1635 case CM_DRP_DEVICEDESC:
1636 lpValueName = L"DeviceDesc";
1637 break;
1638
1639 case CM_DRP_HARDWAREID:
1640 lpValueName = L"HardwareID";
1641 break;
1642
1643 case CM_DRP_COMPATIBLEIDS:
1644 lpValueName = L"CompatibleIDs";
1645 break;
1646
1647 case CM_DRP_SERVICE:
1648 lpValueName = L"Service";
1649 break;
1650
1651 case CM_DRP_CLASS:
1652 lpValueName = L"Class";
1653 break;
1654
1655 case CM_DRP_CLASSGUID:
1656 lpValueName = L"ClassGUID";
1657 break;
1658
1659 case CM_DRP_DRIVER:
1660 lpValueName = L"Driver";
1661 break;
1662
1663 case CM_DRP_CONFIGFLAGS:
1664 lpValueName = L"ConfigFlags";
1665 break;
1666
1667 case CM_DRP_MFG:
1668 lpValueName = L"Mfg";
1669 break;
1670
1671 case CM_DRP_FRIENDLYNAME:
1672 lpValueName = L"FriendlyName";
1673 break;
1674
1675 case CM_DRP_LOCATION_INFORMATION:
1676 lpValueName = L"LocationInformation";
1677 break;
1678
1679 case CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME:
1680 PlugPlayData.Property = PNP_PROPERTY_PHYSICAL_DEVICE_OBJECT_NAME;
1681 break;
1682
1683 case CM_DRP_CAPABILITIES:
1684 lpValueName = L"Capabilities";
1685 break;
1686
1687 case CM_DRP_UI_NUMBER:
1688 PlugPlayData.Property = PNP_PROPERTY_UI_NUMBER;
1689 break;
1690
1691 case CM_DRP_UPPERFILTERS:
1692 lpValueName = L"UpperFilters";
1693 break;
1694
1695 case CM_DRP_LOWERFILTERS:
1696 lpValueName = L"LowerFilters";
1697 break;
1698
1699 case CM_DRP_BUSTYPEGUID:
1700 PlugPlayData.Property = PNP_PROPERTY_BUSTYPEGUID;
1701 break;
1702
1703 case CM_DRP_LEGACYBUSTYPE:
1704 PlugPlayData.Property = PNP_PROPERTY_LEGACYBUSTYPE;
1705 break;
1706
1707 case CM_DRP_BUSNUMBER:
1708 PlugPlayData.Property = PNP_PROPERTY_BUSNUMBER;
1709 break;
1710
1711 case CM_DRP_ENUMERATOR_NAME:
1712 PlugPlayData.Property = PNP_PROPERTY_ENUMERATOR_NAME;
1713 break;
1714
1715 case CM_DRP_SECURITY:
1716 lpValueName = L"Security";
1717 break;
1718
1719 case CM_DRP_DEVTYPE:
1720 lpValueName = L"DeviceType";
1721 break;
1722
1723 case CM_DRP_EXCLUSIVE:
1724 lpValueName = L"Exclusive";
1725 break;
1726
1727 case CM_DRP_CHARACTERISTICS:
1728 lpValueName = L"DeviceCharacteristics";
1729 break;
1730
1731 case CM_DRP_ADDRESS:
1732 PlugPlayData.Property = PNP_PROPERTY_ADDRESS;
1733 break;
1734
1735 case CM_DRP_UI_NUMBER_DESC_FORMAT:
1736 lpValueName = L"UINumberDescFormat";
1737 break;
1738
1739 case CM_DRP_DEVICE_POWER_DATA:
1740 PlugPlayData.Property = PNP_PROPERTY_POWER_DATA;
1741 break;
1742
1743 case CM_DRP_REMOVAL_POLICY:
1744 PlugPlayData.Property = PNP_PROPERTY_REMOVAL_POLICY;
1745 break;
1746
1747 case CM_DRP_REMOVAL_POLICY_HW_DEFAULT:
1748 PlugPlayData.Property = PNP_PROPERTY_REMOVAL_POLICY_HARDWARE_DEFAULT;
1749 break;
1750
1751 case CM_DRP_REMOVAL_POLICY_OVERRIDE:
1752 lpValueName = L"RemovalPolicy";
1753 break;
1754
1755 case CM_DRP_INSTALL_STATE:
1756 PlugPlayData.Property = PNP_PROPERTY_INSTALL_STATE;
1757 break;
1758
1759 #if (WINVER >= _WIN32_WINNT_WS03)
1760 case CM_DRP_LOCATION_PATHS:
1761 PlugPlayData.Property = PNP_PROPERTY_LOCATION_PATHS;
1762 break;
1763 #endif
1764
1765 #if (WINVER >= _WIN32_WINNT_WIN7)
1766 case CM_DRP_BASE_CONTAINERID:
1767 PlugPlayData.Property = PNP_PROPERTY_CONTAINERID;
1768 break;
1769 #endif
1770
1771 default:
1772 ret = CR_INVALID_PROPERTY;
1773 goto done;
1774 }
1775
1776 DPRINT("Value name: %S\n", lpValueName);
1777
1778 if (lpValueName)
1779 {
1780 /* Retrieve information from the Registry */
1781 lError = RegOpenKeyExW(hEnumKey,
1782 pDeviceID,
1783 0,
1784 KEY_QUERY_VALUE,
1785 &hKey);
1786 if (lError != ERROR_SUCCESS)
1787 {
1788 hKey = NULL;
1789 *pulLength = 0;
1790 ret = CR_INVALID_DEVNODE;
1791 goto done;
1792 }
1793
1794 lError = RegQueryValueExW(hKey,
1795 lpValueName,
1796 NULL,
1797 pulRegDataType,
1798 Buffer,
1799 pulLength);
1800 if (lError != ERROR_SUCCESS)
1801 {
1802 if (lError == ERROR_MORE_DATA)
1803 {
1804 ret = CR_BUFFER_SMALL;
1805 }
1806 else
1807 {
1808 *pulLength = 0;
1809 ret = CR_NO_SUCH_VALUE;
1810 }
1811 }
1812 }
1813 else
1814 {
1815 /* Retrieve information from the Device Node */
1816 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
1817 pDeviceID);
1818 PlugPlayData.Buffer = Buffer;
1819 PlugPlayData.BufferSize = *pulLength;
1820
1821 Status = NtPlugPlayControl(PlugPlayControlProperty,
1822 (PVOID)&PlugPlayData,
1823 sizeof(PLUGPLAY_CONTROL_PROPERTY_DATA));
1824 if (NT_SUCCESS(Status))
1825 {
1826 *pulLength = PlugPlayData.BufferSize;
1827 }
1828 else
1829 {
1830 ret = NtStatusToCrError(Status);
1831 }
1832 }
1833
1834 done:
1835 if (pulTransferLen)
1836 *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0;
1837
1838 if (hKey != NULL)
1839 RegCloseKey(hKey);
1840
1841 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret);
1842
1843 return ret;
1844 }
1845
1846
1847 /* Function 14 */
1848 DWORD
1849 WINAPI
1850 PNP_SetDeviceRegProp(
1851 handle_t hBinding,
1852 LPWSTR pDeviceId,
1853 DWORD ulProperty,
1854 DWORD ulDataType,
1855 BYTE *Buffer,
1856 PNP_PROP_SIZE ulLength,
1857 DWORD ulFlags)
1858 {
1859 CONFIGRET ret = CR_SUCCESS;
1860 LPWSTR lpValueName = NULL;
1861 HKEY hKey = 0;
1862
1863 UNREFERENCED_PARAMETER(hBinding);
1864 UNREFERENCED_PARAMETER(ulFlags);
1865
1866 DPRINT("PNP_SetDeviceRegProp(%p %S %lu %lu %p %lu 0x%08lx)\n",
1867 hBinding, pDeviceId, ulProperty, ulDataType, Buffer,
1868 ulLength, ulFlags);
1869
1870 if (!IsValidDeviceInstanceID(pDeviceId))
1871 return CR_INVALID_DEVINST;
1872
1873 switch (ulProperty)
1874 {
1875 case CM_DRP_DEVICEDESC:
1876 lpValueName = L"DeviceDesc";
1877 break;
1878
1879 case CM_DRP_HARDWAREID:
1880 lpValueName = L"HardwareID";
1881 break;
1882
1883 case CM_DRP_COMPATIBLEIDS:
1884 lpValueName = L"CompatibleIDs";
1885 break;
1886
1887 case CM_DRP_SERVICE:
1888 lpValueName = L"Service";
1889 break;
1890
1891 case CM_DRP_CLASS:
1892 lpValueName = L"Class";
1893 break;
1894
1895 case CM_DRP_CLASSGUID:
1896 lpValueName = L"ClassGUID";
1897 break;
1898
1899 case CM_DRP_DRIVER:
1900 lpValueName = L"Driver";
1901 break;
1902
1903 case CM_DRP_CONFIGFLAGS:
1904 lpValueName = L"ConfigFlags";
1905 break;
1906
1907 case CM_DRP_MFG:
1908 lpValueName = L"Mfg";
1909 break;
1910
1911 case CM_DRP_FRIENDLYNAME:
1912 lpValueName = L"FriendlyName";
1913 break;
1914
1915 case CM_DRP_LOCATION_INFORMATION:
1916 lpValueName = L"LocationInformation";
1917 break;
1918
1919 case CM_DRP_UPPERFILTERS:
1920 lpValueName = L"UpperFilters";
1921 break;
1922
1923 case CM_DRP_LOWERFILTERS:
1924 lpValueName = L"LowerFilters";
1925 break;
1926
1927 case CM_DRP_SECURITY:
1928 lpValueName = L"Security";
1929 break;
1930
1931 case CM_DRP_DEVTYPE:
1932 lpValueName = L"DeviceType";
1933 break;
1934
1935 case CM_DRP_EXCLUSIVE:
1936 lpValueName = L"Exclusive";
1937 break;
1938
1939 case CM_DRP_CHARACTERISTICS:
1940 lpValueName = L"DeviceCharacteristics";
1941 break;
1942
1943 case CM_DRP_UI_NUMBER_DESC_FORMAT:
1944 lpValueName = L"UINumberDescFormat";
1945 break;
1946
1947 case CM_DRP_REMOVAL_POLICY_OVERRIDE:
1948 lpValueName = L"RemovalPolicy";
1949 break;
1950
1951 default:
1952 return CR_INVALID_PROPERTY;
1953 }
1954
1955 DPRINT("Value name: %S\n", lpValueName);
1956
1957 if (RegOpenKeyExW(hEnumKey,
1958 pDeviceId,
1959 0,
1960 KEY_SET_VALUE,
1961 &hKey))
1962 return CR_INVALID_DEVNODE;
1963
1964 if (ulLength == 0)
1965 {
1966 if (RegDeleteValueW(hKey,
1967 lpValueName))
1968 ret = CR_REGISTRY_ERROR;
1969 }
1970 else
1971 {
1972 if (RegSetValueExW(hKey,
1973 lpValueName,
1974 0,
1975 ulDataType,
1976 Buffer,
1977 ulLength))
1978 ret = CR_REGISTRY_ERROR;
1979 }
1980
1981 RegCloseKey(hKey);
1982
1983 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret);
1984
1985 return ret;
1986 }
1987
1988
1989 /* Function 15 */
1990 DWORD
1991 WINAPI
1992 PNP_GetClassInstance(
1993 handle_t hBinding,
1994 LPWSTR pDeviceId,
1995 LPWSTR pszClassInstance,
1996 PNP_RPC_STRING_LEN ulLength)
1997 {
1998 WCHAR szClassGuid[40];
1999 WCHAR szClassInstance[5];
2000 HKEY hDeviceClassKey = NULL;
2001 HKEY hClassInstanceKey;
2002 ULONG ulTransferLength, ulDataLength;
2003 DWORD dwDataType, dwDisposition, i;
2004 DWORD dwError;
2005 CONFIGRET ret = CR_SUCCESS;
2006
2007 DPRINT("PNP_GetClassInstance(%p %S %p %lu)\n",
2008 hBinding, pDeviceId, pszClassInstance, ulLength);
2009
2010 if (!IsValidDeviceInstanceID(pDeviceId))
2011 return CR_INVALID_DEVINST;
2012
2013 ulTransferLength = ulLength;
2014 ret = PNP_GetDeviceRegProp(hBinding,
2015 pDeviceId,
2016 CM_DRP_DRIVER,
2017 &dwDataType,
2018 (BYTE *)pszClassInstance,
2019 &ulTransferLength,
2020 &ulLength,
2021 0);
2022 if (ret == CR_SUCCESS)
2023 return ret;
2024
2025 ulTransferLength = sizeof(szClassGuid);
2026 ulDataLength = sizeof(szClassGuid);
2027 ret = PNP_GetDeviceRegProp(hBinding,
2028 pDeviceId,
2029 CM_DRP_CLASSGUID,
2030 &dwDataType,
2031 (BYTE *)szClassGuid,
2032 &ulTransferLength,
2033 &ulDataLength,
2034 0);
2035 if (ret != CR_SUCCESS)
2036 {
2037 DPRINT1("PNP_GetDeviceRegProp() failed (Error %lu)\n", ret);
2038 goto done;
2039 }
2040
2041 dwError = RegOpenKeyExW(hClassKey,
2042 szClassGuid,
2043 0,
2044 KEY_READ,
2045 &hDeviceClassKey);
2046 if (dwError != ERROR_SUCCESS)
2047 {
2048 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError);
2049 ret = CR_FAILURE;
2050 goto done;
2051 }
2052
2053 for (i = 0; i < 10000; i++)
2054 {
2055 wsprintf(szClassInstance, L"%04lu", i);
2056
2057 dwError = RegCreateKeyExW(hDeviceClassKey,
2058 szClassInstance,
2059 0,
2060 NULL,
2061 REG_OPTION_NON_VOLATILE,
2062 KEY_ALL_ACCESS,
2063 NULL,
2064 &hClassInstanceKey,
2065 &dwDisposition);
2066 if (dwError == ERROR_SUCCESS)
2067 {
2068 RegCloseKey(hClassInstanceKey);
2069
2070 if (dwDisposition == REG_CREATED_NEW_KEY)
2071 {
2072 wsprintf(pszClassInstance,
2073 L"%s\\%s",
2074 szClassGuid,
2075 szClassInstance);
2076
2077 ulDataLength = (wcslen(pszClassInstance) + 1) * sizeof(WCHAR);
2078 ret = PNP_SetDeviceRegProp(hBinding,
2079 pDeviceId,
2080 CM_DRP_DRIVER,
2081 REG_SZ,
2082 (BYTE *)pszClassInstance,
2083 ulDataLength,
2084 0);
2085 if (ret != CR_SUCCESS)
2086 {
2087 DPRINT1("PNP_SetDeviceRegProp() failed (Error %lu)\n", ret);
2088 RegDeleteKeyW(hDeviceClassKey,
2089 szClassInstance);
2090 }
2091
2092 break;
2093 }
2094 }
2095 }
2096
2097 done:
2098 if (hDeviceClassKey != NULL)
2099 RegCloseKey(hDeviceClassKey);
2100
2101 return ret;
2102 }
2103
2104
2105 /* Function 16 */
2106 DWORD
2107 WINAPI
2108 PNP_CreateKey(
2109 handle_t hBinding,
2110 LPWSTR pszSubKey,
2111 DWORD samDesired,
2112 DWORD ulFlags)
2113 {
2114 HKEY hDeviceKey = NULL, hParametersKey = NULL;
2115 DWORD dwError;
2116 CONFIGRET ret = CR_SUCCESS;
2117
2118 UNREFERENCED_PARAMETER(hBinding);
2119 UNREFERENCED_PARAMETER(samDesired);
2120
2121 DPRINT("PNP_CreateKey(%p %S 0x%lx 0x%08lx)\n",
2122 hBinding, pszSubKey, samDesired, ulFlags);
2123
2124 if (ulFlags != 0)
2125 return CR_INVALID_FLAG;
2126
2127 if (!IsValidDeviceInstanceID(pszSubKey))
2128 return CR_INVALID_DEVINST;
2129
2130 dwError = RegOpenKeyExW(hEnumKey,
2131 pszSubKey,
2132 0,
2133 KEY_WRITE,
2134 &hDeviceKey);
2135 if (dwError != ERROR_SUCCESS)
2136 {
2137 ret = CR_INVALID_DEVNODE;
2138 goto done;
2139 }
2140
2141 dwError = RegCreateKeyExW(hDeviceKey,
2142 L"Device Parameters",
2143 0,
2144 NULL,
2145 REG_OPTION_NON_VOLATILE,
2146 KEY_ALL_ACCESS,
2147 NULL,
2148 &hParametersKey,
2149 NULL);
2150 if (dwError != ERROR_SUCCESS)
2151 {
2152 ret = CR_REGISTRY_ERROR;
2153 goto done;
2154 }
2155
2156 /* FIXME: Set key security */
2157
2158 done:
2159 if (hParametersKey != NULL)
2160 RegCloseKey(hParametersKey);
2161
2162 if (hDeviceKey != NULL)
2163 RegCloseKey(hDeviceKey);
2164
2165 return ret;
2166 }
2167
2168
2169 /* Function 17 */
2170 DWORD
2171 WINAPI
2172 PNP_DeleteRegistryKey(
2173 handle_t hBinding,
2174 LPWSTR pszDeviceID,
2175 LPWSTR pszParentKey,
2176 LPWSTR pszChildKey,
2177 DWORD ulFlags)
2178 {
2179 UNIMPLEMENTED;
2180 return CR_CALL_NOT_IMPLEMENTED;
2181 }
2182
2183
2184 /* Function 18 */
2185 DWORD
2186 WINAPI
2187 PNP_GetClassCount(
2188 handle_t hBinding,
2189 DWORD *pulClassCount,
2190 DWORD ulFlags)
2191 {
2192 HKEY hKey;
2193 DWORD dwError;
2194
2195 UNREFERENCED_PARAMETER(hBinding);
2196 UNREFERENCED_PARAMETER(ulFlags);
2197
2198 DPRINT("PNP_GetClassCount(%p %p 0x%08lx)\n",
2199 hBinding, pulClassCount, ulFlags);
2200
2201 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2202 REGSTR_PATH_CLASS,
2203 0,
2204 KEY_QUERY_VALUE,
2205 &hKey);
2206 if (dwError != ERROR_SUCCESS)
2207 return CR_INVALID_DATA;
2208
2209 dwError = RegQueryInfoKeyW(hKey,
2210 NULL,
2211 NULL,
2212 NULL,
2213 pulClassCount,
2214 NULL,
2215 NULL,
2216 NULL,
2217 NULL,
2218 NULL,
2219 NULL,
2220 NULL);
2221 RegCloseKey(hKey);
2222 if (dwError != ERROR_SUCCESS)
2223 return CR_INVALID_DATA;
2224
2225 return CR_SUCCESS;
2226 }
2227
2228
2229 /* Function 19 */
2230 DWORD
2231 WINAPI
2232 PNP_GetClassName(
2233 handle_t hBinding,
2234 LPWSTR pszClassGuid,
2235 LPWSTR Buffer,
2236 PNP_RPC_STRING_LEN *pulLength,
2237 DWORD ulFlags)
2238 {
2239 WCHAR szKeyName[MAX_PATH];
2240 CONFIGRET ret = CR_SUCCESS;
2241 HKEY hKey;
2242 DWORD dwSize;
2243
2244 UNREFERENCED_PARAMETER(hBinding);
2245 UNREFERENCED_PARAMETER(ulFlags);
2246
2247 DPRINT("PNP_GetClassName(%p %S %p %p 0x%08lx)\n",
2248 hBinding, pszClassGuid, Buffer, pulLength, ulFlags);
2249
2250 lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\");
2251 if (lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR)))
2252 lstrcatW(szKeyName, pszClassGuid);
2253 else
2254 return CR_INVALID_DATA;
2255
2256 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2257 szKeyName,
2258 0,
2259 KEY_QUERY_VALUE,
2260 &hKey))
2261 return CR_REGISTRY_ERROR;
2262
2263 dwSize = *pulLength * sizeof(WCHAR);
2264 if (RegQueryValueExW(hKey,
2265 L"Class",
2266 NULL,
2267 NULL,
2268 (LPBYTE)Buffer,
2269 &dwSize))
2270 {
2271 *pulLength = 0;
2272 ret = CR_REGISTRY_ERROR;
2273 }
2274 else
2275 {
2276 *pulLength = dwSize / sizeof(WCHAR);
2277 }
2278
2279 RegCloseKey(hKey);
2280
2281 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret);
2282
2283 return ret;
2284 }
2285
2286
2287 /* Function 20 */
2288 DWORD
2289 WINAPI
2290 PNP_DeleteClassKey(
2291 handle_t hBinding,
2292 LPWSTR pszClassGuid,
2293 DWORD ulFlags)
2294 {
2295 CONFIGRET ret = CR_SUCCESS;
2296
2297 UNREFERENCED_PARAMETER(hBinding);
2298
2299 DPRINT("PNP_DeleteClassKey(%p %S 0x%08lx)\n",
2300 hBinding, pszClassGuid, ulFlags);
2301
2302 if (ulFlags & CM_DELETE_CLASS_SUBKEYS)
2303 {
2304 if (SHDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
2305 ret = CR_REGISTRY_ERROR;
2306 }
2307 else
2308 {
2309 if (RegDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
2310 ret = CR_REGISTRY_ERROR;
2311 }
2312
2313 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret);
2314
2315 return ret;
2316 }
2317
2318
2319 /* Function 21 */
2320 DWORD
2321 WINAPI
2322 PNP_GetInterfaceDeviceAlias(
2323 handle_t hBinding,
2324 LPWSTR pszInterfaceDevice,
2325 GUID *AliasInterfaceGuid,
2326 LPWSTR pszAliasInterfaceDevice,
2327 PNP_RPC_STRING_LEN *pulLength,
2328 PNP_RPC_STRING_LEN *pulTransferLen,
2329 DWORD ulFlags)
2330 {
2331 UNIMPLEMENTED;
2332 return CR_CALL_NOT_IMPLEMENTED;
2333 }
2334
2335
2336 /* Function 22 */
2337 DWORD
2338 WINAPI
2339 PNP_GetInterfaceDeviceList(
2340 handle_t hBinding,
2341 GUID *InterfaceGuid,
2342 LPWSTR pszDeviceID,
2343 BYTE *Buffer,
2344 PNP_RPC_BUFFER_SIZE *pulLength,
2345 DWORD ulFlags)
2346 {
2347 NTSTATUS Status;
2348 PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA PlugPlayData;
2349 DWORD ret = CR_SUCCESS;
2350
2351 UNREFERENCED_PARAMETER(hBinding);
2352
2353 DPRINT("PNP_GetInterfaceDeviceList(%p %p %S %p %p 0x%08lx)\n",
2354 hBinding, InterfaceGuid, pszDeviceID, Buffer, pulLength, ulFlags);
2355
2356 if (!IsValidDeviceInstanceID(pszDeviceID))
2357 return CR_INVALID_DEVINST;
2358
2359 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
2360 pszDeviceID);
2361
2362 PlugPlayData.Flags = ulFlags;
2363 PlugPlayData.FilterGuid = InterfaceGuid;
2364 PlugPlayData.Buffer = Buffer;
2365 PlugPlayData.BufferSize = *pulLength;
2366
2367 Status = NtPlugPlayControl(PlugPlayControlGetInterfaceDeviceList,
2368 (PVOID)&PlugPlayData,
2369 sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA));
2370 if (NT_SUCCESS(Status))
2371 {
2372 *pulLength = PlugPlayData.BufferSize;
2373 }
2374 else
2375 {
2376 ret = NtStatusToCrError(Status);
2377 }
2378
2379 DPRINT("PNP_GetInterfaceDeviceList() done (returns %lx)\n", ret);
2380 return ret;
2381 }
2382
2383
2384 /* Function 23 */
2385 DWORD
2386 WINAPI
2387 PNP_GetInterfaceDeviceListSize(
2388 handle_t hBinding,
2389 PNP_RPC_BUFFER_SIZE *pulLen,
2390 GUID *InterfaceGuid,
2391 LPWSTR pszDeviceID,
2392 DWORD ulFlags)
2393 {
2394 NTSTATUS Status;
2395 PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA PlugPlayData;
2396 DWORD ret = CR_SUCCESS;
2397
2398 UNREFERENCED_PARAMETER(hBinding);
2399
2400 DPRINT("PNP_GetInterfaceDeviceListSize(%p %p %p %S 0x%08lx)\n",
2401 hBinding, pulLen, InterfaceGuid, pszDeviceID, ulFlags);
2402
2403 if (!IsValidDeviceInstanceID(pszDeviceID))
2404 return CR_INVALID_DEVINST;
2405
2406 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
2407 pszDeviceID);
2408
2409 PlugPlayData.FilterGuid = InterfaceGuid;
2410 PlugPlayData.Buffer = NULL;
2411 PlugPlayData.BufferSize = 0;
2412 PlugPlayData.Flags = ulFlags;
2413
2414 Status = NtPlugPlayControl(PlugPlayControlGetInterfaceDeviceList,
2415 (PVOID)&PlugPlayData,
2416 sizeof(PLUGPLAY_CONTROL_INTERFACE_DEVICE_LIST_DATA));
2417 if (NT_SUCCESS(Status))
2418 {
2419 *pulLen = PlugPlayData.BufferSize;
2420 }
2421 else
2422 {
2423 ret = NtStatusToCrError(Status);
2424 }
2425
2426 DPRINT("PNP_GetInterfaceDeviceListSize() done (returns %lx)\n", ret);
2427 return ret;
2428 }
2429
2430
2431 /* Function 24 */
2432 DWORD
2433 WINAPI
2434 PNP_RegisterDeviceClassAssociation(
2435 handle_t hBinding,
2436 LPWSTR pszDeviceID,
2437 GUID *InterfaceGuid,
2438 LPWSTR pszReference,
2439 LPWSTR pszSymLink,
2440 PNP_RPC_STRING_LEN *pulLength,
2441 PNP_RPC_STRING_LEN *pulTransferLen,
2442 DWORD ulFlags)
2443 {
2444 UNIMPLEMENTED;
2445 return CR_CALL_NOT_IMPLEMENTED;
2446 }
2447
2448
2449 /* Function 25 */
2450 DWORD
2451 WINAPI
2452 PNP_UnregisterDeviceClassAssociation(
2453 handle_t hBinding,
2454 LPWSTR pszInterfaceDevice,
2455 DWORD ulFlags)
2456 {
2457 UNIMPLEMENTED;
2458 return CR_CALL_NOT_IMPLEMENTED;
2459 }
2460
2461
2462 /* Function 26 */
2463 DWORD
2464 WINAPI
2465 PNP_GetClassRegProp(
2466 handle_t hBinding,
2467 LPWSTR pszClassGuid,
2468 DWORD ulProperty,
2469 DWORD *pulRegDataType,
2470 BYTE *Buffer,
2471 PNP_RPC_STRING_LEN *pulTransferLen,
2472 PNP_RPC_STRING_LEN *pulLength,
2473 DWORD ulFlags)
2474 {
2475 CONFIGRET ret = CR_SUCCESS;
2476 LPWSTR lpValueName = NULL;
2477 HKEY hInstKey = NULL;
2478 HKEY hPropKey = NULL;
2479 LONG lError;
2480
2481 UNREFERENCED_PARAMETER(hBinding);
2482
2483 DPRINT("PNP_GetClassRegProp() called\n");
2484
2485 if (pulTransferLen == NULL || pulLength == NULL)
2486 {
2487 ret = CR_INVALID_POINTER;
2488 goto done;
2489 }
2490
2491 if (ulFlags != 0)
2492 {
2493 ret = CR_INVALID_FLAG;
2494 goto done;
2495 }
2496
2497 if (*pulLength < *pulTransferLen)
2498 *pulLength = *pulTransferLen;
2499
2500 *pulTransferLen = 0;
2501
2502 switch (ulProperty)
2503 {
2504 case CM_CRP_SECURITY:
2505 lpValueName = L"Security";
2506 break;
2507
2508 case CM_CRP_DEVTYPE:
2509 lpValueName = L"DeviceType";
2510 break;
2511
2512 case CM_CRP_EXCLUSIVE:
2513 lpValueName = L"Exclusive";
2514 break;
2515
2516 case CM_CRP_CHARACTERISTICS:
2517 lpValueName = L"DeviceCharacteristics";
2518 break;
2519
2520 default:
2521 ret = CR_INVALID_PROPERTY;
2522 goto done;
2523 }
2524
2525 DPRINT("Value name: %S\n", lpValueName);
2526
2527 lError = RegOpenKeyExW(hClassKey,
2528 pszClassGuid,
2529 0,
2530 KEY_READ,
2531 &hInstKey);
2532 if (lError != ERROR_SUCCESS)
2533 {
2534 *pulLength = 0;
2535 ret = CR_NO_SUCH_REGISTRY_KEY;
2536 goto done;
2537 }
2538
2539 lError = RegOpenKeyExW(hInstKey,
2540 L"Properties",
2541 0,
2542 KEY_READ,
2543 &hPropKey);
2544 if (lError != ERROR_SUCCESS)
2545 {
2546 *pulLength = 0;
2547 ret = CR_NO_SUCH_REGISTRY_KEY;
2548 goto done;
2549 }
2550
2551 lError = RegQueryValueExW(hPropKey,
2552 lpValueName,
2553 NULL,
2554 pulRegDataType,
2555 Buffer,
2556 pulLength);
2557 if (lError != ERROR_SUCCESS)
2558 {
2559 if (lError == ERROR_MORE_DATA)
2560 {
2561 ret = CR_BUFFER_SMALL;
2562 }
2563 else
2564 {
2565 *pulLength = 0;
2566 ret = CR_NO_SUCH_VALUE;
2567 }
2568 }
2569
2570 done:
2571 if (ret == CR_SUCCESS)
2572 *pulTransferLen = *pulLength;
2573
2574 if (hPropKey != NULL)
2575 RegCloseKey(hPropKey);
2576
2577 if (hInstKey != NULL)
2578 RegCloseKey(hInstKey);
2579
2580 DPRINT("PNP_GetClassRegProp() done (returns %lx)\n", ret);
2581
2582 return ret;
2583 }
2584
2585
2586 /* Function 27 */
2587 DWORD
2588 WINAPI
2589 PNP_SetClassRegProp(
2590 handle_t hBinding,
2591 LPWSTR pszClassGuid,
2592 DWORD ulProperty,
2593 DWORD ulDataType,
2594 BYTE *Buffer,
2595 PNP_PROP_SIZE ulLength,
2596 DWORD ulFlags)
2597 {
2598 CONFIGRET ret = CR_SUCCESS;
2599 LPWSTR lpValueName = NULL;
2600 HKEY hInstKey = 0;
2601 HKEY hPropKey = 0;
2602 LONG lError;
2603
2604 UNREFERENCED_PARAMETER(hBinding);
2605
2606 DPRINT("PNP_SetClassRegProp() called\n");
2607
2608 if (ulFlags != 0)
2609 return CR_INVALID_FLAG;
2610
2611 switch (ulProperty)
2612 {
2613 case CM_CRP_SECURITY:
2614 lpValueName = L"Security";
2615 break;
2616
2617 case CM_CRP_DEVTYPE:
2618 lpValueName = L"DeviceType";
2619 break;
2620
2621 case CM_CRP_EXCLUSIVE:
2622 lpValueName = L"Exclusive";
2623 break;
2624
2625 case CM_CRP_CHARACTERISTICS:
2626 lpValueName = L"DeviceCharacteristics";
2627 break;
2628
2629 default:
2630 return CR_INVALID_PROPERTY;
2631 }
2632
2633 lError = RegOpenKeyExW(hClassKey,
2634 pszClassGuid,
2635 0,
2636 KEY_WRITE,
2637 &hInstKey);
2638 if (lError != ERROR_SUCCESS)
2639 {
2640 ret = CR_NO_SUCH_REGISTRY_KEY;
2641 goto done;
2642 }
2643
2644 /* FIXME: Set security descriptor */
2645 lError = RegCreateKeyExW(hInstKey,
2646 L"Properties",
2647 0,
2648 NULL,
2649 REG_OPTION_NON_VOLATILE,
2650 KEY_ALL_ACCESS,
2651 NULL,
2652 &hPropKey,
2653 NULL);
2654 if (lError != ERROR_SUCCESS)
2655 {
2656 ret = CR_REGISTRY_ERROR;
2657 goto done;
2658 }
2659
2660 if (ulLength == 0)
2661 {
2662 if (RegDeleteValueW(hPropKey,
2663 lpValueName))
2664 ret = CR_REGISTRY_ERROR;
2665 }
2666 else
2667 {
2668 if (RegSetValueExW(hPropKey,
2669 lpValueName,
2670 0,
2671 ulDataType,
2672 Buffer,
2673 ulLength))
2674 ret = CR_REGISTRY_ERROR;
2675 }
2676
2677 done:
2678 if (hPropKey != NULL)
2679 RegCloseKey(hPropKey);
2680
2681 if (hInstKey != NULL)
2682 RegCloseKey(hInstKey);
2683
2684 return ret;
2685 }
2686
2687
2688 static CONFIGRET
2689 CreateDeviceInstance(LPWSTR pszDeviceID)
2690 {
2691 WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
2692 WCHAR szDevice[MAX_DEVICE_ID_LEN];
2693 WCHAR szInstance[MAX_DEVICE_ID_LEN];
2694 HKEY hKeyEnumerator;
2695 HKEY hKeyDevice;
2696 HKEY hKeyInstance;
2697 HKEY hKeyControl;
2698 LONG lError;
2699
2700 /* Split the instance ID */
2701 SplitDeviceInstanceID(pszDeviceID,
2702 szEnumerator,
2703 szDevice,
2704 szInstance);
2705
2706 /* Open or create the enumerator key */
2707 lError = RegCreateKeyExW(hEnumKey,
2708 szEnumerator,
2709 0,
2710 NULL,
2711 REG_OPTION_NON_VOLATILE,
2712 KEY_ALL_ACCESS,
2713 NULL,
2714 &hKeyEnumerator,
2715 NULL);
2716 if (lError != ERROR_SUCCESS)
2717 {
2718 return CR_REGISTRY_ERROR;
2719 }
2720
2721 /* Open or create the device key */
2722 lError = RegCreateKeyExW(hKeyEnumerator,
2723 szDevice,
2724 0,
2725 NULL,
2726 REG_OPTION_NON_VOLATILE,
2727 KEY_ALL_ACCESS,
2728 NULL,
2729 &hKeyDevice,
2730 NULL);
2731
2732 /* Close the enumerator key */
2733 RegCloseKey(hKeyEnumerator);
2734
2735 if (lError != ERROR_SUCCESS)
2736 {
2737 return CR_REGISTRY_ERROR;
2738 }
2739
2740 /* Try to open the instance key and fail if it exists */
2741 lError = RegOpenKeyExW(hKeyDevice,
2742 szInstance,
2743 0,
2744 KEY_SET_VALUE,
2745 &hKeyInstance);
2746 if (lError == ERROR_SUCCESS)
2747 {
2748 DPRINT1("Instance %S already exists!\n", szInstance);
2749 RegCloseKey(hKeyInstance);
2750 RegCloseKey(hKeyDevice);
2751 return CR_ALREADY_SUCH_DEVINST;
2752 }
2753
2754 /* Create a new instance key */
2755 lError = RegCreateKeyExW(hKeyDevice,
2756 szInstance,
2757 0,
2758 NULL,
2759 REG_OPTION_NON_VOLATILE,
2760 KEY_ALL_ACCESS,
2761 NULL,
2762 &hKeyInstance,
2763 NULL);
2764
2765 /* Close the device key */
2766 RegCloseKey(hKeyDevice);
2767
2768 if (lError != ERROR_SUCCESS)
2769 {
2770 return CR_REGISTRY_ERROR;
2771 }
2772
2773 /* Create the 'Control' sub key */
2774 lError = RegCreateKeyExW(hKeyInstance,
2775 L"Control",
2776 0,
2777 NULL,
2778 REG_OPTION_NON_VOLATILE,
2779 KEY_ALL_ACCESS,
2780 NULL,
2781 &hKeyControl,
2782 NULL);
2783 if (lError == ERROR_SUCCESS)
2784 {
2785 RegCloseKey(hKeyControl);
2786 }
2787
2788 RegCloseKey(hKeyInstance);
2789
2790 return (lError == ERROR_SUCCESS) ? CR_SUCCESS : CR_REGISTRY_ERROR;
2791 }
2792
2793
2794 /* Function 28 */
2795 DWORD
2796 WINAPI
2797 PNP_CreateDevInst(
2798 handle_t hBinding,
2799 LPWSTR pszDeviceID,
2800 LPWSTR pszParentDeviceID,
2801 PNP_RPC_STRING_LEN ulLength,
2802 DWORD ulFlags)
2803 {
2804 CONFIGRET ret = CR_SUCCESS;
2805
2806 DPRINT("PNP_CreateDevInst(%p %S %S %lu 0x%08lx)\n",
2807 hBinding, pszParentDeviceID, pszDeviceID, ulLength, ulFlags);
2808
2809 if (ulFlags & ~CM_CREATE_DEVNODE_BITS)
2810 return CR_INVALID_FLAG;
2811
2812 if (pszDeviceID == NULL || pszParentDeviceID == NULL)
2813 return CR_INVALID_POINTER;
2814
2815 /* Fail, if the parent device is not the root device */
2816 if (!IsRootDeviceInstanceID(pszParentDeviceID))
2817 return CR_INVALID_DEVINST;
2818
2819 if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID)
2820 {
2821 WCHAR szGeneratedInstance[MAX_DEVICE_ID_LEN];
2822 DWORD dwInstanceNumber;
2823
2824 /* Generated ID is: Root\<Device ID>\<Instance number> */
2825 dwInstanceNumber = 0;
2826 do
2827 {
2828 swprintf(szGeneratedInstance, L"Root\\%ls\\%04lu",
2829 pszDeviceID, dwInstanceNumber);
2830
2831 /* Try to create a device instance with this ID */
2832 ret = CreateDeviceInstance(szGeneratedInstance);
2833
2834 dwInstanceNumber++;
2835 }
2836 while (ret == CR_ALREADY_SUCH_DEVINST);
2837
2838 if (ret == CR_SUCCESS)
2839 {
2840 /* pszDeviceID is an out parameter too for generated IDs */
2841 if (wcslen(szGeneratedInstance) > ulLength)
2842 {
2843 ret = CR_BUFFER_SMALL;
2844 }
2845 else
2846 {
2847 wcscpy(pszDeviceID, szGeneratedInstance);
2848 }
2849 }
2850 }
2851 else
2852 {
2853 /* Create the device instance */
2854 ret = CreateDeviceInstance(pszDeviceID);
2855 }
2856
2857 DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret);
2858
2859 return ret;
2860 }
2861
2862
2863 static CONFIGRET
2864 SetupDeviceInstance(
2865 _In_ LPWSTR pszDeviceInstance,
2866 _In_ DWORD ulMinorAction)
2867 {
2868 HKEY hDeviceKey = NULL;
2869 DWORD dwDisableCount, dwSize;
2870 DWORD ulStatus, ulProblem;
2871 DWORD dwError;
2872 CONFIGRET ret = CR_SUCCESS;
2873
2874 DPRINT1("SetupDeviceInstance(%S 0x%08lx)\n",
2875 pszDeviceInstance, ulMinorAction);
2876
2877 if (IsRootDeviceInstanceID(pszDeviceInstance))
2878 return CR_INVALID_DEVINST;
2879
2880 if (ulMinorAction & ~CM_SETUP_BITS)
2881 return CR_INVALID_FLAG;
2882
2883 if ((ulMinorAction == CM_SETUP_DOWNLOAD) ||
2884 (ulMinorAction == CM_SETUP_WRITE_LOG_CONFS))
2885 return CR_SUCCESS;
2886
2887 dwError = RegOpenKeyExW(hEnumKey,
2888 pszDeviceInstance,
2889 0,
2890 KEY_READ,
2891 &hDeviceKey);
2892 if (dwError != ERROR_SUCCESS)
2893 return CR_INVALID_DEVNODE;
2894
2895 dwSize = sizeof(dwDisableCount);
2896 dwError = RegQueryValueExW(hDeviceKey,
2897 L"DisableCount",
2898 NULL,
2899 NULL,
2900 (LPBYTE)&dwDisableCount,
2901 &dwSize);
2902 if ((dwError == ERROR_SUCCESS) &&
2903 (dwDisableCount > 0))
2904 {
2905 goto done;
2906 }
2907
2908 GetDeviceStatus(pszDeviceInstance,
2909 &ulStatus,
2910 &ulProblem);
2911
2912 if (ulStatus & DN_STARTED)
2913 {
2914 goto done;
2915 }
2916
2917 if (ulStatus & DN_HAS_PROBLEM)
2918 {
2919 ret = ClearDeviceStatus(pszDeviceInstance,
2920 DN_HAS_PROBLEM,
2921 ulProblem);
2922 }
2923
2924 if (ret != CR_SUCCESS)
2925 goto done;
2926
2927
2928 /* FIXME: Start the device */
2929
2930 done:
2931 if (hDeviceKey != NULL)
2932 RegCloseKey(hDeviceKey);
2933
2934 return ret;
2935 }
2936
2937
2938 static CONFIGRET
2939 EnableDeviceInstance(
2940 _In_ LPWSTR pszDeviceInstance)
2941 {
2942 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData;
2943 CONFIGRET ret = CR_SUCCESS;
2944 NTSTATUS Status;
2945
2946 DPRINT("Enable device instance %S\n", pszDeviceInstance);
2947
2948 RtlInitUnicodeString(&ResetDeviceData.DeviceInstance,
2949 pszDeviceInstance);
2950 Status = NtPlugPlayControl(PlugPlayControlResetDevice,
2951 &ResetDeviceData,
2952 sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA));
2953 if (!NT_SUCCESS(Status))
2954 ret = NtStatusToCrError(Status);
2955
2956 return ret;
2957 }
2958
2959
2960 static CONFIGRET
2961 ReenumerateDeviceInstance(
2962 _In_ LPWSTR pszDeviceInstance,
2963 _In_ ULONG ulMinorAction)
2964 {
2965 PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA EnumerateDeviceData;
2966 CONFIGRET ret = CR_SUCCESS;
2967 NTSTATUS Status;
2968
2969 DPRINT1("ReenumerateDeviceInstance(%S 0x%08lx)\n",
2970 pszDeviceInstance, ulMinorAction);
2971
2972 if (ulMinorAction & ~CM_REENUMERATE_BITS)
2973 return CR_INVALID_FLAG;
2974
2975 if (ulMinorAction & CM_REENUMERATE_RETRY_INSTALLATION)
2976 {
2977 DPRINT1("CM_REENUMERATE_RETRY_INSTALLATION not implemented!\n");
2978 }
2979
2980 RtlInitUnicodeString(&EnumerateDeviceData.DeviceInstance,
2981 pszDeviceInstance);
2982 EnumerateDeviceData.Flags = 0;
2983
2984 Status = NtPlugPlayControl(PlugPlayControlEnumerateDevice,
2985 &EnumerateDeviceData,
2986 sizeof(PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA));
2987 if (!NT_SUCCESS(Status))
2988 ret = NtStatusToCrError(Status);
2989
2990 return ret;
2991 }
2992
2993
2994 /* Function 29 */
2995 DWORD
2996 WINAPI
2997 PNP_DeviceInstanceAction(
2998 handle_t hBinding,
2999 DWORD ulMajorAction,
3000 DWORD ulMinorAction,
3001 LPWSTR pszDeviceInstance1,
3002 LPWSTR pszDeviceInstance2)
3003 {
3004 CONFIGRET ret = CR_SUCCESS;
3005
3006 UNREFERENCED_PARAMETER(hBinding);
3007
3008 DPRINT("PNP_DeviceInstanceAction(%p %lu 0x%08lx %S %S)\n",
3009 hBinding, ulMajorAction, ulMinorAction,
3010 pszDeviceInstance1, pszDeviceInstance2);
3011
3012 switch (ulMajorAction)
3013 {
3014 case PNP_DEVINST_SETUP:
3015 ret = SetupDeviceInstance(pszDeviceInstance1,
3016 ulMinorAction);
3017 break;
3018
3019 case PNP_DEVINST_ENABLE:
3020 ret = EnableDeviceInstance(pszDeviceInstance1);
3021 break;
3022
3023 case PNP_DEVINST_REENUMERATE:
3024 ret = ReenumerateDeviceInstance(pszDeviceInstance1,
3025 ulMinorAction);
3026 break;
3027
3028 default:
3029 DPRINT1("Unknown device action %lu: not implemented\n", ulMajorAction);
3030 ret = CR_CALL_NOT_IMPLEMENTED;
3031 }
3032
3033 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
3034
3035 return ret;
3036 }
3037
3038
3039 /* Function 30 */
3040 DWORD
3041 WINAPI
3042 PNP_GetDeviceStatus(
3043 handle_t hBinding,
3044 LPWSTR pDeviceID,
3045 DWORD *pulStatus,
3046 DWORD *pulProblem,
3047 DWORD ulFlags)
3048 {
3049 UNREFERENCED_PARAMETER(hBinding);
3050 UNREFERENCED_PARAMETER(ulFlags);
3051
3052 DPRINT("PNP_GetDeviceStatus(%p %S %p %p)\n",
3053 hBinding, pDeviceID, pulStatus, pulProblem, ulFlags);
3054
3055 if (!IsValidDeviceInstanceID(pDeviceID))
3056 return CR_INVALID_DEVINST;
3057
3058 return GetDeviceStatus(pDeviceID, pulStatus, pulProblem);
3059 }
3060
3061
3062 /* Function 31 */
3063 DWORD
3064 WINAPI
3065 PNP_SetDeviceProblem(
3066 handle_t hBinding,
3067 LPWSTR pDeviceID,
3068 DWORD ulProblem,
3069 DWORD ulFlags)
3070 {
3071 UNIMPLEMENTED;
3072 return CR_CALL_NOT_IMPLEMENTED;
3073 }
3074
3075
3076 /* Function 32 */
3077 DWORD
3078 WINAPI
3079 PNP_DisableDevInst(
3080 handle_t hBinding,
3081 LPWSTR pDeviceID,
3082 PPNP_VETO_TYPE pVetoType,
3083 LPWSTR pszVetoName,
3084 DWORD ulNameLength,
3085 DWORD ulFlags)
3086 {
3087 UNREFERENCED_PARAMETER(hBinding);
3088
3089 DPRINT1("PNP_DisableDevInst(%p %S %p %p %lu 0x%08lx)\n",
3090 hBinding, pDeviceID, pVetoType, pszVetoName, ulNameLength, ulFlags);
3091
3092 if (ulFlags & ~CM_DISABLE_BITS)
3093 return CR_INVALID_FLAG;
3094
3095 if (!IsValidDeviceInstanceID(pDeviceID) ||
3096 IsRootDeviceInstanceID(pDeviceID))
3097 return CR_INVALID_DEVINST;
3098
3099 return DisableDeviceInstance(pDeviceID,
3100 pVetoType,
3101 pszVetoName,
3102 ulNameLength);
3103 }
3104
3105
3106 /* Function 33 */
3107 DWORD
3108 WINAPI
3109 PNP_UninstallDevInst(
3110 handle_t hBinding,
3111 LPWSTR pDeviceID,
3112 DWORD ulFlags)
3113 {
3114 UNIMPLEMENTED;
3115 return CR_CALL_NOT_IMPLEMENTED;
3116 }
3117
3118
3119 static BOOL
3120 CheckForDeviceId(LPWSTR lpDeviceIdList,
3121 LPWSTR lpDeviceId)
3122 {
3123 LPWSTR lpPtr;
3124 DWORD dwLength;
3125
3126 lpPtr = lpDeviceIdList;
3127 while (*lpPtr != 0)
3128 {
3129 dwLength = wcslen(lpPtr);
3130 if (0 == _wcsicmp(lpPtr, lpDeviceId))
3131 return TRUE;
3132
3133 lpPtr += (dwLength + 1);
3134 }
3135
3136 return FALSE;
3137 }
3138
3139
3140 static VOID
3141 AppendDeviceId(LPWSTR lpDeviceIdList,
3142 LPDWORD lpDeviceIdListSize,
3143 LPWSTR lpDeviceId)
3144 {
3145 DWORD dwLen;
3146 DWORD dwPos;
3147
3148 dwLen = wcslen(lpDeviceId);
3149 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
3150
3151 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
3152
3153 dwPos += (dwLen + 1);
3154
3155 lpDeviceIdList[dwPos] = 0;
3156
3157 *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
3158 }
3159
3160
3161 /* Function 34 */
3162 DWORD
3163 WINAPI
3164 PNP_AddID(
3165 handle_t hBinding,
3166 LPWSTR pszDeviceID,
3167 LPWSTR pszID,
3168 DWORD ulFlags)
3169 {
3170 CONFIGRET ret = CR_SUCCESS;
3171 HKEY hDeviceKey;
3172 LPWSTR pszSubKey;
3173 DWORD dwDeviceIdListSize;
3174 DWORD dwNewDeviceIdSize;
3175 WCHAR * pszDeviceIdList = NULL;
3176
3177 UNREFERENCED_PARAMETER(hBinding);
3178
3179 DPRINT("PNP_AddID(%p %S %S 0x%08lx)\n",
3180 hBinding, pszDeviceID, pszID, ulFlags);
3181
3182 if (RegOpenKeyExW(hEnumKey,
3183 pszDeviceID,
3184 0,
3185 KEY_QUERY_VALUE | KEY_SET_VALUE,
3186 &hDeviceKey) != ERROR_SUCCESS)
3187 {
3188 DPRINT("Failed to open the device key!\n");
3189 return CR_INVALID_DEVNODE;
3190 }
3191
3192 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
3193
3194 if (RegQueryValueExW(hDeviceKey,
3195 pszSubKey,
3196 NULL,
3197 NULL,
3198 NULL,
3199 &dwDeviceIdListSize) != ERROR_SUCCESS)
3200 {
3201 DPRINT("Failed to query the desired ID string!\n");
3202 ret = CR_REGISTRY_ERROR;
3203 goto Done;
3204 }
3205
3206 dwNewDeviceIdSize = lstrlenW(pszDeviceID);
3207 if (!dwNewDeviceIdSize)
3208 {
3209 ret = CR_INVALID_POINTER;
3210 goto Done;
3211 }
3212
3213 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR);
3214
3215 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize);
3216 if (!pszDeviceIdList)
3217 {
3218 DPRINT("Failed to allocate memory for the desired ID string!\n");
3219 ret = CR_OUT_OF_MEMORY;
3220 goto Done;
3221 }
3222
3223 if (RegQueryValueExW(hDeviceKey,
3224 pszSubKey,
3225 NULL,
3226 NULL,
3227 (LPBYTE)pszDeviceIdList,
3228 &dwDeviceIdListSize) != ERROR_SUCCESS)
3229 {
3230 DPRINT("Failed to query the desired ID string!\n");
3231 ret = CR_REGISTRY_ERROR;
3232 goto Done;
3233 }
3234
3235 /* Check whether the device ID is already in use */
3236 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID))
3237 {
3238 DPRINT("Device ID was found in the ID string!\n");
3239 ret = CR_SUCCESS;
3240 goto Done;
3241 }
3242
3243 /* Append the Device ID */
3244 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID);
3245
3246 if (RegSetValueExW(hDeviceKey,
3247 pszSubKey,
3248 0,
3249 REG_MULTI_SZ,
3250 (LPBYTE)pszDeviceIdList,
3251 dwDeviceIdListSize) != ERROR_SUCCESS)
3252 {
3253 DPRINT("Failed to set the desired ID string!\n");
3254 ret = CR_REGISTRY_ERROR;
3255 }
3256
3257 Done:
3258 RegCloseKey(hDeviceKey);
3259 if (pszDeviceIdList)
3260 HeapFree(GetProcessHeap(), 0, pszDeviceIdList);
3261
3262 DPRINT("PNP_AddID() done (returns %lx)\n", ret);
3263
3264 return ret;
3265 }
3266
3267
3268 /* Function 35 */
3269 DWORD
3270 WINAPI
3271 PNP_RegisterDriver(
3272 handle_t hBinding,
3273 LPWSTR pszDeviceID,
3274 DWORD ulFlags)
3275 {
3276 DPRINT("PNP_RegisterDriver(%p %S 0x%lx)\n",
3277 hBinding, pszDeviceID, ulFlags);
3278
3279 if (ulFlags & ~CM_REGISTER_DEVICE_DRIVER_BITS)
3280 return CR_INVALID_FLAG;
3281
3282 if (!IsValidDeviceInstanceID(pszDeviceID))
3283 return CR_INVALID_DEVINST;
3284
3285 SetDeviceStatus(pszDeviceID, 0, 0);
3286
3287 return CR_SUCCESS;
3288 }
3289
3290
3291 /* Function 36 */
3292 DWORD
3293 WINAPI
3294 PNP_QueryRemove(
3295 handle_t hBinding,
3296 LPWSTR pszDeviceID,
3297 PPNP_VETO_TYPE pVetoType,
3298 LPWSTR pszVetoName,
3299 DWORD ulNameLength,
3300 DWORD ulFlags)
3301 {
3302 PLUGPLAY_CONTROL_QUERY_REMOVE_DATA PlugPlayData;
3303 NTSTATUS Status;
3304 DWORD ret = CR_SUCCESS;
3305
3306 DPRINT1("PNP_QueryRemove(%p %S %p %p %lu 0x%lx)\n",
3307 hBinding, pszDeviceID, pVetoType, pszVetoName,
3308 ulNameLength, ulFlags);
3309
3310 if (ulFlags & ~CM_REMOVE_BITS)
3311 return CR_INVALID_FLAG;
3312
3313 if (!IsValidDeviceInstanceID(pszDeviceID) ||
3314 IsRootDeviceInstanceID(pszDeviceID))
3315 return CR_INVALID_DEVINST;
3316
3317 if (pVetoType != NULL)
3318 *pVetoType = PNP_VetoTypeUnknown;
3319
3320 if (pszVetoName != NULL && ulNameLength > 0)
3321 *pszVetoName = UNICODE_NULL;
3322
3323 RtlZeroMemory(&PlugPlayData, sizeof(PlugPlayData));
3324 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
3325 pszDeviceID);
3326 PlugPlayData.VetoName = pszVetoName;
3327 PlugPlayData.NameLength = ulNameLength;
3328 // PlugPlayData.Flags =
3329
3330 Status = NtPlugPlayControl(PlugPlayControlQueryAndRemoveDevice,
3331 &PlugPlayData,
3332 sizeof(PlugPlayData));
3333 if (!NT_SUCCESS(Status))
3334 ret = NtStatusToCrError(Status);
3335
3336 return ret;
3337 }
3338
3339
3340 /* Function 37 */
3341 DWORD
3342 WINAPI
3343 PNP_RequestDeviceEject(
3344 handle_t hBinding,
3345 LPWSTR pszDeviceID,
3346 PPNP_VETO_TYPE pVetoType,
3347 LPWSTR pszVetoName,
3348 DWORD ulNameLength,
3349 DWORD ulFlags)
3350 {
3351 PLUGPLAY_CONTROL_QUERY_REMOVE_DATA PlugPlayData;
3352 NTSTATUS Status;
3353 DWORD ret = CR_SUCCESS;
3354
3355 DPRINT1("PNP_RequestDeviceEject(%p %S %p %p %lu 0x%lx)\n",
3356 hBinding, pszDeviceID, pVetoType, pszVetoName,
3357 ulNameLength, ulFlags);
3358
3359 if (ulFlags != 0)
3360 return CR_INVALID_FLAG;
3361
3362 if (!IsValidDeviceInstanceID(pszDeviceID))
3363 return CR_INVALID_DEVINST;
3364
3365 if (pVetoType != NULL)
3366 *pVetoType = PNP_VetoTypeUnknown;
3367
3368 if (pszVetoName != NULL && ulNameLength > 0)
3369 *pszVetoName = UNICODE_NULL;
3370
3371 RtlZeroMemory(&PlugPlayData, sizeof(PlugPlayData));
3372 RtlInitUnicodeString(&PlugPlayData.DeviceInstance,
3373 pszDeviceID);
3374 PlugPlayData.VetoName = pszVetoName;
3375 PlugPlayData.NameLength = ulNameLength;
3376 // PlugPlayData.Flags =
3377
3378 Status = NtPlugPlayControl(PlugPlayControlQueryAndRemoveDevice,
3379 &PlugPlayData,
3380 sizeof(PlugPlayData));
3381 if (!NT_SUCCESS(Status))
3382 ret = NtStatusToCrError(Status);
3383
3384 return ret;
3385 }
3386
3387
3388 /* Function 38 */
3389 CONFIGRET
3390 WINAPI
3391 PNP_IsDockStationPresent(
3392 handle_t hBinding,
3393 BOOL *Present)
3394 {
3395 HKEY hKey;
3396 DWORD dwType;
3397 DWORD dwValue;
3398 DWORD dwSize;
3399 CONFIGRET ret = CR_SUCCESS;
3400
3401 UNREFERENCED_PARAMETER(hBinding);
3402
3403 DPRINT1("PNP_IsDockStationPresent(%p %p)\n",
3404 hBinding, Present);
3405
3406 *Present = FALSE;
3407
3408 if (RegOpenKeyExW(HKEY_CURRENT_CONFIG,
3409 L"CurrentDockInfo",
3410 0,
3411 KEY_READ,
3412 &hKey) != ERROR_SUCCESS)
3413 return CR_REGISTRY_ERROR;
3414
3415 dwSize = sizeof(DWORD);
3416 if (RegQueryValueExW(hKey,
3417 L"DockingState",
3418 NULL,
3419 &dwType,
3420 (LPBYTE)&dwValue,
3421 &dwSize) != ERROR_SUCCESS)
3422 ret = CR_REGISTRY_ERROR;
3423
3424 RegCloseKey(hKey);
3425
3426 if (ret == CR_SUCCESS)
3427 {
3428 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
3429 {
3430 ret = CR_REGISTRY_ERROR;
3431 }
3432 else if (dwValue != 0)
3433 {
3434 *Present = TRUE;
3435 }
3436 }
3437
3438 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
3439
3440 return ret;
3441 }
3442
3443
3444 /* Function 39 */
3445 DWORD
3446 WINAPI
3447 PNP_RequestEjectPC(
3448 handle_t hBinding)
3449 {
3450 WCHAR szDockDeviceInstance[MAX_DEVICE_ID_LEN];
3451 PLUGPLAY_CONTROL_RETRIEVE_DOCK_DATA DockData;
3452 NTSTATUS Status;
3453
3454 DPRINT("PNP_RequestEjectPC(%p)\n", hBinding);
3455
3456 /* Retrieve the dock device */
3457 DockData.DeviceInstanceLength = ARRAYSIZE(szDockDeviceInstance);
3458 DockData.DeviceInstance = szDockDeviceInstance;
3459
3460 Status = NtPlugPlayControl(PlugPlayControlRetrieveDock,
3461 &DockData,
3462 sizeof(DockData));
3463 if (!NT_SUCCESS(Status))
3464 return NtStatusToCrError(Status);
3465
3466 /* Eject the dock device */
3467 return PNP_RequestDeviceEject(hBinding,
3468 szDockDeviceInstance,
3469 NULL,
3470 NULL,
3471 0,
3472 0);
3473 }
3474
3475
3476 /* Function 40 */
3477 DWORD
3478 WINAPI
3479 PNP_HwProfFlags(
3480 handle_t hBinding,
3481 DWORD ulAction,
3482 LPWSTR pDeviceID,
3483 DWORD ulConfig,
3484 DWORD *pulValue,
3485 PPNP_VETO_TYPE pVetoType,
3486 LPWSTR pszVetoName,
3487 DWORD ulNameLength,
3488 DWORD ulFlags)
3489 {
3490 CONFIGRET ret = CR_SUCCESS;
3491 WCHAR szKeyName[MAX_PATH];
3492 HKEY hKey;
3493 HKEY hDeviceKey;
3494 DWORD dwSize;
3495
3496 UNREFERENCED_PARAMETER(hBinding);
3497
3498 DPRINT("PNP_HwProfFlags() called\n");
3499
3500 if (!IsValidDeviceInstanceID(pDeviceID))
3501 return CR_INVALID_DEVINST;
3502
3503 if (ulConfig == 0)
3504 {
3505 wcscpy(szKeyName,
3506 L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
3507 }
3508 else
3509 {
3510 swprintf(szKeyName,
3511 L"System\\CurrentControlSet\\HardwareProfiles\\%04lu\\System\\CurrentControlSet\\Enum",
3512 ulConfig);
3513 }
3514
3515 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3516 szKeyName,
3517 0,
3518 KEY_QUERY_VALUE,
3519 &hKey) != ERROR_SUCCESS)
3520 return CR_REGISTRY_ERROR;
3521
3522 if (ulAction == PNP_GET_HWPROFFLAGS)
3523 {
3524 if (RegOpenKeyExW(hKey,
3525 pDeviceID,
3526 0,
3527 KEY_QUERY_VALUE,
3528 &hDeviceKey) != ERROR_SUCCESS)
3529 {
3530 *pulValue = 0;
3531 }
3532 else
3533 {
3534 dwSize = sizeof(DWORD);
3535 if (RegQueryValueExW(hDeviceKey,
3536 L"CSConfigFlags",
3537 NULL,
3538 NULL,
3539 (LPBYTE)pulValue,
3540 &dwSize) != ERROR_SUCCESS)
3541 {
3542 *pulValue = 0;
3543 }
3544
3545 RegCloseKey(hDeviceKey);
3546 }
3547 }
3548 else if (ulAction == PNP_SET_HWPROFFLAGS)
3549 {
3550 /* FIXME: not implemented yet */
3551 ret = CR_CALL_NOT_IMPLEMENTED;
3552 }
3553
3554 RegCloseKey(hKey);
3555
3556 return ret;
3557 }
3558
3559
3560 /* Function 41 */
3561 DWORD
3562 WINAPI
3563 PNP_GetHwProfInfo(
3564 handle_t hBinding,
3565 DWORD ulIndex,
3566 HWPROFILEINFO *pHWProfileInfo,
3567 DWORD ulProfileInfoSize,
3568 DWORD ulFlags)
3569 {
3570 WCHAR szProfileName[5];
3571 HKEY hKeyConfig = NULL;
3572 HKEY hKeyProfiles = NULL;
3573 HKEY hKeyProfile = NULL;
3574 DWORD dwDisposition;
3575 DWORD dwSize;
3576 LONG lError;
3577 CONFIGRET ret = CR_SUCCESS;
3578
3579 UNREFERENCED_PARAMETER(hBinding);
3580
3581 DPRINT("PNP_GetHwProfInfo() called\n");
3582
3583 if (ulProfileInfoSize == 0)
3584 {
3585 ret = CR_INVALID_DATA;
3586 goto done;
3587 }
3588
3589 if (ulFlags != 0)
3590 {
3591 ret = CR_INVALID_FLAG;
3592 goto done;
3593 }
3594
3595 /* Initialize the profile information */
3596 pHWProfileInfo->HWPI_ulHWProfile = 0;
3597 pHWProfileInfo->HWPI_szFriendlyName[0] = 0;
3598 pHWProfileInfo->HWPI_dwFlags = 0;
3599
3600 /* Open the 'IDConfigDB' key */
3601 lError = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
3602 L"System\\CurrentControlSet\\Control\\IDConfigDB",
3603 0,
3604 NULL,
3605 REG_OPTION_NON_VOLATILE,
3606 KEY_QUERY_VALUE,
3607 NULL,
3608 &hKeyConfig,
3609 &dwDisposition);
3610 if (lError != ERROR_SUCCESS)
3611 {
3612 ret = CR_REGISTRY_ERROR;
3613 goto done;
3614 }
3615
3616 /* Open the 'Hardware Profiles' subkey */
3617 lError = RegCreateKeyExW(hKeyConfig,
3618 L"Hardware Profiles",
3619 0,
3620 NULL,
3621 REG_OPTION_NON_VOLATILE,
3622 KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
3623 NULL,
3624 &hKeyProfiles,
3625 &dwDisposition);
3626 if (lError != ERROR_SUCCESS)
3627 {
3628 ret = CR_REGISTRY_ERROR;
3629 goto done;
3630 }
3631
3632 if (ulIndex == (ULONG)-1)
3633 {
3634 dwSize = sizeof(ULONG);
3635 lError = RegQueryValueExW(hKeyConfig,
3636 L"CurrentConfig",
3637 NULL,
3638 NULL,
3639 (LPBYTE)&pHWProfileInfo->HWPI_ulHWProfile,
3640 &dwSize);
3641 if (lError != ERROR_SUCCESS)
3642 {
3643 pHWProfileInfo->HWPI_ulHWProfile = 0;
3644 ret = CR_REGISTRY_ERROR;
3645 goto done;
3646 }
3647 }
3648 else
3649 {
3650 /* FIXME: not implemented yet */
3651 ret = CR_CALL_NOT_IMPLEMENTED;
3652 goto done;
3653 }
3654
3655 swprintf(szProfileName, L"%04lu", pHWProfileInfo->HWPI_ulHWProfile);
3656
3657 lError = RegOpenKeyExW(hKeyProfiles,
3658 szProfileName,
3659 0,
3660 KEY_QUERY_VALUE,
3661 &hKeyProfile);
3662 if (lError != ERROR_SUCCESS)
3663 {
3664 ret = CR_REGISTRY_ERROR;
3665 goto done;
3666 }
3667
3668 dwSize = sizeof(pHWProfileInfo->HWPI_szFriendlyName);
3669 lError = RegQueryValueExW(hKeyProfile,
3670 L"FriendlyName",
3671 NULL,
3672 NULL,
3673 (LPBYTE)&pHWProfileInfo->HWPI_szFriendlyName,
3674 &dwSize);
3675 if (lError != ERROR_SUCCESS)
3676 {
3677 ret = CR_REGISTRY_ERROR;
3678 goto done;
3679 }
3680
3681 done:
3682 if (hKeyProfile != NULL)
3683 RegCloseKey(hKeyProfile);
3684
3685 if (hKeyProfiles != NULL)
3686 RegCloseKey(hKeyProfiles);
3687
3688 if (hKeyConfig != NULL)
3689 RegCloseKey(hKeyConfig);
3690
3691 return ret;
3692 }
3693
3694
3695 /* Function 42 */
3696 DWORD
3697 WINAPI
3698 PNP_AddEmptyLogConf(
3699 handle_t hBinding,
3700 LPWSTR pDeviceID,
3701 DWORD ulPriority,
3702 DWORD *pulLogConfTag,
3703 DWORD ulFlags)
3704 {
3705 UNIMPLEMENTED;
3706 return CR_CALL_NOT_IMPLEMENTED;
3707 }
3708
3709
3710 /* Function 43 */
3711 DWORD
3712 WINAPI
3713 PNP_FreeLogConf(
3714 handle_t hBinding,
3715 LPWSTR pDeviceID,
3716 DWORD ulLogConfType,
3717 DWORD ulLogConfTag,
3718 DWORD ulFlags)
3719 {
3720 UNIMPLEMENTED;
3721 return CR_CALL_NOT_IMPLEMENTED;
3722 }
3723
3724
3725 /* Function 44 */
3726 DWORD
3727 WINAPI
3728 PNP_GetFirstLogConf(
3729 handle_t hBinding,
3730 LPWSTR pDeviceID,
3731 DWORD ulLogConfType,
3732 DWORD *pulLogConfTag,
3733 DWORD ulFlags)
3734 {
3735 UNIMPLEMENTED;
3736 return CR_CALL_NOT_IMPLEMENTED;
3737 }
3738
3739
3740 /* Function 45 */
3741 DWORD
3742 WINAPI
3743 PNP_GetNextLogConf(
3744 handle_t hBinding,
3745 LPWSTR pDeviceID,
3746 DWORD ulLogConfType,
3747 DWORD ulCurrentTag,
3748 DWORD *pulNextTag,
3749 DWORD ulFlags)
3750 {
3751 UNIMPLEMENTED;
3752 return CR_CALL_NOT_IMPLEMENTED;
3753 }
3754
3755
3756 /* Function 46 */
3757 DWORD
3758 WINAPI
3759 PNP_GetLogConfPriority(
3760 handle_t hBinding,
3761 LPWSTR pDeviceID,
3762 DWORD ulType,
3763 DWORD ulTag,
3764 DWORD *pPriority,
3765 DWORD ulFlags)
3766 {
3767 UNIMPLEMENTED;
3768 return CR_CALL_NOT_IMPLEMENTED;
3769 }
3770
3771
3772 /* Function 47 */
3773 DWORD
3774 WINAPI
3775 PNP_AddResDes(
3776 handle_t hBinding,
3777 LPWSTR pDeviceID,
3778 DWORD ulLogConfTag,
3779 DWORD ulLogConfType,
3780 RESOURCEID ResourceID,
3781 DWORD *pulResourceTag,
3782 BYTE *ResourceData,
3783 PNP_RPC_BUFFER_SIZE ResourceLen,
3784 DWORD ulFlags)
3785 {
3786 UNIMPLEMENTED;
3787 return CR_CALL_NOT_IMPLEMENTED;
3788 }
3789
3790
3791 /* Function 48 */
3792 DWORD
3793 WINAPI
3794 PNP_FreeResDes(
3795 handle_t hBinding,
3796 LPWSTR pDeviceID,
3797 DWORD ulLogConfTag,
3798 DWORD ulLogConfType,
3799 RESOURCEID ResourceID,
3800 DWORD ulResourceTag,
3801 DWORD *pulPreviousResType,
3802 DWORD *pulPreviousResTag,
3803 DWORD ulFlags)
3804 {
3805 UNIMPLEMENTED;
3806 return CR_CALL_NOT_IMPLEMENTED;
3807 }
3808
3809
3810 /* Function 49 */
3811 DWORD
3812 WINAPI
3813 PNP_GetNextResDes(
3814 handle_t hBinding,
3815 LPWSTR pDeviceID,
3816 DWORD ulLogConfTag,
3817 DWORD ulLogConfType,
3818 RESOURCEID ResourceID,
3819 DWORD ulResourceTag,
3820 DWORD *pulNextResType,
3821 DWORD *pulNextResTag,
3822 DWORD ulFlags)
3823 {
3824 UNIMPLEMENTED;
3825 return CR_CALL_NOT_IMPLEMENTED;
3826 }
3827
3828
3829 /* Function 50 */
3830 DWORD
3831 WINAPI
3832 PNP_GetResDesData(
3833 handle_t hBinding,
3834 LPWSTR pDeviceID,
3835 DWORD ulLogConfTag,
3836 DWORD ulLogConfType,
3837 RESOURCEID ResourceID,
3838 DWORD ulResourceTag,
3839 BYTE *Buffer,
3840 PNP_RPC_BUFFER_SIZE BufferLen,
3841 DWORD ulFlags)
3842 {
3843 UNIMPLEMENTED;
3844 return CR_CALL_NOT_IMPLEMENTED;
3845 }
3846
3847
3848 /* Function 51 */
3849 DWORD
3850 WINAPI
3851 PNP_GetResDesDataSize(
3852 handle_t hBinding,
3853 LPWSTR pDeviceID,
3854 DWORD ulLogConfTag,
3855 DWORD ulLogConfType,
3856 RESOURCEID ResourceID,
3857 DWORD ulResourceTag,
3858 DWORD *pulSize,
3859 DWORD ulFlags)
3860 {
3861 UNIMPLEMENTED;
3862 return CR_CALL_NOT_IMPLEMENTED;
3863 }
3864
3865
3866 /* Function 52 */
3867 DWORD
3868 WINAPI
3869 PNP_ModifyResDes(
3870 handle_t hBinding,
3871 LPWSTR pDeviceID,
3872 DWORD ulLogConfTag,
3873 DWORD ulLogConfType,
3874 RESOURCEID CurrentResourceID,
3875 RESOURCEID NewResourceID,
3876 DWORD ulResourceTag,
3877 BYTE *ResourceData,
3878 PNP_RPC_BUFFER_SIZE ResourceLen,
3879 DWORD ulFlags)
3880 {
3881 UNIMPLEMENTED;
3882 return CR_CALL_NOT_IMPLEMENTED;
3883 }
3884
3885
3886 /* Function 53 */
3887 DWORD
3888 WINAPI
3889 PNP_DetectResourceConflict(
3890 handle_t hBinding,
3891 LPWSTR pDeviceID,
3892 RESOURCEID ResourceID,
3893 BYTE *ResourceData,
3894 PNP_RPC_BUFFER_SIZE ResourceLen,
3895 BOOL *pbConflictDetected,
3896 DWORD ulFlags)
3897 {
3898 DPRINT("PNP_DetectResourceConflict()\n");
3899
3900 if (pbConflictDetected != NULL)
3901 *pbConflictDetected = FALSE;
3902
3903 return CR_CALL_NOT_IMPLEMENTED;
3904 }
3905
3906
3907 /* Function 54 */
3908 DWORD
3909 WINAPI
3910 PNP_QueryResConfList(
3911 handle_t hBinding,
3912 LPWSTR pDeviceID,
3913 RESOURCEID ResourceID,
3914 BYTE *ResourceData,
3915 PNP_RPC_BUFFER_SIZE ResourceLen,
3916 BYTE *Buffer,
3917 PNP_RPC_BUFFER_SIZE BufferLen,
3918 DWORD ulFlags)
3919 {
3920 UNIMPLEMENTED;
3921 return CR_CALL_NOT_IMPLEMENTED;
3922 }
3923
3924
3925 /* Function 55 */
3926 DWORD
3927 WINAPI
3928 PNP_SetHwProf(
3929 handle_t hBinding,
3930 DWORD ulHardwareProfile,
3931 DWORD ulFlags)
3932 {
3933 return CR_CALL_NOT_IMPLEMENTED;
3934 }
3935
3936
3937 /* Function 56 */
3938 DWORD
3939 WINAPI
3940 PNP_QueryArbitratorFreeData(
3941 handle_t hBinding,
3942 BYTE *pData,
3943 DWORD DataLen,
3944 LPWSTR pDeviceID,
3945 RESOURCEID ResourceID,
3946 DWORD ulFlags)
3947 {
3948 return CR_CALL_NOT_IMPLEMENTED;
3949 }
3950
3951
3952 /* Function 57 */
3953 DWORD
3954 WINAPI
3955 PNP_QueryArbitratorFreeSize(
3956 handle_t hBinding,
3957 DWORD *pulSize,
3958 LPWSTR pDeviceID,
3959 RESOURCEID ResourceID,
3960 DWORD ulFlags)
3961 {
3962 if (pulSize != NULL)
3963 *pulSize = 0;
3964
3965 return CR_CALL_NOT_IMPLEMENTED;
3966 }
3967
3968
3969 /* Function 58 */
3970 CONFIGRET
3971 WINAPI
3972 PNP_RunDetection(
3973 handle_t hBinding,
3974 DWORD ulFlags)
3975 {
3976 return CR_CALL_NOT_IMPLEMENTED;
3977 }
3978
3979
3980 /* Function 59 */
3981 DWORD
3982 WINAPI
3983 PNP_RegisterNotification(
3984 handle_t hBinding,
3985 DWORD ulUnknown2,
3986 LPWSTR pszName,
3987 BYTE *pNotificationFilter,
3988 DWORD ulNotificationFilterSize,
3989 DWORD ulFlags,
3990 DWORD *pulNotify,
3991 DWORD ulUnknown8,
3992 DWORD *pulUnknown9)
3993 {
3994 PDEV_BROADCAST_DEVICEINTERFACE_W pBroadcastDeviceInterface;
3995 PDEV_BROADCAST_HANDLE pBroadcastDeviceHandle;
3996 #if 0
3997 PNOTIFY_DATA pNotifyData;
3998 #endif
3999
4000 DPRINT1("PNP_RegisterNotification(%p %lx '%S' %p %lu 0x%lx %p %lx %p)\n",
4001 hBinding, ulUnknown2, pszName, pNotificationFilter,
4002 ulNotificationFilterSize, ulFlags, pulNotify, ulUnknown8, pulUnknown9);
4003
4004 if (pNotificationFilter == NULL ||
4005 pulNotify == NULL ||
4006 pulUnknown9 == NULL)
4007 return CR_INVALID_POINTER;
4008
4009 if (ulFlags & ~0x7)
4010 return CR_INVALID_FLAG;
4011
4012 if ((ulNotificationFilterSize < sizeof(DEV_BROADCAST_HDR)) ||
4013 (((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_size < sizeof(DEV_BROADCAST_HDR)))
4014 return CR_INVALID_DATA;
4015
4016 if (((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
4017 {
4018 DPRINT1("DBT_DEVTYP_DEVICEINTERFACE\n");
4019 pBroadcastDeviceInterface = (PDEV_BROADCAST_DEVICEINTERFACE_W)pNotificationFilter;
4020
4021 if ((ulNotificationFilterSize < sizeof(DEV_BROADCAST_DEVICEINTERFACE_W)) ||
4022 (pBroadcastDeviceInterface->dbcc_size < sizeof(DEV_BROADCAST_DEVICEINTERFACE_W)))
4023 return CR_INVALID_DATA;
4024 }
4025 else if (((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_devicetype == DBT_DEVTYP_HANDLE)
4026 {
4027 DPRINT1("DBT_DEVTYP_HANDLE\n");
4028 pBroadcastDeviceHandle = (PDEV_BROADCAST_HANDLE)pNotificationFilter;
4029
4030 if ((ulNotificationFilterSize < sizeof(DEV_BROADCAST_HANDLE)) ||
4031 (pBroadcastDeviceHandle->dbch_size < sizeof(DEV_BROADCAST_HANDLE)))
4032 return CR_INVALID_DATA;
4033
4034 if (ulFlags & DEVICE_NOTIFY_ALL_INTERFACE_CLASSES)
4035 return CR_INVALID_FLAG;
4036 }
4037 else
4038 {
4039 DPRINT1("Invalid device type %lu\n", ((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_devicetype);
4040 return CR_INVALID_DATA;
4041 }
4042
4043
4044 #if 0
4045 pNotifyData = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NOTIFY_DATA));
4046 if (pNotifyData == NULL)
4047 return CR_OUT_OF_MEMORY;
4048
4049 *pulNotify = (DWORD)pNotifyData;
4050 #endif
4051
4052 *pulNotify = 1;
4053
4054 return CR_SUCCESS;
4055 }
4056
4057
4058 /* Function 60 */
4059 DWORD
4060 WINAPI
4061 PNP_UnregisterNotification(
4062 handle_t hBinding,
4063 DWORD ulNotify)
4064 {
4065 DPRINT1("PNP_UnregisterNotification(%p 0x%lx)\n",
4066 hBinding, ulNotify);
4067
4068 #if 0
4069 UNIMPLEMENTED;
4070 return CR_CALL_NOT_IMPLEMENTED;
4071 #endif
4072
4073 return CR_SUCCESS;
4074 }
4075
4076
4077 /* Function 61 */
4078 DWORD
4079 WINAPI
4080 PNP_GetCustomDevProp(
4081 handle_t hBinding,
4082 LPWSTR pDeviceID,
4083 LPWSTR CustomPropName,
4084 DWORD *pulRegDataType,
4085 BYTE *Buffer,
4086 PNP_RPC_STRING_LEN *pulTransferLen,
4087 PNP_RPC_STRING_LEN *pulLength,
4088 DWORD ulFlags)
4089 {
4090 HKEY hDeviceKey = NULL;
4091 HKEY hParamKey = NULL;
4092 LONG lError;
4093 CONFIGRET ret = CR_SUCCESS;
4094
4095 UNREFERENCED_PARAMETER(hBinding);
4096
4097 DPRINT("PNP_GetCustomDevProp() called\n");
4098
4099 if (pulTransferLen == NULL || pulLength == NULL)
4100 {
4101 ret = CR_INVALID_POINTER;
4102 goto done;
4103 }
4104
4105 if (ulFlags & ~CM_CUSTOMDEVPROP_BITS)
4106 {
4107 ret = CR_INVALID_FLAG;
4108 goto done;
4109 }
4110
4111 if (!IsValidDeviceInstanceID(pDeviceID))
4112 return CR_INVALID_DEVINST;
4113
4114 if (*pulLength < *pulTransferLen)
4115 *pulLength = *pulTransferLen;
4116
4117 *pulTransferLen = 0;
4118
4119 lError = RegOpenKeyExW(hEnumKey,
4120 pDeviceID,
4121 0,
4122 KEY_READ,
4123 &hDeviceKey);
4124 if (lError != ERROR_SUCCESS)
4125 {
4126 ret = CR_REGISTRY_ERROR;
4127 goto done;
4128 }
4129
4130 lError = RegOpenKeyExW(hDeviceKey,
4131 L"Device Parameters",
4132 0,
4133 KEY_READ,
4134 &hParamKey);
4135 if (lError != ERROR_SUCCESS)
4136 {
4137 ret = CR_REGISTRY_ERROR;
4138 goto done;
4139 }
4140
4141 lError = RegQueryValueExW(hParamKey,
4142 CustomPropName,
4143 NULL,
4144 pulRegDataType,
4145 Buffer,
4146 pulLength);
4147 if (lError != ERROR_SUCCESS)
4148 {
4149 if (lError == ERROR_MORE_DATA)
4150 {
4151 ret = CR_BUFFER_SMALL;
4152 }
4153 else
4154 {
4155 *pulLength = 0;
4156 ret = CR_NO_SUCH_VALUE;
4157 }
4158 }
4159
4160 done:
4161 if (ret == CR_SUCCESS)
4162 *pulTransferLen = *pulLength;
4163
4164 if (hParamKey != NULL)
4165 RegCloseKey(hParamKey);
4166
4167 if (hDeviceKey != NULL)
4168 RegCloseKey(hDeviceKey);
4169
4170 DPRINT("PNP_GetCustomDevProp() done (returns %lx)\n", ret);
4171
4172 return ret;
4173 }
4174
4175
4176 /* Function 62 */
4177 DWORD
4178 WINAPI
4179 PNP_GetVersionInternal(
4180 handle_t hBinding,
4181 WORD *pwVersion)
4182 {
4183 UNREFERENCED_PARAMETER(hBinding);
4184
4185 *pwVersion = 0x501;
4186 return CR_SUCCESS;
4187 }
4188
4189
4190 /* Function 63 */
4191 DWORD
4192 WINAPI
4193 PNP_GetBlockedDriverInfo(
4194 handle_t hBinding,
4195 BYTE *Buffer,
4196 PNP_RPC_BUFFER_SIZE *pulTransferLen,
4197 PNP_RPC_BUFFER_SIZE *pulLength,
4198 DWORD ulFlags)
4199 {
4200 UNIMPLEMENTED;
4201 return CR_CALL_NOT_IMPLEMENTED;
4202 }
4203
4204
4205 /* Function 64 */
4206 DWORD
4207 WINAPI
4208 PNP_GetServerSideDeviceInstallFlags(
4209 handle_t hBinding,
4210 DWORD *pulSSDIFlags,
4211 DWORD ulFlags)
4212 {
4213 UNREFERENCED_PARAMETER(hBinding);
4214
4215 DPRINT1("PNP_GetServerSideDeviceInstallFlags(%p %p %lu)\n",
4216 hBinding, pulSSDIFlags, ulFlags);
4217
4218 if (pulSSDIFlags == NULL)
4219 return CR_INVALID_POINTER;
4220
4221 if (ulFlags != 0)
4222 return CR_INVALID_FLAG;
4223
4224 /* FIXME */
4225 *pulSSDIFlags = 0;
4226
4227 return CR_SUCCESS;
4228 }
4229
4230
4231 /* Function 65 */
4232 DWORD
4233 WINAPI
4234 PNP_GetObjectPropKeys(
4235 handle_t hBinding,
4236 LPWSTR ObjectName,
4237 DWORD ObjectType,
4238 LPWSTR PropertyCultureName,
4239 PNP_PROP_COUNT *PropertyCount,
4240 PNP_PROP_COUNT *TransferLen,
4241 DEVPROPKEY *PropertyKeys,
4242 DWORD Flags)
4243 {
4244 UNIMPLEMENTED;
4245 return CR_CALL_NOT_IMPLEMENTED;
4246 }
4247
4248
4249 /* Function 66 */
4250 DWORD
4251 WINAPI
4252 PNP_GetObjectProp(
4253 handle_t hBinding,
4254 LPWSTR ObjectName,
4255 DWORD ObjectType,
4256 LPWSTR PropertyCultureName,
4257 const DEVPROPKEY *PropertyKey,
4258 DEVPROPTYPE *PropertyType,
4259 PNP_PROP_SIZE *PropertySize,
4260 PNP_PROP_SIZE *TransferLen,
4261 BYTE *PropertyBuffer,
4262 DWORD Flags)
4263 {
4264 UNIMPLEMENTED;
4265 return CR_CALL_NOT_IMPLEMENTED;
4266 }
4267
4268
4269 /* Function 67 */
4270 DWORD
4271 WINAPI
4272 PNP_SetObjectProp(
4273 handle_t hBinding,
4274 LPWSTR ObjectName,
4275 DWORD ObjectType,
4276 LPWSTR PropertyCultureName,
4277 const DEVPROPKEY *PropertyKey,
4278 DEVPROPTYPE PropertyType,
4279 PNP_PROP_SIZE PropertySize,
4280 BYTE *PropertyBuffer,
4281 DWORD Flags)
4282 {
4283 UNIMPLEMENTED;
4284 return CR_CALL_NOT_IMPLEMENTED;
4285 }
4286
4287
4288 /* Function 68 */
4289 DWORD
4290 WINAPI
4291 PNP_InstallDevInst(
4292 handle_t hBinding)
4293 {
4294 UNIMPLEMENTED;
4295 return CR_CALL_NOT_IMPLEMENTED;
4296 }
4297
4298
4299 /* Function 69 */
4300 DWORD
4301 WINAPI
4302 PNP_ApplyPowerSettings(
4303 handle_t hBinding)
4304 {
4305 UNIMPLEMENTED;
4306 return CR_CALL_NOT_IMPLEMENTED;
4307 }
4308
4309
4310 /* Function 70 */
4311 DWORD
4312 WINAPI
4313 PNP_DriverStoreAddDriverPackage(
4314 handle_t hBinding)
4315 {
4316 UNIMPLEMENTED;
4317 return CR_CALL_NOT_IMPLEMENTED;
4318 }
4319
4320
4321 /* Function 71 */
4322 DWORD
4323 WINAPI
4324 PNP_DriverStoreDeleteDriverPackage(
4325 handle_t hBinding)
4326 {
4327 UNIMPLEMENTED;
4328 return CR_CALL_NOT_IMPLEMENTED;
4329 }
4330
4331
4332 /* Function 72 */
4333 DWORD
4334 WINAPI
4335 PNP_RegisterServiceNotification(
4336 handle_t hBinding)
4337 {
4338 UNIMPLEMENTED;
4339 return CR_CALL_NOT_IMPLEMENTED;
4340 }
4341
4342
4343 /* Function 73 */
4344 DWORD
4345 WINAPI
4346 PNP_SetActiveService(
4347 handle_t hBinding,
4348 LPWSTR pszFilter,
4349 DWORD ulFlags)
4350 {
4351 UNIMPLEMENTED;
4352 return CR_CALL_NOT_IMPLEMENTED;
4353 }
4354
4355
4356 /* Function 74 */
4357 DWORD
4358 WINAPI
4359 PNP_DeleteServiceDevices(
4360 handle_t hBinding)
4361 {
4362 UNIMPLEMENTED;
4363 return CR_CALL_NOT_IMPLEMENTED;
4364 }