ReactOS 0.4.16-dev-983-g23ad936
deviface.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for deviface.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define GUID_STRING_CHARS   38
 
#define GUID_STRING_BYTES   (GUID_STRING_CHARS * sizeof(WCHAR))
 

Functions

 C_ASSERT (sizeof(L"{01234567-89ab-cdef-0123-456789abcdef}")==GUID_STRING_BYTES+sizeof(UNICODE_NULL))
 
PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance (PUNICODE_STRING DeviceInstance)
 
static NTSTATUS IopBuildSymbolicLink (_In_ PCUNICODE_STRING DeviceString, _In_ PCUNICODE_STRING GuidString, _In_opt_ PCUNICODE_STRING ReferenceString, _In_ BOOLEAN UserModePrefixFormat, _Out_ PUNICODE_STRING SymbolicLinkName)
 Creates a new symbolic link from the specified format of the prefix, device string, class GUID and reference string (if any).
 
static NTSTATUS IopSeparateSymbolicLink (_In_ PCUNICODE_STRING SymbolicLinkName, _Out_opt_ PUNICODE_STRING PrefixString, _Out_opt_ PUNICODE_STRING MungedString, _Out_opt_ PUNICODE_STRING GuidString, _Out_opt_ PUNICODE_STRING ReferenceString, _Out_opt_ PBOOLEAN ReferenceStringPresent, _Out_opt_ LPGUID InterfaceClassGuid)
 Parses the specified symbolic link onto the 4 parts: prefix, device string, class GUID and reference string.
 
static NTSTATUS IopOpenOrCreateSymbolicLinkSubKeys (_Out_opt_ PHANDLE DeviceHandle, _Out_opt_ PULONG DeviceDisposition, _Out_opt_ PHANDLE InstanceHandle, _Out_opt_ PULONG InstanceDisposition, _In_ HANDLE ClassHandle, _In_ PCUNICODE_STRING SymbolicLinkName, _In_ ACCESS_MASK DesiredAccess, _In_ BOOLEAN Create)
 Retrieves a handles to the device and instance registry keys for the previously opened registry key handle of the specified symbolic link.
 
static NTSTATUS OpenRegistryHandlesFromSymbolicLink (_In_ PCUNICODE_STRING SymbolicLinkName, _In_ ACCESS_MASK DesiredAccess, _Out_opt_ PHANDLE GuidKey, _Out_opt_ PHANDLE DeviceKey, _Out_opt_ PHANDLE InstanceKey)
 Retrieves a handles to the GUID, device and instance registry keys for the specified symbolic link.
 
NTSTATUS NTAPI IoOpenDeviceInterfaceRegistryKey (IN PUNICODE_STRING SymbolicLinkName, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DeviceInterfaceKey)
 
static NTSTATUS IopOpenInterfaceKey (IN CONST GUID *InterfaceClassGuid, IN ACCESS_MASK DesiredAccess, OUT HANDLE *pInterfaceKey)
 
NTSTATUS NTAPI IoGetDeviceInterfaceAlias (_In_ PUNICODE_STRING SymbolicLinkName, _In_ CONST GUID *AliasInterfaceClassGuid, _Out_ PUNICODE_STRING AliasSymbolicLinkName)
 Returns the alias device interface of the specified device interface instance, if the alias exists.
 
NTSTATUS NTAPI IoGetDeviceInterfaces (IN CONST GUID *InterfaceClassGuid, IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, IN ULONG Flags, OUT PWSTR *SymbolicLinkList)
 
NTSTATUS NTAPI IoRegisterDeviceInterface (IN PDEVICE_OBJECT PhysicalDeviceObject, IN CONST GUID *InterfaceClassGuid, IN PUNICODE_STRING ReferenceString OPTIONAL, OUT PUNICODE_STRING SymbolicLinkName)
 
NTSTATUS NTAPI IoSetDeviceInterfaceState (IN PUNICODE_STRING SymbolicLinkName, IN BOOLEAN Enable)
 

Variables

static PCWSTR BaseKeyString = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses\\"
 

Macro Definition Documentation

◆ GUID_STRING_BYTES

#define GUID_STRING_BYTES   (GUID_STRING_CHARS * sizeof(WCHAR))

Definition at line 22 of file deviface.c.

◆ GUID_STRING_CHARS

#define GUID_STRING_CHARS   38

Definition at line 21 of file deviface.c.

◆ NDEBUG

#define NDEBUG

Definition at line 17 of file deviface.c.

Function Documentation

◆ C_ASSERT()

C_ASSERT ( sizeof(L"{01234567-89ab-cdef-0123-456789abcdef}")  = =GUID_STRING_BYTES+sizeof(UNICODE_NULL))

◆ IoGetDeviceInterfaceAlias()

NTSTATUS NTAPI IoGetDeviceInterfaceAlias ( _In_ PUNICODE_STRING  SymbolicLinkName,
_In_ CONST GUID AliasInterfaceClassGuid,
_Out_ PUNICODE_STRING  AliasSymbolicLinkName 
)

Returns the alias device interface of the specified device interface instance, if the alias exists.

Parameters
[in]SymbolicLinkNamePointer to a symbolic link string which identifies the device interface instance.
[in]AliasInterfaceClassGuidPointer to a device interface class GUID.
[out]AliasSymbolicLinkNamePointer to unicode string which receives the alias symbolic link upon success. Must be freed with RtlFreeUnicodeString after using.
Returns
NTSTATUS values in case of errors, STATUS_SUCCESS otherwise.
Remarks
Must be called at IRQL = PASSIVE_LEVEL in the context of a system thread

Definition at line 758 of file deviface.c.

762{
763 static const UNICODE_STRING UserModePrefix = RTL_CONSTANT_STRING(L"\\\\?\\");
764 UNICODE_STRING AliasSymbolicLink = {0};
765 UNICODE_STRING AliasGuidString = {0};
766 UNICODE_STRING DeviceString = {0};
769 HANDLE DeviceKey, AliasInstanceKey;
770 BOOLEAN UserModePrefixFormat;
771 BOOLEAN ReferenceStringPresent = FALSE; /* Assuming no ref string by default */
774
775 DPRINT("IoGetDeviceInterfaceAlias(%wZ, 0x%p)\n", SymbolicLinkName, AliasInterfaceClassGuid);
776
777 /* Sanity check */
779 {
780 DPRINT1("IoGetDeviceInterfaceAlias() invalid symbolic link or alias class GUID\n");
782 }
783
784 /* Convert alias GUID to a string */
786 if (!NT_SUCCESS(Status))
787 {
788 DPRINT1("RtlStringFromGUID() failed, Status 0x%08lx\n", Status);
789 goto Quit;
790 }
791
792 DPRINT("Alias GUID is %wZ\n", &AliasGuidString);
793
794 /* Get the device instance string of existing symbolic link */
797 NULL,
798 &DeviceKey,
799 NULL);
800 if (!NT_SUCCESS(Status))
801 {
802 DPRINT1("Failed to open device instance key for %wZ, Status 0x%08lx\n", SymbolicLinkName, Status);
803 goto Quit;
804 }
805
806 Status = IopGetRegistryValue(DeviceKey, L"DeviceInstance", &kvInfo);
807 ZwClose(DeviceKey);
808 if (!NT_SUCCESS(Status))
809 {
810 DPRINT1("Failed get device instance value, Status 0x%08lx\n", Status);
811 goto Quit;
812 }
813
814 if (kvInfo->Type != REG_SZ || kvInfo->DataLength == 0 || kvInfo->DataLength > MAXUSHORT)
815 {
816 DPRINT1("Wrong or empty instance value\n");
818 goto Quit;
819 }
820
821 /* Convert received data to unicode string */
822 Buffer = (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset);
823 PnpRegSzToString(Buffer, kvInfo->DataLength, &DeviceString.Length);
824 DeviceString.MaximumLength = DeviceString.Length;
825 DeviceString.Buffer = Buffer;
826
827 /*
828 * Separate symbolic link into 4 parts:
829 * 1) prefix string (\??\ for kernel mode or \\?\ for user mode),
830 * 2) munged path string (like ##?#ACPI#PNP0501#1#{GUID}),
831 * 3) GUID string (the current GUID),
832 * 4) reference string (goes after GUID, starts with '\').
833 *
834 * We need only reference string.
835 */
837 NULL,
838 NULL,
839 NULL,
841 &ReferenceStringPresent,
842 NULL);
843 if (!NT_SUCCESS(Status))
844 {
845 DPRINT1("Failed to separate symbolic link %wZ, Status 0x%08lx\n", SymbolicLinkName, Status);
846 goto Quit;
847 }
848
849 DPRINT("Device string is '%wZ'\n", &DeviceString);
850
851 /* Does symbolic link have kernel mode "\??\" or user mode "\\?\" prefix format? */
852 UserModePrefixFormat = RtlPrefixUnicodeString(&UserModePrefix, SymbolicLinkName, FALSE);
853
854 /* Build up new symbolic link with alias GUID */
855 Status = IopBuildSymbolicLink(&DeviceString,
856 &AliasGuidString,
857 ReferenceStringPresent ? &ReferenceString : NULL,
858 UserModePrefixFormat,
859 &AliasSymbolicLink);
860 if (!NT_SUCCESS(Status))
861 {
862 DPRINT1("Failed to build alias symbolic link, Status 0x%08lx\n", Status);
863 goto Quit;
864 }
865
866 /* Make sure that alias symbolic link key exists in registry */
867 Status = OpenRegistryHandlesFromSymbolicLink(&AliasSymbolicLink,
868 KEY_READ,
869 NULL,
870 NULL,
871 &AliasInstanceKey);
872 if (!NT_SUCCESS(Status))
873 {
874 DPRINT1("Failed to open alias symbolic link key, Status 0x%08lx\n", Status);
875 goto Quit;
876 }
877 ZwClose(AliasInstanceKey);
878
879 /* We're done */
880 DPRINT("IoGetDeviceInterfaceAlias(): alias symbolic link %wZ\n", &AliasSymbolicLink);
881 *AliasSymbolicLinkName = AliasSymbolicLink;
883
884Quit:
885 if (!NT_SUCCESS(Status))
886 {
887 if (AliasSymbolicLink.Buffer)
888 RtlFreeUnicodeString(&AliasSymbolicLink);
889 }
890
891 if (AliasGuidString.Buffer)
892 RtlFreeUnicodeString(&AliasGuidString);
893
894 return Status;
895}
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
Status
Definition: gdiplustypes.h:25
NTSYSAPI NTSTATUS WINAPI RtlStringFromGUID(REFGUID, PUNICODE_STRING)
#define REG_SZ
Definition: layer.c:22
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define KEY_READ
Definition: nt_native.h:1023
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
NTSYSAPI BOOLEAN NTAPI RtlPrefixUnicodeString(IN PUNICODE_STRING String1, IN PUNICODE_STRING String2, IN BOOLEAN CaseInSensitive)
BOOLEAN NTAPI PnpRegSzToString(IN PWCHAR RegSzData, IN ULONG RegSzLength, OUT PUSHORT StringLength OPTIONAL)
Definition: pnputil.c:171
NTSTATUS NTAPI IopGetRegistryValue(IN HANDLE Handle, IN PWSTR ValueName, OUT PKEY_VALUE_FULL_INFORMATION *Information)
Definition: pnpmgr.c:1036
static NTSTATUS IopSeparateSymbolicLink(_In_ PCUNICODE_STRING SymbolicLinkName, _Out_opt_ PUNICODE_STRING PrefixString, _Out_opt_ PUNICODE_STRING MungedString, _Out_opt_ PUNICODE_STRING GuidString, _Out_opt_ PUNICODE_STRING ReferenceString, _Out_opt_ PBOOLEAN ReferenceStringPresent, _Out_opt_ LPGUID InterfaceClassGuid)
Parses the specified symbolic link onto the 4 parts: prefix, device string, class GUID and reference ...
Definition: deviface.c:161
static NTSTATUS IopBuildSymbolicLink(_In_ PCUNICODE_STRING DeviceString, _In_ PCUNICODE_STRING GuidString, _In_opt_ PCUNICODE_STRING ReferenceString, _In_ BOOLEAN UserModePrefixFormat, _Out_ PUNICODE_STRING SymbolicLinkName)
Creates a new symbolic link from the specified format of the prefix, device string,...
Definition: deviface.c:61
static NTSTATUS OpenRegistryHandlesFromSymbolicLink(_In_ PCUNICODE_STRING SymbolicLinkName, _In_ ACCESS_MASK DesiredAccess, _Out_opt_ PHANDLE GuidKey, _Out_opt_ PHANDLE DeviceKey, _Out_opt_ PHANDLE InstanceKey)
Retrieves a handles to the GUID, device and instance registry keys for the specified symbolic link.
Definition: deviface.c:462
#define L(x)
Definition: ntvdm.h:50
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
void * PVOID
Definition: typedefs.h:50
#define MAXUSHORT
Definition: typedefs.h:83
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
_Must_inspect_result_ _In_ WDFDEVICE _In_ CONST GUID _In_opt_ PCUNICODE_STRING ReferenceString
Definition: wdfdevice.h:3630
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING SymbolicLinkName
Definition: wdfdevice.h:3739
_In_ CONST GUID * AliasInterfaceClassGuid
Definition: iofuncs.h:962

