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