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