Referenced by Test_IoGetDeviceInterfaceAlias().

◆ IoGetDeviceInterfaces()

NTSTATUS NTAPI IoGetDeviceInterfaces ( IN CONST GUID InterfaceClassGuid,
IN PDEVICE_OBJECT PhysicalDeviceObject  OPTIONAL,
IN ULONG  Flags,
OUT PWSTR SymbolicLinkList 
)

Definition at line 936 of file deviface.c.

940{
943 HANDLE InterfaceKey = NULL;
944 HANDLE DeviceKey = NULL;
945 HANDLE ReferenceKey = NULL;
946 HANDLE ControlKey = NULL;
947 PKEY_BASIC_INFORMATION DeviceBi = NULL;
948 PKEY_BASIC_INFORMATION ReferenceBi = NULL;
951 PEXTENDED_DEVOBJ_EXTENSION DeviceObjectExtension;
952 PUNICODE_STRING InstanceDevicePath = NULL;
955 BOOLEAN FoundRightPDO = FALSE;
956 ULONG i = 0, j, Size, NeededLength, ActualLength, LinkedValue;
957 UNICODE_STRING ReturnBuffer = { 0, 0, NULL };
959
960 PAGED_CODE();
961
963 {
964 /* Parameters must pass three border of checks */
965 DeviceObjectExtension = (PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension;
966
967 /* 1st level: Presence of a Device Node */
968 if (DeviceObjectExtension->DeviceNode == NULL)
969 {
970 DPRINT("PhysicalDeviceObject 0x%p doesn't have a DeviceNode\n", PhysicalDeviceObject);
972 }
973
974 /* 2nd level: Presence of an non-zero length InstancePath */
975 if (DeviceObjectExtension->DeviceNode->InstancePath.Length == 0)
976 {
977 DPRINT("PhysicalDeviceObject 0x%p's DOE has zero-length InstancePath\n", PhysicalDeviceObject);
979 }
980
981 InstanceDevicePath = &DeviceObjectExtension->DeviceNode->InstancePath;
982 }
983
984
986 if (!NT_SUCCESS(Status))
987 {
988 DPRINT("IopOpenInterfaceKey() failed with status 0x%08lx\n", Status);
989 goto cleanup;
990 }
991
992 /* Enumerate subkeys (i.e. the different device objects) */
993 while (TRUE)
994 {
995 Status = ZwEnumerateKey(
996 InterfaceKey,
997 i,
999 NULL,
1000 0,
1001 &Size);
1003 {
1004 break;
1005 }
1007 {
1008 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
1009 goto cleanup;
1010 }
1011
1012 DeviceBi = ExAllocatePool(PagedPool, Size);
1013 if (!DeviceBi)
1014 {
1015 DPRINT("ExAllocatePool() failed\n");
1017 goto cleanup;
1018 }
1019 Status = ZwEnumerateKey(
1020 InterfaceKey,
1021 i++,
1023 DeviceBi,
1024 Size,
1025 &Size);
1026 if (!NT_SUCCESS(Status))
1027 {
1028 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
1029 goto cleanup;
1030 }
1031
1032 /* Open device key */
1033 KeyName.Length = KeyName.MaximumLength = (USHORT)DeviceBi->NameLength;
1034 KeyName.Buffer = DeviceBi->Name;
1037 &KeyName,
1039 InterfaceKey,
1040 NULL);
1041 Status = ZwOpenKey(
1042 &DeviceKey,
1045 if (!NT_SUCCESS(Status))
1046 {
1047 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
1048 goto cleanup;
1049 }
1050
1052 {
1053 /* Check if we are on the right physical device object,
1054 * by reading the DeviceInstance string
1055 */
1056 RtlInitUnicodeString(&KeyName, L"DeviceInstance");
1057 Status = ZwQueryValueKey(DeviceKey, &KeyName, KeyValuePartialInformation, NULL, 0, &NeededLength);
1059 {
1060 ActualLength = NeededLength;
1061 PartialInfo = ExAllocatePool(NonPagedPool, ActualLength);
1062 if (!PartialInfo)
1063 {
1065 goto cleanup;
1066 }
1067
1068 Status = ZwQueryValueKey(DeviceKey, &KeyName, KeyValuePartialInformation, PartialInfo, ActualLength, &NeededLength);
1069 if (!NT_SUCCESS(Status))
1070 {
1071 DPRINT1("ZwQueryValueKey #2 failed (%x)\n", Status);
1072 ExFreePool(PartialInfo);
1073 goto cleanup;
1074 }
1075 if (PartialInfo->DataLength == InstanceDevicePath->Length)
1076 {
1077 if (RtlCompareMemory(PartialInfo->Data, InstanceDevicePath->Buffer, InstanceDevicePath->Length) == InstanceDevicePath->Length)
1078 {
1079 /* found right pdo */
1080 FoundRightPDO = TRUE;
1081 }
1082 }
1083 ExFreePool(PartialInfo);
1084 PartialInfo = NULL;
1085 if (!FoundRightPDO)
1086 {
1087 /* not yet found */
1088 continue;
1089 }
1090 }
1091 else
1092 {
1093 /* error */
1094 break;
1095 }
1096 }
1097
1098 /* Enumerate subkeys (ie the different reference strings) */
1099 j = 0;
1100 while (TRUE)
1101 {
1102 Status = ZwEnumerateKey(
1103 DeviceKey,
1104 j,
1106 NULL,
1107 0,
1108 &Size);
1110 {
1111 break;
1112 }
1114 {
1115 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
1116 goto cleanup;
1117 }
1118
1119 ReferenceBi = ExAllocatePool(PagedPool, Size);
1120 if (!ReferenceBi)
1121 {
1122 DPRINT("ExAllocatePool() failed\n");
1124 goto cleanup;
1125 }
1126 Status = ZwEnumerateKey(
1127 DeviceKey,
1128 j++,
1130 ReferenceBi,
1131 Size,
1132 &Size);
1133 if (!NT_SUCCESS(Status))
1134 {
1135 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status);
1136 goto cleanup;
1137 }
1138
1139 KeyName.Length = KeyName.MaximumLength = (USHORT)ReferenceBi->NameLength;
1140 KeyName.Buffer = ReferenceBi->Name;
1142 {
1143 /* Skip Control subkey */
1144 goto NextReferenceString;
1145 }
1146
1147 /* Open reference key */
1150 &KeyName,
1152 DeviceKey,
1153 NULL);
1154 Status = ZwOpenKey(
1155 &ReferenceKey,
1158 if (!NT_SUCCESS(Status))
1159 {
1160 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
1161 goto cleanup;
1162 }
1163
1165 {
1166 /* We have to check if the interface is enabled, by
1167 * reading the Linked value in the Control subkey
1168 */
1171 &Control,
1173 ReferenceKey,
1174 NULL);
1175 Status = ZwOpenKey(
1176 &ControlKey,
1180 {
1181 /* That's OK. The key doesn't exist (yet) because
1182 * the interface is not activated.
1183 */
1184 goto NextReferenceString;
1185 }
1186 else if (!NT_SUCCESS(Status))
1187 {
1188 DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status);
1189 goto cleanup;
1190 }
1191
1192 RtlInitUnicodeString(&KeyName, L"Linked");
1193 Status = ZwQueryValueKey(ControlKey,
1194 &KeyName,
1196 NULL,
1197 0,
1198 &NeededLength);
1200 {
1201 ActualLength = NeededLength;
1202 PartialInfo = ExAllocatePool(NonPagedPool, ActualLength);
1203 if (!PartialInfo)
1204 {
1206 goto cleanup;
1207 }
1208
1209 Status = ZwQueryValueKey(ControlKey,
1210 &KeyName,
1212 PartialInfo,
1213 ActualLength,
1214 &NeededLength);
1215 if (!NT_SUCCESS(Status))
1216 {
1217 DPRINT1("ZwQueryValueKey #2 failed (%x)\n", Status);
1218 ExFreePool(PartialInfo);
1219 goto cleanup;
1220 }
1221
1222 if (PartialInfo->Type != REG_DWORD || PartialInfo->DataLength != sizeof(ULONG))
1223 {
1224 DPRINT1("Bad registry read\n");
1225 ExFreePool(PartialInfo);
1226 goto cleanup;
1227 }
1228
1229 RtlCopyMemory(&LinkedValue,
1230 PartialInfo->Data,
1231 PartialInfo->DataLength);
1232
1233 ExFreePool(PartialInfo);
1234 if (LinkedValue == 0)
1235 {
1236 /* This interface isn't active */
1237 goto NextReferenceString;
1238 }
1239 }
1240 else
1241 {
1242 DPRINT1("ZwQueryValueKey #1 failed (%x)\n", Status);
1243 goto cleanup;
1244 }
1245 }
1246
1247 /* Read the SymbolicLink string and add it into SymbolicLinkList */
1248 Status = ZwQueryValueKey(
1249 ReferenceKey,
1250 &SymbolicLink,
1252 NULL,
1253 0,
1254 &Size);
1256 {
1257 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
1258 goto cleanup;
1259 }
1261 if (!bip)
1262 {
1263 DPRINT("ExAllocatePool() failed\n");
1265 goto cleanup;
1266 }
1267 Status = ZwQueryValueKey(
1268 ReferenceKey,
1269 &SymbolicLink,
1271 bip,
1272 Size,
1273 &Size);
1274 if (!NT_SUCCESS(Status))
1275 {
1276 DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status);
1277 goto cleanup;
1278 }
1279 else if (bip->Type != REG_SZ)
1280 {
1281 DPRINT("Unexpected registry type 0x%lx (expected 0x%lx)\n", bip->Type, REG_SZ);
1283 goto cleanup;
1284 }
1285 else if (bip->DataLength < 5 * sizeof(WCHAR))
1286 {
1287 DPRINT("Registry string too short (length %lu, expected %lu at least)\n", bip->DataLength, 5 * sizeof(WCHAR));
1289 goto cleanup;
1290 }
1291 KeyName.Length = KeyName.MaximumLength = (USHORT)bip->DataLength;
1292 KeyName.Buffer = (PWSTR)bip->Data;
1293
1294 /* Fixup the prefix (from "\\?\") */
1295 RtlCopyMemory(KeyName.Buffer, L"\\??\\", 4 * sizeof(WCHAR));
1296
1297 /* Add new symbolic link to symbolic link list */
1298 if (ReturnBuffer.Length + KeyName.Length + sizeof(WCHAR) > ReturnBuffer.MaximumLength)
1299 {
1300 PWSTR NewBuffer;
1301 ReturnBuffer.MaximumLength = (USHORT)max(2 * ReturnBuffer.MaximumLength,
1302 (USHORT)(ReturnBuffer.Length +
1303 KeyName.Length +
1304 2 * sizeof(WCHAR)));
1305 NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength);
1306 if (!NewBuffer)
1307 {
1308 DPRINT("ExAllocatePool() failed\n");
1310 goto cleanup;
1311 }
1312 if (ReturnBuffer.Buffer)
1313 {
1314 RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length);
1315 ExFreePool(ReturnBuffer.Buffer);
1316 }
1317 ReturnBuffer.Buffer = NewBuffer;
1318 }
1319 DPRINT("Adding symbolic link %wZ\n", &KeyName);
1321 if (!NT_SUCCESS(Status))
1322 {
1323 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
1324 goto cleanup;
1325 }
1326 /* RtlAppendUnicodeStringToString added a NULL at the end of the
1327 * destination string, but didn't increase the Length field.
1328 * Do it for it.
1329 */
1330 ReturnBuffer.Length += sizeof(WCHAR);
1331
1332NextReferenceString:
1333 ExFreePool(ReferenceBi);
1334 ReferenceBi = NULL;
1335 if (bip)
1336 ExFreePool(bip);
1337 bip = NULL;
1338 if (ReferenceKey != NULL)
1339 {
1340 ZwClose(ReferenceKey);
1341 ReferenceKey = NULL;
1342 }
1343 if (ControlKey != NULL)
1344 {
1345 ZwClose(ControlKey);
1346 ControlKey = NULL;
1347 }
1348 }
1349 if (FoundRightPDO)
1350 {
1351 /* No need to go further, as we already have found what we searched */
1352 break;
1353 }
1354
1355 ExFreePool(DeviceBi);
1356 DeviceBi = NULL;
1357 ZwClose(DeviceKey);
1358 DeviceKey = NULL;
1359 }
1360
1361 /* Add final NULL to ReturnBuffer */
1362 ASSERT(ReturnBuffer.Length <= ReturnBuffer.MaximumLength);
1363 if (ReturnBuffer.Length >= ReturnBuffer.MaximumLength)
1364 {
1365 PWSTR NewBuffer;
1366 ReturnBuffer.MaximumLength += sizeof(WCHAR);
1367 NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength);
1368 if (!NewBuffer)
1369 {
1370 DPRINT("ExAllocatePool() failed\n");
1372 goto cleanup;
1373 }
1374 if (ReturnBuffer.Buffer)
1375 {
1376 RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length);
1377 ExFreePool(ReturnBuffer.Buffer);
1378 }
1379 ReturnBuffer.Buffer = NewBuffer;
1380 }
1381 ReturnBuffer.Buffer[ReturnBuffer.Length / sizeof(WCHAR)] = UNICODE_NULL;
1382 *SymbolicLinkList = ReturnBuffer.Buffer;
1384
1385cleanup:
1386 if (!NT_SUCCESS(Status) && ReturnBuffer.Buffer)
1387 ExFreePool(ReturnBuffer.Buffer);
1388 if (InterfaceKey != NULL)
1389 ZwClose(InterfaceKey);
1390 if (DeviceKey != NULL)
1391 ZwClose(DeviceKey);
1392 if (ReferenceKey != NULL)
1393 ZwClose(ReferenceKey);
1394 if (ControlKey != NULL)
1395 ZwClose(ControlKey);
1396 if (DeviceBi)
1397 ExFreePool(DeviceBi);
1398 if (ReferenceBi)
1399 ExFreePool(ReferenceBi);
1400 if (bip)
1401 ExFreePool(bip);
1402 return Status;
1403}
#define PAGED_CODE()
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1157
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define TRUE
Definition: types.h:120
static void cleanup(void)
Definition: main.c:1335
static const WCHAR SymbolicLink[]
Definition: interface.c:31
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define NonPagedPool
Definition: env_spec_w32.h:307
#define PagedPool
Definition: env_spec_w32.h:308
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
if(dx< 0)
Definition: linetemp.h:194
#define ASSERT(a)
Definition: mode.c:44
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
struct _EXTENDED_DEVOBJ_EXTENSION * PEXTENDED_DEVOBJ_EXTENSION
@ KeyBasicInformation
Definition: nt_native.h:1131
@ KeyValuePartialInformation
Definition: nt_native.h:1182
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
#define UNICODE_NULL
static NTSTATUS IopOpenInterfaceKey(IN CONST GUID *InterfaceClassGuid, IN ACCESS_MASK DesiredAccess, OUT HANDLE *pInterfaceKey)
Definition: deviface.c:652
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
unsigned short USHORT
Definition: pedump.c:61
#define REG_DWORD
Definition: sdbapi.c:596
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
struct _DEVICE_NODE * DeviceNode
Definition: iotypes.h:1090
#define max(a, b)
Definition: svc.c:63
uint16_t * PWSTR
Definition: typedefs.h:56
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_In_ WDF_WMI_PROVIDER_CONTROL Control
Definition: wdfwmi.h:166
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_In_opt_ PDEVICE_OBJECT _In_ ULONG _Outptr_result_nullonfailure_ _At_ * SymbolicLinkList(return==0, __drv_allocatesMem(Mem))) PZZWSTR *SymbolicLinkList
_In_ CONST GUID * InterfaceClassGuid
Definition: iofuncs.h:1136
#define DEVICE_INTERFACE_INCLUDE_NONACTIVE
Definition: iofuncs.h:2856
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by CompBattGetBatteries(), get_device_pnp_name_guid(), IopFetchConfigurationInformation(), IopGetInterfaceDeviceList(), IoRegisterPlugPlayNotification(), KsRegisterFilterWithNoKSPins(), Test_IoGetDeviceInterfaces(), and WdmAudOpenSysAudioDevices().

