1 /* 2 * PROJECT: ReactOS Sound System "MME Buddy" Library 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: lib/drivers/sound/mmebuddy/kernel.c 5 * 6 * PURPOSE: Routines assisting with device I/O between user-mode and 7 * kernel-mode. 8 * 9 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org) 10 */ 11 12 #include "precomp.h" 13 14 /* 15 Wraps around CreateFile in order to provide a simpler interface tailored 16 towards sound driver support code. This simply takes a device path and 17 opens the device in either read-only mode, or read/write mode (depending on 18 the ReadOnly parameter). 19 20 If the device is opened in read/write mode, it is opened for overlapped I/O. 21 */ 22 MMRESULT 23 OpenKernelSoundDeviceByName( 24 IN PWSTR DevicePath, 25 IN BOOLEAN ReadOnly, 26 OUT PHANDLE Handle) 27 { 28 DWORD AccessRights; 29 30 VALIDATE_MMSYS_PARAMETER( DevicePath ); 31 VALIDATE_MMSYS_PARAMETER( Handle ); 32 33 AccessRights = ReadOnly ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE; 34 35 SND_TRACE(L"OpenKernelSoundDeviceByName: %wS\n", DevicePath); 36 *Handle = CreateFile(DevicePath, 37 AccessRights, 38 FILE_SHARE_WRITE, /* FIXME? Should be read also? */ 39 NULL, 40 OPEN_EXISTING, 41 ReadOnly ? 0 : FILE_FLAG_OVERLAPPED, 42 NULL); 43 44 if ( *Handle == INVALID_HANDLE_VALUE ) 45 { 46 SND_ERR(L"CreateFile filed - winerror %d\n", GetLastError()); 47 return Win32ErrorToMmResult(GetLastError()); 48 } 49 50 return MMSYSERR_NOERROR; 51 } 52 53 54 /* 55 Just a wrapped around CloseHandle. 56 */ 57 MMRESULT 58 CloseKernelSoundDevice( 59 IN HANDLE Handle) 60 { 61 VALIDATE_MMSYS_PARAMETER( Handle ); 62 63 CloseHandle(Handle); 64 65 return MMSYSERR_NOERROR; 66 } 67 68 /* 69 This is a wrapper around DeviceIoControl which provides control over 70 instantiated sound devices. It waits for I/O to complete (since an 71 instantiated sound device is opened in overlapped mode, this is necessary). 72 */ 73 MMRESULT 74 SyncOverlappedDeviceIoControl( 75 IN HANDLE Handle, 76 IN DWORD IoControlCode, 77 IN LPVOID InBuffer, 78 IN DWORD InBufferSize, 79 OUT LPVOID OutBuffer, 80 IN DWORD OutBufferSize, 81 OUT LPDWORD BytesTransferred OPTIONAL) 82 { 83 OVERLAPPED Overlapped; 84 BOOLEAN IoResult; 85 DWORD Transferred; 86 87 /* Overlapped I/O is done here - this is used for waiting for completion */ 88 ZeroMemory(&Overlapped, sizeof(OVERLAPPED)); 89 Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 90 91 if ( ! Overlapped.hEvent ) 92 return Win32ErrorToMmResult(GetLastError()); 93 94 /* Talk to the device */ 95 IoResult = DeviceIoControl(Handle, 96 IoControlCode, 97 InBuffer, 98 InBufferSize, 99 OutBuffer, 100 OutBufferSize, 101 NULL, 102 &Overlapped); 103 104 /* If failure occurs, make sure it's not just due to the overlapped I/O */ 105 if ( ! IoResult ) 106 { 107 if ( GetLastError() != ERROR_IO_PENDING ) 108 { 109 CloseHandle(Overlapped.hEvent); 110 return Win32ErrorToMmResult(GetLastError()); 111 } 112 } 113 114 /* Wait for the I/O to complete */ 115 IoResult = GetOverlappedResult(Handle, 116 &Overlapped, 117 &Transferred, 118 TRUE); 119 120 /* Don't need this any more */ 121 CloseHandle(Overlapped.hEvent); 122 123 if ( ! IoResult ) 124 return Win32ErrorToMmResult(GetLastError()); 125 126 SND_TRACE(L"Transferred %d bytes in Sync overlapped I/O\n", Transferred); 127 128 if ( BytesTransferred ) 129 *BytesTransferred = Transferred; 130 131 return MMSYSERR_NOERROR; 132 } 133