Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendevname.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
1.7.6.1
|