◆ IoOpenDeviceInterfaceRegistryKey()

NTSTATUS NTAPI IoOpenDeviceInterfaceRegistryKey ( IN PUNICODE_STRING  SymbolicLinkName,
IN ACCESS_MASK  DesiredAccess,
OUT PHANDLE  DeviceInterfaceKey 
)

Definition at line 595 of file deviface.c.

598{
599 HANDLE InstanceKey, DeviceParametersKey;
602 UNICODE_STRING DeviceParametersU = RTL_CONSTANT_STRING(L"Device Parameters");
603
606 NULL,
607 NULL,
608 &InstanceKey);
609 if (!NT_SUCCESS(Status))
610 return Status;
611
613 &DeviceParametersU,
615 InstanceKey,
616 NULL);
617 Status = ZwCreateKey(&DeviceParametersKey,
620 0,
621 NULL,
623 NULL);
624 ZwClose(InstanceKey);
625
626 if (NT_SUCCESS(Status))
627 *DeviceInterfaceKey = DeviceParametersKey;
628
629 return Status;
630}
#define OBJ_OPENIF
Definition: winternl.h:229
#define KEY_CREATE_SUB_KEY
Definition: nt_native.h:1018
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_In_ ACCESS_MASK _Out_ PHANDLE DeviceInterfaceKey
Definition: iofuncs.h:1116

