bindctx.c 17.8 KB
Newer Older
1
/*
2 3 4
 *	                      BindCtx 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 <stdarg.h>
22
#include <string.h>
23 24 25

#define COBJMACROS

26
#include "winerror.h"
27
#include "windef.h"
28
#include "winbase.h"
29
#include "winnls.h"
30
#include "objbase.h"
31

32
#include "wine/debug.h"
33

34
WINE_DEFAULT_DEBUG_CHANNEL(ole);
35

36
#define  BINDCTX_FIRST_TABLE_SIZE 4
Noomen Hamza's avatar
Noomen Hamza committed
37 38 39 40 41 42 43 44 45 46 47 48

/* data structure of the BindCtx table elements */
typedef struct BindCtxObject{

    IUnknown*   pObj; /* point on a bound object */

    LPOLESTR  pkeyObj; /* key associated to this bound object */

    BYTE regType; /* registration type: 1 if RegisterObjectParam and 0 if RegisterObjectBound */

} BindCtxObject;

Austin English's avatar
Austin English committed
49
/* BindCtx data structure */
50 51
typedef struct BindCtxImpl{

52
    IBindCtx IBindCtx_iface;
53

54
    LONG ref; /* reference counter for this object */
55

56
    BindCtxObject* bindCtxTable; /* this is a table in which all bounded objects are stored*/
Noomen Hamza's avatar
Noomen Hamza committed
57 58
    DWORD          bindCtxTableLastIndex;  /* first free index in the table */
    DWORD          bindCtxTableSize;   /* size table */
59

60
    BIND_OPTS2 bindOption2; /* a structure which contains the bind options*/
61

Noomen Hamza's avatar
Noomen Hamza committed
62
} BindCtxImpl;
63

Noomen Hamza's avatar
Noomen Hamza committed
64
/* IBindCtx prototype functions : */
65 66
static HRESULT WINAPI BindCtxImpl_ReleaseBoundObjects(IBindCtx*);
static HRESULT BindCtxImpl_GetObjectIndex(BindCtxImpl*, IUnknown*, LPOLESTR, DWORD *);
67
static HRESULT BindCtxImpl_ExpandTable(BindCtxImpl *);
68

69 70 71 72 73
static inline BindCtxImpl *impl_from_IBindCtx(IBindCtx *iface)
{
return CONTAINING_RECORD(iface, BindCtxImpl, IBindCtx_iface);
}

74 75 76
/*******************************************************************************
 *        BindCtx_QueryInterface
 *******************************************************************************/
77 78
static HRESULT WINAPI
BindCtxImpl_QueryInterface(IBindCtx* iface,REFIID riid,void** ppvObject)
79
{
80
    BindCtxImpl *This = impl_from_IBindCtx(iface);
81

82
    TRACE("(%p %s %p)\n",This, debugstr_guid(riid), ppvObject);
83

84
    /* Perform a sanity check on the parameters.*/
85 86
    if (!ppvObject)
        return E_POINTER;
87

88 89
    /* Initialize the return parameter.*/
    *ppvObject = 0;
90

91 92 93 94
    /* Compare the riid with the interface IDs implemented by this object.*/
    if (IsEqualIID(&IID_IUnknown, riid) ||
        IsEqualIID(&IID_IBindCtx, riid))
    {
95
        *ppvObject = This;
96 97 98
        IBindCtx_AddRef(iface);
        return S_OK;
    }
99

100
    return E_NOINTERFACE;
101 102 103
}

/******************************************************************************
Noomen Hamza's avatar
Noomen Hamza committed
104
 *       BindCtx_AddRef
105
 ******************************************************************************/
