itemmoniker.c 34.4 KB
Newer Older
1
/*
2 3 4
 *	                      ItemMonikers implementation
 *
 *           Copyright 1999  Noomen Hamza
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
18 19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */
20 21

#include <assert.h>
22
#include <stdarg.h>
23
#include <string.h>
24

25
#define COBJMACROS
26 27
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
28

29
#include "winerror.h"
30
#include "windef.h"
31
#include "winbase.h"
32
#include "winuser.h"
33
#include "winnls.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

Noomen Hamza's avatar
Noomen Hamza committed
41
/* ItemMoniker data structure */
42
typedef struct ItemMonikerImpl{
43 44 45
    IMoniker IMoniker_iface;  /* VTable relative to the IMoniker interface.*/
    IROTData IROTData_iface;  /* VTable relative to the IROTData interface.*/
    LONG ref;
Noomen Hamza's avatar
Noomen Hamza committed
46 47
    LPOLESTR itemName; /* item name identified by this ItemMoniker */
    LPOLESTR itemDelimiter; /* Delimiter string */
48
    IUnknown *pMarshal; /* custom marshaler */
49 50
} ItemMonikerImpl;

51
static inline ItemMonikerImpl *impl_from_IMoniker(IMoniker *iface)
52
{
53 54 55 56 57 58
    return CONTAINING_RECORD(iface, ItemMonikerImpl, IMoniker_iface);
}

static inline ItemMonikerImpl *impl_from_IROTData(IROTData *iface)
{
    return CONTAINING_RECORD(iface, ItemMonikerImpl, IROTData_iface);
59 60
}

61
static HRESULT ItemMonikerImpl_Destroy(ItemMonikerImpl* iface);
Noomen Hamza's avatar
Noomen Hamza committed
62

63 64 65
/*******************************************************************************
 *        ItemMoniker_QueryInterface
 *******************************************************************************/
66
static HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
67
{
68
    ItemMonikerImpl *This = impl_from_IMoniker(iface);
69

70
    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
71

72 73
    if (!ppvObject)
        return E_INVALIDARG;
74

75 76 77 78 79 80
    /* Compare the riid with the interface IDs implemented by this object.*/
    if (IsEqualIID(&IID_IUnknown, riid) ||
        IsEqualIID(&IID_IPersist, riid) ||
        IsEqualIID(&IID_IPersistStream, riid) ||
        IsEqualIID(&IID_IMoniker, riid))
        *ppvObject = iface;
Noomen Hamza's avatar
Noomen Hamza committed
81
    else if (IsEqualIID(&IID_IROTData, riid))
82
        *ppvObject = &This->IROTData_iface;
83 84 85 86 87 88 89 90 91
    else if (IsEqualIID(&IID_IMarshal, riid))
    {
        HRESULT hr = S_OK;
        if (!This->pMarshal)
            hr = MonikerMarshal_Create(iface, &This->pMarshal);
        if (hr != S_OK)
            return hr;
        return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);
    }
92 93 94
    else
    {
        *ppvObject = NULL;
Noomen Hamza's avatar
Noomen Hamza committed
95
        return E_NOINTERFACE;
96
    }
97

98 99
    IMoniker_AddRef(iface);
    return S_OK;
100 101 102 103 104
}

/******************************************************************************
 *        ItemMoniker_AddRef
 ******************************************************************************/
105
static ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface)
106
{
107
    ItemMonikerImpl *This = impl_from_IMoniker(iface);
108

109
    TRACE("(%p)\n",This);
110

111
    return InterlockedIncrement(&This->ref);
112 113 114 115 116
}

/******************************************************************************
 *        ItemMoniker_Release
 ******************************************************************************/
117
static ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface)
118
{
119
    ItemMonikerImpl *This = impl_from_IMoniker(iface);
120
    ULONG ref;
121

122
    TRACE("(%p)\n",This);
123

124
    ref = InterlockedDecrement(&This->ref);
125

Noomen Hamza's avatar
Noomen Hamza committed
126
    /* destroy the object if there's no more reference on it */
127
    if (ref == 0) ItemMonikerImpl_Destroy(This);
Noomen Hamza's avatar
Noomen Hamza committed
128

129
    return ref;
130 131 132 133 134
}

/******************************************************************************
 *        ItemMoniker_GetClassID
 ******************************************************************************/
135
static HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
136
{
Robert Shearman's avatar
Robert Shearman committed
137
    TRACE("(%p,%p)\n",iface,pClassID);
Noomen Hamza's avatar
Noomen Hamza committed
138 139 140

    if (pClassID==NULL)
        return E_POINTER;
141

Noomen Hamza's avatar
Noomen Hamza committed
142
    *pClassID = CLSID_ItemMoniker;
143

Noomen Hamza's avatar
Noomen Hamza committed
144
    return S_OK;
145 146 147 148 149
}

/******************************************************************************
 *        ItemMoniker_IsDirty
 ******************************************************************************/