Referenced by Enum(), KsFilterFactoryUpdateCacheData(), KsRegisterFilterWithNoKSPins(), PcNewRegistryKey(), and Test_IoOpenDeviceInterfaceRegistryKey().

◆ IopBuildSymbolicLink()

static NTSTATUS IopBuildSymbolicLink ( _In_ PCUNICODE_STRING  DeviceString,
_In_ PCUNICODE_STRING  GuidString,
_In_opt_ PCUNICODE_STRING  ReferenceString,
_In_ BOOLEAN  UserModePrefixFormat,
_Out_ PUNICODE_STRING  SymbolicLinkName 
)
static

Creates a new symbolic link from the specified format of the prefix, device string, class GUID and reference string (if any).

Parameters
[in]DeviceStringDevice string, placed after prefix and before GUID, for example ACPI::PNP0501#1#.
[in]GuidStringDevice interface class GUID represented by a string. Placed in curly brackets {}, after device string, should always be 38 characters long. For example, {01234567-89ab-cdef-0123-456789abcdef}.
[in]ReferenceStringOptional reference string, if any. Placed after GUID, at the end of symbolic link. Usually contains human-readable subdevice name or class GUID.
[in]UserModePrefixFormatSpecifies whether a new symbolic link should have either a kernel mode or user mode prefix. TRUE for user mode prefix, FALSE for kernel mode.
[out]SymbolicLinkNamePointer to unicode string which receives created symbolic link.
Returns
STATUS_SUCCESS in case of success, or an NTSTATUS error code otherwise.

Definition at line 61 of file deviface.c.

67{
68 static const UNICODE_STRING KernelModePrefix = RTL_CONSTANT_STRING(L"\\??\\");
69 static const UNICODE_STRING UserModePrefix = RTL_CONSTANT_STRING(L"\\\\?\\");
70 static const UNICODE_STRING PathSep = RTL_CONSTANT_STRING(L"\\");
71 UNICODE_STRING MungedDeviceString, SymbolicLink;
74 USHORT i;
75
76 /* Use a backslash if reference string is not specified */
77 if (!ReferenceString)
78 ReferenceString = &PathSep;
79
80 /* Duplicate the device string (to "munge" it) */
81 Status = RtlDuplicateUnicodeString(0, DeviceString, &MungedDeviceString);
82 if (!NT_SUCCESS(Status))
83 {
84 DPRINT1("RtlDuplicateUnicodeString() failed, Status 0x%08lx\n", Status);
85 return Status;
86 }
87
88 /* Replace all '\' by '#' in device string */
89 for (i = 0; i < MungedDeviceString.Length / sizeof(WCHAR); i++)
90 {
91 if (MungedDeviceString.Buffer[i] == L'\\')
92 MungedDeviceString.Buffer[i] = L'#';
93 }
94
95 /* Calculate total length */
96 Length = KernelModePrefix.Length // Same as UserModePrefix.Length
97 + MungedDeviceString.Length
98 + sizeof(L"#") + GuidString->Length
99 + ReferenceString->Length;
101
102 /* Build up new symbolic link */
103 SymbolicLink.Length = 0;
104 SymbolicLink.MaximumLength = Length;
106 if (!SymbolicLink.Buffer)
107 {
108 DPRINT1("ExAllocatePoolWithTag() failed\n");
110 }
111
113 L"%wZ%wZ#%wZ%wZ",
114 UserModePrefixFormat ?
115 &UserModePrefix : &KernelModePrefix,
116 &MungedDeviceString,
120
121 DPRINT("New symbolic link is %wZ\n", &SymbolicLink);
122
124 return STATUS_SUCCESS;
125}
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
NTSYSAPI NTSTATUS WINAPI RtlDuplicateUnicodeString(int, const UNICODE_STRING *, UNICODE_STRING *)
static PWSTR GuidString
Definition: apphelp.c:93
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
NTSTRSAFEVAPI RtlUnicodeStringPrintf(_In_ PUNICODE_STRING DestinationString, _In_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:3241
#define TAG_IO
Definition: tag.h:79
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3304

Referenced by IoGetDeviceInterfaceAlias().

◆ IopGetDeviceObjectFromDeviceInstance()

PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance ( PUNICODE_STRING  DeviceInstance)

Definition at line 206 of file plugplay.c.

207{
209 IOP_FIND_DEVICE_INSTANCE_TRAVERSE_CONTEXT DeviceInstanceContext;
210
211 if (IopRootDeviceNode == NULL)
212 return NULL;
213
214 if (DeviceInstance == NULL ||
215 DeviceInstance->Length == 0)
216 {
218 {
221 }
222 else
223 return NULL;
224 }
225
226 /* Traverse the device tree to find the matching device node */
227 DeviceInstanceContext.InstancePath = DeviceInstance;
228 DeviceInstanceContext.DeviceObject = NULL;
232 &DeviceInstanceContext);
234
235 /* In case of error or instance not found, this will still be NULL from above. */
236 return DeviceInstanceContext.DeviceObject;
237}
static const WCHAR DeviceInstance[]
Definition: interface.c:28
#define IopInitDeviceTreeTraverseContext( _DeviceTreeTraverseContext, _DeviceNode, _Action, _Context)
Definition: io.h:229
NTSTATUS IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context)
PDEVICE_NODE IopRootDeviceNode
Definition: devnode.c:18
NTSTATUS IopFindDeviceInstanceTraverse(_In_ PDEVICE_NODE DeviceNode, _Inout_ PVOID Context)
Definition: plugplay.c:186
PDEVICE_OBJECT PhysicalDeviceObject
Definition: iotypes.h:1010
#define ObReferenceObject
Definition: obfuncs.h:204

Referenced by IoSetDeviceInterfaceState().

◆ IopOpenInterfaceKey()

static NTSTATUS IopOpenInterfaceKey ( IN CONST GUID InterfaceClassGuid,
IN ACCESS_MASK  DesiredAccess,
OUT HANDLE pInterfaceKey 
)
static

Definition at line 652 of file deviface.c.

655{
656 UNICODE_STRING LocalMachine = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\");
660 HANDLE InterfaceKey = NULL;
662
663 GuidString.Buffer = KeyName.Buffer = NULL;
664
666 if (!NT_SUCCESS(Status))
667 {
668 DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status);
669 goto cleanup;
670 }
671
672 KeyName.Length = 0;
673 KeyName.MaximumLength = LocalMachine.Length + ((USHORT)wcslen(REGSTR_PATH_DEVICE_CLASSES) + 1) * sizeof(WCHAR) + GuidString.Length;
674 KeyName.Buffer = ExAllocatePool(PagedPool, KeyName.MaximumLength);
675 if (!KeyName.Buffer)
676 {
677 DPRINT("ExAllocatePool() failed\n");
679 goto cleanup;
680 }
681
683 if (!NT_SUCCESS(Status))
684 {
685 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
686 goto cleanup;
687 }
689 if (!NT_SUCCESS(Status))
690 {
691 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
692 goto cleanup;
693 }
695 if (!NT_SUCCESS(Status))
696 {
697 DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status);
698 goto cleanup;
699 }
701 if (!NT_SUCCESS(Status))
702 {
703 DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status);
704 goto cleanup;
705 }
706
709 &KeyName,
711 NULL,
712 NULL);
713 Status = ZwOpenKey(
714 &InterfaceKey,
717 if (!NT_SUCCESS(Status))
718 {
719 DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status);
720 goto cleanup;
721 }
722
723 *pInterfaceKey = InterfaceKey;
725
726cleanup:
727 if (!NT_SUCCESS(Status))
728 {
729 if (InterfaceKey != NULL)
730 ZwClose(InterfaceKey);
731 }
734 return Status;
735}
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define REGSTR_PATH_DEVICE_CLASSES
Definition: regstr.h:481

Referenced by IoGetDeviceInterfaces().

◆ IopOpenOrCreateSymbolicLinkSubKeys()

static NTSTATUS IopOpenOrCreateSymbolicLinkSubKeys ( _Out_opt_ PHANDLE  DeviceHandle,
_Out_opt_ PULONG  DeviceDisposition,
_Out_opt_ PHANDLE  InstanceHandle,
_Out_opt_ PULONG  InstanceDisposition,
_In_ HANDLE  ClassHandle,
_In_ PCUNICODE_STRING  SymbolicLinkName,
_In_ ACCESS_MASK  DesiredAccess,
_In_ BOOLEAN  Create 
)
static

Retrieves a handles to the device and instance registry keys for the previously opened registry key handle of the specified symbolic link.

Definition at line 297 of file deviface.c.

