ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

devname.c
Go to the documentation of this file.
00001 /*
00002     ReactOS Sound System
00003     Device naming & creation helper routines
00004 
00005     Author:
00006         Andrew Greenwood (silverblade@reactos.org)
00007 
00008     History:
00009         25 May 2008 - Created
00010 */
00011 
00012 #include <ntddk.h>
00013 #include <ntddsnd.h>
00014 #include <sndnames.h>
00015 #include <sndtypes.h>
00016 #include <debug.h>
00017 
00018 
00019 /*
00020     Default device names
00021 
00022     Just to keep things tidy, we define a structure to hold both the \\Device
00023     and \\DosDevices names, and then fill this structure with the default
00024     device names that can be found in NTDDSND.H
00025 */
00026 
00027 typedef struct _DEVICE_NAME_GROUP
00028 {
00029     PCWSTR DeviceName;
00030     PCWSTR DosDeviceName;
00031 } DEVICE_NAME_GROUP;
00032 
00033 DEVICE_NAME_GROUP SoundDeviceNameBodies[6] =
00034 {
00035     {
00036         DD_WAVE_IN_DEVICE_NAME_U,
00037         DD_WAVE_IN_DOS_DEVICE_NAME_U
00038     },
00039     {
00040         DD_WAVE_OUT_DEVICE_NAME_U,
00041         DD_WAVE_OUT_DOS_DEVICE_NAME_U
00042     },
00043     {
00044         DD_MIDI_IN_DEVICE_NAME_U,
00045         DD_MIDI_IN_DOS_DEVICE_NAME_U
00046     },
00047     {
00048         DD_MIDI_OUT_DEVICE_NAME_U,
00049         DD_MIDI_OUT_DOS_DEVICE_NAME_U
00050     },
00051     {
00052         DD_MIX_DEVICE_NAME_U,
00053         DD_MIX_DOS_DEVICE_NAME_U
00054     },
00055     {
00056         DD_AUX_DEVICE_NAME_U,
00057         DD_AUX_DOS_DEVICE_NAME_U
00058     }
00059 };
00060 
00061 
00062 /*
00063     ConstructDeviceName
00064 
00065     This takes a wide-character string containing the device name body (for
00066     example, "\\Device\\WaveOut") and appends the device index, forming a
00067     string like "\\Device\\WaveOut0", and so on.
00068 
00069     The resulting device name is a unicode string.
00070 */
00071 
00072 NTSTATUS
00073 ConstructDeviceName(
00074     IN  PCWSTR Path,
00075     IN  UCHAR Index,
00076     OUT PUNICODE_STRING DeviceName)
00077 {
00078     UNICODE_STRING UnicodePath;
00079     UNICODE_STRING UnicodeIndex;
00080     WCHAR IndexStringBuffer[5];
00081     USHORT Size;
00082     USHORT LastCharacterIndex;
00083 
00084     /* Check for NULL parameters */
00085     if ( ( ! Path ) || ( ! DeviceName ) )
00086     {
00087         DPRINT("Unexpected NULL parameter");
00088         return STATUS_INVALID_PARAMETER;
00089     }
00090 
00091     /* Range-check */
00092     if ( Index >= SOUND_MAX_DEVICES )
00093     {
00094         DPRINT("Device index %d out of range", Index);
00095         return STATUS_INVALID_PARAMETER;
00096     }
00097 
00098     /* Initialise the unicode path string */
00099     RtlInitUnicodeString(&UnicodePath, Path);
00100 
00101     /* Calculate the length to hold the full string */
00102     Size = UnicodePath.Length +
00103            sizeof(IndexStringBuffer) +
00104            sizeof(UNICODE_NULL);
00105 
00106     /* Allocate memory for DeviceName */
00107     DeviceName->Buffer = ExAllocatePool(PagedPool, Size);
00108     DeviceName->MaximumLength = Size;
00109 
00110     if ( ! DeviceName->Buffer )
00111     {
00112         DPRINT("Couldn't allocate memory for device name string");
00113         return STATUS_INSUFFICIENT_RESOURCES;
00114     }
00115 
00116     /* Copy the path */
00117     RtlCopyUnicodeString(DeviceName, &UnicodePath);
00118 
00119     /* Convert Index to string and append */
00120     UnicodeIndex.Buffer = IndexStringBuffer;
00121     UnicodeIndex.MaximumLength = sizeof(IndexStringBuffer);
00122 
00123     RtlIntegerToUnicodeString((ULONG)Index, 10, &UnicodeIndex);
00124     RtlAppendUnicodeStringToString(DeviceName, &UnicodeIndex);
00125 
00126     /* Terminate the string */
00127     LastCharacterIndex = DeviceName->Length / sizeof(UNICODE_NULL);
00128     DeviceName->Buffer[LastCharacterIndex] = UNICODE_NULL;
00129 
00130     return STATUS_SUCCESS;
00131 }
00132 
00133 
00134 /*
00135     FreeUnicodeStringBuffer
00136 
00137     A small helper routine to free a unicode string buffer, nullify the
00138     buffer and reset the lengths to zero.
00139 */
00140 
00141 VOID
00142 FreeUnicodeStringBuffer(IN PUNICODE_STRING String)
00143 {
00144     ASSERT(String != NULL);
00145     ASSERT(String->Buffer != NULL);
00146 
00147     ExFreePool(String->Buffer);
00148 
00149     String->Buffer = NULL;
00150     String->Length = 0;
00151     String->MaximumLength = 0;
00152 }
00153 
00154 
00155 /*
00156     GetDefaultSoundDeviceNameBodies
00157 
00158     Simply accesses the SoundDeviceNameBodies struct defined earlier and
00159     fills the DeviceNameBody and DosDeviceNameBody parameters accordingly.
00160 
00161     Basically a "safe" way to access the array and perform two assignments
00162     with one call, as this will assign the name and DOS name if a valid
00163     DeviceType is passed, otherwise it will fail with STATUS_INVALID_PARAMETER.
00164 */
00165 
00166 NTSTATUS
00167 GetDefaultSoundDeviceNameBodies(
00168     IN  UCHAR DeviceType,
00169     OUT PCWSTR* DeviceNameBody,
00170     OUT PCWSTR* DosDeviceNameBody)
00171 {
00172     if ( ! IS_VALID_SOUND_DEVICE_TYPE(DeviceType) )
00173     {
00174         DPRINT("Invalid device type");
00175         return STATUS_INVALID_PARAMETER;
00176     }
00177 
00178     if ( DeviceNameBody )
00179     {
00180         DPRINT("Reporting device name\n");
00181         *DeviceNameBody = SoundDeviceNameBodies[DeviceType].DeviceName;
00182         DPRINT("%ws\n", *DeviceNameBody);
00183     }
00184 
00185     if ( DosDeviceNameBody )
00186     {
00187         DPRINT("Reporting DOS device name\n");
00188         *DosDeviceNameBody = SoundDeviceNameBodies[DeviceType].DosDeviceName;
00189         DPRINT("%ws\n", *DosDeviceNameBody);
00190     }
00191 
00192     return STATUS_SUCCESS;
00193 }
00194 
00195 
00196 /*
00197     ConstructSoundDeviceNames
00198 
00199     Given two wide-character strings and a device index, convert these into
00200     two unicode strings with the index appended to the end.
00201 
00202     This is intended for converting a device name and a DOS device name at
00203     the same time.
00204 */
00205 
00206 NTSTATUS
00207 ConstructSoundDeviceNames(
00208     IN  PCWSTR DeviceNameBody,
00209     IN  PCWSTR DosDeviceNameBody,
00210     IN  UCHAR Index,
00211     OUT PUNICODE_STRING FullDeviceName,
00212     OUT PUNICODE_STRING FullDosDeviceName)
00213 {
00214     NTSTATUS Status;
00215 
00216     /* Check for NULL parameters */
00217     if ( ( ! DeviceNameBody ) || ( ! DosDeviceNameBody ) ||
00218          ( ! FullDeviceName ) || ( ! FullDosDeviceName ) )
00219     {
00220         DPRINT("Unexpected NULL parameter");
00221         return STATUS_INVALID_PARAMETER;
00222     }
00223 
00224     /* Range-check */
00225     if ( Index >= SOUND_MAX_DEVICES )
00226     {
00227         DPRINT("Device %d exceeds maximum", Index);
00228         return STATUS_INVALID_PARAMETER;
00229     }
00230 
00231     Status = ConstructDeviceName(DeviceNameBody, Index, FullDeviceName);
00232 
00233     if ( ! NT_SUCCESS(Status) )
00234     {
00235         /* No need to clean up on failure here */
00236         return Status;
00237     }
00238 
00239     Status = ConstructDeviceName(DosDeviceNameBody, Index, FullDosDeviceName);
00240 
00241     if ( ! NT_SUCCESS(Status) )
00242     {
00243         /* We need to free the string we successfully got earlier */
00244         FreeUnicodeStringBuffer(FullDeviceName);
00245         return Status;
00246     }
00247 
00248     return STATUS_SUCCESS;
00249 }
00250 
00251 
00252 /*
00253     CreateSoundDevice
00254 
00255     Creates a device and symbolically-links a DOS device to this. Use this
00256     when you want to specify alternative device names to the defaults
00257     (eg: "\\Device\\MySoundDev" rather than "\\Device\\WaveOut")
00258 */
00259 
00260 NTSTATUS
00261 CreateSoundDevice(
00262     IN  PDRIVER_OBJECT DriverObject,
00263     IN  PCWSTR WideDeviceName,
00264     IN  PCWSTR WideDosDeviceName,
00265     IN  UCHAR Index,
00266     IN  ULONG ExtensionSize,
00267     OUT PDEVICE_OBJECT* DeviceObject)
00268 {
00269     NTSTATUS Status;
00270 
00271     UNICODE_STRING DeviceName;
00272     UNICODE_STRING DosDeviceName;
00273 
00274     /* Check for NULL parameters */
00275     if ( ( ! DriverObject ) || ( ! DeviceObject ) ||
00276          ( ! WideDeviceName ) || ( ! WideDosDeviceName ) )
00277     {
00278         DPRINT("Unexpected NULL parameter");
00279         return STATUS_INVALID_PARAMETER;
00280     }
00281 
00282     /* Range-check */
00283     if ( Index >= SOUND_MAX_DEVICES )
00284     {
00285         DPRINT("Device index %d exceeds maximum", Index);
00286         return STATUS_INVALID_PARAMETER;
00287     }
00288 
00289     /* Construct the device and DOS device names */
00290     Status = ConstructSoundDeviceNames(WideDeviceName,
00291                                        WideDosDeviceName,
00292                                        Index,
00293                                        &DeviceName,
00294                                        &DosDeviceName);
00295 
00296     if ( ! NT_SUCCESS(Status) )
00297     {
00298         return Status;
00299     }
00300 
00301     DPRINT("Creating device %ws\n", DeviceName.Buffer);
00302 
00303     /* Now create the device */
00304     Status = IoCreateDevice(DriverObject,
00305                             ExtensionSize,
00306                             &DeviceName,
00307                             FILE_DEVICE_SOUND,
00308                             0,
00309                             FALSE,
00310                             DeviceObject);
00311 
00312     if ( ! NT_SUCCESS(Status) )
00313     {
00314         /* These will have been allocated by ConstructSoundDeviceNames */
00315         FreeUnicodeStringBuffer(&DeviceName);
00316         FreeUnicodeStringBuffer(&DosDeviceName);
00317 
00318         return Status;
00319     }
00320 
00321     DPRINT("Creating link %ws\n", DosDeviceName.Buffer);
00322 
00323     /* Create a symbolic link for the DOS deviec name */
00324     Status = IoCreateSymbolicLink(&DosDeviceName, &DeviceName);
00325 
00326     if ( ! NT_SUCCESS(Status) )
00327     {
00328         IoDeleteDevice(*DeviceObject);
00329 
00330         /* These will have been allocated by ConstructSoundDeviceNames */
00331         FreeUnicodeStringBuffer(&DeviceName);
00332         FreeUnicodeStringBuffer(&DosDeviceName);
00333 
00334         return Status;
00335     }
00336 
00337     return STATUS_SUCCESS;
00338 }
00339 
00340 
00341 /*
00342     CreateSoundDeviceWithDefaultName
00343 
00344     Similar to CreateSoundDevice, except this uses the default device names
00345     ("\\Device\\WaveOut" etc.) based on the DeviceType parameter.
00346 */
00347 
00348 NTSTATUS
00349 CreateSoundDeviceWithDefaultName(
00350     IN  PDRIVER_OBJECT DriverObject,
00351     IN  UCHAR DeviceType,
00352     IN  UCHAR Index,
00353     IN  ULONG ExtensionSize,
00354     OUT PDEVICE_OBJECT* DeviceObject)
00355 {
00356     NTSTATUS Status;
00357     PCWSTR WideDeviceName = NULL;
00358     PCWSTR WideDosDeviceName = NULL;
00359 
00360     /* Check for NULL parameters */
00361     if ( ( ! DriverObject ) || ( ! DeviceObject ) )
00362     {
00363         DPRINT("Unexpected NULL parameter");
00364         return STATUS_INVALID_PARAMETER;
00365     }
00366 
00367     /* Range-check */
00368     if ( Index >= SOUND_MAX_DEVICES )
00369     {
00370         DPRINT("Device index %d exceeds maximum", Index);
00371         return STATUS_INVALID_PARAMETER;
00372     }
00373 
00374     /* Look-up the default name based on the device type */
00375     Status = GetDefaultSoundDeviceNameBodies(DeviceType,
00376                                              &WideDeviceName,
00377                                              &WideDosDeviceName);
00378 
00379     if ( ! NT_SUCCESS(Status) )
00380     {
00381         return Status;
00382     }
00383 
00384     /* Go create the device! */
00385     Status = CreateSoundDevice(DriverObject,
00386                                WideDeviceName,
00387                                WideDosDeviceName,
00388                                Index,
00389                                ExtensionSize,
00390                                DeviceObject);
00391 
00392     if ( ! NT_SUCCESS(Status) )
00393     {
00394         /* No clean-up to do */
00395         return Status;
00396     }
00397 
00398     return STATUS_SUCCESS;
00399 }
00400 
00401 NTSTATUS
00402 DestroySoundDevice(
00403     IN  PDEVICE_OBJECT DeviceObject,
00404     IN  PCWSTR WideDosDeviceName,
00405     IN  UCHAR Index)
00406 {
00407     NTSTATUS Status;
00408     UNICODE_STRING DosDeviceName;
00409 
00410     /* Check for NULL parameters */
00411     if ( ( ! WideDosDeviceName ) || ( ! DeviceObject ) )
00412     {
00413         DPRINT("Unexpected NULL parameter");
00414         return STATUS_INVALID_PARAMETER;
00415     }
00416 
00417     /* Range-check */
00418     if ( Index >= SOUND_MAX_DEVICES )
00419     {
00420         DPRINT("Device %d exceeds maximum", Index);
00421         return STATUS_INVALID_PARAMETER;
00422     }
00423 
00424     Status = ConstructDeviceName(WideDosDeviceName, Index, &DosDeviceName);
00425 
00426     if ( ! NT_SUCCESS(Status) )
00427     {
00428         return Status;
00429     }
00430 
00431     DPRINT("Deleting symlink %ws\n", DosDeviceName.Buffer);
00432 
00433     Status = IoDeleteSymbolicLink(&DosDeviceName);
00434     DPRINT("Status of symlink deletion is 0x%08x\n", Status);
00435 /*
00436     ASSERT(NT_SUCCESS(Status));
00437 */
00438 
00439     IoDeleteDevice(DeviceObject);
00440 
00441     return STATUS_SUCCESS;
00442 }
00443 
00444 NTSTATUS
00445 DestroySoundDeviceWithDefaultName(
00446     IN  PDEVICE_OBJECT DeviceObject,
00447     IN  UCHAR DeviceType,
00448     IN  UCHAR Index)
00449 {
00450     NTSTATUS Status;
00451     PCWSTR WideDosDeviceName = NULL;
00452 
00453     /* Check for NULL parameters */
00454     if ( ( ! DeviceObject ) )
00455     {
00456         DPRINT("Unexpected NULL parameter");
00457         return STATUS_INVALID_PARAMETER;
00458     }
00459 
00460     /* Range-check */
00461     if ( Index >= SOUND_MAX_DEVICES )
00462     {
00463         DPRINT("Device index %d exceeds maximum", Index);
00464         return STATUS_INVALID_PARAMETER;
00465     }
00466 
00467     /* Look-up the default name based on the device type */
00468     Status = GetDefaultSoundDeviceNameBodies(DeviceType,
00469                                              NULL,
00470                                              &WideDosDeviceName);
00471 
00472     if ( ! NT_SUCCESS(Status) )
00473     {
00474         return Status;
00475     }
00476 
00477     DPRINT("DOS device name at %p\n", WideDosDeviceName);
00478 
00479     DPRINT("DOS device name is based on %ws\n", WideDosDeviceName);
00480 
00481     return DestroySoundDevice(DeviceObject, WideDosDeviceName, Index);
00482 }

Generated on Sat May 26 2012 04:35:02 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.