150
static HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface)
151
{
Noomen Hamza's avatar
Noomen Hamza committed
152 153 154
    /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
       method in the OLE-provided moniker interfaces always return S_FALSE because
       their internal state never changes. */
155

156
    TRACE("(%p)\n",iface);
Noomen Hamza's avatar
Noomen Hamza committed
157 158

    return S_FALSE;
159 160 161 162 163
}

/******************************************************************************
 *        ItemMoniker_Load
 ******************************************************************************/
164
static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface,IStream* pStm)
165
{
166
    ItemMonikerImpl *This = impl_from_IMoniker(iface);
Noomen Hamza's avatar
Noomen Hamza committed
167
    HRESULT res;
168
    DWORD delimiterLength,nameLength,lenW;
Noomen Hamza's avatar
Noomen Hamza committed
169 170 171
    CHAR *itemNameA,*itemDelimiterA;
    ULONG bread;

Robert Shearman's avatar
Robert Shearman committed
172 173
    TRACE("\n");

Austin English's avatar
Austin English committed
174
    /* for more details about data read by this function see comments of ItemMonikerImpl_Save function */
Noomen Hamza's avatar
Noomen Hamza committed
175 176 177 178 179 180 181

    /* read item delimiter string length + 1 */
    res=IStream_Read(pStm,&delimiterLength,sizeof(DWORD),&bread);
    if (bread != sizeof(DWORD))
        return E_FAIL;

    /* read item delimiter string */
182 183
    if (!(itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength)))
        return E_OUTOFMEMORY;
Noomen Hamza's avatar
Noomen Hamza committed
184 185
    res=IStream_Read(pStm,itemDelimiterA,delimiterLength,&bread);
    if (bread != delimiterLength)
186 187
    {
        HeapFree( GetProcessHeap(), 0, itemDelimiterA );
Noomen Hamza's avatar
Noomen Hamza committed
188
        return E_FAIL;
189
    }
Noomen Hamza's avatar
Noomen Hamza committed
190

191 192
    lenW = MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, NULL, 0 );
    This->itemDelimiter=HeapReAlloc(GetProcessHeap(),0,This->itemDelimiter,lenW*sizeof(WCHAR));
Noomen Hamza's avatar
Noomen Hamza committed
193
    if (!This->itemDelimiter)
194 195
    {
        HeapFree( GetProcessHeap(), 0, itemDelimiterA );
Noomen Hamza's avatar
Noomen Hamza committed
196
        return E_OUTOFMEMORY;
197 198 199
    }
    MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, This->itemDelimiter, lenW );
    HeapFree( GetProcessHeap(), 0, itemDelimiterA );
Noomen Hamza's avatar
Noomen Hamza committed
200 201 202 203 204 205 206

    /* read item name string length + 1*/
    res=IStream_Read(pStm,&nameLength,sizeof(DWORD),&bread);
    if (bread != sizeof(DWORD))
        return E_FAIL;

    /* read item name string */
207 208
    if (!(itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength)))
        return E_OUTOFMEMORY;
Noomen Hamza's avatar
Noomen Hamza committed
209 210
    res=IStream_Read(pStm,itemNameA,nameLength,&bread);
    if (bread != nameLength)
211 212
    {
        HeapFree( GetProcessHeap(), 0, itemNameA );
Noomen Hamza's avatar
Noomen Hamza committed
213
        return E_FAIL;
214
    }
Noomen Hamza's avatar
Noomen Hamza committed
215

216 217
    lenW = MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, NULL, 0 );
    This->itemName=HeapReAlloc(GetProcessHeap(),0,This->itemName,lenW*sizeof(WCHAR));
Noomen Hamza's avatar
Noomen Hamza committed
218
    if (!This->itemName)
219 220
    {
        HeapFree( GetProcessHeap(), 0, itemNameA );
Noomen Hamza's avatar
Noomen Hamza committed
221
        return E_OUTOFMEMORY;
222 223 224
    }
    MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, This->itemName, lenW );
    HeapFree( GetProcessHeap(), 0, itemNameA );
Noomen Hamza's avatar
Noomen Hamza committed
225 226

    return res;
227 228 229
}

/******************************************************************************
230
 *        ItemMoniker_Save
231
 ******************************************************************************/
232
static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
233
{
234
    ItemMonikerImpl *This = impl_from_IMoniker(iface);
Noomen Hamza's avatar
Noomen Hamza committed
235 236 237
    HRESULT res;
    CHAR *itemNameA,*itemDelimiterA;

Francois Gouget's avatar
Francois Gouget committed
238
    /* data written by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */
Noomen Hamza's avatar
Noomen Hamza committed
239 240 241 242
    /*                                    2) String (type A): item delimiter string ('\0' included)          */
    /*                                    3) DWORD : size of item name string ('\0' included)       */
    /*                                    4) String (type A): item name string ('\0' included)               */

243 244
    DWORD nameLength = WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, NULL, 0, NULL, NULL);
    DWORD delimiterLength = WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, NULL, 0, NULL, NULL);
Noomen Hamza's avatar
Noomen Hamza committed
245 246
    itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);
    itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);