306{
309 HANDLE DeviceKeyHandle, InstanceKeyHandle;
310 ULONG DeviceKeyDisposition, InstanceKeyDisposition;
311 BOOLEAN ReferenceStringPresent = FALSE; /* Assuming no ref string by default */
313 USHORT i;
314
315 DeviceKeyHandle = InstanceKeyHandle = NULL;
316
317 /* Duplicate the symbolic link (we'll modify it later) */
319 if (!NT_SUCCESS(Status))
320 {
321 DPRINT1("RtlDuplicateUnicodeString() failed, Status 0x%08lx\n", Status);
322 goto Quit;
323 }
324
325 /* Separate it into its constituents */
327 NULL,
328 NULL,
329 NULL,
331 &ReferenceStringPresent,
332 NULL);
333 if (!NT_SUCCESS(Status))
334 {
335 DPRINT1("Failed to separate symbolic link %wZ, Status 0x%08lx\n", &SymbolicLink, Status);
336 goto Quit;
337 }
338
339 /* Did we got a ref string? */
340 if (ReferenceStringPresent)
341 {
342 /* Remove it from our symbolic link */
343 SymbolicLink.MaximumLength = SymbolicLink.Length -= ReferenceString.Length;
344
345 /* Replace the 1st backslash `\` character by '#' pound */
346 ReferenceString.Buffer[0] = L'#';
347 }
348 else
349 {
350 /* No ref string, initialize it with a single pound character '#' */
352 }
353
354 /* Replace all '\' by '#' in symbolic link */
355 for (i = 0; i < SymbolicLink.Length / sizeof(WCHAR); i++)
356 {
357 if (SymbolicLink.Buffer[i] == L'\\')
358 SymbolicLink.Buffer[i] = L'#';
359 }
360
361 /* Fix prefix: '#??#' -> '##?#' */
362 SymbolicLink.Buffer[1] = L'#';
363
364 DPRINT("Munged symbolic link is %wZ\n", &SymbolicLink);
365
366 /* Try to open or create device interface keys */
367 if (Create)
368 {
369 Status = IopCreateRegistryKeyEx(&DeviceKeyHandle,
370 ClassHandle,
374 &DeviceKeyDisposition);
375 }
376 else
377 {
378 Status = IopOpenRegistryKeyEx(&DeviceKeyHandle,
379 ClassHandle,
382 }
383
384 if (!NT_SUCCESS(Status))
385 {
386 DPRINT1("Failed to create or open %wZ, Status 0x%08lx\n", &SymbolicLink, Status);
387 goto Quit;
388 }
389
390 DPRINT("Munged reference string is %wZ\n", &ReferenceString);
391
392 /* Try to open or create instance subkeys */
393 if (Create)
394 {
395 Status = IopCreateRegistryKeyEx(&InstanceKeyHandle,
396 DeviceKeyHandle,
400 &InstanceKeyDisposition);
401 }
402 else
403 {
404 Status = IopOpenRegistryKeyEx(&InstanceKeyHandle,
405 DeviceKeyHandle,
408 }
409
410 if (!NT_SUCCESS(Status))
411 {
412 DPRINT1("Failed to create or open %wZ, Status 0x%08lx\n", &ReferenceString, Status);
413 goto Quit;
414 }
415
417
418Quit:
419 if (NT_SUCCESS(Status))
420 {
421 if (DeviceHandle)
422 *DeviceHandle = DeviceKeyHandle;
423 else
424 ZwClose(DeviceKeyHandle);
425
426 if (DeviceDisposition)
427 *DeviceDisposition = DeviceKeyDisposition;
428
429 if (InstanceHandle)
430 *InstanceHandle = InstanceKeyHandle;
431 else
432 ZwClose(InstanceKeyHandle);
433
434 if (InstanceDisposition)
435 *InstanceDisposition = InstanceKeyDisposition;
436 }
437 else
438 {
439 if (InstanceKeyHandle)
440 ZwClose(InstanceKeyHandle);
441
442 if (Create)
443 ZwDeleteKey(DeviceKeyHandle);
444
445 if (DeviceKeyHandle)
446 ZwClose(DeviceKeyHandle);
447 }
448
449 if (SymbolicLink.Buffer)
451
452 return Status;
453}
@ Create
Definition: registry.c:563
_Inout_ PUSB_DEVICE_HANDLE DeviceHandle
Definition: hubbusif.h:121
NTSTATUS NTAPI IopOpenRegistryKeyEx(PHANDLE KeyHandle, HANDLE ParentKey, PUNICODE_STRING Name, ACCESS_MASK DesiredAccess)
Definition: pnpmgr.c:885
NTSTATUS NTAPI IopCreateRegistryKeyEx(OUT PHANDLE Handle, IN HANDLE BaseHandle OPTIONAL, IN PUNICODE_STRING KeyName, IN ACCESS_MASK DesiredAccess, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL)

Referenced by OpenRegistryHandlesFromSymbolicLink().

◆ IopSeparateSymbolicLink()

static NTSTATUS IopSeparateSymbolicLink ( _In_ PCUNICODE_STRING  SymbolicLinkName,
_Out_opt_ PUNICODE_STRING  PrefixString,
_Out_opt_ PUNICODE_STRING  MungedString,
_Out_opt_ PUNICODE_STRING  GuidString,
_Out_opt_ PUNICODE_STRING  ReferenceString,
_Out_opt_ PBOOLEAN  ReferenceStringPresent,
_Out_opt_ LPGUID  InterfaceClassGuid 
)
static

Parses the specified symbolic link onto the 4 parts: prefix, device string, class GUID and reference string.

Parameters
[in]SymbolicLinkNamePointer to a symbolic link string to parse.
[out]PrefixStringReceives prefix of symbolic link. Can be '\??\' for Kernel mode or '\?\' for User mode.
[out]MungedStringReceives device string. For example, ##?#ACPI#PNP0501#1#.
[out]GuidStringReceives device interface class GUID string represented by device interface. For example, {01234567-89ab-cdef-0123-456789abcdef}.
[out]ReferenceStringReceives reference string, if any. Usually contains a human-readable subdevice name or class GUID.
[out]ReferenceStringPresentPointer to variable that indicates whether the reference string exists in symbolic link. TRUE if it does, FALSE otherwise.
[out]InterfaceClassGuidReceives the interface class GUID to which specified symbolic link belongs to.
Returns
STATUS_SUCCESS in case of success, or an NTSTATUS error code otherwise.

Definition at line 161 of file deviface.c.

169{
170 static const UNICODE_STRING KernelModePrefix = RTL_CONSTANT_STRING(L"\\??\\");
171 static const UNICODE_STRING UserModePrefix = RTL_CONSTANT_STRING(L"\\\\?\\");
172 UNICODE_STRING MungedStringReal, GuidStringReal, ReferenceStringReal;
173 UNICODE_STRING LinkNameNoPrefix;
174 USHORT i, ReferenceStringOffset;
176
177 DPRINT("Symbolic link is %wZ\n", SymbolicLinkName);
178
179 /* The symbolic link name looks like \??\ACPI#PNP0501#1#{GUID}\ReferenceString
180 * Make sure it starts with the expected prefix. */
181 if (!RtlPrefixUnicodeString(&KernelModePrefix, SymbolicLinkName, FALSE) &&
183 {
184 DPRINT1("Invalid link name %wZ\n", SymbolicLinkName);
186 }
187
188 /* Sanity checks */
189 ASSERT(KernelModePrefix.Length == UserModePrefix.Length);
190 ASSERT(SymbolicLinkName->Length >= KernelModePrefix.Length);
191
192 /* Make a version without the prefix for further processing */
193 LinkNameNoPrefix.Buffer = SymbolicLinkName->Buffer + KernelModePrefix.Length / sizeof(WCHAR);
194 LinkNameNoPrefix.Length = SymbolicLinkName->Length - KernelModePrefix.Length;
195 LinkNameNoPrefix.MaximumLength = LinkNameNoPrefix.Length;
196
197 DPRINT("Symbolic link without prefix is %wZ\n", &LinkNameNoPrefix);
198
199 /* Find the reference string, if any */
200 for (i = 0; i < LinkNameNoPrefix.Length / sizeof(WCHAR); i++)
201 {
202 if (LinkNameNoPrefix.Buffer[i] == L'\\')
203 break;
204 }
205 ReferenceStringOffset = i * sizeof(WCHAR);
206
207 /* The GUID is before the reference string or at the end */
208 ASSERT(LinkNameNoPrefix.Length >= ReferenceStringOffset);
209 if (ReferenceStringOffset < GUID_STRING_BYTES + sizeof(WCHAR))
210 {
211 DPRINT1("Invalid link name %wZ\n", SymbolicLinkName);
213 }
214
215 /* Get reference string (starts with \ after {GUID}) from link without prefix */
216 ReferenceStringReal.Buffer = LinkNameNoPrefix.Buffer + ReferenceStringOffset / sizeof(WCHAR);
217 ReferenceStringReal.Length = LinkNameNoPrefix.Length - ReferenceStringOffset;
218 ReferenceStringReal.MaximumLength = ReferenceStringReal.Length;
219
220 DPRINT("Reference string is %wZ\n", &ReferenceStringReal);
221
222 /* Get GUID string (device class GUID in {} brackets) */
223 GuidStringReal.Buffer = LinkNameNoPrefix.Buffer + (ReferenceStringOffset - GUID_STRING_BYTES) / sizeof(WCHAR);
224 GuidStringReal.Length = GUID_STRING_BYTES;
225 GuidStringReal.MaximumLength = GuidStringReal.Length;
226
227 DPRINT("GUID string is %wZ\n", &GuidStringReal);
228
229 /* Validate GUID string for:
230 * 1) {} brackets at the start and the end;
231 * 2) - separators in the appropriate places. */
232 ASSERT(GuidStringReal.Buffer[0] == L'{');
233 ASSERT(GuidStringReal.Buffer[GUID_STRING_CHARS - 1] == L'}');
234 ASSERT(GuidStringReal.Buffer[9] == L'-');
235 ASSERT(GuidStringReal.Buffer[14] == L'-');
236 ASSERT(GuidStringReal.Buffer[19] == L'-');
237 ASSERT(GuidStringReal.Buffer[24] == L'-');
238
239 if (MungedString)
240 {
241 /* Create a munged path string (looks like ACPI#PNP0501#1#) */
242 MungedStringReal.Buffer = LinkNameNoPrefix.Buffer;
243 MungedStringReal.Length = LinkNameNoPrefix.Length - ReferenceStringReal.Length - GUID_STRING_BYTES - sizeof(WCHAR);
244 MungedStringReal.MaximumLength = MungedStringReal.Length;
245
246 DPRINT("Munged string is %wZ\n", &MungedStringReal);
247 }
248
249 /* Store received parts if the parameters are not null */
250 if (PrefixString)
251 {
252 PrefixString->Buffer = SymbolicLinkName->Buffer;
253 PrefixString->Length = KernelModePrefix.Length; // Same as UserModePrefix.Length
254 PrefixString->MaximumLength = PrefixString->Length;
255
256 DPRINT("Prefix string is %wZ\n", PrefixString);
257 }
258
259 if (MungedString)
260 *MungedString = MungedStringReal;
261
262 if (GuidString)
263 *GuidString = GuidStringReal;
264
265 if (ReferenceString)
266 {
267 if (ReferenceStringReal.Length > sizeof(WCHAR))
268 *ReferenceString = ReferenceStringReal;
269 else
270 RtlInitEmptyUnicodeString(ReferenceString, NULL, 0);
271 }
272
273 if (ReferenceStringPresent)
274 *ReferenceStringPresent = ReferenceStringReal.Length > sizeof(WCHAR);
275
277 {
278 /* Convert GUID string into a GUID and store it also */
279 Status = RtlGUIDFromString(&GuidStringReal, InterfaceClassGuid);
280 if (!NT_SUCCESS(Status))
281 {
282 DPRINT1("RtlGUIDFromString() failed, Status 0x%08lx\n", Status);
283 }
284 }
285
286 /* We're done */
287 return Status;
288}
NTSYSAPI NTSTATUS WINAPI RtlGUIDFromString(PUNICODE_STRING, GUID *)
#define GUID_STRING_CHARS
Definition: deviface.c:21
#define GUID_STRING_BYTES
Definition: deviface.c:22

Referenced by IoGetDeviceInterfaceAlias(), IopOpenOrCreateSymbolicLinkSubKeys(), and OpenRegistryHandlesFromSymbolicLink().

◆ IoRegisterDeviceInterface()

NTSTATUS NTAPI IoRegisterDeviceInterface ( IN PDEVICE_OBJECT  PhysicalDeviceObject,
IN CONST GUID InterfaceClassGuid,
IN PUNICODE_STRING ReferenceString  OPTIONAL,
OUT PUNICODE_STRING  SymbolicLinkName 
)

Definition at line 1437 of file deviface.c.

1441{
1442 PUNICODE_STRING InstancePath;
1445 UNICODE_STRING InterfaceKeyName;
1446 UNICODE_STRING BaseKeyName;
1447 UCHAR PdoNameInfoBuffer[sizeof(OBJECT_NAME_INFORMATION) + (256 * sizeof(WCHAR))];
1448 POBJECT_NAME_INFORMATION PdoNameInfo = (POBJECT_NAME_INFORMATION)PdoNameInfoBuffer;
1451 HANDLE ClassKey;
1452 HANDLE InterfaceKey;
1453 HANDLE SubKey;
1454 ULONG StartIndex;
1456 ULONG i;
1457 NTSTATUS Status, SymLinkStatus;
1458 PEXTENDED_DEVOBJ_EXTENSION DeviceObjectExtension;
1459
1461
1462 DPRINT("IoRegisterDeviceInterface(): PDO %p, RefString: %wZ\n",
1464
1465 /* Parameters must pass three border of checks */
1466 DeviceObjectExtension = (PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension;
1467
1468 /* 1st level: Presence of a Device Node */
1469 if (DeviceObjectExtension->DeviceNode == NULL)
1470 {
1471 DPRINT("PhysicalDeviceObject 0x%p doesn't have a DeviceNode\n", PhysicalDeviceObject);
1473 }
1474
1475 /* 2nd level: Presence of an non-zero length InstancePath */
1476 if (DeviceObjectExtension->DeviceNode->InstancePath.Length == 0)
1477 {
1478 DPRINT("PhysicalDeviceObject 0x%p's DOE has zero-length InstancePath\n", PhysicalDeviceObject);
1480 }
1481
1482 /* 3rd level: Optional, based on WDK documentation */
1483 if (ReferenceString != NULL)
1484 {
1485 /* Reference string must not contain path-separator symbols */
1486 for (i = 0; i < ReferenceString->Length / sizeof(WCHAR); i++)
1487 {
1488 if ((ReferenceString->Buffer[i] == '\\') ||
1489 (ReferenceString->Buffer[i] == '/'))
1491 }
1492 }
1493
1495 if (!NT_SUCCESS(Status))
1496 {
1497 DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status);
1498 return Status;
1499 }
1500
1501 /* Create Pdo name: \Device\xxxxxxxx (unnamed device) */
1504 PdoNameInfo,
1505 sizeof(PdoNameInfoBuffer),
1506 &i);
1507 if (!NT_SUCCESS(Status))
1508 {
1509 DPRINT("ObQueryNameString() failed with status 0x%08lx\n", Status);
1510 return Status;
1511 }
1512 ASSERT(PdoNameInfo->Name.Length);
1513
1514 /* Create base key name for this interface: HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1515 ASSERT(((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode);
1516 InstancePath = &((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode->InstancePath;
1517 BaseKeyName.Length = (USHORT)wcslen(BaseKeyString) * sizeof(WCHAR);
1518 BaseKeyName.MaximumLength = BaseKeyName.Length
1519 + GuidString.Length;
1520 BaseKeyName.Buffer = ExAllocatePool(
1521 PagedPool,
1522 BaseKeyName.MaximumLength);
1523 if (!BaseKeyName.Buffer)
1524 {
1525 DPRINT("ExAllocatePool() failed\n");
1527 }
1528 wcscpy(BaseKeyName.Buffer, BaseKeyString);
1530
1531 /* Create BaseKeyName key in registry */
1534 &BaseKeyName,
1536 NULL, /* RootDirectory */
1537 NULL); /* SecurityDescriptor */
1538
1539 Status = ZwCreateKey(
1540 &ClassKey,
1541 KEY_WRITE,
1543 0, /* TileIndex */
1544 NULL, /* Class */
1546 NULL); /* Disposition */
1547
1548 if (!NT_SUCCESS(Status))
1549 {
1550 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
1551 ExFreePool(BaseKeyName.Buffer);
1552 return Status;
1553 }
1554
1555 /* Create key name for this interface: ##?#ACPI#PNP0501#1#{GUID} */
1556 InterfaceKeyName.Length = 0;
1557 InterfaceKeyName.MaximumLength =
1558 4 * sizeof(WCHAR) + /* 4 = size of ##?# */
1559 InstancePath->Length +
1560 sizeof(WCHAR) + /* 1 = size of # */
1561 GuidString.Length;
1562 InterfaceKeyName.Buffer = ExAllocatePool(
1563 PagedPool,
1564 InterfaceKeyName.MaximumLength);
1565 if (!InterfaceKeyName.Buffer)
1566 {
1567 DPRINT("ExAllocatePool() failed\n");
1569 }
1570
1571 RtlAppendUnicodeToString(&InterfaceKeyName, L"##?#");
1572 StartIndex = InterfaceKeyName.Length / sizeof(WCHAR);
1573 RtlAppendUnicodeStringToString(&InterfaceKeyName, InstancePath);
1574 for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++)
1575 {
1576 if (InterfaceKeyName.Buffer[StartIndex + i] == '\\')
1577 InterfaceKeyName.Buffer[StartIndex + i] = '#';
1578 }
1579 RtlAppendUnicodeToString(&InterfaceKeyName, L"#");
1580 RtlAppendUnicodeStringToString(&InterfaceKeyName, &GuidString);
1581
1582 /* Create the interface key in registry */
1585 &InterfaceKeyName,
1587 ClassKey,
1588 NULL); /* SecurityDescriptor */
1589
1590 Status = ZwCreateKey(
1591 &InterfaceKey,
1592 KEY_WRITE,
1594 0, /* TileIndex */
1595 NULL, /* Class */
1597 NULL); /* Disposition */
1598
1599 if (!NT_SUCCESS(Status))
1600 {
1601 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
1602 ZwClose(ClassKey);
1603 ExFreePool(BaseKeyName.Buffer);
1604 return Status;
1605 }
1606
1607 /* Write DeviceInstance entry. Value is InstancePath */
1608 Status = ZwSetValueKey(
1609 InterfaceKey,
1611 0, /* TileIndex */
1612 REG_SZ,
1613 InstancePath->Buffer,
1614 InstancePath->Length);
1615 if (!NT_SUCCESS(Status))
1616 {
1617 DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status);
1618 ZwClose(InterfaceKey);
1619 ZwClose(ClassKey);
1620 ExFreePool(InterfaceKeyName.Buffer);
1621 ExFreePool(BaseKeyName.Buffer);
1622 return Status;
1623 }
1624
1625 /* Create subkey. Name is #ReferenceString */
1626 SubKeyName.Length = 0;
1627 SubKeyName.MaximumLength = sizeof(WCHAR);
1628 if (ReferenceString && ReferenceString->Length)
1629 SubKeyName.MaximumLength += ReferenceString->Length;
1630 SubKeyName.Buffer = ExAllocatePool(
1631 PagedPool,
1632 SubKeyName.MaximumLength);
1633 if (!SubKeyName.Buffer)
1634 {
1635 DPRINT("ExAllocatePool() failed\n");
1636 ZwClose(InterfaceKey);
1637 ZwClose(ClassKey);
1638 ExFreePool(InterfaceKeyName.Buffer);
1639 ExFreePool(BaseKeyName.Buffer);
1641 }
1643 if (ReferenceString && ReferenceString->Length)
1645
1646 /* Create SubKeyName key in registry */
1649 &SubKeyName,
1651 InterfaceKey, /* RootDirectory */
1652 NULL); /* SecurityDescriptor */
1653
1654 Status = ZwCreateKey(
1655 &SubKey,
1656 KEY_WRITE,
1658 0, /* TileIndex */
1659 NULL, /* Class */
1661 NULL); /* Disposition */
1662
1663 if (!NT_SUCCESS(Status))
1664 {
1665 DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status);
1666 ZwClose(InterfaceKey);
1667 ZwClose(ClassKey);
1668 ExFreePool(InterfaceKeyName.Buffer);
1669 ExFreePool(BaseKeyName.Buffer);
1670 return Status;
1671 }
1672
1673 /* Create symbolic link name: \??\ACPI#PNP0501#1#{GUID}\ReferenceString */
1674 SymbolicLinkName->Length = 0;
1675 SymbolicLinkName->MaximumLength = SymbolicLinkName->Length
1676 + 4 * sizeof(WCHAR) /* 4 = size of \??\ */
1677 + InstancePath->Length
1678 + sizeof(WCHAR) /* 1 = size of # */
1679 + GuidString.Length
1680 + sizeof(WCHAR); /* final NULL */
1681 if (ReferenceString && ReferenceString->Length)
1682 SymbolicLinkName->MaximumLength += sizeof(WCHAR) + ReferenceString->Length;
1684 PagedPool,
1685 SymbolicLinkName->MaximumLength);
1686 if (!SymbolicLinkName->Buffer)
1687 {
1688 DPRINT("ExAllocatePool() failed\n");
1689 ZwClose(SubKey);
1690 ZwClose(InterfaceKey);
1691 ZwClose(ClassKey);
1692 ExFreePool(InterfaceKeyName.Buffer);
1693 ExFreePool(SubKeyName.Buffer);
1694 ExFreePool(BaseKeyName.Buffer);
1696 }
1698 StartIndex = SymbolicLinkName->Length / sizeof(WCHAR);
1700 for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++)
1701 {
1702 if (SymbolicLinkName->Buffer[StartIndex + i] == '\\')
1703 SymbolicLinkName->Buffer[StartIndex + i] = '#';
1704 }
1707 SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0';
1708
1709 /* Create symbolic link */
1710 DPRINT("IoRegisterDeviceInterface(): creating symbolic link %wZ -> %wZ\n", SymbolicLinkName, &PdoNameInfo->Name);
1711 SymLinkStatus = IoCreateSymbolicLink(SymbolicLinkName, &PdoNameInfo->Name);
1712
1713 /* If the symbolic link already exists, return an informational success status */
1714 if (SymLinkStatus == STATUS_OBJECT_NAME_COLLISION)
1715 {
1716 /* HACK: Delete the existing symbolic link and update it to the new PDO name */
1718 IoCreateSymbolicLink(SymbolicLinkName, &PdoNameInfo->Name);
1719 SymLinkStatus = STATUS_OBJECT_NAME_EXISTS;
1720 }
1721
1722 if (!NT_SUCCESS(SymLinkStatus))
1723 {
1724 DPRINT1("IoCreateSymbolicLink() failed with status 0x%08lx\n", SymLinkStatus);
1725 ZwClose(SubKey);
1726 ZwClose(InterfaceKey);
1727 ZwClose(ClassKey);
1728 ExFreePool(SubKeyName.Buffer);
1729 ExFreePool(InterfaceKeyName.Buffer);
1730 ExFreePool(BaseKeyName.Buffer);
1732 return SymLinkStatus;
1733 }
1734
1735 if (ReferenceString && ReferenceString->Length)
1736 {
1739 }
1740 SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0';
1741
1742 /* Write symbolic link name in registry */
1743 SymbolicLinkName->Buffer[1] = '\\';
1744 Status = ZwSetValueKey(
1745 SubKey,
1746 &SymbolicLink,
1747 0, /* TileIndex */
1748 REG_SZ,
1749 SymbolicLinkName->Buffer,
1750 SymbolicLinkName->Length);
1751 if (!NT_SUCCESS(Status))
1752 {
1753 DPRINT1("ZwSetValueKey() failed with status 0x%08lx\n", Status);
1755 }
1756 else
1757 {
1758 SymbolicLinkName->Buffer[1] = '?';
1759 }
1760
1761 ZwClose(SubKey);
1762 ZwClose(InterfaceKey);
1763 ZwClose(ClassKey);
1764 ExFreePool(SubKeyName.Buffer);
1765 ExFreePool(InterfaceKeyName.Buffer);
1766 ExFreePool(BaseKeyName.Buffer);
1767
1768 return NT_SUCCESS(Status) ? SymLinkStatus : Status;
1769}
wcscpy
#define ASSERT_IRQL_EQUAL(x)
Definition: debug.h:43
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING SubKeyName
Definition: ndis.h:4725
struct _OBJECT_NAME_INFORMATION OBJECT_NAME_INFORMATION
struct _OBJECT_NAME_INFORMATION * POBJECT_NAME_INFORMATION
#define KEY_WRITE
Definition: nt_native.h:1031
static PCWSTR BaseKeyString
Definition: deviface.c:30
#define STATUS_OBJECT_NAME_EXISTS
Definition: ntstatus.h:114
NTSTATUS NTAPI ObQueryNameString(IN PVOID Object, OUT POBJECT_NAME_INFORMATION ObjectNameInfo, IN ULONG Length, OUT PULONG ReturnLength)
Definition: obname.c:1207
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by _Function_class_(), BatteryClassInitializeDevice(), Bus_PDO_PnP(), ClassAddDevice(), ClasspRegisterMountedDeviceInterface(), FdoHandleStartDevice(), FdoStartAdapter(), FreeBT_AddDevice(), HidClassPDO_PnP(), i8042PowerWorkItem(), KsCreateBusEnumObject(), KspRegisterDeviceAssociation(), KspRegisterDeviceInterfaces(), Mx::MxRegisterDeviceInterface(), NdisIAddDevice(), PartitionHandleStartDevice(), PcRegisterSubdevice(), RamdiskAddDevice(), RamdiskPnp(), RegisterDeviceInterfaces(), ScsiFlopInitDevice(), SerenumAddDevice(), SerialAddDeviceInternal(), SysAudioRegisterDeviceInterfaces(), USBH_SymbolicLink(), USBPORT_RegisterDeviceInterface(), and WdmAudRegisterDeviceInterface().

