itemmoniker.c 34.5 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
#define NONAMELESSUNION
27

28
#include "winerror.h"
29
#include "windef.h"
30
#include "winbase.h"
31
#include "winuser.h"
32
#include "winnls.h"
33
#include "wine/debug.h"
34
#include "ole2.h"
35
#include "wine/unicode.h"
36
#include "moniker.h"
37

38
WINE_DEFAULT_DEBUG_CHANNEL(ole);
39

Noomen Hamza's avatar
Noomen Hamza committed
40
/* ItemMoniker data structure */
41
typedef struct ItemMonikerImpl{
42 43 44
    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
45 46
    LPOLESTR itemName; /* item name identified by this ItemMoniker */
    LPOLESTR itemDelimiter; /* Delimiter string */
47
    IUnknown *pMarshal; /* custom marshaler */
48 49
} ItemMonikerImpl;

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

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

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

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

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

71 72
    if (!ppvObject)
        return E_INVALIDARG;
73

74 75 76 77 78 79
    /* 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
80
    else if (IsEqualIID(&IID_IROTData, riid))
81
        *ppvObject = &This->IROTData_iface;
82 83 84 85 86 87 88 89 90
    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);
    }
91 92 93
    else
    {
        *ppvObject = NULL;
Noomen Hamza's avatar
Noomen Hamza committed
94
        return E_NOINTERFACE;
95
    }
96

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

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

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

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

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

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

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

125
    /* destroy the object if there are no more references to it */
126
    if (ref == 0) ItemMonikerImpl_Destroy(This);
Noomen Hamza's avatar
Noomen Hamza committed
127

128
    return ref;
129 130 131 132 133
}

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

    if (pClassID==NULL)
        return E_POINTER;
140

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

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

/******************************************************************************
 *        ItemMoniker_IsDirty
 ******************************************************************************/
149
static HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface)
150
{
Noomen Hamza's avatar
Noomen Hamza committed
151 152 153
    /* 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. */
154

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

    return S_FALSE;
158 159 160 161 162
}

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

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

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

    /* 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 */
181 182
    if (!(itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength)))
        return E_OUTOFMEMORY;
Noomen Hamza's avatar
Noomen Hamza committed
183 184
    res=IStream_Read(pStm,itemDelimiterA,delimiterLength,&bread);
    if (bread != delimiterLength)
185 186
    {
        HeapFree( GetProcessHeap(), 0, itemDelimiterA );
Noomen Hamza's avatar
Noomen Hamza committed
187
        return E_FAIL;
188
    }
Noomen Hamza's avatar
Noomen Hamza committed
189

190 191
    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
192
    if (!This->itemDelimiter)
193 194
    {
        HeapFree( GetProcessHeap(), 0, itemDelimiterA );
Noomen Hamza's avatar
Noomen Hamza committed
195
        return E_OUTOFMEMORY;
196 197 198
    }
    MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, This->itemDelimiter, lenW );
    HeapFree( GetProcessHeap(), 0, itemDelimiterA );
Noomen Hamza's avatar
Noomen Hamza committed
199 200 201 202 203 204 205

    /* 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 */
206 207
    if (!(itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength)))
        return E_OUTOFMEMORY;
Noomen Hamza's avatar
Noomen Hamza committed
208 209
    res=IStream_Read(pStm,itemNameA,nameLength,&bread);
    if (bread != nameLength)
210 211
    {
        HeapFree( GetProcessHeap(), 0, itemNameA );
Noomen Hamza's avatar
Noomen Hamza committed
212
        return E_FAIL;
213
    }
Noomen Hamza's avatar
Noomen Hamza committed
214

215 216
    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
217
    if (!This->itemName)
218 219
    {
        HeapFree( GetProcessHeap(), 0, itemNameA );
Noomen Hamza's avatar
Noomen Hamza committed
220
        return E_OUTOFMEMORY;
221 222 223
    }
    MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, This->itemName, lenW );
    HeapFree( GetProcessHeap(), 0, itemNameA );
Noomen Hamza's avatar
Noomen Hamza committed
224 225

    return res;
226 227 228
}

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

Francois Gouget's avatar
Francois Gouget committed
237
    /* data written by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */
Noomen Hamza's avatar
Noomen Hamza committed
238 239 240 241
    /*                                    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)               */

242 243
    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
244 245
    itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);
    itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);
246 247
    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
248

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

Noomen Hamza's avatar
Noomen Hamza committed
251 252 253 254 255
    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);

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

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

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

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

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

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

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

    return S_OK;
286 287 288 289 290
}

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

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

    if(ppvResult ==NULL)
        return E_POINTER;

    if(pmkToLeft==NULL)
        return E_INVALIDARG;

    *ppvResult=0;

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

    if (SUCCEEDED(res)){

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

        IOleItemContainer_Release(poic);
    }

    return res;
322 323 324 325 326
}

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

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

    *ppvResult=0;

    if(pmkToLeft==NULL)
        return E_INVALIDARG;
