mapi32: Fully merge the IMAPIProp ifaces into IPropData.
[wine] / dlls / strmbase / dllfunc.c
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 #define MAX_KEY_LEN  260
55
56 static WCHAR const clsid_keyname[6] =
57 {'C','L','S','I','D',0 };
58 static WCHAR const ips32_keyname[15] =
59 {'I','n','P','r','o','c','S','e','r','v','e','r','3','2',0};
60 static WCHAR const tmodel_keyname[15] =
61 {'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
62 static WCHAR const tmodel_both[] =
63 {'B','o','t','h',0};
64
65 /*
66  * SetupRegisterClass()
67  */
68 static HRESULT SetupRegisterClass(HKEY clsid, LPCWSTR szCLSID,
69                                   LPCWSTR szDescription,
70                                   LPCWSTR szFileName,
71                                   LPCWSTR szServerType,
72                                   LPCWSTR szThreadingModel)
73 {
74     HKEY hkey, hsubkey = NULL;
75     LONG ret = RegCreateKeyW(clsid, szCLSID, &hkey);
76     if (ERROR_SUCCESS != ret)
77         return HRESULT_FROM_WIN32(ret);
78
79     /* set description string */
80     ret = RegSetValueW(hkey, NULL, REG_SZ, szDescription,
81                        sizeof(WCHAR) * (lstrlenW(szDescription) + 1));
82     if (ERROR_SUCCESS != ret)
83         goto err_out;
84
85     /* create CLSID\\{"CLSID"}\\"ServerType" key, using key to CLSID\\{"CLSID"}
86        passed back by last call to RegCreateKeyW(). */
87     ret = RegCreateKeyW(hkey,  szServerType, &hsubkey);
88     if (ERROR_SUCCESS != ret)
89         goto err_out;
90
91     /* set server path */
92     ret = RegSetValueW(hsubkey, NULL, REG_SZ, szFileName,
93                        sizeof(WCHAR) * (lstrlenW(szFileName) + 1));
94     if (ERROR_SUCCESS != ret)
95         goto err_out;
96
97     /* set threading model */
98     ret = RegSetValueExW(hsubkey, tmodel_keyname, 0L, REG_SZ,
99                          (const BYTE*)szThreadingModel,
100                          sizeof(WCHAR) * (lstrlenW(szThreadingModel) + 1));
101 err_out:
102     if (hsubkey)
103         RegCloseKey(hsubkey);
104     RegCloseKey(hkey);
105     return HRESULT_FROM_WIN32(ret);
106 }
107
108 /*
109  * RegisterAllClasses()
110  */
111 static HRESULT SetupRegisterAllClasses(const FactoryTemplate * pList, int num,
112                                        LPCWSTR szFileName, BOOL bRegister)
113 {
114     HRESULT hr = NOERROR;
115     HKEY hkey;
116     OLECHAR szCLSID[CHARS_IN_GUID];
117     LONG i, ret = RegCreateKeyW(HKEY_CLASSES_ROOT, clsid_keyname, &hkey);
118     if (ERROR_SUCCESS != ret)
119         return HRESULT_FROM_WIN32(ret);
120
121     for (i = 0; i < num; i++, pList++)
122     {
123         /* (un)register CLSID and InprocServer32 */
124         hr = StringFromGUID2(pList->m_ClsID, szCLSID, CHARS_IN_GUID);
125         if (SUCCEEDED(hr))
126         {
127             if (bRegister )
128                 hr = SetupRegisterClass(hkey, szCLSID,
129                                         pList->m_Name, szFileName,
130                                         ips32_keyname, tmodel_both);
131             else
132                 hr = RegDeleteTreeW(hkey, szCLSID);
133         }
134     }
135     RegCloseKey(hkey);
136     return hr;
137 }
138
139 HRESULT WINAPI AMovieSetupRegisterFilter2(const AMOVIESETUP_FILTER *pFilter, IFilterMapper2  *pIFM2, BOOL  bRegister)
140 {
141     if (!pFilter)
142         return S_OK;
143
144     if (bRegister)
145     {
146         {
147             REGFILTER2 rf2;
148             rf2.dwVersion = 1;
149             rf2.dwMerit = pFilter->merit;
150             rf2.u.s.cPins = pFilter->pins;
151             rf2.u.s.rgPins = pFilter->pPin;
152
153             return IFilterMapper2_RegisterFilter(pIFM2, pFilter->clsid, pFilter->name, NULL, &CLSID_LegacyAmFilterCategory, NULL, &rf2);
154         }
155     }
156     else
157        return IFilterMapper2_UnregisterFilter(pIFM2, &CLSID_LegacyAmFilterCategory, NULL, pFilter->clsid);
158 }
159
160 HRESULT WINAPI AMovieDllRegisterServer2(BOOL bRegister)
161 {
162     HRESULT hr;
163     int i;
164     IFilterMapper2 *pIFM2 = NULL;
165     WCHAR szFileName[MAX_PATH];
166
167     if (!GetModuleFileNameW(g_hInst, szFileName, MAX_PATH))
168     {
169         ERR("Failed to get module file name for registration\n");
170         return E_FAIL;
171     }
172
173     if (bRegister)
174         hr = SetupRegisterAllClasses(g_Templates, g_cTemplates, szFileName, TRUE );
175
176     hr = CoInitialize(NULL);
177
178     TRACE("Getting IFilterMapper2\r\n");
179     hr = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER,
180                           &IID_IFilterMapper2, (void **)&pIFM2);
181
182     for (i = 0; SUCCEEDED(hr) && i < g_cTemplates; i++)
183         hr = AMovieSetupRegisterFilter2(g_Templates[i].m_pAMovieSetup_Filter, pIFM2, bRegister);
184
185     /* release interface */
186     if (pIFM2)
187         IFilterMapper2_Release(pIFM2);
188
189     /* and clear up */
190     CoFreeUnusedLibraries();
191     CoUninitialize();
192
193     /* if unregistering, unregister all OLE servers */
194     if (SUCCEEDED(hr) && !bRegister)
195         hr = SetupRegisterAllClasses(g_Templates, g_cTemplates, szFileName, FALSE);
196
197     return hr;
198 }
199
200 /****************************************************************************
201  * SetupInitializeServers
202  *
203  * This function is table driven using the static members of the
204  * CFactoryTemplate class defined in the Dll.
205  *
206  * It calls the initialize function for any class in CFactoryTemplate with
207  * one defined.
208  *
209  ****************************************************************************/
210 static void SetupInitializeServers(const FactoryTemplate * pList, int num,
211                             BOOL bLoading)
212 {
213     int i;
214
215     for (i = 0; i < num; i++, pList++)
216     {
217         if (pList->m_lpfnInit)
218             pList->m_lpfnInit(bLoading, pList->m_ClsID);
219     }
220 }
221
222 BOOL WINAPI STRMBASE_DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
223 {
224     switch (fdwReason)
225     {
226         case DLL_PROCESS_ATTACH:
227             g_hInst = hInstDLL;
228             DisableThreadLibraryCalls(hInstDLL);
229             SetupInitializeServers(g_Templates, g_cTemplates, TRUE);
230             break;
231         case DLL_PROCESS_DETACH:
232             SetupInitializeServers(g_Templates, g_cTemplates, FALSE);
233             break;
234     }
235     return TRUE;
236 }
237
238 /******************************************************************************
239  * DLL ClassFactory
240  */
241 typedef struct {
242     IClassFactory ITF_IClassFactory;
243
244     LONG ref;
245     LPFNNewCOMObject pfnCreateInstance;
246 } IClassFactoryImpl;
247
248 static HRESULT WINAPI
249 DSCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
250 {
251     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
252
253     if (IsEqualGUID(riid, &IID_IUnknown) ||
254         IsEqualGUID(riid, &IID_IClassFactory))
255     {
256         IClassFactory_AddRef(iface);
257         *ppobj = This;
258         return S_OK;
259     }
260
261     WARN("(%p)->(%s,%p), not found\n", This, debugstr_guid(riid), ppobj);
262     return E_NOINTERFACE;
263 }
264
265 static ULONG WINAPI DSCF_AddRef(LPCLASSFACTORY iface)
266 {
267     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
268     return InterlockedIncrement(&This->ref);
269 }
270
271 static ULONG WINAPI DSCF_Release(LPCLASSFACTORY iface)
272 {
273     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
274
275     ULONG ref = InterlockedDecrement(&This->ref);
276
277     if (ref == 0)
278         HeapFree(GetProcessHeap(), 0, This);
279
280     return ref;
281 }
282
283 static HRESULT WINAPI DSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter,
284                                           REFIID riid, LPVOID *ppobj)
285 {
286     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
287     HRESULT hres = ERROR_SUCCESS;
288     LPUNKNOWN punk;
289
290     TRACE("(%p)->(%p,%s,%p)\n", This, pOuter, debugstr_guid(riid), ppobj);
291
292     if (!ppobj)
293         return E_POINTER;
294
295     /* Enforce the normal OLE rules regarding interfaces and delegation */
296     if (pOuter && !IsEqualGUID(riid, &IID_IUnknown))
297         return E_NOINTERFACE;
298
299     *ppobj = NULL;
300     punk = This->pfnCreateInstance(pOuter, &hres);
301     if (!punk)
302     {
303         /* No object created, update error if it isn't done already and return */
304         if (SUCCEEDED(hres))
305             hres = E_OUTOFMEMORY;
306     return hres;
307     }
308
309     if (SUCCEEDED(hres))
310     {
311         hres = IUnknown_QueryInterface(punk, riid, ppobj);
312     }
313     /* Releasing the object. If everything was successful, QueryInterface
314        should have incremented the refcount once more, otherwise this will
315        purge the object. */
316     IUnknown_Release(punk);
317     return hres;
318 }
319
320 static HRESULT WINAPI DSCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
321 {
322     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
323     TRACE("(%p)->(%d)\n",This, dolock);
324
325     if (dolock)
326         InterlockedIncrement(&server_locks);
327     else
328         InterlockedDecrement(&server_locks);
329     return S_OK;
330 }
331
332 static const IClassFactoryVtbl DSCF_Vtbl =
333 {
334     DSCF_QueryInterface,
335     DSCF_AddRef,
336     DSCF_Release,
337     DSCF_CreateInstance,
338     DSCF_LockServer
339 };
340
341 /***********************************************************************
342  *    DllGetClassObject
343  */
344 HRESULT WINAPI STRMBASE_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
345 {
346     const FactoryTemplate *pList = g_Templates;
347     IClassFactoryImpl *factory;
348     int i;
349
350     TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
351
352     if (!ppv)
353         return E_POINTER;
354
355     *ppv = NULL;
356
357     if (!IsEqualGUID(&IID_IClassFactory, riid) &&
358         !IsEqualGUID(&IID_IUnknown, riid))
359         return E_NOINTERFACE;
360
361     for (i = 0; i < g_cTemplates; i++, pList++)
362     {
363         if (IsEqualGUID(pList->m_ClsID, rclsid))
364             break;
365     }
366
367     if (i == g_cTemplates)
368     {
369         FIXME("%s: no class found.\n", debugstr_guid(rclsid));
370         return CLASS_E_CLASSNOTAVAILABLE;
371     }
372
373     factory = HeapAlloc(GetProcessHeap(), 0, sizeof(IClassFactoryImpl));
374     if (!factory)
375         return E_OUTOFMEMORY;
376
377     factory->ITF_IClassFactory.lpVtbl = &DSCF_Vtbl;
378     factory->ref = 1;
379
380     factory->pfnCreateInstance = pList->m_lpfnNew;
381
382     *ppv = &(factory->ITF_IClassFactory);
383     return S_OK;
384 }
385
386 /***********************************************************************
387  *    DllCanUnloadNow
388  */
389 HRESULT WINAPI STRMBASE_DllCanUnloadNow(void)
390 {
391     TRACE("\n");
392
393     if (server_locks == 0)
394         return S_OK;
395     return S_FALSE;
396 }