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