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