247 248
    WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, itemNameA, nameLength, NULL, NULL);
    WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, itemDelimiterA, delimiterLength, NULL, NULL);
Noomen Hamza's avatar
Noomen Hamza committed
249

Robert Shearman's avatar
Robert Shearman committed
250 251
    TRACE("%p, %s\n", pStm, fClearDirty ? "TRUE" : "FALSE");

Noomen Hamza's avatar
Noomen Hamza committed
252 253 254 255 256
    res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL);
    res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL);
    res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL);
    res=IStream_Write(pStm,itemNameA,nameLength * sizeof(CHAR),NULL);

257 258 259
    HeapFree(GetProcessHeap(), 0, itemNameA);
    HeapFree(GetProcessHeap(), 0, itemDelimiterA);

Noomen Hamza's avatar
Noomen Hamza committed
260
    return res;
261 262 263 264 265
}

/******************************************************************************
 *        ItemMoniker_GetSizeMax
 ******************************************************************************/
266
static HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
267
{
268
    ItemMonikerImpl *This = impl_from_IMoniker(iface);
Noomen Hamza's avatar
Noomen Hamza committed
269 270
    DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1;
    DWORD nameLength=lstrlenW(This->itemName)+1;
271

272
    TRACE("(%p,%p)\n",iface,pcbSize);
Noomen Hamza's avatar
Noomen Hamza committed
273

274
    if (!pcbSize)
Noomen Hamza's avatar
Noomen Hamza committed
275 276
        return E_POINTER;

Austin English's avatar
Austin English committed
277
    /* for more details see ItemMonikerImpl_Save comments */
278

279
    pcbSize->u.LowPart =  sizeof(DWORD) + /* DWORD which contains delimiter length */
280
                        delimiterLength*4 + /* item delimiter string */
281
                        sizeof(DWORD) + /* DWORD which contains item name length */
282 283
                        nameLength*4 + /* item name string */
                        18; /* strange, but true */
284
    pcbSize->u.HighPart=0;
Noomen Hamza's avatar
Noomen Hamza committed
285 286

    return S_OK;
287 288 289 290 291
}

/******************************************************************************
 *                  ItemMoniker_BindToObject
 ******************************************************************************/
292 293 294 295 296
static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,
                                                   IBindCtx* pbc,
                                                   IMoniker* pmkToLeft,
                                                   REFIID riid,
                                                   VOID** ppvResult)
297
{
298
    ItemMonikerImpl *This = impl_from_IMoniker(iface);
Noomen Hamza's avatar
Noomen Hamza committed
299 300 301 302
    HRESULT   res;
    IID    refid=IID_IOleItemContainer;
    IOleItemContainer *poic=0;

Robert Shearman's avatar
Robert Shearman committed
303
    TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
Noomen Hamza's avatar
Noomen Hamza committed
304 305 306 307 308 309 310 311 312

    if(ppvResult ==NULL)
        return E_POINTER;

    if(pmkToLeft==NULL)
        return E_INVALIDARG;

    *ppvResult=0;

313
    res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&refid,(void**)&poic);
Noomen Hamza's avatar
Noomen Hamza committed
314 315 316 317 318 319 320 321 322

    if (SUCCEEDED(res)){

        res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,riid,ppvResult);

        IOleItemContainer_Release(poic);
    }

    return res;
323 324 325 326 327
}

/******************************************************************************
 *        ItemMoniker_BindToStorage
 ******************************************************************************/
328 329 330 331 332
static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,
                                                    IBindCtx* pbc,
                                                    IMoniker* pmkToLeft,
                                                    REFIID riid,
                                                    VOID** ppvResult)
333
{
334
    ItemMonikerImpl *This = impl_from_IMoniker(iface);
Noomen Hamza's avatar
Noomen Hamza committed
335 336 337
    HRESULT   res;
    IOleItemContainer *poic=0;

Robert Shearman's avatar
Robert Shearman committed
338
    TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
Noomen Hamza's avatar
Noomen Hamza committed
339 340 341 342 343

    *ppvResult=0;

    if(pmkToLeft==NULL)
        return E_INVALIDARG;
344

345
    res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
Noomen Hamza's avatar
Noomen Hamza committed
346 347 348 349 350 351 352 353 354

    if (SUCCEEDED(res)){

        res=IOleItemContainer_GetObjectStorage(poic,This->itemName,pbc,riid,ppvResult);

        IOleItemContainer_Release(poic);
    }

    return res;
355 356 357 358 359
}

/******************************************************************************
 *        ItemMoniker_Reduce
 ******************************************************************************/
360 361 362 363 364
static HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,
                                             IBindCtx* pbc,
                                             DWORD dwReduceHowFar,
                                             IMoniker** ppmkToLeft,
                                             IMoniker** ppmkReduced)
