Build idl files as part of the normal build process.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24
25 #include <stdarg.h>
26 #include <stdio.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "winnls.h"
32 #include "winreg.h"
33 #include "ole2.h"
34
35 #include "itss.h"
36 #include "uuids.h"
37
38 #include "wine/unicode.h"
39 #include "wine/debug.h"
40
41 #include "itsstor.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(itss);
44
45 /*****************************************************************************/
46
47 typedef struct {
48     IMonikerVtbl *vtbl_ITS_IMoniker;
49     DWORD ref;
50     LPWSTR szHtml;
51     WCHAR szFile[1];
52 } ITS_IMonikerImpl;
53
54 /*** IUnknown methods ***/
55 static HRESULT WINAPI ITS_IMonikerImpl_QueryInterface(
56     IMoniker* iface,
57     REFIID riid,
58     void** ppvObject)
59 {
60     ITS_IMonikerImpl *This = (ITS_IMonikerImpl *)iface;
61
62     if (IsEqualGUID(riid, &IID_IUnknown)
63         || IsEqualGUID(riid, &IID_IParseDisplayName))
64     {
65         IClassFactory_AddRef(iface);
66         *ppvObject = This;
67         return S_OK;
68     }
69
70     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
71     return E_NOINTERFACE;
72 }
73
74 static ULONG WINAPI ITS_IMonikerImpl_AddRef(
75     IMoniker* iface)
76 {
77     ITS_IMonikerImpl *This = (ITS_IMonikerImpl *)iface;
78     TRACE("%p\n", This);
79     return ++(This->ref);
80 }
81
82 static ULONG WINAPI ITS_IMonikerImpl_Release(
83     IMoniker* iface)
84 {
85     ITS_IMonikerImpl *This = (ITS_IMonikerImpl *)iface;
86     ULONG ref = --This->ref;
87
88     if (ref == 0)
89         HeapFree(GetProcessHeap(), 0, This);
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     memcpy( pClassID, &CLSID_ITStorage, sizeof (CLSID) );
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 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, LPWSTR 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     return S_OK;
368 }
369
370 /*****************************************************************************/
371
372 typedef struct {
373     IParseDisplayNameVtbl *vtbl_ITS_IParseDisplayName;
374     DWORD ref;
375 } ITS_IParseDisplayNameImpl;
376
377 static HRESULT WINAPI ITS_IParseDisplayNameImpl_QueryInterface(
378     IParseDisplayName* iface,
379     REFIID riid,
380     void** ppvObject)
381 {
382     ITS_IParseDisplayNameImpl *This = (ITS_IParseDisplayNameImpl *)iface;
383
384     if (IsEqualGUID(riid, &IID_IUnknown)
385         || IsEqualGUID(riid, &IID_IParseDisplayName))
386     {
387         IClassFactory_AddRef(iface);
388         *ppvObject = This;
389         return S_OK;
390     }
391
392     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppvObject);
393     return E_NOINTERFACE;
394 }
395
396 static ULONG WINAPI ITS_IParseDisplayNameImpl_AddRef(
397     IParseDisplayName* iface)
398 {
399     ITS_IParseDisplayNameImpl *This = (ITS_IParseDisplayNameImpl *)iface;
400     TRACE("%p\n", This);
401     return ++(This->ref);
402 }
403
404 static ULONG WINAPI ITS_IParseDisplayNameImpl_Release(
405     IParseDisplayName* iface)
406 {
407     ITS_IParseDisplayNameImpl *This = (ITS_IParseDisplayNameImpl *)iface;
408     ULONG ref = --This->ref;
409
410     if (ref == 0)
411         HeapFree(GetProcessHeap(), 0, This);
412
413     return ref;
414 }
415
416 static HRESULT WINAPI ITS_IParseDisplayNameImpl_ParseDisplayName(
417     IParseDisplayName *iface,
418     IBindCtx * pbc,
419     LPOLESTR pszDisplayName, 
420     ULONG * pchEaten,
421     IMoniker ** ppmkOut)
422 {
423     static const WCHAR szPrefix[] = { 
424         '@','M','S','I','T','S','t','o','r','e',':',0 };
425     const DWORD prefix_len = (sizeof szPrefix/sizeof szPrefix[0])-1;
426     DWORD n;
427
428     ITS_IParseDisplayNameImpl *This = (ITS_IParseDisplayNameImpl *)iface;
429
430     TRACE("%p %s %p %p\n", This,
431           debugstr_w( pszDisplayName ), pchEaten, ppmkOut );
432
433     if( strncmpW( pszDisplayName, szPrefix, prefix_len ) )
434         return MK_E_SYNTAX;
435
436     /* search backwards for a double colon */
437     for( n = strlenW( pszDisplayName ) - 3; prefix_len <= n; n-- )
438         if( ( pszDisplayName[n] == ':' ) && ( pszDisplayName[n+1] == ':' ) )
439             break;
440
441     if( n < prefix_len )
442         return MK_E_SYNTAX;
443
444     if( !pszDisplayName[n+2] )
445         return MK_E_SYNTAX;
446
447     *pchEaten = strlenW( pszDisplayName ) - n - 3;
448
449     return ITS_IMoniker_create( ppmkOut,
450               &pszDisplayName[prefix_len], n-prefix_len );
451 }
452
453 static IParseDisplayNameVtbl ITS_IParseDisplayNameImpl_Vtbl =
454 {
455     ITS_IParseDisplayNameImpl_QueryInterface,
456     ITS_IParseDisplayNameImpl_AddRef,
457     ITS_IParseDisplayNameImpl_Release,
458     ITS_IParseDisplayNameImpl_ParseDisplayName
459 };
460  
461 HRESULT ITS_IParseDisplayName_create(IUnknown *pUnkOuter, LPVOID *ppObj)
462 {
463     ITS_IParseDisplayNameImpl *its;
464
465     its = HeapAlloc( GetProcessHeap(), 0, sizeof(ITS_IParseDisplayNameImpl) );
466     its->vtbl_ITS_IParseDisplayName = &ITS_IParseDisplayNameImpl_Vtbl;
467     its->ref = 1;
468
469     TRACE("-> %p\n", its);
470     *ppObj = (LPVOID) its;
471
472     return S_OK;
473 }