343

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

    if (SUCCEEDED(res)){

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

        IOleItemContainer_Release(poic);
    }

    return res;
354 355 356 357 358
}

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

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

    ItemMonikerImpl_AddRef(iface);
371

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

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

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

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

    *ppmkComposite=0;
396

Noomen Hamza's avatar
Noomen Hamza committed
397 398 399 400 401 402 403 404 405
    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. */
406

Noomen Hamza's avatar
Noomen Hamza committed
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
         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);
424

Noomen Hamza's avatar
Noomen Hamza committed
425 426 427 428 429 430 431 432 433
                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);
434
                }
Noomen Hamza's avatar
Noomen Hamza committed
435 436 437 438 439 440 441 442 443 444 445 446 447 448
                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;
449 450 451 452 453
}

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

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

    *ppenumMoniker = NULL;
462

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

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

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

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

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

481

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

486 487 488 489 490 491 492 493 494 495 496
    /* 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;
497 498 499 500 501
}

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

    if (pdwHash==NULL)
        return E_POINTER;
512

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

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

    *pdwHash=h;

    return S_OK;
522 523 524 525 526
}

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

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

    /* 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)
546
                return E_INVALIDARG;
Noomen Hamza's avatar
Noomen Hamza committed
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561

            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. */
562

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

        if (SUCCEEDED(res)){

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

            IOleItemContainer_Release(poic);
        }
    }

    return res;
574 575 576 577 578
}

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

588
    TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime);
Noomen Hamza's avatar
Noomen Hamza committed
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603

    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);
604 605
        if (FAILED(res))
            return res;
Noomen Hamza's avatar
Noomen Hamza committed
606 607

        res=IBindCtx_GetRunningObjectTable(pbc,&rot);
608 609 610 611
        if (FAILED(res)) {
            IMoniker_Release(compositeMk);
            return res;
        }
Noomen Hamza's avatar
Noomen Hamza committed
612 613 614 615 616 617

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

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

        IMoniker_Release(compositeMk);
618
    }
Noomen Hamza's avatar
Noomen Hamza committed
619 620

    return res;
621 622 623 624 625
}

/******************************************************************************
 *        ItemMoniker_Inverse
 ******************************************************************************/
626
static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
627
{
628
    TRACE("(%p,%p)\n",iface,ppmk);
629

Noomen Hamza's avatar
Noomen Hamza committed
630 631 632 633
    if (ppmk==NULL)
        return E_POINTER;

    return CreateAntiMoniker(ppmk);
634 635 636 637 638
}

/******************************************************************************
 *        ItemMoniker_CommonPrefixWith
 ******************************************************************************/
639
static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
640
{
Noomen Hamza's avatar
Noomen Hamza committed
641
    DWORD mkSys;
Robert Shearman's avatar
Robert Shearman committed
642 643 644
    
    TRACE("(%p,%p)\n", pmkOther, ppmkPrefix);

Noomen Hamza's avatar
Noomen Hamza committed
645 646 647 648 649 650 651
    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;
652

Noomen Hamza's avatar
Noomen Hamza committed
653
        IMoniker_AddRef(iface);
654

Noomen Hamza's avatar
Noomen Hamza committed
655 656 657 658 659 660
        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);
661 662 663 664 665
}

/******************************************************************************
 *        ItemMoniker_RelativePathTo
 ******************************************************************************/
666
static HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
667
{
668
    TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
669

Noomen Hamza's avatar
Noomen Hamza committed
670 671 672 673
    if (ppmkRelPath==NULL)
        return E_POINTER;

    *ppmkRelPath=0;
674

Noomen Hamza's avatar
Noomen Hamza committed
675
    return MK_E_NOTBINDABLE;
676 677 678 679 680
}

/******************************************************************************
 *        ItemMoniker_GetDisplayName
 ******************************************************************************/
681 682 683 684
static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,
                                                     IBindCtx* pbc,
                                                     IMoniker* pmkToLeft,
                                                     LPOLESTR *ppszDisplayName)
685
{
686
    ItemMonikerImpl *This = impl_from_IMoniker(iface);
687

688
    TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
Noomen Hamza's avatar
Noomen Hamza committed
689 690 691 692 693 694 695 696 697 698 699 700 701

    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;

702 703
    lstrcpyW(*ppszDisplayName,This->itemDelimiter);
    lstrcatW(*ppszDisplayName,This->itemName);
704

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

Noomen Hamza's avatar
Noomen Hamza committed
707
    return S_OK;
708 709 710 711 712
}

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

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

Noomen Hamza's avatar
Noomen Hamza committed
728 729 730 731 732 733 734
    /* 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 */
735 736
        /* IParseDisplayName interface pointer to the object identified by the moniker, and passes the display */
        /* name to IParseDisplayName::ParseDisplayName */
737
        res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