106
static ULONG WINAPI BindCtxImpl_AddRef(IBindCtx* iface)
107
{
108
    BindCtxImpl *This = impl_from_IBindCtx(iface);
Noomen Hamza's avatar
Noomen Hamza committed
109

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

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

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
/******************************************************************************
 *        BindCtx_Destroy    (local function)
 *******************************************************************************/
static HRESULT BindCtxImpl_Destroy(BindCtxImpl* This)
{
    TRACE("(%p)\n",This);

    /* free the table space memory */
    HeapFree(GetProcessHeap(),0,This->bindCtxTable);

    /* free the bindctx structure */
    HeapFree(GetProcessHeap(),0,This);

    return S_OK;
}

131 132 133
/******************************************************************************
 *        BindCtx_Release
 ******************************************************************************/
134
static ULONG WINAPI BindCtxImpl_Release(IBindCtx* iface)
135
{
136
    BindCtxImpl *This = impl_from_IBindCtx(iface);
137
    ULONG ref;
Noomen Hamza's avatar
Noomen Hamza committed
138

139
    TRACE("(%p)\n",This);
140

141
    ref = InterlockedDecrement(&This->ref);
142 143
    if (ref == 0)
    {
Alexandre Julliard's avatar
Alexandre Julliard committed
144
        /* release all registered objects */
145
        BindCtxImpl_ReleaseBoundObjects(&This->IBindCtx_iface);
Noomen Hamza's avatar
Noomen Hamza committed
146

147
        BindCtxImpl_Destroy(This);
148
    }
149
    return ref;
150 151 152 153 154 155
}


/******************************************************************************
 *        BindCtx_RegisterObjectBound
 ******************************************************************************/
156 157
static HRESULT WINAPI
BindCtxImpl_RegisterObjectBound(IBindCtx* iface,IUnknown* punk)
158
{
159
    BindCtxImpl *This = impl_from_IBindCtx(iface);
Noomen Hamza's avatar
Noomen Hamza committed
160 161
    DWORD lastIndex=This->bindCtxTableLastIndex;

162
    TRACE("(%p,%p)\n",This,punk);
Noomen Hamza's avatar
Noomen Hamza committed
163 164

    if (punk==NULL)
165
        return S_OK;
166

167 168 169 170 171 172 173
    if (lastIndex == This->bindCtxTableSize)
    {
        HRESULT hr = BindCtxImpl_ExpandTable(This);
        if (FAILED(hr))
            return hr;
    }

Noomen Hamza's avatar
Noomen Hamza committed
174
    IUnknown_AddRef(punk);
175

Noomen Hamza's avatar
Noomen Hamza committed
176 177 178 179 180 181 182
    /* put the object in the first free element in the table */
    This->bindCtxTable[lastIndex].pObj = punk;
    This->bindCtxTable[lastIndex].pkeyObj = NULL;
    This->bindCtxTable[lastIndex].regType = 0;
    lastIndex= ++This->bindCtxTableLastIndex;

    return S_OK;
183 184 185 186 187
}

/******************************************************************************
 *        BindCtx_RevokeObjectBound
 ******************************************************************************/
188 189
static HRESULT WINAPI
BindCtxImpl_RevokeObjectBound(IBindCtx* iface, IUnknown* punk)
190
{
Noomen Hamza's avatar
Noomen Hamza committed
191 192
    DWORD index,j;

193
    BindCtxImpl *This = impl_from_IBindCtx(iface);
194

195
    TRACE("(%p,%p)\n",This,punk);
Noomen Hamza's avatar
Noomen Hamza committed
196

197 198 199
    if (!punk)
        return E_INVALIDARG;

200
    /* check if the object was registered or not */
Noomen Hamza's avatar
Noomen Hamza committed
201 202 203
    if (BindCtxImpl_GetObjectIndex(This,punk,NULL,&index)==S_FALSE)
        return MK_E_NOTBOUND;

204 205
    if(This->bindCtxTable[index].pObj)
        IUnknown_Release(This->bindCtxTable[index].pObj);
206
    HeapFree(GetProcessHeap(),0,This->bindCtxTable[index].pkeyObj);
207
    
Andreas Mohr's avatar
Andreas Mohr committed
208
    /* left-shift all elements in the right side of the current revoked object */
Noomen Hamza's avatar
Noomen Hamza committed
209 210
    for(j=index; j<This->bindCtxTableLastIndex-1; j++)
        This->bindCtxTable[j]= This->bindCtxTable[j+1];
211

Noomen Hamza's avatar
Noomen Hamza committed
212 213 214
    This->bindCtxTableLastIndex--;

    return S_OK;
215 216 217
}

/******************************************************************************
Noomen Hamza's avatar
Noomen Hamza committed
218
 *        BindCtx_ReleaseBoundObjects
219
 ******************************************************************************/
220 221
static HRESULT WINAPI
BindCtxImpl_ReleaseBoundObjects(IBindCtx* iface)
222
{
Noomen Hamza's avatar
Noomen Hamza committed
223 224
    DWORD i;

225
    BindCtxImpl *This = impl_from_IBindCtx(iface);
226

227
    TRACE("(%p)\n",This);
Noomen Hamza's avatar
Noomen Hamza committed
228 229

    for(i=0;i<This->bindCtxTableLastIndex;i++)
230 231 232
    {
        if(This->bindCtxTable[i].pObj)
            IUnknown_Release(This->bindCtxTable[i].pObj);
233
        HeapFree(GetProcessHeap(),0,This->bindCtxTable[i].pkeyObj);
234 235
    }
    
Noomen Hamza's avatar
Noomen Hamza committed
236 237 238
    This->bindCtxTableLastIndex = 0;

    return S_OK;
239 240 241 242 243
}

/******************************************************************************
 *        BindCtx_SetBindOptions
 ******************************************************************************/
244 245
static HRESULT WINAPI
BindCtxImpl_SetBindOptions(IBindCtx* iface,BIND_OPTS *pbindopts)
246
{
247
    BindCtxImpl *This = impl_from_IBindCtx(iface);
248

249
    TRACE("(%p,%p)\n",This,pbindopts);
Noomen Hamza's avatar
Noomen Hamza committed
250 251 252

    if (pbindopts==NULL)
        return E_POINTER;
253

254 255
    if (pbindopts->cbStruct > sizeof(BIND_OPTS2))
    {
256
        WARN("invalid size\n");
257 258 259
        return E_INVALIDARG; /* FIXME : not verified */
    }
    memcpy(&This->bindOption2, pbindopts, pbindopts->cbStruct);
Noomen Hamza's avatar
Noomen Hamza committed
260
    return S_OK;
261 262 263 264 265
}

/******************************************************************************
 *        BindCtx_GetBindOptions
 ******************************************************************************/
266 267
static HRESULT WINAPI
BindCtxImpl_GetBindOptions(IBindCtx* iface,BIND_OPTS *pbindopts)
268
{
269
    BindCtxImpl *This = impl_from_IBindCtx(iface);
270
    ULONG cbStruct;
271

272
    TRACE("(%p,%p)\n",This,pbindopts);
Noomen Hamza's avatar
Noomen Hamza committed
273 274 275 276

    if (pbindopts==NULL)
        return E_POINTER;

277 278 279 280 281 282
    cbStruct = pbindopts->cbStruct;
    if (cbStruct > sizeof(BIND_OPTS2))
        cbStruct = sizeof(BIND_OPTS2);

    memcpy(pbindopts, &This->bindOption2, cbStruct);
    pbindopts->cbStruct = cbStruct;
283

Noomen Hamza's avatar
Noomen Hamza committed
284
    return S_OK;
285 286 287 288 289
}

/******************************************************************************
 *        BindCtx_GetRunningObjectTable
 ******************************************************************************/
290 291
static HRESULT WINAPI
BindCtxImpl_GetRunningObjectTable(IBindCtx* iface,IRunningObjectTable** pprot)
292
{
293
    BindCtxImpl *This = impl_from_IBindCtx(iface);
294

295
    TRACE("(%p,%p)\n",This,pprot);
Noomen Hamza's avatar
Noomen Hamza committed
296 297 298

    if (pprot==NULL)
        return E_POINTER;
299

300
    return GetRunningObjectTable(0, pprot);
301 302 303 304 305
}

/******************************************************************************
 *        BindCtx_RegisterObjectParam
 ******************************************************************************/
306 307
static HRESULT WINAPI
BindCtxImpl_RegisterObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown* punk)
308
{
309
    DWORD index=0;
310
    BindCtxImpl *This = impl_from_IBindCtx(iface);
311

312
    TRACE("(%p,%s,%p)\n",This,debugstr_w(pszkey),punk);
Noomen Hamza's avatar
Noomen Hamza committed
313 314 315

    if (punk==NULL)
        return E_INVALIDARG;
316

317 318 319 320 321 322
    if (pszkey!=NULL && BindCtxImpl_GetObjectIndex(This,NULL,pszkey,&index)==S_OK)
    {
	TRACE("Overwriting existing key\n");
	if(This->bindCtxTable[index].pObj!=NULL)
	    IUnknown_Release(This->bindCtxTable[index].pObj);
	This->bindCtxTable[index].pObj=punk;
323
	IUnknown_AddRef(punk);
324 325
	return S_OK;
    }
326 327 328 329 330 331 332 333

    if (This->bindCtxTableLastIndex == This->bindCtxTableSize)
    {
        HRESULT hr = BindCtxImpl_ExpandTable(This);
        if (FAILED(hr))
            return hr;
    }

Noomen Hamza's avatar
Noomen Hamza committed
334 335 336 337 338 339 340
    This->bindCtxTable[This->bindCtxTableLastIndex].pObj = punk;
    This->bindCtxTable[This->bindCtxTableLastIndex].regType = 1;

    if (pszkey==NULL)

        This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj=NULL;

341 342
    else
    {
Noomen Hamza's avatar
Noomen Hamza committed
343 344 345 346 347 348

        This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj=
            HeapAlloc(GetProcessHeap(),0,(sizeof(WCHAR)*(1+lstrlenW(pszkey))));

        if (This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj==NULL)
            return E_OUTOFMEMORY;
349
        lstrcpyW(This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj,pszkey);
350
    }
351

Noomen Hamza's avatar
Noomen Hamza committed
352
    This->bindCtxTableLastIndex++;
353

354
    IUnknown_AddRef(punk);
Noomen Hamza's avatar
Noomen Hamza committed
355 356
    return S_OK;
}
357

