1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/legacy/wdmaud/deviface.c
5 * PURPOSE: System Audio graph builder
6 * PROGRAMMER: Andrew Greenwood
7 * Johannes Anderwald
8 */
9
10 #include "wdmaud.h"
11
12 #define NDEBUG
13 #include <debug.h>
14
15 NTSTATUS
WdmAudOpenSysAudioDevice(IN LPWSTR DeviceName,OUT PHANDLE Handle)16 WdmAudOpenSysAudioDevice(
17 IN LPWSTR DeviceName,
18 OUT PHANDLE Handle)
19 {
20 UNICODE_STRING SymbolicLink;
21 OBJECT_ATTRIBUTES ObjectAttributes;
22 IO_STATUS_BLOCK IoStatusBlock;
23 NTSTATUS Status;
24
25 RtlInitUnicodeString(&SymbolicLink, DeviceName);
26 InitializeObjectAttributes(&ObjectAttributes, &SymbolicLink, OBJ_OPENIF | OBJ_KERNEL_HANDLE, NULL, NULL);
27
28 Status = IoCreateFile(Handle,
29 SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
30 &ObjectAttributes,
31 &IoStatusBlock,
32 NULL,
33 0,
34 0,
35 FILE_OPEN,
36 FILE_SYNCHRONOUS_IO_NONALERT,
37 NULL,
38 0,
39 CreateFileTypeNone,
40 NULL,
41 IO_NO_PARAMETER_CHECKING | IO_FORCE_ACCESS_CHECK);
42
43 return Status;
44 }
45
46 NTSTATUS
47 NTAPI
DeviceInterfaceChangeCallback(IN PVOID NotificationStructure,IN PVOID Context)48 DeviceInterfaceChangeCallback(
49 IN PVOID NotificationStructure,
50 IN PVOID Context)
51 {
52 DEVICE_INTERFACE_CHANGE_NOTIFICATION * Event = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)NotificationStructure;
53
54 DPRINT1("DeviceInterfaceChangeCallback called %p\n", Event);
55 DbgBreakPoint();
56 return STATUS_SUCCESS;
57 }
58
59 NTSTATUS
WdmAudOpenSysAudioDeviceInterfaces(IN PWDMAUD_DEVICE_EXTENSION DeviceExtension,IN LPWSTR SymbolicLinkList)60 WdmAudOpenSysAudioDeviceInterfaces(
61 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension,
62 IN LPWSTR SymbolicLinkList)
63 {
64 SYSAUDIO_ENTRY * Entry;
65 ULONG Length;
66
67 DPRINT1("WdmAudOpenSysAudioDeviceInterfaces called\n");
68
69 while(*SymbolicLinkList)
70 {
71 Length = wcslen(SymbolicLinkList) + 1;
72 Entry = (SYSAUDIO_ENTRY*)AllocateItem(NonPagedPool, sizeof(SYSAUDIO_ENTRY) + Length * sizeof(WCHAR));
73 if (!Entry)
74 {
75 return STATUS_INSUFFICIENT_RESOURCES;
76 }
77
78 Entry->SymbolicLink.Length = Length * sizeof(WCHAR);
79 Entry->SymbolicLink.MaximumLength = Length * sizeof(WCHAR);
80 Entry->SymbolicLink.Buffer = (LPWSTR) (Entry + 1);
81 wcscpy(Entry->SymbolicLink.Buffer, SymbolicLinkList);
82
83 InsertTailList(&DeviceExtension->SysAudioDeviceList, &Entry->Entry);
84
85 DeviceExtension->NumSysAudioDevices++;
86 SymbolicLinkList += Length;
87 }
88 return STATUS_SUCCESS;
89 }
90
91
92 NTSTATUS
WdmAudOpenSysAudioDevices(IN PDEVICE_OBJECT DeviceObject,IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)93 WdmAudOpenSysAudioDevices(
94 IN PDEVICE_OBJECT DeviceObject,
95 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
96 {
97 NTSTATUS Status = STATUS_SUCCESS;
98 LPWSTR SymbolicLinkList;
99 SYSAUDIO_ENTRY * Entry;
100 ULONG Length;
101 HANDLE hSysAudio;
102 PFILE_OBJECT FileObject;
103 UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\sysaudio\\GLOBAL");
104
105 if (DeviceExtension->DeviceInterfaceSupport)
106 {
107 Status = IoGetDeviceInterfaces(&KSCATEGORY_SYSAUDIO,
108 NULL,
109 0,
110 &SymbolicLinkList);
111
112 if (NT_SUCCESS(Status))
113 {
114 WdmAudOpenSysAudioDeviceInterfaces(DeviceExtension, SymbolicLinkList);
115 FreeItem(SymbolicLinkList);
116 }
117
118
119 Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
120 PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
121 (PVOID)&KSCATEGORY_SYSAUDIO,
122 DeviceObject->DriverObject,
123 DeviceInterfaceChangeCallback,
124 (PVOID)DeviceExtension,
125 &DeviceExtension->SysAudioNotification);
126 }
127 else
128 {
129 Entry = (SYSAUDIO_ENTRY*)AllocateItem(NonPagedPool, sizeof(SYSAUDIO_ENTRY));
130 if (!Entry)
131 {
132 return STATUS_INSUFFICIENT_RESOURCES;
133 }
134
135
136 Length = wcslen(DeviceName.Buffer) + 1;
137 Entry->SymbolicLink.Length = 0;
138 Entry->SymbolicLink.MaximumLength = Length * sizeof(WCHAR);
139 Entry->SymbolicLink.Buffer = AllocateItem(NonPagedPool, Entry->SymbolicLink.MaximumLength);
140
141 if (!Entry->SymbolicLink.Buffer)
142 {
143 FreeItem(Entry);
144 return STATUS_INSUFFICIENT_RESOURCES;
145 }
146
147 Status = RtlAppendUnicodeStringToString(&Entry->SymbolicLink, &DeviceName);
148
149 if (!NT_SUCCESS(Status))
150 {
151 FreeItem(Entry->SymbolicLink.Buffer);
152 FreeItem(Entry);
153 return Status;
154 }
155
156 DPRINT("Opening device %S\n", Entry->SymbolicLink.Buffer);
157 Status = WdmAudOpenSysAudioDevice(Entry->SymbolicLink.Buffer, &hSysAudio);
158 if (!NT_SUCCESS(Status))
159 {
160 DPRINT1("Failed to open sysaudio %x\n", Status);
161 FreeItem(Entry->SymbolicLink.Buffer);
162 FreeItem(Entry);
163 return Status;
164 }
165
166 InsertTailList(&DeviceExtension->SysAudioDeviceList, &Entry->Entry);
167 DeviceExtension->NumSysAudioDevices++;
168
169 /* get the file object */
170 Status = ObReferenceObjectByHandle(hSysAudio, FILE_READ_DATA | FILE_WRITE_DATA, *IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
171 if (!NT_SUCCESS(Status))
172 {
173 DPRINT1("Failed to reference FileObject %x\n", Status);
174 ZwClose(hSysAudio);
175 return Status;
176 }
177 DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
178 DeviceExtension->hSysAudio = hSysAudio;
179 DeviceExtension->FileObject = FileObject;
180 }
181
182 return Status;
183 }
184
185 NTSTATUS
WdmAudRegisterDeviceInterface(IN PDEVICE_OBJECT PhysicalDeviceObject,IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)186 WdmAudRegisterDeviceInterface(
187 IN PDEVICE_OBJECT PhysicalDeviceObject,
188 IN PWDMAUD_DEVICE_EXTENSION DeviceExtension)
189 {
190 NTSTATUS Status;
191 UNICODE_STRING SymbolicLinkName;
192
193 Status = IoRegisterDeviceInterface(PhysicalDeviceObject, &KSCATEGORY_WDMAUD, NULL, &SymbolicLinkName);
194 if (NT_SUCCESS(Status))
195 {
196 IoSetDeviceInterfaceState(&SymbolicLinkName, TRUE);
197 RtlFreeUnicodeString(&SymbolicLinkName);
198 //DeviceExtension->DeviceInterfaceSupport = TRUE;
199 return Status;
200 }
201
202 return Status;
203 }
204
205 NTSTATUS
WdmAudOpenSysaudio(IN PDEVICE_OBJECT DeviceObject,IN PWDMAUD_CLIENT * pClient)206 WdmAudOpenSysaudio(
207 IN PDEVICE_OBJECT DeviceObject,
208 IN PWDMAUD_CLIENT *pClient)
209 {
210 PWDMAUD_CLIENT Client;
211 PWDMAUD_DEVICE_EXTENSION DeviceExtension;
212
213 /* get device extension */
214 DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
215
216 if (!DeviceExtension->NumSysAudioDevices)
217 {
218 /* wdmaud failed to open sysaudio */
219 return STATUS_UNSUCCESSFUL;
220 }
221
222 /* sanity check */
223 ASSERT(!IsListEmpty(&DeviceExtension->SysAudioDeviceList));
224
225 /* allocate client context struct */
226 Client = AllocateItem(NonPagedPool, sizeof(WDMAUD_CLIENT));
227
228 /* check for allocation failure */
229 if (!Client)
230 {
231 /* not enough memory */
232 return STATUS_INSUFFICIENT_RESOURCES;
233 }
234
235 /* zero client context struct */
236 RtlZeroMemory(Client, sizeof(WDMAUD_CLIENT));
237
238 /* initialize mixer event list */
239 InitializeListHead(&Client->MixerEventList);
240
241 /* store result */
242 *pClient = Client;
243
244 /* insert client into list */
245 ExInterlockedInsertTailList(&DeviceExtension->WdmAudClientList, &Client->Entry, &DeviceExtension->Lock);
246
247 /* done */
248 return STATUS_SUCCESS;
249 }
250