365
{
366
    TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
367

Noomen Hamza's avatar
Noomen Hamza committed
368 369 370 371
    if (ppmkReduced==NULL)
        return E_POINTER;

    ItemMonikerImpl_AddRef(iface);
372

Noomen Hamza's avatar
Noomen Hamza committed
373
    *ppmkReduced=iface;
374

Noomen Hamza's avatar
Noomen Hamza committed
375 376
    return MK_S_REDUCED_TO_SELF;
}
377 378 379
/******************************************************************************
 *        ItemMoniker_ComposeWith
 ******************************************************************************/
380 381 382 383
static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,
                                                  IMoniker* pmkRight,
                                                  BOOL fOnlyIfNotGeneric,
                                                  IMoniker** ppmkComposite)
384
{
Noomen Hamza's avatar
Noomen Hamza committed
385 386 387 388 389
    HRESULT res=S_OK;
    DWORD mkSys,mkSys2;
    IEnumMoniker* penumMk=0;
    IMoniker *pmostLeftMk=0;
    IMoniker* tempMkComposite=0;
390

391
    TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
Noomen Hamza's avatar
Noomen Hamza committed
392 393 394 395 396

    if ((ppmkComposite==NULL)||(pmkRight==NULL))
	return E_POINTER;

    *ppmkComposite=0;
397

Noomen Hamza's avatar
Noomen Hamza committed
398 399 400 401 402 403 404 405 406
    IMoniker_IsSystemMoniker(pmkRight,&mkSys);

    /* If pmkRight is an anti-moniker, the returned moniker is NULL */
    if(mkSys==MKSYS_ANTIMONIKER)
        return res;

    else
        /* if pmkRight is a composite whose leftmost component is an anti-moniker,           */
        /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
407

Noomen Hamza's avatar
Noomen Hamza committed
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
         if(mkSys==MKSYS_GENERICCOMPOSITE){

            res=IMoniker_Enum(pmkRight,TRUE,&penumMk);

            if (FAILED(res))
                return res;

            res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);

            IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);

            if(mkSys2==MKSYS_ANTIMONIKER){

                IMoniker_Release(pmostLeftMk);

                tempMkComposite=iface;
                IMoniker_AddRef(iface);
425

Noomen Hamza's avatar
Noomen Hamza committed
426 427 428 429 430 431 432 433 434
                while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){

                    res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);

                    IMoniker_Release(tempMkComposite);
                    IMoniker_Release(pmostLeftMk);

                    tempMkComposite=*ppmkComposite;
                    IMoniker_AddRef(tempMkComposite);
435
                }
Noomen Hamza's avatar
Noomen Hamza committed
436 437 438 439 440 441 442 443 444 445 446 447 448 449
                return res;
            }
            else
                return CreateGenericComposite(iface,pmkRight,ppmkComposite);
         }
         /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
          composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
          a NULL moniker and a return value of MK_E_NEEDGENERIC */
          else
            if (!fOnlyIfNotGeneric)
                return CreateGenericComposite(iface,pmkRight,ppmkComposite);

            else
                return MK_E_NEEDGENERIC;
450 451 452 453 454
}

/******************************************************************************
 *        ItemMoniker_Enum
 ******************************************************************************/
455
static HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
456
{
457
    TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
458

Noomen Hamza's avatar
Noomen Hamza committed
459 460 461 462
    if (ppenumMoniker == NULL)
        return E_POINTER;

    *ppenumMoniker = NULL;
463

Noomen Hamza's avatar
Noomen Hamza committed
464
    return S_OK;
465 466 467 468 469
}

/******************************************************************************
 *        ItemMoniker_IsEqual
 ******************************************************************************/
470
static HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
471
{
472

Noomen Hamza's avatar
Noomen Hamza committed
473 474 475
    CLSID clsid;
    LPOLESTR dispName1,dispName2;
    IBindCtx* bind;
476
    HRESULT res = S_FALSE;
Noomen Hamza's avatar
Noomen Hamza committed
477

478
    TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
Noomen Hamza's avatar
Noomen Hamza committed
479

480
    if (!pmkOtherMoniker) return S_FALSE;
Noomen Hamza's avatar
Noomen Hamza committed
481

482

483 484 485
    /* check if both are ItemMoniker */
    if(FAILED (IMoniker_GetClassID(pmkOtherMoniker,&clsid))) return S_FALSE;
    if(!IsEqualCLSID(&clsid,&CLSID_ItemMoniker)) return S_FALSE;
486

487 488 489 490 491 492 493 494 495 496 497
    /* check if both displaynames are the same */
    if(SUCCEEDED ((res = CreateBindCtx(0,&bind)))) {
        if(SUCCEEDED (IMoniker_GetDisplayName(iface,bind,NULL,&dispName1))) {
	    if(SUCCEEDED (IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2))) {
                if(lstrcmpW(dispName1,dispName2)==0) res = S_OK;
                CoTaskMemFree(dispName2);
            }
            CoTaskMemFree(dispName1);
	}
    }
    return res;
498 499 500 501 502
}

/******************************************************************************
 *        ItemMoniker_Hash
 ******************************************************************************/