358 359 360
/******************************************************************************
 *        BindCtx_GetObjectParam
 ******************************************************************************/
361 362
static HRESULT WINAPI
BindCtxImpl_GetObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown** punk)
363
{
Noomen Hamza's avatar
Noomen Hamza committed
364
    DWORD index;
365
    BindCtxImpl *This = impl_from_IBindCtx(iface);
366

367
    TRACE("(%p,%s,%p)\n",This,debugstr_w(pszkey),punk);
Noomen Hamza's avatar
Noomen Hamza committed
368 369 370 371 372

    if (punk==NULL)
        return E_POINTER;

    *punk=0;
373

Noomen Hamza's avatar
Noomen Hamza committed
374 375 376 377
    if (BindCtxImpl_GetObjectIndex(This,NULL,pszkey,&index)==S_FALSE)
        return E_FAIL;

    IUnknown_AddRef(This->bindCtxTable[index].pObj);
378

Noomen Hamza's avatar
Noomen Hamza committed
379 380 381
    *punk = This->bindCtxTable[index].pObj;

    return S_OK;
382 383 384
}

/******************************************************************************
Noomen Hamza's avatar
Noomen Hamza committed
385
 *        BindCtx_RevokeObjectParam
386
 ******************************************************************************/
387 388
static HRESULT WINAPI
BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR ppenum)
389
{
Noomen Hamza's avatar
Noomen Hamza committed
390 391
    DWORD index,j;

392
    BindCtxImpl *This = impl_from_IBindCtx(iface);
393

394
    TRACE("(%p,%s)\n",This,debugstr_w(ppenum));
Noomen Hamza's avatar
Noomen Hamza committed
395 396 397 398 399

    if (BindCtxImpl_GetObjectIndex(This,NULL,ppenum,&index)==S_FALSE)
        return E_FAIL;

    /* release the object if it's found */
400 401
    if(This->bindCtxTable[index].pObj)
        IUnknown_Release(This->bindCtxTable[index].pObj);
402
    HeapFree(GetProcessHeap(),0,This->bindCtxTable[index].pkeyObj);
403
    
Noomen Hamza's avatar
Noomen Hamza committed
404 405 406
    /* remove the object from the table with a left-shifting of all objects in the right side */
    for(j=index; j<This->bindCtxTableLastIndex-1; j++)
        This->bindCtxTable[j]= This->bindCtxTable[j+1];
407

Noomen Hamza's avatar
Noomen Hamza committed
408 409 410
    This->bindCtxTableLastIndex--;

    return S_OK;
411 412 413
}

