ReactOS 0.4.16-dev-300-g2aadf2e
devname.c
Go to the documentation of this file.
1/*
2 ReactOS Sound System
3 Device naming & creation helper routines
4
5 Author:
6 Andrew Greenwood (silverblade@reactos.org)
7
8 History:
9 25 May 2008 - Created
10*/
11
12#include <ntddk.h>
13#include <ntddsnd.h>
14#include <sndnames.h>
15#include <sndtypes.h>
16#include <debug.h>
17
18
19/*
20 Default device names
21
22 Just to keep things tidy, we define a structure to hold both the \\Device
23 and \\DosDevices names, and then fill this structure with the default
24 device names that can be found in NTDDSND.H
25*/
26
27typedef struct _DEVICE_NAME_GROUP
28{
32
34{
35 {
38 },
39 {
42 },
43 {
46 },
47 {
50 },
51 {
54 },
55 {
58 }
59};
60
61
62/*
63 ConstructDeviceName
64
65 This takes a wide-character string containing the device name body (for
66 example, "\\Device\\WaveOut") and appends the device index, forming a
67 string like "\\Device\\WaveOut0", and so on.
68
69 The resulting device name is a unicode string.
70*/
71
77{
78 UNICODE_STRING UnicodePath;
79 UNICODE_STRING UnicodeIndex;
80 WCHAR IndexStringBuffer[5];
82 USHORT LastCharacterIndex;
83
84 /* Check for NULL parameters */
85 if ( ( ! Path ) || ( ! DeviceName ) )
86 {
87 DPRINT("Unexpected NULL parameter");
89 }
90
91 /* Range-check */
92 if ( Index >= SOUND_MAX_DEVICES )
93 {
94 DPRINT("Device index %d out of range", Index);
96 }
97
98 /* Initialise the unicode path string */
99 RtlInitUnicodeString(&UnicodePath, Path);
100
101 /* Calculate the length to hold the full string */
102 Size = UnicodePath.Length +
103 sizeof(IndexStringBuffer) +
104 sizeof(UNICODE_NULL);
105
106 /* Allocate memory for DeviceName */
108 DeviceName->MaximumLength = Size;
109
110 if ( ! DeviceName->Buffer )
111 {
112 DPRINT("Couldn't allocate memory for device name string");
114 }
115
116 /* Copy the path */
117 RtlCopyUnicodeString(DeviceName, &UnicodePath);
118
119 /* Convert Index to string and append */
120 UnicodeIndex.Buffer = IndexStringBuffer;
121 UnicodeIndex.MaximumLength = sizeof(IndexStringBuffer);
122
123 RtlIntegerToUnicodeString((ULONG)Index, 10, &UnicodeIndex);
125
126 /* Terminate the string */
127 LastCharacterIndex = DeviceName->Length / sizeof(UNICODE_NULL);
128 DeviceName->Buffer[LastCharacterIndex] = UNICODE_NULL;
129
130 return STATUS_SUCCESS;
131}
132
133
134/*
135 FreeUnicodeStringBuffer
136
137 A small helper routine to free a unicode string buffer, nullify the
138 buffer and reset the lengths to zero.
139*/
140
141VOID
143{
144 ASSERT(String != NULL);
145 ASSERT(String->Buffer != NULL);
146
147 ExFreePool(String->Buffer);
148
149 String->Buffer = NULL;
150 String->Length = 0;
151 String->MaximumLength = 0;
152}
153
154
155/*
156 GetDefaultSoundDeviceNameBodies
157
158 Simply accesses the SoundDeviceNameBodies struct defined earlier and
159 fills the DeviceNameBody and DosDeviceNameBody parameters accordingly.
160
161 Basically a "safe" way to access the array and perform two assignments
162 with one call, as this will assign the name and DOS name if a valid
163 DeviceType is passed, otherwise it will fail with STATUS_INVALID_PARAMETER.
164*/
165
169 OUT PCWSTR* DeviceNameBody,
170 OUT PCWSTR* DosDeviceNameBody)
171{
173 {
174 DPRINT("Invalid device type");
176 }
177
178 if ( DeviceNameBody )
179 {
180 DPRINT("Reporting device name\n");
182 DPRINT("%ws\n", *DeviceNameBody);
183 }
184
185 if ( DosDeviceNameBody )
186 {
187 DPRINT("Reporting DOS device name\n");
188 *DosDeviceNameBody = SoundDeviceNameBodies[DeviceType].DosDeviceName;
189 DPRINT("%ws\n", *DosDeviceNameBody);
190 }
191
192 return STATUS_SUCCESS;
193}
194
195
196/*
197 ConstructSoundDeviceNames
198
199 Given two wide-character strings and a device index, convert these into
200 two unicode strings with the index appended to the end.
201
202 This is intended for converting a device name and a DOS device name at
203 the same time.
204*/
205
208 IN PCWSTR DeviceNameBody,
209 IN PCWSTR DosDeviceNameBody,
210 IN UCHAR Index,
211 OUT PUNICODE_STRING FullDeviceName,
212 OUT PUNICODE_STRING FullDosDeviceName)
213{
215
216 /* Check for NULL parameters */
217 if ( ( ! DeviceNameBody ) || ( ! DosDeviceNameBody ) ||
218 ( ! FullDeviceName ) || ( ! FullDosDeviceName ) )
219 {
220 DPRINT("Unexpected NULL parameter");
222 }
223
224 /* Range-check */
225 if ( Index >= SOUND_MAX_DEVICES )
226 {
227 DPRINT("Device %d exceeds maximum", Index);
229 }
230
231 Status = ConstructDeviceName(DeviceNameBody, Index, FullDeviceName);
232
233 if ( ! NT_SUCCESS(Status) )
234 {
235 /* No need to clean up on failure here */
236 return Status;
237 }
238
239 Status = ConstructDeviceName(DosDeviceNameBody, Index, FullDosDeviceName);
240
241 if ( ! NT_SUCCESS(Status) )
242 {
243 /* We need to free the string we successfully got earlier */
244 FreeUnicodeStringBuffer(FullDeviceName);
245 return Status;
246 }
247
248 return STATUS_SUCCESS;
249}
250
251
252/*
253 CreateSoundDevice
254
255 Creates a device and symbolically-links a DOS device to this. Use this
256 when you want to specify alternative device names to the defaults
257 (eg: "\\Device\\MySoundDev" rather than "\\Device\\WaveOut")
258*/
259
263 IN PCWSTR WideDeviceName,
264 IN PCWSTR WideDosDeviceName,
265 IN UCHAR Index,
268{
270
273
274 /* Check for NULL parameters */
275 if ( ( ! DriverObject ) || ( ! DeviceObject ) ||
276 ( ! WideDeviceName ) || ( ! WideDosDeviceName ) )
277 {
278 DPRINT("Unexpected NULL parameter");
280 }
281
282 /* Range-check */
283 if ( Index >= SOUND_MAX_DEVICES )
284 {
285 DPRINT("Device index %d exceeds maximum", Index);
287 }
288
289 /* Construct the device and DOS device names */
290 Status = ConstructSoundDeviceNames(WideDeviceName,
291 WideDosDeviceName,
292 Index,
293 &DeviceName,
295
296 if ( ! NT_SUCCESS(Status) )
297 {
298 return Status;
299 }
300
301 DPRINT("Creating device %ws\n", DeviceName.Buffer);
302
303 /* Now create the device */
306 &DeviceName,
308 0,
309 FALSE,
311
312 if ( ! NT_SUCCESS(Status) )
313 {
314 /* These will have been allocated by ConstructSoundDeviceNames */
317
318 return Status;
319 }
320
321 DPRINT("Creating link %ws\n", DosDeviceName.Buffer);
322
323 /* Create a symbolic link for the DOS deviec name */
325
326 if ( ! NT_SUCCESS(Status) )
327 {
329
330 /* These will have been allocated by ConstructSoundDeviceNames */
333
334 return Status;
335 }
336
337 return STATUS_SUCCESS;
338}
339
340
341/*
342 CreateSoundDeviceWithDefaultName
343
344 Similar to CreateSoundDevice, except this uses the default device names
345 ("\\Device\\WaveOut" etc.) based on the DeviceType parameter.
346*/
347
352 IN UCHAR Index,
355{
357 PCWSTR WideDeviceName = NULL;
358 PCWSTR WideDosDeviceName = NULL;
359
360 /* Check for NULL parameters */
361 if ( ( ! DriverObject ) || ( ! DeviceObject ) )
362 {
363 DPRINT("Unexpected NULL parameter");
365 }
366
367 /* Range-check */
368 if ( Index >= SOUND_MAX_DEVICES )
369 {
370 DPRINT("Device index %d exceeds maximum", Index);
372 }
373
374 /* Look-up the default name based on the device type */
376 &WideDeviceName,
377 &WideDosDeviceName);
378
379 if ( ! NT_SUCCESS(Status) )
380 {
381 return Status;
382 }
383
384 /* Go create the device! */
386 WideDeviceName,
387 WideDosDeviceName,
388 Index,
391
392 if ( ! NT_SUCCESS(Status) )
393 {
394 /* No clean-up to do */
395 return Status;
396 }
397
398 return STATUS_SUCCESS;
399}
400
404 IN PCWSTR WideDosDeviceName,
405 IN UCHAR Index)
406{
409
410 /* Check for NULL parameters */
411 if ( ( ! WideDosDeviceName ) || ( ! DeviceObject ) )
412 {
413 DPRINT("Unexpected NULL parameter");
415 }
416
417 /* Range-check */
418 if ( Index >= SOUND_MAX_DEVICES )
419 {
420 DPRINT("Device %d exceeds maximum", Index);
422 }
423
424 Status = ConstructDeviceName(WideDosDeviceName, Index, &DosDeviceName);
425
426 if ( ! NT_SUCCESS(Status) )
427 {
428 return Status;
429 }
430
431 DPRINT("Deleting symlink %ws\n", DosDeviceName.Buffer);
432
434 DPRINT("Status of symlink deletion is 0x%08x\n", Status);
435/*
436 ASSERT(NT_SUCCESS(Status));
437*/
438
440
441 return STATUS_SUCCESS;
442}
443
448 IN UCHAR Index)
449{
451 PCWSTR WideDosDeviceName = NULL;
452
453 /* Check for NULL parameters */
454 if ( ( ! DeviceObject ) )
455 {
456 DPRINT("Unexpected NULL parameter");
458 }
459
460 /* Range-check */
461 if ( Index >= SOUND_MAX_DEVICES )
462 {
463 DPRINT("Device index %d exceeds maximum", Index);
465 }
466
467 /* Look-up the default name based on the device type */
469 NULL,
470 &WideDosDeviceName);
471
472 if ( ! NT_SUCCESS(Status) )
473 {
474 return Status;
475 }
476
477 DPRINT("DOS device name at %p\n", WideDosDeviceName);
478
479 DPRINT("DOS device name is based on %ws\n", WideDosDeviceName);
480
481 return DestroySoundDevice(DeviceObject, WideDosDeviceName, Index);
482}
PRTL_UNICODE_STRING_BUFFER Path
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS CreateSoundDeviceWithDefaultName(IN PDRIVER_OBJECT DriverObject, IN UCHAR DeviceType, IN UCHAR Index, IN ULONG ExtensionSize, OUT PDEVICE_OBJECT *DeviceObject)
Definition: devname.c:349
struct _DEVICE_NAME_GROUP DEVICE_NAME_GROUP
NTSTATUS CreateSoundDevice(IN PDRIVER_OBJECT DriverObject, IN PCWSTR WideDeviceName, IN PCWSTR WideDosDeviceName, IN UCHAR Index, IN ULONG ExtensionSize, OUT PDEVICE_OBJECT *DeviceObject)
Definition: devname.c:261
NTSTATUS GetDefaultSoundDeviceNameBodies(IN UCHAR DeviceType, OUT PCWSTR *DeviceNameBody, OUT PCWSTR *DosDeviceNameBody)
Definition: devname.c:167
NTSTATUS ConstructDeviceName(IN PCWSTR Path, IN UCHAR Index, OUT PUNICODE_STRING DeviceName)
Definition: devname.c:73
NTSTATUS DestroySoundDevice(IN PDEVICE_OBJECT DeviceObject, IN PCWSTR WideDosDeviceName, IN UCHAR Index)
Definition: devname.c:402
NTSTATUS ConstructSoundDeviceNames(IN PCWSTR DeviceNameBody, IN PCWSTR DosDeviceNameBody, IN UCHAR Index, OUT PUNICODE_STRING FullDeviceName, OUT PUNICODE_STRING FullDosDeviceName)
Definition: devname.c:207
DEVICE_NAME_GROUP SoundDeviceNameBodies[6]
Definition: devname.c:33
VOID FreeUnicodeStringBuffer(IN PUNICODE_STRING String)
Definition: devname.c:142
NTSTATUS DestroySoundDeviceWithDefaultName(IN PDEVICE_OBJECT DeviceObject, IN UCHAR DeviceType, IN UCHAR Index)
Definition: devname.c:445
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define PagedPool
Definition: env_spec_w32.h:308
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
Status
Definition: gdiplustypes.h:25
static char DosDeviceName[DEVICE_SIZE]
Definition: lsdd.c:26
#define SOUND_MAX_DEVICES
Definition: mmdef.h:23
DeviceType
Definition: mmdrv.h:42
#define ASSERT(a)
Definition: mode.c:44
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI NTSTATUS NTAPI RtlIntegerToUnicodeString(ULONG Value, ULONG Base, PUNICODE_STRING String)
#define UNICODE_NULL
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
unsigned short USHORT
Definition: pedump.c:61
#define FILE_DEVICE_SOUND
Definition: winioctl.h:74
WORD ExtensionSize
Definition: apisets.c:17
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DD_MIX_DEVICE_NAME_U
Definition: sndnames.h:57
#define DD_MIDI_OUT_DEVICE_NAME_U
Definition: sndnames.h:50
#define DD_WAVE_OUT_DOS_DEVICE_NAME_U
Definition: sndnames.h:38
#define DD_WAVE_IN_DOS_DEVICE_NAME_U
Definition: sndnames.h:31
#define DD_WAVE_IN_DEVICE_NAME_U
Definition: sndnames.h:29
#define DD_AUX_DEVICE_NAME_U
Definition: sndnames.h:64
#define DD_MIDI_IN_DEVICE_NAME_U
Definition: sndnames.h:43
#define DD_MIX_DOS_DEVICE_NAME_U
Definition: sndnames.h:59
#define DD_MIDI_IN_DOS_DEVICE_NAME_U
Definition: sndnames.h:45
#define DD_WAVE_OUT_DEVICE_NAME_U
Definition: sndnames.h:36
#define DD_AUX_DOS_DEVICE_NAME_U
Definition: sndnames.h:66
#define DD_MIDI_OUT_DOS_DEVICE_NAME_U
Definition: sndnames.h:52
#define IS_VALID_SOUND_DEVICE_TYPE(x)
Definition: sndtypes.h:43
#define DPRINT
Definition: sndvol32.h:73
PCWSTR DeviceName
Definition: devname.c:29
PCWSTR DosDeviceName
Definition: devname.c:30
USHORT MaximumLength
Definition: env_spec_w32.h:370
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2433
_Must_inspect_result_ _In_ PWDFDEVICE_INIT _In_opt_ PCUNICODE_STRING DeviceName
Definition: wdfdevice.h:3275
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180