2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/io/pnpmgr/devintrf.c
5 * PURPOSE: Device interface functions
6 * PROGRAMMER: Filip Navara (xnavara@volny.cz)
7 * Matthew Brace (ismarc@austin.rr.com)
9 * 22/09/2003 FiN Created
12 /* INCLUDES ******************************************************************/
17 #include <internal/debug.h>
19 DEFINE_GUID(GUID_SERENUM_BUS_ENUMERATOR
,
20 0x4D36E978L
, 0xE325, 0x11CE, 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18);
22 /* FUNCTIONS *****************************************************************/
29 IoOpenDeviceInterfaceRegistryKey(
30 IN PUNICODE_STRING SymbolicLinkName
,
31 IN ACCESS_MASK DesiredAccess
,
32 OUT PHANDLE DeviceInterfaceKey
)
34 return STATUS_NOT_IMPLEMENTED
;
42 IoGetDeviceInterfaceAlias(
43 IN PUNICODE_STRING SymbolicLinkName
,
44 IN CONST GUID
*AliasInterfaceClassGuid
,
45 OUT PUNICODE_STRING AliasSymbolicLinkName
)
47 return STATUS_NOT_IMPLEMENTED
;
51 * IoGetDeviceInterfaces
53 * Returns a list of device interfaces of a particular device interface class.
57 * Points to a class GUID specifying the device interface class.
59 * PhysicalDeviceObject
60 * Points to an optional PDO that narrows the search to only the
61 * device interfaces of the device represented by the PDO.
64 * Specifies flags that modify the search for device interfaces. The
65 * DEVICE_INTERFACE_INCLUDE_NONACTIVE flag specifies that the list of
66 * returned symbolic links should contain also disabled device
67 * interfaces in addition to the enabled ones.
70 * Points to a character pointer that is filled in on successful return
71 * with a list of unicode strings identifying the device interfaces
72 * that match the search criteria. The newly allocated buffer contains
73 * a list of symbolic link names. Each unicode string in the list is
74 * null-terminated; the end of the whole list is marked by an additional
75 * NULL. The caller is responsible for freeing the buffer (ExFreePool)
76 * when it is no longer needed.
77 * If no device interfaces match the search criteria, this routine
78 * returns STATUS_SUCCESS and the string contains a single NULL
84 * The parameters PhysicalDeviceObject and Flags aren't correctly
85 * processed. Rest of the cases was tested under Windows(R) XP and
86 * the function worked correctly.
90 IoGetDeviceInterfaces(
91 IN CONST GUID
*InterfaceClassGuid
,
92 IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL
,
94 OUT PWSTR
*SymbolicLinkList
)
96 PWCHAR BaseKeyString
= L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\DeviceClasses\\";
97 PWCHAR BaseInterfaceString
= L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
98 UNICODE_STRING GuidString
;
99 UNICODE_STRING BaseKeyName
;
100 UNICODE_STRING AliasKeyName
;
101 UNICODE_STRING SymbolicLink
;
102 UNICODE_STRING Control
;
103 UNICODE_STRING SubKeyName
;
104 UNICODE_STRING SymbolicLinkKeyName
;
105 UNICODE_STRING ControlKeyName
;
106 UNICODE_STRING TempString
;
109 HANDLE SymbolicLinkKey
;
110 PKEY_FULL_INFORMATION fip
;
111 PKEY_FULL_INFORMATION bfip
= NULL
;
112 PKEY_BASIC_INFORMATION bip
;
113 PKEY_VALUE_PARTIAL_INFORMATION vpip
= NULL
;
114 PWCHAR SymLinkList
= NULL
;
115 ULONG SymLinkListSize
= 0;
120 OBJECT_ATTRIBUTES ObjectAttributes
;
122 Status
= RtlStringFromGUID(InterfaceClassGuid
, &GuidString
);
123 if (!NT_SUCCESS(Status
))
125 DPRINT("RtlStringFromGUID() Failed.\n");
126 return STATUS_INVALID_HANDLE
;
129 RtlInitUnicodeString(&AliasKeyName
, BaseInterfaceString
);
130 RtlInitUnicodeString(&SymbolicLink
, L
"SymbolicLink");
131 RtlInitUnicodeString(&Control
, L
"\\Control");
132 BaseKeyName
.Length
= wcslen(BaseKeyString
) * sizeof(WCHAR
);
133 BaseKeyName
.MaximumLength
= BaseKeyName
.Length
+ (38 * sizeof(WCHAR
));
134 BaseKeyName
.Buffer
= ExAllocatePool(
136 BaseKeyName
.MaximumLength
);
137 ASSERT(BaseKeyName
.Buffer
!= NULL
);
138 wcscpy(BaseKeyName
.Buffer
, BaseKeyString
);
139 RtlAppendUnicodeStringToString(&BaseKeyName
, &GuidString
);
141 if (PhysicalDeviceObject
)
143 WCHAR GuidBuffer
[40];
144 UNICODE_STRING PdoGuidString
;
146 RtlFreeUnicodeString(&BaseKeyName
);
149 PhysicalDeviceObject
,
150 DevicePropertyClassGuid
,
155 RtlInitUnicodeString(&PdoGuidString
, GuidBuffer
);
156 if (RtlCompareUnicodeString(&GuidString
, &PdoGuidString
, TRUE
))
158 DPRINT("Inconsistent Guid's asked for in IoGetDeviceInterfaces()\n");
159 return STATUS_INVALID_HANDLE
;
162 DPRINT("IoGetDeviceInterfaces() called with PDO, not implemented.\n");
163 return STATUS_NOT_IMPLEMENTED
;
167 InitializeObjectAttributes(
170 OBJ_CASE_INSENSITIVE
,
179 if (!NT_SUCCESS(Status
))
181 DPRINT("ZwOpenKey() Failed. (0x%X)\n", Status
);
182 RtlFreeUnicodeString(&BaseKeyName
);
193 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
195 DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status
);
196 RtlFreeUnicodeString(&BaseKeyName
);
197 ZwClose(InterfaceKey
);
201 fip
= (PKEY_FULL_INFORMATION
)ExAllocatePool(NonPagedPool
, Size
);
211 if (!NT_SUCCESS(Status
))
213 DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status
);
215 RtlFreeUnicodeString(&BaseKeyName
);
216 ZwClose(InterfaceKey
);
220 for (; i
< fip
->SubKeys
; i
++)
222 Status
= ZwEnumerateKey(
230 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
232 DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status
);
234 if (SymLinkList
!= NULL
)
235 ExFreePool(SymLinkList
);
236 RtlFreeUnicodeString(&BaseKeyName
);
237 ZwClose(InterfaceKey
);
241 bip
= (PKEY_BASIC_INFORMATION
)ExAllocatePool(NonPagedPool
, Size
);
244 Status
= ZwEnumerateKey(
252 if (!NT_SUCCESS(Status
))
254 DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status
);
257 if (SymLinkList
!= NULL
)
258 ExFreePool(SymLinkList
);
259 RtlFreeUnicodeString(&BaseKeyName
);
260 ZwClose(InterfaceKey
);
264 SubKeyName
.Length
= 0;
265 SubKeyName
.MaximumLength
= BaseKeyName
.Length
+ bip
->NameLength
+ sizeof(WCHAR
);
266 SubKeyName
.Buffer
= ExAllocatePool(NonPagedPool
, SubKeyName
.MaximumLength
);
267 ASSERT(SubKeyName
.Buffer
!= NULL
);
268 TempString
.Length
= TempString
.MaximumLength
= bip
->NameLength
;
269 TempString
.Buffer
= bip
->Name
;
270 RtlCopyUnicodeString(&SubKeyName
, &BaseKeyName
);
271 RtlAppendUnicodeToString(&SubKeyName
, L
"\\");
272 RtlAppendUnicodeStringToString(&SubKeyName
, &TempString
);
276 InitializeObjectAttributes(
279 OBJ_CASE_INSENSITIVE
,
288 if (!NT_SUCCESS(Status
))
290 DPRINT("ZwOpenKey() Failed. (0x%X)\n", Status
);
292 if (SymLinkList
!= NULL
)
293 ExFreePool(SymLinkList
);
294 RtlFreeUnicodeString(&SubKeyName
);
295 RtlFreeUnicodeString(&BaseKeyName
);
296 ZwClose(InterfaceKey
);
307 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
309 DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status
);
311 RtlFreeUnicodeString(&BaseKeyName
);
312 RtlFreeUnicodeString(&SubKeyName
);
314 ZwClose(InterfaceKey
);
318 bfip
= (PKEY_FULL_INFORMATION
)ExAllocatePool(NonPagedPool
, Size
);
319 ASSERT(bfip
!= NULL
);
328 if (!NT_SUCCESS(Status
))
330 DPRINT("ZwQueryKey() Failed. (0x%X)\n", Status
);
332 RtlFreeUnicodeString(&SubKeyName
);
333 RtlFreeUnicodeString(&BaseKeyName
);
335 ZwClose(InterfaceKey
);
339 for(j
= 0; j
< bfip
->SubKeys
; j
++)
341 Status
= ZwEnumerateKey(
349 if (Status
== STATUS_NO_MORE_ENTRIES
)
352 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
354 DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status
);
357 if (SymLinkList
!= NULL
)
358 ExFreePool(SymLinkList
);
359 RtlFreeUnicodeString(&SubKeyName
);
360 RtlFreeUnicodeString(&BaseKeyName
);
362 ZwClose(InterfaceKey
);
366 bip
= (PKEY_BASIC_INFORMATION
)ExAllocatePool(NonPagedPool
, Size
);
369 Status
= ZwEnumerateKey(
377 if (!NT_SUCCESS(Status
))
379 DPRINT("ZwEnumerateKey() Failed.(0x%X)\n", Status
);
383 if (SymLinkList
!= NULL
)
384 ExFreePool(SymLinkList
);
385 RtlFreeUnicodeString(&SubKeyName
);
386 RtlFreeUnicodeString(&BaseKeyName
);
388 ZwClose(InterfaceKey
);
392 if (!wcsncmp(bip
->Name
, L
"Control", bip
->NameLength
))
397 SymbolicLinkKeyName
.Length
= 0;
398 SymbolicLinkKeyName
.MaximumLength
= SubKeyName
.Length
+ bip
->NameLength
+ sizeof(WCHAR
);
399 SymbolicLinkKeyName
.Buffer
= ExAllocatePool(NonPagedPool
, SymbolicLinkKeyName
.MaximumLength
);
400 ASSERT(SymbolicLinkKeyName
.Buffer
!= NULL
);
401 TempString
.Length
= TempString
.MaximumLength
= bip
->NameLength
;
402 TempString
.Buffer
= bip
->Name
;
403 RtlCopyUnicodeString(&SymbolicLinkKeyName
, &SubKeyName
);
404 RtlAppendUnicodeToString(&SymbolicLinkKeyName
, L
"\\");
405 RtlAppendUnicodeStringToString(&SymbolicLinkKeyName
, &TempString
);
407 ControlKeyName
.Length
= 0;
408 ControlKeyName
.MaximumLength
= SymbolicLinkKeyName
.Length
+ Control
.Length
+ sizeof(WCHAR
);
409 ControlKeyName
.Buffer
= ExAllocatePool(NonPagedPool
, ControlKeyName
.MaximumLength
);
410 ASSERT(ControlKeyName
.Buffer
!= NULL
);
411 RtlCopyUnicodeString(&ControlKeyName
, &SymbolicLinkKeyName
);
412 RtlAppendUnicodeStringToString(&ControlKeyName
, &Control
);
416 InitializeObjectAttributes(
418 &SymbolicLinkKeyName
,
419 OBJ_CASE_INSENSITIVE
,
428 if (!NT_SUCCESS(Status
))
430 DPRINT("ZwOpenKey() Failed. (0x%X)\n", Status
);
433 if (SymLinkList
!= NULL
)
434 ExFreePool(SymLinkList
);
435 RtlFreeUnicodeString(&SymbolicLinkKeyName
);
436 RtlFreeUnicodeString(&SubKeyName
);
437 RtlFreeUnicodeString(&BaseKeyName
);
439 ZwClose(InterfaceKey
);
443 Status
= ZwQueryValueKey(
446 KeyValuePartialInformation
,
451 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
454 if (Status
!= STATUS_BUFFER_TOO_SMALL
)
456 DPRINT("ZwQueryValueKey() Failed.(0x%X)\n", Status
);
459 if (SymLinkList
!= NULL
)
460 ExFreePool(SymLinkList
);
461 RtlFreeUnicodeString(&SymbolicLinkKeyName
);
462 RtlFreeUnicodeString(&SubKeyName
);
463 RtlFreeUnicodeString(&BaseKeyName
);
464 ZwClose(SymbolicLinkKey
);
466 ZwClose(InterfaceKey
);
470 vpip
= (PKEY_VALUE_PARTIAL_INFORMATION
)ExAllocatePool(NonPagedPool
, Size
);
471 ASSERT(vpip
!= NULL
);
473 Status
= ZwQueryValueKey(
476 KeyValuePartialInformation
,
481 if (!NT_SUCCESS(Status
))
483 DPRINT("ZwQueryValueKey() Failed.(0x%X)\n", Status
);
487 if (SymLinkList
!= NULL
)
488 ExFreePool(SymLinkList
);
489 RtlFreeUnicodeString(&SymbolicLinkKeyName
);
490 RtlFreeUnicodeString(&SubKeyName
);
491 RtlFreeUnicodeString(&BaseKeyName
);
492 ZwClose(SymbolicLinkKey
);
494 ZwClose(InterfaceKey
);
498 Status
= RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE
, ControlKeyName
.Buffer
);
500 if (NT_SUCCESS(Status
))
502 /* Put the name in the string here */
503 if (SymLinkList
== NULL
)
505 SymLinkListSize
= vpip
->DataLength
;
506 SymLinkList
= ExAllocatePool(NonPagedPool
, SymLinkListSize
+ sizeof(WCHAR
));
507 ASSERT(SymLinkList
!= NULL
);
508 RtlCopyMemory(SymLinkList
, vpip
->Data
, vpip
->DataLength
);
509 SymLinkList
[vpip
->DataLength
/ sizeof(WCHAR
)] = 0;
510 SymLinkList
[1] = '?';
514 PWCHAR OldSymLinkList
;
515 ULONG OldSymLinkListSize
;
516 PWCHAR SymLinkListPtr
;
518 OldSymLinkList
= SymLinkList
;
519 OldSymLinkListSize
= SymLinkListSize
;
520 SymLinkListSize
+= vpip
->DataLength
;
521 SymLinkList
= ExAllocatePool(NonPagedPool
, SymLinkListSize
+ sizeof(WCHAR
));
522 ASSERT(SymLinkList
!= NULL
);
523 RtlCopyMemory(SymLinkList
, OldSymLinkList
, OldSymLinkListSize
);
524 ExFreePool(OldSymLinkList
);
525 SymLinkListPtr
= SymLinkList
+ (OldSymLinkListSize
/ sizeof(WCHAR
));
526 RtlCopyMemory(SymLinkListPtr
, vpip
->Data
, vpip
->DataLength
);
527 SymLinkListPtr
[vpip
->DataLength
/ sizeof(WCHAR
)] = 0;
528 SymLinkListPtr
[1] = '?';
532 RtlFreeUnicodeString(&SymbolicLinkKeyName
);
533 RtlFreeUnicodeString(&ControlKeyName
);
534 ZwClose(SymbolicLinkKey
);
538 RtlFreeUnicodeString(&SubKeyName
);
542 if (SymLinkList
!= NULL
)
544 SymLinkList
[SymLinkListSize
/ sizeof(WCHAR
)] = 0;
548 SymLinkList
= ExAllocatePool(NonPagedPool
, 2 * sizeof(WCHAR
));
552 *SymbolicLinkList
= SymLinkList
;
554 RtlFreeUnicodeString(&BaseKeyName
);
555 ZwClose(InterfaceKey
);
560 return STATUS_SUCCESS
;
568 IoRegisterDeviceInterface(
569 IN PDEVICE_OBJECT PhysicalDeviceObject
,
570 IN CONST GUID
*InterfaceClassGuid
,
571 IN PUNICODE_STRING ReferenceString OPTIONAL
,
572 OUT PUNICODE_STRING SymbolicLinkName
)
574 PWCHAR KeyNameString
= L
"\\Device\\Serenum";
576 DPRINT("IoRegisterDeviceInterface called (UNIMPLEMENTED)\n");
577 if (!memcmp(InterfaceClassGuid
, (LPGUID
)&GUID_SERENUM_BUS_ENUMERATOR
, sizeof(GUID
)))
579 RtlInitUnicodeString(SymbolicLinkName
, KeyNameString
);
580 return STATUS_SUCCESS
;
583 return STATUS_INVALID_DEVICE_REQUEST
;
591 IoSetDeviceInterfaceState(
592 IN PUNICODE_STRING SymbolicLinkName
,
595 return STATUS_NOT_IMPLEMENTED
;