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