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
OpenKernelSoundDeviceByName(IN PWSTR DevicePath,IN BOOLEAN ReadOnly,OUT PHANDLE Handle)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
CloseKernelSoundDevice(IN HANDLE Handle)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
SyncOverlappedDeviceIoControl(IN HANDLE Handle,IN DWORD IoControlCode,IN LPVOID InBuffer,IN DWORD InBufferSize,OUT LPVOID OutBuffer,IN DWORD OutBufferSize,OUT LPDWORD BytesTransferred OPTIONAL)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