1*c2c66affSColin Finck /*
2*c2c66affSColin Finck *
3*c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
4*c2c66affSColin Finck * PROJECT: ReactOS Sound System
5*c2c66affSColin Finck * FILE: drivers/multimedia/audio/sndblst/sndblst.c
6*c2c66affSColin Finck * PURPOSE: Sound Blaster / Pro / 16 driver
7*c2c66affSColin Finck * PROGRAMMER: Andrew Greenwood (silverblade@reactos.org)
8*c2c66affSColin Finck *
9*c2c66affSColin Finck * UPDATE HISTORY: Feb 25, 2009: New rewrite started
10*c2c66affSColin Finck *
11*c2c66affSColin Finck */
12*c2c66affSColin Finck
13*c2c66affSColin Finck /* DEFINES AND INCLUDES ******************************************************/
14*c2c66affSColin Finck
15*c2c66affSColin Finck #include <ntddk.h>
16*c2c66affSColin Finck #include <windef.h>
17*c2c66affSColin Finck #include <mmsystem.h>
18*c2c66affSColin Finck #include <debug.h>
19*c2c66affSColin Finck
20*c2c66affSColin Finck #define CompleteIrpAndReturn(irp, status) \
21*c2c66affSColin Finck irp->IoStatus.Status = status; \
22*c2c66affSColin Finck irp->IoStatus.Information = 0; \
23*c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT); \
24*c2c66affSColin Finck return status;
25*c2c66affSColin Finck
26*c2c66affSColin Finck
27*c2c66affSColin Finck /* FORWARD DECLARATIONS *****************************************************/
28*c2c66affSColin Finck
29*c2c66affSColin Finck static VOID NTAPI
30*c2c66affSColin Finck UnloadSoundBlaster(PDRIVER_OBJECT DriverObject);
31*c2c66affSColin Finck
32*c2c66affSColin Finck
33*c2c66affSColin Finck /* DEVICE "DISCOVERY" *******************************************************/
34*c2c66affSColin Finck /* Nb: These need to go in the helper lib */
35*c2c66affSColin Finck
36*c2c66affSColin Finck typedef NTSTATUS (*SOUNDDEVICEENUMERATIONCALLBACK)(
37*c2c66affSColin Finck IN PUNICODE_STRING DeviceRegistryPath);
38*c2c66affSColin Finck
39*c2c66affSColin Finck NTSTATUS
EnumerateSoundDevices(IN PUNICODE_STRING RegistryPath,IN PWSTR RegistrySubKey,IN SOUNDDEVICEENUMERATIONCALLBACK Callback)40*c2c66affSColin Finck EnumerateSoundDevices(
41*c2c66affSColin Finck IN PUNICODE_STRING RegistryPath,
42*c2c66affSColin Finck IN PWSTR RegistrySubKey,
43*c2c66affSColin Finck IN SOUNDDEVICEENUMERATIONCALLBACK Callback)
44*c2c66affSColin Finck {
45*c2c66affSColin Finck NTSTATUS Status;
46*c2c66affSColin Finck OBJECT_ATTRIBUTES RegAttributes;
47*c2c66affSColin Finck HKEY MainKeyHandle, ChildKeyHandle;
48*c2c66affSColin Finck UNICODE_STRING UnicodeSubkeyName, DeviceKeyName;
49*c2c66affSColin Finck KEY_BASIC_INFORMATION KeyInfo, *FinalKeyInfo;
50*c2c66affSColin Finck ULONG i = 0, NeededDataLength = 0, FinalDataLength = 0, NameLength = 0;
51*c2c66affSColin Finck
52*c2c66affSColin Finck /* Turn the subkey name into a Unicode string */
53*c2c66affSColin Finck RtlInitUnicodeString(&UnicodeSubkeyName, RegistrySubKey);
54*c2c66affSColin Finck
55*c2c66affSColin Finck /* Open the registry key for the service */
56*c2c66affSColin Finck InitializeObjectAttributes(&RegAttributes,
57*c2c66affSColin Finck RegistryPath,
58*c2c66affSColin Finck OBJ_CASE_INSENSITIVE,
59*c2c66affSColin Finck NULL,
60*c2c66affSColin Finck (PSECURITY_DESCRIPTOR) NULL);
61*c2c66affSColin Finck
62*c2c66affSColin Finck Status = ZwOpenKey(&MainKeyHandle, KEY_READ, &RegAttributes);
63*c2c66affSColin Finck
64*c2c66affSColin Finck if ( ! NT_SUCCESS(Status) )
65*c2c66affSColin Finck {
66*c2c66affSColin Finck DPRINT("Failed to open registry key\n");
67*c2c66affSColin Finck return Status;
68*c2c66affSColin Finck }
69*c2c66affSColin Finck
70*c2c66affSColin Finck /* Open the subkey usually named "Parameters" */
71*c2c66affSColin Finck InitializeObjectAttributes(&RegAttributes,
72*c2c66affSColin Finck &UnicodeSubkeyName,
73*c2c66affSColin Finck OBJ_CASE_INSENSITIVE,
74*c2c66affSColin Finck MainKeyHandle,
75*c2c66affSColin Finck (PSECURITY_DESCRIPTOR) NULL);
76*c2c66affSColin Finck
77*c2c66affSColin Finck Status = ZwOpenKey(&ChildKeyHandle, KEY_ENUMERATE_SUB_KEYS, &RegAttributes);
78*c2c66affSColin Finck
79*c2c66affSColin Finck /* We're done with the main key now */
80*c2c66affSColin Finck ZwClose(MainKeyHandle);
81*c2c66affSColin Finck
82*c2c66affSColin Finck if ( ! NT_SUCCESS(Status) )
83*c2c66affSColin Finck {
84*c2c66affSColin Finck DPRINT("Failed to open registry subkeys for enumeration\n");
85*c2c66affSColin Finck return Status;
86*c2c66affSColin Finck }
87*c2c66affSColin Finck
88*c2c66affSColin Finck /* Enumerate through the device keys */
89*c2c66affSColin Finck while ( ( Status = ZwEnumerateKey(ChildKeyHandle,
90*c2c66affSColin Finck i,
91*c2c66affSColin Finck KeyBasicInformation,
92*c2c66affSColin Finck &KeyInfo,
93*c2c66affSColin Finck sizeof(KEY_BASIC_INFORMATION),
94*c2c66affSColin Finck &NeededDataLength) ) != STATUS_NO_MORE_ENTRIES )
95*c2c66affSColin Finck {
96*c2c66affSColin Finck PWSTR EnumeratedKeyName, StartOfEnumeratedKeyName;
97*c2c66affSColin Finck
98*c2c66affSColin Finck DPRINT("Found subkey %d\n", i);
99*c2c66affSColin Finck
100*c2c66affSColin Finck FinalDataLength = NeededDataLength + FIELD_OFFSET(KEY_BASIC_INFORMATION, Name[0]);
101*c2c66affSColin Finck DPRINT("Allocating %d bytes\n", FinalDataLength);
102*c2c66affSColin Finck
103*c2c66affSColin Finck FinalKeyInfo = (PKEY_BASIC_INFORMATION) ExAllocatePool(PagedPool, FinalDataLength);
104*c2c66affSColin Finck
105*c2c66affSColin Finck if ( ! FinalKeyInfo )
106*c2c66affSColin Finck {
107*c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES;
108*c2c66affSColin Finck break;
109*c2c66affSColin Finck }
110*c2c66affSColin Finck
111*c2c66affSColin Finck /* This time we get the real info */
112*c2c66affSColin Finck Status = ZwEnumerateKey(ChildKeyHandle,
113*c2c66affSColin Finck i,
114*c2c66affSColin Finck KeyBasicInformation,
115*c2c66affSColin Finck FinalKeyInfo,
116*c2c66affSColin Finck FinalDataLength,
117*c2c66affSColin Finck &NeededDataLength);
118*c2c66affSColin Finck
119*c2c66affSColin Finck if ( ! NT_SUCCESS(Status) )
120*c2c66affSColin Finck {
121*c2c66affSColin Finck DPRINT("FAILED to enumerate key!\n");
122*c2c66affSColin Finck }
123*c2c66affSColin Finck else
124*c2c66affSColin Finck {
125*c2c66affSColin Finck NameLength = RegistryPath->Length + sizeof(WCHAR) +
126*c2c66affSColin Finck UnicodeSubkeyName.Length + sizeof(WCHAR) +
127*c2c66affSColin Finck FinalKeyInfo->NameLength + sizeof(UNICODE_NULL);
128*c2c66affSColin Finck
129*c2c66affSColin Finck DPRINT("Allocating memory for name (%d bytes)\n", NameLength);
130*c2c66affSColin Finck
131*c2c66affSColin Finck EnumeratedKeyName = (PWSTR) ExAllocatePool(PagedPool, NameLength);
132*c2c66affSColin Finck
133*c2c66affSColin Finck if ( ! EnumeratedKeyName )
134*c2c66affSColin Finck {
135*c2c66affSColin Finck ExFreePool((PVOID)FinalKeyInfo);
136*c2c66affSColin Finck Status = STATUS_INSUFFICIENT_RESOURCES;
137*c2c66affSColin Finck break;
138*c2c66affSColin Finck }
139*c2c66affSColin Finck
140*c2c66affSColin Finck StartOfEnumeratedKeyName = EnumeratedKeyName;
141*c2c66affSColin Finck
142*c2c66affSColin Finck /* Start building the registry path using the service key */
143*c2c66affSColin Finck RtlCopyMemory(EnumeratedKeyName,
144*c2c66affSColin Finck RegistryPath->Buffer,
145*c2c66affSColin Finck RegistryPath->Length);
146*c2c66affSColin Finck
147*c2c66affSColin Finck EnumeratedKeyName += RegistryPath->Length / sizeof(WCHAR);
148*c2c66affSColin Finck EnumeratedKeyName[0] = '\\';
149*c2c66affSColin Finck ++ EnumeratedKeyName;
150*c2c66affSColin Finck
151*c2c66affSColin Finck /* Append the parameters subkey */
152*c2c66affSColin Finck RtlCopyMemory(EnumeratedKeyName,
153*c2c66affSColin Finck RegistrySubKey,
154*c2c66affSColin Finck UnicodeSubkeyName.Length);
155*c2c66affSColin Finck
156*c2c66affSColin Finck EnumeratedKeyName += UnicodeSubkeyName.Length / sizeof(WCHAR);
157*c2c66affSColin Finck EnumeratedKeyName[0] = '\\';
158*c2c66affSColin Finck ++ EnumeratedKeyName;
159*c2c66affSColin Finck
160*c2c66affSColin Finck /* And finally append the enumerated key name */
161*c2c66affSColin Finck RtlCopyMemory(EnumeratedKeyName,
162*c2c66affSColin Finck FinalKeyInfo->Name,
163*c2c66affSColin Finck FinalKeyInfo->NameLength);
164*c2c66affSColin Finck
165*c2c66affSColin Finck EnumeratedKeyName += FinalKeyInfo->NameLength / sizeof(WCHAR);
166*c2c66affSColin Finck EnumeratedKeyName[0] = UNICODE_NULL;
167*c2c66affSColin Finck
168*c2c66affSColin Finck /* Reset pointer */
169*c2c66affSColin Finck EnumeratedKeyName = StartOfEnumeratedKeyName;
170*c2c66affSColin Finck
171*c2c66affSColin Finck /* Convert into a Unicode string for the callback */
172*c2c66affSColin Finck RtlInitUnicodeString(&DeviceKeyName, EnumeratedKeyName);
173*c2c66affSColin Finck
174*c2c66affSColin Finck Callback(&DeviceKeyName);
175*c2c66affSColin Finck
176*c2c66affSColin Finck /* No longer need the key name */
177*c2c66affSColin Finck ExFreePool((PVOID)EnumeratedKeyName);
178*c2c66affSColin Finck EnumeratedKeyName = NULL;
179*c2c66affSColin Finck }
180*c2c66affSColin Finck
181*c2c66affSColin Finck /* No longer need the key info */
182*c2c66affSColin Finck ExFreePool((PVOID)FinalKeyInfo);
183*c2c66affSColin Finck FinalKeyInfo = NULL;
184*c2c66affSColin Finck
185*c2c66affSColin Finck ++ i;
186*c2c66affSColin Finck }
187*c2c66affSColin Finck
188*c2c66affSColin Finck /* We're done with enumeration so close this */
189*c2c66affSColin Finck ZwClose(ChildKeyHandle);
190*c2c66affSColin Finck
191*c2c66affSColin Finck /* This isn't an error */
192*c2c66affSColin Finck if ( Status == STATUS_NO_MORE_ENTRIES )
193*c2c66affSColin Finck {
194*c2c66affSColin Finck Status = STATUS_SUCCESS;
195*c2c66affSColin Finck }
196*c2c66affSColin Finck
197*c2c66affSColin Finck /* No devices configured? */
198*c2c66affSColin Finck if ( i == 0 && Status == STATUS_NO_MORE_ENTRIES )
199*c2c66affSColin Finck {
200*c2c66affSColin Finck Status = STATUS_DEVICE_CONFIGURATION_ERROR;
201*c2c66affSColin Finck }
202*c2c66affSColin Finck
203*c2c66affSColin Finck return Status;
204*c2c66affSColin Finck }
205*c2c66affSColin Finck
206*c2c66affSColin Finck NTSTATUS
PublishWaveOutDevice(IN DWORD HardwareDeviceIndex,IN PWSTR BaseDeviceName,IN DWORD DeviceIndex,IN LPWAVEOUTCAPS Capabilities)207*c2c66affSColin Finck PublishWaveOutDevice(
208*c2c66affSColin Finck IN DWORD HardwareDeviceIndex,
209*c2c66affSColin Finck IN PWSTR BaseDeviceName,
210*c2c66affSColin Finck IN DWORD DeviceIndex,
211*c2c66affSColin Finck IN LPWAVEOUTCAPS Capabilities)
212*c2c66affSColin Finck {
213*c2c66affSColin Finck return STATUS_SUCCESS;
214*c2c66affSColin Finck }
215*c2c66affSColin Finck
216*c2c66affSColin Finck
217*c2c66affSColin Finck typedef struct _SOUND_BLASTER_DEVICE
218*c2c66affSColin Finck {
219*c2c66affSColin Finck DWORD BasePort;
220*c2c66affSColin Finck DWORD MidiUartBasePort;
221*c2c66affSColin Finck
222*c2c66affSColin Finck DWORD Irq;
223*c2c66affSColin Finck
224*c2c66affSColin Finck DWORD DmaChannel_8;
225*c2c66affSColin Finck DWORD DmaChannel_16;
226*c2c66affSColin Finck
227*c2c66affSColin Finck DWORD DspVersion;
228*c2c66affSColin Finck
229*c2c66affSColin Finck DWORD ActualDmaBufferSize;
230*c2c66affSColin Finck DWORD DmaBufferSize;
231*c2c66affSColin Finck } SOUND_BLASTER_DEVICE;
232*c2c66affSColin Finck
233*c2c66affSColin Finck
234*c2c66affSColin Finck NTSTATUS
AllocateSoundBlasterStructure(OUT SOUND_BLASTER_DEVICE * SoundBlasterDevice)235*c2c66affSColin Finck AllocateSoundBlasterStructure(OUT SOUND_BLASTER_DEVICE* SoundBlasterDevice)
236*c2c66affSColin Finck {
237*c2c66affSColin Finck return STATUS_NOT_IMPLEMENTED;
238*c2c66affSColin Finck }
239*c2c66affSColin Finck
240*c2c66affSColin Finck /* callback */
241*c2c66affSColin Finck /*
242*c2c66affSColin Finck Configuration options within the registry:
243*c2c66affSColin Finck REG_DWORD Actual Dma Buffer Size 0x00004000
244*c2c66affSColin Finck REG_DWORD Configuration Error 0xffffffff
245*c2c66affSColin Finck REG_DWORD Dma Buffer Size 0x00004000
246*c2c66affSColin Finck REG_DWORD DmaChannel 0x00000001
247*c2c66affSColin Finck REG_DWORD DmaChannel16 0x00000005
248*c2c66affSColin Finck REG_DWORD DSP Version 0x00000405
249*c2c66affSColin Finck REG_DWORD Interrupt 0x00000005
250*c2c66affSColin Finck REG_DWORD Load Type 0x00000000
251*c2c66affSColin Finck REG_BINARY Mixer Settings ??
252*c2c66affSColin Finck REG_DWORD MPU401 Port 0xffffffff
253*c2c66affSColin Finck REG_DWORD Port 0x00000220
254*c2c66affSColin Finck */
255*c2c66affSColin Finck
256*c2c66affSColin Finck NTSTATUS
ConfigureSoundBlasterDevice(IN PUNICODE_STRING DeviceRegistryPath)257*c2c66affSColin Finck ConfigureSoundBlasterDevice(IN PUNICODE_STRING DeviceRegistryPath)
258*c2c66affSColin Finck {
259*c2c66affSColin Finck OBJECT_ATTRIBUTES RegAttributes;
260*c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS;
261*c2c66affSColin Finck HKEY ConfigKeyHandle;
262*c2c66affSColin Finck
263*c2c66affSColin Finck DPRINT("Configuring Sound Blaster (config at %S)\n", DeviceRegistryPath->Buffer);
264*c2c66affSColin Finck
265*c2c66affSColin Finck if ( ! DeviceRegistryPath )
266*c2c66affSColin Finck {
267*c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
268*c2c66affSColin Finck }
269*c2c66affSColin Finck
270*c2c66affSColin Finck /* Open the registry key */
271*c2c66affSColin Finck InitializeObjectAttributes(&RegAttributes,
272*c2c66affSColin Finck DeviceRegistryPath,
273*c2c66affSColin Finck OBJ_CASE_INSENSITIVE,
274*c2c66affSColin Finck NULL,
275*c2c66affSColin Finck (PSECURITY_DESCRIPTOR) NULL);
276*c2c66affSColin Finck
277*c2c66affSColin Finck Status = ZwOpenKey(&ConfigKeyHandle, KEY_READ, &RegAttributes);
278*c2c66affSColin Finck
279*c2c66affSColin Finck if ( ! NT_SUCCESS(Status) )
280*c2c66affSColin Finck {
281*c2c66affSColin Finck DPRINT("Failed to open config registry key\n");
282*c2c66affSColin Finck return Status;
283*c2c66affSColin Finck }
284*c2c66affSColin Finck
285*c2c66affSColin Finck /* Read configuration */
286*c2c66affSColin Finck DPRINT("Reading configuration\n");
287*c2c66affSColin Finck
288*c2c66affSColin Finck //Status = ZwQueryValueKey(ConfigKeyHandle,
289*c2c66affSColin Finck
290*c2c66affSColin Finck return Status;
291*c2c66affSColin Finck }
292*c2c66affSColin Finck
293*c2c66affSColin Finck
294*c2c66affSColin Finck /* IRP DISPATCHERS **********************************************************/
295*c2c66affSColin Finck
296*c2c66affSColin Finck static NTSTATUS NTAPI
CreateSoundBlaster(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)297*c2c66affSColin Finck CreateSoundBlaster(
298*c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
299*c2c66affSColin Finck IN PIRP Irp)
300*c2c66affSColin Finck {
301*c2c66affSColin Finck DPRINT("Sound Blaster driver received IRP_MJ_CREATE\n");
302*c2c66affSColin Finck
303*c2c66affSColin Finck CompleteIrpAndReturn(Irp, STATUS_SUCCESS);
304*c2c66affSColin Finck }
305*c2c66affSColin Finck
306*c2c66affSColin Finck static NTSTATUS NTAPI
CloseSoundBlaster(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)307*c2c66affSColin Finck CloseSoundBlaster(
308*c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
309*c2c66affSColin Finck IN PIRP Irp)
310*c2c66affSColin Finck {
311*c2c66affSColin Finck DPRINT("Sound Blaster driver received IRP_MJ_CLOSE\n");
312*c2c66affSColin Finck
313*c2c66affSColin Finck CompleteIrpAndReturn(Irp, STATUS_SUCCESS);
314*c2c66affSColin Finck }
315*c2c66affSColin Finck
316*c2c66affSColin Finck static NTSTATUS NTAPI
CleanupSoundBlaster(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)317*c2c66affSColin Finck CleanupSoundBlaster(
318*c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
319*c2c66affSColin Finck IN PIRP Irp)
320*c2c66affSColin Finck {
321*c2c66affSColin Finck DPRINT("Sound Blaster driver received IRP_MJ_CLEANUP\n");
322*c2c66affSColin Finck
323*c2c66affSColin Finck CompleteIrpAndReturn(Irp, STATUS_SUCCESS);
324*c2c66affSColin Finck }
325*c2c66affSColin Finck
326*c2c66affSColin Finck static NTSTATUS NTAPI
ControlSoundBlaster(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)327*c2c66affSColin Finck ControlSoundBlaster(
328*c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
329*c2c66affSColin Finck IN PIRP Irp)
330*c2c66affSColin Finck {
331*c2c66affSColin Finck DPRINT("Sound Blaster driver received IRP_MJ_CONTROL\n");
332*c2c66affSColin Finck
333*c2c66affSColin Finck CompleteIrpAndReturn(Irp, STATUS_SUCCESS);
334*c2c66affSColin Finck }
335*c2c66affSColin Finck
336*c2c66affSColin Finck static NTSTATUS NTAPI
WriteToSoundBlaster(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)337*c2c66affSColin Finck WriteToSoundBlaster(
338*c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
339*c2c66affSColin Finck IN PIRP Irp)
340*c2c66affSColin Finck {
341*c2c66affSColin Finck DPRINT("Sound Blaster driver received IRP_MJ_WRITE\n");
342*c2c66affSColin Finck
343*c2c66affSColin Finck CompleteIrpAndReturn(Irp, STATUS_SUCCESS);
344*c2c66affSColin Finck }
345*c2c66affSColin Finck
346*c2c66affSColin Finck
347*c2c66affSColin Finck /* DRIVER ENTRYPOINT ********************************************************/
348*c2c66affSColin Finck
349*c2c66affSColin Finck NTSTATUS NTAPI
DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)350*c2c66affSColin Finck DriverEntry(
351*c2c66affSColin Finck IN PDRIVER_OBJECT DriverObject,
352*c2c66affSColin Finck IN PUNICODE_STRING RegistryPath)
353*c2c66affSColin Finck {
354*c2c66affSColin Finck NTSTATUS Status = STATUS_SUCCESS;
355*c2c66affSColin Finck
356*c2c66affSColin Finck DPRINT("Sound Blaster driver by silverblade\n");
357*c2c66affSColin Finck
358*c2c66affSColin Finck DriverObject->Flags = 0;
359*c2c66affSColin Finck DriverObject->MajorFunction[IRP_MJ_CREATE] = CreateSoundBlaster;
360*c2c66affSColin Finck DriverObject->MajorFunction[IRP_MJ_CLOSE] = CloseSoundBlaster;
361*c2c66affSColin Finck DriverObject->MajorFunction[IRP_MJ_CLEANUP] = CleanupSoundBlaster;
362*c2c66affSColin Finck DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ControlSoundBlaster;
363*c2c66affSColin Finck DriverObject->MajorFunction[IRP_MJ_WRITE] = WriteToSoundBlaster;
364*c2c66affSColin Finck DriverObject->DriverUnload = UnloadSoundBlaster;
365*c2c66affSColin Finck
366*c2c66affSColin Finck EnumerateSoundDevices(RegistryPath, L"Parameters", ConfigureSoundBlasterDevice);
367*c2c66affSColin Finck
368*c2c66affSColin Finck return Status;
369*c2c66affSColin Finck }
370*c2c66affSColin Finck
371*c2c66affSColin Finck static VOID NTAPI
UnloadSoundBlaster(IN PDRIVER_OBJECT DriverObject)372*c2c66affSColin Finck UnloadSoundBlaster(IN PDRIVER_OBJECT DriverObject)
373*c2c66affSColin Finck {
374*c2c66affSColin Finck DPRINT("Sound Blaster driver is being unloaded\n");
375*c2c66affSColin Finck }
376