ReactOS 0.4.16-dev-122-g325d74c
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 /* Fail, if we do not have any resource */
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 DPRINT("REG_RESOURCE_REQUIREMENTS_LIST->AlternativeLists %lu\n",
4264 ((PIO_RESOURCE_REQUIREMENTS_LIST)lpData)->AlternativeLists);
4265
4266 /* Fail, if we do not have any requirements */
4267 if (((PIO_RESOURCE_REQUIREMENTS_LIST)lpData)->AlternativeLists == 0)
4268 {
4270 goto done;
4271 }
4272 }
4273
4274done:
4275 if (lpData != NULL)
4276 HeapFree(GetProcessHeap(), 0, lpData);
4277
4278 if (hConfigKey != NULL)
4279 RegCloseKey(hConfigKey);
4280
4281 DPRINT("PNP_GetFirstLogConf() returns %lu\n", ret);
4282
4283 return ret;
4284}
4285
4286
4287/* Function 45 */
4288DWORD
4289WINAPI
4292 LPWSTR pDeviceID,
4293 DWORD ulLogConfType,
4294 DWORD ulCurrentTag,
4295 DWORD *pulNextTag,
4296 DWORD ulFlags)
4297{
4298 HKEY hConfigKey = NULL;
4299 DWORD RegDataType = 0;
4300 ULONG ulDataSize = 0;
4301 LPBYTE lpData = NULL;
4303
4304 DPRINT("PNP_GetNextLogConf(%p %S %lu %ul %p 0x%08lx)\n",
4305 hBinding, pDeviceID, ulLogConfType, ulCurrentTag, pulNextTag, ulFlags);
4306
4307 if (pulNextTag == NULL)
4308 return CR_INVALID_POINTER;
4309
4310 *pulNextTag = (DWORD)0;
4311
4312 if (ulFlags != 0)
4313 return CR_INVALID_FLAG;
4314
4315 if (!IsValidDeviceInstanceID(pDeviceID))
4316 return CR_INVALID_DEVINST;
4317
4318 ret = OpenConfigurationKey(pDeviceID,
4319 ulLogConfType,
4320 &hConfigKey);
4321 if (ret != CR_SUCCESS)
4322 {
4323 DPRINT1("OpenConfigurationKey() failed (Error %lu)\n", ret);
4325 goto done;
4326 }
4327
4328 ret = GetConfigurationData(hConfigKey,
4329 ulLogConfType,
4330 &RegDataType,
4331 &ulDataSize,
4332 &lpData);
4333 if (ret != CR_SUCCESS)
4334 {
4335 DPRINT1("GetConfigurationData() failed (Error %lu)\n", ret);
4337 goto done;
4338 }
4339
4340 DPRINT("Data size %lu\n", ulDataSize);
4341
4342 if (ulDataSize == 0 || lpData == NULL)
4343 {
4344 DPRINT1("No config data available!\n");
4346 goto done;
4347 }
4348
4349 /* Check if the next entry is available */
4350 if (RegDataType == REG_RESOURCE_LIST)
4351 {
4352 DPRINT("REG_RESOURCE_LIST->Count %lu\n", ((PCM_RESOURCE_LIST)lpData)->Count);
4353
4354 /* Fail, if we are beyond the end of the list */
4355 if (ulCurrentTag >= ((PCM_RESOURCE_LIST)lpData)->Count)
4356 {
4358 goto done;
4359 }
4360
4361 /* Indicate that we reached the end of the list */
4362 if (ulCurrentTag == ((PCM_RESOURCE_LIST)lpData)->Count - 1)
4363 {
4365 goto done;
4366 }
4367 }
4368 else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST)
4369 {
4370 DPRINT("REG_RESOURCE_REQUIREMENTS_LIST->AlternativeLists %lu\n",
4371 ((PIO_RESOURCE_REQUIREMENTS_LIST)lpData)->AlternativeLists);
4372
4373 /* Fail, if we are beyond the end of the list */
4374 if (ulCurrentTag >= ((PIO_RESOURCE_REQUIREMENTS_LIST)lpData)->AlternativeLists)
4375 {
4377 goto done;
4378 }
4379
4380 /* Indicate that we reached the end of the list */
4381 if (ulCurrentTag == ((PIO_RESOURCE_REQUIREMENTS_LIST)lpData)->AlternativeLists - 1)
4382 {
4384 goto done;
4385 }
4386 }
4387
4388 /* Return the next tag value */
4389 *pulNextTag = ulCurrentTag + 1;
4390
4391done:
4392 if (lpData != NULL)
4393 HeapFree(GetProcessHeap(), 0, lpData);
4394
4395 if (hConfigKey != NULL)
4396 RegCloseKey(hConfigKey);
4397
4398 DPRINT("PNP_GetNextLogConf() returns %lu\n", ret);
4399
4400 return ret;
4401}
4402
4403
4404/* Function 46 */
4405DWORD
4406WINAPI
4409 LPWSTR pDeviceID,
4410 DWORD ulType,
4411 DWORD ulTag,
4412 DWORD *pPriority,
4413 DWORD ulFlags)
4414{
4417}
4418
4419
4420/* Function 47 */
4421DWORD
4422WINAPI
4425 LPWSTR pDeviceID,
4426 DWORD ulLogConfTag,
4427 DWORD ulLogConfType,
4428 RESOURCEID ResourceID,
4429 DWORD *pulResourceTag,
4430 BYTE *ResourceData,
4431 PNP_RPC_BUFFER_SIZE ResourceLen,
4432 DWORD ulFlags)
4433{
4436}
4437
4438
4439/* Function 48 */
4440DWORD
4441WINAPI
4444 LPWSTR pDeviceID,
4445 DWORD ulLogConfTag,
4446 DWORD ulLogConfType,
4447 RESOURCEID ResourceID,
4448 DWORD ulResourceTag,
4449 DWORD *pulPreviousResType,
4450 DWORD *pulPreviousResTag,
4451 DWORD ulFlags)
4452{
4455}
4456
4457
4458/* Function 49 */
4459DWORD
4460WINAPI
4463 LPWSTR pDeviceID,
4464 DWORD ulLogConfTag,
4465 DWORD ulLogConfType,
4466 RESOURCEID ResourceID,
4467 DWORD ulResourceTag,
4468 DWORD *pulNextResType,
4469 DWORD *pulNextResTag,
4470 DWORD ulFlags)
4471{
4472 HKEY hConfigKey = NULL;
4473 DWORD RegDataType = 0;
4474 ULONG ulDataSize = 0;
4475 LPBYTE lpData = NULL;
4477
4478 DPRINT1("PNP_GetNextResDes(%p %S 0x%lx %lu %lu %ul %p %p 0x%08lx)\n",
4479 hBinding, pDeviceID, ulLogConfTag, ulLogConfType, ResourceID,
4480 ulResourceTag, pulNextResType, pulNextResTag, ulFlags);
4481
4482 if (pulNextResType == NULL)
4483 return CR_INVALID_POINTER;
4484
4485 *pulNextResType = 0;
4486
4487 if (ulFlags != 0)
4488 return CR_INVALID_FLAG;
4489
4490 if (!IsValidDeviceInstanceID(pDeviceID))
4491 return CR_INVALID_DEVINST;
4492
4493 ret = OpenConfigurationKey(pDeviceID,
4494 ulLogConfType,
4495 &hConfigKey);
4496 if (ret != CR_SUCCESS)
4497 {
4498 DPRINT1("OpenConfigurationKey() failed (Error %lu)\n", ret);
4500 goto done;
4501 }
4502
4503 ret = GetConfigurationData(hConfigKey,
4504 ulLogConfType,
4505 &RegDataType,
4506 &ulDataSize,
4507 &lpData);
4508 if (ret != CR_SUCCESS)
4509 {
4510 DPRINT1("GetConfigurationData() failed (Error %lu)\n", ret);
4512 goto done;
4513 }
4514
4515 DPRINT1("Data size %lu\n", ulDataSize);
4516
4517 if (ulDataSize == 0 || lpData == NULL)
4518 {
4519 DPRINT1("No config data available!\n");
4521 goto done;
4522 }
4523
4524 /* Get the next resource descriptor */
4525 if (RegDataType == REG_RESOURCE_LIST)
4526 {
4527 DPRINT1("FIXME: REG_RESOURCE_LIST\n");
4528 /* FIXME */
4530 goto done;
4531 }
4532 else if (RegDataType == REG_RESOURCE_REQUIREMENTS_LIST)
4533 {
4534 DPRINT1("FIXME: REG_RESOURCE_REQUIREMENTS_LIST\n");
4535 /* FIXME */
4537 goto done;
4538 }
4539
4540done:
4541 if (lpData != NULL)
4542 HeapFree(GetProcessHeap(), 0, lpData);
4543
4544 if (hConfigKey != NULL)
4545 RegCloseKey(hConfigKey);
4546
4547 DPRINT1("PNP_GetNextResDes() returns %lu\n", ret);
4548
4549 return ret;
4550}
4551
4552
4553/* Function 50 */
4554DWORD
4555WINAPI
4558 LPWSTR pDeviceID,
4559 DWORD ulLogConfTag,
4560 DWORD ulLogConfType,
4561 RESOURCEID ResourceID,
4562 DWORD ulResourceTag,
4563 BYTE *Buffer,
4564 PNP_RPC_BUFFER_SIZE BufferLen,
4565 DWORD ulFlags)
4566{
4569}
4570
4571
4572/* Function 51 */
4573DWORD
4574WINAPI
4577 LPWSTR pDeviceID,
4578 DWORD ulLogConfTag,
4579 DWORD ulLogConfType,
4580 RESOURCEID ResourceID,
4581 DWORD ulResourceTag,
4582 DWORD *pulSize,
4583 DWORD ulFlags)
4584{
4587}
4588
4589
4590/* Function 52 */
4591DWORD
4592WINAPI
4595 LPWSTR pDeviceID,
4596 DWORD ulLogConfTag,
4597 DWORD ulLogConfType,
4598 RESOURCEID CurrentResourceID,
4599 RESOURCEID NewResourceID,
4600 DWORD ulResourceTag,
4601 BYTE *ResourceData,
4602 PNP_RPC_BUFFER_SIZE ResourceLen,
4603 DWORD ulFlags)
4604{
4607}
4608
4609
4610/* Function 53 */
4611DWORD
4612WINAPI
4615 LPWSTR pDeviceID,
4616 RESOURCEID ResourceID,
4617 BYTE *ResourceData,
4618 PNP_RPC_BUFFER_SIZE ResourceLen,
4619 BOOL *pbConflictDetected,
4620 DWORD ulFlags)
4621{
4622 DPRINT("PNP_DetectResourceConflict()\n");
4623
4624 if (pbConflictDetected != NULL)
4625 *pbConflictDetected = FALSE;
4626
4628}
4629
4630
4631/* Function 54 */
4632DWORD
4633WINAPI
4636 LPWSTR pDeviceID,
4637 RESOURCEID ResourceID,
4638 BYTE *ResourceData,
4639 PNP_RPC_BUFFER_SIZE ResourceLen,
4640 BYTE *Buffer,
4641 PNP_RPC_BUFFER_SIZE BufferLen,
4642 DWORD ulFlags)
4643{
4646}
4647
4648
4649/* Function 55 */
4650DWORD
4651WINAPI
4654 DWORD ulHardwareProfile,
4655 DWORD ulFlags)
4656{
4658}
4659
4660
4661/* Function 56 */
4662DWORD
4663WINAPI
4666 BYTE *pData,
4667 DWORD DataLen,
4668 LPWSTR pDeviceID,
4669 RESOURCEID ResourceID,
4670 DWORD ulFlags)
4671{
4673}
4674
4675
4676/* Function 57 */
4677DWORD
4678WINAPI
4681 DWORD *pulSize,
4682 LPWSTR pDeviceID,
4683 RESOURCEID ResourceID,
4684 DWORD ulFlags)
4685{
4686 if (pulSize != NULL)
4687 *pulSize = 0;
4688
4690}
4691
4692
4693/* Function 58 */
4695WINAPI
4698 DWORD ulFlags)
4699{
4701}
4702
4703
4704/* Function 59 */
4705DWORD
4706WINAPI
4709 DWORD_PTR hRecipient,
4710 LPWSTR pszName,
4711 BYTE *pNotificationFilter,
4712 DWORD ulNotificationFilterSize,
4713 DWORD ulFlags,
4714 PNP_NOTIFY_HANDLE *pNotifyHandle,
4715 DWORD ulProcessId,
4716 DWORD *pulUnknown9)
4717{
4718 PDEV_BROADCAST_DEVICEINTERFACE_W pBroadcastDeviceInterface;
4719 PDEV_BROADCAST_HANDLE pBroadcastDeviceHandle;
4720 PNOTIFY_ENTRY pNotifyData = NULL;
4721
4722 DPRINT1("PNP_RegisterNotification(%p %p '%S' %p %lu 0x%lx %p %lx %p)\n",
4723 hBinding, hRecipient, pszName, pNotificationFilter,
4724 ulNotificationFilterSize, ulFlags, pNotifyHandle, ulProcessId, pulUnknown9);
4725
4726 if (pNotifyHandle == NULL)
4727 return CR_INVALID_POINTER;
4728
4729 *pNotifyHandle = NULL;
4730
4731 if (pNotificationFilter == NULL ||
4732 pulUnknown9 == NULL)
4733 return CR_INVALID_POINTER;
4734
4735 if (ulFlags & ~0x7)
4736 return CR_INVALID_FLAG;
4737
4738 if ((ulNotificationFilterSize < sizeof(DEV_BROADCAST_HDR)) ||
4739 (((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_size < sizeof(DEV_BROADCAST_HDR)))
4740 return CR_INVALID_DATA;
4741
4742 if (((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
4743 {
4744 DPRINT1("DBT_DEVTYP_DEVICEINTERFACE\n");
4745 pBroadcastDeviceInterface = (PDEV_BROADCAST_DEVICEINTERFACE_W)pNotificationFilter;
4746
4747 if ((ulNotificationFilterSize < sizeof(DEV_BROADCAST_DEVICEINTERFACE_W)) ||
4748 (pBroadcastDeviceInterface->dbcc_size < sizeof(DEV_BROADCAST_DEVICEINTERFACE_W)))
4749 return CR_INVALID_DATA;
4750
4752 if (pNotifyData == NULL)
4753 return CR_OUT_OF_MEMORY;
4754
4755 if (pszName != NULL)
4756 {
4757 pNotifyData->pszName = RtlAllocateHeap(GetProcessHeap(),
4759 (wcslen(pszName) + 1) * sizeof(WCHAR));
4760 if (pNotifyData->pszName == NULL)
4761 {
4762 RtlFreeHeap(GetProcessHeap(), 0, pNotifyData);
4763 return CR_OUT_OF_MEMORY;
4764 }
4765 }
4766
4767 /* Add the entry to the notification list */
4769
4770 DPRINT("pNotifyData: %p\n", pNotifyData);
4771 *pNotifyHandle = (PNP_NOTIFY_HANDLE)pNotifyData;
4772 }
4773 else if (((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_devicetype == DBT_DEVTYP_HANDLE)
4774 {
4775 DPRINT1("DBT_DEVTYP_HANDLE\n");
4776 pBroadcastDeviceHandle = (PDEV_BROADCAST_HANDLE)pNotificationFilter;
4777
4778 if ((ulNotificationFilterSize < sizeof(DEV_BROADCAST_HANDLE)) ||
4779 (pBroadcastDeviceHandle->dbch_size < sizeof(DEV_BROADCAST_HANDLE)))
4780 return CR_INVALID_DATA;
4781
4782 if (ulFlags & DEVICE_NOTIFY_ALL_INTERFACE_CLASSES)
4783 return CR_INVALID_FLAG;
4784 }
4785 else
4786 {
4787 DPRINT1("Invalid device type %lu\n", ((PDEV_BROADCAST_HDR)pNotificationFilter)->dbch_devicetype);
4788 return CR_INVALID_DATA;
4789 }
4790
4791 return CR_SUCCESS;
4792}
4793
4794
4795/* Function 60 */
4796DWORD
4797WINAPI
4800 PNP_NOTIFY_HANDLE *pNotifyHandle)
4801{
4803
4804 DPRINT1("PNP_UnregisterNotification(%p %p)\n",
4805 hBinding, pNotifyHandle);
4806
4807 pEntry = (PNOTIFY_ENTRY)*pNotifyHandle;
4808 if (pEntry == NULL)
4809 return CR_INVALID_DATA;
4810
4811 RemoveEntryList(&pEntry->ListEntry);
4812 if (pEntry->pszName)
4813 RtlFreeHeap(RtlGetProcessHeap(), 0, pEntry->pszName);
4814 RtlFreeHeap(RtlGetProcessHeap(), 0, pEntry);
4815 *pNotifyHandle = NULL;
4816
4817 return CR_SUCCESS;
4818}
4819
4820
4821/* Function 61 */
4822DWORD
4823WINAPI
4826 LPWSTR pDeviceID,
4827 LPWSTR CustomPropName,
4828 DWORD *pulRegDataType,
4829 BYTE *Buffer,
4830 PNP_RPC_STRING_LEN *pulTransferLen,
4831 PNP_RPC_STRING_LEN *pulLength,
4832 DWORD ulFlags)
4833{
4834 HKEY hDeviceKey = NULL;
4835 HKEY hParamKey = NULL;
4836 LONG lError;
4838
4840
4841 DPRINT("PNP_GetCustomDevProp() called\n");
4842
4843 if (pulTransferLen == NULL || pulLength == NULL)
4844 {
4846 goto done;
4847 }
4848
4849 if (ulFlags & ~CM_CUSTOMDEVPROP_BITS)
4850 {
4852 goto done;
4853 }
4854
4855 if (!IsValidDeviceInstanceID(pDeviceID))
4856 return CR_INVALID_DEVINST;
4857
4858 if (*pulLength < *pulTransferLen)
4859 *pulLength = *pulTransferLen;
4860
4861 *pulTransferLen = 0;
4862
4863 lError = RegOpenKeyExW(hEnumKey,
4864 pDeviceID,
4865 0,
4866 KEY_READ,
4867 &hDeviceKey);
4868 if (lError != ERROR_SUCCESS)
4869 {
4871 goto done;
4872 }
4873
4874 lError = RegOpenKeyExW(hDeviceKey,
4875 L"Device Parameters",
4876 0,
4877 KEY_READ,
4878 &hParamKey);
4879 if (lError != ERROR_SUCCESS)
4880 {
4882 goto done;
4883 }
4884
4885 lError = RegQueryValueExW(hParamKey,
4886 CustomPropName,
4887 NULL,
4888 pulRegDataType,
4889 Buffer,
4890 pulLength);
4891 if (lError != ERROR_SUCCESS)
4892 {
4893 if (lError == ERROR_MORE_DATA)
4894 {
4896 }
4897 else
4898 {
4899 *pulLength = 0;
4901 }
4902 }
4903
4904done:
4905 if (ret == CR_SUCCESS)
4906 *pulTransferLen = *pulLength;
4907
4908 if (hParamKey != NULL)
4909 RegCloseKey(hParamKey);
4910
4911 if (hDeviceKey != NULL)
4912 RegCloseKey(hDeviceKey);
4913
4914 DPRINT("PNP_GetCustomDevProp() done (returns %lx)\n", ret);
4915
4916 return ret;
4917}
4918
4919
4920/* Function 62 */
4921DWORD
4922WINAPI
4925 WORD *pwVersion)
4926{
4928
4929 *pwVersion = WINVER;
4930 return CR_SUCCESS;
4931}
4932
4933
4934/* Function 63 */
4935DWORD
4936WINAPI
4939 BYTE *Buffer,
4940 PNP_RPC_BUFFER_SIZE *pulTransferLen,
4941 PNP_RPC_BUFFER_SIZE *pulLength,
4942 DWORD ulFlags)
4943{
4946}
4947
4948
4949/* Function 64 */
4950DWORD
4951WINAPI
4954 DWORD *pulSSDIFlags,
4955 DWORD ulFlags)
4956{
4958
4959 DPRINT1("PNP_GetServerSideDeviceInstallFlags(%p %p %lu)\n",
4960 hBinding, pulSSDIFlags, ulFlags);
4961
4962 if (pulSSDIFlags == NULL)
4963 return CR_INVALID_POINTER;
4964
4965 if (ulFlags != 0)
4966 return CR_INVALID_FLAG;
4967
4968 /* FIXME */
4969 *pulSSDIFlags = 0;
4970
4971 return CR_SUCCESS;
4972}
4973
4974
4975/* Function 65 */
4976DWORD
4977WINAPI
4982 LPWSTR PropertyCultureName,
4983 PNP_PROP_COUNT *PropertyCount,
4984 PNP_PROP_COUNT *TransferLen,
4985 DEVPROPKEY *PropertyKeys,
4986 DWORD Flags)
4987{
4990}
4991
4992
4993/* Function 66 */
4994DWORD
4995WINAPI
5000 LPWSTR PropertyCultureName,
5001 const DEVPROPKEY *PropertyKey,
5003 PNP_PROP_SIZE *PropertySize,
5004 PNP_PROP_SIZE *TransferLen,
5006 DWORD Flags)
5007{
5010}
5011
5012
5013/* Function 67 */
5014DWORD
5015WINAPI
5020 LPWSTR PropertyCultureName,
5021 const DEVPROPKEY *PropertyKey,
5023 PNP_PROP_SIZE Propert