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 IBindCtx IBindCtx_iface
;
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 */
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 static inline BindCtxImpl
*impl_from_IBindCtx(IBindCtx
*iface
)
71 return CONTAINING_RECORD(iface
, BindCtxImpl
, IBindCtx_iface
);
74 /*******************************************************************************
75 * BindCtx_QueryInterface
76 *******************************************************************************/
78 BindCtxImpl_QueryInterface(IBindCtx
* iface
,REFIID riid
,void** ppvObject
)
80 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
82 TRACE("(%p %s %p)\n",This
, debugstr_guid(riid
), ppvObject
);
84 /* Perform a sanity check on the parameters.*/
88 /* Initialize the return parameter.*/
91 /* Compare the riid with the interface IDs implemented by this object.*/
92 if (IsEqualIID(&IID_IUnknown
, riid
) ||
93 IsEqualIID(&IID_IBindCtx
, riid
))
95 *ppvObject
= &This
->IBindCtx_iface
;
96 IBindCtx_AddRef(iface
);
100 return E_NOINTERFACE
;
103 /******************************************************************************
105 ******************************************************************************/
106 static ULONG WINAPI
BindCtxImpl_AddRef(IBindCtx
* iface
)
108 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
110 TRACE("(%p)\n",This
);
112 return InterlockedIncrement(&This
->ref
);
115 /******************************************************************************
116 * BindCtx_Destroy (local function)
117 *******************************************************************************/
118 static HRESULT
BindCtxImpl_Destroy(BindCtxImpl
* This
)
120 TRACE("(%p)\n",This
);
122 /* free the table space memory */
123 HeapFree(GetProcessHeap(),0,This
->bindCtxTable
);
125 /* free the bindctx structure */
126 HeapFree(GetProcessHeap(),0,This
);
131 /******************************************************************************
133 ******************************************************************************/
134 static ULONG WINAPI
BindCtxImpl_Release(IBindCtx
* iface
)
136 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
139 TRACE("(%p)\n",This
);
141 ref
= InterlockedDecrement(&This
->ref
);
144 /* release all registered objects */
145 BindCtxImpl_ReleaseBoundObjects(&This
->IBindCtx_iface
);
147 BindCtxImpl_Destroy(This
);
153 /******************************************************************************
154 * BindCtx_RegisterObjectBound
155 ******************************************************************************/
156 static HRESULT WINAPI
157 BindCtxImpl_RegisterObjectBound(IBindCtx
* iface
,IUnknown
* punk
)
159 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
160 DWORD lastIndex
=This
->bindCtxTableLastIndex
;
162 TRACE("(%p,%p)\n",This
,punk
);
167 if (lastIndex
== This
->bindCtxTableSize
)
169 HRESULT hr
= BindCtxImpl_ExpandTable(This
);
174 IUnknown_AddRef(punk
);
176 /* put the object in the first free element in the table */
177 This
->bindCtxTable
[lastIndex
].pObj
= punk
;
178 This
->bindCtxTable
[lastIndex
].pkeyObj
= NULL
;
179 This
->bindCtxTable
[lastIndex
].regType
= 0;
180 lastIndex
= ++This
->bindCtxTableLastIndex
;
185 /******************************************************************************
186 * BindCtx_RevokeObjectBound
187 ******************************************************************************/
188 static HRESULT WINAPI
189 BindCtxImpl_RevokeObjectBound(IBindCtx
* iface
, IUnknown
* punk
)
193 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
195 TRACE("(%p,%p)\n",This
,punk
);
200 /* check if the object was registered or not */
201 if (BindCtxImpl_GetObjectIndex(This
,punk
,NULL
,&index
)==S_FALSE
)
202 return MK_E_NOTBOUND
;
204 if(This
->bindCtxTable
[index
].pObj
)
205 IUnknown_Release(This
->bindCtxTable
[index
].pObj
);
206 HeapFree(GetProcessHeap(),0,This
->bindCtxTable
[index
].pkeyObj
);
208 /* left-shift all elements in the right side of the current revoked object */
209 for(j
=index
; j
<This
->bindCtxTableLastIndex
-1; j
++)
210 This
->bindCtxTable
[j
]= This
->bindCtxTable
[j
+1];
212 This
->bindCtxTableLastIndex
--;
217 /******************************************************************************
218 * BindCtx_ReleaseBoundObjects
219 ******************************************************************************/
220 static HRESULT WINAPI
221 BindCtxImpl_ReleaseBoundObjects(IBindCtx
* iface
)
225 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
227 TRACE("(%p)\n",This
);
229 for(i
=0;i
<This
->bindCtxTableLastIndex
;i
++)
231 if(This
->bindCtxTable
[i
].pObj
)
232 IUnknown_Release(This
->bindCtxTable
[i
].pObj
);
233 HeapFree(GetProcessHeap(),0,This
->bindCtxTable
[i
].pkeyObj
);
236 This
->bindCtxTableLastIndex
= 0;
241 /******************************************************************************
242 * BindCtx_SetBindOptions
243 ******************************************************************************/
244 static HRESULT WINAPI
245 BindCtxImpl_SetBindOptions(IBindCtx
* iface
,BIND_OPTS
*pbindopts
)
247 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
249 TRACE("(%p,%p)\n",This
, pbindopts
);
254 if (pbindopts
->cbStruct
> sizeof(This
->options
))
256 WARN("invalid size %u.\n", pbindopts
->cbStruct
);
259 memcpy(&This
->options
, pbindopts
, pbindopts
->cbStruct
);
263 /******************************************************************************
264 * BindCtx_GetBindOptions
265 ******************************************************************************/
266 static HRESULT WINAPI
267 BindCtxImpl_GetBindOptions(IBindCtx
* iface
,BIND_OPTS
*pbindopts
)
269 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
272 TRACE("(%p,%p)\n",This
,pbindopts
);
277 size
= min(pbindopts
->cbStruct
, sizeof(This
->options
));
278 memcpy(pbindopts
, &This
->options
, size
);
279 pbindopts
->cbStruct
= size
;
284 /******************************************************************************
285 * BindCtx_GetRunningObjectTable
286 ******************************************************************************/
287 static HRESULT WINAPI
288 BindCtxImpl_GetRunningObjectTable(IBindCtx
* iface
,IRunningObjectTable
** pprot
)
290 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
292 TRACE("(%p,%p)\n",This
,pprot
);
297 return GetRunningObjectTable(0, pprot
);
300 /******************************************************************************
301 * BindCtx_RegisterObjectParam
302 ******************************************************************************/
303 static HRESULT WINAPI
304 BindCtxImpl_RegisterObjectParam(IBindCtx
* iface
,LPOLESTR pszkey
, IUnknown
* punk
)
307 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
309 TRACE("(%p,%s,%p)\n",This
,debugstr_w(pszkey
),punk
);
314 if (pszkey
!=NULL
&& BindCtxImpl_GetObjectIndex(This
,NULL
,pszkey
,&index
)==S_OK
)
316 TRACE("Overwriting existing key\n");
317 if(This
->bindCtxTable
[index
].pObj
!=NULL
)
318 IUnknown_Release(This
->bindCtxTable
[index
].pObj
);
319 This
->bindCtxTable
[index
].pObj
=punk
;
320 IUnknown_AddRef(punk
);
324 if (This
->bindCtxTableLastIndex
== This
->bindCtxTableSize
)
326 HRESULT hr
= BindCtxImpl_ExpandTable(This
);
331 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pObj
= punk
;
332 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].regType
= 1;
336 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
=NULL
;
341 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
=
342 HeapAlloc(GetProcessHeap(),0,(sizeof(WCHAR
)*(1+lstrlenW(pszkey
))));
344 if (This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
==NULL
)
345 return E_OUTOFMEMORY
;
346 lstrcpyW(This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
,pszkey
);
349 This
->bindCtxTableLastIndex
++;
351 IUnknown_AddRef(punk
);
355 /******************************************************************************
356 * BindCtx_GetObjectParam
357 ******************************************************************************/
358 static HRESULT WINAPI
359 BindCtxImpl_GetObjectParam(IBindCtx
* iface
,LPOLESTR pszkey
, IUnknown
** punk
)
362 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
364 TRACE("(%p,%s,%p)\n",This
,debugstr_w(pszkey
),punk
);
371 if (BindCtxImpl_GetObjectIndex(This
,NULL
,pszkey
,&index
)==S_FALSE
)
374 IUnknown_AddRef(This
->bindCtxTable
[index
].pObj
);
376 *punk
= This
->bindCtxTable
[index
].pObj
;
381 /******************************************************************************
382 * BindCtx_RevokeObjectParam
383 ******************************************************************************/
384 static HRESULT WINAPI
385 BindCtxImpl_RevokeObjectParam(IBindCtx
* iface
,LPOLESTR ppenum
)
389 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
391 TRACE("(%p,%s)\n",This
,debugstr_w(ppenum
));
393 if (BindCtxImpl_GetObjectIndex(This
,NULL
,ppenum
,&index
)==S_FALSE
)
396 /* release the object if it's found */
397 if(This
->bindCtxTable
[index
].pObj
)
398 IUnknown_Release(This
->bindCtxTable
[index
].pObj
);
399 HeapFree(GetProcessHeap(),0,This
->bindCtxTable
[index
].pkeyObj
);
401 /* remove the object from the table with a left-shifting of all objects in the right side */
402 for(j
=index
; j
<This
->bindCtxTableLastIndex
-1; j
++)
403 This
->bindCtxTable
[j
]= This
->bindCtxTable
[j
+1];
405 This
->bindCtxTableLastIndex
--;
410 /******************************************************************************
411 * BindCtx_EnumObjectParam
412 ******************************************************************************/
413 static HRESULT WINAPI
414 BindCtxImpl_EnumObjectParam(IBindCtx
* iface
,IEnumString
** pszkey
)
416 TRACE("(%p,%p)\n",iface
,pszkey
);
420 /* not implemented in native either */
424 /********************************************************************************
425 * GetObjectIndex (local function)
426 ********************************************************************************/
427 static HRESULT
BindCtxImpl_GetObjectIndex(BindCtxImpl
* This
,
435 TRACE("(%p,%p,%p,%p)\n",This
,punk
,pszkey
,index
);
438 /* search object identified by a register key */
439 for(i
=0; ( (i
<This
->bindCtxTableLastIndex
) && (!found
));i
++)
441 if(This
->bindCtxTable
[i
].regType
==1){
443 if ( ( (This
->bindCtxTable
[i
].pkeyObj
==NULL
) && (pszkey
==NULL
) ) ||
444 ( (This
->bindCtxTable
[i
].pkeyObj
!=NULL
) &&
446 (wcscmp(This
->bindCtxTable
[i
].pkeyObj
,pszkey
)==0)
454 /* search object identified by a moniker*/
455 for(i
=0; ( (i
<This
->bindCtxTableLastIndex
) && (!found
));i
++)
456 if(This
->bindCtxTable
[i
].pObj
==punk
)
464 TRACE("key not found\n");
468 static HRESULT
BindCtxImpl_ExpandTable(BindCtxImpl
*This
)
470 if (!This
->bindCtxTableSize
)
472 This
->bindCtxTableSize
= BINDCTX_FIRST_TABLE_SIZE
;
473 This
->bindCtxTable
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
474 This
->bindCtxTableSize
* sizeof(BindCtxObject
));
478 This
->bindCtxTableSize
*= 2;
480 This
->bindCtxTable
= HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,This
->bindCtxTable
,
481 This
->bindCtxTableSize
* sizeof(BindCtxObject
));
484 if (!This
->bindCtxTable
)
485 return E_OUTOFMEMORY
;
491 /* Virtual function table for the BindCtx class. */
492 static const IBindCtxVtbl VT_BindCtxImpl
=
494 BindCtxImpl_QueryInterface
,
497 BindCtxImpl_RegisterObjectBound
,
498 BindCtxImpl_RevokeObjectBound
,
499 BindCtxImpl_ReleaseBoundObjects
,
500 BindCtxImpl_SetBindOptions
,
501 BindCtxImpl_GetBindOptions
,
502 BindCtxImpl_GetRunningObjectTable
,
503 BindCtxImpl_RegisterObjectParam
,
504 BindCtxImpl_GetObjectParam
,
505 BindCtxImpl_EnumObjectParam
,
506 BindCtxImpl_RevokeObjectParam
509 /******************************************************************************
510 * BindCtx_Construct (local function)
511 *******************************************************************************/
512 static HRESULT
BindCtxImpl_Construct(BindCtxImpl
* This
)
514 TRACE("(%p)\n",This
);
516 /* Initialize the virtual function table.*/
517 This
->IBindCtx_iface
.lpVtbl
= &VT_BindCtxImpl
;
520 memset(&This
->options
, 0, sizeof(This
->options
));
521 This
->options
.cbStruct
= sizeof(This
->options
);
522 This
->options
.grfMode
= STGM_READWRITE
;
523 This
->options
.dwClassContext
= CLSCTX_SERVER
;
524 This
->options
.locale
= GetThreadLocale();
526 /* Initialize the bindctx table */
527 This
->bindCtxTableSize
=0;
528 This
->bindCtxTableLastIndex
=0;
529 This
->bindCtxTable
= NULL
;
534 /******************************************************************************
535 * CreateBindCtx (OLE32.@)
537 * Creates a bind context. A bind context encompasses information and options
538 * used when binding to a moniker.
541 * reserved [I] Reserved. Set to 0.
542 * ppbc [O] Address that receives the bind context object.
546 * Failure: Any HRESULT code.
548 HRESULT WINAPI
CreateBindCtx(DWORD reserved
, LPBC
* ppbc
)
550 BindCtxImpl
* newBindCtx
;
553 TRACE("(%d,%p)\n",reserved
,ppbc
);
555 if (!ppbc
) return E_INVALIDARG
;
561 ERR("reserved should be 0, not 0x%x\n", reserved
);
565 newBindCtx
= HeapAlloc(GetProcessHeap(), 0, sizeof(BindCtxImpl
));
567 return E_OUTOFMEMORY
;
569 hr
= BindCtxImpl_Construct(newBindCtx
);
572 HeapFree(GetProcessHeap(),0,newBindCtx
);
576 return BindCtxImpl_QueryInterface(&newBindCtx
->IBindCtx_iface
,&IID_IBindCtx
,(void**)ppbc
);
579 /******************************************************************************
580 * BindMoniker [OLE32.@]
582 * Binds to a moniker.
585 * pmk [I] Moniker to bind to.
586 * grfOpt [I] Reserved option flags. Set to 0.
587 * riid [I] ID of the interface to bind to.
588 * pvResult [O] Address that receives the interface of the object that was bound to.
592 * Failure: Any HRESULT code.
594 HRESULT WINAPI
BindMoniker(LPMONIKER pmk
, DWORD grfOpt
, REFIID riid
, LPVOID
* ppvResult
)
599 TRACE("(%p, %x, %s, %p)\n", pmk
, grfOpt
, debugstr_guid(riid
), ppvResult
);
601 res
= CreateBindCtx(grfOpt
, &pbc
);
604 res
= IMoniker_BindToObject(pmk
, pbc
, NULL
, riid
, ppvResult
);
605 IBindCtx_Release(pbc
);