2 * BindCtx implementation
4 * Copyright 1999 Noomen Hamza
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
36 #define BINDCTX_FIRST_TABLE_SIZE 4
38 /* data structure of the BindCtx table elements */
39 typedef struct BindCtxObject
{
41 IUnknown
* pObj
; /* point on a bound object */
43 LPOLESTR pkeyObj
; /* key associated to this bound object */
45 BYTE regType
; /* registration type: 1 if RegisterObjectParam and 0 if RegisterObjectBound */
49 /* BindCtx data structure */
50 typedef struct BindCtxImpl
{
52 const IBindCtxVtbl
*lpVtbl
; /* VTable relative to the IBindCtx interface.*/
54 LONG ref
; /* reference counter for this object */
56 BindCtxObject
* bindCtxTable
; /* this is a table in which all bounded objects are stored*/
57 DWORD bindCtxTableLastIndex
; /* first free index in the table */
58 DWORD bindCtxTableSize
; /* size table */
60 BIND_OPTS2 bindOption2
; /* a structure which contains the bind options*/
64 /* IBindCtx prototype functions : */
65 static HRESULT WINAPI
BindCtxImpl_ReleaseBoundObjects(IBindCtx
*);
66 static HRESULT
BindCtxImpl_GetObjectIndex(BindCtxImpl
*, IUnknown
*, LPOLESTR
, DWORD
*);
67 static HRESULT
BindCtxImpl_ExpandTable(BindCtxImpl
*);
69 /*******************************************************************************
70 * BindCtx_QueryInterface
71 *******************************************************************************/
73 BindCtxImpl_QueryInterface(IBindCtx
* iface
,REFIID riid
,void** ppvObject
)
75 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
77 TRACE("(%p %s %p)\n",This
, debugstr_guid(riid
), ppvObject
);
79 /* Perform a sanity check on the parameters.*/
83 /* Initialize the return parameter.*/
86 /* Compare the riid with the interface IDs implemented by this object.*/
87 if (IsEqualIID(&IID_IUnknown
, riid
) ||
88 IsEqualIID(&IID_IBindCtx
, riid
))
90 *ppvObject
= (IBindCtx
*)This
;
91 IBindCtx_AddRef(iface
);
98 /******************************************************************************
100 ******************************************************************************/
101 static ULONG WINAPI
BindCtxImpl_AddRef(IBindCtx
* iface
)
103 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
105 TRACE("(%p)\n",This
);
107 return InterlockedIncrement(&This
->ref
);
110 /******************************************************************************
111 * BindCtx_Destroy (local function)
112 *******************************************************************************/
113 static HRESULT
BindCtxImpl_Destroy(BindCtxImpl
* This
)
115 TRACE("(%p)\n",This
);
117 /* free the table space memory */
118 HeapFree(GetProcessHeap(),0,This
->bindCtxTable
);
120 /* free the bindctx structure */
121 HeapFree(GetProcessHeap(),0,This
);
126 /******************************************************************************
128 ******************************************************************************/
129 static ULONG WINAPI
BindCtxImpl_Release(IBindCtx
* iface
)
131 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
134 TRACE("(%p)\n",This
);
136 ref
= InterlockedDecrement(&This
->ref
);
139 /* release all registered objects */
140 BindCtxImpl_ReleaseBoundObjects((IBindCtx
*)This
);
142 BindCtxImpl_Destroy(This
);
148 /******************************************************************************
149 * BindCtx_RegisterObjectBound
150 ******************************************************************************/
151 static HRESULT WINAPI
152 BindCtxImpl_RegisterObjectBound(IBindCtx
* iface
,IUnknown
* punk
)
154 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
155 DWORD lastIndex
=This
->bindCtxTableLastIndex
;
157 TRACE("(%p,%p)\n",This
,punk
);
162 if (lastIndex
== This
->bindCtxTableSize
)
164 HRESULT hr
= BindCtxImpl_ExpandTable(This
);
169 IUnknown_AddRef(punk
);
171 /* put the object in the first free element in the table */
172 This
->bindCtxTable
[lastIndex
].pObj
= punk
;
173 This
->bindCtxTable
[lastIndex
].pkeyObj
= NULL
;
174 This
->bindCtxTable
[lastIndex
].regType
= 0;
175 lastIndex
= ++This
->bindCtxTableLastIndex
;
180 /******************************************************************************
181 * BindCtx_RevokeObjectBound
182 ******************************************************************************/
183 static HRESULT WINAPI
184 BindCtxImpl_RevokeObjectBound(IBindCtx
* iface
, IUnknown
* punk
)
188 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
190 TRACE("(%p,%p)\n",This
,punk
);
195 /* check if the object was registered or not */
196 if (BindCtxImpl_GetObjectIndex(This
,punk
,NULL
,&index
)==S_FALSE
)
197 return MK_E_NOTBOUND
;
199 if(This
->bindCtxTable
[index
].pObj
)
200 IUnknown_Release(This
->bindCtxTable
[index
].pObj
);
201 HeapFree(GetProcessHeap(),0,This
->bindCtxTable
[index
].pkeyObj
);
203 /* left-shift all elements in the right side of the current revoked object */
204 for(j
=index
; j
<This
->bindCtxTableLastIndex
-1; j
++)
205 This
->bindCtxTable
[j
]= This
->bindCtxTable
[j
+1];
207 This
->bindCtxTableLastIndex
--;
212 /******************************************************************************
213 * BindCtx_ReleaseBoundObjects
214 ******************************************************************************/
215 static HRESULT WINAPI
216 BindCtxImpl_ReleaseBoundObjects(IBindCtx
* iface
)
220 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
222 TRACE("(%p)\n",This
);
224 for(i
=0;i
<This
->bindCtxTableLastIndex
;i
++)
226 if(This
->bindCtxTable
[i
].pObj
)
227 IUnknown_Release(This
->bindCtxTable
[i
].pObj
);
228 HeapFree(GetProcessHeap(),0,This
->bindCtxTable
[i
].pkeyObj
);
231 This
->bindCtxTableLastIndex
= 0;
236 /******************************************************************************
237 * BindCtx_SetBindOptions
238 ******************************************************************************/
239 static HRESULT WINAPI
240 BindCtxImpl_SetBindOptions(IBindCtx
* iface
,BIND_OPTS
*pbindopts
)
242 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
244 TRACE("(%p,%p)\n",This
,pbindopts
);
249 if (pbindopts
->cbStruct
> sizeof(BIND_OPTS2
))
251 WARN("invalid size\n");
252 return E_INVALIDARG
; /* FIXME : not verified */
254 memcpy(&This
->bindOption2
, pbindopts
, pbindopts
->cbStruct
);
258 /******************************************************************************
259 * BindCtx_GetBindOptions
260 ******************************************************************************/
261 static HRESULT WINAPI
262 BindCtxImpl_GetBindOptions(IBindCtx
* iface
,BIND_OPTS
*pbindopts
)
264 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
267 TRACE("(%p,%p)\n",This
,pbindopts
);
272 cbStruct
= pbindopts
->cbStruct
;
273 if (cbStruct
> sizeof(BIND_OPTS2
))
274 cbStruct
= sizeof(BIND_OPTS2
);
276 memcpy(pbindopts
, &This
->bindOption2
, cbStruct
);
277 pbindopts
->cbStruct
= cbStruct
;
282 /******************************************************************************
283 * BindCtx_GetRunningObjectTable
284 ******************************************************************************/
285 static HRESULT WINAPI
286 BindCtxImpl_GetRunningObjectTable(IBindCtx
* iface
,IRunningObjectTable
** pprot
)
290 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
292 TRACE("(%p,%p)\n",This
,pprot
);
297 res
=GetRunningObjectTable(0, pprot
);
302 /******************************************************************************
303 * BindCtx_RegisterObjectParam
304 ******************************************************************************/
305 static HRESULT WINAPI
306 BindCtxImpl_RegisterObjectParam(IBindCtx
* iface
,LPOLESTR pszkey
, IUnknown
* punk
)
309 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
311 TRACE("(%p,%s,%p)\n",This
,debugstr_w(pszkey
),punk
);
316 if (pszkey
!=NULL
&& BindCtxImpl_GetObjectIndex(This
,NULL
,pszkey
,&index
)==S_OK
)
318 TRACE("Overwriting existing key\n");
319 if(This
->bindCtxTable
[index
].pObj
!=NULL
)
320 IUnknown_Release(This
->bindCtxTable
[index
].pObj
);
321 This
->bindCtxTable
[index
].pObj
=punk
;
322 IUnknown_AddRef(punk
);
326 if (This
->bindCtxTableLastIndex
== This
->bindCtxTableSize
)
328 HRESULT hr
= BindCtxImpl_ExpandTable(This
);
333 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pObj
= punk
;
334 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].regType
= 1;
338 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
=NULL
;
343 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
=
344 HeapAlloc(GetProcessHeap(),0,(sizeof(WCHAR
)*(1+lstrlenW(pszkey
))));
346 if (This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
==NULL
)
347 return E_OUTOFMEMORY
;
348 lstrcpyW(This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
,pszkey
);
351 This
->bindCtxTableLastIndex
++;
353 IUnknown_AddRef(punk
);
357 /******************************************************************************
358 * BindCtx_GetObjectParam
359 ******************************************************************************/
360 static HRESULT WINAPI
361 BindCtxImpl_GetObjectParam(IBindCtx
* iface
,LPOLESTR pszkey
, IUnknown
** punk
)
364 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
366 TRACE("(%p,%s,%p)\n",This
,debugstr_w(pszkey
),punk
);
373 if (BindCtxImpl_GetObjectIndex(This
,NULL
,pszkey
,&index
)==S_FALSE
)
376 IUnknown_AddRef(This
->bindCtxTable
[index
].pObj
);
378 *punk
= This
->bindCtxTable
[index
].pObj
;
383 /******************************************************************************
384 * BindCtx_RevokeObjectParam
385 ******************************************************************************/
386 static HRESULT WINAPI
387 BindCtxImpl_RevokeObjectParam(IBindCtx
* iface
,LPOLESTR ppenum
)
391 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
393 TRACE("(%p,%s)\n",This
,debugstr_w(ppenum
));
395 if (BindCtxImpl_GetObjectIndex(This
,NULL
,ppenum
,&index
)==S_FALSE
)
398 /* release the object if it's found */
399 if(This
->bindCtxTable
[index
].pObj
)
400 IUnknown_Release(This
->bindCtxTable
[index
].pObj
);
401 HeapFree(GetProcessHeap(),0,This
->bindCtxTable
[index
].pkeyObj
);
403 /* remove the object from the table with a left-shifting of all objects in the right side */
404 for(j
=index
; j
<This
->bindCtxTableLastIndex
-1; j
++)
405 This
->bindCtxTable
[j
]= This
->bindCtxTable
[j
+1];
407 This
->bindCtxTableLastIndex
--;
412 /******************************************************************************
413 * BindCtx_EnumObjectParam
414 ******************************************************************************/
415 static HRESULT WINAPI
416 BindCtxImpl_EnumObjectParam(IBindCtx
* iface
,IEnumString
** pszkey
)
418 TRACE("(%p,%p)\n",iface
,pszkey
);
422 /* not implemented in native either */
426 /********************************************************************************
427 * GetObjectIndex (local function)
428 ********************************************************************************/
429 static HRESULT
BindCtxImpl_GetObjectIndex(BindCtxImpl
* This
,
438 TRACE("(%p,%p,%p,%p)\n",This
,punk
,pszkey
,index
);
441 /* search object identified by a register key */
442 for(i
=0; ( (i
<This
->bindCtxTableLastIndex
) && (!found
));i
++)
444 if(This
->bindCtxTable
[i
].regType
==1){
446 if ( ( (This
->bindCtxTable
[i
].pkeyObj
==NULL
) && (pszkey
==NULL
) ) ||
447 ( (This
->bindCtxTable
[i
].pkeyObj
!=NULL
) &&
449 (lstrcmpW(This
->bindCtxTable
[i
].pkeyObj
,pszkey
)==0)
457 /* search object identified by a moniker*/
458 for(i
=0; ( (i
<This
->bindCtxTableLastIndex
) && (!found
));i
++)
459 if(This
->bindCtxTable
[i
].pObj
==punk
)
467 TRACE("key not found\n");
471 static HRESULT
BindCtxImpl_ExpandTable(BindCtxImpl
*This
)
473 if (!This
->bindCtxTableSize
)
475 This
->bindCtxTableSize
= BINDCTX_FIRST_TABLE_SIZE
;
476 This
->bindCtxTable
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
477 This
->bindCtxTableSize
* sizeof(BindCtxObject
));
481 This
->bindCtxTableSize
*= 2;
483 This
->bindCtxTable
= HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,This
->bindCtxTable
,
484 This
->bindCtxTableSize
* sizeof(BindCtxObject
));
487 if (!This
->bindCtxTable
)
488 return E_OUTOFMEMORY
;
494 /* Virtual function table for the BindCtx class. */
495 static const IBindCtxVtbl VT_BindCtxImpl
=
497 BindCtxImpl_QueryInterface
,
500 BindCtxImpl_RegisterObjectBound
,
501 BindCtxImpl_RevokeObjectBound
,
502 BindCtxImpl_ReleaseBoundObjects
,
503 BindCtxImpl_SetBindOptions
,
504 BindCtxImpl_GetBindOptions
,
505 BindCtxImpl_GetRunningObjectTable
,
506 BindCtxImpl_RegisterObjectParam
,
507 BindCtxImpl_GetObjectParam
,
508 BindCtxImpl_EnumObjectParam
,
509 BindCtxImpl_RevokeObjectParam
512 /******************************************************************************
513 * BindCtx_Construct (local function)
514 *******************************************************************************/
515 static HRESULT
BindCtxImpl_Construct(BindCtxImpl
* This
)
517 TRACE("(%p)\n",This
);
519 /* Initialize the virtual function table.*/
520 This
->lpVtbl
= &VT_BindCtxImpl
;
523 /* Initialize the BIND_OPTS2 structure */
524 This
->bindOption2
.cbStruct
= sizeof(BIND_OPTS2
);
525 This
->bindOption2
.grfFlags
= 0;
526 This
->bindOption2
.grfMode
= STGM_READWRITE
;
527 This
->bindOption2
.dwTickCountDeadline
= 0;
529 This
->bindOption2
.dwTrackFlags
= 0;
530 This
->bindOption2
.dwClassContext
= CLSCTX_SERVER
;
531 This
->bindOption2
.locale
= GetThreadLocale();
532 This
->bindOption2
.pServerInfo
= 0;
534 /* Initialize the bindctx table */
535 This
->bindCtxTableSize
=0;
536 This
->bindCtxTableLastIndex
=0;
537 This
->bindCtxTable
= NULL
;
542 /******************************************************************************
543 * CreateBindCtx (OLE32.@)
545 * Creates a bind context. A bind context encompasses information and options
546 * used when binding to a moniker.
549 * reserved [I] Reserved. Set to 0.
550 * ppbc [O] Address that receives the bind context object.
554 * Failure: Any HRESULT code.
556 HRESULT WINAPI
CreateBindCtx(DWORD reserved
, LPBC
* ppbc
)
558 BindCtxImpl
* newBindCtx
= 0;
560 IID riid
=IID_IBindCtx
;
562 TRACE("(%d,%p)\n",reserved
,ppbc
);
564 if (!ppbc
) return E_INVALIDARG
;
570 ERR("reserved should be 0, not 0x%x\n", reserved
);
574 newBindCtx
= HeapAlloc(GetProcessHeap(), 0, sizeof(BindCtxImpl
));
576 return E_OUTOFMEMORY
;
578 hr
= BindCtxImpl_Construct(newBindCtx
);
581 HeapFree(GetProcessHeap(),0,newBindCtx
);
585 hr
= BindCtxImpl_QueryInterface((IBindCtx
*)newBindCtx
,&riid
,(void**)ppbc
);
590 /******************************************************************************
591 * BindMoniker [OLE32.@]
593 * Binds to a moniker.
596 * pmk [I] Moniker to bind to.
597 * grfOpt [I] Reserved option flags. Set to 0.
598 * riid [I] ID of the interface to bind to.
599 * pvResult [O] Address that receives the interface of the object that was bound to.
603 * Failure: Any HRESULT code.
605 HRESULT WINAPI
BindMoniker(LPMONIKER pmk
, DWORD grfOpt
, REFIID riid
, LPVOID
* ppvResult
)
610 TRACE("(%p, %x, %s, %p)\n", pmk
, grfOpt
, debugstr_guid(riid
), ppvResult
);
612 res
= CreateBindCtx(grfOpt
, &pbc
);
615 res
= IMoniker_BindToObject(pmk
, pbc
, NULL
, riid
, ppvResult
);
616 IBindCtx_Release(pbc
);