itss: Standardize the COM usage in itss.c.
[wine] / dlls / itss / itss.c
1 /*
2  *    ITSS Class Factory
3  *
4  * Copyright 2002 Lionel Ulmer
5  * Copyright 2004 Mike McCormack
6  *
7  *  see http://bonedaddy.net/pabs3/hhm/#chmspec
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #include "config.h"
25
26 #include <stdarg.h>
27 #include <stdio.h>
28
29 #define COBJMACROS
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winuser.h"
34 #include "winreg.h"
35 #include "ole2.h"
36 #include "advpub.h"
37
38 #include "wine/unicode.h"
39 #include "wine/debug.h"
40
41 #include "itsstor.h"
42
43 #include "initguid.h"
44 #include "wine/itss.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(itss);
47
48 static HRESULT ITSS_create(IUnknown *pUnkOuter, LPVOID *ppObj);
49
50 LONG dll_count = 0;
51 static HINSTANCE hInst;
52
53 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
54 {
55     switch(fdwReason) {
56     case DLL_PROCESS_ATTACH:
57         DisableThreadLibraryCalls(hInstDLL);
58         hInst = hInstDLL;
59         break;
60     case DLL_PROCESS_DETACH:
61         break;
62     }
63     return TRUE;
64 }
65
66 /******************************************************************************
67  * ITSS ClassFactory
68  */
69 typedef struct {
70     IClassFactory IClassFactory_iface;
71     HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
72 } IClassFactoryImpl;
73
74 static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
75 {
76     return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
77 }
78
79 static HRESULT WINAPI
80 ITSSCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
81 {
82     IClassFactoryImpl *This = impl_from_IClassFactory(iface);
83
84     if (IsEqualGUID(riid, &IID_IUnknown) ||
85         IsEqualGUID(riid, &IID_IClassFactory))
86     {
87         IClassFactory_AddRef(iface);
88         *ppobj = This;
89         return S_OK;
90     }
91
92     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
93     return E_NOINTERFACE;
94 }
95
96 static ULONG WINAPI ITSSCF_AddRef(LPCLASSFACTORY iface)
97 {
98     ITSS_LockModule();
99     return 2;
100 }
101
102 static ULONG WINAPI ITSSCF_Release(LPCLASSFACTORY iface)
103 {
104     ITSS_UnlockModule();
105     return 1;
106 }
107
108
109 static HRESULT WINAPI ITSSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter,
110                                           REFIID riid, LPVOID *ppobj)
111 {
112     IClassFactoryImpl *This = impl_from_IClassFactory(iface);
113     HRESULT hres;
114     LPUNKNOWN punk;
115
116     TRACE("(%p)->(%p,%s,%p)\n", This, pOuter, debugstr_guid(riid), ppobj);
117
118     *ppobj = NULL;
119     hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
120     if (SUCCEEDED(hres)) {
121         hres = IUnknown_QueryInterface(punk, riid, ppobj);
122         IUnknown_Release(punk);
123     }
124     return hres;
125 }
126
127 static HRESULT WINAPI ITSSCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
128 {
129     TRACE("(%p)->(%d)\n", iface, dolock);
130
131     if (dolock)
132         ITSS_LockModule();
133     else
134         ITSS_UnlockModule();
135
136     return S_OK;
137 }
138
139 static const IClassFactoryVtbl ITSSCF_Vtbl =
140 {
141     ITSSCF_QueryInterface,
142     ITSSCF_AddRef,
143     ITSSCF_Release,
144     ITSSCF_CreateInstance,
145     ITSSCF_LockServer
146 };
147
148 static const IClassFactoryImpl ITStorage_factory = { { &ITSSCF_Vtbl }, ITSS_create };
149 static const IClassFactoryImpl MSITStore_factory = { { &ITSSCF_Vtbl }, ITS_IParseDisplayName_create };
150 static const IClassFactoryImpl ITSProtocol_factory = { { &ITSSCF_Vtbl }, ITSProtocol_create };
151
152 /***********************************************************************
153  *              DllGetClassObject       (ITSS.@)
154  */
155 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
156 {
157     const IClassFactoryImpl *factory;
158
159     TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv);
160
161     if (IsEqualGUID(&CLSID_ITStorage, rclsid))
162         factory = &ITStorage_factory;
163     else if (IsEqualGUID(&CLSID_MSITStore, rclsid))
164         factory = &MSITStore_factory;
165     else if (IsEqualGUID(&CLSID_ITSProtocol, rclsid))
166         factory = &ITSProtocol_factory;
167     else
168     {
169         FIXME("%s: no class found.\n", debugstr_guid(rclsid));
170         return CLASS_E_CLASSNOTAVAILABLE;
171     }
172
173     return IUnknown_QueryInterface( (IUnknown*) factory, iid, ppv );
174 }
175
176 /*****************************************************************************/
177
178 typedef struct {
179     IITStorage IITStorage_iface;
180     LONG ref;
181 } ITStorageImpl;
182
183 static inline ITStorageImpl *impl_from_IITStorage(IITStorage *iface)
184 {
185     return CONTAINING_RECORD(iface, ITStorageImpl, IITStorage_iface);
186 }
187
188
189 static HRESULT WINAPI ITStorageImpl_QueryInterface(
190     IITStorage* iface,
191     REFIID riid,
192     void** ppvObject)
193 {
194     ITStorageImpl *This = impl_from_IITStorage(iface);
195     if (IsEqualGUID(riid, &IID_IUnknown)
196         || IsEqualGUID(riid, &IID_IITStorage))
197     {
198         IClassFactory_AddRef(iface);
199         *ppvObject = This;
200         return S_OK;
201     }
202
203     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
204     return E_NOINTERFACE;
205 }
206
207 static ULONG WINAPI ITStorageImpl_AddRef(
208     IITStorage* iface)
209 {
210     ITStorageImpl *This = impl_from_IITStorage(iface);
211     TRACE("%p\n", This);
212     return InterlockedIncrement(&This->ref);
213 }
214
215 static ULONG WINAPI ITStorageImpl_Release(
216     IITStorage* iface)
217 {
218     ITStorageImpl *This = impl_from_IITStorage(iface);
219     ULONG ref = InterlockedDecrement(&This->ref);
220
221     if (ref == 0) {
222         HeapFree(GetProcessHeap(), 0, This);
223         ITSS_UnlockModule();
224     }
225
226     return ref;
227 }
228
229 static HRESULT WINAPI ITStorageImpl_StgCreateDocfile(
230     IITStorage* iface,
231     const WCHAR* pwcsName,
232     DWORD grfMode,
233     DWORD reserved,
234     IStorage** ppstgOpen)
235 {
236     ITStorageImpl *This = impl_from_IITStorage(iface);
237
238     TRACE("%p %s %u %u %p\n", This,
239           debugstr_w(pwcsName), grfMode, reserved, ppstgOpen );
240
241     return ITSS_StgOpenStorage( pwcsName, NULL, grfMode,
242                                 0, reserved, ppstgOpen);
243 }
244
245 static HRESULT WINAPI ITStorageImpl_StgCreateDocfileOnILockBytes(
246     IITStorage* iface,
247     ILockBytes* plkbyt,
248     DWORD grfMode,
249     DWORD reserved,
250     IStorage** ppstgOpen)
251 {
252     ITStorageImpl *This = impl_from_IITStorage(iface);
253     FIXME("%p\n", This);
254     return E_NOTIMPL;
255 }
256
257 static HRESULT WINAPI ITStorageImpl_StgIsStorageFile(
258     IITStorage* iface,
259     const WCHAR* pwcsName)
260 {
261     ITStorageImpl *This = impl_from_IITStorage(iface);
262     FIXME("%p\n", This);
263     return E_NOTIMPL;
264 }
265
266 static HRESULT WINAPI ITStorageImpl_StgIsStorageILockBytes(
267     IITStorage* iface,
268     ILockBytes* plkbyt)
269 {
270     ITStorageImpl *This = impl_from_IITStorage(iface);
271     FIXME("%p\n", This);
272     return E_NOTIMPL;
273 }
274
275 static HRESULT WINAPI ITStorageImpl_StgOpenStorage(
276     IITStorage* iface,
277     const WCHAR* pwcsName,
278     IStorage* pstgPriority,
279     DWORD grfMode,
280     SNB snbExclude,
281     DWORD reserved,
282     IStorage** ppstgOpen)
283 {
284     ITStorageImpl *This = impl_from_IITStorage(iface);
285
286     TRACE("%p %s %p %d %p\n", This, debugstr_w( pwcsName ),
287            pstgPriority, grfMode, snbExclude );
288
289     return ITSS_StgOpenStorage( pwcsName, pstgPriority, grfMode,
290                                 snbExclude, reserved, ppstgOpen);
291 }
292
293 static HRESULT WINAPI ITStorageImpl_StgOpenStorageOnILockBytes(
294     IITStorage* iface,
295     ILockBytes* plkbyt,
296     IStorage* pStgPriority,
297     DWORD grfMode,
298     SNB snbExclude,
299     DWORD reserved,
300     IStorage** ppstgOpen)
301 {
302     ITStorageImpl *This = impl_from_IITStorage(iface);
303     FIXME("%p\n", This);
304     return E_NOTIMPL;
305 }
306
307 static HRESULT WINAPI ITStorageImpl_StgSetTimes(
308     IITStorage* iface,
309     const WCHAR* lpszName,
310     const FILETIME* pctime,
311     const FILETIME* patime,
312     const FILETIME* pmtime)
313 {
314     ITStorageImpl *This = impl_from_IITStorage(iface);
315     FIXME("%p\n", This);
316     return E_NOTIMPL;
317 }
318
319 static HRESULT WINAPI ITStorageImpl_SetControlData(
320     IITStorage* iface,
321     PITS_Control_Data pControlData)
322 {
323     ITStorageImpl *This = impl_from_IITStorage(iface);
324     FIXME("%p\n", This);
325     return E_NOTIMPL;
326 }
327
328 static HRESULT WINAPI ITStorageImpl_DefaultControlData(
329     IITStorage* iface,
330     PITS_Control_Data* ppControlData)
331 {
332     ITStorageImpl *This = impl_from_IITStorage(iface);
333     FIXME("%p\n", This);
334     return E_NOTIMPL;
335 }
336
337 static HRESULT WINAPI ITStorageImpl_Compact(
338     IITStorage* iface,
339     const WCHAR* pwcsName,
340     ECompactionLev iLev)
341 {
342     ITStorageImpl *This = impl_from_IITStorage(iface);
343     FIXME("%p\n", This);
344     return E_NOTIMPL;
345 }
346
347 static const IITStorageVtbl ITStorageImpl_Vtbl =
348 {
349     ITStorageImpl_QueryInterface,
350     ITStorageImpl_AddRef,
351     ITStorageImpl_Release,
352     ITStorageImpl_StgCreateDocfile,
353     ITStorageImpl_StgCreateDocfileOnILockBytes,
354     ITStorageImpl_StgIsStorageFile,
355     ITStorageImpl_StgIsStorageILockBytes,
356     ITStorageImpl_StgOpenStorage,
357     ITStorageImpl_StgOpenStorageOnILockBytes,
358     ITStorageImpl_StgSetTimes,
359     ITStorageImpl_SetControlData,
360     ITStorageImpl_DefaultControlData,
361     ITStorageImpl_Compact,
362 };
363
364 static HRESULT ITSS_create(IUnknown *pUnkOuter, LPVOID *ppObj)
365 {
366     ITStorageImpl *its;
367
368     if( pUnkOuter )
369         return CLASS_E_NOAGGREGATION;
370
371     its = HeapAlloc( GetProcessHeap(), 0, sizeof(ITStorageImpl) );
372     its->IITStorage_iface.lpVtbl = &ITStorageImpl_Vtbl;
373     its->ref = 1;
374
375     TRACE("-> %p\n", its);
376     *ppObj = its;
377
378     ITSS_LockModule();
379     return S_OK;
380 }
381
382 /*****************************************************************************/
383
384 HRESULT WINAPI DllCanUnloadNow(void)
385 {
386     TRACE("dll_count = %u\n", dll_count);
387     return dll_count ? S_FALSE : S_OK;
388 }
389
390 #define INF_SET_ID(id)            \
391     do                            \
392     {                             \
393         static CHAR name[] = #id; \
394                                   \
395         pse[i].pszName = name;    \
396         clsids[i++] = &id;        \
397     } while (0)
398
399 #define INF_SET_CLSID(clsid) INF_SET_ID(CLSID_ ## clsid)
400
401 static HRESULT register_server(BOOL do_register)
402 {
403     HRESULT hres;
404     HMODULE hAdvpack;
405     HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable);
406     STRTABLEA strtable;
407     STRENTRYA pse[4];
408     static CLSID const *clsids[4];
409     DWORD i = 0;
410
411     static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0};
412
413     INF_SET_CLSID(ITStorage);
414     INF_SET_CLSID(MSFSStore);
415     INF_SET_CLSID(MSITStore);
416     INF_SET_CLSID(ITSProtocol);
417
418     strtable.cEntries = sizeof(pse)/sizeof(pse[0]);
419     strtable.pse = pse;
420
421     for(i=0; i < strtable.cEntries; i++) {
422         pse[i].pszValue = HeapAlloc(GetProcessHeap(), 0, 39);
423         sprintf(pse[i].pszValue, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
424                 clsids[i]->Data1, clsids[i]->Data2, clsids[i]->Data3, clsids[i]->Data4[0],
425                 clsids[i]->Data4[1], clsids[i]->Data4[2], clsids[i]->Data4[3], clsids[i]->Data4[4],
426                 clsids[i]->Data4[5], clsids[i]->Data4[6], clsids[i]->Data4[7]);
427     }
428
429     hAdvpack = LoadLibraryW(wszAdvpack);
430     pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall");
431
432     hres = pRegInstall(hInst, do_register ? "RegisterDll" : "UnregisterDll", &strtable);
433
434     for(i=0; i < sizeof(pse)/sizeof(pse[0]); i++)
435         HeapFree(GetProcessHeap(), 0, pse[i].pszValue);
436
437     return hres;
438 }
439
440 #undef INF_SET_CLSID
441 #undef INF_SET_ID
442
443 /***********************************************************************
444  *          DllRegisterServer (ITSS.@)
445  */
446 HRESULT WINAPI DllRegisterServer(void)
447 {
448     return register_server(TRUE);
449 }
450
451 /***********************************************************************
452  *          DllUnregisterServer (ITSS.@)
453  */
454 HRESULT WINAPI DllUnregisterServer(void)
455 {
456     return register_server(FALSE);
457 }