503
static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
504
{
505
    ItemMonikerImpl *This = impl_from_IMoniker(iface);
506 507
    DWORD h = 0;
    int  i,len;
Noomen Hamza's avatar
Noomen Hamza committed
508 509 510 511 512
    int  off = 0;
    LPOLESTR val;

    if (pdwHash==NULL)
        return E_POINTER;
513

Noomen Hamza's avatar
Noomen Hamza committed
514 515 516
    val =  This->itemName;
    len = lstrlenW(val);

517 518
    for (i = len ; i > 0; i--)
        h = (h * 3) ^ toupperW(val[off++]);
Noomen Hamza's avatar
Noomen Hamza committed
519 520 521 522

    *pdwHash=h;

    return S_OK;
523 524 525 526 527
}

/******************************************************************************
 *        ItemMoniker_IsRunning
 ******************************************************************************/
528 529 530 531
static HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,
                                                IBindCtx* pbc,
                                                IMoniker* pmkToLeft,
                                                IMoniker* pmkNewlyRunning)
532
{
533
    ItemMonikerImpl *This = impl_from_IMoniker(iface);
Noomen Hamza's avatar
Noomen Hamza committed
534 535 536
    IRunningObjectTable* rot;
    HRESULT res;
    IOleItemContainer *poic=0;
537

538
    TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
Noomen Hamza's avatar
Noomen Hamza committed
539 540 541 542 543 544 545 546

    /* If pmkToLeft is NULL, this method returns TRUE if pmkNewlyRunning is non-NULL and is equal to this */
    /* moniker. Otherwise, the method checks the ROT to see whether this moniker is running.              */
    if (pmkToLeft==NULL)
        if ((pmkNewlyRunning!=NULL)&&(IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK))
            return S_OK;
        else {
            if (pbc==NULL)
547
                return E_INVALIDARG;
Noomen Hamza's avatar
Noomen Hamza committed
548 549 550 551 552 553 554 555 556 557 558 559 560 561 562

            res=IBindCtx_GetRunningObjectTable(pbc,&rot);

            if (FAILED(res))
                return res;

            res = IRunningObjectTable_IsRunning(rot,iface);

            IRunningObjectTable_Release(rot);
        }
    else{

        /* If pmkToLeft is non-NULL, the method calls IMoniker::BindToObject on the pmkToLeft parameter,         */
        /* requesting an IOleItemContainer interface pointer. The method then calls IOleItemContainer::IsRunning,*/
        /* passing the string contained within this moniker. */
563

564
        res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
Noomen Hamza's avatar
Noomen Hamza committed
565 566 567 568 569 570 571 572 573 574

        if (SUCCEEDED(res)){

            res=IOleItemContainer_IsRunning(poic,This->itemName);

            IOleItemContainer_Release(poic);
        }
    }

    return res;
575 576 577 578 579
}

/******************************************************************************
 *        ItemMoniker_GetTimeOfLastChange
 ******************************************************************************/
580 581 582 583
static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
                                                          IBindCtx* pbc,
                                                          IMoniker* pmkToLeft,
                                                          FILETIME* pItemTime)
584
{
Noomen Hamza's avatar
Noomen Hamza committed
585 586 587
    IRunningObjectTable* rot;
    HRESULT res;
    IMoniker *compositeMk;
588

589
    TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime);
Noomen Hamza's avatar
Noomen Hamza committed
590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612

    if (pItemTime==NULL)
        return E_INVALIDARG;

    /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
    if (pmkToLeft==NULL)

        return MK_E_NOTBINDABLE;
    else {

        /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access  */
        /* the time of last change. If the object is not in the ROT, the method calls                          */
        /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter.                                            */

        res=CreateGenericComposite(pmkToLeft,iface,&compositeMk);

        res=IBindCtx_GetRunningObjectTable(pbc,&rot);

        if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK)

            res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime);

        IMoniker_Release(compositeMk);
613
    }
Noomen Hamza's avatar
Noomen Hamza committed
614 615

    return res;
616 617 618 619 620
}

/******************************************************************************
 *        ItemMoniker_Inverse
 ******************************************************************************/
621
static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
622
{
623
    TRACE("(%p,%p)\n",iface,ppmk);
624

Noomen Hamza's avatar
Noomen Hamza committed
625 626 627 628
    if (ppmk==NULL)
        return E_POINTER;

    return CreateAntiMoniker(ppmk);
629 630 631 632 633
}

/******************************************************************************
 *        ItemMoniker_CommonPrefixWith
 ******************************************************************************/
634
static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
635
{
Noomen Hamza's avatar
Noomen Hamza committed
636
    DWORD mkSys;
Robert Shearman's avatar
Robert Shearman committed
637 638 639
    
    TRACE("(%p,%p)\n", pmkOther, ppmkPrefix);

Noomen Hamza's avatar
Noomen Hamza committed
640 641 642 643 644 645 646
    IMoniker_IsSystemMoniker(pmkOther,&mkSys);
    /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */
    /* to this moniker and returns MK_S_US */

    if((mkSys==MKSYS_ITEMMONIKER) && (IMoniker_IsEqual(iface,pmkOther)==S_OK) ){

        *ppmkPrefix=iface;
647

Noomen Hamza's avatar
Noomen Hamza committed
648
        IMoniker_AddRef(iface);
649

Noomen Hamza's avatar
Noomen Hamza committed
650 651 652 653 654 655
        return MK_S_US;
    }
    else
        /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */
        /* the case where the other moniker is a generic composite. */
        return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
656 657 658 659 660
}

