ReactOS  0.4.14-dev-317-g96040ec
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 
27 typedef 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 
74  IN PCWSTR Path,
75  IN UCHAR Index,
77 {
78  UNICODE_STRING UnicodePath;
79  UNICODE_STRING UnicodeIndex;
80  WCHAR IndexStringBuffer[5];
81  USHORT Size;
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 
141 VOID
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 
166 NTSTATUS
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");
181  *DeviceNameBody = SoundDeviceNameBodies[DeviceType].DeviceName;
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 
206 NTSTATUS
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 
260 NTSTATUS
263  IN PCWSTR WideDeviceName,
264  IN PCWSTR WideDosDeviceName,
265  IN UCHAR Index,
266  IN ULONG ExtensionSize,
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,
294  &DosDeviceName);
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 */
305  ExtensionSize,
306  &DeviceName,
308  0,
309  FALSE,
310  DeviceObject);
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 
348 NTSTATUS
352  IN UCHAR Index,
353  IN ULONG ExtensionSize,
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,
389  ExtensionSize,
390  DeviceObject);
391 
392  if ( ! NT_SUCCESS(Status) )
393  {
394  /* No clean-up to do */
395  return Status;
396  }
397 
398  return STATUS_SUCCESS;
399 }
400 
401 NTSTATUS
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 
444 NTSTATUS
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 }
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define IN
Definition: typedefs.h:38
#define DD_MIDI_IN_DOS_DEVICE_NAME_U
Definition: sndnames.h:45
#define DD_MIX_DOS_DEVICE_NAME_U
Definition: sndnames.h:59
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
DeviceType
Definition: mmdrv.h:41
LONG NTSTATUS
Definition: precomp.h:26
#define DD_WAVE_OUT_DEVICE_NAME_U
Definition: sndnames.h:36
struct _DEVICE_NAME_GROUP DEVICE_NAME_GROUP
NTSTATUS CreateSoundDeviceWithDefaultName(IN PDRIVER_OBJECT DriverObject, IN UCHAR DeviceType, IN UCHAR Index, IN ULONG ExtensionSize, OUT PDEVICE_OBJECT *DeviceObject)
Definition: devname.c:349
static WCHAR String[]
Definition: stringtable.c:55
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
WCHAR DeviceName[]
Definition: adapter.cpp:21
#define DD_MIDI_OUT_DEVICE_NAME_U
Definition: sndnames.h:50
#define DD_MIDI_IN_DEVICE_NAME_U
Definition: sndnames.h:43
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
VOID FreeUnicodeStringBuffer(IN PUNICODE_STRING String)
Definition: devname.c:142
#define UNICODE_NULL
smooth NULL
Definition: ftsmooth.c:416
PCWSTR DosDeviceName
Definition: devname.c:30
static PDRIVER_OBJECT DriverObject
Definition: template.c:42
void DPRINT(...)
Definition: polytest.cpp:61
#define DD_MIDI_OUT_DOS_DEVICE_NAME_U
Definition: sndnames.h:52
NTSTATUS DestroySoundDeviceWithDefaultName(IN PDEVICE_OBJECT DeviceObject, IN UCHAR DeviceType, IN UCHAR Index)
Definition: devname.c:445
NTSYSAPI NTSTATUS NTAPI RtlIntegerToUnicodeString(ULONG Value, ULONG Base, PUNICODE_STRING String)
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
DEVICE_NAME_GROUP SoundDeviceNameBodies[6]
Definition: devname.c:33
static const UCHAR Index[8]
Definition: usbohci.c:18
#define DD_AUX_DEVICE_NAME_U
Definition: sndnames.h:64
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static char DosDeviceName[DEVICE_SIZE]
Definition: lsdd.c:26
unsigned char UCHAR
Definition: xmlstorage.h:181
#define SOUND_MAX_DEVICES
Definition: mmdef.h:23
NTSTATUS ConstructSoundDeviceNames(IN PCWSTR DeviceNameBody, IN PCWSTR DosDeviceNameBody, IN UCHAR Index, OUT PUNICODE_STRING FullDeviceName, OUT PUNICODE_STRING FullDosDeviceName)
Definition: devname.c:207
#define DD_WAVE_OUT_DOS_DEVICE_NAME_U
Definition: sndnames.h:38
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
#define FILE_DEVICE_SOUND
Definition: winioctl.h:134
#define DD_MIX_DEVICE_NAME_U
Definition: sndnames.h:57
#define DD_WAVE_IN_DEVICE_NAME_U
Definition: sndnames.h:29
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
Status
Definition: gdiplustypes.h:24
NTSTATUS DestroySoundDevice(IN PDEVICE_OBJECT DeviceObject, IN PCWSTR WideDosDeviceName, IN UCHAR Index)
Definition: devname.c:402
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
PRTL_UNICODE_STRING_BUFFER Path
unsigned short USHORT
Definition: pedump.c:61
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define IS_VALID_SOUND_DEVICE_TYPE(x)
Definition: sndtypes.h:43
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
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
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define DD_WAVE_IN_DOS_DEVICE_NAME_U
Definition: sndnames.h:31
NTSTATUS GetDefaultSoundDeviceNameBodies(IN UCHAR DeviceType, OUT PCWSTR *DeviceNameBody, OUT PCWSTR *DosDeviceNameBody)
Definition: devname.c:167
return STATUS_SUCCESS
Definition: btrfs.c:2938
NTSTATUS ConstructDeviceName(IN PCWSTR Path, IN UCHAR Index, OUT PUNICODE_STRING DeviceName)
Definition: devname.c:73
PCWSTR DeviceName
Definition: devname.c:29
#define DD_AUX_DOS_DEVICE_NAME_U
Definition: sndnames.h:66
#define ExFreePool(addr)
Definition: env_spec_w32.h:352