/******************************************************************************
Noomen Hamza's avatar
Noomen Hamza committed
414
 *        BindCtx_EnumObjectParam
415
 ******************************************************************************/
416 417
static HRESULT WINAPI
BindCtxImpl_EnumObjectParam(IBindCtx* iface,IEnumString** pszkey)
418
{
419 420 421 422 423
    TRACE("(%p,%p)\n",iface,pszkey);

    *pszkey = NULL;

    /* not implemented in native either */
424 425 426
    return E_NOTIMPL;
}

Noomen Hamza's avatar
Noomen Hamza committed
427 428 429
/********************************************************************************
 *        GetObjectIndex (local function)
 ********************************************************************************/
430
static HRESULT BindCtxImpl_GetObjectIndex(BindCtxImpl* This,
Noomen Hamza's avatar
Noomen Hamza committed
431 432 433 434 435 436 437
                                          IUnknown* punk,
                                          LPOLESTR pszkey,
                                          DWORD *index)
{

    DWORD i;
    BYTE found=0;
438

439
    TRACE("(%p,%p,%p,%p)\n",This,punk,pszkey,index);
Noomen Hamza's avatar
Noomen Hamza committed
440 441 442

    if (punk==NULL)
        /* search object identified by a register key */
443 444
        for(i=0; ( (i<This->bindCtxTableLastIndex) && (!found));i++)
        {
Noomen Hamza's avatar
Noomen Hamza committed
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
            if(This->bindCtxTable[i].regType==1){

                if ( ( (This->bindCtxTable[i].pkeyObj==NULL) && (pszkey==NULL) ) ||
                     ( (This->bindCtxTable[i].pkeyObj!=NULL) &&
                       (pszkey!=NULL) &&
                       (lstrcmpW(This->bindCtxTable[i].pkeyObj,pszkey)==0)
                     )
                   )

                    found=1;
            }
        }
    else
        /* search object identified by a moniker*/
        for(i=0; ( (i<This->bindCtxTableLastIndex) && (!found));i++)
            if(This->bindCtxTable[i].pObj==punk)
                found=1;

    if (index != NULL)
        *index=i-1;

    if (found)
        return S_OK;
468 469
    TRACE("key not found\n");
    return S_FALSE;
Noomen Hamza's avatar
Noomen Hamza committed
470
}
471

