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