/******************************************************************************
 *        ItemMoniker_RelativePathTo
 ******************************************************************************/
661
static HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
662
{
663
    TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
664

Noomen Hamza's avatar
Noomen Hamza committed
665 666 667 668
    if (ppmkRelPath==NULL)
        return E_POINTER;

    *ppmkRelPath=0;
669

Noomen Hamza's avatar
Noomen Hamza committed
670
    return MK_E_NOTBINDABLE;
671 672 673 674 675
}

/******************************************************************************
 *        ItemMoniker_GetDisplayName
 ******************************************************************************/
676 677 678 679
static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,
                                                     IBindCtx* pbc,
                                                     IMoniker* pmkToLeft,
                                                     LPOLESTR *ppszDisplayName)
680
{
681
    ItemMonikerImpl *This = impl_from_IMoniker(iface);
682

683
    TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
Noomen Hamza's avatar
Noomen Hamza committed
684 685 686 687 688 689 690 691 692 693 694 695 696

    if (ppszDisplayName==NULL)
        return E_POINTER;

    if (pmkToLeft!=NULL){
        return E_INVALIDARG;
    }

    *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(lstrlenW(This->itemDelimiter)+lstrlenW(This->itemName)+1));

    if (*ppszDisplayName==NULL)
        return E_OUTOFMEMORY;

697 698
    lstrcpyW(*ppszDisplayName,This->itemDelimiter);
    lstrcatW(*ppszDisplayName,This->itemName);
699

Robert Shearman's avatar
Robert Shearman committed
700 701
    TRACE("-- %s\n", debugstr_w(*ppszDisplayName));

Noomen Hamza's avatar
Noomen Hamza committed
702
    return S_OK;
703 704 705 706 707
}

/******************************************************************************
 *        ItemMoniker_ParseDisplayName
 ******************************************************************************/
708 709 710 711 712 713
static HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,
                                                       IBindCtx* pbc,
                                                       IMoniker* pmkToLeft,
                                                       LPOLESTR pszDisplayName,
                                                       ULONG* pchEaten,
                                                       IMoniker** ppmkOut)
714
{
715
    ItemMonikerImpl *This = impl_from_IMoniker(iface);
Noomen Hamza's avatar
Noomen Hamza committed
716 717 718 719
    IOleItemContainer* poic=0;
    IParseDisplayName* ppdn=0;
    LPOLESTR displayName;
    HRESULT res;
720

Robert Shearman's avatar
Robert Shearman committed
721 722
    TRACE("%s\n", debugstr_w(pszDisplayName));

Noomen Hamza's avatar
Noomen Hamza committed
723 724 725 726 727 728 729
    /* If pmkToLeft is NULL, this method returns MK_E_SYNTAX */
    if (pmkToLeft==NULL)

        return MK_E_SYNTAX;

    else{
        /* Otherwise, the method calls IMoniker::BindToObject on the pmkToLeft parameter, requesting an */
730 731
        /* IParseDisplayName interface pointer to the object identified by the moniker, and passes the display */
        /* name to IParseDisplayName::ParseDisplayName */
732
        res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
Noomen Hamza's avatar
Noomen Hamza committed
733 734 735

        if (SUCCEEDED(res)){

736
            res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,&IID_IParseDisplayName,(void**)&ppdn);
Noomen Hamza's avatar
Noomen Hamza committed
737 738 739 740 741 742 743 744

            res=IMoniker_GetDisplayName(iface,pbc,NULL,&displayName);

            res=IParseDisplayName_ParseDisplayName(ppdn,pbc,displayName,pchEaten,ppmkOut);

            IOleItemContainer_Release(poic);
            IParseDisplayName_Release(ppdn);
        }
745
    }
Noomen Hamza's avatar
Noomen Hamza committed
746
    return res;
747 748 749
}

/******************************************************************************
Andreas Mohr's avatar
Andreas Mohr committed
750
 *        ItemMoniker_IsSystemMoniker
751
 ******************************************************************************/
752
static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
753
{
754
    TRACE("(%p,%p)\n",iface,pwdMksys);
Noomen Hamza's avatar
Noomen Hamza committed
755 756 757

    if (!pwdMksys)
        return E_POINTER;
758

Noomen Hamza's avatar
Noomen Hamza committed
759 760 761 762
    (*pwdMksys)=MKSYS_ITEMMONIKER;

    return S_OK;
}
763

Noomen Hamza's avatar
Noomen Hamza committed
764 765 766
/*******************************************************************************
 *        ItemMonikerIROTData_QueryInterface
 *******************************************************************************/
767 768
static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,
                                                            void **ppvObject)
