2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/legacy/wdmaud/main.c
5 * PURPOSE: System Audio graph builder
6 * PROGRAMMER: Andrew Greenwood
11 const GUID KSCATEGORY_SYSAUDIO
= {0xA7C7A5B1L
, 0x5AF3, 0x11D1, {0x9C, 0xED, 0x00, 0xA0, 0x24, 0xBF, 0x04, 0x07}};
12 const GUID KSCATEGORY_WDMAUD
= {0x3E227E76L
, 0x690D, 0x11D2, {0x81, 0x61, 0x00, 0x00, 0xF8, 0x77, 0x5B, 0xF1}};
17 IN PDRIVER_OBJECT DriverObject
)
19 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\wdmaud");
20 UNICODE_STRING SymlinkName
= RTL_CONSTANT_STRING(L
"\\DosDevices\\wdmaud");
21 PDEVICE_OBJECT DeviceObject
;
23 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
25 DPRINT("WdmAudInstallDevice called\n");
27 Status
= IoCreateDevice(DriverObject
,
28 sizeof(WDMAUD_DEVICE_EXTENSION
),
35 if (!NT_SUCCESS(Status
))
37 DPRINT1("IoCreateDevice failed with %x\n", Status
);
41 /* clear device extension */
42 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
43 RtlZeroMemory(DeviceExtension
, sizeof(WDMAUD_DEVICE_EXTENSION
));
45 /* register device interfaces */
46 Status
= WdmAudRegisterDeviceInterface(DeviceObject
, DeviceExtension
);
47 if (!NT_SUCCESS(Status
))
49 DPRINT1("WdmRegisterDeviceInterface failed with %x\n", Status
);
50 IoDeleteDevice(DeviceObject
);
54 /* initialize sysaudio device list */
55 InitializeListHead(&DeviceExtension
->SysAudioDeviceList
);
57 /* initialize client context device list */
58 InitializeListHead(&DeviceExtension
->WdmAudClientList
);
60 /* initialize spinlock */
61 KeInitializeSpinLock(&DeviceExtension
->Lock
);
63 /* find available sysaudio devices */
64 Status
= WdmAudOpenSysAudioDevices(DeviceObject
, DeviceExtension
);
65 if (!NT_SUCCESS(Status
))
67 DPRINT1("WdmAudOpenSysAudioDevices failed with %x\n", Status
);
68 IoDeleteSymbolicLink(&SymlinkName
);
69 IoDeleteDevice(DeviceObject
);
72 /* allocate ks device header */
73 Status
= KsAllocateDeviceHeader(&DeviceExtension
->DeviceHeader
, 0, NULL
);
74 if (!NT_SUCCESS(Status
))
76 DPRINT1("KsAllocateDeviceHeader failed with %x\n", Status
);
77 IoDeleteSymbolicLink(&SymlinkName
);
78 IoDeleteDevice(DeviceObject
);
82 Status
= WdmAudMixerInitialize(DeviceObject
);
83 DPRINT("WdmAudMixerInitialize Status %x\n", Status
);
84 Status
= WdmAudWaveInitialize(DeviceObject
);
85 DPRINT("WdmAudWaveInitialize Status %x\n", Status
);
87 DeviceObject
->Flags
|= DO_DIRECT_IO
| DO_POWER_PAGABLE
;
88 DeviceObject
->Flags
&= ~ DO_DEVICE_INITIALIZING
;
90 return STATUS_SUCCESS
;
96 IN PDRIVER_OBJECT driver
)
98 DPRINT("WdmAudUnload called\n");
104 IN PDEVICE_OBJECT DeviceObject
,
107 PIO_STACK_LOCATION IrpStack
;
109 DPRINT("WdmAudPnp called\n");
111 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
113 if (IrpStack
->MinorFunction
== IRP_MN_QUERY_PNP_DEVICE_STATE
)
115 Irp
->IoStatus
.Information
|= PNP_DEVICE_NOT_DISABLEABLE
;
116 return KsDefaultDispatchPnp(DeviceObject
, Irp
);
118 return KsDefaultDispatchPnp(DeviceObject
, Irp
);
125 IN PDEVICE_OBJECT DeviceObject
,
129 PIO_STACK_LOCATION IoStack
;
130 PWDMAUD_CLIENT pClient
;
131 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
133 /* get device extension */
134 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
137 Status
= KsReferenceSoftwareBusObject((KSDEVICE_HEADER
)DeviceObject
->DeviceExtension
);
138 if (!NT_SUCCESS(Status
))
140 DPRINT1("KsReferenceSoftwareBusObject failed with %x\n", Status
);
145 Status
= WdmAudOpenSysaudio(DeviceObject
, &pClient
);
146 if (!NT_SUCCESS(Status
))
148 DPRINT1("Failed to open sysaudio!\n");
150 /* complete and forget */
151 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
152 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
154 return STATUS_UNSUCCESSFUL
;
157 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
158 ASSERT(IoStack
->FileObject
);
160 /* store client context in file object */
161 IoStack
->FileObject
->FsContext
= pClient
;
162 Status
= STATUS_SUCCESS
;
164 Irp
->IoStatus
.Status
= Status
;
165 Irp
->IoStatus
.Information
= 0;
166 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
174 IN PDEVICE_OBJECT DeviceObject
,
177 /* nothing to do complete request */
179 Status
= KsDereferenceSoftwareBusObject(DeviceExtension
->DeviceHeader
);
181 if (NT_SUCCESS(Status
))
183 if (DeviceExtension
->SysAudioNotification
)
184 Status
= IoUnregisterPlugPlayNotification(DeviceExtension
->SysAudioNotification
);
188 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
189 Irp
->IoStatus
.Information
= 0;
190 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
193 return STATUS_SUCCESS
;
199 IN PDEVICE_OBJECT DeviceObject
,
202 PIO_STACK_LOCATION IoStack
;
203 PWDMAUD_CLIENT pClient
;
204 PWDMAUD_DEVICE_EXTENSION DeviceExtension
;
208 /* get device extension */
209 DeviceExtension
= (PWDMAUD_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
211 /* get current irp stack location */
212 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
215 ASSERT(IoStack
->FileObject
);
217 /* get client context struct */
218 pClient
= (PWDMAUD_CLIENT
)IoStack
->FileObject
->FsContext
;
223 /* acquire client context list lock */
224 KeAcquireSpinLock(&DeviceExtension
->Lock
, &OldIrql
);
227 RemoveEntryList(&pClient
->Entry
);
230 KeReleaseSpinLock(&DeviceExtension
->Lock
, OldIrql
);
232 /* check if all audio pins have been closed */
233 for (Index
= 0; Index
< pClient
->NumPins
; Index
++)
235 DPRINT("Index %u Pin %p Type %x\n", Index
, pClient
->hPins
[Index
].Handle
, pClient
->hPins
[Index
].Type
);
236 if (pClient
->hPins
[Index
].Handle
&& pClient
->hPins
[Index
].Type
!= MIXER_DEVICE_TYPE
)
238 /* found an still open audio pin */
239 ZwClose(pClient
->hPins
[Index
].Handle
);
245 ExFreePool(pClient
->hPins
);
247 /* free client context struct */
250 /* clear old client pointer */
251 IoStack
->FileObject
->FsContext
= NULL
;
253 /* complete request */
254 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
255 Irp
->IoStatus
.Information
= 0;
256 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
259 return STATUS_SUCCESS
;
265 IN PDRIVER_OBJECT Driver
,
266 IN PUNICODE_STRING Registry_path
269 DPRINT("Wdmaud.sys loaded\n");
271 Driver
->DriverUnload
= WdmAudUnload
;
273 Driver
->MajorFunction
[IRP_MJ_CREATE
] = WdmAudCreate
;
274 Driver
->MajorFunction
[IRP_MJ_CLOSE
] = WdmAudClose
;
275 Driver
->MajorFunction
[IRP_MJ_PNP
] = WdmAudPnp
;
276 Driver
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = KsDefaultForwardIrp
;
277 Driver
->MajorFunction
[IRP_MJ_CLEANUP
] = WdmAudCleanup
;
278 Driver
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = WdmAudDeviceControl
;
279 Driver
->MajorFunction
[IRP_MJ_WRITE
] = WdmAudReadWrite
;
280 Driver
->MajorFunction
[IRP_MJ_READ
] = WdmAudReadWrite
;
281 Driver
->MajorFunction
[IRP_MJ_POWER
] = KsDefaultDispatchPower
;
283 return WdmAudInstallDevice(Driver
);