◆ IoSetDeviceInterfaceState()

NTSTATUS NTAPI IoSetDeviceInterfaceState ( IN PUNICODE_STRING  SymbolicLinkName,
IN BOOLEAN  Enable 
)

Definition at line 1793 of file deviface.c.

1795{
1800 HANDLE InstanceHandle, ControlHandle;
1803 ULONG LinkedValue, Index;
1804 GUID DeviceGuid;
1805 UNICODE_STRING DosDevicesPrefix1 = RTL_CONSTANT_STRING(L"\\??\\");
1806 UNICODE_STRING DosDevicesPrefix2 = RTL_CONSTANT_STRING(L"\\\\?\\");
1807 UNICODE_STRING LinkNameNoPrefix;
1808 USHORT i;
1809 USHORT ReferenceStringOffset;
1810
1811 if (SymbolicLinkName == NULL)
1812 {
1814 }
1815
1816 DPRINT("IoSetDeviceInterfaceState('%wZ', %u)\n", SymbolicLinkName, Enable);
1817
1818 /* Symbolic link name is \??\ACPI#PNP0501#1#{GUID}\ReferenceString */
1819 /* Make sure it starts with the expected prefix */
1820 if (!RtlPrefixUnicodeString(&DosDevicesPrefix1, SymbolicLinkName, FALSE) &&
1821 !RtlPrefixUnicodeString(&DosDevicesPrefix2, SymbolicLinkName, FALSE))
1822 {
1823 DPRINT1("IoSetDeviceInterfaceState() invalid link name '%wZ'\n", SymbolicLinkName);
1825 }
1826
1827 /* Make a version without the prefix for further processing */
1828 ASSERT(DosDevicesPrefix1.Length == DosDevicesPrefix2.Length);
1829 ASSERT(SymbolicLinkName->Length >= DosDevicesPrefix1.Length);
1830 LinkNameNoPrefix.Buffer = SymbolicLinkName->Buffer + DosDevicesPrefix1.Length / sizeof(WCHAR);
1831 LinkNameNoPrefix.Length = SymbolicLinkName->Length - DosDevicesPrefix1.Length;
1832 LinkNameNoPrefix.MaximumLength = LinkNameNoPrefix.Length;
1833
1834 /* Find the reference string, if any */
1835 for (i = 0; i < LinkNameNoPrefix.Length / sizeof(WCHAR); i++)
1836 {
1837 if (LinkNameNoPrefix.Buffer[i] == L'\\')
1838 {
1839 break;
1840 }
1841 }
1842 ReferenceStringOffset = i * sizeof(WCHAR);
1843
1844 /* The GUID is before the reference string or at the end */
1845 ASSERT(LinkNameNoPrefix.Length >= ReferenceStringOffset);
1846 if (ReferenceStringOffset < GUID_STRING_BYTES + sizeof(WCHAR))
1847 {
1848 DPRINT1("IoSetDeviceInterfaceState() invalid link name '%wZ'\n", SymbolicLinkName);
1850 }
1851
1852 GuidString.Buffer = LinkNameNoPrefix.Buffer + (ReferenceStringOffset - GUID_STRING_BYTES) / sizeof(WCHAR);
1854 GuidString.MaximumLength = GuidString.Length;
1855 Status = RtlGUIDFromString(&GuidString, &DeviceGuid);
1856 if (!NT_SUCCESS(Status))
1857 {
1858 DPRINT1("RtlGUIDFromString() invalid GUID '%wZ' in link name '%wZ'\n", &GuidString, SymbolicLinkName);
1859 return Status;
1860 }
1861
1862 /* Open registry keys */
1865 NULL,
1866 NULL,
1867 &InstanceHandle);
1868 if (!NT_SUCCESS(Status))
1869 return Status;
1870
1871 RtlInitUnicodeString(&KeyName, L"Control");
1873 &KeyName,
1875 InstanceHandle,
1876 NULL);
1877 Status = ZwCreateKey(&ControlHandle,
1880 0,
1881 NULL,
1883 NULL);
1884 ZwClose(InstanceHandle);
1885 if (!NT_SUCCESS(Status))
1886 {
1887 DPRINT1("Failed to create the Control subkey\n");
1888 return Status;
1889 }
1890
1891 LinkedValue = (Enable ? 1 : 0);
1892
1893 RtlInitUnicodeString(&KeyName, L"Linked");
1894 Status = ZwSetValueKey(ControlHandle,
1895 &KeyName,
1896 0,
1897 REG_DWORD,
1898 &LinkedValue,
1899 sizeof(ULONG));
1900 ZwClose(ControlHandle);
1901 if (!NT_SUCCESS(Status))
1902 {
1903 DPRINT1("Failed to write the Linked value\n");
1904 return Status;
1905 }
1906
1907 ASSERT(GuidString.Buffer >= LinkNameNoPrefix.Buffer + 1);
1908 DeviceInstance.Length = (GuidString.Buffer - LinkNameNoPrefix.Buffer - 1) * sizeof(WCHAR);
1909 if (DeviceInstance.Length == 0)
1910 {
1911 DPRINT1("No device instance in link name '%wZ'\n", SymbolicLinkName);
1913 }
1914 DeviceInstance.MaximumLength = DeviceInstance.Length;
1916 DeviceInstance.MaximumLength,
1917 TAG_IO);
1918 if (DeviceInstance.Buffer == NULL)
1919 {
1920 /* no memory */
1922 }
1923
1925 LinkNameNoPrefix.Buffer,
1926 DeviceInstance.Length);
1927
1928 for (Index = 0; Index < DeviceInstance.Length / sizeof(WCHAR); Index++)
1929 {
1930 if (DeviceInstance.Buffer[Index] == L'#')
1931 {
1932 DeviceInstance.Buffer[Index] = L'\\';
1933 }
1934 }
1935
1937
1939 {
1940 DPRINT1("IopGetDeviceObjectFromDeviceInstance failed to find device object for %wZ\n", &DeviceInstance);
1943 }
1944
1946
1948
1951
1953 DPRINT("Status %x\n", Status);
1954 return STATUS_SUCCESS;
1955}
const GUID GUID_DEVICE_INTERFACE_ARRIVAL
Definition: deviface.c:14
const GUID GUID_DEVICE_INTERFACE_REMOVAL
Definition: deviface.c:15
_Must_inspect_result_ _In_ WDFDEVICE _In_ REFGUID EventGuid
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
#define KEY_SET_VALUE
Definition: nt_native.h:1017
_In_ ULONGLONG _In_ ULONGLONG _In_ BOOLEAN Enable
Definition: ntddpcm.h:142
NTSTATUS IopQueueDeviceChangeEvent(_In_ const GUID *EventGuid, _In_ const GUID *InterfaceClassGuid, _In_ PUNICODE_STRING SymbolicLinkName)
Definition: plugplay.c:52
VOID PiNotifyDeviceInterfaceChange(_In_ LPCGUID Event, _In_ LPCGUID InterfaceClassGuid, _In_ PUNICODE_STRING SymbolicLinkName)
Delivers the event to all drivers subscribed to EventCategoryDeviceInterfaceChange.
Definition: pnpnotify.c:161
PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance)
Definition: plugplay.c:206
_In_ WDFCOLLECTION _In_ ULONG Index
#define ObDereferenceObject
Definition: obfuncs.h:203

