ReactOS 0.4.15-dev-8241-g63935f8
rpcserver.c
Go to the documentation of this file.
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
39static WCHAR szRootDeviceInstanceID[] = L"HTREE\\ROOT\\0";
40
42
43/* FUNCTIONS *****************************************************************/
44
47{
49 BOOLEAN RegisteredProtSeq = FALSE;
50
51 UNREFERENCED_PARAMETER(lpParameter);
52
53 DPRINT("RpcServerThread() called\n");
54
56
57#if 0
58 /* 2k/XP/2k3-compatible protocol sequence/endpoint */
60 20,
61 L"\\pipe\\ntsvcs",
62 NULL); // Security descriptor
63 if (Status == RPC_S_OK)
64 RegisteredProtSeq = TRUE;
65 else
66 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
67#endif
68
69 /* Vista/7-compatible protocol sequence/endpoint */
71 20,
72 L"\\pipe\\plugplay",
73 NULL); // Security descriptor
74 if (Status == RPC_S_OK)
75 RegisteredProtSeq = TRUE;
76 else
77 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
78
79 /* Make sure there's a usable endpoint */
80 if (RegisteredProtSeq == FALSE)
81 return 0;
82
83 Status = RpcServerRegisterIf(pnp_v1_0_s_ifspec,
84 NULL,
85 NULL);
86 if (Status != RPC_S_OK)
87 {
88 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
89 return 0;
90 }
91
93 20,
94 FALSE);
95 if (Status != RPC_S_OK)
96 {
97 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
98 return 0;
99 }
100
101 /* ROS HACK (this should never happen...) */
102 DPRINT1("*** Other devices won't be installed correctly. If something\n");
103 DPRINT1("*** doesn't work, try to reboot to get a new chance.\n");
104
105 DPRINT("RpcServerThread() done\n");
106
107 return 0;
108}
109
110
112{
114}
115
116
118{
120}
121
122
123static CONFIGRET WINAPI
125{
126 switch (Status)
127 {
130
132 return CR_INVALID_DATA;
133
135 return CR_NO_SUCH_DEVINST;
136
138 return CR_ACCESS_DENIED;
139
141 return CR_BUFFER_SMALL;
142
144 return CR_NO_SUCH_VALUE;
145
146 default:
147 return CR_FAILURE;
148 }
149}
150
151
152static VOID
153SplitDeviceInstanceID(IN LPWSTR pszDeviceInstanceID,
154 OUT LPWSTR pszEnumerator,
155 OUT LPWSTR pszDevice,
156 OUT LPWSTR pszInstance)
157{
158 WCHAR szLocalDeviceInstanceID[MAX_DEVICE_ID_LEN];
159 LPWSTR lpEnumerator = NULL;
160 LPWSTR lpDevice = NULL;
161 LPWSTR lpInstance = NULL;
162 LPWSTR ptr;
163
164 wcscpy(szLocalDeviceInstanceID, pszDeviceInstanceID);
165
166 *pszEnumerator = 0;
167 *pszDevice = 0;
168 *pszInstance = 0;
169
170 lpEnumerator = szLocalDeviceInstanceID;
171
172 ptr = wcschr(lpEnumerator, L'\\');
173 if (ptr != NULL)
174 {
175 *ptr = 0;
176 lpDevice = ++ptr;
177
178 ptr = wcschr(lpDevice, L'\\');
179 if (ptr != NULL)
180 {
181 *ptr = 0;
182 lpInstance = ++ptr;
183 }
184 }
185
186 if (lpEnumerator != NULL)
187 wcscpy(pszEnumerator, lpEnumerator);
188
189 if (lpDevice != NULL)
190 wcscpy(pszDevice, lpDevice);
191
192 if (lpInstance != NULL)
193 wcscpy(pszInstance, lpInstance);
194}
195
196
197static
200 _In_ LPWSTR pszDeviceID,
201 _In_ DWORD ulStatus,
202 _In_ DWORD ulProblem)
203{
204 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
207
208 DPRINT1("ClearDeviceStatus(%S 0x%lx 0x%lx)\n",
209 pszDeviceID, ulStatus, ulProblem);
210
212 pszDeviceID);
213 PlugPlayData.Operation = PNP_CLEAR_DEVICE_STATUS;
214 PlugPlayData.DeviceStatus = ulStatus;
215 PlugPlayData.DeviceProblem = ulProblem;
216
218 (PVOID)&PlugPlayData,
220 if (!NT_SUCCESS(Status))
222
223 return ret;
224}
225
226
227static
230 _In_ LPWSTR pszDeviceID,
231 _Out_ DWORD *pulStatus,
232 _Out_ DWORD *pulProblem)
233{
234 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
237
238 DPRINT("GetDeviceStatus(%S %p %p)\n",
239 pszDeviceID, pulStatus, pulProblem);
240
242 pszDeviceID);
243 PlugPlayData.Operation = PNP_GET_DEVICE_STATUS;
244
246 (PVOID)&PlugPlayData,
248 if (NT_SUCCESS(Status))
249 {
250 *pulStatus = PlugPlayData.DeviceStatus;
251 *pulProblem = PlugPlayData.DeviceProblem;
252 }
253 else
254 {
256 }
257
258 return ret;
259}
260
261
262static
265 _In_ LPWSTR pszDeviceID,
266 _In_ DWORD ulStatus,
267 _In_ DWORD ulProblem)
268{
269 PLUGPLAY_CONTROL_STATUS_DATA PlugPlayData;
272
273 DPRINT1("SetDeviceStatus(%S 0x%lx 0x%lx)\n",
274 pszDeviceID, ulStatus, ulProblem);
275
277 pszDeviceID);
278 PlugPlayData.Operation = PNP_SET_DEVICE_STATUS;
279 PlugPlayData.DeviceStatus = ulStatus;
280 PlugPlayData.DeviceProblem = ulProblem;
281
283 (PVOID)&PlugPlayData,
285 if (!NT_SUCCESS(Status))
287
288 return ret;
289}
290
291
292static
295 _In_ LPWSTR pszDeviceInstance,
296 _Inout_opt_ PPNP_VETO_TYPE pVetoType,
297 _Inout_opt_ LPWSTR pszVetoName,
298 _In_ DWORD ulNameLength)
299{
303
304 DPRINT1("DisableDeviceInstance(%S %p %p %lu)\n",
305 pszDeviceInstance, pVetoType, pszVetoName, ulNameLength);
306
307 RtlInitUnicodeString(&QueryRemoveData.DeviceInstance,
308 pszDeviceInstance);
309
310 QueryRemoveData.Flags = 0;
311 QueryRemoveData.VetoType = 0;
312 QueryRemoveData.VetoName = pszVetoName;
313 QueryRemoveData.NameLength = ulNameLength;
314
316 &QueryRemoveData,
319 {
321 }
323 {
324 if (pVetoType != NULL)
325 *pVetoType = QueryRemoveData.VetoType;
326
328 }
329 else if (!NT_SUCCESS(Status))
330 {
332 }
333
334 return ret;
335}
336
337
338static
339BOOL
341 _In_ PWSTR pszDeviceInstanceID)
342{
343 INT nPartLength[3] = {0, 0, 0};
344 INT nLength = 0, nParts = 0;
345 PWCHAR p;
346
347 DPRINT("IsValidDeviceInstanceID(%S)\n",
348 pszDeviceInstanceID);
349
350 if (pszDeviceInstanceID == NULL)
351 {
352 DPRINT("Device instance ID is NULL!\n");
353 return FALSE;
354 }
355
356 p = pszDeviceInstanceID;
357 while (*p != UNICODE_NULL)
358 {
359 if (*p == L'\\')
360 {
361 nParts++;
362 if (nParts >= 3)
363 {
364 DPRINT("Too many separators: %d\n", nParts);
365 return FALSE;
366 }
367 }
368 else
369 {
370 nPartLength[nParts]++;
371 }
372
373 nLength++;
375 {
376 DPRINT("Too long: %d\n", nLength);
377 return FALSE;
378 }
379
380 p++;
381 }
382
383 if (nParts != 2)
384 {
385 DPRINT("Invalid number of separtors: %d\n", nParts);
386 return FALSE;
387 }
388
389 if ((nPartLength[0] == 0) ||
390 (nPartLength[1] == 0) ||
391 (nPartLength[2] == 0))
392 {
393 DPRINT("Invalid part lengths: %d %d %d\n",
394 nPartLength[0], nPartLength[1], nPartLength[2]);
395 return FALSE;
396 }
397
398 DPRINT("Valid device instance ID!\n");
399
400 return TRUE;
401}
402
403
404static
405BOOL
407 _In_ PWSTR pszDeviceInstanceID)
408{
409 if (_wcsicmp(pszDeviceInstanceID, szRootDeviceInstanceID) == 0)
410 return TRUE;
411
412 return FALSE;
413}
414
415
416static
417BOOL
419 _In_ LPWSTR pszDeviceInstanceID)
420{
421 DWORD ulStatus, ulProblem;
422
423 return (GetDeviceStatus(pszDeviceInstanceID, &ulStatus, &ulProblem) == CR_SUCCESS);
424}
425
426
427static
430 _In_ LPCWSTR pszDeviceID,
431 _In_ DWORD ulLogConfType,
432 _Out_ PHKEY phKey)
433{
434 WCHAR szKeyName[MAX_PATH];
435 PCWSTR pszSubKeyName;
436 HKEY hInstanceKey;
437 DWORD dwError;
438
439 /* Build the full device instance key name */
440 wcscpy(szKeyName, L"System\\CurrentControlSet\\Enum\\");
441 wcscat(szKeyName, pszDeviceID);
442
443 /* Open the device instance key */
445 szKeyName,
446 0,
448 &hInstanceKey);
449 if (dwError != ERROR_SUCCESS)
450 return CR_INVALID_DEVINST;
451
452 switch (ulLogConfType)
453 {
454 case BOOT_LOG_CONF:
455 case BASIC_LOG_CONF:
456 pszSubKeyName = L"LogConf";
457 break;
458
459 case ALLOC_LOG_CONF:
461 pszSubKeyName = L"Control";
462 break;
463
464 default:
465 DPRINT1("Unsupported configuration type!\n");
466 return CR_FAILURE;
467 }
468
469 /* Create or open the LogConf key */
470 dwError = RegCreateKeyExW(hInstanceKey,
471 pszSubKeyName,
472 0,
473 NULL,
476 NULL,
477 phKey,
478 NULL);
479
480 /* Close the device instance key */
481 RegCloseKey(hInstanceKey);
482
483 if (dwError != ERROR_SUCCESS)
484 return CR_REGISTRY_ERROR;
485
486 return CR_SUCCESS;
487}
488
489
490static
493 _In_ HKEY hKey,
494 _In_ ULONG ulLogConfType,
495 _Out_ PULONG pulRegDataType,
496 _Out_ PULONG pulDataSize,
497 _Out_ LPBYTE *ppBuffer)
498{
499 LPCWSTR pszValueName;
500
501 switch (ulLogConfType)
502 {
503 case BOOT_LOG_CONF:
504 pszValueName = L"BootConfig";
505 *pulRegDataType = REG_RESOURCE_LIST;
506 break;
507
508 case ALLOC_LOG_CONF:
509 pszValueName = L"AllocConfig";
510 *pulRegDataType = REG_RESOURCE_LIST;
511 break;
512
513 case FORCED_LOG_CONF:
514 pszValueName = L"ForcedConfig";
515 *pulRegDataType = REG_RESOURCE_LIST;
516 break;
517
519 pszValueName = L"FilteredConfigVector";
520 *pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
521 break;
522
523 case BASIC_LOG_CONF:
524 pszValueName = L"BasicConfigVector";
525 *pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
526 break;
527
529 pszValueName = L"OverrideConfigVector";
530 *pulRegDataType = REG_RESOURCE_REQUIREMENTS_LIST;
531 break;
532
533 default:
534 DPRINT1("Unsupported configuration type!\n");
535 return CR_FAILURE;
536 }
537
538 /* Get the configuration data size */
540 pszValueName,
541 NULL,
542 NULL,
543 NULL,
544 pulDataSize) != ERROR_SUCCESS)
545 {
546 return CR_INVALID_LOG_CONF;
547 }
548
549 /* Allocate the buffer */
550 *ppBuffer = HeapAlloc(GetProcessHeap(), 0, *pulDataSize);
551 if (*ppBuffer == NULL)
552 {
553 return CR_OUT_OF_MEMORY;
554 }
555
556 /* Retrieve the configuration data */
558 pszValueName,
559 NULL,
560 NULL,
561 (LPBYTE)*ppBuffer,
562 pulDataSize) != ERROR_SUCCESS)
563 {
564 return CR_INVALID_LOG_CONF;
565 }
566
567 return CR_SUCCESS;
568}
569
570
571static
572BOOL
575{
577 HANDLE hToken;
578 PSID pInteractiveSid = NULL;
579 BOOL bInteractive = FALSE;
580 RPC_STATUS RpcStatus;
581
582 DPRINT("IsCallerInteractive(%p)\n", hBinding);
583
584 /* Allocate an interactive user sid */
586 1,
588 0, 0, 0, 0, 0, 0, 0,
589 &pInteractiveSid))
590 {
591 DPRINT1("AllocateAndInitializeSid failed\n");
592 return FALSE;
593 }
594
595 /* Impersonate the client */
596 RpcStatus = RpcImpersonateClient(hBinding);
597 if (RpcStatus != RPC_S_OK)
598 {
599 DPRINT1("RpcImpersonateClient failed (Status 0x%08lx)\n", RpcStatus);
600 goto done;
601 }
602
603 /* Open the thread token and check for interactive user membership */
605 {
606 CheckTokenMembership(hToken, pInteractiveSid, &bInteractive);
607 CloseHandle(hToken);
608 }
609
610 /* Revert the impersonation */
612
613done:
614 if (pInteractiveSid)
615 FreeSid(pInteractiveSid);
616
617 return bInteractive;
618}
619
620
621VOID
624 PNP_NOTIFY_HANDLE pHandle)
625{
626 DPRINT1("PNP_NOTIFY_HANDLE_rundown(%p)\n", pHandle);
627}
628
629
630/* PUBLIC FUNCTIONS **********************************************************/
631
632/* Function 0 */
633DWORD
634WINAPI
637{
639 return CR_SUCCESS;
640}
641
642
643/* Function 1 */
644DWORD
645WINAPI
648{
650 return CR_SUCCESS;
651}
652
653
654/* Function 2 */
655DWORD
656WINAPI
659 WORD *pVersion)
660{
662
663 DPRINT("PNP_GetVersion(%p %p)\n",
664 hBinding, pVersion);
665
666 *pVersion = CONFIGMG_VERSION;
667
668 return CR_SUCCESS;
669}
670
671
672/* Function 3 */
673DWORD
674WINAPI
677 DWORD *pulState,
678 DWORD ulFlags)
679{
681
682 DPRINT("PNP_GetGlobalState(%p %p 0x%08lx)\n",
683 hBinding, pulState, ulFlags);
684
685 if (ulFlags != 0)
686 return CR_INVALID_FLAG;
687
689
690 return CR_SUCCESS;
691}
692
693
694/* Function 4 */
695DWORD
696WINAPI
699{
701
702 DPRINT("PNP_InitDetection(%p)\n",
703 hBinding);
704
705 return CR_SUCCESS;
706}
707
708
709/* Function 5 */
710DWORD
711WINAPI
714 BOOL Admin,
716{
719
721
722 DPRINT("PNP_ReportLogOn(%p %u, %u)\n",
723 hBinding, Admin, ProcessId);
724
725 /* Fail, if the caller is not an interactive user */
727 goto cleanup;
728
729 /* Get the users token */
731
732 if (!hProcess)
733 {
734 DPRINT1("OpenProcess failed with error %u\n", GetLastError());
735 goto cleanup;
736 }
737
738 if (hUserToken)
739 {
742 }
743
745 {
746 DPRINT1("OpenProcessToken failed with error %u\n", GetLastError());
747 goto cleanup;
748 }
749
750 /* Trigger the installer thread */
751 if (hInstallEvent)
753
755
756cleanup:
757 if (hProcess)
759
760 return ReturnValue;
761}
762
763
764/* Function 6 */
765DWORD
766WINAPI
769 LPWSTR pDeviceID,
770 DWORD ulFlags)
771{
773 HKEY hDeviceKey = NULL;
774
776 UNREFERENCED_PARAMETER(ulFlags);
777
778 DPRINT("PNP_ValidateDeviceInstance(%p %S 0x%08lx)\n",
779 hBinding, pDeviceID, ulFlags);
780
781 if (!IsValidDeviceInstanceID(pDeviceID))
782 return CR_INVALID_DEVINST;
783
785 pDeviceID,
786 0,
787 KEY_READ,
788 &hDeviceKey))
789 {
790 DPRINT("Could not open the Device Key!\n");
792 goto Done;
793 }
794
795 /* FIXME: add more tests */
796
797Done:
798 if (hDeviceKey != NULL)
799 RegCloseKey(hDeviceKey);
800
801 DPRINT("PNP_ValidateDeviceInstance() done (returns %lx)\n", ret);
802
803 return ret;
804}
805
806
807/* Function 7 */
808DWORD
809WINAPI
812 LPWSTR pDeviceID,
813 PNP_RPC_STRING_LEN ulLength)
814{
816
818
819 DPRINT("PNP_GetRootDeviceInstance(%p %S %lu)\n",
820 hBinding, pDeviceID, ulLength);
821
822 if (!pDeviceID)
823 {
825 goto Done;
826 }
827
828 if (ulLength < lstrlenW(szRootDeviceInstanceID) + 1)
829 {
831 goto Done;
832 }
833
834 lstrcpyW(pDeviceID,
836
837Done:
838 DPRINT("PNP_GetRootDeviceInstance() done (returns %lx)\n", ret);
839
840 return ret;
841}
842
843
844/* Function 8 */
845DWORD
846WINAPI
849 DWORD ulRelationship,
850 LPWSTR pDeviceID,
851 LPWSTR pRelatedDeviceId,
852 PNP_RPC_STRING_LEN *pulLength,
853 DWORD ulFlags)
854{
858
860 UNREFERENCED_PARAMETER(ulFlags);
861
862 DPRINT("PNP_GetRelatedDeviceInstance(%p %lu %S %p %p 0x%lx)\n",
863 hBinding, ulRelationship, pDeviceID, pRelatedDeviceId,
864 pulLength, ulFlags);
865
866 if (!IsValidDeviceInstanceID(pDeviceID))
867 return CR_INVALID_DEVINST;
868
869 if (ulRelationship == PNP_GET_PARENT_DEVICE_INSTANCE)
870 {
871 /* The root device does not have a parent */
872 if (IsRootDeviceInstanceID(pDeviceID))
873 return CR_NO_SUCH_DEVINST;
874
875 /* Return the root device for non existing devices */
876 if (!IsPresentDeviceInstanceID(pDeviceID))
877 {
878 if ((wcslen(szRootDeviceInstanceID) + 1) > *pulLength)
879 {
880 *pulLength = wcslen(szRootDeviceInstanceID) + 1;
881 return CR_BUFFER_SMALL;
882 }
883
884 wcscpy(pRelatedDeviceId, szRootDeviceInstanceID);
885 *pulLength = wcslen(szRootDeviceInstanceID) + 1;
886 return CR_SUCCESS;
887 }
888 }
889 else if (ulRelationship == PNP_GET_SIBLING_DEVICE_INSTANCE)
890 {
891 /* The root device does not have siblings */
892 if (IsRootDeviceInstanceID(pDeviceID))
893 return CR_NO_SUCH_DEVINST;
894 }
895
897 pDeviceID);
898
899 PlugPlayData.Relation = ulRelationship;
900
901 PlugPlayData.RelatedDeviceInstanceLength = *pulLength;
902 PlugPlayData.RelatedDeviceInstance = pRelatedDeviceId;
903
905 (PVOID)&PlugPlayData,
907 if (!NT_SUCCESS(Status))
908 {
910 }
911
912 DPRINT("PNP_GetRelatedDeviceInstance() done (returns %lx)\n", ret);
913 if (ret == CR_SUCCESS)
914 {
915 DPRINT("RelatedDevice: %wZ\n", &PlugPlayData.RelatedDeviceInstance);
916 }
917
918 return ret;
919}
920
921
922/* Function 9 */
923DWORD
924WINAPI
927 DWORD ulBranch,
928 DWORD ulIndex,
930 PNP_RPC_STRING_LEN ulLength,
931 PNP_RPC_STRING_LEN *pulRequiredLen,
932 DWORD ulFlags)
933{
935 HKEY hKey;
936 DWORD dwError;
937
939 UNREFERENCED_PARAMETER(ulFlags);
940
941 DPRINT("PNP_EnumerateSubKeys(%p %lu %lu %p %lu %p 0x%08lx)\n",
942 hBinding, ulBranch, ulIndex, Buffer, ulLength,
943 pulRequiredLen, ulFlags);
944
945 switch (ulBranch)
946 {
947 case PNP_ENUMERATOR_SUBKEYS:
948 hKey = hEnumKey;
949 break;
950
951 case PNP_CLASS_SUBKEYS:
952 hKey = hClassKey;
953 break;
954
955 default:
956 return CR_FAILURE;
957 }
958
959 *pulRequiredLen = ulLength;
960 dwError = RegEnumKeyExW(hKey,
961 ulIndex,
962 Buffer,
963 pulRequiredLen,
964 NULL,
965 NULL,
966 NULL,
967 NULL);
968 if (dwError != ERROR_SUCCESS)
969 {
971 }
972 else
973 {
974 (*pulRequiredLen)++;
975 }
976
977 DPRINT("PNP_EnumerateSubKeys() done (returns %lx)\n", ret);
978
979 return ret;
980}
981
982
983static
986 _In_ PWSTR pszDevice,
987 _In_ DWORD ulFlags,
988 _Inout_ PWSTR pszBuffer,
989 _Inout_ PDWORD pulLength)
990{
994
996 pszDevice);
997
999 {
1000 PlugPlayData.Relations = 3;
1001 }
1002 else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS)
1003 {
1004 PlugPlayData.Relations = 2;
1005 }
1006 else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS)
1007 {
1008 PlugPlayData.Relations = 1;
1009 }
1010 else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS)
1011 {
1012 PlugPlayData.Relations = 0;
1013 }
1014
1015 PlugPlayData.BufferSize = *pulLength * sizeof(WCHAR);
1016 PlugPlayData.Buffer = pszBuffer;
1017
1019 (PVOID)&PlugPlayData,
1021 if (NT_SUCCESS(Status))
1022 {
1023 *pulLength = PlugPlayData.BufferSize / sizeof(WCHAR);
1024 }
1025 else
1026 {
1028 }
1029
1030 return ret;
1031}
1032
1033
1034static
1037 _In_ PWSTR pszService,
1038 _Inout_ PWSTR pszBuffer,
1039 _Inout_ PDWORD pulLength)
1040{
1041 WCHAR szPathBuffer[512];
1042 WCHAR szName[16];
1043 HKEY hServicesKey = NULL, hServiceKey = NULL, hEnumKey = NULL;
1044 DWORD dwValues, dwSize, dwIndex, dwUsedLength, dwPathLength;
1045 DWORD dwError;
1046 PWSTR pPtr;
1048
1049 /* Open the device key */
1051 L"System\\CurrentControlSet\\Services",
1052 0,
1053 KEY_READ,
1054 &hServicesKey);
1055 if (dwError != ERROR_SUCCESS)
1056 {
1057 DPRINT("Failed to open the services key (Error %lu)\n", dwError);
1058 return CR_REGISTRY_ERROR;
1059 }
1060
1061 dwError = RegOpenKeyExW(hServicesKey,
1062 pszService,
1063 0,
1064 KEY_READ,
1065 &hServiceKey);
1066 if (dwError != ERROR_SUCCESS)
1067 {
1068 DPRINT("Failed to open the service key (Error %lu)\n", dwError);
1070 goto Done;
1071 }
1072
1073 dwError = RegOpenKeyExW(hServiceKey,
1074 L"Enum",
1075 0,
1076 KEY_READ,
1077 &hEnumKey);
1078 if (dwError != ERROR_SUCCESS)
1079 {
1080 DPRINT("Failed to open the service enum key (Error %lu)\n", dwError);
1082 goto Done;
1083 }
1084
1085 /* Retrieve the number of device instances */
1086 dwSize = sizeof(DWORD);
1087 dwError = RegQueryValueExW(hEnumKey,
1088 L"Count",
1089 NULL,
1090 NULL,
1091 (LPBYTE)&dwValues,
1092 &dwSize);
1093 if (dwError != ERROR_SUCCESS)
1094 {
1095 DPRINT("RegQueryValueExW failed (Error %lu)\n", dwError);
1096 dwValues = 1;
1097 }
1098
1099 DPRINT("dwValues %lu\n", dwValues);
1100
1101 dwUsedLength = 0;
1102 pPtr = pszBuffer;
1103
1104 for (dwIndex = 0; dwIndex < dwValues; dwIndex++)
1105 {
1106 wsprintf(szName, L"%lu", dwIndex);
1107
1108 dwSize = sizeof(szPathBuffer);
1109 dwError = RegQueryValueExW(hEnumKey,
1110 szName,
1111 NULL,
1112 NULL,
1113 (LPBYTE)szPathBuffer,
1114 &dwSize);
1115 if (dwError != ERROR_SUCCESS)
1116 break;
1117
1118 DPRINT("Path: %S\n", szPathBuffer);
1119
1120 dwPathLength = wcslen(szPathBuffer) + 1;
1121 if (dwUsedLength + dwPathLength + 1 > *pulLength)
1122 {
1124 break;
1125 }
1126
1127 wcscpy(pPtr, szPathBuffer);
1128 dwUsedLength += dwPathLength;
1129 pPtr += dwPathLength;
1130
1131 *pPtr = UNICODE_NULL;
1132 }
1133
1134Done:
1135 if (hEnumKey != NULL)
1137
1138 if (hServiceKey != NULL)
1139 RegCloseKey(hServiceKey);
1140
1141 if (hServicesKey != NULL)
1143
1144 if (ret == CR_SUCCESS)
1145 *pulLength = dwUsedLength + 1;
1146 else
1147 *pulLength = 0;
1148
1149 return ret;
1150}
1151
1152
1153static
1156 _In_ PWSTR pszDevice,
1157 _Inout_ PWSTR pszBuffer,
1158 _Inout_ PDWORD pulLength)
1159{
1160 WCHAR szInstanceBuffer[MAX_DEVICE_ID_LEN];
1161 WCHAR szPathBuffer[512];
1162 HKEY hDeviceKey;
1163 DWORD dwInstanceLength, dwPathLength, dwUsedLength;
1164 DWORD dwIndex, dwError;
1165 PWSTR pPtr;
1167
1168 /* Open the device key */
1169 dwError = RegOpenKeyExW(hEnumKey,
1170 pszDevice,
1171 0,
1173 &hDeviceKey);
1174 if (dwError != ERROR_SUCCESS)
1175 {
1176 DPRINT("Failed to open the device key (Error %lu)\n", dwError);
1177 return CR_REGISTRY_ERROR;
1178 }
1179
1180 dwUsedLength = 0;
1181 pPtr = pszBuffer;
1182
1183 for (dwIndex = 0; ; dwIndex++)
1184 {
1185 dwInstanceLength = MAX_DEVICE_ID_LEN;
1186 dwError = RegEnumKeyExW(hDeviceKey,
1187 dwIndex,
1188 szInstanceBuffer,
1189 &dwInstanceLength,
1190 NULL,
1191 NULL,
1192 NULL,
1193 NULL);
1194 if (dwError != ERROR_SUCCESS)
1195 break;
1196
1197 wsprintf(szPathBuffer, L"%s\\%s", pszDevice, szInstanceBuffer);
1198 DPRINT("Path: %S\n", szPathBuffer);
1199
1200 dwPathLength = wcslen(szPathBuffer) + 1;
1201 if (dwUsedLength + dwPathLength + 1 > *pulLength)
1202 {
1204 break;
1205 }
1206
1207 wcscpy(pPtr, szPathBuffer);
1208 dwUsedLength += dwPathLength;
1209 pPtr += dwPathLength;
1210
1211 *pPtr = UNICODE_NULL;
1212 }
1213
1214 RegCloseKey(hDeviceKey);
1215
1216 if (ret == CR_SUCCESS)
1217 *pulLength = dwUsedLength + 1;
1218 else
1219 *pulLength = 0;
1220
1221 return ret;
1222}
1223
1224
1227 _In_ PWSTR pszEnumerator,
1228 _Inout_ PWSTR pszBuffer,
1229 _Inout_ PDWORD pulLength)
1230{
1231 WCHAR szDeviceBuffer[MAX_DEVICE_ID_LEN];
1232 WCHAR szPathBuffer[512];
1233 HKEY hEnumeratorKey;
1234 PWSTR pPtr;
1235 DWORD dwIndex, dwDeviceLength, dwUsedLength, dwRemainingLength, dwPathLength;
1236 DWORD dwError;
1238
1239 /* Open the enumerator key */
1240 dwError = RegOpenKeyExW(hEnumKey,
1241 pszEnumerator,
1242 0,
1244 &hEnumeratorKey);
1245 if (dwError != ERROR_SUCCESS)
1246 {
1247 DPRINT("Failed to open the enumerator key (Error %lu)\n", dwError);
1248 return CR_REGISTRY_ERROR;
1249 }
1250
1251 dwUsedLength = 0;
1252 dwRemainingLength = *pulLength;
1253 pPtr = pszBuffer;
1254
1255 for (dwIndex = 0; ; dwIndex++)
1256 {
1257 dwDeviceLength = MAX_DEVICE_ID_LEN;
1258 dwError = RegEnumKeyExW(hEnumeratorKey,
1259 dwIndex,
1260 szDeviceBuffer,
1261 &dwDeviceLength,
1262 NULL,
1263 NULL,
1264 NULL,
1265 NULL);
1266 if (dwError != ERROR_SUCCESS)
1267 break;
1268
1269 wsprintf(szPathBuffer, L"%s\\%s", pszEnumerator, szDeviceBuffer);
1270 DPRINT("Path: %S\n", szPathBuffer);
1271
1272 dwPathLength = dwRemainingLength;
1273 ret = GetDeviceInstanceList(szPathBuffer,
1274 pPtr,
1275 &dwPathLength);
1276 if (ret != CR_SUCCESS)
1277 break;
1278
1279 dwUsedLength += dwPathLength - 1;
1280 dwRemainingLength -= dwPathLength - 1;
1281 pPtr += dwPathLength - 1;
1282 }
1283
1284 RegCloseKey(hEnumeratorKey);
1285
1286 if (ret == CR_SUCCESS)
1287 *pulLength = dwUsedLength + 1;
1288 else
1289 *pulLength = 0;
1290
1291 return ret;
1292}
1293
1294
1295static
1298 _Inout_ PWSTR pszBuffer,
1299 _Inout_ PDWORD pulLength)
1300{
1301 WCHAR szEnumeratorBuffer[MAX_DEVICE_ID_LEN];
1302 PWSTR pPtr;
1303 DWORD dwIndex, dwEnumeratorLength, dwUsedLength, dwRemainingLength, dwPathLength;
1304 DWORD dwError;
1306
1307 dwUsedLength = 0;
1308 dwRemainingLength = *pulLength;
1309 pPtr = pszBuffer;
1310
1311 for (dwIndex = 0; ; dwIndex++)
1312 {
1313 dwEnumeratorLength = MAX_DEVICE_ID_LEN;
1314 dwError = RegEnumKeyExW(hEnumKey,
1315 dwIndex,
1316 szEnumeratorBuffer,
1317 &dwEnumeratorLength,
1318 NULL, NULL, NULL, NULL);
1319 if (dwError != ERROR_SUCCESS)
1320 break;
1321
1322 dwPathLength = dwRemainingLength;
1323 ret = GetEnumeratorInstanceList(szEnumeratorBuffer,
1324 pPtr,
1325 &dwPathLength);
1326 if (ret != CR_SUCCESS)
1327 break;
1328
1329 dwUsedLength += dwPathLength - 1;
1330 dwRemainingLength -= dwPathLength - 1;
1331 pPtr += dwPathLength - 1;
1332 }
1333
1334 if (ret == CR_SUCCESS)
1335 *pulLength = dwUsedLength + 1;
1336 else
1337 *pulLength = 0;
1338
1339 return ret;
1340}
1341
1342
1343/* Function 10 */
1344DWORD
1345WINAPI
1348 LPWSTR pszFilter,
1349 LPWSTR Buffer,
1350 PNP_RPC_STRING_LEN *pulLength,
1351 DWORD ulFlags)
1352{
1353 WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
1354 WCHAR szDevice[MAX_DEVICE_ID_LEN];
1355 WCHAR szInstance[MAX_DEVICE_ID_LEN];
1357
1358 DPRINT("PNP_GetDeviceList(%p %S %p %p 0x%08lx)\n",
1359 hBinding, pszFilter, Buffer, pulLength, ulFlags);
1360
1361 if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
1362 return CR_INVALID_FLAG;
1363
1364 if (pulLength == NULL)
1365 return CR_INVALID_POINTER;
1366
1367 if ((ulFlags != CM_GETIDLIST_FILTER_NONE) &&
1368 (pszFilter == NULL))
1369 return CR_INVALID_POINTER;
1370
1371 if (ulFlags &
1376 {
1377 ret = GetRelationsInstanceList(pszFilter,
1378 ulFlags,
1379 Buffer,
1380 pulLength);
1381 }
1382 else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE)
1383 {
1384 ret = GetServiceInstanceList(pszFilter,
1385 Buffer,
1386 pulLength);
1387 }
1388 else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR)
1389 {
1390 SplitDeviceInstanceID(pszFilter,
1391 szEnumerator,
1392 szDevice,
1393 szInstance);
1394
1395 if (*szEnumerator != UNICODE_NULL && *szDevice != UNICODE_NULL)
1396 {
1397 ret = GetDeviceInstanceList(pszFilter,
1398 Buffer,
1399 pulLength);
1400 }
1401 else
1402 {
1403 ret = GetEnumeratorInstanceList(pszFilter,
1404 Buffer,
1405 pulLength);
1406 }
1407 }
1408 else /* CM_GETIDLIST_FILTER_NONE */
1409 {
1411 pulLength);
1412 }
1413
1414 return ret;
1415}
1416
1417
1418static
1421 _In_ PWSTR pszDevice,
1422 _In_ DWORD ulFlags,
1423 _Inout_ PDWORD pulLength)
1424{
1428
1430 pszDevice);
1431
1433 {
1434 PlugPlayData.Relations = 3;
1435 }
1436 else if (ulFlags & CM_GETIDLIST_FILTER_POWERRELATIONS)
1437 {
1438 PlugPlayData.Relations = 2;
1439 }
1440 else if (ulFlags & CM_GETIDLIST_FILTER_REMOVALRELATIONS)
1441 {
1442 PlugPlayData.Relations = 1;
1443 }
1444 else if (ulFlags & CM_GETIDLIST_FILTER_EJECTRELATIONS)
1445 {
1446 PlugPlayData.Relations = 0;
1447 }
1448
1449 PlugPlayData.BufferSize = 0;
1450 PlugPlayData.Buffer = NULL;
1451
1453 (PVOID)&PlugPlayData,
1455 if (NT_SUCCESS(Status))
1456 {
1457 *pulLength = PlugPlayData.BufferSize / sizeof(WCHAR);
1458 }
1459 else
1460 {
1462 }
1463
1464 return ret;
1465}
1466
1467
1468static
1471 _In_ PWSTR pszService,
1472 _Out_ PDWORD pulLength)
1473{
1474 HKEY hServicesKey = NULL, hServiceKey = NULL, hEnumKey = NULL;
1475 DWORD dwValues, dwMaxValueLength, dwSize;
1476 DWORD dwError;
1478
1479 /* Open the device key */
1481 L"System\\CurrentControlSet\\Services",
1482 0,
1483 KEY_READ,
1484 &hServicesKey);
1485 if (dwError != ERROR_SUCCESS)
1486 {
1487 DPRINT("Failed to open the services key (Error %lu)\n", dwError);
1488 return CR_REGISTRY_ERROR;
1489 }
1490
1491 dwError = RegOpenKeyExW(hServicesKey,
1492 pszService,
1493 0,
1494 KEY_READ,
1495 &hServiceKey);
1496 if (dwError != ERROR_SUCCESS)
1497 {
1498 DPRINT("Failed to open the service key (Error %lu)\n", dwError);
1500 goto Done;
1501 }
1502
1503 dwError = RegOpenKeyExW(hServiceKey,
1504 L"Enum",
1505 0,
1506 KEY_READ,
1507 &hEnumKey);
1508 if (dwError != ERROR_SUCCESS)
1509 {
1510 DPRINT("Failed to open the service enum key (Error %lu)\n", dwError);
1512 goto Done;
1513 }
1514
1515 /* Retrieve the number of device instances */
1516 dwSize = sizeof(DWORD);
1517 dwError = RegQueryValueExW(hEnumKey,
1518 L"Count",
1519 NULL,
1520 NULL,
1521 (LPBYTE)&dwValues,
1522 &dwSize);
1523 if (dwError != ERROR_SUCCESS)
1524 {
1525 DPRINT("RegQueryValueExW failed (Error %lu)\n", dwError);
1526 dwValues = 1;
1527 }
1528
1529 /* Retrieve the maximum instance name length */
1530 dwError = RegQueryInfoKeyW(hEnumKey,
1531 NULL,
1532 NULL,
1533 NULL,
1534 NULL,
1535 NULL,
1536 NULL,
1537 NULL,
1538 NULL,
1539 &dwMaxValueLength,
1540 NULL,
1541 NULL);
1542 if (dwError != ERROR_SUCCESS)
1543 {
1544 DPRINT("RegQueryInfoKeyW failed (Error %lu)\n", dwError);
1545 dwMaxValueLength = MAX_DEVICE_ID_LEN;
1546 }
1547
1548 DPRINT("dwValues %lu dwMaxValueLength %lu\n", dwValues, dwMaxValueLength / sizeof(WCHAR));
1549
1550 /* Return the largest possible buffer size */
1551 *pulLength = dwValues * dwMaxValueLength / sizeof(WCHAR) + 2;
1552
1553Done:
1554 if (hEnumKey != NULL)
1556
1557 if (hServiceKey != NULL)
1558 RegCloseKey(hServiceKey);
1559
1560 if (hServicesKey != NULL)
1562
1563 return ret;
1564}
1565
1566
1567static
1570 _In_ LPCWSTR pszDevice,
1571 _Out_ PULONG pulLength)
1572{
1573 HKEY hDeviceKey;
1574 DWORD dwSubKeys, dwMaxSubKeyLength;
1575 DWORD dwError;
1576
1577 /* Open the device key */
1578 dwError = RegOpenKeyExW(hEnumKey,
1579 pszDevice,
1580 0,
1581 KEY_READ,
1582 &hDeviceKey);
1583 if (dwError != ERROR_SUCCESS)
1584 {
1585 DPRINT("Failed to open the device key (Error %lu)\n", dwError);
1586 return CR_REGISTRY_ERROR;
1587 }
1588
1589 /* Retrieve the number of device instances and the maximum name length */
1590 dwError = RegQueryInfoKeyW(hDeviceKey,
1591 NULL,
1592 NULL,
1593 NULL,
1594 &dwSubKeys,
1595 &dwMaxSubKeyLength,
1596 NULL,
1597 NULL,
1598 NULL,
1599 NULL,
1600 NULL,
1601 NULL);
1602 if (dwError != ERROR_SUCCESS)
1603 {
1604 DPRINT("RegQueryInfoKeyW failed (Error %lu)\n", dwError);
1605 dwSubKeys = 0;
1606 dwMaxSubKeyLength = 0;
1607 }
1608
1609 /* Close the device key */
1610 RegCloseKey(hDeviceKey);
1611
1612 /* Return the largest possible buffer size */
1613 *pulLength = dwSubKeys * (wcslen(pszDevice) + 1 + dwMaxSubKeyLength + 1);
1614
1615 return CR_SUCCESS;
1616}
1617
1618
1619static
1622 _In_ LPCWSTR pszEnumerator,
1623 _Out_ PULONG pulLength)
1624{
1625 WCHAR szDeviceBuffer[MAX_DEVICE_ID_LEN];
1626 WCHAR szPathBuffer[512];
1627 HKEY hEnumeratorKey;
1628 DWORD dwIndex, dwDeviceLength, dwBufferLength;
1629 DWORD dwError;
1631
1632 *pulLength = 0;
1633
1634 /* Open the enumerator key */
1635 dwError = RegOpenKeyExW(hEnumKey,
1636 pszEnumerator,
1637 0,
1639 &hEnumeratorKey);
1640 if (dwError != ERROR_SUCCESS)
1641 {
1642 DPRINT("Failed to open the enumerator key (Error %lu)\n", dwError);
1643 return CR_REGISTRY_ERROR;
1644 }
1645
1646 for (dwIndex = 0; ; dwIndex++)
1647 {
1648 dwDeviceLength = MAX_DEVICE_ID_LEN;
1649 dwError = RegEnumKeyExW(hEnumeratorKey,
1650 dwIndex,
1651 szDeviceBuffer,
1652 &dwDeviceLength,
1653 NULL,
1654 NULL,
1655 NULL,
1656 NULL);
1657 if (dwError != ERROR_SUCCESS)
1658 break;
1659
1660 wsprintf(szPathBuffer, L"%s\\%s", pszEnumerator, szDeviceBuffer);
1661 DPRINT("Path: %S\n", szPathBuffer);
1662
1663 ret = GetDeviceInstanceListSize(szPathBuffer, &dwBufferLength);
1664 if (ret != CR_SUCCESS)
1665 {
1666 *pulLength = 0;
1667 break;
1668 }
1669
1670 *pulLength += dwBufferLength;
1671 }
1672
1673 /* Close the enumerator key */
1674 RegCloseKey(hEnumeratorKey);
1675
1676 return ret;
1677}
1678
1679
1680static
1683 _Out_ PULONG pulLength)
1684{
1685 WCHAR szEnumeratorBuffer[MAX_DEVICE_ID_LEN];
1686 DWORD dwIndex, dwEnumeratorLength, dwBufferLength;
1687 DWORD dwError;
1689
1690 for (dwIndex = 0; ; dwIndex++)
1691 {
1692 dwEnumeratorLength = MAX_DEVICE_ID_LEN;
1693 dwError = RegEnumKeyExW(hEnumKey,
1694 dwIndex,
1695 szEnumeratorBuffer,
1696 &dwEnumeratorLength,
1697 NULL, NULL, NULL, NULL);
1698 if (dwError != ERROR_SUCCESS)
1699 break;
1700
1701 /* Get the size of all device instances for the enumerator */
1702 ret = GetEnumeratorInstanceListSize(szEnumeratorBuffer,
1703 &dwBufferLength);
1704 if (ret != CR_SUCCESS)
1705 break;
1706
1707 *pulLength += dwBufferLength;
1708 }
1709
1710 return ret;
1711}
1712
1713
1714/* Function 11 */
1715DWORD
1716WINAPI
1719 LPWSTR pszFilter,
1720 PNP_RPC_BUFFER_SIZE *pulLength,
1721 DWORD ulFlags)
1722{
1723 WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
1724 WCHAR szDevice[MAX_DEVICE_ID_LEN];
1725 WCHAR szInstance[MAX_DEVICE_ID_LEN];
1727
1728 DPRINT("PNP_GetDeviceListSize(%p %S %p 0x%08lx)\n",
1729 hBinding, pszFilter, pulLength, ulFlags);
1730
1731 if (ulFlags & ~CM_GETIDLIST_FILTER_BITS)
1732 return CR_INVALID_FLAG;
1733
1734 if (pulLength == NULL)
1735 return CR_INVALID_POINTER;
1736
1737 if ((ulFlags != CM_GETIDLIST_FILTER_NONE) &&
1738 (pszFilter == NULL))
1739 return CR_INVALID_POINTER;
1740
1741 *pulLength = 0;
1742
1743 if (ulFlags &
1748 {
1750 ulFlags,
1751 pulLength);
1752 }
1753 else if (ulFlags & CM_GETIDLIST_FILTER_SERVICE)
1754 {
1755 ret = GetServiceInstanceListSize(pszFilter,
1756 pulLength);
1757 }
1758 else if (ulFlags & CM_GETIDLIST_FILTER_ENUMERATOR)
1759 {
1760 SplitDeviceInstanceID(pszFilter,
1761 szEnumerator,
1762 szDevice,
1763 szInstance);
1764
1765 if (*szEnumerator != UNICODE_NULL && *szDevice != UNICODE_NULL)
1766 {
1767 ret = GetDeviceInstanceListSize(pszFilter,
1768 pulLength);
1769 }
1770 else
1771 {
1773 pulLength);
1774 }
1775 }
1776 else /* CM_GETIDLIST_FILTER_NONE */
1777 {
1778 ret = GetAllInstanceListSize(pulLength);
1779 }
1780
1781 /* Add one character for the terminating double UNICODE_NULL */
1782 if (ret == CR_SUCCESS)
1783 (*pulLength) += 1;
1784
1785 return ret;
1786}
1787
1788
1789/* Function 12 */
1790DWORD
1791WINAPI
1794 LPWSTR pszDeviceID,
1795 DWORD *pulDepth,
1796 DWORD ulFlags)
1797{
1798 PLUGPLAY_CONTROL_DEPTH_DATA PlugPlayData;
1801
1803 UNREFERENCED_PARAMETER(ulFlags);
1804
1805 DPRINT("PNP_GetDepth(%p %S %p 0x%08lx)\n",
1806 hBinding, pszDeviceID, pulDepth, ulFlags);
1807
1808 if (!IsValidDeviceInstanceID(pszDeviceID))
1809 return CR_INVALID_DEVINST;
1810
1812 pszDeviceID);
1813
1815 (PVOID)&PlugPlayData,
1817 if (NT_SUCCESS(Status))
1818 {
1819 *pulDepth = PlugPlayData.Depth;
1820 }
1821 else
1822 {
1824 }
1825
1826 DPRINT("PNP_GetDepth() done (returns %lx)\n", ret);
1827
1828 return ret;
1829}
1830
1831
1832/* Function 13 */
1833DWORD
1834WINAPI
1837 LPWSTR pDeviceID,
1838 DWORD ulProperty,
1839 DWORD *pulRegDataType,
1840 BYTE *Buffer,
1841 PNP_PROP_SIZE *pulTransferLen,
1842 PNP_PROP_SIZE *pulLength,
1843 DWORD ulFlags)
1844{
1845 PLUGPLAY_CONTROL_PROPERTY_DATA PlugPlayData;
1847 LPWSTR lpValueName = NULL;
1848 HKEY hKey = NULL;
1849 LONG lError;
1851
1853
1854 DPRINT("PNP_GetDeviceRegProp(%p %S %lu %p %p %p %p 0x%08lx)\n",
1855 hBinding, pDeviceID, ulProperty, pulRegDataType, Buffer,
1856 pulTransferLen, pulLength, ulFlags);
1857
1858 if (pulTransferLen == NULL || pulLength == NULL)
1859 {
1861 goto done;
1862 }
1863
1864 if (ulFlags != 0)
1865 {
1867 goto done;
1868 }
1869
1870 /* Check pDeviceID */
1871 if (!IsValidDeviceInstanceID(pDeviceID))
1872 {
1874 goto done;
1875 }
1876
1877 if (*pulLength < *pulTransferLen)
1878 *pulLength = *pulTransferLen;
1879
1880 *pulTransferLen = 0;
1881
1882 switch (ulProperty)
1883 {
1884 case CM_DRP_DEVICEDESC:
1885 lpValueName = L"DeviceDesc";
1886 break;
1887
1888 case CM_DRP_HARDWAREID:
1889 lpValueName = L"HardwareID";
1890 break;
1891
1893 lpValueName = L"CompatibleIDs";
1894 break;
1895
1896 case CM_DRP_SERVICE:
1897 lpValueName = L"Service";
1898 break;
1899
1900 case CM_DRP_CLASS:
1901 lpValueName = L"Class";
1902 break;
1903
1904 case CM_DRP_CLASSGUID:
1905 lpValueName = L"ClassGUID";
1906 break;
1907
1908 case CM_DRP_DRIVER:
1909 lpValueName = L"Driver";
1910 break;
1911
1912 case CM_DRP_CONFIGFLAGS:
1913 lpValueName = L"ConfigFlags";
1914 break;
1915
1916 case CM_DRP_MFG:
1917 lpValueName = L"Mfg";
1918 break;
1919
1921 lpValueName = L"FriendlyName";
1922 break;
1923
1925 lpValueName = L"LocationInformation";
1926 break;
1927
1930 *pulRegDataType = REG_SZ;
1931 break;
1932
1934 lpValueName = L"Capabilities";
1935 break;
1936
1937 case CM_DRP_UI_NUMBER:
1938 PlugPlayData.Property = PNP_PROPERTY_UI_NUMBER;
1939 break;
1940
1942 lpValueName = L"UpperFilters";
1943 break;
1944
1946 lpValueName = L"LowerFilters";
1947 break;
1948
1949 case CM_DRP_BUSTYPEGUID:
1950 PlugPlayData.Property = PNP_PROPERTY_BUSTYPEGUID;
1951 *pulRegDataType = REG_BINARY;
1952 break;
1953
1955 PlugPlayData.Property = PNP_PROPERTY_LEGACYBUSTYPE;
1956 *pulRegDataType = REG_DWORD;
1957 break;
1958
1959 case CM_DRP_BUSNUMBER:
1960 PlugPlayData.Property = PNP_PROPERTY_BUSNUMBER;
1961 *pulRegDataType = REG_DWORD;
1962 break;
1963
1966 *pulRegDataType = REG_SZ;
1967 break;
1968
1969 case CM_DRP_SECURITY:
1970 lpValueName = L"Security";
1971 break;
1972
1973 case CM_DRP_DEVTYPE:
1974 lpValueName = L"DeviceType";
1975 break;
1976
1977 case CM_DRP_EXCLUSIVE:
1978 lpValueName = L"Exclusive";
1979 break;
1980
1982 lpValueName = L"DeviceCharacteristics";
1983 break;
1984
1985 case CM_DRP_ADDRESS:
1986 PlugPlayData.Property = PNP_PROPERTY_ADDRESS;
1987 *pulRegDataType = REG_DWORD;
1988 break;
1989
1991 lpValueName = L"UINumberDescFormat";
1992 break;
1993
1995 PlugPlayData.Property = PNP_PROPERTY_POWER_DATA;
1996 *pulRegDataType = REG_BINARY;
1997 break;
1998
2001 *pulRegDataType = REG_DWORD;
2002 break;
2003
2006 *pulRegDataType = REG_DWORD;
2007 break;
2008
2010 lpValueName = L"RemovalPolicy";
2011 *pulRegDataType = REG_DWORD;
2012 break;
2013
2015 PlugPlayData.Property = PNP_PROPERTY_INSTALL_STATE;
2016 *pulRegDataType = REG_DWORD;
2017 break;
2018
2019#if (WINVER >= _WIN32_WINNT_WS03)
2022 *pulRegDataType = REG_MULTI_SZ;
2023 break;
2024#endif
2025
2026#if (WINVER >= _WIN32_WINNT_WIN7)
2028 PlugPlayData.Property = PNP_PROPERTY_CONTAINERID;
2029 *pulRegDataType = REG_SZ;
2030 break;
2031#endif
2032
2033 default:
2035 goto done;
2036 }
2037
2038 DPRINT("Value name: %S\n", lpValueName);
2039
2040 if (lpValueName)
2041 {
2042 /* Retrieve information from the Registry */
2043 lError = RegOpenKeyExW(hEnumKey,
2044 pDeviceID,
2045 0,
2047 &hKey);
2048 if (lError != ERROR_SUCCESS)
2049 {
2050 hKey = NULL;
2051 *pulLength = 0;
2053 goto done;
2054 }
2055
2056 lError = RegQueryValueExW(hKey,
2057 lpValueName,
2058 NULL,
2059 pulRegDataType,
2060 Buffer,
2061 pulLength);
2062 if (lError != ERROR_SUCCESS)
2063 {
2064 if (lError == ERROR_MORE_DATA)
2065 {
2067 }
2068 else
2069 {
2070 *pulLength = 0;
2072 }
2073 }
2074 }
2075 else
2076 {
2077 /* Retrieve information from the Device Node */
2079 pDeviceID);
2080 PlugPlayData.Buffer = Buffer;
2081 PlugPlayData.BufferSize = *pulLength;
2082
2084 (PVOID)&PlugPlayData,
2086 if (NT_SUCCESS(Status))
2087 {
2088 *pulLength = PlugPlayData.BufferSize;
2089 }
2090 else
2091 {
2093 }
2094 }
2095
2096done:
2097 if (pulTransferLen)
2098 *pulTransferLen = (ret == CR_SUCCESS) ? *pulLength : 0;
2099
2100 if (hKey != NULL)
2102
2103 DPRINT("PNP_GetDeviceRegProp() done (returns %lx)\n", ret);
2104
2105 return ret;
2106}
2107
2108
2109/* Function 14 */
2110DWORD
2111WINAPI
2114 LPWSTR pDeviceId,
2115 DWORD ulProperty,
2116 DWORD ulDataType,
2117 BYTE *Buffer,
2118 PNP_PROP_SIZE ulLength,
2119 DWORD ulFlags)
2120{
2122 LPWSTR lpValueName = NULL;
2123 HKEY hKey = 0;
2124
2126 UNREFERENCED_PARAMETER(ulFlags);
2127
2128 DPRINT("PNP_SetDeviceRegProp(%p %S %lu %lu %p %lu 0x%08lx)\n",
2129 hBinding, pDeviceId, ulProperty, ulDataType, Buffer,
2130 ulLength, ulFlags);
2131
2132 if (!IsValidDeviceInstanceID(pDeviceId))
2133 return CR_INVALID_DEVINST;
2134
2135 switch (ulProperty)
2136 {
2137 case CM_DRP_DEVICEDESC:
2138 lpValueName = L"DeviceDesc";
2139 break;
2140
2141 case CM_DRP_HARDWAREID:
2142 lpValueName = L"HardwareID";
2143 break;
2144
2146 lpValueName = L"CompatibleIDs";
2147 break;
2148
2149 case CM_DRP_SERVICE:
2150 lpValueName = L"Service";
2151 break;
2152
2153 case CM_DRP_CLASS:
2154 lpValueName = L"Class";
2155 break;
2156
2157 case CM_DRP_CLASSGUID:
2158 lpValueName = L"ClassGUID";
2159 break;
2160
2161 case CM_DRP_DRIVER:
2162 lpValueName = L"Driver";
2163 break;
2164
2165 case CM_DRP_CONFIGFLAGS:
2166 lpValueName = L"ConfigFlags";
2167 break;
2168
2169 case CM_DRP_MFG:
2170 lpValueName = L"Mfg";
2171 break;
2172
2174 lpValueName = L"FriendlyName";
2175 break;
2176
2178 lpValueName = L"LocationInformation";
2179 break;
2180
2182 lpValueName = L"UpperFilters";
2183 break;
2184
2186 lpValueName = L"LowerFilters";
2187 break;
2188
2189 case CM_DRP_SECURITY:
2190 lpValueName = L"Security";
2191 break;
2192
2193 case CM_DRP_DEVTYPE:
2194 lpValueName = L"DeviceType";
2195 break;
2196
2197 case CM_DRP_EXCLUSIVE:
2198 lpValueName = L"Exclusive";
2199 break;
2200
2202 lpValueName = L"DeviceCharacteristics";
2203 break;
2204
2206 lpValueName = L"UINumberDescFormat";
2207 break;
2208
2210 lpValueName = L"RemovalPolicy";
2211 break;
2212
2213 default:
2214 return CR_INVALID_PROPERTY;
2215 }
2216
2217 DPRINT("Value name: %S\n", lpValueName);
2218
2220 pDeviceId,
2221 0,
2223 &hKey))
2224 return CR_INVALID_DEVNODE;
2225
2226 if (ulLength == 0)
2227 {
2229 lpValueName))
2231 }
2232 else
2233 {
2234 if (RegSetValueExW(hKey,
2235 lpValueName,
2236 0,
2237 ulDataType,
2238 Buffer,
2239 ulLength))
2241 }
2242
2244
2245 DPRINT("PNP_SetDeviceRegProp() done (returns %lx)\n", ret);
2246
2247 return ret;
2248}
2249
2250
2251/* Function 15 */
2252DWORD
2253WINAPI
2256 LPWSTR pDeviceId,
2257 LPWSTR pszClassInstance,
2258 PNP_RPC_STRING_LEN ulLength)
2259{
2260 WCHAR szClassGuid[40];
2261 WCHAR szClassInstance[5];
2262 HKEY hDeviceClassKey = NULL;
2263 HKEY hClassInstanceKey;
2264 ULONG ulTransferLength, ulDataLength;
2265 DWORD dwDataType, dwDisposition, i;
2266 DWORD dwError;
2268
2269 DPRINT("PNP_GetClassInstance(%p %S %p %lu)\n",
2270 hBinding, pDeviceId, pszClassInstance, ulLength);
2271
2272 if (!IsValidDeviceInstanceID(pDeviceId))
2273 return CR_INVALID_DEVINST;
2274
2275 ulTransferLength = ulLength;
2277 pDeviceId,
2279 &dwDataType,
2280 (BYTE *)pszClassInstance,
2281 &ulTransferLength,
2282 &ulLength,
2283 0);
2284 if (ret == CR_SUCCESS)
2285 return ret;
2286
2287 ulTransferLength = sizeof(szClassGuid);
2288 ulDataLength = sizeof(szClassGuid);
2290 pDeviceId,
2292 &dwDataType,
2293 (BYTE *)szClassGuid,
2294 &ulTransferLength,
2295 &ulDataLength,
2296 0);
2297 if (ret != CR_SUCCESS)
2298 {
2299 DPRINT1("PNP_GetDeviceRegProp() failed (Error %lu)\n", ret);
2300 goto done;
2301 }
2302
2303 dwError = RegOpenKeyExW(hClassKey,
2304 szClassGuid,
2305 0,
2306 KEY_READ,
2307 &hDeviceClassKey);
2308 if (dwError != ERROR_SUCCESS)
2309 {
2310 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError);
2311 ret = CR_FAILURE;
2312 goto done;
2313 }
2314
2315 for (i = 0; i < 10000; i++)
2316 {
2317 wsprintf(szClassInstance, L"%04lu", i);
2318
2319 dwError = RegCreateKeyExW(hDeviceClassKey,
2320 szClassInstance,
2321 0,
2322 NULL,
2325 NULL,
2326 &hClassInstanceKey,
2327 &dwDisposition);
2328 if (dwError == ERROR_SUCCESS)
2329 {
2330 RegCloseKey(hClassInstanceKey);
2331
2332 if (dwDisposition == REG_CREATED_NEW_KEY)
2333 {
2334 wsprintf(pszClassInstance,
2335 L"%s\\%s",
2336 szClassGuid,
2337 szClassInstance);
2338
2339 ulDataLength = (wcslen(pszClassInstance) + 1) * sizeof(WCHAR);
2341 pDeviceId,
2343 REG_SZ,
2344 (BYTE *)pszClassInstance,
2345 ulDataLength,
2346 0);
2347 if (ret != CR_SUCCESS)
2348 {
2349 DPRINT1("PNP_SetDeviceRegProp() failed (Error %lu)\n", ret);
2350 RegDeleteKeyW(hDeviceClassKey,
2351 szClassInstance);
2352 }
2353
2354 break;
2355 }
2356 }
2357 }
2358
2359done:
2360 if (hDeviceClassKey != NULL)
2361 RegCloseKey(hDeviceClassKey);
2362
2363 return ret;
2364}
2365
2366
2367/* Function 16 */
2368DWORD
2369WINAPI
2372 LPWSTR pszSubKey,
2373 DWORD samDesired,
2374 DWORD ulFlags)
2375{
2376 HKEY hDeviceKey = NULL, hParametersKey = NULL;
2377 DWORD dwError;
2379
2381 UNREFERENCED_PARAMETER(samDesired);
2382
2383 DPRINT("PNP_CreateKey(%p %S 0x%lx 0x%08lx)\n",
2384 hBinding, pszSubKey, samDesired, ulFlags);
2385
2386 if (ulFlags != 0)
2387 return CR_INVALID_FLAG;
2388
2389 if (!IsValidDeviceInstanceID(pszSubKey))
2390 return CR_INVALID_DEVINST;
2391
2392 dwError = RegOpenKeyExW(hEnumKey,
2393 pszSubKey,
2394 0,
2395 KEY_WRITE,
2396 &hDeviceKey);
2397 if (dwError != ERROR_SUCCESS)
2398 {
2400 goto done;
2401 }
2402
2403 dwError = RegCreateKeyExW(hDeviceKey,
2404 L"Device Parameters",
2405 0,
2406 NULL,
2409 NULL,
2410 &hParametersKey,
2411 NULL);
2412 if (dwError != ERROR_SUCCESS)
2413 {
2415 goto done;
2416 }
2417
2418 /* FIXME: Set key security */
2419
2420done:
2421 if (hParametersKey != NULL)
2422 RegCloseKey(hParametersKey);
2423
2424 if (hDeviceKey != NULL)
2425 RegCloseKey(hDeviceKey);
2426
2427 return ret;
2428}
2429
2430
2431/* Function 17 */
2432DWORD
2433WINAPI
2436 LPWSTR pszDeviceID,
2437 LPWSTR pszParentKey,
2438 LPWSTR pszChildKey,
2439 DWORD ulFlags)
2440{
2443}
2444
2445
2446/* Function 18 */
2447DWORD
2448WINAPI
2451 DWORD *pulClassCount,
2452 DWORD ulFlags)
2453{
2454 HKEY hKey;
2455 DWORD dwError;
2456
2458 UNREFERENCED_PARAMETER(ulFlags);
2459
2460 DPRINT("PNP_GetClassCount(%p %p 0x%08lx)\n",
2461 hBinding, pulClassCount, ulFlags);
2462
2465 0,
2467 &hKey);
2468 if (dwError != ERROR_SUCCESS)
2469 return CR_INVALID_DATA;
2470
2471 dwError = RegQueryInfoKeyW(hKey,
2472 NULL,
2473 NULL,
2474 NULL,
2475 pulClassCount,
2476 NULL,
2477 NULL,
2478 NULL,
2479 NULL,
2480 NULL,
2481 NULL,
2482 NULL);
2484 if (dwError != ERROR_SUCCESS)
2485 return CR_INVALID_DATA;
2486
2487 return CR_SUCCESS;
2488}
2489
2490
2491/* Function 19 */
2492DWORD
2493WINAPI
2496 LPWSTR pszClassGuid,
2497 LPWSTR Buffer,
2498 PNP_RPC_STRING_LEN *pulLength,
2499 DWORD ulFlags)
2500{
2501 WCHAR szKeyName[MAX_PATH];
2503 HKEY hKey;
2504 DWORD dwSize;
2505
2507 UNREFERENCED_PARAMETER(ulFlags);
2508
2509 DPRINT("PNP_GetClassName(%p %S %p %p 0x%08lx)\n",
2510 hBinding, pszClassGuid, Buffer, pulLength, ulFlags);
2511
2512 lstrcpyW(szKeyName, L"System\\CurrentControlSet\\Control\\Class\\");
2513 if (lstrlenW(pszClassGuid) + 1 < sizeof(szKeyName)/sizeof(WCHAR)-(lstrlenW(szKeyName) * sizeof(WCHAR)))
2514 lstrcatW(szKeyName, pszClassGuid);
2515 else
2516 return CR_INVALID_DATA;
2517
2519 szKeyName,
2520 0,
2522 &hKey))
2523 return CR_REGISTRY_ERROR;
2524
2525 dwSize = *pulLength * sizeof(WCHAR);
2527 L"Class",
2528 NULL,
2529 NULL,
2530 (LPBYTE)Buffer,
2531 &dwSize))
2532 {
2533 *pulLength = 0;
2535 }
2536 else
2537 {
2538 *pulLength = dwSize / sizeof(WCHAR);
2539 }
2540
2542
2543 DPRINT("PNP_GetClassName() done (returns %lx)\n", ret);
2544
2545 return ret;
2546}
2547
2548
2549/* Function 20 */
2550DWORD
2551WINAPI
2554 LPWSTR pszClassGuid,
2555 DWORD ulFlags)
2556{
2558
2560
2561 DPRINT("PNP_DeleteClassKey(%p %S 0x%08lx)\n",
2562 hBinding, pszClassGuid, ulFlags);
2563
2564 if (ulFlags & CM_DELETE_CLASS_SUBKEYS)
2565 {
2566 if (SHDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
2568 }
2569 else
2570 {
2571 if (RegDeleteKeyW(hClassKey, pszClassGuid) != ERROR_SUCCESS)
2573 }
2574
2575 DPRINT("PNP_DeleteClassKey() done (returns %lx)\n", ret);
2576
2577 return ret;
2578}
2579
2580
2581/* Function 21 */
2582DWORD
2583WINAPI
2586 LPWSTR pszInterfaceDevice,
2587 GUID *AliasInterfaceGuid,
2588 LPWSTR pszAliasInterfaceDevice,
2589 PNP_RPC_STRING_LEN *pulLength,
2590 PNP_RPC_STRING_LEN *pulTransferLen,
2591 DWORD ulFlags)
2592{
2595}
2596
2597
2598/* Function 22 */
2599DWORD
2600WINAPI
2604 LPWSTR pszDeviceID,
2605 BYTE *Buffer,
2606 PNP_RPC_BUFFER_SIZE *pulLength,
2607 DWORD ulFlags)
2608{
2612
2614
2615 DPRINT("PNP_GetInterfaceDeviceList(%p %p %S %p %p 0x%08lx)\n",
2616 hBinding, InterfaceGuid, pszDeviceID, Buffer, pulLength, ulFlags);
2617
2618 if (!IsValidDeviceInstanceID(pszDeviceID))
2619 return CR_INVALID_DEVINST;
2620
2622 pszDeviceID);
2623
2624 PlugPlayData.Flags = ulFlags;
2625 PlugPlayData.FilterGuid = InterfaceGuid;
2626 PlugPlayData.Buffer = Buffer;
2627 PlugPlayData.BufferSize = *pulLength;
2628
2630 (PVOID)&PlugPlayData,
2632 if (NT_SUCCESS(Status))
2633 {
2634 *pulLength = PlugPlayData.BufferSize;
2635 }
2636 else
2637 {
2639 }
2640
2641 DPRINT("PNP_GetInterfaceDeviceList() done (returns %lx)\n", ret);
2642 return ret;
2643}
2644
2645
2646/* Function 23 */
2647DWORD
2648WINAPI
2651 PNP_RPC_BUFFER_SIZE *pulLen,
2653 LPWSTR pszDeviceID,
2654 DWORD ulFlags)
2655{
2659
2661
2662 DPRINT("PNP_GetInterfaceDeviceListSize(%p %p %p %S 0x%08lx)\n",
2663 hBinding, pulLen, InterfaceGuid, pszDeviceID, ulFlags);
2664
2665 if (!IsValidDeviceInstanceID(pszDeviceID))
2666 return CR_INVALID_DEVINST;
2667
2669 pszDeviceID);
2670
2671 PlugPlayData.FilterGuid = InterfaceGuid;
2672 PlugPlayData.Buffer = NULL;
2673 PlugPlayData.BufferSize = 0;
2674 PlugPlayData.Flags = ulFlags;
2675
2677 (PVOID)&PlugPlayData,
2679 if (NT_SUCCESS(Status))
2680 {
2681 *pulLen = PlugPlayData.BufferSize;
2682 }
2683 else
2684 {
2686 }
2687
2688 DPRINT("PNP_GetInterfaceDeviceListSize() done (returns %lx)\n", ret);
2689 return ret;
2690}
2691
2692
2693/* Function 24 */
2694DWORD
2695WINAPI
2698 LPWSTR pszDeviceID,
2700 LPWSTR pszReference,
2701 LPWSTR pszSymLink,
2702 PNP_RPC_STRING_LEN *pulLength,
2703 PNP_RPC_STRING_LEN *pulTransferLen,
2704 DWORD ulFlags)
2705{
2708}
2709
2710
2711/* Function 25 */
2712DWORD
2713WINAPI
2716 LPWSTR pszInterfaceDevice,
2717 DWORD ulFlags)
2718{
2721}
2722
2723
2724/* Function 26 */
2725DWORD
2726WINAPI
2729 LPWSTR pszClassGuid,
2730 DWORD ulProperty,
2731 DWORD *pulRegDataType,
2732 BYTE *Buffer,
2733 PNP_RPC_STRING_LEN *pulTransferLen,
2734 PNP_RPC_STRING_LEN *pulLength,
2735 DWORD ulFlags)
2736{
2738 LPWSTR lpValueName = NULL;
2739 HKEY hInstKey = NULL;
2740 HKEY hPropKey = NULL;
2741 LONG lError;
2742
2744
2745 DPRINT("PNP_GetClassRegProp(%p %S %lu %p %p %p %p 0x%08lx)\n",
2746 hBinding, pszClassGuid, ulProperty, pulRegDataType,
2747 Buffer, pulTransferLen, pulLength, ulFlags);
2748
2749 if (pulTransferLen == NULL || pulLength == NULL)
2750 {
2752 goto done;
2753 }
2754
2755 if (ulFlags != 0)
2756 {
2758 goto done;
2759 }
2760
2761 if (*pulLength < *pulTransferLen)
2762 *pulLength = *pulTransferLen;
2763
2764 *pulTransferLen = 0;
2765
2766 switch (ulProperty)
2767 {
2768 case CM_CRP_SECURITY:
2769 lpValueName = L"Security";
2770 break;
2771
2772 case CM_CRP_DEVTYPE:
2773 lpValueName = L"DeviceType";
2774 break;
2775
2776 case CM_CRP_EXCLUSIVE:
2777 lpValueName = L"Exclusive";
2778 break;
2779
2781 lpValueName = L"DeviceCharacteristics";
2782 break;
2783
2784 default:
2786 goto done;
2787 }
2788
2789 DPRINT("Value name: %S\n", lpValueName);
2790
2791 lError = RegOpenKeyExW(hClassKey,
2792 pszClassGuid,
2793 0,
2794 KEY_READ,
2795 &hInstKey);
2796 if (lError != ERROR_SUCCESS)
2797 {
2798 *pulLength = 0;
2800 goto done;
2801 }
2802
2803 lError = RegOpenKeyExW(hInstKey,
2804 L"Properties",
2805 0,
2806 KEY_READ,
2807 &hPropKey);
2808 if (lError != ERROR_SUCCESS)
2809 {
2810 *pulLength = 0;
2812 goto done;
2813 }
2814
2815 lError = RegQueryValueExW(hPropKey,
2816 lpValueName,
2817 NULL,
2818 pulRegDataType,
2819 Buffer,
2820 pulLength);
2821 if (lError != ERROR_SUCCESS)
2822 {
2823 if (lError == ERROR_MORE_DATA)
2824 {
2826 }
2827 else
2828 {
2829 *pulLength = 0;
2831 }
2832 }
2833
2834done:
2835 if (ret == CR_SUCCESS)
2836 *pulTransferLen = *pulLength;
2837
2838 if (hPropKey != NULL)
2839 RegCloseKey(hPropKey);
2840
2841 if (hInstKey != NULL)
2842 RegCloseKey(hInstKey);
2843
2844 DPRINT("PNP_GetClassRegProp() done (returns %lx)\n", ret);
2845
2846 return ret;
2847}
2848
2849
2850/* Function 27 */
2851DWORD
2852WINAPI
2855 LPWSTR pszClassGuid,
2856 DWORD ulProperty,
2857 DWORD ulDataType,
2858 BYTE *Buffer,
2859 PNP_PROP_SIZE ulLength,
2860 DWORD ulFlags)
2861{
2863 LPWSTR lpValueName = NULL;
2864 HKEY hInstKey = 0;
2865 HKEY hPropKey = 0;
2866 LONG lError;
2867
2869
2870 DPRINT("PNP_SetClassRegProp(%p %S %lu %lu %p %lu 0x%08lx)\n",
2871 hBinding, pszClassGuid, ulProperty, ulDataType,
2872 Buffer, ulLength, ulFlags);
2873
2874 if (ulFlags != 0)
2875 return CR_INVALID_FLAG;
2876
2877 switch (ulProperty)
2878 {
2879 case CM_CRP_SECURITY:
2880 lpValueName = L"Security";
2881 break;
2882
2883 case CM_CRP_DEVTYPE:
2884 lpValueName = L"DeviceType";
2885 break;
2886
2887 case CM_CRP_EXCLUSIVE:
2888 lpValueName = L"Exclusive";
2889 break;
2890
2892 lpValueName = L"DeviceCharacteristics";
2893 break;
2894
2895 default:
2896 return CR_INVALID_PROPERTY;
2897 }
2898
2899 lError = RegOpenKeyExW(hClassKey,
2900 pszClassGuid,
2901 0,
2902 KEY_WRITE,
2903 &hInstKey);
2904 if (lError != ERROR_SUCCESS)
2905 {
2907 goto done;
2908 }
2909
2910 /* FIXME: Set security descriptor */
2911 lError = RegCreateKeyExW(hInstKey,
2912 L"Properties",
2913 0,
2914 NULL,
2917 NULL,
2918 &hPropKey,
2919 NULL);
2920 if (lError != ERROR_SUCCESS)
2921 {
2923 goto done;
2924 }
2925
2926 if (ulLength == 0)
2927 {
2928 if (RegDeleteValueW(hPropKey,
2929 lpValueName))
2931 }
2932 else
2933 {
2934 if (RegSetValueExW(hPropKey,
2935 lpValueName,
2936 0,
2937 ulDataType,
2938 Buffer,
2939 ulLength))
2941 }
2942
2943done:
2944 if (hPropKey != NULL)
2945 RegCloseKey(hPropKey);
2946
2947 if (hInstKey != NULL)
2948 RegCloseKey(hInstKey);
2949
2950 return ret;
2951}
2952
2953
2954static
2957 _In_ LPWSTR pszDeviceID,
2958 _In_ BOOL bPhantomDevice)
2959{
2960 WCHAR szEnumerator[MAX_DEVICE_ID_LEN];
2961 WCHAR szDevice[MAX_DEVICE_ID_LEN];
2962 WCHAR szInstance[MAX_DEVICE_ID_LEN];
2963 HKEY hKeyEnumerator;
2964 HKEY hKeyDevice;
2965 HKEY hKeyInstance;
2966 HKEY hKeyControl;
2967 LONG lError;
2968
2969 /* Split the instance ID */
2970 SplitDeviceInstanceID(pszDeviceID,
2971 szEnumerator,
2972 szDevice,
2973 szInstance);
2974
2975 /* Open or create the enumerator key */
2976 lError = RegCreateKeyExW(hEnumKey,
2977 szEnumerator,
2978 0,
2979 NULL,
2982 NULL,
2983 &hKeyEnumerator,
2984 NULL);
2985 if (lError != ERROR_SUCCESS)
2986 {
2987 return CR_REGISTRY_ERROR;
2988 }
2989
2990 /* Open or create the device key */
2991 lError = RegCreateKeyExW(hKeyEnumerator,
2992 szDevice,
2993 0,
2994 NULL,
2997 NULL,
2998 &hKeyDevice,
2999 NULL);
3000
3001 /* Close the enumerator key */
3002 RegCloseKey(hKeyEnumerator);
3003
3004 if (lError != ERROR_SUCCESS)
3005 {
3006 return CR_REGISTRY_ERROR;
3007 }
3008
3009 /* Try to open the instance key and fail if it exists */
3010 lError = RegOpenKeyExW(hKeyDevice,
3011 szInstance,
3012 0,
3014 &hKeyInstance);
3015 if (lError == ERROR_SUCCESS)
3016 {
3017 DPRINT1("Instance %S already exists!\n", szInstance);
3018 RegCloseKey(hKeyInstance);
3019 RegCloseKey(hKeyDevice);
3021 }
3022
3023 /* Create a new instance key */
3024 lError = RegCreateKeyExW(hKeyDevice,
3025 szInstance,
3026 0,
3027 NULL,
3030 NULL,
3031 &hKeyInstance,
3032 NULL);
3033
3034 /* Close the device key */
3035 RegCloseKey(hKeyDevice);
3036
3037 if (lError != ERROR_SUCCESS)
3038 {
3039 return CR_REGISTRY_ERROR;
3040 }
3041
3042 if (bPhantomDevice)
3043 {
3044 DWORD dwPhantomValue = 1;
3045 RegSetValueExW(hKeyInstance,
3046 L"Phantom",
3047 0,
3048 REG_DWORD,
3049 (PBYTE)&dwPhantomValue,
3050 sizeof(dwPhantomValue));
3051 }
3052
3053 /* Create the 'Control' sub key */
3054 lError = RegCreateKeyExW(hKeyInstance,
3055 L"Control",
3056 0,
3057 NULL,
3060 NULL,
3061 &hKeyControl,
3062 NULL);
3063 if (lError == ERROR_SUCCESS)
3064 {
3065 RegCloseKey(hKeyControl);
3066 }
3067
3068 RegCloseKey(hKeyInstance);
3069
3070 return (lError == ERROR_SUCCESS) ? CR_SUCCESS : CR_REGISTRY_ERROR;
3071}
3072
3073
3074static
3077 _Inout_ LPWSTR pszDeviceID,
3078 _In_ PNP_RPC_STRING_LEN ulLength)
3079{
3080 WCHAR szGeneratedInstance[MAX_DEVICE_ID_LEN];
3081 HKEY hKey;
3082 DWORD dwInstanceNumber;
3083 DWORD dwError = ERROR_SUCCESS;
3085
3086 /* Fail, if the device name contains backslashes */
3087 if (wcschr(pszDeviceID, L'\\') != NULL)
3088 return CR_INVALID_DEVICE_ID;
3089
3090 /* Generated ID is: Root<Device ID><Instance number> */
3091 dwInstanceNumber = 0;
3092 while (dwError == ERROR_SUCCESS)
3093 {
3094 if (dwInstanceNumber >= 10000)
3095 return CR_FAILURE;
3096
3097 swprintf(szGeneratedInstance, L"Root\\%ls\\%04lu",
3098 pszDeviceID, dwInstanceNumber);
3099
3100 /* Try to open the enum key of the device instance */
3101 dwError = RegOpenKeyEx(hEnumKey, szGeneratedInstance, 0, KEY_QUERY_VALUE, &hKey);
3102 if (dwError == ERROR_SUCCESS)
3103 {
3105 dwInstanceNumber++;
3106 }
3107 }
3108
3109 /* pszDeviceID is an out parameter too for generated IDs */
3110 if (wcslen(szGeneratedInstance) > ulLength)
3111 {
3113 }
3114 else
3115 {
3116 wcscpy(pszDeviceID, szGeneratedInstance);
3117 }
3118
3119 return ret;
3120}
3121
3122
3123/* Function 28 */
3124DWORD
3125WINAPI
3128 LPWSTR pszDeviceID,
3129 LPWSTR pszParentDeviceID,
3130 PNP_RPC_STRING_LEN ulLength,
3131 DWORD ulFlags)
3132{
3134 HKEY hKey = NULL;
3135 DWORD dwSize, dwPhantom;
3138
3139 DPRINT("PNP_CreateDevInst(%p %S %S %lu 0x%08lx)\n",
3140 hBinding, pszParentDeviceID, pszDeviceID, ulLength, ulFlags);
3141
3142 if (ulFlags & ~CM_CREATE_DEVNODE_BITS)
3143 return CR_INVALID_FLAG;
3144
3145 if (pszDeviceID == NULL || pszParentDeviceID == NULL)
3146 return CR_INVALID_POINTER;
3147
3148 /* Fail, if the parent device is not the root device */
3149 if (!IsRootDeviceInstanceID(pszParentDeviceID))
3150 return CR_INVALID_DEVINST;
3151
3152 if (ulFlags & CM_CREATE_DEVNODE_GENERATE_ID)
3153 {
3154 ret = GenerateDeviceID(pszDeviceID,
3155 ulLength);
3156 if (ret != CR_SUCCESS)
3157 return ret;
3158 }
3159
3160 /* Try to open the device instance key */
3161 RegOpenKeyEx(hEnumKey, pszDeviceID, 0, KEY_READ | KEY_WRITE, &hKey);
3162
3163 if (ulFlags & CM_CREATE_DEVNODE_PHANTOM)
3164 {
3165 /* Fail, if the device already exists */
3166 if (hKey != NULL)
3167 {
3169 goto done;
3170 }
3171
3172 /* Create the phantom device instance */
3173 ret = CreateDeviceInstance(pszDeviceID, TRUE);
3174 }
3175 else
3176 {
3177 /* Fail, if the device exists and is present */
3178 if ((hKey != NULL) && (IsPresentDeviceInstanceID(pszDeviceID)))
3179 {
3181 goto done;
3182 }
3183
3184 /* If it does not already exist ... */
3185 if (hKey == NULL)
3186 {
3187 /* Create the device instance */
3188 ret = CreateDeviceInstance(pszDeviceID, FALSE);
3189
3190 /* Open the device instance key */
3191 RegOpenKeyEx(hEnumKey, pszDeviceID, 0, KEY_READ | KEY_WRITE, &hKey);
3192 }
3193
3194 /* Create a device node for the device */
3195 RtlInitUnicodeString(&ControlData.DeviceInstance, pszDeviceID);
3197 &ControlData,
3198 sizeof(ControlData));
3199 if (!NT_SUCCESS(Status))
3200 {
3201 ret = CR_FAILURE;
3202 goto done;
3203 }
3204
3205 /* If the device is a phantom device, turn it into a normal device */
3206 if (hKey != NULL)
3207 {
3208 dwPhantom = 0;
3209 dwSize = sizeof(DWORD);
3210 RegQueryValueEx(hKey, L"Phantom", NULL, NULL, (PBYTE)&dwPhantom, &dwSize);
3211
3212 if (dwPhantom != 0)
3213 RegDeleteValue(hKey, L"Phantom");
3214 }
3215 }
3216
3217done:
3218 if (hKey)
3220
3221 DPRINT("PNP_CreateDevInst() done (returns %lx)\n", ret);
3222
3223 return ret;
3224}
3225
3226
3227static CONFIGRET
3229 _In_ LPWSTR pszDeviceInstance,
3230 _In_ DWORD ulMinorAction)
3231{
3233 HKEY hDeviceKey = NULL;
3234 DWORD dwDisableCount, dwSize;
3235 DWORD ulStatus, ulProblem;
3236 DWORD dwError;
3239
3240 DPRINT1("SetupDeviceInstance(%S 0x%08lx)\n",
3241 pszDeviceInstance, ulMinorAction);
3242
3243 if (IsRootDeviceInstanceID(pszDeviceInstance))
3244 return CR_INVALID_DEVINST;
3245
3246 if (ulMinorAction & ~CM_SETUP_BITS)
3247 return CR_INVALID_FLAG;
3248
3249 if ((ulMinorAction == CM_SETUP_DOWNLOAD) ||
3250 (ulMinorAction == CM_SETUP_WRITE_LOG_CONFS))
3251 return CR_SUCCESS;
3252
3253 dwError = RegOpenKeyExW(hEnumKey,
3254 pszDeviceInstance,
3255 0,
3256 KEY_READ,
3257 &hDeviceKey);
3258 if (dwError != ERROR_SUCCESS)
3259 return CR_INVALID_DEVNODE;
3260
3261 dwSize = sizeof(dwDisableCount);
3262 dwError = RegQueryValueExW(hDeviceKey,
3263 L"DisableCount",
3264 NULL,
3265 NULL,
3266 (LPBYTE)&dwDisableCount,
3267 &dwSize);
3268 if ((dwError == ERROR_SUCCESS) &&
3269 (dwDisableCount > 0))
3270 {
3271 goto done;
3272 }
3273
3274 GetDeviceStatus(pszDeviceInstance,
3275 &ulStatus,
3276 &ulProblem);
3277
3278 if (ulStatus & DN_STARTED)
3279 {
3280 goto done;
3281 }
3282
3283 if (ulStatus & DN_HAS_PROBLEM)
3284 {
3285 ret = ClearDeviceStatus(pszDeviceInstance,
3287 ulProblem);
3288 }
3289
3290 if (ret != CR_SUCCESS)
3291 goto done;
3292
3293 /* Start the device */
3295 pszDeviceInstance);
3297 &ControlData,
3299 if (!NT_SUCCESS(Status))
3301
3302done:
3303 if (hDeviceKey != NULL)
3304 RegCloseKey(hDeviceKey);
3305
3306 return ret;
3307}
3308
3309
3310static CONFIGRET
3312 _In_ LPWSTR pszDeviceInstance)
3313{
3317
3318 DPRINT("Enable device instance %S\n", pszDeviceInstance);
3319
3320 RtlInitUnicodeString(&ControlData.DeviceInstance, pszDeviceInstance);
3321 Status = NtPlugPlayControl(PlugPlayControlStartDevice, &ControlData, sizeof(ControlData));
3322 if (!NT_SUCCESS(Status))
3324
3325 return ret;
3326}
3327
3328
3329static CONFIGRET
3331 _In_ LPWSTR pszDeviceInstance,
3332 _In_ ULONG ulMinorAction)
3333{
3334 PLUGPLAY_CONTROL_ENUMERATE_DEVICE_DATA EnumerateDeviceData;
3337
3338 DPRINT1("ReenumerateDeviceInstance(%S 0x%08lx)\n",
3339 pszDeviceInstance, ulMinorAction);
3340
3341 if (ulMinorAction & ~CM_REENUMERATE_BITS)
3342 return CR_INVALID_FLAG;
3343
3344 if (ulMinorAction & CM_REENUMERATE_RETRY_INSTALLATION)
3345 {
3346 DPRINT1("CM_REENUMERATE_RETRY_INSTALLATION not implemented!\n");
3347 }
3348
3349 RtlInitUnicodeString(&EnumerateDeviceData.DeviceInstance,
3350 pszDeviceInstance);
3351 EnumerateDeviceData.Flags = 0;
3352
3354 &EnumerateDeviceData,
3356 if (!NT_SUCCESS(Status))
3358
3359 return ret;
3360}
3361
3362
3363/* Function 29 */
3364DWORD
3365WINAPI
3368 DWORD ulMajorAction,
3369 DWORD ulMinorAction,
3370 LPWSTR pszDeviceInstance1,
3371 LPWSTR pszDeviceInstance2)
3372{
3374
3376
3377 DPRINT("PNP_DeviceInstanceAction(%p %lu 0x%08lx %S %S)\n",
3378 hBinding, ulMajorAction, ulMinorAction,
3379 pszDeviceInstance1, pszDeviceInstance2);
3380
3381 switch (ulMajorAction)
3382 {
3383 case PNP_DEVINST_SETUP:
3384 ret = SetupDeviceInstance(pszDeviceInstance1,
3385 ulMinorAction);
3386 break;
3387
3388 case PNP_DEVINST_ENABLE:
3389 ret = EnableDeviceInstance(pszDeviceInstance1);
3390 break;
3391
3392 case PNP_DEVINST_REENUMERATE:
3393 ret = ReenumerateDeviceInstance(pszDeviceInstance1,
3394 ulMinorAction);
3395 break;
3396
3397 default:
3398 DPRINT1("Unknown device action %lu: not implemented\n", ulMajorAction);
3400 }
3401
3402 DPRINT("PNP_DeviceInstanceAction() done (returns %lx)\n", ret);
3403
3404 return ret;
3405}
3406
3407
3408/* Function 30 */
3409DWORD
3410WINAPI
3413 LPWSTR pDeviceID,
3414 DWORD *pulStatus,
3415 DWORD *pulProblem,
3416 DWORD ulFlags)
3417{
3418 DWORD ulDataType, ulTransferLength, ulLength;
3419 DWORD ulCapabilities, ulConfigFlags;
3420 CONFIGRET ret;
3421
3423 UNREFERENCED_PARAMETER(ulFlags);
3424
3425 DPRINT("PNP_GetDeviceStatus(%p %S %p %p 0x%08lx)\n",
3426 hBinding, pDeviceID, pulStatus, pulProblem, ulFlags);
3427
3428 if (ulFlags != 0)
3429 return CR_INVALID_FLAG;
3430
3431 if ((pulStatus == NULL) || (pulProblem == NULL))
3432 return CR_INVALID_POINTER;
3433
3434 if (!IsValidDeviceInstanceID(pDeviceID))
3435 return CR_INVALID_DEVINST;
3436
3437 ret = GetDeviceStatus(pDeviceID, pulStatus, pulProblem);
3438 if (ret != CR_SUCCESS)
3439 return ret;
3440
3441 /* Check for DN_REMOVABLE */
3442 ulTransferLength = sizeof(ulCapabilities);
3443 ulLength = sizeof(ulCapabilities);
3445 pDeviceID,
3447 &ulDataType,
3448 (PBYTE)&ulCapabilities,
3449 &ulTransferLength,
3450 &ulLength,
3451 0);
3452 if (ret != CR_SUCCESS)
3453 ulCapabilities = 0;
3454
3455 if (ulCapabilities & CM_DEVCAP_REMOVABLE)
3456 *pulStatus |= DN_REMOVABLE;
3457
3458 /* Check for DN_MANUAL */
3459 ulTransferLength = sizeof(ulConfigFlags);
3460 ulLength = sizeof(ulConfigFlags);
3462 pDeviceID,
3464 &ulDataType,
3465 (PBYTE)&ulConfigFlags,
3466 &ulTransferLength,
3467 &ulLength,
3468 0);
3469 if (ret != CR_SUCCESS)
3470 ulConfigFlags = 0;
3471
3472 if (ulConfigFlags & CONFIGFLAG_MANUAL_INSTALL)
3473 *pulStatus |= DN_MANUAL;
3474
3475 /* Check for failed install */
3476 if (((*pulStatus & DN_HAS_PROBLEM) == 0) && (ulConfigFlags & CONFIGFLAG_FAILEDINSTALL))
3477 {
3478 *pulStatus |= DN_HAS_PROBLEM;
3479 *pulProblem = CM_PROB_FAILED_INSTALL;
3480 }
3481
3482 return CR_SUCCESS;
3483}
3484
3485
3486/* Function 31 */
3487DWORD
3488WINAPI
3491 LPWSTR pDeviceID,
3492 DWORD ulProblem,
3493 DWORD ulFlags)
3494{
3495 ULONG ulOldStatus, ulOldProblem;
3497
3499
3500 DPRINT1("PNP_SetDeviceProblem(%p %S %lu 0x%08lx)\n",
3501 hBinding, pDeviceID, ulProblem, ulFlags);
3502
3503 if (ulFlags & ~CM_SET_DEVNODE_PROBLEM_BITS)
3504 return CR_INVALID_FLAG;
3505
3506 if (!IsValidDeviceInstanceID(pDeviceID))
3507 return CR_INVALID_DEVINST;
3508
3509 ret = GetDeviceStatus(pDeviceID,
3510 &ulOldStatus,
3511 &ulOldProblem);
3512 if (ret != CR_SUCCESS)
3513 return ret;
3514
3515 if (((ulFlags & CM_SET_DEVNODE_PROBLEM_OVERRIDE) == 0) &&
3516 (ulOldProblem != 0) &&
3517 (ulOldProblem != ulProblem))
3518 {
3519 return CR_FAILURE;
3520 }
3521
3522 if (ulProblem == 0)
3523 {
3524 ret = ClearDeviceStatus(pDeviceID,
3526 ulOldProblem);
3527 }
3528 else
3529 {
3530 ret = SetDeviceStatus(pDeviceID,
3532 ulProblem);
3533 }
3534
3535 return ret;
3536}
3537
3538
3539/* Function 32 */
3540DWORD
3541WINAPI
3544 LPWSTR pDeviceID,
3545 PPNP_VETO_TYPE pVetoType,
3546 LPWSTR pszVetoName,
3547 DWORD ulNameLength,
3548 DWORD ulFlags)
3549{
3551
3552 DPRINT1("PNP_DisableDevInst(%p %S %p %p %lu 0x%08lx)\n",
3553 hBinding, pDeviceID, pVetoType, pszVetoName, ulNameLength, ulFlags);
3554
3555 if (ulFlags & ~CM_DISABLE_BITS)
3556 return CR_INVALID_FLAG;
3557
3558 if (!IsValidDeviceInstanceID(pDeviceID) ||
3559 IsRootDeviceInstanceID(pDeviceID))
3560 return CR_INVALID_DEVINST;
3561
3562 return DisableDeviceInstance(pDeviceID,
3563 pVetoType,
3564 pszVetoName,
3565 ulNameLength);
3566}
3567
3568
3569/* Function 33 */
3570DWORD
3571WINAPI
3574 LPWSTR pDeviceID,
3575 DWORD ulFlags)
3576{
3579}
3580
3581
3582static BOOL
3584 LPWSTR lpDeviceId)
3585{
3586 LPWSTR lpPtr;
3588
3589 lpPtr = lpDeviceIdList;
3590 while (*lpPtr != 0)
3591 {
3592 dwLength = wcslen(lpPtr);
3593 if (0 == _wcsicmp(lpPtr, lpDeviceId))
3594 return TRUE;
3595
3596 lpPtr += (dwLength + 1);
3597 }
3598
3599 return FALSE;
3600}
3601
3602
3603static VOID
3604AppendDeviceId(LPWSTR lpDeviceIdList,
3605 LPDWORD lpDeviceIdListSize,
3606 LPWSTR lpDeviceId)
3607{
3608 DWORD dwLen;
3609 DWORD dwPos;
3610
3611 dwLen = wcslen(lpDeviceId);
3612 dwPos = (*lpDeviceIdListSize / sizeof(WCHAR)) - 1;
3613
3614 wcscpy(&lpDeviceIdList[dwPos], lpDeviceId);
3615
3616 dwPos += (dwLen + 1);
3617
3618 lpDeviceIdList[dwPos] = 0;
3619
3620 *lpDeviceIdListSize = dwPos * sizeof(WCHAR);
3621}
3622
3623
3624/* Function 34 */
3625DWORD
3626WINAPI
3629 LPWSTR pszDeviceID,
3630 LPWSTR pszID,
3631 DWORD ulFlags)
3632{
3634 HKEY hDeviceKey;
3635 LPWSTR pszSubKey;
3636 DWORD dwDeviceIdListSize;
3637 DWORD dwNewDeviceIdSize;
3638 WCHAR * pszDeviceIdList = NULL;
3639
3641
3642 DPRINT("PNP_AddID(%p %S %S 0x%08lx)\n",
3643 hBinding, pszDeviceID, pszID, ulFlags);
3644
3646 pszDeviceID,
3647 0,
3649 &hDeviceKey) != ERROR_SUCCESS)
3650 {
3651 DPRINT("Failed to open the device key!\n");
3652 return CR_INVALID_DEVNODE;
3653 }
3654
3655 pszSubKey = (ulFlags & CM_ADD_ID_COMPATIBLE) ? L"CompatibleIDs" : L"HardwareID";
3656
3657 if (RegQueryValueExW(hDeviceKey,
3658 pszSubKey,
3659 NULL,
3660 NULL,
3661 NULL,
3662 &dwDeviceIdListSize) != ERROR_SUCCESS)
3663 {
3664 DPRINT("Failed to query the desired ID string!\n");
3666 goto Done;
3667 }
3668
3669 dwNewDeviceIdSize = lstrlenW(pszDeviceID);
3670 if (!dwNewDeviceIdSize)
3671 {
3673 goto Done;
3674 }
3675
3676 dwDeviceIdListSize += (dwNewDeviceIdSize + 2) * sizeof(WCHAR);
3677
3678 pszDeviceIdList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwDeviceIdListSize);
3679 if (!pszDeviceIdList)
3680 {
3681 DPRINT("Failed to allocate memory for the desired ID string!\n");
3683 goto Done;
3684 }
3685
3686 if (RegQueryValueExW(hDeviceKey,
3687 pszSubKey,
3688 NULL,
3689 NULL,
3690 (LPBYTE)pszDeviceIdList,
3691 &dwDeviceIdListSize) != ERROR_SUCCESS)
3692 {
3693 DPRINT("Failed to query the desired ID string!\n");
3695 goto Done;
3696 }
3697
3698 /* Check whether the device ID is already in use */
3699 if (CheckForDeviceId(pszDeviceIdList, pszDeviceID))
3700 {
3701 DPRINT("Device ID was found in the ID string!\n");
3702 ret = CR_SUCCESS;
3703 goto Done;
3704 }
3705
3706 /* Append the Device ID */
3707 AppendDeviceId(pszDeviceIdList, &dwDeviceIdListSize, pszID);
3708
3709 if (RegSetValueExW(hDeviceKey,
3710 pszSubKey,
3711 0,
3713 (LPBYTE)pszDeviceIdList,
3714 dwDeviceIdListSize) != ERROR_SUCCESS)
3715 {
3716 DPRINT("Failed to set the desired ID string!\n");
3718 }
3719
3720Done:
3721 RegCloseKey(hDeviceKey);
3722 if (pszDeviceIdList)
3723 HeapFree(GetProcessHeap(), 0, pszDeviceIdList);
3724
3725 DPRINT("PNP_AddID() done (returns %lx)\n", ret);
3726
3727 return ret;
3728}
3729
3730
3731/* Function 35 */
3732DWORD
3733WINAPI
3736 LPWSTR pszDeviceID,
3737 DWORD ulFlags)
3738{
3739 DPRINT("PNP_RegisterDriver(%p %S 0x%lx)\n",
3740 hBinding, pszDeviceID, ulFlags);
3741
3742 if (ulFlags & ~CM_REGISTER_DEVICE_DRIVER_BITS)
3743 return CR_INVALID_FLAG;
3744
3745 if (!IsValidDeviceInstanceID(pszDeviceID))
3746 return CR_INVALID_DEVINST;
3747
3748 SetDeviceStatus(pszDeviceID, 0, 0);
3749
3750 return CR_SUCCESS;
3751}
3752
3753
3754/* Function 36 */
3755DWORD
3756WINAPI
3759 LPWSTR pszDeviceID,
3760 PPNP_VETO_TYPE pVetoType,
3761 LPWSTR pszVetoName,
3762 DWORD ulNameLength,
3763 DWORD ulFlags)
3764{
3768
3769 DPRINT1("PNP_QueryRemove(%p %S %p %p %lu 0x%lx)\n",
3770 hBinding, pszDeviceID, pVetoType, pszVetoName,
3771 ulNameLength, ulFlags);
3772
3773 if (ulFlags & ~CM_REMOVE_BITS)
3774 return CR_INVALID_FLAG;
3775
3776 if (!IsValidDeviceInstanceID(pszDeviceID) ||
3777 IsRootDeviceInstanceID(pszDeviceID))
3778 return CR_INVALID_DEVINST;
3779
3780 if (pVetoType != NULL)
3781 *pVetoType = PNP_VetoTypeUnknown;
3782
3783 if (pszVetoName != NULL && ulNameLength > 0)
3784 *pszVetoName = UNICODE_NULL;
3785
3786 RtlZeroMemory(&PlugPlayData, sizeof(PlugPlayData));
3788 pszDeviceID);
3789 PlugPlayData.VetoName = pszVetoName;
3790 PlugPlayData.NameLength = ulNameLength;
3791// PlugPlayData.Flags =
3792
3794 &PlugPlayData,
3795 sizeof(PlugPlayData));
3796 if (!NT_SUCCESS(Status))
3798
3799 return ret;
3800}
3801
3802
3803/* Function 37 */
3804DWORD
3805WINAPI
3808 LPWSTR pszDeviceID,
3809 PPNP_VETO_TYPE pVetoType,
3810 LPWSTR pszVetoName,
3811 DWORD ulNameLength,
3812 DWORD ulFlags)
3813{
3817
3818 DPRINT1("PNP_RequestDeviceEject(%p %S %p %p %lu 0x%lx)\n",
3819 hBinding, pszDeviceID, pVetoType, pszVetoName,
3820 ulNameLength, ulFlags);
3821
3822 if (ulFlags != 0)
3823 return CR_INVALID_FLAG;
3824
3825 if (!IsValidDeviceInstanceID(pszDeviceID))
3826 return CR_INVALID_DEVINST;
3827
3828 if (pVetoType != NULL)
3829 *pVetoType = PNP_VetoTypeUnknown;
3830
3831 if (pszVetoName != NULL && ulNameLength > 0)
3832 *pszVetoName = UNICODE_NULL;
3833
3834 RtlZeroMemory(&PlugPlayData, sizeof(PlugPlayData));
3836 pszDeviceID);
3837 PlugPlayData.VetoName = pszVetoName;
3838 PlugPlayData.NameLength = ulNameLength;
3839// PlugPlayData.Flags =
3840
3842 &PlugPlayData,
3843 sizeof(PlugPlayData));
3844 if (!NT_SUCCESS(Status))
3846
3847 return ret;
3848}
3849
3850
3851/* Function 38 */
3853WINAPI
3856 BOOL *Present)
3857{
3858 HKEY hKey;
3859 DWORD dwType;
3860 DWORD dwValue;
3861 DWORD dwSize;
3863
3865
3866 DPRINT1("PNP_IsDockStationPresent(%p %p)\n",
3867 hBinding, Present);
3868
3869 *Present = FALSE;
3870
3872 L"CurrentDockInfo",
3873 0,
3874 KEY_READ,
3875 &hKey) != ERROR_SUCCESS)
3876 return CR_REGISTRY_ERROR;
3877
3878 dwSize = sizeof(DWORD);
3880 L"DockingState",
3881 NULL,
3882 &dwType,
3883 (LPBYTE)&dwValue,
3884 &dwSize) != ERROR_SUCCESS)
3886
3888
3889 if (ret == CR_SUCCESS)
3890 {
3891 if (dwType != REG_DWORD || dwSize != sizeof(DWORD))
3892 {
3894 }
3895 else if (dwValue != 0)
3896 {
3897 *Present = TRUE;
3898 }
3899 }
3900
3901 DPRINT1("PNP_IsDockStationPresent() done (returns %lx)\n", ret);
3902
3903 return ret;
3904}
3905
3906
3907/* Function 39 */
3908DWORD
3909WINAPI
3912{
3913 WCHAR szDockDeviceInstance[MAX_DEVICE_ID_LEN];
3916
3917 DPRINT("PNP_RequestEjectPC(%p)\n", hBinding);
3918
3919 /* Retrieve the dock device */
3920 DockData.DeviceInstanceLength = ARRAYSIZE(szDockDeviceInstance);
3921 DockData.DeviceInstance = szDockDeviceInstance;
3922
3924 &DockData,
3925 sizeof(DockData));
3926 if (!NT_SUCCESS(Status))
3927 return NtStatusToCrError(Status);
3928
3929 /* Eject the dock device */
3931 szDockDeviceInstance,
3932 NULL,
3933 NULL,
3934 0,
3935 0);
3936}
3937
3938
3939/* Function 40 */
3940DWORD
3941WINAPI
3944 DWORD ulAction,
3945 LPWSTR pDeviceID,
3946 DWORD ulConfig,
3947 DWORD *pulValue,
3948 PPNP_VETO_TYPE pVetoType,
3949 LPWSTR pszVetoName,
3950 DWORD ulNameLength,
3951 DWORD ulFlags)
3952{
3954 WCHAR szKeyName[MAX_PATH];
3955 HKEY hKey;
3956 HKEY hDeviceKey;
3957 DWORD dwSize;
3958
3960
3961 DPRINT("PNP_HwProfFlags() called\n");
3962
3963 if (!IsValidDeviceInstanceID(pDeviceID))
3964 return CR_INVALID_DEVINST;
3965
3966 if (ulConfig == 0)
3967 {
3968 wcscpy(szKeyName,
3969 L"System\\CurrentControlSet\\HardwareProfiles\\Current\\System\\CurrentControlSet\\Enum");
3970 }
3971 else
3972 {
3973 swprintf(szKeyName,
3974 L"System\\CurrentControlSet\\HardwareProfiles\\%04lu\\System\\CurrentControlSet\\Enum",
3975 ulConfig);
3976 }
3977
3979 szKeyName,
3980 0,
3982 &hKey) != ERROR_SUCCESS)
3983 return CR_REGISTRY_ERROR;
3984
3985 if (ulAction == PNP_GET_HWPROFFLAGS)
3986 {
3987 if (RegOpenKeyExW(hKey,
3988 pDeviceID,
3989 0,
3991 &hDeviceKey) != ERROR_SUCCESS)
3992 {
3993 *pulValue = 0;
3994 }
3995 else
3996 {
3997 dwSize = sizeof(DWORD);
3998 if (RegQueryValueExW(hDeviceKey,
3999 L"CSConfigFlags",
4000 NULL,
4001 NULL,
4002 (LPBYTE)pulValue,
4003 &dwSize) != ERROR_SUCCESS)
4004 {
4005 *pulValue = 0;
4006 }
4007
4008 RegCloseKey(hDeviceKey);
4009 }
4010 }
4011 else if (ulAction == PNP_SET_HWPROFFLAGS)
4012 {
4013 /* FIXME: not implemented yet */
4015 }
4016
4018
4019 return ret;
4020}
4021
4022
4023/* Function 41 */
4024DWORD
4025WINAPI
4028 DWORD ulIndex,
4029 HWPROFILEINFO *pHWProfileInfo,
4030 DWORD ulProfileInfoSize,
4031 DWORD ulFlags)
4032{
4033 WCHAR szProfileName[5];
4034 HKEY hKeyConfig = NULL;
4035 HKEY hKeyProfiles = NULL;
4036 HKEY hKeyProfile = NULL;
4037 DWORD dwDisposition;
4038 DWORD dwSize;
4039 LONG lError;
4041
4043
4044 DPRINT("PNP_GetHwProfInfo() called\n");
4045
4046 if (ulProfileInfoSize == 0)
4047 {
4049 goto done;
4050 }
4051
4052 if (ulFlags != 0)
4053 {
4055 goto done;
4056 }
4057
4058 /* Initialize the profile information */
4059 pHWProfileInfo->HWPI_ulHWProfile = 0;
4060 pHWProfileInfo->HWPI_szFriendlyName[0] = 0;
4061 pHWProfileInfo->HWPI_dwFlags = 0;
4062
4063 /* Open the 'IDConfigDB' key */
4065 L"System\\CurrentControlSet\\Control\\IDConfigDB",
4066 0,
4067 NULL,
4070 NULL,
4071 &hKeyConfig,
4072 &dwDisposition);
4073 if (lError != ERROR_SUCCESS)
4074 {
4076 goto done;
4077 }
4078
4079 /* Open the 'Hardware Profiles' subkey */
4080 lError = RegCreateKeyExW(hKeyConfig,
4081 L"Hardware Profiles",
4082 0,
4083 NULL,
4086 NULL,
4087 &hKeyProfiles,
4088 &dwDisposition);
4089 if (lError != ERROR_SUCCESS)
4090 {
4092 goto done;
4093 }
4094
4095 if (ulIndex == (ULONG)-1)
4096 {
4097 dwSize = sizeof(ULONG);
4098 lError = RegQueryValueExW(hKeyConfig,
4099 L"CurrentConfig",
4100 NULL,
4101 NULL,
4102 (LPBYTE)&pHWProfileInfo->HWPI_ulHWProfile,
4103 &dwSize);
4104 if (lError != ERROR_SUCCESS)
4105 {
4106 pHWProfileInfo->HWPI_ulHWProfile = 0;
4108 goto done;
4109 }
4110 }
4111 else
4112 {
4113 /* FIXME: not implemented yet */
4115 goto done;
4116 }
4117
4118 swprintf(szProfileName, L"%04lu", pHWProfileInfo->HWPI_ulHWProfile);
4119
4120 lError = RegOpenKeyExW(hKeyProfiles,
4121 szProfileName,
4122 0,
4124 &hKeyProfile);
4125 if (lError != ERROR_SUCCESS)
4126 {
4128 goto done;
4129 }
4130
4131 dwSize = sizeof(pHWProfileInfo->HWPI_szFriendlyName);
4132 lError = RegQueryValueExW(hKeyProfile,
4133 L"FriendlyName",
4134 NULL,
4135 NULL,
4136 (LPBYTE)&pHWProfileInfo->HWPI_szFriendlyName,
4137 &dwSize);
4138 if (lError != ERROR_SUCCESS)
4139 {
4141 goto done;
4142 }
4143
4144done:
4145 if (hKeyProfile != NULL)
4146 RegCloseKey(hKeyProfile);
4147
4148 if (hKeyProfiles != NULL)
4149 RegCloseKey(hKeyProfiles);
4150
4151 if (hKeyConfig != NULL)
4152 RegCloseKey(hKeyConfig);
4153
4154 return ret;
4155}
4156
4157
4158/* Function 42 */
4159DWORD
4160WINAPI
4163 LPWSTR pDeviceID,
4164 DWORD ulPriority,
4165 DWORD *pulLogConfTag,
4166 DWORD ulFlags)
4167{
4170}
4171
4172
4173/* Function 43 */
4174DWORD
4175WINAPI
4178 LPWSTR pDeviceID,
4179 DWORD ulLogConfType,
4180 DWORD ulLogConfTag,
4181 DWORD ulFlags)
4182{
4185}
4186
4187
4188/* Function 44 */
4189DWORD
4190WINAPI
4193 LPWSTR pDeviceID,
4194 DWORD ulLogConfType,
4195 DWORD *pulLogConfTag,
4196 DWORD ulFlags)
4197{
4198 HKEY hConfigKey = NULL;
4199 DWORD RegDataType = 0;
4200 ULONG ulDataSize = 0;
4201 LPBYTE lpData = NULL;
4203
4204 DPRINT("PNP_GetFirstLogConf(%p %S %lu %p 0x%08lx)\n",
4205 hBinding, pDeviceID, ulLogConfType, pulLogConfTag, ulFlags);
4206
4207 if (pulLogConfTag == NULL)
4208 return CR_INVALID_POINTER;
4209
4210 *pulLogConfTag = (DWORD)0;
4211
4212 if (ulFlags & ~LOG_CONF_BITS)
4213 return CR_INVALID_FLAG;
4214
4215 if (!IsValidDeviceInstanceID(pDeviceID))
4216 return CR_INVALID_DEVINST;
4217
4218 ret = OpenConfigurationKey(pDeviceID,
4219 ulLogConfType,
4220 &hConfigKey);
4221 if (ret != CR_SUCCESS)
4222 {
4223 DPRINT1("OpenConfigurationKey() failed (Error %lu)\n", ret);
4225 goto done;
4226 }
4227
4228 ret = GetConfigurationData(hConfigKey,
4229 ulLogConfType,
4230 &RegDataType,
4231 &ulDataSize,
4232 &lpData);
4233 if (ret != CR_SUCCESS)
4234 {
4235 DPRINT1("GetConfigurationData() failed (Error %lu)\n", ret);
4237 goto done;
4238 }
4239
4240 DPRINT1("Data size %lu\n", ulDataSize);
4241 if (ulDataSize == 0 || lpData == NULL)
4242 {
4243 DPRINT1("No config data available!\n");
4245 goto done;
4246 }
4247
4248 /* Get the first tag */
4249 if (RegDataType == REG_RESOURCE_LIST)
4250 {
4251 DPRINT("REG_RESOURCE_LIST->Count %lu\n", ((PCM_RESOURCE_LIST)lpData)->Count);
4252
4253 /* Indicate that we reached the end of the list */
4254 if (((PCM_RESOURCE_LIST)lpData)->Count == 0)
4255 {
4256 DPRINT1("No resource descriptors!\n");
4258 goto done;
4259 }
4260 }
4261 else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST)
4262 {
4263 DPRINT1("FIXME: REG_RESOURCE_REQUIREMENTS_LIST\n");
4264 /* FIXME */
4266 goto done;
4267 }
4268
4269done:
4270 if (lpData != NULL)
4271 HeapFree(GetProcessHeap(), 0, lpData);
4272
4273 if (hConfigKey != NULL)
4274 RegCloseKey(hConfigKey);
4275
4276 DPRINT("PNP_GetFirstLogConf() returns %lu\n", ret);
4277
4278 return ret;
4279}
4280
4281
4282/* Function 45 */
4283DWORD
4284WINAPI
4287 LPWSTR pDeviceID,
4288 DWORD ulLogConfType,
4289 DWORD ulCurrentTag,
4290 DWORD *pulNextTag,
4291 DWORD ulFlags)
4292{
4293 HKEY hConfigKey = NULL;
4294 DWORD RegDataType = 0;
4295 ULONG ulDataSize = 0;
4296 LPBYTE lpData = NULL;
4298
4299 DPRINT("PNP_GetNextLogConf(%p %S %lu %ul %p 0x%08lx)\n",
4300 hBinding, pDeviceID, ulLogConfType, ulCurrentTag, pulNextTag, ulFlags);
4301
4302 if (pulNextTag == NULL)
4303 return CR_INVALID_POINTER;
4304
4305 *pulNextTag = (DWORD)0;
4306
4307 if (ulFlags != 0)
4308 return CR_INVALID_FLAG;
4309
4310 if (!IsValidDeviceInstanceID(pDeviceID))
4311 return CR_INVALID_DEVINST;
4312
4313 ret = OpenConfigurationKey(pDeviceID,
4314 ulLogConfType,
4315 &hConfigKey);
4316 if (ret != CR_SUCCESS)
4317 {
4318 DPRINT1("OpenConfigurationKey() failed (Error %lu)\n", ret);
4320 goto done;
4321 }
4322
4323 ret = GetConfigurationData(hConfigKey,
4324 ulLogConfType,
4325 &RegDataType,
4326 &ulDataSize,
4327 &lpData);
4328 if (ret != CR_SUCCESS)
4329 {
4330 DPRINT1("GetConfigurationData() failed (Error %lu)\n", ret);
4332 goto done;
4333 }
4334
4335 DPRINT("Data size %lu\n", ulDataSize);
4336
4337 if (ulDataSize == 0 || lpData == NULL)
4338 {
4339 DPRINT1("No config data available!\n");
4341 goto done;
4342 }
4343
4344 /* Check if the next entry is available */
4345 if (RegDataType == REG_RESOURCE_LIST)
4346 {
4347 DPRINT("REG_RESOURCE_LIST->Count %lu\n", ((PCM_RESOURCE_LIST)lpData)->Count);
4348
4349 /* Fail, if we are beyond the end of the list */
4350 if (ulCurrentTag >= ((PCM_RESOURCE_LIST)lpData)->Count)
4351 {
4353 goto done;
4354 }
4355
4356 /* Indicate that we reached the end of the list */
4357 if (ulCurrentTag == ((PCM_RESOURCE_LIST)lpData)->Count - 1)
4358 {
4360 goto done;
4361 }
4362 }
4363 else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST)
4364 {
4365 DPRINT1("FIXME: REG_RESOURCE_REQUIREMENTS_LIST\n");
4366 /* FIXME */
4368 goto done;
4369 }
4370
4371 /* Return the next tag value */
4372 *pulNextTag = ulCurrentTag + 1;
4373
4374done:
4375 if (lpData != NULL)
4376 HeapFree(GetProcessHeap(), 0, lpData);
4377
4378 if (hConfigKey != NULL)
4379 RegCloseKey(hConfigKey);
4380
4381 DPRINT("PNP_GetNextLogConf() returns %lu\n", ret);
4382
4383 return ret;
4384}
4385
4386
4387/* Function 46 */
4388DWORD
4389WINAPI
4392 LPWSTR pDeviceID,
4393 DWORD ulType,
4394 DWORD ulTag,
4395 DWORD *pPriority,
4396 DWORD ulFlags)
4397{
4400}
4401
4402
4403/* Function 47 */
4404DWORD
4405WINAPI
4408 LPWSTR pDeviceID,
4409 DWORD ulLogConfTag,
4410 DWORD ulLogConfType,
4411 RESOURCEID ResourceID,
4412 DWORD *pulResourceTag,
4413 BYTE *ResourceData,
4414 PNP_RPC_BUFFER_SIZE ResourceLen,
4415 DWORD ulFlags)
4416{
4419}
4420
4421
4422/* Function 48 */
4423DWORD
4424WINAPI
4427 LPWSTR pDeviceID,
4428 DWORD ulLogConfTag,
4429 DWORD ulLogConfType,
4430 RESOURCEID ResourceID,
4431 DWORD ulResourceTag,
4432 DWORD *pulPreviousResType,
4433 DWORD *pulPreviousResTag,
4434 DWORD ulFlags)
4435{
4438}
4439
4440
4441/* Function 49 */
4442DWORD
4443WINAPI
4446 LPWSTR pDeviceID,
4447 DWORD ulLogConfTag,
4448 DWORD ulLogConfType,
4449 RESOURCEID ResourceID,
4450 DWORD ulResourceTag,
4451 DWORD *pulNextResType,
4452 DWORD *pulNextResTag,
4453 DWORD ulFlags)
4454{
4455 HKEY hConfigKey = NULL;
4456 DWORD RegDataType = 0;
4457 ULONG ulDataSize = 0;
4458 LPBYTE lpData = NULL;
4460
4461 DPRINT1("PNP_GetNextResDes(%p %S 0x%lx %lu %lu %ul %p %p 0x%08lx)\n",
4462 hBinding, pDeviceID, ulLogConfTag, ulLogConfType, ResourceID,
4463 ulResourceTag, pulNextResType, pulNextResTag, ulFlags);
4464
4465 if (pulNextResType == NULL)
4466 return CR_INVALID_POINTER;
4467
4468 *pulNextResType = 0;
4469
4470 if (ulFlags != 0)
4471 return CR_INVALID_FLAG;
4472
4473 if (!IsValidDeviceInstanceID(pDeviceID))
4474 return CR_INVALID_DEVINST;
4475
4476 ret = OpenConfigurationKey(pDeviceID,
4477 ulLogConfType,
4478 &hConfigKey);
4479 if (ret != CR_SUCCESS)
4480 {
4481 DPRINT1("OpenConfigurationKey() failed (Error %lu)\n", ret);
4483 goto done;
4484 }
4485
4486 ret = GetConfigurationData(hConfigKey,
4487 ulLogConfType,
4488 &RegDataType,
4489 &ulDataSize,
4490 &lpData);
4491 if (ret != CR_SUCCESS)
4492 {
4493 DPRINT1("GetConfigurationData() failed (Error %lu)\n", ret);
4495 goto done;
4496 }
4497
4498 DPRINT1("Data size %lu\n", ulDataSize);
4499
4500 if (ulDataSize == 0 || lpData == NULL)
4501 {
4502 DPRINT1("No config data available!\n");
4504 goto done;
4505 }
4506
4507 /* Get the next resource descriptor */
4508 if (RegDataType == REG_RESOURCE_LIST)
4509 {
4510 DPRINT1("FIXME: REG_RESOURCE_LIST\n");
4511 /* FIXME */
4513 goto done;
4514 }
4515 else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST)
4516 {
4517 DPRINT1("FIXME: REG_RESOURCE_REQUIREMENTS_LIST\n");
4518 /* FIXME */
4520 goto done;
4521 }
4522
4523done:
4524 if (lpData != NULL)
4525 HeapFree(GetProcessHeap(), 0, lpData);
4526
4527 if (hConfigKey != NULL)
4528 RegCloseKey(hConfigKey);
4529
4530 DPRINT1("PNP_GetNextResDes() returns %lu\n", ret);
4531
4532 return ret;
4533}
4534
4535
4536/* Function 50 */
4537DWORD
4538WINAPI
4541 LPWSTR pDeviceID,
4542 DWORD ulLogConfTag,
4543 DWORD ulLogConfType,
4544 RESOURCEID ResourceID,
4545 DWORD ulResourceTag,
4546 BYTE *Buffer,
4547 PNP_RPC_BUFFER_SIZE BufferLen,
4548 DWORD ulFlags)
4549{
4552}
4553
4554
4555/* Function 51 */
4556DWORD
4557WINAPI
4560 LPWSTR pDeviceID,
4561 DWORD ulLogConfTag,
4562 DWORD ulLogConfType,
4563 RESOURCEID ResourceID,
4564 DWORD ulResourceTag,
4565 DWORD *pulSize,
4566 DWORD ulFlags)
4567{
4570}
4571
4572
4573/* Function 52 */
4574DWORD
4575WINAPI
4578 LPWSTR pDeviceID,
4579 DWORD ulLogConfTag,
4580 DWORD ulLogConfType,
4581 RESOURCEID CurrentResourceID,
4582 RESOURCEID NewResourceID,
4583 DWORD ulResourceTag,
4584 BYTE *ResourceData,
4585 PNP_RPC_BUFFER_SIZE ResourceLen,
4586 DWORD ulFlags)
4587{
4590}
4591
4592
4593/* Function 53 */
4594DWORD
4595WINAPI
4598 LPWSTR pDeviceID,
4599 RESOURCEID ResourceID,
4600 BYTE *ResourceData,
4601 PNP_RPC_BUFFER_SIZE ResourceLen,
4602 BOOL *pbConflictDetected,
4603 DWORD ulFlags)
4604{
4605 DPRINT("PNP_DetectResourceConflict()\n");
4606
4607 if (pbConflictDetected != NULL)
4608 *pbConflictDetected = FALSE;
4609
4611}
4612
4613
4614/* Function 54 */
4615DWORD
4616WINAPI
4619 LPWSTR pDeviceID,
4620 RESOURCEID ResourceID,
4621 BYTE *ResourceData,
4622 PNP_RPC_BUFFER_SIZE ResourceLen,
4623 BYTE *Buffer,
4624 PNP_RPC_BUFFER_SIZE BufferLen,
4625 DWORD ulFlags)
4626{
4629}
4630
4631
4632/* Function 55 */
4633DWORD
4634WINAPI
4637 DWORD ulHardwareProfile,
4638 DWORD ulFlags)
4639{
4641}
4642
4643
4644/* Function 56 */
4645DWORD
4646WINAPI
4649 BYTE *pData,
4650 DWORD DataLen,
4651 LPWSTR pDeviceID,
4652 RESOURCEID ResourceID,
4653 DWORD ulFlags)
4654{
4656}
4657
4658
4659/* Function 57 */
4660DWORD
4661WINAPI
4664 DWORD *pulSize,
4665 LPWSTR pDeviceID,
4666 RESOURCEID ResourceID,
4667 DWORD ulFlags)
4668{
4669 if (pulSize != NULL)
4670 *pulSize = 0;
4671
4673}
4674
4675
4676/* Function 58 */
4678WINAPI
4681 DWORD ulFlags)
4682{
4684}
4685
4686
4687/* Function 59 */
4688DWORD
4689WINAPI
4692 DWORD_PTR hRecipient,
4693 LPWSTR pszName,
4694 BYTE *pNotificationFilter,
4695 DWORD ulNotificationFilterSize,
4696 DWORD ulFlags,
4697 PNP_NOTIFY_HANDLE *pNotifyHandle,
4698 DWORD ulProcessId,
4699 DWORD *pulUnknown9)
4700{
4701 PDEV_BROADCAST_DEVICEINTERFACE_W pBroadcastDeviceInterface;
4702 PDEV_BROADCAST_HANDLE pBroadcastDeviceHandle;
4703 PNOTIFY_ENTRY pNotifyData = NULL;
4704
4705 DPRINT1("PNP_RegisterNotification(%p %p '%S' %p %lu 0x%lx %p %lx %p)\n",
4706 hBinding, hRecipient, pszName, pNotificationFilter,
4707 ulNotificationFilterSize, ulFlags, pNotifyHandle, ulProcessId, pulUnknown9);
4708
4709 if (pNotifyHandle == NULL)
4710 return CR_INVALID_POINTER;
4711
4712 *pNotifyHandle = NULL;
4713
4714 if (pNotificationFilter == NULL ||
4715 pulUnknown9 == NULL)
4716 return CR_INVALID_POINTER;
4717
4718 if (ulFlags & ~0x7)
4719 return CR_INVALID_FLAG;
4720
4721 if ((ulNotificationFilterSize < sizeof(DEV_BROADCAST_HDR)) ||
4722 (((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_size < sizeof(DEV_BROADCAST_HDR)))
4723 return CR_INVALID_DATA;
4724
4725 if (((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
4726 {
4727 DPRINT1("DBT_DEVTYP_DEVICEINTERFACE\n");
4728 pBroadcastDeviceInterface = (PDEV_BROADCAST_DEVICEINTERFACE_W)pNotificationFilter;
4729
4730 if ((ulNotificationFilterSize < sizeof(DEV_BROADCAST_DEVICEINTERFACE_W)) ||
4731 (pBroadcastDeviceInterface->dbcc_size < sizeof(DEV_BROADCAST_DEVICEINTERFACE_W)))
4732 return CR_INVALID_DATA;
4733
4735 if (pNotifyData == NULL)
4736 return CR_OUT_OF_MEMORY;
4737
4738 if (pszName != NULL)
4739 {
4740 pNotifyData->pszName = RtlAllocateHeap(GetProcessHeap(),
4742 (wcslen(pszName) + 1) * sizeof(WCHAR));
4743 if (pNotifyData->pszName == NULL)
4744 {
4745 RtlFreeHeap(GetProcessHeap(), 0, pNotifyData);
4746 return CR_OUT_OF_MEMORY;
4747 }
4748 }
4749
4750 /* Add the entry to the notification list */
4752
4753 DPRINT("pNotifyData: %p\n", pNotifyData);
4754 *pNotifyHandle = (PNP_NOTIFY_HANDLE)pNotifyData;
4755 }
4756 else if (((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_devicetype == DBT_DEVTYP_HANDLE)
4757 {
4758 DPRINT1("DBT_DEVTYP_HANDLE\n");
4759 pBroadcastDeviceHandle = (PDEV_BROADCAST_HANDLE)pNotificationFilter;
4760
4761 if ((ulNotificationFilterSize < sizeof(DEV_BROADCAST_HANDLE)) ||
4762 (pBroadcastDeviceHandle->dbch_size < sizeof(DEV_BROADCAST_HANDLE)))
4763 return CR_INVALID_DATA;
4764
4765 if (ulFlags & DEVICE_NOTIFY_ALL_INTERFACE_CLASSES)
4766 return CR_INVALID_FLAG;
4767 }
4768 else
4769 {
4770 DPRINT1("Invalid device type %lu\n", ((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_devicetype);
4771 return CR_INVALID_DATA;
4772 }
4773
4774 return CR_SUCCESS;
4775}
4776
4777
4778/* Function 60 */
4779DWORD
4780WINAPI
4783 PNP_NOTIFY_HANDLE *pNotifyHandle)
4784{
4786
4787 DPRINT1("PNP_UnregisterNotification(%p %p)\n",
4788 hBinding, pNotifyHandle);
4789
4790 pEntry = (PNOTIFY_ENTRY)*pNotifyHandle;
4791 if (pEntry == NULL)
4792 return CR_INVALID_DATA;
4793
4794 RemoveEntryList(&pEntry->ListEntry);
4795 if (pEntry->pszName)
4796 RtlFreeHeap(RtlGetProcessHeap(), 0, pEntry->pszName);
4797 RtlFreeHeap(RtlGetProcessHeap(), 0, pEntry);
4798 *pNotifyHandle = NULL;
4799
4800 return CR_SUCCESS;
4801}
4802
4803
4804/* Function 61 */
4805DWORD
4806WINAPI
4809 LPWSTR pDeviceID,
4810 LPWSTR CustomPropName,
4811 DWORD *pulRegDataType,
4812 BYTE *Buffer,
4813 PNP_RPC_STRING_LEN *pulTransferLen,
4814 PNP_RPC_STRING_LEN *pulLength,
4815 DWORD ulFlags)
4816{
4817 HKEY hDeviceKey = NULL;
4818 HKEY hParamKey = NULL;
4819 LONG lError;
4821
4823
4824 DPRINT("PNP_GetCustomDevProp() called\n");
4825
4826 if (pulTransferLen == NULL || pulLength == NULL)
4827 {
4829 goto done;
4830 }
4831
4832 if (ulFlags & ~CM_CUSTOMDEVPROP_BITS)
4833 {
4835 goto done;
4836 }
4837
4838 if (!IsValidDeviceInstanceID(pDeviceID))
4839 return CR_INVALID_DEVINST;
4840
4841 if (*pulLength < *pulTransferLen)
4842 *pulLength = *pulTransferLen;
4843
4844 *pulTransferLen = 0;
4845
4846 lError = RegOpenKeyExW(hEnumKey,
4847 pDeviceID,
4848 0,
4849 KEY_READ,
4850 &hDeviceKey);
4851 if (lError != ERROR_SUCCESS)
4852 {
4854 goto done;
4855 }
4856
4857 lError = RegOpenKeyExW(hDeviceKey,
4858 L"Device Parameters",
4859 0,
4860 KEY_READ,
4861 &hParamKey);
4862 if (lError != ERROR_SUCCESS)
4863 {
4865 goto done;
4866 }
4867
4868 lError = RegQueryValueExW(hParamKey,
4869 CustomPropName,
4870 NULL,
4871 pulRegDataType,
4872 Buffer,
4873 pulLength);
4874 if (lError != ERROR_SUCCESS)
4875 {
4876 if (lError == ERROR_MORE_DATA)
4877 {
4879 }
4880 else
4881 {
4882 *pulLength = 0;
4884 }
4885 }
4886
4887done:
4888 if (ret == CR_SUCCESS)
4889 *pulTransferLen = *pulLength;
4890
4891 if (hParamKey != NULL)
4892 RegCloseKey(hParamKey);
4893
4894 if (hDeviceKey != NULL)
4895 RegCloseKey(hDeviceKey);
4896
4897 DPRINT("PNP_GetCustomDevProp() done (returns %lx)\n", ret);
4898
4899 return ret;
4900}
4901
4902
4903/* Function 62 */
4904DWORD
4905WINAPI
4908 WORD *pwVersion)
4909{
4911
4912 *pwVersion = WINVER;
4913 return CR_SUCCESS;
4914}
4915
4916
4917/* Function 63 */
4918DWORD
4919WINAPI
4922 BYTE *Buffer,
4923 PNP_RPC_BUFFER_SIZE *pulTransferLen,
4924 PNP_RPC_BUFFER_SIZE *pulLength,
4925 DWORD ulFlags)
4926{
4929}
4930
4931
4932/* Function 64 */
4933DWORD
4934WINAPI
4937 DWORD *pulSSDIFlags,
4938 DWORD ulFlags)
4939{
4941
4942 DPRINT1("PNP_GetServerSideDeviceInstallFlags(%p %p %lu)\n",
4943 hBinding, pulSSDIFlags, ulFlags);
4944
4945 if (pulSSDIFlags == NULL)
4946 return CR_INVALID_POINTER;
4947
4948 if (ulFlags != 0)
4949 return CR_INVALID_FLAG;
4950
4951 /* FIXME */
4952 *pulSSDIFlags = 0;
4953
4954 return CR_SUCCESS;
4955}
4956
4957
4958/* Function 65 */
4959DWORD
4960WINAPI
4965 LPWSTR PropertyCultureName,
4966 PNP_PROP_COUNT *PropertyCount,
4967 PNP_PROP_COUNT *TransferLen,
4968 DEVPROPKEY *PropertyKeys,
4969 DWORD Flags)
4970{
4973}
4974
4975
4976/* Function 66 */
4977DWORD
4978WINAPI
4983 LPWSTR PropertyCultureName,
4984 const DEVPROPKEY *PropertyKey,
4986 PNP_PROP_SIZE *PropertySize,
4987 PNP_PROP_SIZE *TransferLen,
4989 DWORD Flags)
4990{
4993}
4994
4995
4996/* Function 67 */
4997DWORD
4998WINAPI
5003 LPWSTR PropertyCultureName,
5004 const DEVPROPKEY *PropertyKey,
5006 PNP_PROP_SIZE PropertySize,
5008 DWORD Flags)
5009{
5012}
5013
5014
5015/* Function 68 */
5016DWORD
5017WINAPI
5020{
5021