1 /* DirectShow Base Functions (QUARTZ.DLL) 2 * 3 * Copyright 2002 Lionel Ulmer 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 18 */ 19 20 #include "config.h" 21 #include "wine/debug.h" 22 23 #include "quartz_private.h" 24 #include "wine/unicode.h" 25 26 WINE_DEFAULT_DEBUG_CHANNEL(quartz); 27 28 extern HRESULT WINAPI QUARTZ_DllGetClassObject(REFCLSID, REFIID, LPVOID *) DECLSPEC_HIDDEN; 29 extern HRESULT WINAPI QUARTZ_DllCanUnloadNow(void) DECLSPEC_HIDDEN; 30 extern BOOL WINAPI QUARTZ_DllMain(HINSTANCE, DWORD, LPVOID) DECLSPEC_HIDDEN; 31 32 static LONG server_locks = 0; 33 34 /* For the moment, do nothing here. */ 35 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) 36 { 37 return QUARTZ_DllMain( hInstDLL, fdwReason, lpv ); 38 } 39 40 static HRESULT SeekingPassThru_create(IUnknown *pUnkOuter, LPVOID *ppObj) 41 { 42 return PosPassThru_Construct(pUnkOuter,ppObj); /* from strmbase */ 43 } 44 45 /****************************************************************************** 46 * DirectShow ClassFactory 47 */ 48 typedef struct { 49 IClassFactory IClassFactory_iface; 50 LONG ref; 51 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj); 52 } IClassFactoryImpl; 53 54 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface) 55 { 56 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface); 57 } 58 59 struct object_creation_info 60 { 61 const CLSID *clsid; 62 HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj); 63 }; 64 65 static const struct object_creation_info object_creation[] = 66 { 67 { &CLSID_SeekingPassThru, SeekingPassThru_create }, 68 { &CLSID_FilterGraph, FilterGraph_create }, 69 { &CLSID_FilterGraphNoThread, FilterGraphNoThread_create }, 70 { &CLSID_FilterMapper, FilterMapper_create }, 71 { &CLSID_FilterMapper2, FilterMapper2_create }, 72 { &CLSID_AsyncReader, AsyncReader_create }, 73 { &CLSID_MemoryAllocator, StdMemAllocator_create }, 74 { &CLSID_AviSplitter, AVISplitter_create }, 75 { &CLSID_MPEG1Splitter, MPEGSplitter_create }, 76 { &CLSID_VideoRenderer, VideoRenderer_create }, 77 { &CLSID_NullRenderer, NullRenderer_create }, 78 { &CLSID_VideoMixingRenderer, VMR7Impl_create }, 79 { &CLSID_VideoMixingRenderer9, VMR9Impl_create }, 80 { &CLSID_VideoRendererDefault, VideoRendererDefault_create }, 81 { &CLSID_DSoundRender, DSoundRender_create }, 82 { &CLSID_AudioRender, DSoundRender_create }, 83 { &CLSID_AVIDec, AVIDec_create }, 84 { &CLSID_SystemClock, QUARTZ_CreateSystemClock }, 85 { &CLSID_ACMWrapper, ACMWrapper_create }, 86 { &CLSID_WAVEParser, WAVEParser_create } 87 }; 88 89 static HRESULT WINAPI DSCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj) 90 { 91 if (IsEqualGUID(riid, &IID_IUnknown) 92 || IsEqualGUID(riid, &IID_IClassFactory)) 93 { 94 IClassFactory_AddRef(iface); 95 *ppobj = iface; 96 return S_OK; 97 } 98 99 *ppobj = NULL; 100 WARN("(%p)->(%s,%p), not found\n", iface, debugstr_guid(riid), ppobj); 101 return E_NOINTERFACE; 102 } 103 104 static ULONG WINAPI DSCF_AddRef(IClassFactory *iface) 105 { 106 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 107 return InterlockedIncrement(&This->ref); 108 } 109 110 static ULONG WINAPI DSCF_Release(IClassFactory *iface) 111 { 112 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 113 ULONG ref = InterlockedDecrement(&This->ref); 114 115 if (ref == 0) 116 CoTaskMemFree(This); 117 118 return ref; 119 } 120 121 122 static HRESULT WINAPI DSCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter, 123 REFIID riid, void **ppobj) 124 { 125 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 126 HRESULT hres; 127 LPUNKNOWN punk; 128 129 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj); 130 131 *ppobj = NULL; 132 if(pOuter && !IsEqualGUID(&IID_IUnknown, riid)) 133 return E_NOINTERFACE; 134 135 hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk); 136 if (SUCCEEDED(hres)) { 137 hres = IUnknown_QueryInterface(punk, riid, ppobj); 138 IUnknown_Release(punk); 139 } 140 return hres; 141 } 142 143 static HRESULT WINAPI DSCF_LockServer(IClassFactory *iface, BOOL dolock) 144 { 145 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 146 FIXME("(%p)->(%d),stub!\n",This,dolock); 147 if(dolock) 148 InterlockedIncrement(&server_locks); 149 else 150 InterlockedDecrement(&server_locks); 151 return S_OK; 152 } 153 154 static const IClassFactoryVtbl DSCF_Vtbl = 155 { 156 DSCF_QueryInterface, 157 DSCF_AddRef, 158 DSCF_Release, 159 DSCF_CreateInstance, 160 DSCF_LockServer 161 }; 162 163 /******************************************************************************* 164 * DllGetClassObject [QUARTZ.@] 165 * Retrieves class object from a DLL object 166 * 167 * NOTES 168 * Docs say returns STDAPI 169 * 170 * PARAMS 171 * rclsid [I] CLSID for the class object 172 * riid [I] Reference to identifier of interface for class object 173 * ppv [O] Address of variable to receive interface pointer for riid 174 * 175 * RETURNS 176 * Success: S_OK 177 * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG, 178 * E_UNEXPECTED 179 */ 180 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) 181 { 182 unsigned int i; 183 184 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); 185 186 if (IsEqualGUID( &IID_IClassFactory, riid ) || IsEqualGUID( &IID_IUnknown, riid)) 187 { 188 for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++) 189 { 190 if (IsEqualGUID(object_creation[i].clsid, rclsid)) 191 { 192 IClassFactoryImpl *factory = CoTaskMemAlloc(sizeof(*factory)); 193 if (factory == NULL) return E_OUTOFMEMORY; 194 195 factory->IClassFactory_iface.lpVtbl = &DSCF_Vtbl; 196 factory->ref = 1; 197 198 factory->pfnCreateInstance = object_creation[i].pfnCreateInstance; 199 200 *ppv = &factory->IClassFactory_iface; 201 return S_OK; 202 } 203 } 204 } 205 return QUARTZ_DllGetClassObject( rclsid, riid, ppv ); 206 } 207 208 /*********************************************************************** 209 * DllCanUnloadNow (QUARTZ.@) 210 */ 211 HRESULT WINAPI DllCanUnloadNow(void) 212 { 213 if(server_locks == 0 && QUARTZ_DllCanUnloadNow() == S_OK) 214 return S_OK; 215 return S_FALSE; 216 } 217 218 219 #define OUR_GUID_ENTRY(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ 220 { { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } , #name }, 221 222 static const struct { 223 const GUID riid; 224 const char *name; 225 } InterfaceDesc[] = 226 { 227 #include "uuids.h" 228 { { 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0} }, NULL } 229 }; 230 231 /*********************************************************************** 232 * proxies 233 */ 234 HRESULT CALLBACK ICaptureGraphBuilder_FindInterface_Proxy( ICaptureGraphBuilder *This, 235 const GUID *pCategory, 236 IBaseFilter *pf, 237 REFIID riid, 238 void **ppint ) 239 { 240 return ICaptureGraphBuilder_RemoteFindInterface_Proxy( This, pCategory, pf, 241 riid, (IUnknown **)ppint ); 242 } 243 244 HRESULT __RPC_STUB ICaptureGraphBuilder_FindInterface_Stub( ICaptureGraphBuilder *This, 245 const GUID *pCategory, 246 IBaseFilter *pf, 247 REFIID riid, 248 IUnknown **ppint ) 249 { 250 return ICaptureGraphBuilder_FindInterface( This, pCategory, pf, riid, (void **)ppint ); 251 } 252 253 HRESULT CALLBACK ICaptureGraphBuilder2_FindInterface_Proxy( ICaptureGraphBuilder2 *This, 254 const GUID *pCategory, 255 const GUID *pType, 256 IBaseFilter *pf, 257 REFIID riid, 258 void **ppint ) 259 { 260 return ICaptureGraphBuilder2_RemoteFindInterface_Proxy( This, pCategory, pType, 261 pf, riid, (IUnknown **)ppint ); 262 } 263 264 HRESULT __RPC_STUB ICaptureGraphBuilder2_FindInterface_Stub( ICaptureGraphBuilder2 *This, 265 const GUID *pCategory, 266 const GUID *pType, 267 IBaseFilter *pf, 268 REFIID riid, 269 IUnknown **ppint ) 270 { 271 return ICaptureGraphBuilder2_FindInterface( This, pCategory, pType, pf, riid, (void **)ppint ); 272 } 273 274 /*********************************************************************** 275 * qzdebugstr_guid (internal) 276 * 277 * Gives a text version of DirectShow GUIDs 278 */ 279 const char * qzdebugstr_guid( const GUID * id ) 280 { 281 int i; 282 283 for (i=0; InterfaceDesc[i].name; i++) 284 if (IsEqualGUID(&InterfaceDesc[i].riid, id)) return InterfaceDesc[i].name; 285 286 return debugstr_guid(id); 287 } 288 289 LONG WINAPI AmpFactorToDB(LONG ampfactor) 290 { 291 FIXME("(%d) Stub!\n", ampfactor); 292 return 0; 293 } 294 295 LONG WINAPI DBToAmpFactor(LONG db) 296 { 297 FIXME("(%d) Stub!\n", db); 298 /* Avoid divide by zero (probably during range computation) in Windows Media Player 6.4 */ 299 if (db < -1000) 300 return 0; 301 return 100; 302 } 303 304 /*********************************************************************** 305 * AMGetErrorTextA (QUARTZ.@) 306 */ 307 DWORD WINAPI AMGetErrorTextA(HRESULT hr, LPSTR buffer, DWORD maxlen) 308 { 309 DWORD res; 310 WCHAR errorW[MAX_ERROR_TEXT_LEN]; 311 312 TRACE("(%x,%p,%d)\n", hr, buffer, maxlen); 313 if (!buffer) 314 return 0; 315 316 res = AMGetErrorTextW(hr, errorW, sizeof(errorW)/sizeof(*errorW)); 317 return WideCharToMultiByte(CP_ACP, 0, errorW, res, buffer, maxlen, 0, 0); 318 } 319 320 /*********************************************************************** 321 * AMGetErrorTextW (QUARTZ.@) 322 */ 323 DWORD WINAPI AMGetErrorTextW(HRESULT hr, LPWSTR buffer, DWORD maxlen) 324 { 325 unsigned int len; 326 static const WCHAR format[] = {'E','r','r','o','r',':',' ','0','x','%','l','x',0}; 327 WCHAR error[MAX_ERROR_TEXT_LEN]; 328 329 FIXME("(%x,%p,%d) stub\n", hr, buffer, maxlen); 330 331 if (!buffer) return 0; 332 wsprintfW(error, format, hr); 333 if ((len = strlenW(error)) >= maxlen) return 0; 334 lstrcpyW(buffer, error); 335 return len; 336 } 337