Referenced by _Function_class_(), add_volume_device(), BatteryClassInitializeDevice(), BatteryClassUnload(), Bus_PDO_PnP(), check_system_root(), ClasspRegisterMountedDeviceInterface(), FdoHandleRemoveDevice(), FdoHandleStartDevice(), FdoRemoveAdapter(), FdoStartAdapter(), HandleRemoveDevice(), HandleStartDevice(), HandleSurpriseRemoval(), HidClassPDO_PnP(), i8042PowerWorkItem(), KsCreateBusEnumObject(), KspEnableBusDeviceInterface(), KspRegisterDeviceAssociation(), KspRemoveDeviceAssociations(), KspSetDeviceInterfacesState(), Mx::MxSetDeviceInterfaceState(), NdisIPnPStartDevice(), NdisIPnPStopDevice(), PartitionHandleRemove(), PartitionHandleStartDevice(), PcRegisterSubdevice(), RamdiskAddDevice(), RamdiskPnp(), RamdiskRemoveBusDevice(), RegisterDeviceInterfaces(), remove_volume_child(), ScsiFlopRemoveDevice(), ScsiFlopStartDevice(), SerenumFdoStartDevice(), SerialPnpStartDevice(), SysAudioRegisterDeviceInterfaces(), Test_IoSetDeviceInterfaceState(), USBH_SymbolicLink(), USBPORT_RegisterDeviceInterface(), and WdmAudRegisterDeviceInterface().