472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
static HRESULT BindCtxImpl_ExpandTable(BindCtxImpl *This)
{
    if (!This->bindCtxTableSize)
    {
        This->bindCtxTableSize = BINDCTX_FIRST_TABLE_SIZE;
        This->bindCtxTable = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
                                       This->bindCtxTableSize * sizeof(BindCtxObject));
    }
    else
    {
        This->bindCtxTableSize *= 2;

        This->bindCtxTable = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->bindCtxTable,
                                         This->bindCtxTableSize * sizeof(BindCtxObject));
    }

    if (!This->bindCtxTable)
        return E_OUTOFMEMORY;

    return S_OK;
}


495
/* Virtual function table for the BindCtx class. */
496
static const IBindCtxVtbl VT_BindCtxImpl =
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
{
    BindCtxImpl_QueryInterface,
    BindCtxImpl_AddRef,
    BindCtxImpl_Release,
    BindCtxImpl_RegisterObjectBound,
    BindCtxImpl_RevokeObjectBound,
    BindCtxImpl_ReleaseBoundObjects,
    BindCtxImpl_SetBindOptions,
    BindCtxImpl_GetBindOptions,
    BindCtxImpl_GetRunningObjectTable,
    BindCtxImpl_RegisterObjectParam,
    BindCtxImpl_GetObjectParam,
    BindCtxImpl_EnumObjectParam,
    BindCtxImpl_RevokeObjectParam
};

/******************************************************************************
 *         BindCtx_Construct (local function)
 *******************************************************************************/
