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