◆ OpenRegistryHandlesFromSymbolicLink()

static NTSTATUS OpenRegistryHandlesFromSymbolicLink ( _In_ PCUNICODE_STRING  SymbolicLinkName,
_In_ ACCESS_MASK  DesiredAccess,
_Out_opt_ PHANDLE  GuidKey,
_Out_opt_ PHANDLE  DeviceKey,
_Out_opt_ PHANDLE  InstanceKey 
)
static

Retrieves a handles to the GUID, device and instance registry keys for the specified symbolic link.

Definition at line 462 of file deviface.c.

468{
469 UNICODE_STRING BaseKeyU;
471 HANDLE ClassesKey;
472 HANDLE GuidKeyReal, DeviceKeyReal, InstanceKeyReal;
474
475 ClassesKey = GuidKeyReal = DeviceKeyReal = InstanceKeyReal = NULL;
476
478
479 /* Separate symbolic link onto the parts */
481 NULL,
482 NULL,
483 &GuidString,
484 NULL,
485 NULL,
486 NULL);
487 if (!NT_SUCCESS(Status))
488 {
489 DPRINT1("Failed to parse symbolic link %wZ, Status 0x%08lx\n",
491 goto Quit;
492 }
493
494 /* Open the DeviceClasses key */
495 Status = IopOpenRegistryKeyEx(&ClassesKey,
496 NULL,
497 &BaseKeyU,
499 if (!NT_SUCCESS(Status))
500 {
501 DPRINT1("Failed to open %wZ, Status 0x%08lx\n", &BaseKeyU, Status);
502 goto Quit;
503 }
504
505 /* Open the GUID subkey */
506 Status = IopOpenRegistryKeyEx(&GuidKeyReal,
507 ClassesKey,
508 &GuidString,
510 if (!NT_SUCCESS(Status))
511 {
512 DPRINT1("Failed to open %wZ%wZ, Status 0x%08lx\n", &BaseKeyU, &GuidString, Status);
513 goto Quit;
514 }
515
516 /* Open the device and instance subkeys */
518 NULL,
519 &InstanceKeyReal,
520 NULL,
521 GuidKeyReal,
524 FALSE);
525 if (!NT_SUCCESS(Status))
526 {
527 DPRINT1("Failed to open %wZ%wZ, Status 0x%08lx\n", &BaseKeyU, &GuidString, Status);
528 goto Quit;
529 }
530
532
533Quit:
534 if (NT_SUCCESS(Status))
535 {
536 if (GuidKey)
537 *GuidKey = GuidKeyReal;
538 else
539 ZwClose(GuidKeyReal);
540
541 if (DeviceKey)
542 *DeviceKey = DeviceKeyReal;
543 else
544 ZwClose(DeviceKeyReal);
545
546 if (InstanceKey)
547 *InstanceKey = InstanceKeyReal;
548 else
549 ZwClose(InstanceKeyReal);
550 }
551 else
552 {
553 if (GuidKeyReal)
554 ZwClose(GuidKeyReal);
555
556 if (DeviceKeyReal)
557 ZwClose(DeviceKeyReal);
558
559 if (InstanceKeyReal)
560 ZwClose(InstanceKeyReal);
561 }
562
563 if (ClassesKey)
564 ZwClose(ClassesKey);
565
566 return Status;
567}
static NTSTATUS IopOpenOrCreateSymbolicLinkSubKeys(_Out_opt_ PHANDLE DeviceHandle, _Out_opt_ PULONG DeviceDisposition, _Out_opt_ PHANDLE InstanceHandle, _Out_opt_ PULONG InstanceDisposition, _In_ HANDLE ClassHandle, _In_ PCUNICODE_STRING SymbolicLinkName, _In_ ACCESS_MASK DesiredAccess, _In_ BOOLEAN Create)
Retrieves a handles to the device and instance registry keys for the previously opened registry key h...
Definition: deviface.c:297

Referenced by IoGetDeviceInterfaceAlias(), IoOpenDeviceInterfaceRegistryKey(), and IoSetDeviceInterfaceState().

Variable Documentation

◆ BaseKeyString

PCWSTR BaseKeyString = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses\\"
static

Definition at line 30 of file deviface.c.

Referenced by IoRegisterDeviceInterface(), and OpenRegistryHandlesFromSymbolicLink().