Noomen Hamza's avatar
Noomen Hamza committed
738 739 740

        if (SUCCEEDED(res)){

741
            res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,&IID_IParseDisplayName,(void**)&ppdn);
Noomen Hamza's avatar
Noomen Hamza committed
742 743 744 745 746 747 748 749

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

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

            IOleItemContainer_Release(poic);
            IParseDisplayName_Release(ppdn);
        }
750
    }
Noomen Hamza's avatar
Noomen Hamza committed
751
    return res;
752 753 754
}

/******************************************************************************
Andreas Mohr's avatar
Andreas Mohr committed
755
 *        ItemMoniker_IsSystemMoniker
756
 ******************************************************************************/
757
static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
758
{
759
    TRACE("(%p,%p)\n",iface,pwdMksys);
Noomen Hamza's avatar
Noomen Hamza committed
760 761 762

    if (!pwdMksys)
        return E_POINTER;
763

Noomen Hamza's avatar
Noomen Hamza committed
764 765 766 767
    (*pwdMksys)=MKSYS_ITEMMONIKER;

    return S_OK;
}
768

Noomen Hamza's avatar
Noomen Hamza committed
769 770 771
/*******************************************************************************
 *        ItemMonikerIROTData_QueryInterface
 *******************************************************************************/
772 773
static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,
                                                            void **ppvObject)
Noomen Hamza's avatar
Noomen Hamza committed
774 775
{

776
    ItemMonikerImpl *This = impl_from_IROTData(iface);
Noomen Hamza's avatar
Noomen Hamza committed
777

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

780
    return ItemMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject);
Noomen Hamza's avatar
Noomen Hamza committed
781 782 783 784 785
}

/***********************************************************************
 *        ItemMonikerIROTData_AddRef
 */
786
static ULONG   WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface)
Noomen Hamza's avatar
Noomen Hamza committed
787
{
788
    ItemMonikerImpl *This = impl_from_IROTData(iface);
Noomen Hamza's avatar
Noomen Hamza committed
789

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

792
    return ItemMonikerImpl_AddRef(&This->IMoniker_iface);
Noomen Hamza's avatar
Noomen Hamza committed
793 794 795 796 797
}

/***********************************************************************
 *        ItemMonikerIROTData_Release
 */
798
static ULONG   WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface)
Noomen Hamza's avatar
Noomen Hamza committed
799
{
800
    ItemMonikerImpl *This = impl_from_IROTData(iface);
801

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

804
    return ItemMonikerImpl_Release(&This->IMoniker_iface);
Noomen Hamza's avatar
Noomen Hamza committed
805 806 807
}

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

821
    TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData);
822 823 824 825 826 827 828 829 830

    *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));
831
    *pszItemDelimiter = *This->itemDelimiter;
832 833 834
    /* write name */
    pszItemName = pszItemDelimiter + 1;
    for (i = 0; i < len; i++)
835
        pszItemName[i] = toupperW(This->itemName[i]);
836 837

    return S_OK;
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 888 889 890 891 892
/********************************************************************************/
/* 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. */
893 894
    This->IMoniker_iface.lpVtbl = &VT_ItemMonikerImpl;
    This->IROTData_iface.lpVtbl = &VT_ROTDataImpl;
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 928 929 930 931 932
    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;
}

933
/******************************************************************************
934
 *        CreateItemMoniker	[OLE32.@]
935
 ******************************************************************************/
936
HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim, LPCOLESTR  lpszItem, IMoniker **ppmk)
937
{
Robert Shearman's avatar
Robert Shearman committed
938 939
    ItemMonikerImpl* newItemMoniker;
    HRESULT        hr;
940

Robert Shearman's avatar
Robert Shearman committed
941
    TRACE("(%s,%s,%p)\n",debugstr_w(lpszDelim),debugstr_w(lpszItem),ppmk);
942 943 944

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

Robert Shearman's avatar
Robert Shearman committed
945
    if (!newItemMoniker)
946 947 948 949
        return STG_E_INSUFFICIENTMEMORY;

    hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem);

Noomen Hamza's avatar
Noomen Hamza committed
950
    if (FAILED(hr)){
951

Noomen Hamza's avatar
Noomen Hamza committed
952
        HeapFree(GetProcessHeap(),0,newItemMoniker);
953
    return hr;
Noomen Hamza's avatar
Noomen Hamza committed
954 955
    }

956 957
    return ItemMonikerImpl_QueryInterface(&newItemMoniker->IMoniker_iface,&IID_IMoniker,
                                          (void**)ppmk);
958
}
959

960
static HRESULT WINAPI ItemMonikerCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
961 962 963 964 965
{
    *ppv = NULL;
    if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
    {
        *ppv = iface;
966
        IClassFactory_AddRef(iface);
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 999 1000 1001 1002
        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))
1003
        hr = ItemMonikerImpl_QueryInterface(&newItemMoniker->IMoniker_iface, riid, ppv);
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029
    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);
}