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 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 ***/ 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 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 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 ***/ 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 ***/ 110 static HRESULT WINAPI ITS_IMonikerImpl_IsDirty( 111 IMoniker* iface) 112 { 113 FIXME("\n"); 114 return E_NOTIMPL; 115 } 116 117 static HRESULT WINAPI ITS_IMonikerImpl_Load( 118 IMoniker* iface, 119 IStream* pStm) 120 { 121 FIXME("\n"); 122 return E_NOTIMPL; 123 } 124 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 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 ***/ 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 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 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 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 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 217 static HRESULT WINAPI ITS_IMonikerImpl_IsEqual( 218 IMoniker* iface, 219 IMoniker* pmkOtherMoniker) 220 { 221 FIXME("\n"); 222 return E_NOTIMPL; 223 } 224 225 static HRESULT WINAPI ITS_IMonikerImpl_Hash( 226 IMoniker* iface, 227 DWORD* pdwHash) 228 { 229 FIXME("\n"); 230 return E_NOTIMPL; 231 } 232 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 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 253 static HRESULT WINAPI ITS_IMonikerImpl_Inverse( 254 IMoniker* iface, 255 IMoniker** ppmk) 256 { 257 FIXME("\n"); 258 return E_NOTIMPL; 259 } 260 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 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 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 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 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 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 381 static inline ITS_IParseDisplayNameImpl *impl_from_IParseDisplayName(IParseDisplayName *iface) 382 { 383 return CONTAINING_RECORD(iface, ITS_IParseDisplayNameImpl, IParseDisplayName_iface); 384 } 385 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 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 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 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 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