Noomen Hamza's avatar
Noomen Hamza committed
769 770
{

771
    ItemMonikerImpl *This = impl_from_IROTData(iface);
Noomen Hamza's avatar
Noomen Hamza committed
772

773
    TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
Noomen Hamza's avatar
Noomen Hamza committed
774

775
    return ItemMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject);
Noomen Hamza's avatar
Noomen Hamza committed
776 777 778 779 780
}

/***********************************************************************
 *        ItemMonikerIROTData_AddRef
 */
781
static ULONG   WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface)
Noomen Hamza's avatar
Noomen Hamza committed
782
{
783
    ItemMonikerImpl *This = impl_from_IROTData(iface);
Noomen Hamza's avatar
Noomen Hamza committed
784

785
    TRACE("(%p)\n",iface);
Noomen Hamza's avatar
Noomen Hamza committed
786

787
    return ItemMonikerImpl_AddRef(&This->IMoniker_iface);
Noomen Hamza's avatar
Noomen Hamza committed
788 789 790 791 792
}

/***********************************************************************
 *        ItemMonikerIROTData_Release
 */
793
static ULONG   WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface)
Noomen Hamza's avatar
Noomen Hamza committed
794
{
795
    ItemMonikerImpl *This = impl_from_IROTData(iface);
796

797
    TRACE("(%p)\n",iface);
Noomen Hamza's avatar
Noomen Hamza committed
798

799
    return ItemMonikerImpl_Release(&This->IMoniker_iface);
Noomen Hamza's avatar
Noomen Hamza committed
800 801 802
}

/******************************************************************************
803
 *        ItemMonikerIROTData_GetComparisonData
Noomen Hamza's avatar
Noomen Hamza committed
804
 ******************************************************************************/
805 806 807 808
static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData* iface,
                                                               BYTE* pbData,
                                                               ULONG cbMax,
                                                               ULONG* pcbData)
Noomen Hamza's avatar
Noomen Hamza committed
809
{
810 811
    ItemMonikerImpl *This = impl_from_IROTData(iface);
    int len = (strlenW(This->itemName)+1);
812 813 814 815
    int i;
    LPWSTR pszItemName;
    LPWSTR pszItemDelimiter;

816
    TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData);
817 818 819 820 821 822 823 824 825

    *pcbData = sizeof(CLSID) + sizeof(WCHAR) + len * sizeof(WCHAR);
    if (cbMax < *pcbData)
        return E_OUTOFMEMORY;

    /* write CLSID */
    memcpy(pbData, &CLSID_ItemMoniker, sizeof(CLSID));
    /* write delimiter */
    pszItemDelimiter = (LPWSTR)(pbData+sizeof(CLSID));
826
    *pszItemDelimiter = *This->itemDelimiter;
827 828 829
    /* write name */
    pszItemName = pszItemDelimiter + 1;
    for (i = 0; i < len; i++)
830
        pszItemName[i] = toupperW(This->itemName[i]);
831 832

    return S_OK;
833 834
}

835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887
/********************************************************************************/
/* Virtual function table for the ItemMonikerImpl class which  include IPersist,*/
/* IPersistStream and IMoniker functions.                                       */
static const IMonikerVtbl VT_ItemMonikerImpl =
    {
    ItemMonikerImpl_QueryInterface,
    ItemMonikerImpl_AddRef,
    ItemMonikerImpl_Release,
    ItemMonikerImpl_GetClassID,
    ItemMonikerImpl_IsDirty,
    ItemMonikerImpl_Load,
    ItemMonikerImpl_Save,
    ItemMonikerImpl_GetSizeMax,
    ItemMonikerImpl_BindToObject,
    ItemMonikerImpl_BindToStorage,
    ItemMonikerImpl_Reduce,
    ItemMonikerImpl_ComposeWith,
    ItemMonikerImpl_Enum,
    ItemMonikerImpl_IsEqual,
    ItemMonikerImpl_Hash,
    ItemMonikerImpl_IsRunning,
    ItemMonikerImpl_GetTimeOfLastChange,
    ItemMonikerImpl_Inverse,
    ItemMonikerImpl_CommonPrefixWith,
    ItemMonikerImpl_RelativePathTo,
    ItemMonikerImpl_GetDisplayName,
    ItemMonikerImpl_ParseDisplayName,
    ItemMonikerImpl_IsSystemMoniker
};

/********************************************************************************/
/* Virtual function table for the IROTData class.                               */
static const IROTDataVtbl VT_ROTDataImpl =
{
    ItemMonikerROTDataImpl_QueryInterface,
    ItemMonikerROTDataImpl_AddRef,
    ItemMonikerROTDataImpl_Release,
    ItemMonikerROTDataImpl_GetComparisonData
};

/******************************************************************************
 *         ItemMoniker_Construct (local function)
 *******************************************************************************/
