32d6ed860862cc123d5741139ca01547f52066a2
[reactos.git] / reactos / drivers / wdm / audio / sysaudio / control.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/sysaudio/control.c
5 * PURPOSE: System Audio graph builder
6 * PROGRAMMER: Johannes Anderwald
7 */
8
9 #include "sysaudio.h"
10
11 const GUID KSPROPSETID_Sysaudio = {0xCBE3FAA0L, 0xCC75, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
12 const GUID KSPROPSETID_Sysaudio_Pin = {0xA3A53220L, 0xC6E4, 0x11D0, {0xB4, 0x65, 0x00, 0x00, 0x1A, 0x18, 0x18, 0xE6}};
13 const GUID KSPROPSETID_General = {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
14 const GUID KSPROPSETID_Pin = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
15 const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
16 const GUID KSPROPSETID_Topology = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
17 const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
18 const GUID KSDATAFORMAT_SUBTYPE_PCM = {0x00000001L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
19 const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}};
20
21 NTSTATUS
22 SetIrpIoStatus(
23 IN PIRP Irp,
24 IN NTSTATUS Status,
25 IN ULONG Length)
26 {
27 Irp->IoStatus.Information = Length;
28 Irp->IoStatus.Status = Status;
29 if (Status != STATUS_PENDING)
30 {
31 IoCompleteRequest(Irp, IO_NO_INCREMENT);
32 }
33 else
34 {
35 IoMarkIrpPending(Irp);
36 }
37 return Status;
38
39 }
40
41 PKSAUDIO_DEVICE_ENTRY
42 GetListEntry(
43 IN PLIST_ENTRY Head,
44 IN ULONG Index)
45 {
46 PLIST_ENTRY Entry = Head->Flink;
47
48 while(Index-- && Entry != Head)
49 Entry = Entry->Flink;
50
51 if (Entry == Head)
52 return NULL;
53
54 return (PKSAUDIO_DEVICE_ENTRY)CONTAINING_RECORD(Entry, KSAUDIO_DEVICE_ENTRY, Entry);
55 }
56
57 NTSTATUS
58 SysAudioOpenVirtualDevice(
59 IN PIRP Irp,
60 IN ULONG DeviceNumber,
61 PSYSAUDIODEVEXT DeviceExtension)
62 {
63 PKSAUDIO_DEVICE_ENTRY Entry;
64 PIO_STACK_LOCATION IoStack;
65
66 /* get current irp stack */
67 IoStack = IoGetCurrentIrpStackLocation(Irp);
68
69 /* sanity check */
70 ASSERT(IoStack->FileObject);
71
72 if (DeviceNumber >= DeviceExtension->NumberOfKsAudioDevices)
73 {
74 /* invalid device index */
75 return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
76 }
77
78 /* get device context */
79 Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, DeviceNumber);
80 ASSERT(Entry != NULL);
81
82 /* store device entry in FsContext2
83 * see pin.c DispatchCreateSysAudioPin for details
84 */
85 IoStack->FileObject->FsContext2 = (PVOID)Entry;
86
87 return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0);
88 }
89
90 NTSTATUS
91 HandleSysAudioFilterPinProperties(
92 PIRP Irp,
93 PKSPROPERTY Property,
94 PSYSAUDIODEVEXT DeviceExtension)
95 {
96 PIO_STACK_LOCATION IoStack;
97 NTSTATUS Status;
98 PKSAUDIO_DEVICE_ENTRY Entry;
99 ULONG BytesReturned;
100 PKSP_PIN Pin;
101
102 // in order to access pin properties of a sysaudio device
103 // the caller must provide a KSP_PIN struct, where
104 // Reserved member points to virtual device index
105
106 IoStack = IoGetCurrentIrpStackLocation(Irp);
107 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSP_PIN))
108 {
109 /* too small buffer */
110 return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSPROPERTY) + sizeof(ULONG));
111 }
112
113 Pin = (PKSP_PIN)Property;
114
115 Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, ((KSP_PIN*)Property)->Reserved);
116 if (!Entry)
117 {
118 /* invalid device index */
119 return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
120 }
121
122 if (!Entry->Pins)
123 {
124 /* expected pins */
125 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
126 }
127
128 if (Entry->PinDescriptorsCount <= Pin->PinId)
129 {
130 /* invalid pin id */
131 return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
132 }
133
134 if (Property->Id == KSPROPERTY_PIN_CTYPES)
135 {
136 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
137 {
138 /* too small buffer */
139 return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(ULONG));
140 }
141 /* store result */
142 *((PULONG)Irp->UserBuffer) = Entry->PinDescriptorsCount;
143 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(ULONG));
144 }
145 else if (Property->Id == KSPROPERTY_PIN_COMMUNICATION)
146 {
147 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSPIN_COMMUNICATION))
148 {
149 /* too small buffer */
150 return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSPIN_COMMUNICATION));
151 }
152 /* store result */
153 *((KSPIN_COMMUNICATION*)Irp->UserBuffer) = Entry->PinDescriptors[Pin->PinId].Communication;
154 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(KSPIN_COMMUNICATION));
155
156 }
157 else if (Property->Id == KSPROPERTY_PIN_DATAFLOW)
158 {
159 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSPIN_DATAFLOW))
160 {
161 /* too small buffer */
162 return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSPIN_DATAFLOW));
163 }
164 /* store result */
165 *((KSPIN_DATAFLOW*)Irp->UserBuffer) = Entry->PinDescriptors[Pin->PinId].DataFlow;
166 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(KSPIN_DATAFLOW));
167 }
168 else
169 {
170 /* forward request to the filter implementing the property */
171 Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY,
172 (PVOID)IoStack->Parameters.DeviceIoControl.Type3InputBuffer,
173 IoStack->Parameters.DeviceIoControl.InputBufferLength,
174 Irp->UserBuffer,
175 IoStack->Parameters.DeviceIoControl.OutputBufferLength,
176 &BytesReturned);
177
178 return SetIrpIoStatus(Irp, Status, BytesReturned);
179 }
180 }
181
182
183 NTSTATUS
184 ComputeCompatibleFormat(
185 IN PKSAUDIO_DEVICE_ENTRY Entry,
186 IN ULONG PinId,
187 IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat,
188 OUT PKSDATAFORMAT_WAVEFORMATEX MixerFormat)
189 {
190 BOOL bFound;
191 ULONG BytesReturned;
192 PKSP_PIN PinRequest;
193 NTSTATUS Status;
194 PKSMULTIPLE_ITEM MultipleItem;
195 ULONG Length;
196 PKSDATARANGE_AUDIO AudioRange;
197 ULONG Index;
198
199 Length = sizeof(KSP_PIN) + sizeof(KSMULTIPLE_ITEM) + ClientFormat->DataFormat.FormatSize;
200 PinRequest = ExAllocatePool(NonPagedPool, Length);
201 if (!PinRequest)
202 return STATUS_UNSUCCESSFUL;
203
204 PinRequest->PinId = PinId;
205 PinRequest->Property.Set = KSPROPSETID_Pin;
206 PinRequest->Property.Flags = KSPROPERTY_TYPE_GET;
207 PinRequest->Property.Id = KSPROPERTY_PIN_DATAINTERSECTION;
208
209 MultipleItem = (PKSMULTIPLE_ITEM)(PinRequest + 1);
210 MultipleItem->Count = 1;
211 MultipleItem->Size = sizeof(KSMULTIPLE_ITEM) + ClientFormat->DataFormat.FormatSize;
212
213 RtlMoveMemory(MultipleItem + 1, ClientFormat, ClientFormat->DataFormat.FormatSize);
214 /* Query the miniport data intersection handler */
215 Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)PinRequest, Length, (PVOID)MixerFormat, sizeof(KSDATAFORMAT_WAVEFORMATEX), &BytesReturned);
216
217 DPRINT("Status %x\n", Status);
218
219 if (NT_SUCCESS(Status))
220 {
221 ExFreePool(PinRequest);
222 return Status;
223 }
224
225 /* Setup request block */
226 PinRequest->Property.Id = KSPROPERTY_PIN_DATARANGES;
227 /* Query pin data ranges */
228 Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)PinRequest, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
229
230 if (Status != STATUS_BUFFER_TOO_SMALL)
231 {
232 /* Failed to data ranges */
233 return Status;
234 }
235
236 MultipleItem = ExAllocatePool(NonPagedPool, BytesReturned);
237 if (!MultipleItem)
238 {
239 ExFreePool(PinRequest);
240 return STATUS_NO_MEMORY;
241 }
242
243 Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)PinRequest, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
244 if (!NT_SUCCESS(Status))
245 {
246 DPRINT("Property Request KSPROPERTY_PIN_DATARANGES failed with %x\n", Status);
247 ExFreePool(MultipleItem);
248 ExFreePool(PinRequest);
249 return STATUS_UNSUCCESSFUL;
250 }
251
252 AudioRange = (PKSDATARANGE_AUDIO)(MultipleItem + 1);
253 bFound = FALSE;
254 for(Index = 0; Index < MultipleItem->Count; Index++)
255 {
256 if (AudioRange->DataRange.FormatSize != sizeof(KSDATARANGE_AUDIO))
257 {
258 UNIMPLEMENTED
259 AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize);
260 continue;
261 }
262 /* Select best quality available */
263
264 MixerFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX);
265 MixerFormat->DataFormat.Flags = 0;
266 MixerFormat->DataFormat.Reserved = 0;
267 MixerFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO;
268 MixerFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
269 MixerFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX;
270 MixerFormat->DataFormat.SampleSize = 4;
271 MixerFormat->WaveFormatEx.wFormatTag = ClientFormat->WaveFormatEx.wFormatTag;
272 #ifndef NO_AC97_HACK
273 /* HACK: AC97 does not support mono render / record */
274 MixerFormat->WaveFormatEx.nChannels = 2;
275 /*HACK: AC97 only supports 16-Bit Bits */
276 MixerFormat->WaveFormatEx.wBitsPerSample = 16;
277
278 #else
279 MixerFormat->WaveFormatEx.nChannels = min(ClientFormat->WaveFormatEx.nSamplesPerSec, AudioRange->MaximumChannels);
280 MixerFormat->WaveFormatEx.wBitsPerSample = AudioRange->MaximumBitsPerSample;
281 #endif
282
283 #ifdef KMIXER_RESAMPLING_IMPLEMENTED
284 MixerFormat->WaveFormatEx.nSamplesPerSec = AudioRange->MaximumSampleFrequency;
285 #else
286 MixerFormat->WaveFormatEx.nSamplesPerSec = max(AudioRange->MinimumSampleFrequency, min(ClientFormat->WaveFormatEx.nSamplesPerSec, AudioRange->MaximumSampleFrequency));
287 #endif
288
289 MixerFormat->WaveFormatEx.cbSize = 0;
290 MixerFormat->WaveFormatEx.nBlockAlign = (MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.wBitsPerSample) / 8;
291 MixerFormat->WaveFormatEx.nAvgBytesPerSec = MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.nSamplesPerSec * (MixerFormat->WaveFormatEx.wBitsPerSample / 8);
292
293 bFound = TRUE;
294 break;
295
296 AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize);
297 }
298
299 #if 0
300 DPRINT1("\nNum Max Channels %u Channels %u Old Channels %u\n Max SampleRate %u SampleRate %u Old SampleRate %u\n Max BitsPerSample %u BitsPerSample %u Old BitsPerSample %u\n",
301 AudioRange->MaximumChannels, MixerFormat->WaveFormatEx.nChannels, ClientFormat->WaveFormatEx.nChannels,
302 AudioRange->MaximumSampleFrequency, MixerFormat->WaveFormatEx.nSamplesPerSec, ClientFormat->WaveFormatEx.nSamplesPerSec,
303 AudioRange->MaximumBitsPerSample, MixerFormat->WaveFormatEx.wBitsPerSample, ClientFormat->WaveFormatEx.wBitsPerSample);
304
305
306 #endif
307
308 ExFreePool(MultipleItem);
309 ExFreePool(PinRequest);
310
311 if (bFound)
312 return STATUS_SUCCESS;
313 else
314 return STATUS_NOT_IMPLEMENTED;
315 }
316
317 NTSTATUS
318 GetPinInstanceCount(
319 PKSAUDIO_DEVICE_ENTRY Entry,
320 PKSPIN_CINSTANCES PinInstances,
321 PKSPIN_CONNECT PinConnect)
322 {
323 KSP_PIN PinRequest;
324 ULONG BytesReturned;
325
326 /* query the instance count */
327 PinRequest.PinId = PinConnect->PinId;
328 PinRequest.Property.Set = KSPROPSETID_Pin;
329 PinRequest.Property.Flags = KSPROPERTY_TYPE_GET;
330 PinRequest.Property.Id = KSPROPERTY_PIN_CINSTANCES;
331
332 return KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)PinInstances, sizeof(KSPIN_CINSTANCES), &BytesReturned);
333
334 }
335
336 NTSTATUS
337 SysAudioHandleProperty(
338 PDEVICE_OBJECT DeviceObject,
339 PIRP Irp)
340 {
341 PIO_STACK_LOCATION IoStack;
342 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
343 KSPROPERTY PropertyRequest;
344 KSCOMPONENTID ComponentId;
345 PULONG Index;
346 PKSPROPERTY Property;
347 PSYSAUDIODEVEXT DeviceExtension;
348 PKSAUDIO_DEVICE_ENTRY Entry;
349 PSYSAUDIO_INSTANCE_INFO InstanceInfo;
350 ULONG BytesReturned;
351 PKSOBJECT_CREATE_ITEM CreateItem;
352 UNICODE_STRING GuidString;
353 PKSP_PIN Pin;
354 LPWSTR DeviceName;
355
356 /* access the create item */
357 CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
358
359 IoStack = IoGetCurrentIrpStackLocation(Irp);
360
361 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
362 {
363 /* buffer must be at least of sizeof KSPROPERTY */
364 return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSPROPERTY));
365 }
366
367 Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
368 DeviceExtension = (PSYSAUDIODEVEXT)DeviceObject->DeviceExtension;
369
370 if (IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Pin))
371 {
372 return HandleSysAudioFilterPinProperties(Irp, Property, DeviceExtension);
373 }
374 else if(IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Topology))
375 {
376 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSP_PIN))
377 {
378 /* too small buffer */
379 return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSP_PIN));
380 }
381 Pin = (PKSP_PIN)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
382 Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, Pin->Reserved);
383 ASSERT(Entry != NULL);
384
385 /* forward request to the filter implementing the property */
386 Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY,
387 (PVOID)IoStack->Parameters.DeviceIoControl.Type3InputBuffer,
388 IoStack->Parameters.DeviceIoControl.InputBufferLength,
389 Irp->UserBuffer,
390 IoStack->Parameters.DeviceIoControl.OutputBufferLength,
391 &BytesReturned);
392
393 return SetIrpIoStatus(Irp, Status, BytesReturned);
394 }
395 else if (IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Sysaudio))
396 {
397 if (Property->Id == KSPROPERTY_SYSAUDIO_DEVICE_INTERFACE_NAME)
398 {
399 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY) + sizeof(ULONG))
400 {
401 /* invalid request */
402 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, sizeof(KSPROPERTY) + sizeof(ULONG));
403 }
404 Index = (PULONG)(Property + 1);
405
406 if (DeviceExtension->NumberOfKsAudioDevices <= *Index)
407 {
408 /* invalid index */
409 return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
410 }
411
412 Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, *Index);
413 ASSERT(Entry != NULL);
414
415 BytesReturned = Entry->DeviceName.Length + sizeof(WCHAR);
416 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < BytesReturned)
417 {
418 /* too small buffer */
419 return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, BytesReturned);
420 }
421
422 /* copy device name */
423 DeviceName = (LPWSTR)Irp->UserBuffer;
424
425 RtlMoveMemory(DeviceName, Entry->DeviceName.Buffer, Entry->DeviceName.Length);
426 DeviceName[Entry->DeviceName.Length / sizeof(WCHAR)] = L'\0';
427 return SetIrpIoStatus(Irp, STATUS_SUCCESS, BytesReturned);
428 }
429
430 if (Property->Id == KSPROPERTY_SYSAUDIO_COMPONENT_ID)
431 {
432 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY) + sizeof(ULONG))
433 {
434 /* too small buffer */
435 return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSPROPERTY) + sizeof(ULONG));
436 }
437
438 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(KSCOMPONENTID))
439 {
440 /* too small buffer */
441 return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(KSCOMPONENTID));
442 }
443
444 Index = (PULONG)(Property + 1);
445
446 if (DeviceExtension->NumberOfKsAudioDevices <= *Index)
447 {
448 /* invalid index */
449 return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0);
450 }
451 Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, *Index);
452 ASSERT(Entry != NULL);
453
454 PropertyRequest.Set = KSPROPSETID_General;
455 PropertyRequest.Id = KSPROPERTY_GENERAL_COMPONENTID;
456 PropertyRequest.Flags = KSPROPERTY_TYPE_GET;
457
458 /* call the filter */
459 Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PropertyRequest, sizeof(KSPROPERTY), (PVOID)&ComponentId, sizeof(KSCOMPONENTID), &BytesReturned);
460 if (!NT_SUCCESS(Status))
461 {
462 DPRINT("KsSynchronousIoControlDevice failed with %x for KSPROPERTY_GENERAL_COMPONENTID\n", Status);
463 return SetIrpIoStatus(Irp, Status, 0);
464 }
465 RtlMoveMemory(Irp->UserBuffer, &ComponentId, sizeof(KSCOMPONENTID));
466 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(KSCOMPONENTID));
467 }
468 else if (Property->Id == KSPROPERTY_SYSAUDIO_DEVICE_COUNT)
469 {
470 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
471 {
472 /* too small buffer */
473 return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(ULONG));
474 }
475
476 *((PULONG)Irp->UserBuffer) = DeviceExtension->NumberOfKsAudioDevices;
477 return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(ULONG));
478 }
479 else if (Property->Id == KSPROPERTY_SYSAUDIO_DEVICE_INSTANCE)
480 {
481 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
482 {
483 /* too small buffer */
484 return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(ULONG));
485 }
486
487 if (Property->Flags & KSPROPERTY_TYPE_SET)
488 {
489 Index = (PULONG)Irp->UserBuffer;
490 return SysAudioOpenVirtualDevice(Irp, *Index, DeviceExtension);
491 }
492 }
493 else if (Property->Id == KSPROPERTY_SYSAUDIO_INSTANCE_INFO)
494 {
495 if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SYSAUDIO_INSTANCE_INFO))
496 {
497 /* too small buffer */
498 return SetIrpIoStatus(Irp, STATUS_BUFFER_TOO_SMALL, sizeof(SYSAUDIO_INSTANCE_INFO));
499 }
500
501 /* get input parameter */
502 InstanceInfo = (PSYSAUDIO_INSTANCE_INFO)Property;
503
504 if (Property->Flags & KSPROPERTY_TYPE_SET)
505 {
506 return SysAudioOpenVirtualDevice(Irp, InstanceInfo->DeviceNumber, DeviceExtension);
507 }
508 }
509 }
510
511 RtlStringFromGUID(&Property->Set, &GuidString);
512 DPRINT1("Unhandeled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
513 RtlFreeUnicodeString(&GuidString);
514 return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0);
515 }