ole32: Get rid of the ICOM_THIS_MULTI macro.
[wine] / dlls / itss / moniker.c
1 /*
2  *    ITSS Moniker implementation
3  *
4  * Copyright 2004 Mike McCormack
5  *
6  *  Implementation of the infamous mk:@MSITStore moniker
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24
25 #include <stdarg.h>
26 #include <stdio.h>
27
28 #define COBJMACROS
29
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winuser.h"
33 #include "ole2.h"
34
35 #include "wine/itss.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
38
39 #include "itsstor.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(itss);
42
43 /*****************************************************************************/
44
45 typedef struct {
46     const IMonikerVtbl *vtbl_ITS_IMoniker;
47     LONG ref;
48     LPWSTR szHtml;
49     WCHAR szFile[1];
50 } ITS_IMonikerImpl;
51
52 /*** IUnknown methods ***/
53 static HRESULT WINAPI ITS_IMonikerImpl_QueryInterface(
54     IMoniker* iface,
55     REFIID riid,
56     void** ppvObject)
57 {
58     ITS_IMonikerImpl *This = (ITS_IMonikerImpl *)iface;
59
60     if (IsEqualGUID(riid, &IID_IUnknown)
61         || IsEqualGUID(riid, &IID_IParseDisplayName))
62     {
63         IClassFactory_AddRef(iface);
64         *ppvObject = This;
65         return S_OK;
66     }
67
68     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
69     return E_NOINTERFACE;
70 }
71
72 static ULONG WINAPI ITS_IMonikerImpl_AddRef(
73     IMoniker* iface)
74 {
75     ITS_IMonikerImpl *This = (ITS_IMonikerImpl *)iface;
76     TRACE("%p\n", This);
77     return InterlockedIncrement(&This->ref);
78 }
79
80 static ULONG WINAPI ITS_IMonikerImpl_Release(
81     IMoniker* iface)
82 {
83     ITS_IMonikerImpl *This = (ITS_IMonikerImpl *)iface;
84     ULONG ref = InterlockedDecrement(&This->ref);
85
86     if (ref == 0) {
87         HeapFree(GetProcessHeap(), 0, This);
88         ITSS_UnlockModule();
89     }
90
91     return ref;
92 }
93
94 /*** IPersist methods ***/
95 static HRESULT WINAPI ITS_IMonikerImpl_GetClassID(
96     IMoniker* iface,
97     CLSID* pClassID)
98 {
99     ITS_IMonikerImpl *This = (ITS_IMonikerImpl *)iface;
100
101     TRACE("%p %p\n", This, pClassID);
102     *pClassID = CLSID_ITStorage;
103     return S_OK;
104 }
105
106 /*** IPersistStream methods ***/
107 static HRESULT WINAPI ITS_IMonikerImpl_IsDirty(
108     IMoniker* iface)
109 {
110     FIXME("\n");
111     return E_NOTIMPL;
112 }
113
114 static HRESULT WINAPI ITS_IMonikerImpl_Load(
115     IMoniker* iface,
116     IStream* pStm)
117 {
118     FIXME("\n");
119     return E_NOTIMPL;
120 }
121
122 static HRESULT WINAPI ITS_IMonikerImpl_Save(
123     IMoniker* iface,
124     IStream* pStm,
125     BOOL fClearDirty)
126 {
127     FIXME("\n");
128     return E_NOTIMPL;
129 }
130
131 static HRESULT WINAPI ITS_IMonikerImpl_GetSizeMax(
132     IMoniker* iface,
133     ULARGE_INTEGER* pcbSize)
134 {
135     FIXME("\n");
136     return E_NOTIMPL;
137 }
138
139 /*** IMoniker methods ***/
140 static HRESULT WINAPI ITS_IMonikerImpl_BindToObject(
141     IMoniker* iface,
142     IBindCtx* pbc,
143     IMoniker* pmkToLeft,
144     REFIID riidResult,
145     void** ppvResult)
146 {
147     FIXME("\n");
148     return E_NOTIMPL;
149 }
150
151 static HRESULT WINAPI ITS_IMonikerImpl_BindToStorage(
152     IMoniker* iface,
153     IBindCtx* pbc,
154     IMoniker* pmkToLeft,
155     REFIID riid,
156     void** ppvObj)
157 {
158     ITS_IMonikerImpl *This = (ITS_IMonikerImpl *)iface;
159     DWORD grfMode = STGM_SIMPLE | STGM_READ | STGM_SHARE_EXCLUSIVE;
160     HRESULT r;
161     IStorage *stg = NULL;
162
163     TRACE("%p %p %p %s %p\n", This,
164            pbc, pmkToLeft, debugstr_guid(riid), ppvObj);
165
166     r = ITSS_StgOpenStorage( This->szFile, NULL, grfMode, 0, 0, &stg );
167     if( r == S_OK )
168     {
169         TRACE("Opened storage %s\n", debugstr_w( This->szFile ) );
170         if (IsEqualGUID(riid, &IID_IStream))
171             r = IStorage_OpenStream( stg, This->szHtml,
172                        NULL, grfMode, 0, (IStream**)ppvObj );
173         else if (IsEqualGUID(riid, &IID_IStorage))
174             r = IStorage_OpenStorage( stg, This->szHtml,
175                        NULL, grfMode, NULL, 0, (IStorage**)ppvObj );
176         else
177             r = STG_E_ACCESSDENIED;
178         IStorage_Release( stg );
179     }
180
181     return r;
182 }
183
184 static HRESULT WINAPI ITS_IMonikerImpl_Reduce(
185     IMoniker* iface,
186     IBindCtx* pbc,
187     DWORD dwReduceHowFar,
188     IMoniker** ppmkToLeft,
189     IMoniker** ppmkReduced)
190 {
191     FIXME("\n");
192     return E_NOTIMPL;
193 }
194
195 static HRESULT WINAPI ITS_IMonikerImpl_ComposeWith(
196     IMoniker* iface,
197     IMoniker* pmkRight,
198     BOOL fOnlyIfNotGeneric,
199     IMoniker** ppmkComposite)
200 {
201     FIXME("\n");
202     return E_NOTIMPL;
203 }
204
205 static HRESULT WINAPI ITS_IMonikerImpl_Enum(
206     IMoniker* iface,
207     BOOL fForward,
208     IEnumMoniker** ppenumMoniker)
209 {
210     FIXME("\n");
211     return E_NOTIMPL;
212 }
213
214 static HRESULT WINAPI ITS_IMonikerImpl_IsEqual(
215     IMoniker* iface,
216     IMoniker* pmkOtherMoniker)
217 {
218     FIXME("\n");
219     return E_NOTIMPL;
220 }
221
222 static HRESULT WINAPI ITS_IMonikerImpl_Hash(
223     IMoniker* iface,
224     DWORD* pdwHash)
225 {
226     FIXME("\n");
227     return E_NOTIMPL;
228 }
229
230 static HRESULT WINAPI ITS_IMonikerImpl_IsRunning(
231     IMoniker* iface,
232     IBindCtx* pbc,
233     IMoniker* pmkToLeft,
234     IMoniker* pmkNewlyRunning)
235 {
236     FIXME("\n");
237     return E_NOTIMPL;
238 }
239
240 static HRESULT WINAPI ITS_IMonikerImpl_GetTimeOfLastChange(
241     IMoniker* iface,
242     IBindCtx* pbc,
243     IMoniker* pmkToLeft,
244     FILETIME* pFileTime)
245 {
246     FIXME("\n");
247     return E_NOTIMPL;
248 }
249
250 static HRESULT WINAPI ITS_IMonikerImpl_Inverse(
251     IMoniker* iface,
252     IMoniker** ppmk)
253 {
254     FIXME("\n");
255     return E_NOTIMPL;
256 }
257
258 static HRESULT WINAPI ITS_IMonikerImpl_CommonPrefixWith(
259     IMoniker* iface,
260     IMoniker* pmkOther,
261     IMoniker** ppmkPrefix)
262 {
263     FIXME("\n");
264     return E_NOTIMPL;
265 }
266
267 static HRESULT WINAPI ITS_IMonikerImpl_RelativePathTo(
268     IMoniker* iface,
269     IMoniker* pmkOther,
270     IMoniker** ppmkRelPath)
271 {
272     FIXME("\n");
273     return E_NOTIMPL;
274 }
275
276 static HRESULT WINAPI ITS_IMonikerImpl_GetDisplayName(
277     IMoniker* iface,
278     IBindCtx* pbc,
279     IMoniker* pmkToLeft,
280     LPOLESTR* ppszDisplayName)
281 {
282     ITS_IMonikerImpl *This = (ITS_IMonikerImpl *)iface;
283     static const WCHAR szFormat[] = {
284         'm','s','-','i','t','s',':','%','s',':',':','%','s',0 };
285     DWORD len = sizeof szFormat / sizeof(WCHAR);
286     LPWSTR str;
287
288     TRACE("%p %p %p %p\n", iface, pbc, pmkToLeft, ppszDisplayName);
289
290     len = strlenW( This->szFile ) + strlenW( This->szHtml );
291     str = CoTaskMemAlloc( len*sizeof(WCHAR) );
292     sprintfW( str, szFormat, This->szFile, This->szHtml );
293
294     *ppszDisplayName = str;
295     
296     return S_OK;
297 }
298
299 static HRESULT WINAPI ITS_IMonikerImpl_ParseDisplayName(
300     IMoniker* iface,
301     IBindCtx* pbc,
302     IMoniker* pmkToLeft,
303     LPOLESTR pszDisplayName,
304     ULONG* pchEaten,
305     IMoniker** ppmkOut)
306 {
307     FIXME("\n");
308     return E_NOTIMPL;
309 }
310
311 static HRESULT WINAPI ITS_IMonikerImpl_IsSystemMoniker(
312     IMoniker* iface,
313     DWORD* pdwMksys)
314 {
315     FIXME("\n");
316     return E_NOTIMPL;
317 }
318
319 static const IMonikerVtbl ITS_IMonikerImpl_Vtbl =
320 {
321     ITS_IMonikerImpl_QueryInterface,
322     ITS_IMonikerImpl_AddRef,
323     ITS_IMonikerImpl_Release,
324     ITS_IMonikerImpl_GetClassID,
325     ITS_IMonikerImpl_IsDirty,
326     ITS_IMonikerImpl_Load,
327     ITS_IMonikerImpl_Save,
328     ITS_IMonikerImpl_GetSizeMax,
329     ITS_IMonikerImpl_BindToObject,
330     ITS_IMonikerImpl_BindToStorage,
331     ITS_IMonikerImpl_Reduce,
332     ITS_IMonikerImpl_ComposeWith,
333     ITS_IMonikerImpl_Enum,
334     ITS_IMonikerImpl_IsEqual,
335     ITS_IMonikerImpl_Hash,
336     ITS_IMonikerImpl_IsRunning,
337     ITS_IMonikerImpl_GetTimeOfLastChange,
338     ITS_IMonikerImpl_Inverse,
339     ITS_IMonikerImpl_CommonPrefixWith,
340     ITS_IMonikerImpl_RelativePathTo,
341     ITS_IMonikerImpl_GetDisplayName,
342     ITS_IMonikerImpl_ParseDisplayName,
343     ITS_IMonikerImpl_IsSystemMoniker
344 };
345
346 static HRESULT ITS_IMoniker_create( IMoniker **ppObj, LPCWSTR name, DWORD n )
347 {
348     ITS_IMonikerImpl *itsmon;
349     DWORD sz;
350
351     /* szFile[1] has space for one character already */
352     sz = sizeof(ITS_IMonikerImpl) + strlenW( name )*sizeof(WCHAR);
353
354     itsmon = HeapAlloc( GetProcessHeap(), 0, sz );
355     itsmon->vtbl_ITS_IMoniker = &ITS_IMonikerImpl_Vtbl;
356     itsmon->ref = 1;
357     strcpyW( itsmon->szFile, name );
358     itsmon->szHtml = &itsmon->szFile[n];
359
360     while( *itsmon->szHtml == ':' )
361         *itsmon->szHtml++ = 0;
362
363     TRACE("-> %p %s %s\n", itsmon,
364           debugstr_w(itsmon->szFile), debugstr_w(itsmon->szHtml) );
365     *ppObj = (IMoniker*) itsmon;
366
367     ITSS_LockModule();
368     return S_OK;
369 }
370
371 /*****************************************************************************/
372
373 typedef struct {
374     const IParseDisplayNameVtbl *vtbl_ITS_IParseDisplayName;
375     LONG ref;
376 } ITS_IParseDisplayNameImpl;
377
378 static HRESULT WINAPI ITS_IParseDisplayNameImpl_QueryInterface(
379     IParseDisplayName* iface,
380     REFIID riid,
381     void** ppvObject)
382 {
383     ITS_IParseDisplayNameImpl *This = (ITS_IParseDisplayNameImpl *)iface;
384
385     if (IsEqualGUID(riid, &IID_IUnknown)
386         || IsEqualGUID(riid, &IID_IParseDisplayName))
387     {
388         IClassFactory_AddRef(iface);
389         *ppvObject = This;
390         return S_OK;
391     }
392
393     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
394     return E_NOINTERFACE;
395 }
396
397 static ULONG WINAPI ITS_IParseDisplayNameImpl_AddRef(
398     IParseDisplayName* iface)
399 {
400     ITS_IParseDisplayNameImpl *This = (ITS_IParseDisplayNameImpl *)iface;
401     TRACE("%p\n", This);
402     return InterlockedIncrement(&This->ref);
403 }
404
405 static ULONG WINAPI ITS_IParseDisplayNameImpl_Release(
406     IParseDisplayName* iface)
407 {
408     ITS_IParseDisplayNameImpl *This = (ITS_IParseDisplayNameImpl *)iface;
409     ULONG ref = InterlockedDecrement(&This->ref);
410
411     if (ref == 0) {
412         HeapFree(GetProcessHeap(), 0, This);
413         ITSS_UnlockModule();
414     }
415
416     return ref;
417 }
418
419 static HRESULT WINAPI ITS_IParseDisplayNameImpl_ParseDisplayName(
420     IParseDisplayName *iface,
421     IBindCtx * pbc,
422     LPOLESTR pszDisplayName, 
423     ULONG * pchEaten,
424     IMoniker ** ppmkOut)
425 {
426     static const WCHAR szPrefix[] = { 
427         '@','M','S','I','T','S','t','o','r','e',':',0 };
428     const DWORD prefix_len = (sizeof szPrefix/sizeof szPrefix[0])-1;
429     DWORD n;
430
431     ITS_IParseDisplayNameImpl *This = (ITS_IParseDisplayNameImpl *)iface;
432
433     TRACE("%p %s %p %p\n", This,
434           debugstr_w( pszDisplayName ), pchEaten, ppmkOut );
435
436     if( strncmpW( pszDisplayName, szPrefix, prefix_len ) )
437         return MK_E_SYNTAX;
438
439     /* search backwards for a double colon */
440     for( n = strlenW( pszDisplayName ) - 3; prefix_len <= n; n-- )
441         if( ( pszDisplayName[n] == ':' ) && ( pszDisplayName[n+1] == ':' ) )
442             break;
443
444     if( n < prefix_len )
445         return MK_E_SYNTAX;
446
447     if( !pszDisplayName[n+2] )
448         return MK_E_SYNTAX;
449
450     *pchEaten = strlenW( pszDisplayName ) - n - 3;
451
452     return ITS_IMoniker_create( ppmkOut,
453               &pszDisplayName[prefix_len], n-prefix_len );
454 }
455
456 static const IParseDisplayNameVtbl ITS_IParseDisplayNameImpl_Vtbl =
457 {
458     ITS_IParseDisplayNameImpl_QueryInterface,
459     ITS_IParseDisplayNameImpl_AddRef,
460     ITS_IParseDisplayNameImpl_Release,
461     ITS_IParseDisplayNameImpl_ParseDisplayName
462 };
463  
464 HRESULT ITS_IParseDisplayName_create(IUnknown *pUnkOuter, LPVOID *ppObj)
465 {
466     ITS_IParseDisplayNameImpl *its;
467
468     if( pUnkOuter )
469         return CLASS_E_NOAGGREGATION;
470
471     its = HeapAlloc( GetProcessHeap(), 0, sizeof(ITS_IParseDisplayNameImpl) );
472     its->vtbl_ITS_IParseDisplayName = &ITS_IParseDisplayNameImpl_Vtbl;
473     its->ref = 1;
474
475     TRACE("-> %p\n", its);
476     *ppObj = its;
477
478     ITSS_LockModule();
479     return S_OK;
480 }