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