static HRESULT ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDelim,LPCOLESTR lpszItem)
{

    int sizeStr1=lstrlenW(lpszItem), sizeStr2;
    static const OLECHAR emptystr[1];
    LPCOLESTR	delim;

    TRACE("(%p,%s,%s)\n",This,debugstr_w(lpszDelim),debugstr_w(lpszItem));

    /* Initialize the virtual function table. */
888 889
    This->IMoniker_iface.lpVtbl = &VT_ItemMonikerImpl;
    This->IROTData_iface.lpVtbl = &VT_ROTDataImpl;
890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927
    This->ref          = 0;
    This->pMarshal     = NULL;

    This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1));
    if (!This->itemName)
	return E_OUTOFMEMORY;
    lstrcpyW(This->itemName,lpszItem);

    if (!lpszDelim)
	FIXME("lpszDelim is NULL. Using empty string which is possibly wrong.\n");

    delim = lpszDelim ? lpszDelim : emptystr;

    sizeStr2=lstrlenW(delim);
    This->itemDelimiter=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr2+1));
    if (!This->itemDelimiter) {
	HeapFree(GetProcessHeap(),0,This->itemName);
	return E_OUTOFMEMORY;
    }
    lstrcpyW(This->itemDelimiter,delim);
    return S_OK;
}

/******************************************************************************
 *        ItemMoniker_Destroy (local function)
 *******************************************************************************/
static HRESULT ItemMonikerImpl_Destroy(ItemMonikerImpl* This)
{
    TRACE("(%p)\n",This);

    if (This->pMarshal) IUnknown_Release(This->pMarshal);
    HeapFree(GetProcessHeap(),0,This->itemName);
    HeapFree(GetProcessHeap(),0,This->itemDelimiter);
    HeapFree(GetProcessHeap(),0,This);

    return S_OK;
}

928
/******************************************************************************
929
 *        CreateItemMoniker	[OLE32.@]
930
 ******************************************************************************/
931
HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim, LPCOLESTR  lpszItem, IMoniker **ppmk)
932
{
Robert Shearman's avatar
Robert Shearman committed
933 934
    ItemMonikerImpl* newItemMoniker;
    HRESULT        hr;
935

Robert Shearman's avatar
Robert Shearman committed
936
    TRACE("(%s,%s,%p)\n",debugstr_w(lpszDelim),debugstr_w(lpszItem),ppmk);
937 938 939

    newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));

Robert Shearman's avatar
Robert Shearman committed
940
    if (!newItemMoniker)
941 942 943 944
        return STG_E_INSUFFICIENTMEMORY;

    hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem);

Noomen Hamza's avatar
Noomen Hamza committed
945
    if (FAILED(hr)){
946

Noomen Hamza's avatar
Noomen Hamza committed
947
        HeapFree(GetProcessHeap(),0,newItemMoniker);
948
    return hr;
Noomen Hamza's avatar
Noomen Hamza committed
949 950
    }

951 952
    return ItemMonikerImpl_QueryInterface(&newItemMoniker->IMoniker_iface,&IID_IMoniker,
                                          (void**)ppmk);
953
}
954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998

static HRESULT WINAPI ItemMonikerCF_QueryInterface(LPCLASSFACTORY iface,
                                                  REFIID riid, LPVOID *ppv)
{
    *ppv = NULL;
    if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
    {
        *ppv = iface;
        IUnknown_AddRef(iface);
        return S_OK;
    }
    return E_NOINTERFACE;
}

static ULONG WINAPI ItemMonikerCF_AddRef(LPCLASSFACTORY iface)
{
    return 2; /* non-heap based object */
}

static ULONG WINAPI ItemMonikerCF_Release(LPCLASSFACTORY iface)
{
    return 1; /* non-heap based object */
}

static HRESULT WINAPI ItemMonikerCF_CreateInstance(LPCLASSFACTORY iface,
    LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
{
    ItemMonikerImpl* newItemMoniker;
    HRESULT  hr;
    static const WCHAR wszEmpty[] = { 0 };

    TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);

    *ppv = NULL;

    if (pUnk)
        return CLASS_E_NOAGGREGATION;

    newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));
    if (!newItemMoniker)
        return E_OUTOFMEMORY;

    hr = ItemMonikerImpl_Construct(newItemMoniker, wszEmpty, wszEmpty);

    if (SUCCEEDED(hr))
999
        hr = ItemMonikerImpl_QueryInterface(&newItemMoniker->IMoniker_iface, riid, ppv);
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
    if (FAILED(hr))
        HeapFree(GetProcessHeap(),0,newItemMoniker);

    return hr;
}

static HRESULT WINAPI ItemMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
{
    FIXME("(%d), stub!\n",fLock);
    return S_OK;
}

static const IClassFactoryVtbl ItemMonikerCFVtbl =
{
    ItemMonikerCF_QueryInterface,
    ItemMonikerCF_AddRef,
    ItemMonikerCF_Release,
    ItemMonikerCF_CreateInstance,
    ItemMonikerCF_LockServer
};
static const IClassFactoryVtbl *ItemMonikerCF = &ItemMonikerCFVtbl;

HRESULT ItemMonikerCF_Create(REFIID riid, LPVOID *ppv)
{
    return IClassFactory_QueryInterface((IClassFactory *)&ItemMonikerCF, riid, ppv);
}