static HRESULT BindCtxImpl_Construct(BindCtxImpl* This)
{
    TRACE("(%p)\n",This);

    /* Initialize the virtual function table.*/
521
    This->IBindCtx_iface.lpVtbl = &VT_BindCtxImpl;
522 523 524 525 526 527 528 529 530 531
    This->ref          = 0;

    /* Initialize the BIND_OPTS2 structure */
    This->bindOption2.cbStruct  = sizeof(BIND_OPTS2);
    This->bindOption2.grfFlags = 0;
    This->bindOption2.grfMode = STGM_READWRITE;
    This->bindOption2.dwTickCountDeadline = 0;

    This->bindOption2.dwTrackFlags = 0;
    This->bindOption2.dwClassContext = CLSCTX_SERVER;
532
    This->bindOption2.locale = GetThreadLocale();
533 534 535
    This->bindOption2.pServerInfo = 0;

    /* Initialize the bindctx table */
536
    This->bindCtxTableSize=0;
537
    This->bindCtxTableLastIndex=0;
538
    This->bindCtxTable = NULL;
539 540 541 542

    return S_OK;
}

543
/******************************************************************************
544
 *        CreateBindCtx (OLE32.@)
545 546 547 548 549 550 551 552 553 554 555 556
 *
 * Creates a bind context. A bind context encompasses information and options
 * used when binding to a moniker.
 *
 * PARAMS
 *  reserved [I] Reserved. Set to 0.
 *  ppbc     [O] Address that receives the bind context object.
 *
 * RETURNS
 *  Success: S_OK.
 *  Failure: Any HRESULT code.
 */
557
HRESULT WINAPI CreateBindCtx(DWORD reserved, LPBC * ppbc)
558
{
559
    BindCtxImpl* newBindCtx;
Noomen Hamza's avatar
Noomen Hamza committed
560
    HRESULT hr;
561

562
    TRACE("(%d,%p)\n",reserved,ppbc);
563

564 565
    if (!ppbc) return E_INVALIDARG;

566 567 568 569 570 571 572 573
    *ppbc = NULL;

    if (reserved != 0)
    {
        ERR("reserved should be 0, not 0x%x\n", reserved);
        return E_INVALIDARG;
    }

574 575
    newBindCtx = HeapAlloc(GetProcessHeap(), 0, sizeof(BindCtxImpl));
    if (newBindCtx == 0)
Noomen Hamza's avatar
Noomen Hamza committed
576
        return E_OUTOFMEMORY;
577 578

    hr = BindCtxImpl_Construct(newBindCtx);
579 580
    if (FAILED(hr))
    {
Noomen Hamza's avatar
Noomen Hamza committed
581
        HeapFree(GetProcessHeap(),0,newBindCtx);
582
        return hr;
Noomen Hamza's avatar
Noomen Hamza committed
583
    }
584

585
    return BindCtxImpl_QueryInterface(&newBindCtx->IBindCtx_iface,&IID_IBindCtx,(void**)ppbc);
586
}
587

588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
/******************************************************************************
 *              BindMoniker        [OLE32.@]
 *
 * Binds to a moniker.
 *
 * PARAMS
 *  pmk      [I] Moniker to bind to.
 *  grfOpt   [I] Reserved option flags. Set to 0.
 *  riid     [I] ID of the interface to bind to.
 *  pvResult [O] Address that receives the interface of the object that was bound to.
 *
 * RETURNS
 *  Success: S_OK.
 *  Failure: Any HRESULT code.
 */
603 604 605 606 607
HRESULT WINAPI BindMoniker(LPMONIKER pmk, DWORD grfOpt, REFIID riid, LPVOID * ppvResult)
{
    HRESULT res;
    IBindCtx * pbc;

608
    TRACE("(%p, %x, %s, %p)\n", pmk, grfOpt, debugstr_guid(riid), ppvResult);
609 610 611

    res = CreateBindCtx(grfOpt, &pbc);
    if (SUCCEEDED(res))
612
    {
613
        res = IMoniker_BindToObject(pmk, pbc, NULL, riid, ppvResult);
614 615
        IBindCtx_Release(pbc);
    }
616 617
    return res;
}