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