1 /* 2 * AntiMonikers implementation 3 * 4 * Copyright 1999 Noomen Hamza 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include <assert.h> 22 #include <stdarg.h> 23 #include <string.h> 24 25 #define COBJMACROS 26 #define NONAMELESSUNION 27 28 #include "windef.h" 29 #include "winbase.h" 30 #include "winerror.h" 31 #include "objbase.h" 32 #include "wine/debug.h" 33 #include "moniker.h" 34 35 WINE_DEFAULT_DEBUG_CHANNEL(ole); 36 37 /* AntiMoniker data structure */ 38 typedef struct AntiMonikerImpl{ 39 IMoniker IMoniker_iface; 40 IROTData IROTData_iface; 41 LONG ref; 42 IUnknown *pMarshal; /* custom marshaler */ 43 } AntiMonikerImpl; 44 45 static inline AntiMonikerImpl *impl_from_IMoniker(IMoniker *iface) 46 { 47 return CONTAINING_RECORD(iface, AntiMonikerImpl, IMoniker_iface); 48 } 49 50 static inline AntiMonikerImpl *impl_from_IROTData(IROTData *iface) 51 { 52 return CONTAINING_RECORD(iface, AntiMonikerImpl, IROTData_iface); 53 } 54 55 56 /******************************************************************************* 57 * AntiMoniker_QueryInterface 58 *******************************************************************************/ 59 static HRESULT WINAPI 60 AntiMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) 61 { 62 AntiMonikerImpl *This = impl_from_IMoniker(iface); 63 64 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject); 65 66 /* Perform a sanity check on the parameters.*/ 67 if ( ppvObject==0 ) 68 return E_INVALIDARG; 69 70 /* Initialize the return parameter */ 71 *ppvObject = 0; 72 73 /* Compare the riid with the interface IDs implemented by this object.*/ 74 if (IsEqualIID(&IID_IUnknown, riid) || 75 IsEqualIID(&IID_IPersist, riid) || 76 IsEqualIID(&IID_IPersistStream, riid) || 77 IsEqualIID(&IID_IMoniker, riid)) 78 *ppvObject = iface; 79 else if (IsEqualIID(&IID_IROTData, riid)) 80 *ppvObject = &This->IROTData_iface; 81 else if (IsEqualIID(&IID_IMarshal, riid)) 82 { 83 HRESULT hr = S_OK; 84 if (!This->pMarshal) 85 hr = MonikerMarshal_Create(iface, &This->pMarshal); 86 if (hr != S_OK) 87 return hr; 88 return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject); 89 } 90 91 /* Check that we obtained an interface.*/ 92 if ((*ppvObject)==0) 93 return E_NOINTERFACE; 94 95 /* always increase the reference count by one when it is successful */ 96 IMoniker_AddRef(iface); 97 98 return S_OK; 99 } 100 101 /****************************************************************************** 102 * AntiMoniker_AddRef 103 ******************************************************************************/ 104 static ULONG WINAPI 105 AntiMonikerImpl_AddRef(IMoniker* iface) 106 { 107 AntiMonikerImpl *This = impl_from_IMoniker(iface); 108 109 TRACE("(%p)\n",This); 110 111 return InterlockedIncrement(&This->ref); 112 } 113 114 /****************************************************************************** 115 * AntiMoniker_Release 116 ******************************************************************************/ 117 static ULONG WINAPI 118 AntiMonikerImpl_Release(IMoniker* iface) 119 { 120 AntiMonikerImpl *This = impl_from_IMoniker(iface); 121 ULONG ref; 122 123 TRACE("(%p)\n",This); 124 125 ref = InterlockedDecrement(&This->ref); 126 127 /* destroy the object if there are no more references to it */ 128 if (ref == 0) 129 { 130 if (This->pMarshal) IUnknown_Release(This->pMarshal); 131 HeapFree(GetProcessHeap(),0,This); 132 } 133 134 return ref; 135 } 136 137 /****************************************************************************** 138 * AntiMoniker_GetClassID 139 ******************************************************************************/ 140 static HRESULT WINAPI 141 AntiMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID) 142 { 143 TRACE("(%p,%p)\n",iface,pClassID); 144 145 if (pClassID==NULL) 146 return E_POINTER; 147 148 *pClassID = CLSID_AntiMoniker; 149 150 return S_OK; 151 } 152 153 /****************************************************************************** 154 * AntiMoniker_IsDirty 155 ******************************************************************************/ 156 static HRESULT WINAPI 157 AntiMonikerImpl_IsDirty(IMoniker* iface) 158 { 159 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty 160 method in the OLE-provided moniker interfaces always return S_FALSE because 161 their internal state never changes. */ 162 163 TRACE("(%p)\n",iface); 164 165 return S_FALSE; 166 } 167 168 /****************************************************************************** 169 * AntiMoniker_Load 170 ******************************************************************************/ 171 static HRESULT WINAPI 172 AntiMonikerImpl_Load(IMoniker* iface,IStream* pStm) 173 { 174 DWORD constant=1,dwbuffer; 175 HRESULT res; 176 177 /* data read by this function is only a DWORD constant (must be 1) ! */ 178 res=IStream_Read(pStm,&dwbuffer,sizeof(DWORD),NULL); 179 180 if (SUCCEEDED(res)&& dwbuffer!=constant) 181 return E_FAIL; 182 183 return res; 184 } 185 186 /****************************************************************************** 187 * AntiMoniker_Save 188 ******************************************************************************/ 189 static HRESULT WINAPI 190 AntiMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty) 191 { 192 static const DWORD constant = 1; 193 /* data written by this function is only a DWORD constant set to 1 ! */ 194 return IStream_Write(pStm,&constant,sizeof(constant),NULL); 195 } 196 197 /****************************************************************************** 198 * AntiMoniker_GetSizeMax 199 * 200 * PARAMS 201 * pcbSize [out] Pointer to size of stream needed to save object 202 ******************************************************************************/ 203 static HRESULT WINAPI 204 AntiMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize) 205 { 206 TRACE("(%p,%p)\n",iface,pcbSize); 207 208 if (!pcbSize) 209 return E_POINTER; 210 211 /* for more details see AntiMonikerImpl_Save comments */ 212 213 /* 214 * Normally the sizemax must be sizeof DWORD, but 215 * I tested this function it usually return 16 bytes 216 * more than the number of bytes used by AntiMoniker::Save function 217 */ 218 pcbSize->u.LowPart = sizeof(DWORD)+16; 219 220 pcbSize->u.HighPart=0; 221 222 return S_OK; 223 } 224 225 /****************************************************************************** 226 * AntiMoniker_BindToObject 227 ******************************************************************************/ 228 static HRESULT WINAPI 229 AntiMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, 230 REFIID riid, VOID** ppvResult) 231 { 232 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult); 233 return E_NOTIMPL; 234 } 235 236 /****************************************************************************** 237 * AntiMoniker_BindToStorage 238 ******************************************************************************/ 239 static HRESULT WINAPI 240 AntiMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, 241 REFIID riid, VOID** ppvResult) 242 { 243 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult); 244 return E_NOTIMPL; 245 } 246 247 /****************************************************************************** 248 * AntiMoniker_Reduce 249 ******************************************************************************/ 250 static HRESULT WINAPI 251 AntiMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar, 252 IMoniker** ppmkToLeft, IMoniker** ppmkReduced) 253 { 254 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced); 255 256 if (ppmkReduced==NULL) 257 return E_POINTER; 258 259 AntiMonikerImpl_AddRef(iface); 260 261 *ppmkReduced=iface; 262 263 return MK_S_REDUCED_TO_SELF; 264 } 265 /****************************************************************************** 266 * AntiMoniker_ComposeWith 267 ******************************************************************************/ 268 static HRESULT WINAPI 269 AntiMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight, 270 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite) 271 { 272 273 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite); 274 275 if ((ppmkComposite==NULL)||(pmkRight==NULL)) 276 return E_POINTER; 277 278 *ppmkComposite=0; 279 280 if (fOnlyIfNotGeneric) 281 return MK_E_NEEDGENERIC; 282 else 283 return CreateGenericComposite(iface,pmkRight,ppmkComposite); 284 } 285 286 /****************************************************************************** 287 * AntiMoniker_Enum 288 ******************************************************************************/ 289 static HRESULT WINAPI 290 AntiMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker) 291 { 292 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker); 293 294 if (ppenumMoniker == NULL) 295 return E_POINTER; 296 297 *ppenumMoniker = NULL; 298 299 return S_OK; 300 } 301 302 /****************************************************************************** 303 * AntiMoniker_IsEqual 304 ******************************************************************************/ 305 static HRESULT WINAPI 306 AntiMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) 307 { 308 DWORD mkSys; 309 310 TRACE("(%p,%p)\n",iface,pmkOtherMoniker); 311 312 if (pmkOtherMoniker==NULL) 313 return S_FALSE; 314 315 IMoniker_IsSystemMoniker(pmkOtherMoniker,&mkSys); 316 317 if (mkSys==MKSYS_ANTIMONIKER) 318 return S_OK; 319 else 320 return S_FALSE; 321 } 322 323 /****************************************************************************** 324 * AntiMoniker_Hash 325 ******************************************************************************/ 326 static HRESULT WINAPI AntiMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) 327 { 328 if (pdwHash==NULL) 329 return E_POINTER; 330 331 *pdwHash = 0x80000001; 332 333 return S_OK; 334 } 335 336 /****************************************************************************** 337 * AntiMoniker_IsRunning 338 ******************************************************************************/ 339 static HRESULT WINAPI 340 AntiMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, 341 IMoniker* pmkNewlyRunning) 342 { 343 IRunningObjectTable* rot; 344 HRESULT res; 345 346 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning); 347 348 if (pbc==NULL) 349 return E_INVALIDARG; 350 351 res=IBindCtx_GetRunningObjectTable(pbc,&rot); 352 353 if (FAILED(res)) 354 return res; 355 356 res = IRunningObjectTable_IsRunning(rot,iface); 357 358 IRunningObjectTable_Release(rot); 359 360 return res; 361 } 362 363 /****************************************************************************** 364 * AntiMoniker_GetTimeOfLastChange 365 ******************************************************************************/ 366 static HRESULT WINAPI AntiMonikerImpl_GetTimeOfLastChange(IMoniker* iface, 367 IBindCtx* pbc, 368 IMoniker* pmkToLeft, 369 FILETIME* pAntiTime) 370 { 371 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pAntiTime); 372 return E_NOTIMPL; 373 } 374 375 /****************************************************************************** 376 * AntiMoniker_Inverse 377 ******************************************************************************/ 378 static HRESULT WINAPI 379 AntiMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) 380 { 381 TRACE("(%p,%p)\n",iface,ppmk); 382 383 if (ppmk==NULL) 384 return E_POINTER; 385 386 *ppmk=0; 387 388 return MK_E_NOINVERSE; 389 } 390 391 /****************************************************************************** 392 * AntiMoniker_CommonPrefixWith 393 ******************************************************************************/ 394 static HRESULT WINAPI 395 AntiMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) 396 { 397 DWORD mkSys; 398 399 IMoniker_IsSystemMoniker(pmkOther,&mkSys); 400 401 if(mkSys==MKSYS_ANTIMONIKER){ 402 403 IMoniker_AddRef(iface); 404 405 *ppmkPrefix=iface; 406 407 IMoniker_AddRef(iface); 408 409 return MK_S_US; 410 } 411 else 412 return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix); 413 } 414 415 /****************************************************************************** 416 * AntiMoniker_RelativePathTo 417 ******************************************************************************/ 418 static HRESULT WINAPI 419 AntiMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath) 420 { 421 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath); 422 423 if (ppmkRelPath==NULL) 424 return E_POINTER; 425 426 IMoniker_AddRef(pmOther); 427 428 *ppmkRelPath=pmOther; 429 430 return MK_S_HIM; 431 } 432 433 /****************************************************************************** 434 * AntiMoniker_GetDisplayName 435 ******************************************************************************/ 436 static HRESULT WINAPI 437 AntiMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc, 438 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName) 439 { 440 static const WCHAR back[]={'\\','.','.',0}; 441 442 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName); 443 444 if (ppszDisplayName==NULL) 445 return E_POINTER; 446 447 if (pmkToLeft!=NULL){ 448 FIXME("() pmkToLeft!=NULL not implemented\n"); 449 return E_NOTIMPL; 450 } 451 452 *ppszDisplayName=CoTaskMemAlloc(sizeof(back)); 453 454 if (*ppszDisplayName==NULL) 455 return E_OUTOFMEMORY; 456 457 lstrcpyW(*ppszDisplayName,back); 458 459 return S_OK; 460 } 461 462 /****************************************************************************** 463 * AntiMoniker_ParseDisplayName 464 ******************************************************************************/ 465 static HRESULT WINAPI 466 AntiMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, 467 IMoniker* pmkToLeft, LPOLESTR pszDisplayName, 468 ULONG* pchEaten, IMoniker** ppmkOut) 469 { 470 TRACE("(%p,%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut); 471 return E_NOTIMPL; 472 } 473 474 /****************************************************************************** 475 * AntiMoniker_IsSystemMoniker 476 ******************************************************************************/ 477 static HRESULT WINAPI 478 AntiMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) 479 { 480 TRACE("(%p,%p)\n",iface,pwdMksys); 481 482 if (!pwdMksys) 483 return E_POINTER; 484 485 (*pwdMksys)=MKSYS_ANTIMONIKER; 486 487 return S_OK; 488 } 489 490 /******************************************************************************* 491 * AntiMonikerIROTData_QueryInterface 492 *******************************************************************************/ 493 static HRESULT WINAPI 494 AntiMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject) 495 { 496 AntiMonikerImpl *This = impl_from_IROTData(iface); 497 498 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppvObject); 499 500 return AntiMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject); 501 } 502 503 /*********************************************************************** 504 * AntiMonikerIROTData_AddRef 505 */ 506 static ULONG WINAPI AntiMonikerROTDataImpl_AddRef(IROTData *iface) 507 { 508 AntiMonikerImpl *This = impl_from_IROTData(iface); 509 510 TRACE("(%p)\n",iface); 511 512 return AntiMonikerImpl_AddRef(&This->IMoniker_iface); 513 } 514 515 /*********************************************************************** 516 * AntiMonikerIROTData_Release 517 */ 518 static ULONG WINAPI AntiMonikerROTDataImpl_Release(IROTData* iface) 519 { 520 AntiMonikerImpl *This = impl_from_IROTData(iface); 521 522 TRACE("(%p)\n",iface); 523 524 return AntiMonikerImpl_Release(&This->IMoniker_iface); 525 } 526 527 /****************************************************************************** 528 * AntiMonikerIROTData_GetComparisonData 529 ******************************************************************************/ 530 static HRESULT WINAPI 531 AntiMonikerROTDataImpl_GetComparisonData(IROTData* iface, BYTE* pbData, 532 ULONG cbMax, ULONG* pcbData) 533 { 534 DWORD constant = 1; 535 536 TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData); 537 538 *pcbData = sizeof(CLSID) + sizeof(DWORD); 539 if (cbMax < *pcbData) 540 return E_OUTOFMEMORY; 541 542 memcpy(pbData, &CLSID_AntiMoniker, sizeof(CLSID)); 543 memcpy(pbData+sizeof(CLSID), &constant, sizeof(DWORD)); 544 545 return S_OK; 546 } 547 548 /********************************************************************************/ 549 /* Virtual function table for the AntiMonikerImpl class which include IPersist,*/ 550 /* IPersistStream and IMoniker functions. */ 551 static const IMonikerVtbl VT_AntiMonikerImpl = 552 { 553 AntiMonikerImpl_QueryInterface, 554 AntiMonikerImpl_AddRef, 555 AntiMonikerImpl_Release, 556 AntiMonikerImpl_GetClassID, 557 AntiMonikerImpl_IsDirty, 558 AntiMonikerImpl_Load, 559 AntiMonikerImpl_Save, 560 AntiMonikerImpl_GetSizeMax, 561 AntiMonikerImpl_BindToObject, 562 AntiMonikerImpl_BindToStorage, 563 AntiMonikerImpl_Reduce, 564 AntiMonikerImpl_ComposeWith, 565 AntiMonikerImpl_Enum, 566 AntiMonikerImpl_IsEqual, 567 AntiMonikerImpl_Hash, 568 AntiMonikerImpl_IsRunning, 569 AntiMonikerImpl_GetTimeOfLastChange, 570 AntiMonikerImpl_Inverse, 571 AntiMonikerImpl_CommonPrefixWith, 572 AntiMonikerImpl_RelativePathTo, 573 AntiMonikerImpl_GetDisplayName, 574 AntiMonikerImpl_ParseDisplayName, 575 AntiMonikerImpl_IsSystemMoniker 576 }; 577 578 /********************************************************************************/ 579 /* Virtual function table for the IROTData class. */ 580 static const IROTDataVtbl VT_ROTDataImpl = 581 { 582 AntiMonikerROTDataImpl_QueryInterface, 583 AntiMonikerROTDataImpl_AddRef, 584 AntiMonikerROTDataImpl_Release, 585 AntiMonikerROTDataImpl_GetComparisonData 586 }; 587 588 /****************************************************************************** 589 * AntiMoniker_Construct (local function) 590 *******************************************************************************/ 591 static HRESULT AntiMonikerImpl_Construct(AntiMonikerImpl* This) 592 { 593 594 TRACE("(%p)\n",This); 595 596 /* Initialize the virtual function table. */ 597 This->IMoniker_iface.lpVtbl = &VT_AntiMonikerImpl; 598 This->IROTData_iface.lpVtbl = &VT_ROTDataImpl; 599 This->ref = 0; 600 This->pMarshal = NULL; 601 602 return S_OK; 603 } 604 605 /****************************************************************************** 606 * CreateAntiMoniker [OLE32.@] 607 ******************************************************************************/ 608 HRESULT WINAPI CreateAntiMoniker(IMoniker **ppmk) 609 { 610 AntiMonikerImpl* newAntiMoniker; 611 HRESULT hr; 612 613 TRACE("(%p)\n",ppmk); 614 615 newAntiMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(AntiMonikerImpl)); 616 617 if (newAntiMoniker == 0) 618 return STG_E_INSUFFICIENTMEMORY; 619 620 hr = AntiMonikerImpl_Construct(newAntiMoniker); 621 if (FAILED(hr)) 622 { 623 HeapFree(GetProcessHeap(),0,newAntiMoniker); 624 return hr; 625 } 626 627 return AntiMonikerImpl_QueryInterface(&newAntiMoniker->IMoniker_iface, &IID_IMoniker, 628 (void**)ppmk); 629 } 630 631 HRESULT WINAPI AntiMoniker_CreateInstance(IClassFactory *iface, 632 IUnknown *pUnk, REFIID riid, void **ppv) 633 { 634 IMoniker *pMoniker; 635 HRESULT hr; 636 637 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv); 638 639 *ppv = NULL; 640 641 if (pUnk) 642 return CLASS_E_NOAGGREGATION; 643 644 hr = CreateAntiMoniker(&pMoniker); 645 if (FAILED(hr)) 646 return hr; 647 648 hr = IMoniker_QueryInterface(pMoniker, riid, ppv); 649 650 if (FAILED(hr)) 651 IMoniker_Release(pMoniker); 652 653 return hr; 654 } 655