1 /* 2 * Class Monikers 3 * 4 * Copyright 1999 Noomen Hamza 5 * Copyright 2005-2007 Robert Shearman 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include <assert.h> 23 #include <stdarg.h> 24 #include <string.h> 25 26 #define COBJMACROS 27 #define NONAMELESSUNION 28 #define NONAMELESSSTRUCT 29 30 #include "winerror.h" 31 #include "windef.h" 32 #include "winbase.h" 33 #include "winuser.h" 34 #include "wine/debug.h" 35 #include "ole2.h" 36 #include "wine/unicode.h" 37 #include "moniker.h" 38 39 WINE_DEFAULT_DEBUG_CHANNEL(ole); 40 41 #define CHARS_IN_GUID 39 42 43 /* ClassMoniker data structure */ 44 typedef struct ClassMoniker 45 { 46 const IMonikerVtbl* lpVtbl; /* VTable relative to the IMoniker interface.*/ 47 const IROTDataVtbl* lpVtblRotData; /* VTable relative to the IROTData interface.*/ 48 LONG ref; /* reference counter for this object */ 49 CLSID clsid; /* clsid identified by this moniker */ 50 IUnknown *pMarshal; /* custom marshaler */ 51 } ClassMoniker; 52 53 static inline IMoniker *impl_from_IROTData( IROTData *iface ) 54 { 55 return (IMoniker *)((char*)iface - FIELD_OFFSET(ClassMoniker, lpVtblRotData)); 56 } 57 58 /******************************************************************************* 59 * ClassMoniker_QueryInterface 60 *******************************************************************************/ 61 static HRESULT WINAPI ClassMoniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) 62 { 63 ClassMoniker *This = (ClassMoniker *)iface; 64 65 TRACE("(%p,%p,%p)\n",This,riid,ppvObject); 66 67 /* Perform a sanity check on the parameters.*/ 68 if (!ppvObject) 69 return E_POINTER; 70 71 /* Initialize the return parameter */ 72 *ppvObject = 0; 73 74 /* Compare the riid with the interface IDs implemented by this object.*/ 75 if (IsEqualIID(&IID_IUnknown, riid) || 76 IsEqualIID(&IID_IPersist, riid) || 77 IsEqualIID(&IID_IPersistStream, riid) || 78 IsEqualIID(&IID_IMoniker, riid)) 79 { 80 *ppvObject = iface; 81 } 82 else if (IsEqualIID(&IID_IROTData, riid)) 83 *ppvObject = &This->lpVtblRotData; 84 else if (IsEqualIID(&IID_IMarshal, riid)) 85 { 86 HRESULT hr = S_OK; 87 if (!This->pMarshal) 88 hr = MonikerMarshal_Create(iface, &This->pMarshal); 89 if (hr != S_OK) 90 return hr; 91 return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject); 92 } 93 94 /* Check that we obtained an interface.*/ 95 if (!*ppvObject) 96 return E_NOINTERFACE; 97 98 /* Query Interface always increases the reference count by one when it is successful */ 99 IMoniker_AddRef(iface); 100 101 return S_OK; 102 } 103 104 /****************************************************************************** 105 * ClassMoniker_AddRef 106 ******************************************************************************/ 107 static ULONG WINAPI ClassMoniker_AddRef(IMoniker* iface) 108 { 109 ClassMoniker *This = (ClassMoniker *)iface; 110 111 TRACE("(%p)\n",This); 112 113 return InterlockedIncrement(&This->ref); 114 } 115 116 /****************************************************************************** 117 * ClassMoniker_Destroy (local function) 118 *******************************************************************************/ 119 static HRESULT ClassMoniker_Destroy(ClassMoniker* This) 120 { 121 TRACE("(%p)\n",This); 122 123 if (This->pMarshal) IUnknown_Release(This->pMarshal); 124 125 HeapFree(GetProcessHeap(),0,This); 126 127 return S_OK; 128 } 129 130 /****************************************************************************** 131 * ClassMoniker_Release 132 ******************************************************************************/ 133 static ULONG WINAPI ClassMoniker_Release(IMoniker* iface) 134 { 135 ClassMoniker *This = (ClassMoniker *)iface; 136 ULONG ref; 137 138 TRACE("(%p)\n",This); 139 140 ref = InterlockedDecrement(&This->ref); 141 142 /* destroy the object if there's no more reference on it */ 143 if (ref == 0) ClassMoniker_Destroy(This); 144 145 return ref; 146 } 147 148 /****************************************************************************** 149 * ClassMoniker_GetClassID 150 ******************************************************************************/ 151 static HRESULT WINAPI ClassMoniker_GetClassID(IMoniker* iface,CLSID *pClassID) 152 { 153 TRACE("(%p,%p),stub!\n",iface,pClassID); 154 155 if (pClassID==NULL) 156 return E_POINTER; 157 158 *pClassID = CLSID_ClassMoniker; 159 160 return S_OK; 161 } 162 163 /****************************************************************************** 164 * ClassMoniker_IsDirty 165 ******************************************************************************/ 166 static HRESULT WINAPI ClassMoniker_IsDirty(IMoniker* iface) 167 { 168 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty 169 method in the OLE-provided moniker interfaces always return S_FALSE because 170 their internal state never changes. */ 171 172 TRACE("(%p)\n",iface); 173 174 return S_FALSE; 175 } 176 177 /****************************************************************************** 178 * ClassMoniker_Load 179 ******************************************************************************/ 180 static HRESULT WINAPI ClassMoniker_Load(IMoniker* iface,IStream* pStm) 181 { 182 ClassMoniker *This = (ClassMoniker *)iface; 183 HRESULT hr; 184 DWORD zero; 185 186 TRACE("(%p)\n", pStm); 187 188 hr = IStream_Read(pStm, &This->clsid, sizeof(This->clsid), NULL); 189 if (hr != S_OK) return STG_E_READFAULT; 190 191 hr = IStream_Read(pStm, &zero, sizeof(zero), NULL); 192 if ((hr != S_OK) || (zero != 0)) return STG_E_READFAULT; 193 194 return S_OK; 195 } 196 197 /****************************************************************************** 198 * ClassMoniker_Save 199 ******************************************************************************/ 200 static HRESULT WINAPI ClassMoniker_Save(IMoniker* iface, 201 IStream* pStm,/* pointer to the stream where the object is to be saved */ 202 BOOL fClearDirty)/* Specifies whether to clear the dirty flag */ 203 { 204 ClassMoniker *This = (ClassMoniker *)iface; 205 HRESULT hr; 206 DWORD zero = 0; 207 208 TRACE("(%p, %s)\n", pStm, fClearDirty ? "TRUE" : "FALSE"); 209 210 hr = IStream_Write(pStm, &This->clsid, sizeof(This->clsid), NULL); 211 if (FAILED(hr)) return hr; 212 213 hr = IStream_Write(pStm, &zero, sizeof(zero), NULL); 214 215 return hr; 216 } 217 218 /****************************************************************************** 219 * ClassMoniker_GetSizeMax 220 ******************************************************************************/ 221 static HRESULT WINAPI ClassMoniker_GetSizeMax(IMoniker* iface, 222 ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */ 223 { 224 TRACE("(%p)\n", pcbSize); 225 226 pcbSize->QuadPart = sizeof(CLSID) + sizeof(DWORD); 227 228 return S_OK; 229 } 230 231 /****************************************************************************** 232 * ClassMoniker_BindToObject 233 ******************************************************************************/ 234 static HRESULT WINAPI ClassMoniker_BindToObject(IMoniker* iface, 235 IBindCtx* pbc, 236 IMoniker* pmkToLeft, 237 REFIID riid, 238 VOID** ppvResult) 239 { 240 ClassMoniker *This = (ClassMoniker *)iface; 241 BIND_OPTS2 bindopts; 242 IClassActivator *pActivator; 243 HRESULT hr; 244 245 TRACE("(%p,%p,%p,%p)\n", pbc, pmkToLeft, riid, ppvResult); 246 247 bindopts.cbStruct = sizeof(bindopts); 248 IBindCtx_GetBindOptions(pbc, (BIND_OPTS *)&bindopts); 249 250 if (!pmkToLeft) 251 return CoGetClassObject(&This->clsid, bindopts.dwClassContext, NULL, 252 riid, ppvResult); 253 else 254 { 255 hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IClassActivator, 256 (void **)&pActivator); 257 if (FAILED(hr)) return hr; 258 259 hr = IClassActivator_GetClassObject(pActivator, &This->clsid, 260 bindopts.dwClassContext, 261 bindopts.locale, riid, ppvResult); 262 263 IClassActivator_Release(pActivator); 264 265 return hr; 266 } 267 } 268 269 /****************************************************************************** 270 * ClassMoniker_BindToStorage 271 ******************************************************************************/ 272 static HRESULT WINAPI ClassMoniker_BindToStorage(IMoniker* iface, 273 IBindCtx* pbc, 274 IMoniker* pmkToLeft, 275 REFIID riid, 276 VOID** ppvResult) 277 { 278 TRACE("(%p,%p,%p,%p)\n",pbc, pmkToLeft, riid, ppvResult); 279 return ClassMoniker_BindToObject(iface, pbc, pmkToLeft, riid, ppvResult); 280 } 281 282 /****************************************************************************** 283 * ClassMoniker_Reduce 284 ******************************************************************************/ 285 static HRESULT WINAPI ClassMoniker_Reduce(IMoniker* iface, 286 IBindCtx* pbc, 287 DWORD dwReduceHowFar, 288 IMoniker** ppmkToLeft, 289 IMoniker** ppmkReduced) 290 { 291 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced); 292 293 if (!ppmkReduced) 294 return E_POINTER; 295 296 ClassMoniker_AddRef(iface); 297 298 *ppmkReduced = iface; 299 300 return MK_S_REDUCED_TO_SELF; 301 } 302 /****************************************************************************** 303 * ClassMoniker_ComposeWith 304 ******************************************************************************/ 305 static HRESULT WINAPI ClassMoniker_ComposeWith(IMoniker* iface, 306 IMoniker* pmkRight, 307 BOOL fOnlyIfNotGeneric, 308 IMoniker** ppmkComposite) 309 { 310 HRESULT res=S_OK; 311 DWORD mkSys,mkSys2; 312 IEnumMoniker* penumMk=0; 313 IMoniker *pmostLeftMk=0; 314 IMoniker* tempMkComposite=0; 315 316 TRACE("(%p,%d,%p)\n", pmkRight, fOnlyIfNotGeneric, ppmkComposite); 317 318 if ((ppmkComposite==NULL)||(pmkRight==NULL)) 319 return E_POINTER; 320 321 *ppmkComposite=0; 322 323 IMoniker_IsSystemMoniker(pmkRight,&mkSys); 324 325 /* If pmkRight is an anti-moniker, the returned moniker is NULL */ 326 if(mkSys==MKSYS_ANTIMONIKER) 327 return res; 328 329 else 330 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */ 331 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */ 332 333 if(mkSys==MKSYS_GENERICCOMPOSITE){ 334 335 res=IMoniker_Enum(pmkRight,TRUE,&penumMk); 336 337 if (FAILED(res)) 338 return res; 339 340 res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL); 341 342 IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2); 343 344 if(mkSys2==MKSYS_ANTIMONIKER){ 345 346 IMoniker_Release(pmostLeftMk); 347 348 tempMkComposite=iface; 349 IMoniker_AddRef(iface); 350 351 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){ 352 353 res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite); 354 355 IMoniker_Release(tempMkComposite); 356 IMoniker_Release(pmostLeftMk); 357 358 tempMkComposite=*ppmkComposite; 359 IMoniker_AddRef(tempMkComposite); 360 } 361 return res; 362 } 363 else 364 return CreateGenericComposite(iface,pmkRight,ppmkComposite); 365 } 366 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic 367 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns 368 a NULL moniker and a return value of MK_E_NEEDGENERIC */ 369 else 370 if (!fOnlyIfNotGeneric) 371 return CreateGenericComposite(iface,pmkRight,ppmkComposite); 372 373 else 374 return MK_E_NEEDGENERIC; 375 } 376 377 /****************************************************************************** 378 * ClassMoniker_Enum 379 ******************************************************************************/ 380 static HRESULT WINAPI ClassMoniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker) 381 { 382 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker); 383 384 if (ppenumMoniker == NULL) 385 return E_POINTER; 386 387 *ppenumMoniker = NULL; 388 389 return S_OK; 390 } 391 392 /****************************************************************************** 393 * ClassMoniker_IsEqual 394 ******************************************************************************/ 395 static HRESULT WINAPI ClassMoniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) 396 { 397 398 CLSID clsid; 399 LPOLESTR dispName1,dispName2; 400 IBindCtx* bind; 401 HRESULT res = S_FALSE; 402 403 TRACE("(%p,%p)\n",iface,pmkOtherMoniker); 404 405 if (!pmkOtherMoniker) return S_FALSE; 406 407 408 /* check if both are ClassMoniker */ 409 if(FAILED (IMoniker_GetClassID(pmkOtherMoniker,&clsid))) return S_FALSE; 410 if(!IsEqualCLSID(&clsid,&CLSID_ClassMoniker)) return S_FALSE; 411 412 /* check if both displaynames are the same */ 413 if(SUCCEEDED ((res = CreateBindCtx(0,&bind)))) { 414 if(SUCCEEDED (IMoniker_GetDisplayName(iface,bind,NULL,&dispName1))) { 415 if(SUCCEEDED (IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2))) { 416 if(lstrcmpW(dispName1,dispName2)==0) res = S_OK; 417 CoTaskMemFree(dispName2); 418 } 419 CoTaskMemFree(dispName1); 420 } 421 } 422 return res; 423 } 424 425 /****************************************************************************** 426 * ClassMoniker_Hash 427 ******************************************************************************/ 428 static HRESULT WINAPI ClassMoniker_Hash(IMoniker* iface,DWORD* pdwHash) 429 { 430 ClassMoniker *This = (ClassMoniker *)iface; 431 432 TRACE("(%p)\n", pdwHash); 433 434 *pdwHash = This->clsid.Data1; 435 436 return S_OK; 437 } 438 439 /****************************************************************************** 440 * ClassMoniker_IsRunning 441 ******************************************************************************/ 442 static HRESULT WINAPI ClassMoniker_IsRunning(IMoniker* iface, 443 IBindCtx* pbc, 444 IMoniker* pmkToLeft, 445 IMoniker* pmkNewlyRunning) 446 { 447 TRACE("(%p, %p, %p)\n", pbc, pmkToLeft, pmkNewlyRunning); 448 449 /* as in native */ 450 return E_NOTIMPL; 451 } 452 453 /****************************************************************************** 454 * ClassMoniker_GetTimeOfLastChange 455 ******************************************************************************/ 456 static HRESULT WINAPI ClassMoniker_GetTimeOfLastChange(IMoniker* iface, 457 IBindCtx* pbc, 458 IMoniker* pmkToLeft, 459 FILETIME* pItemTime) 460 { 461 TRACE("(%p, %p, %p)\n", pbc, pmkToLeft, pItemTime); 462 463 return MK_E_UNAVAILABLE; 464 } 465 466 /****************************************************************************** 467 * ClassMoniker_Inverse 468 ******************************************************************************/ 469 static HRESULT WINAPI ClassMoniker_Inverse(IMoniker* iface,IMoniker** ppmk) 470 { 471 TRACE("(%p)\n",ppmk); 472 473 if (!ppmk) 474 return E_POINTER; 475 476 return CreateAntiMoniker(ppmk); 477 } 478 479 /****************************************************************************** 480 * ClassMoniker_CommonPrefixWith 481 ******************************************************************************/ 482 static HRESULT WINAPI ClassMoniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) 483 { 484 DWORD mkSys; 485 486 TRACE("(%p, %p)\n", pmkOther, ppmkPrefix); 487 488 *ppmkPrefix = NULL; 489 490 IMoniker_IsSystemMoniker(pmkOther, &mkSys); 491 492 /* If the other moniker is an class moniker that is equal to this moniker, this method sets *ppmkPrefix */ 493 /* to this moniker and returns MK_S_US */ 494 495 if (mkSys == MKSYS_CLASSMONIKER) 496 { 497 if (IMoniker_IsEqual(iface, pmkOther) == S_OK) 498 { 499 *ppmkPrefix = iface; 500 501 IMoniker_AddRef(iface); 502 503 return MK_S_US; 504 } 505 else 506 return MK_E_NOPREFIX; 507 } 508 else 509 /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */ 510 /* the case where the other moniker is a generic composite. */ 511 return MonikerCommonPrefixWith(iface, pmkOther, ppmkPrefix); 512 } 513 514 /****************************************************************************** 515 * ClassMoniker_RelativePathTo 516 ******************************************************************************/ 517 static HRESULT WINAPI ClassMoniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath) 518 { 519 TRACE("(%p, %p)\n",pmOther,ppmkRelPath); 520 521 if (!ppmkRelPath) 522 return E_POINTER; 523 524 *ppmkRelPath = NULL; 525 526 return MK_E_NOTBINDABLE; 527 } 528 529 /****************************************************************************** 530 * ClassMoniker_GetDisplayName 531 ******************************************************************************/ 532 static HRESULT WINAPI ClassMoniker_GetDisplayName(IMoniker* iface, 533 IBindCtx* pbc, 534 IMoniker* pmkToLeft, 535 LPOLESTR *ppszDisplayName) 536 { 537 ClassMoniker *This = (ClassMoniker *)iface; 538 static const WCHAR wszClsidPrefix[] = {'c','l','s','i','d',':',0}; 539 540 TRACE("(%p, %p, %p)\n", pbc, pmkToLeft, ppszDisplayName); 541 542 if (!ppszDisplayName) 543 return E_POINTER; 544 545 if (pmkToLeft) 546 return E_INVALIDARG; 547 548 *ppszDisplayName = CoTaskMemAlloc(sizeof(wszClsidPrefix) + (CHARS_IN_GUID-2) * sizeof(WCHAR)); 549 550 StringFromGUID2(&This->clsid, *ppszDisplayName+sizeof(wszClsidPrefix)/sizeof(WCHAR)-2, CHARS_IN_GUID); 551 552 /* note: this overwrites the opening curly bracket of the CLSID string generated above */ 553 memcpy(*ppszDisplayName, wszClsidPrefix, sizeof(wszClsidPrefix)-sizeof(WCHAR)); 554 555 /* note: this overwrites the closing curly bracket of the CLSID string generated above */ 556 (*ppszDisplayName)[sizeof(wszClsidPrefix)/sizeof(WCHAR)-2+CHARS_IN_GUID-2] = ':'; 557 (*ppszDisplayName)[sizeof(wszClsidPrefix)/sizeof(WCHAR)-2+CHARS_IN_GUID-1] = '\0'; 558 559 TRACE("string is %s\n", debugstr_w(*ppszDisplayName)); 560 return S_OK; 561 } 562 563 /****************************************************************************** 564 * ClassMoniker_ParseDisplayName 565 ******************************************************************************/ 566 static HRESULT WINAPI ClassMoniker_ParseDisplayName(IMoniker* iface, 567 IBindCtx* pbc, 568 IMoniker* pmkToLeft, 569 LPOLESTR pszDisplayName, 570 ULONG* pchEaten, 571 IMoniker** ppmkOut) 572 { 573 FIXME("(%p, %p, %s, %p, %p)\n", pbc, pmkToLeft, debugstr_w(pszDisplayName), pchEaten, ppmkOut); 574 return E_NOTIMPL; 575 } 576 577 /****************************************************************************** 578 * ClassMoniker_IsSystemMoniker 579 ******************************************************************************/ 580 static HRESULT WINAPI ClassMoniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) 581 { 582 TRACE("(%p,%p)\n",iface,pwdMksys); 583 584 if (!pwdMksys) 585 return E_POINTER; 586 587 *pwdMksys = MKSYS_CLASSMONIKER; 588 589 return S_OK; 590 } 591 592 /******************************************************************************* 593 * ClassMonikerIROTData_QueryInterface 594 *******************************************************************************/ 595 static HRESULT WINAPI ClassMonikerROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject) 596 { 597 598 IMoniker *This = impl_from_IROTData(iface); 599 600 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject); 601 602 return ClassMoniker_QueryInterface(This, riid, ppvObject); 603 } 604 605 /*********************************************************************** 606 * ClassMonikerIROTData_AddRef 607 */ 608 static ULONG WINAPI ClassMonikerROTData_AddRef(IROTData *iface) 609 { 610 IMoniker *This = impl_from_IROTData(iface); 611 612 TRACE("(%p)\n",iface); 613 614 return ClassMoniker_AddRef(This); 615 } 616 617 /*********************************************************************** 618 * ClassMonikerIROTData_Release 619 */ 620 static ULONG WINAPI ClassMonikerROTData_Release(IROTData* iface) 621 { 622 IMoniker *This = impl_from_IROTData(iface); 623 624 TRACE("(%p)\n",iface); 625 626 return ClassMoniker_Release(This); 627 } 628 629 /****************************************************************************** 630 * ClassMonikerIROTData_GetComparisonData 631 ******************************************************************************/ 632 static HRESULT WINAPI ClassMonikerROTData_GetComparisonData(IROTData* iface, 633 BYTE* pbData, 634 ULONG cbMax, 635 ULONG* pcbData) 636 { 637 ClassMoniker *This = (ClassMoniker *)impl_from_IROTData(iface); 638 639 TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData); 640 641 *pcbData = 2*sizeof(CLSID); 642 if (cbMax < *pcbData) 643 return E_OUTOFMEMORY; 644 645 /* write CLSID of the moniker */ 646 memcpy(pbData, &CLSID_ClassMoniker, sizeof(CLSID)); 647 /* write CLSID the moniker represents */ 648 memcpy(pbData+sizeof(CLSID), &This->clsid, sizeof(CLSID)); 649 650 return S_OK; 651 } 652 653 /********************************************************************************/ 654 /* Virtual function table for the ClassMoniker class which include IPersist,*/ 655 /* IPersistStream and IMoniker functions. */ 656 static const IMonikerVtbl ClassMonikerVtbl = 657 { 658 ClassMoniker_QueryInterface, 659 ClassMoniker_AddRef, 660 ClassMoniker_Release, 661 ClassMoniker_GetClassID, 662 ClassMoniker_IsDirty, 663 ClassMoniker_Load, 664 ClassMoniker_Save, 665 ClassMoniker_GetSizeMax, 666 ClassMoniker_BindToObject, 667 ClassMoniker_BindToStorage, 668 ClassMoniker_Reduce, 669 ClassMoniker_ComposeWith, 670 ClassMoniker_Enum, 671 ClassMoniker_IsEqual, 672 ClassMoniker_Hash, 673 ClassMoniker_IsRunning, 674 ClassMoniker_GetTimeOfLastChange, 675 ClassMoniker_Inverse, 676 ClassMoniker_CommonPrefixWith, 677 ClassMoniker_RelativePathTo, 678 ClassMoniker_GetDisplayName, 679 ClassMoniker_ParseDisplayName, 680 ClassMoniker_IsSystemMoniker 681 }; 682 683 /********************************************************************************/ 684 /* Virtual function table for the IROTData class. */ 685 static const IROTDataVtbl ROTDataVtbl = 686 { 687 ClassMonikerROTData_QueryInterface, 688 ClassMonikerROTData_AddRef, 689 ClassMonikerROTData_Release, 690 ClassMonikerROTData_GetComparisonData 691 }; 692 693 /****************************************************************************** 694 * ClassMoniker_Construct (local function) 695 *******************************************************************************/ 696 static HRESULT ClassMoniker_Construct(ClassMoniker* This, REFCLSID rclsid) 697 { 698 TRACE("(%p,%s)\n",This,debugstr_guid(rclsid)); 699 700 /* Initialize the virtual function table. */ 701 This->lpVtbl = &ClassMonikerVtbl; 702 This->lpVtblRotData = &ROTDataVtbl; 703 This->ref = 0; 704 This->clsid = *rclsid; 705 This->pMarshal = NULL; 706 707 return S_OK; 708 } 709 710 /****************************************************************************** 711 * CreateClassMoniker [OLE32.@] 712 ******************************************************************************/ 713 HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker **ppmk) 714 { 715 ClassMoniker* newClassMoniker; 716 HRESULT hr; 717 718 TRACE("(%s,%p)\n", debugstr_guid(rclsid), ppmk); 719 720 newClassMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ClassMoniker)); 721 722 if (!newClassMoniker) 723 return STG_E_INSUFFICIENTMEMORY; 724 725 hr = ClassMoniker_Construct(newClassMoniker, rclsid); 726 727 if (FAILED(hr)) 728 { 729 HeapFree(GetProcessHeap(), 0, newClassMoniker); 730 return hr; 731 } 732 733 return ClassMoniker_QueryInterface((IMoniker *)newClassMoniker, &IID_IMoniker, (void**)ppmk); 734 } 735 736 HRESULT ClassMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName, 737 LPDWORD pchEaten, LPMONIKER *ppmk) 738 { 739 HRESULT hr; 740 LPCWSTR s = strchrW(szDisplayName, ':'); 741 LPCWSTR end; 742 CLSID clsid; 743 BYTE table[256]; 744 int i; 745 746 if (!s) 747 return MK_E_SYNTAX; 748 749 s++; 750 751 for (end = s; *end && (*end != ':'); end++) 752 ; 753 754 TRACE("parsing %s\n", debugstr_wn(s, end - s)); 755 756 /* validate the CLSID string */ 757 if (s[0] == '{') 758 { 759 if ((end - s != 38) || (s[37] != '}')) 760 return MK_E_SYNTAX; 761 s++; 762 } 763 else 764 { 765 if (end - s != 36) 766 return MK_E_SYNTAX; 767 } 768 769 for (i=0; i<36; i++) 770 { 771 if ((i == 8)||(i == 13)||(i == 18)||(i == 23)) 772 { 773 if (s[i] != '-') 774 return MK_E_SYNTAX; 775 continue; 776 } 777 if (!(((s[i] >= '0') && (s[i] <= '9')) || 778 ((s[i] >= 'a') && (s[i] <= 'f')) || 779 ((s[i] >= 'A') && (s[i] <= 'F')))) 780 return MK_E_SYNTAX; 781 } 782 783 /* quick lookup table */ 784 memset(table, 0, 256); 785 786 for (i = 0; i < 10; i++) 787 table['0' + i] = i; 788 for (i = 0; i < 6; i++) 789 { 790 table['A' + i] = i+10; 791 table['a' + i] = i+10; 792 } 793 794 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */ 795 796 clsid.Data1 = (table[s[0]] << 28 | table[s[1]] << 24 | table[s[2]] << 20 | table[s[3]] << 16 | 797 table[s[4]] << 12 | table[s[5]] << 8 | table[s[6]] << 4 | table[s[7]]); 798 clsid.Data2 = table[s[9]] << 12 | table[s[10]] << 8 | table[s[11]] << 4 | table[s[12]]; 799 clsid.Data3 = table[s[14]] << 12 | table[s[15]] << 8 | table[s[16]] << 4 | table[s[17]]; 800 801 /* these are just sequential bytes */ 802 clsid.Data4[0] = table[s[19]] << 4 | table[s[20]]; 803 clsid.Data4[1] = table[s[21]] << 4 | table[s[22]]; 804 clsid.Data4[2] = table[s[24]] << 4 | table[s[25]]; 805 clsid.Data4[3] = table[s[26]] << 4 | table[s[27]]; 806 clsid.Data4[4] = table[s[28]] << 4 | table[s[29]]; 807 clsid.Data4[5] = table[s[30]] << 4 | table[s[31]]; 808 clsid.Data4[6] = table[s[32]] << 4 | table[s[33]]; 809 clsid.Data4[7] = table[s[34]] << 4 | table[s[35]]; 810 811 hr = CreateClassMoniker(&clsid, ppmk); 812 if (SUCCEEDED(hr)) 813 *pchEaten = (*end == ':' ? end + 1 : end) - szDisplayName; 814 return hr; 815 } 816 817 static HRESULT WINAPI ClassMonikerCF_QueryInterface(LPCLASSFACTORY iface, 818 REFIID riid, LPVOID *ppv) 819 { 820 *ppv = NULL; 821 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) 822 { 823 *ppv = iface; 824 IUnknown_AddRef(iface); 825 return S_OK; 826 } 827 return E_NOINTERFACE; 828 } 829 830 static ULONG WINAPI ClassMonikerCF_AddRef(LPCLASSFACTORY iface) 831 { 832 return 2; /* non-heap based object */ 833 } 834 835 static ULONG WINAPI ClassMonikerCF_Release(LPCLASSFACTORY iface) 836 { 837 return 1; /* non-heap based object */ 838 } 839 840 static HRESULT WINAPI ClassMonikerCF_CreateInstance(LPCLASSFACTORY iface, 841 LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv) 842 { 843 HRESULT hr; 844 IMoniker *pmk; 845 846 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv); 847 848 *ppv = NULL; 849 850 if (pUnk) 851 return CLASS_E_NOAGGREGATION; 852 853 hr = CreateClassMoniker(&CLSID_NULL, &pmk); 854 if (FAILED(hr)) return hr; 855 856 hr = IMoniker_QueryInterface(pmk, riid, ppv); 857 IMoniker_Release(pmk); 858 859 return hr; 860 } 861 862 static HRESULT WINAPI ClassMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) 863 { 864 FIXME("(%d), stub!\n",fLock); 865 return S_OK; 866 } 867 868 static const IClassFactoryVtbl ClassMonikerCFVtbl = 869 { 870 ClassMonikerCF_QueryInterface, 871 ClassMonikerCF_AddRef, 872 ClassMonikerCF_Release, 873 ClassMonikerCF_CreateInstance, 874 ClassMonikerCF_LockServer 875 }; 876 static const IClassFactoryVtbl *ClassMonikerCF = &ClassMonikerCFVtbl; 877 878 HRESULT ClassMonikerCF_Create(REFIID riid, LPVOID *ppv) 879 { 880 return IClassFactory_QueryInterface((IClassFactory *)&ClassMonikerCF, riid, ppv); 881 } 882