xref: /reactos/sdk/lib/drivers/sound/mmebuddy/kernel.c (revision 84ccccab)
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