2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: drivers/wdm/audio/sysaudio/main.c
5 * PURPOSE: System Audio graph builder
6 * PROGRAMMER: Andrew Greenwood
9 * 8 Jul 07 Started basic implementation
15 const GUID KSCATEGORY_SYSAUDIO
= {0xA7C7A5B1L
, 0x5AF3, 0x11D1, {0x9C, 0xED, 0x00, 0xA0, 0x24, 0xBF, 0x04, 0x07}};
16 const GUID KSCATEGORY_AUDIO_DEVICE
= {0xFBF6F530L
, 0x07B9, 0x11D2, {0xA7, 0x1E, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
17 const GUID KSCATEGORY_PREFERRED_WAVEOUT_DEVICE
= {0xD6C5066EL
, 0x72C1, 0x11D2, {0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
18 const GUID KSCATEGORY_PREFERRED_WAVEIN_DEVICE
= {0xD6C50671L
, 0x72C1, 0x11D2, {0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
19 const GUID KSCATEGORY_PREFERRED_MIDIOUT_DEVICE
= {0xD6C50674L
, 0x72C1, 0x11D2, {0x97, 0x55, 0x00, 0x00, 0xF8, 0x00, 0x47, 0x88}};
23 IN POOL_TYPE PoolType
,
24 IN SIZE_T NumberOfBytes
)
26 PVOID Item
= ExAllocatePool(PoolType
, NumberOfBytes
);
30 RtlZeroMemory(Item
, NumberOfBytes
);
44 SysAudio_Unload(IN PDRIVER_OBJECT DriverObject
)
46 DPRINT("SysAudio_Unload called\n");
52 IN PDEVICE_OBJECT DeviceObject
,
55 PKSAUDIO_DEVICE_ENTRY DeviceEntry
;
56 PSYSAUDIODEVEXT DeviceExtension
;
59 DPRINT("SysAudio_Shutdown called\n");
61 DeviceExtension
= (PSYSAUDIODEVEXT
)DeviceObject
->DeviceExtension
;
63 while(!IsListEmpty(&DeviceExtension
->KsAudioDeviceList
))
65 Entry
= RemoveHeadList(&DeviceExtension
->KsAudioDeviceList
);
66 DeviceEntry
= (PKSAUDIO_DEVICE_ENTRY
)CONTAINING_RECORD(Entry
, KSAUDIO_DEVICE_ENTRY
, Entry
);
68 DPRINT("Freeing item %wZ\n", &DeviceEntry
->DeviceName
);
70 /* dereference audio device file object */
71 ObDereferenceObject(DeviceEntry
->FileObject
);
73 /* close audio device handle */
74 ZwClose(DeviceEntry
->Handle
);
76 /* free device string */
77 RtlFreeUnicodeString(&DeviceEntry
->DeviceName
);
79 /* free audio device entry */
80 FreeItem(DeviceEntry
);
83 Irp
->IoStatus
.Information
= 0;
84 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
85 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
86 return STATUS_SUCCESS
;
93 IN PDEVICE_OBJECT DeviceObject
,
96 PIO_STACK_LOCATION IrpStack
;
97 UNICODE_STRING SymlinkName
= RTL_CONSTANT_STRING(L
"\\DosDevices\\sysaudio");
98 SYSAUDIODEVEXT
*DeviceExtension
;
100 /* Get current irp stack */
101 IrpStack
= IoGetCurrentIrpStackLocation(Irp
);
103 /* Fetch the device extension */
104 DeviceExtension
= (SYSAUDIODEVEXT
*)DeviceObject
->DeviceExtension
;
105 ASSERT(DeviceExtension
);
107 if (IrpStack
->MinorFunction
== IRP_MN_REMOVE_DEVICE
)
109 /* Unregister the echo cancel hook */
110 if (DeviceExtension
->EchoCancelNotificationEntry
)
111 IoUnregisterPlugPlayNotification(DeviceExtension
->EchoCancelNotificationEntry
);
113 /* Unregister the ks audio hook */
114 if (DeviceExtension
->KsAudioNotificationEntry
)
115 IoUnregisterPlugPlayNotification(DeviceExtension
->KsAudioNotificationEntry
);
117 /* Destroy our symbolic link */
118 IoDeleteSymbolicLink(&SymlinkName
);
120 else if (IrpStack
->MinorFunction
== IRP_MN_QUERY_PNP_DEVICE_STATE
)
122 /* Sysaudio can not be disabled */
123 Irp
->IoStatus
.Information
|= PNP_DEVICE_NOT_DISABLEABLE
;
126 /* Perform default pnp actions */
127 return KsDefaultDispatchPnp(DeviceObject
, Irp
);
132 SysAudio_InstallDevice(
133 IN PDRIVER_OBJECT DriverObject
)
136 UNICODE_STRING DeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\sysaudio");
137 UNICODE_STRING SymlinkName
= RTL_CONSTANT_STRING(L
"\\DosDevices\\sysaudio");
138 PDEVICE_OBJECT DeviceObject
;
139 SYSAUDIODEVEXT
*DeviceExtension
;
142 DPRINT("SysAudio_InstallDevice called\n");
144 /* Create the device */
145 Status
= IoCreateDevice(DriverObject
,
146 sizeof(SYSAUDIODEVEXT
),
153 /* Check for success */
154 if (!NT_SUCCESS(Status
))
156 DPRINT("Failed to create \\Device\\sysaudio !\n");
160 /* Register device interfaces */
161 Status
= SysAudioRegisterDeviceInterfaces(DeviceObject
);
162 if (!NT_SUCCESS(Status
))
164 /* Failed to register
165 * Create a hack interface
167 Status
= IoCreateSymbolicLink(&SymlinkName
, &DeviceName
);
168 if (!NT_SUCCESS(Status
))
170 IoDeleteDevice(DeviceObject
);
171 DPRINT1("Failed to create sysaudio symlink!\n");
175 /* Acquire device extension */
176 DeviceExtension
= (SYSAUDIODEVEXT
*)DeviceObject
->DeviceExtension
;
177 /* Initialize device extension */
178 RtlZeroMemory(DeviceExtension
, sizeof(SYSAUDIODEVEXT
));
180 /* Initialize the mutex */
181 KeInitializeSpinLock(&DeviceExtension
->Lock
);
183 /* Initialize the ks audio device list */
184 InitializeListHead(&DeviceExtension
->KsAudioDeviceList
);
186 /* Allocate kernel streaming device header */
187 Status
= SysAudioAllocateDeviceHeader(DeviceExtension
);
188 if (!NT_SUCCESS(Status
))
190 DPRINT1("KsAllocateDeviceHeader failed with %x\n", Status
);
194 /* Register device notification hooks */
195 Status
= SysAudioRegisterNotifications(DriverObject
,
197 if (!NT_SUCCESS(Status
))
199 DPRINT1("Failed to register device notifications\n");
204 Status
= SysAudioOpenKMixer(DeviceExtension
);
205 if (!NT_SUCCESS(Status
))
207 DPRINT1("SysAudioOpenKMixer failed with %x\n", Status
);
212 DeviceObject
->Flags
|= DO_DIRECT_IO
| DO_POWER_PAGABLE
;
213 /* clear initializing flag */
214 DeviceObject
->Flags
&= ~ DO_DEVICE_INITIALIZING
;
216 /* register shutdown notfication */
217 IoRegisterShutdownNotification(DeviceObject
);
221 return STATUS_SUCCESS
;
225 if (DeviceExtension
->KsAudioNotificationEntry
)
226 IoUnregisterPlugPlayNotification(DeviceExtension
->KsAudioNotificationEntry
);
228 if (DeviceExtension
->EchoCancelNotificationEntry
)
229 IoUnregisterPlugPlayNotification(DeviceExtension
->EchoCancelNotificationEntry
);
231 IoDeleteSymbolicLink(&SymlinkName
);
232 IoDeleteDevice(DeviceObject
);
239 IN PDRIVER_OBJECT DriverObject
,
240 IN PUNICODE_STRING RegistryPath
)
242 DPRINT("System audio graph builder (sysaudio) started\n");
244 /* Let ks handle these */
245 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_CREATE
);
246 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_CLOSE
);
247 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_WRITE
);
248 KsSetMajorFunctionHandler(DriverObject
, IRP_MJ_DEVICE_CONTROL
);
250 /* Let ks handle these */
251 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = KsDefaultDispatchPower
;
252 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = KsDefaultForwardIrp
;
254 /* Use provided ks unload function */
255 DriverObject
->DriverUnload
= KsNullDriverUnload
;
257 /* Sysaudio needs to do work on pnp, so handle it */
258 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = SysAudio_Pnp
;
259 DriverObject
->MajorFunction
[IRP_MJ_SHUTDOWN
] = SysAudio_Shutdown
;
261 /* Call our initialization function */
262 return SysAudio_InstallDevice(DriverObject
);