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