urlmon/tests: Keep track of download state in tests.
[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     const IClassFactoryVtbl *lpVtbl;
71     HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
72 } IClassFactoryImpl;
73
74 static HRESULT WINAPI
75 ITSSCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
76 {
77     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
78
79     if (IsEqualGUID(riid, &IID_IUnknown) ||
80         IsEqualGUID(riid, &IID_IClassFactory))
81     {
82         IClassFactory_AddRef(iface);
83         *ppobj = This;
84         return S_OK;
85     }
86
87     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
88     return E_NOINTERFACE;
89 }
90
91 static ULONG WINAPI ITSSCF_AddRef(LPCLASSFACTORY iface)
92 {
93     ITSS_LockModule();
94     return 2;
95 }
96
97 static ULONG WINAPI ITSSCF_Release(LPCLASSFACTORY iface)
98 {
99     ITSS_UnlockModule();
100     return 1;
101 }
102
103
104 static HRESULT WINAPI ITSSCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter,
105                                           REFIID riid, LPVOID *ppobj)
106 {
107     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
108     HRESULT hres;
109     LPUNKNOWN punk;
110
111     TRACE("(%p)->(%p,%s,%p)\n", This, pOuter, debugstr_guid(riid), ppobj);
112
113     *ppobj = NULL;
114     hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk);
115     if (SUCCEEDED(hres)) {
116         hres = IUnknown_QueryInterface(punk, riid, ppobj);
117         IUnknown_Release(punk);
118     }
119     return hres;
120 }
121
122 static HRESULT WINAPI ITSSCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
123 {
124     TRACE("(%p)->(%d)\n", iface, dolock);
125
126     if (dolock)
127         ITSS_LockModule();
128     else
129         ITSS_UnlockModule();
130
131     return S_OK;
132 }
133
134 static const IClassFactoryVtbl ITSSCF_Vtbl =
135 {
136     ITSSCF_QueryInterface,
137     ITSSCF_AddRef,
138     ITSSCF_Release,
139     ITSSCF_CreateInstance,
140     ITSSCF_LockServer
141 };
142
143 static const IClassFactoryImpl ITStorage_factory = { &ITSSCF_Vtbl, ITSS_create };
144 static const IClassFactoryImpl MSITStore_factory = { &ITSSCF_Vtbl, ITS_IParseDisplayName_create };
145 static const IClassFactoryImpl ITSProtocol_factory = { &ITSSCF_Vtbl, ITSProtocol_create };
146
147 /***********************************************************************
148  *              DllGetClassObject       (ITSS.@)
149  */
150 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
151 {
152     const IClassFactoryImpl *factory;
153
154     TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv);
155
156     if (IsEqualGUID(&CLSID_ITStorage, rclsid))
157         factory = &ITStorage_factory;
158     else if (IsEqualGUID(&CLSID_MSITStore, rclsid))
159         factory = &MSITStore_factory;
160     else if (IsEqualGUID(&CLSID_ITSProtocol, rclsid))
161         factory = &ITSProtocol_factory;
162     else
163     {
164         FIXME("%s: no class found.\n", debugstr_guid(rclsid));
165         return CLASS_E_CLASSNOTAVAILABLE;
166     }
167
168     return IUnknown_QueryInterface( (IUnknown*) factory, iid, ppv );
169 }
170
171 /*****************************************************************************/
172
173 typedef struct {
174     const IITStorageVtbl *vtbl_IITStorage;
175     LONG ref;
176 } ITStorageImpl;
177
178
179 static HRESULT WINAPI ITStorageImpl_QueryInterface(
180     IITStorage* iface,
181     REFIID riid,
182     void** ppvObject)
183 {
184     ITStorageImpl *This = (ITStorageImpl *)iface;
185     if (IsEqualGUID(riid, &IID_IUnknown)
186         || IsEqualGUID(riid, &IID_IITStorage))
187     {
188         IClassFactory_AddRef(iface);
189         *ppvObject = This;
190         return S_OK;
191     }
192
193     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
194     return E_NOINTERFACE;
195 }
196
197 static ULONG WINAPI ITStorageImpl_AddRef(
198     IITStorage* iface)
199 {
200     ITStorageImpl *This = (ITStorageImpl *)iface;
201     TRACE("%p\n", This);
202     return InterlockedIncrement(&This->ref);
203 }
204
205 static ULONG WINAPI ITStorageImpl_Release(
206     IITStorage* iface)
207 {
208     ITStorageImpl *This = (ITStorageImpl *)iface;
209     ULONG ref = InterlockedDecrement(&This->ref);
210
211     if (ref == 0) {
212         HeapFree(GetProcessHeap(), 0, This);
213         ITSS_UnlockModule();
214     }
215
216     return ref;
217 }
218
219 static HRESULT WINAPI ITStorageImpl_StgCreateDocfile(
220     IITStorage* iface,
221     const WCHAR* pwcsName,
222     DWORD grfMode,
223     DWORD reserved,
224     IStorage** ppstgOpen)
225 {
226     ITStorageImpl *This = (ITStorageImpl *)iface;
227
228     TRACE("%p %s %u %u %p\n", This,
229           debugstr_w(pwcsName), grfMode, reserved, ppstgOpen );
230
231     return ITSS_StgOpenStorage( pwcsName, NULL, grfMode,
232                                 0, reserved, ppstgOpen);
233 }
234
235 static HRESULT WINAPI ITStorageImpl_StgCreateDocfileOnILockBytes(
236     IITStorage* iface,
237     ILockBytes* plkbyt,
238     DWORD grfMode,
239     DWORD reserved,
240     IStorage** ppstgOpen)
241 {
242     ITStorageImpl *This = (ITStorageImpl *)iface;
243     FIXME("%p\n", This);
244     return E_NOTIMPL;
245 }
246
247 static HRESULT WINAPI ITStorageImpl_StgIsStorageFile(
248     IITStorage* iface,
249     const WCHAR* pwcsName)
250 {
251     ITStorageImpl *This = (ITStorageImpl *)iface;
252     FIXME("%p\n", This);
253     return E_NOTIMPL;
254 }
255
256 static HRESULT WINAPI ITStorageImpl_StgIsStorageILockBytes(
257     IITStorage* iface,
258     ILockBytes* plkbyt)
259 {
260     ITStorageImpl *This = (ITStorageImpl *)iface;
261     FIXME("%p\n", This);
262     return E_NOTIMPL;
263 }
264
265 static HRESULT WINAPI ITStorageImpl_StgOpenStorage(
266     IITStorage* iface,
267     const WCHAR* pwcsName,
268     IStorage* pstgPriority,
269     DWORD grfMode,
270     SNB snbExclude,
271     DWORD reserved,
272     IStorage** ppstgOpen)
273 {
274     ITStorageImpl *This = (ITStorageImpl *)iface;
275
276     TRACE("%p %s %p %d %p\n", This, debugstr_w( pwcsName ),
277            pstgPriority, grfMode, snbExclude );
278
279     return ITSS_StgOpenStorage( pwcsName, pstgPriority, grfMode,
280                                 snbExclude, reserved, ppstgOpen);
281 }
282
283 static HRESULT WINAPI ITStorageImpl_StgOpenStorageOnILockBytes(
284     IITStorage* iface,
285     ILockBytes* plkbyt,
286     IStorage* pStgPriority,
287     DWORD grfMode,
288     SNB snbExclude,
289     DWORD reserved,
290     IStorage** ppstgOpen)
291 {
292     ITStorageImpl *This = (ITStorageImpl *)iface;
293     FIXME("%p\n", This);
294     return E_NOTIMPL;
295 }
296
297 static HRESULT WINAPI ITStorageImpl_StgSetTimes(
298     IITStorage* iface,
299     WCHAR* lpszName,
300     FILETIME* pctime,
301     FILETIME* patime,
302     FILETIME* pmtime)
303 {
304     ITStorageImpl *This = (ITStorageImpl *)iface;
305     FIXME("%p\n", This);
306     return E_NOTIMPL;
307 }
308
309 static HRESULT WINAPI ITStorageImpl_SetControlData(
310     IITStorage* iface,
311     PITS_Control_Data pControlData)
312 {
313     ITStorageImpl *This = (ITStorageImpl *)iface;
314     FIXME("%p\n", This);
315     return E_NOTIMPL;
316 }
317
318 static HRESULT WINAPI ITStorageImpl_DefaultControlData(
319     IITStorage* iface,
320     PITS_Control_Data* ppControlData)
321 {
322     ITStorageImpl *This = (ITStorageImpl *)iface;
323     FIXME("%p\n", This);
324     return E_NOTIMPL;
325 }
326
327 static HRESULT WINAPI ITStorageImpl_Compact(
328     IITStorage* iface,
329     const WCHAR* pwcsName,
330     ECompactionLev iLev)
331 {
332     ITStorageImpl *This = (ITStorageImpl *)iface;
333     FIXME("%p\n", This);
334     return E_NOTIMPL;
335 }
336
337 static const IITStorageVtbl ITStorageImpl_Vtbl =
338 {
339     ITStorageImpl_QueryInterface,
340     ITStorageImpl_AddRef,
341     ITStorageImpl_Release,
342     ITStorageImpl_StgCreateDocfile,
343     ITStorageImpl_StgCreateDocfileOnILockBytes,
344     ITStorageImpl_StgIsStorageFile,
345     ITStorageImpl_StgIsStorageILockBytes,
346     ITStorageImpl_StgOpenStorage,
347     ITStorageImpl_StgOpenStorageOnILockBytes,
348     ITStorageImpl_StgSetTimes,
349     ITStorageImpl_SetControlData,
350     ITStorageImpl_DefaultControlData,
351     ITStorageImpl_Compact,
352 };
353
354 static HRESULT ITSS_create(IUnknown *pUnkOuter, LPVOID *ppObj)
355 {
356     ITStorageImpl *its;
357
358     if( pUnkOuter )
359         return CLASS_E_NOAGGREGATION;
360
361     its = HeapAlloc( GetProcessHeap(), 0, sizeof(ITStorageImpl) );
362     its->vtbl_IITStorage = &ITStorageImpl_Vtbl;
363     its->ref = 1;
364
365     TRACE("-> %p\n", its);
366     *ppObj = (LPVOID) its;
367
368     ITSS_LockModule();
369     return S_OK;
370 }
371
372 /*****************************************************************************/
373
374 HRESULT WINAPI DllCanUnloadNow(void)
375 {
376     TRACE("dll_count = %u\n", dll_count);
377     return dll_count ? S_FALSE : S_OK;
378 }
379
380 #define INF_SET_ID(id)            \
381     do                            \
382     {                             \
383         static CHAR name[] = #id; \
384                                   \
385         pse[i].pszName = name;    \
386         clsids[i++] = &id;        \
387     } while (0)
388
389 #define INF_SET_CLSID(clsid) INF_SET_ID(CLSID_ ## clsid)
390
391 static HRESULT register_server(BOOL do_register)
392 {
393     HRESULT hres;
394     HMODULE hAdvpack;
395     typeof(RegInstallA) *pRegInstall;
396     STRTABLEA strtable;
397     STRENTRYA pse[4];
398     static CLSID const *clsids[4];
399     int i = 0;
400
401     static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0};
402
403     INF_SET_CLSID(ITStorage);
404     INF_SET_CLSID(MSFSStore);
405     INF_SET_CLSID(MSITStore);
406     INF_SET_CLSID(ITSProtocol);
407
408     strtable.cEntries = sizeof(pse)/sizeof(pse[0]);
409     strtable.pse = pse;
410
411     for(i=0; i < strtable.cEntries; i++) {
412         pse[i].pszValue = HeapAlloc(GetProcessHeap(), 0, 39);
413         sprintf(pse[i].pszValue, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
414                 clsids[i]->Data1, clsids[i]->Data2, clsids[i]->Data3, clsids[i]->Data4[0],
415                 clsids[i]->Data4[1], clsids[i]->Data4[2], clsids[i]->Data4[3], clsids[i]->Data4[4],
416                 clsids[i]->Data4[5], clsids[i]->Data4[6], clsids[i]->Data4[7]);
417     }
418
419     hAdvpack = LoadLibraryW(wszAdvpack);
420     pRegInstall = (typeof(RegInstallA)*)GetProcAddress(hAdvpack, "RegInstall");
421
422     hres = pRegInstall(hInst, do_register ? "RegisterDll" : "UnregisterDll", &strtable);
423
424     for(i=0; i < sizeof(pse)/sizeof(pse[0]); i++)
425         HeapFree(GetProcessHeap(), 0, pse[i].pszValue);
426
427     return hres;
428 }
429
430 #undef INF_SET_CLSID
431 #undef INF_SET_ID
432
433 /***********************************************************************
434  *          DllRegisterServer (ITSS.@)
435  */
436 HRESULT WINAPI DllRegisterServer(void)
437 {
438     return register_server(TRUE);
439 }
440
441 /***********************************************************************
442  *          DllUnregisterServer (ITSS.@)
443  */
444 HRESULT WINAPI DllUnregisterServer(void)
445 {
446     return register_server(FALSE);
447 }