1 /*
2  * Interface for dynamically loading directsound and providing a dummy
3  * implementation if it isn't present.
4  *
5  * Author: Ross Bencina (some portions Phil Burk & Robert Marsanyi)
6  *
7  * For PortAudio Portable Real-Time Audio Library
8  * For more information see: http://www.portaudio.com
9  * Copyright (c) 1999-2006 Phil Burk, Robert Marsanyi and Ross Bencina
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining
12  * a copy of this software and associated documentation files
13  * (the "Software"), to deal in the Software without restriction,
14  * including without limitation the rights to use, copy, modify, merge,
15  * publish, distribute, sublicense, and/or sell copies of the Software,
16  * and to permit persons to whom the Software is furnished to do so,
17  * subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be
20  * included in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
26  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
27  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29  */
30 
31 /*
32  * The text above constitutes the entire PortAudio license; however,
33  * the PortAudio community also makes the following non-binding requests:
34  *
35  * Any person wishing to distribute modifications to the Software is
36  * requested to send the modifications to the original developer so that
37  * they can be incorporated into the canonical version. It is also
38  * requested that these non-binding requests be included along with the
39  * license above.
40  */
41 
42 /**
43  @file
44  @ingroup hostapi_src
45 */
46 
47 #include "pa_win_ds_dynlink.h"
48 #include "pa_debugprint.h"
49 
50 PaWinDsDSoundEntryPoints paWinDsDSoundEntryPoints = { 0, 0, 0, 0, 0, 0, 0 };
51 
52 
53 static HRESULT WINAPI DummyDllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
54 {
55     (void)rclsid; /* unused parameter */
56     (void)riid; /* unused parameter */
57     (void)ppv; /* unused parameter */
58     return CLASS_E_CLASSNOTAVAILABLE;
59 }
60 
61 static HRESULT WINAPI DummyDirectSoundCreate(LPGUID lpcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter)
62 {
63     (void)lpcGuidDevice; /* unused parameter */
64     (void)ppDS; /* unused parameter */
65     (void)pUnkOuter; /* unused parameter */
66     return E_NOTIMPL;
67 }
68 
69 static HRESULT WINAPI DummyDirectSoundEnumerateW(LPDSENUMCALLBACKW lpDSEnumCallback, LPVOID lpContext)
70 {
71     (void)lpDSEnumCallback; /* unused parameter */
72     (void)lpContext; /* unused parameter */
73     return E_NOTIMPL;
74 }
75 
76 static HRESULT WINAPI DummyDirectSoundEnumerateA(LPDSENUMCALLBACKA lpDSEnumCallback, LPVOID lpContext)
77 {
78     (void)lpDSEnumCallback; /* unused parameter */
79     (void)lpContext; /* unused parameter */
80     return E_NOTIMPL;
81 }
82 
83 static HRESULT WINAPI DummyDirectSoundCaptureCreate(LPGUID lpcGUID, LPDIRECTSOUNDCAPTURE *lplpDSC, LPUNKNOWN pUnkOuter)
84 {
85     (void)lpcGUID; /* unused parameter */
86     (void)lplpDSC; /* unused parameter */
87     (void)pUnkOuter; /* unused parameter */
88     return E_NOTIMPL;
89 }
90 
91 static HRESULT WINAPI DummyDirectSoundCaptureEnumerateW(LPDSENUMCALLBACKW lpDSCEnumCallback, LPVOID lpContext)
92 {
93     (void)lpDSCEnumCallback; /* unused parameter */
94     (void)lpContext; /* unused parameter */
95     return E_NOTIMPL;
96 }
97 
98 static HRESULT WINAPI DummyDirectSoundCaptureEnumerateA(LPDSENUMCALLBACKA lpDSCEnumCallback, LPVOID lpContext)
99 {
100     (void)lpDSCEnumCallback; /* unused parameter */
101     (void)lpContext; /* unused parameter */
102     return E_NOTIMPL;
103 }
104 
105 #ifdef PAWIN_USE_DIRECTSOUNDFULLDUPLEXCREATE
106 static HRESULT WINAPI DummyDirectSoundFullDuplexCreate8(
107          LPCGUID pcGuidCaptureDevice,
108          LPCGUID pcGuidRenderDevice,
109          LPCDSCBUFFERDESC pcDSCBufferDesc,
110          LPCDSBUFFERDESC pcDSBufferDesc,
111          HWND hWnd,
112          DWORD dwLevel,
113          LPDIRECTSOUNDFULLDUPLEX * ppDSFD,
114          LPDIRECTSOUNDCAPTUREBUFFER8 * ppDSCBuffer8,
115          LPDIRECTSOUNDBUFFER8 * ppDSBuffer8,
116          LPUNKNOWN pUnkOuter)
117 {
118     (void)pcGuidCaptureDevice; /* unused parameter */
119     (void)pcGuidRenderDevice; /* unused parameter */
120     (void)pcDSCBufferDesc; /* unused parameter */
121     (void)pcDSBufferDesc; /* unused parameter */
122     (void)hWnd; /* unused parameter */
123     (void)dwLevel; /* unused parameter */
124     (void)ppDSFD; /* unused parameter */
125     (void)ppDSCBuffer8; /* unused parameter */
126     (void)ppDSBuffer8; /* unused parameter */
127     (void)pUnkOuter; /* unused parameter */
128 
129     return E_NOTIMPL;
130 }
131 #endif /* PAWIN_USE_DIRECTSOUNDFULLDUPLEXCREATE */
132 
133 void PaWinDs_InitializeDSoundEntryPoints(void)
134 {
135     paWinDsDSoundEntryPoints.hInstance_ = LoadLibraryA("dsound.dll");
136     if( paWinDsDSoundEntryPoints.hInstance_ != NULL )
137     {
138         paWinDsDSoundEntryPoints.DllGetClassObject =
139                 (HRESULT (WINAPI *)(REFCLSID, REFIID , LPVOID *))
140                 GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DllGetClassObject" );
141         if( paWinDsDSoundEntryPoints.DllGetClassObject == NULL )
142             paWinDsDSoundEntryPoints.DllGetClassObject = DummyDllGetClassObject;
143 
144         paWinDsDSoundEntryPoints.DirectSoundCreate =
145                 (HRESULT (WINAPI *)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN))
146                 GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundCreate" );
147         if( paWinDsDSoundEntryPoints.DirectSoundCreate == NULL )
148             paWinDsDSoundEntryPoints.DirectSoundCreate = DummyDirectSoundCreate;
149 
150         paWinDsDSoundEntryPoints.DirectSoundEnumerateW =
151                 (HRESULT (WINAPI *)(LPDSENUMCALLBACKW, LPVOID))
152                 GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundEnumerateW" );
153         if( paWinDsDSoundEntryPoints.DirectSoundEnumerateW == NULL )
154             paWinDsDSoundEntryPoints.DirectSoundEnumerateW = DummyDirectSoundEnumerateW;
155 
156         paWinDsDSoundEntryPoints.DirectSoundEnumerateA =
157                 (HRESULT (WINAPI *)(LPDSENUMCALLBACKA, LPVOID))
158                 GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundEnumerateA" );
159         if( paWinDsDSoundEntryPoints.DirectSoundEnumerateA == NULL )
160             paWinDsDSoundEntryPoints.DirectSoundEnumerateA = DummyDirectSoundEnumerateA;
161 
162         paWinDsDSoundEntryPoints.DirectSoundCaptureCreate =
163                 (HRESULT (WINAPI *)(LPGUID, LPDIRECTSOUNDCAPTURE *, LPUNKNOWN))
164                 GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundCaptureCreate" );
165         if( paWinDsDSoundEntryPoints.DirectSoundCaptureCreate == NULL )
166             paWinDsDSoundEntryPoints.DirectSoundCaptureCreate = DummyDirectSoundCaptureCreate;
167 
168         paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateW =
169                 (HRESULT (WINAPI *)(LPDSENUMCALLBACKW, LPVOID))
170                 GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundCaptureEnumerateW" );
171         if( paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateW == NULL )
172             paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateW = DummyDirectSoundCaptureEnumerateW;
173 
174         paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA =
175                 (HRESULT (WINAPI *)(LPDSENUMCALLBACKA, LPVOID))
176                 GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundCaptureEnumerateA" );
177         if( paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA == NULL )
178             paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA = DummyDirectSoundCaptureEnumerateA;
179 
180 #ifdef PAWIN_USE_DIRECTSOUNDFULLDUPLEXCREATE
181         paWinDsDSoundEntryPoints.DirectSoundFullDuplexCreate8 =
182                 (HRESULT (WINAPI *)(LPCGUID, LPCGUID, LPCDSCBUFFERDESC, LPCDSBUFFERDESC,
183                                     HWND, DWORD, LPDIRECTSOUNDFULLDUPLEX *, LPDIRECTSOUNDCAPTUREBUFFER8 *,
184                                     LPDIRECTSOUNDBUFFER8 *, LPUNKNOWN))
185                 GetProcAddress( paWinDsDSoundEntryPoints.hInstance_, "DirectSoundFullDuplexCreate" );
186         if( paWinDsDSoundEntryPoints.DirectSoundFullDuplexCreate8 == NULL )
187             paWinDsDSoundEntryPoints.DirectSoundFullDuplexCreate8 = DummyDirectSoundFullDuplexCreate8;
188 #endif
189     }
190     else
191     {
192         DWORD errorCode = GetLastError(); // 126 (0x7E) == ERROR_MOD_NOT_FOUND
193         PA_DEBUG(("Couldn't load dsound.dll error code: %d \n",errorCode));
194 
195         /* initialize with dummy entry points to make live easy when ds isn't present */
196         paWinDsDSoundEntryPoints.DirectSoundCreate = DummyDirectSoundCreate;
197         paWinDsDSoundEntryPoints.DirectSoundEnumerateW = DummyDirectSoundEnumerateW;
198         paWinDsDSoundEntryPoints.DirectSoundEnumerateA = DummyDirectSoundEnumerateA;
199         paWinDsDSoundEntryPoints.DirectSoundCaptureCreate = DummyDirectSoundCaptureCreate;
200         paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateW = DummyDirectSoundCaptureEnumerateW;
201         paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA = DummyDirectSoundCaptureEnumerateA;
202 #ifdef PAWIN_USE_DIRECTSOUNDFULLDUPLEXCREATE
203         paWinDsDSoundEntryPoints.DirectSoundFullDuplexCreate8 = DummyDirectSoundFullDuplexCreate8;
204 #endif
205     }
206 }
207 
208 
209 void PaWinDs_TerminateDSoundEntryPoints(void)
210 {
211     if( paWinDsDSoundEntryPoints.hInstance_ != NULL )
212     {
213         /* ensure that we crash reliably if the entry points arent initialised */
214         paWinDsDSoundEntryPoints.DirectSoundCreate = 0;
215         paWinDsDSoundEntryPoints.DirectSoundEnumerateW = 0;
216         paWinDsDSoundEntryPoints.DirectSoundEnumerateA = 0;
217         paWinDsDSoundEntryPoints.DirectSoundCaptureCreate = 0;
218         paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateW = 0;
219         paWinDsDSoundEntryPoints.DirectSoundCaptureEnumerateA = 0;
220 
221         FreeLibrary( paWinDsDSoundEntryPoints.hInstance_ );
222         paWinDsDSoundEntryPoints.hInstance_ = NULL;
223     }
224 }