1 /* 2 * Strmbase DLL functions 3 * 4 * Copyright (C) 2005 Rolf Kalbermatter 5 * Copyright (C) 2010 Aric Stewart, CodeWeavers 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 #include "config.h" 22 23 #include <stdarg.h> 24 #include <assert.h> 25 26 #define COBJMACROS 27 #define NONAMELESSSTRUCT 28 #define NONAMELESSUNION 29 30 #include "windef.h" 31 #include "winbase.h" 32 #include "wingdi.h" 33 #include "winerror.h" 34 #include "winreg.h" 35 #include "objbase.h" 36 #include "uuids.h" 37 #include "strmif.h" 38 39 #include "wine/unicode.h" 40 #include "wine/debug.h" 41 #include "wine/strmbase.h" 42 43 WINE_DEFAULT_DEBUG_CHANNEL(strmbase); 44 45 extern const int g_cTemplates; 46 extern const FactoryTemplate g_Templates[]; 47 48 static HINSTANCE g_hInst = NULL; 49 static LONG server_locks = 0; 50 51 /* 52 * defines and constants 53 */ 54 55 static const WCHAR clsid_keyname[] = {'C','L','S','I','D',0 }; 56 static const WCHAR ips32_keyname[] = {'I','n','P','r','o','c','S','e','r','v','e','r','3','2',0}; 57 static const WCHAR tmodel_keyname[] = {'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0}; 58 static const WCHAR tmodel_both[] = {'B','o','t','h',0}; 59 60 /* 61 * SetupRegisterClass() 62 */ 63 static HRESULT SetupRegisterClass(HKEY clsid, LPCWSTR szCLSID, 64 LPCWSTR szDescription, 65 LPCWSTR szFileName, 66 LPCWSTR szServerType, 67 LPCWSTR szThreadingModel) 68 { 69 HKEY hkey, hsubkey = NULL; 70 LONG ret = RegCreateKeyW(clsid, szCLSID, &hkey); 71 if (ERROR_SUCCESS != ret) 72 return HRESULT_FROM_WIN32(ret); 73 74 /* set description string */ 75 ret = RegSetValueW(hkey, NULL, REG_SZ, szDescription, 76 sizeof(WCHAR) * (lstrlenW(szDescription) + 1)); 77 if (ERROR_SUCCESS != ret) 78 goto err_out; 79 80 /* create CLSID\\{"CLSID"}\\"ServerType" key, using key to CLSID\\{"CLSID"} 81 passed back by last call to RegCreateKeyW(). */ 82 ret = RegCreateKeyW(hkey, szServerType, &hsubkey); 83 if (ERROR_SUCCESS != ret) 84 goto err_out; 85 86 /* set server path */ 87 ret = RegSetValueW(hsubkey, NULL, REG_SZ, szFileName, 88 sizeof(WCHAR) * (lstrlenW(szFileName) + 1)); 89 if (ERROR_SUCCESS != ret) 90 goto err_out; 91 92 /* set threading model */ 93 ret = RegSetValueExW(hsubkey, tmodel_keyname, 0L, REG_SZ, 94 (const BYTE*)szThreadingModel, 95 sizeof(WCHAR) * (lstrlenW(szThreadingModel) + 1)); 96 err_out: 97 if (hsubkey) 98 RegCloseKey(hsubkey); 99 RegCloseKey(hkey); 100 return HRESULT_FROM_WIN32(ret); 101 } 102 103 /* 104 * RegisterAllClasses() 105 */ 106 static HRESULT SetupRegisterAllClasses(const FactoryTemplate * pList, int num, 107 LPCWSTR szFileName, BOOL bRegister) 108 { 109 HRESULT hr = NOERROR; 110 HKEY hkey; 111 OLECHAR szCLSID[CHARS_IN_GUID]; 112 LONG i, ret = RegCreateKeyW(HKEY_CLASSES_ROOT, clsid_keyname, &hkey); 113 if (ERROR_SUCCESS != ret) 114 return HRESULT_FROM_WIN32(ret); 115 116 for (i = 0; i < num; i++, pList++) 117 { 118 /* (un)register CLSID and InprocServer32 */ 119 hr = StringFromGUID2(pList->m_ClsID, szCLSID, CHARS_IN_GUID); 120 if (SUCCEEDED(hr)) 121 { 122 if (bRegister ) 123 hr = SetupRegisterClass(hkey, szCLSID, 124 pList->m_Name, szFileName, 125 ips32_keyname, tmodel_both); 126 else 127 hr = RegDeleteTreeW(hkey, szCLSID); 128 } 129 } 130 RegCloseKey(hkey); 131 return hr; 132 } 133 134 HRESULT WINAPI AMovieSetupRegisterFilter2(const AMOVIESETUP_FILTER *pFilter, IFilterMapper2 *pIFM2, BOOL bRegister) 135 { 136 if (!pFilter) 137 return S_OK; 138 139 if (bRegister) 140 { 141 { 142 REGFILTER2 rf2; 143 rf2.dwVersion = 1; 144 rf2.dwMerit = pFilter->merit; 145 rf2.u.s1.cPins = pFilter->pins; 146 rf2.u.s1.rgPins = pFilter->pPin; 147 148 return IFilterMapper2_RegisterFilter(pIFM2, pFilter->clsid, pFilter->name, NULL, &CLSID_LegacyAmFilterCategory, NULL, &rf2); 149 } 150 } 151 else 152 return IFilterMapper2_UnregisterFilter(pIFM2, &CLSID_LegacyAmFilterCategory, NULL, pFilter->clsid); 153 } 154 155 HRESULT WINAPI AMovieDllRegisterServer2(BOOL bRegister) 156 { 157 HRESULT hr; 158 int i; 159 IFilterMapper2 *pIFM2 = NULL; 160 WCHAR szFileName[MAX_PATH]; 161 162 if (!GetModuleFileNameW(g_hInst, szFileName, MAX_PATH)) 163 { 164 ERR("Failed to get module file name for registration\n"); 165 return E_FAIL; 166 } 167 168 if (bRegister) 169 hr = SetupRegisterAllClasses(g_Templates, g_cTemplates, szFileName, TRUE ); 170 171 CoInitialize(NULL); 172 173 TRACE("Getting IFilterMapper2\r\n"); 174 hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, 175 &IID_IFilterMapper2, (void **)&pIFM2); 176 177 for (i = 0; SUCCEEDED(hr) && i < g_cTemplates; i++) 178 hr = AMovieSetupRegisterFilter2(g_Templates[i].m_pAMovieSetup_Filter, pIFM2, bRegister); 179 180 /* release interface */ 181 if (pIFM2) 182 IFilterMapper2_Release(pIFM2); 183 184 /* and clear up */ 185 CoFreeUnusedLibraries(); 186 CoUninitialize(); 187 188 /* if unregistering, unregister all OLE servers */ 189 if (SUCCEEDED(hr) && !bRegister) 190 hr = SetupRegisterAllClasses(g_Templates, g_cTemplates, szFileName, FALSE); 191 192 return hr; 193 } 194 195 /**************************************************************************** 196 * SetupInitializeServers 197 * 198 * This function is table driven using the static members of the 199 * CFactoryTemplate class defined in the Dll. 200 * 201 * It calls the initialize function for any class in CFactoryTemplate with 202 * one defined. 203 * 204 ****************************************************************************/ 205 static void SetupInitializeServers(const FactoryTemplate * pList, int num, 206 BOOL bLoading) 207 { 208 int i; 209 210 for (i = 0; i < num; i++, pList++) 211 { 212 if (pList->m_lpfnInit) 213 pList->m_lpfnInit(bLoading, pList->m_ClsID); 214 } 215 } 216 217 BOOL WINAPI STRMBASE_DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv) 218 { 219 switch (fdwReason) 220 { 221 case DLL_PROCESS_ATTACH: 222 g_hInst = hInstDLL; 223 DisableThreadLibraryCalls(hInstDLL); 224 SetupInitializeServers(g_Templates, g_cTemplates, TRUE); 225 break; 226 case DLL_PROCESS_DETACH: 227 SetupInitializeServers(g_Templates, g_cTemplates, FALSE); 228 break; 229 } 230 return TRUE; 231 } 232 233 /****************************************************************************** 234 * DLL ClassFactory 235 */ 236 typedef struct { 237 IClassFactory IClassFactory_iface; 238 LONG ref; 239 LPFNNewCOMObject pfnCreateInstance; 240 } IClassFactoryImpl; 241 242 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface) 243 { 244 return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface); 245 } 246 247 static HRESULT WINAPI DSCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj) 248 { 249 if (IsEqualGUID(riid, &IID_IUnknown) || 250 IsEqualGUID(riid, &IID_IClassFactory)) 251 { 252 IClassFactory_AddRef(iface); 253 *ppobj = iface; 254 return S_OK; 255 } 256 257 *ppobj = NULL; 258 WARN("(%p)->(%s,%p), not found\n", iface, debugstr_guid(riid), ppobj); 259 return E_NOINTERFACE; 260 } 261 262 static ULONG WINAPI DSCF_AddRef(IClassFactory *iface) 263 { 264 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 265 return InterlockedIncrement(&This->ref); 266 } 267 268 static ULONG WINAPI DSCF_Release(IClassFactory *iface) 269 { 270 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 271 ULONG ref = InterlockedDecrement(&This->ref); 272 273 if (ref == 0) 274 HeapFree(GetProcessHeap(), 0, This); 275 276 return ref; 277 } 278 279 static HRESULT WINAPI DSCF_CreateInstance(IClassFactory *iface, IUnknown *pOuter, 280 REFIID riid, void **ppobj) 281 { 282 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 283 HRESULT hres = ERROR_SUCCESS; 284 LPUNKNOWN punk; 285 286 TRACE("(%p)->(%p,%s,%p)\n", This, pOuter, debugstr_guid(riid), ppobj); 287 288 if (!ppobj) 289 return E_POINTER; 290 291 /* Enforce the normal OLE rules regarding interfaces and delegation */ 292 if (pOuter && !IsEqualGUID(riid, &IID_IUnknown)) 293 return E_NOINTERFACE; 294 295 *ppobj = NULL; 296 punk = This->pfnCreateInstance(pOuter, &hres); 297 if (!punk) 298 { 299 /* No object created, update error if it isn't done already and return */ 300 if (SUCCEEDED(hres)) 301 hres = E_OUTOFMEMORY; 302 return hres; 303 } 304 305 if (SUCCEEDED(hres)) 306 { 307 hres = IUnknown_QueryInterface(punk, riid, ppobj); 308 } 309 /* Releasing the object. If everything was successful, QueryInterface 310 should have incremented the refcount once more, otherwise this will 311 purge the object. */ 312 IUnknown_Release(punk); 313 return hres; 314 } 315 316 static HRESULT WINAPI DSCF_LockServer(IClassFactory *iface, BOOL dolock) 317 { 318 IClassFactoryImpl *This = impl_from_IClassFactory(iface); 319 TRACE("(%p)->(%d)\n",This, dolock); 320 321 if (dolock) 322 InterlockedIncrement(&server_locks); 323 else 324 InterlockedDecrement(&server_locks); 325 return S_OK; 326 } 327 328 static const IClassFactoryVtbl DSCF_Vtbl = 329 { 330 DSCF_QueryInterface, 331 DSCF_AddRef, 332 DSCF_Release, 333 DSCF_CreateInstance, 334 DSCF_LockServer 335 }; 336 337 /*********************************************************************** 338 * DllGetClassObject 339 */ 340 HRESULT WINAPI STRMBASE_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) 341 { 342 const FactoryTemplate *pList = g_Templates; 343 IClassFactoryImpl *factory; 344 int i; 345 346 TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); 347 348 if (!ppv) 349 return E_POINTER; 350 351 *ppv = NULL; 352 353 if (!IsEqualGUID(&IID_IClassFactory, riid) && 354 !IsEqualGUID(&IID_IUnknown, riid)) 355 return E_NOINTERFACE; 356 357 for (i = 0; i < g_cTemplates; i++, pList++) 358 { 359 if (IsEqualGUID(pList->m_ClsID, rclsid)) 360 break; 361 } 362 363 if (i == g_cTemplates) 364 { 365 char dllname[MAX_PATH]; 366 if (!GetModuleFileNameA(g_hInst, dllname, sizeof(dllname))) 367 strcpy(dllname, "???"); 368 ERR("%s: no class found in %s.\n", debugstr_guid(rclsid), dllname); 369 return CLASS_E_CLASSNOTAVAILABLE; 370 } 371 else if (!pList->m_lpfnNew) 372 { 373 FIXME("%s: class not implemented yet.\n", debugstr_guid(rclsid)); 374 return CLASS_E_CLASSNOTAVAILABLE; 375 } 376 377 factory = HeapAlloc(GetProcessHeap(), 0, sizeof(IClassFactoryImpl)); 378 if (!factory) 379 return E_OUTOFMEMORY; 380 381 factory->IClassFactory_iface.lpVtbl = &DSCF_Vtbl; 382 factory->ref = 1; 383 384 factory->pfnCreateInstance = pList->m_lpfnNew; 385 386 *ppv = &factory->IClassFactory_iface; 387 return S_OK; 388 } 389 390 /*********************************************************************** 391 * DllCanUnloadNow 392 */ 393 HRESULT WINAPI STRMBASE_DllCanUnloadNow(void) 394 { 395 TRACE("\n"); 396 397 if (server_locks == 0) 398 return S_OK; 399 return S_FALSE; 400 } 401