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"
33 #include "wine/heap.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
37 #define BINDCTX_FIRST_TABLE_SIZE 4
39 /* data structure of the BindCtx table elements */
40 typedef struct BindCtxObject
{
42 IUnknown
* pObj
; /* point on a bound object */
44 LPOLESTR pkeyObj
; /* key associated to this bound object */
46 BYTE regType
; /* registration type: 1 if RegisterObjectParam and 0 if RegisterObjectBound */
50 /* BindCtx data structure */
51 typedef struct BindCtxImpl
{
53 IBindCtx IBindCtx_iface
;
55 LONG ref
; /* reference counter for this object */
57 BindCtxObject
* bindCtxTable
; /* this is a table in which all bounded objects are stored*/
58 DWORD bindCtxTableLastIndex
; /* first free index in the table */
59 DWORD bindCtxTableSize
; /* size table */
65 /* IBindCtx prototype functions : */
66 static HRESULT WINAPI
BindCtxImpl_ReleaseBoundObjects(IBindCtx
*);
67 static HRESULT
BindCtxImpl_GetObjectIndex(BindCtxImpl
*, IUnknown
*, LPOLESTR
, DWORD
*);
68 static HRESULT
BindCtxImpl_ExpandTable(BindCtxImpl
*);
70 static inline BindCtxImpl
*impl_from_IBindCtx(IBindCtx
*iface
)
72 return CONTAINING_RECORD(iface
, BindCtxImpl
, IBindCtx_iface
);
75 /*******************************************************************************
76 * BindCtx_QueryInterface
77 *******************************************************************************/
79 BindCtxImpl_QueryInterface(IBindCtx
* iface
,REFIID riid
,void** ppvObject
)
81 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
83 TRACE("(%p %s %p)\n",This
, debugstr_guid(riid
), ppvObject
);
85 /* Perform a sanity check on the parameters.*/
89 /* Initialize the return parameter.*/
92 /* Compare the riid with the interface IDs implemented by this object.*/
93 if (IsEqualIID(&IID_IUnknown
, riid
) ||
94 IsEqualIID(&IID_IBindCtx
, riid
))
96 *ppvObject
= &This
->IBindCtx_iface
;
97 IBindCtx_AddRef(iface
);
101 return E_NOINTERFACE
;
104 /******************************************************************************
106 ******************************************************************************/
107 static ULONG WINAPI
BindCtxImpl_AddRef(IBindCtx
* iface
)
109 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
111 TRACE("(%p)\n",This
);
113 return InterlockedIncrement(&This
->ref
);
116 static ULONG WINAPI
BindCtxImpl_Release(IBindCtx
* iface
)
118 BindCtxImpl
*context
= impl_from_IBindCtx(iface
);
119 ULONG refcount
= InterlockedDecrement(&context
->ref
);
121 TRACE("%p, refcount %lu.\n", iface
, refcount
);
125 BindCtxImpl_ReleaseBoundObjects(&context
->IBindCtx_iface
);
126 heap_free(context
->bindCtxTable
);
134 /******************************************************************************
135 * BindCtx_RegisterObjectBound
136 ******************************************************************************/
137 static HRESULT WINAPI
138 BindCtxImpl_RegisterObjectBound(IBindCtx
* iface
,IUnknown
* punk
)
140 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
141 DWORD lastIndex
=This
->bindCtxTableLastIndex
;
143 TRACE("(%p,%p)\n",This
,punk
);
148 if (lastIndex
== This
->bindCtxTableSize
)
150 HRESULT hr
= BindCtxImpl_ExpandTable(This
);
155 IUnknown_AddRef(punk
);
157 /* put the object in the first free element in the table */
158 This
->bindCtxTable
[lastIndex
].pObj
= punk
;
159 This
->bindCtxTable
[lastIndex
].pkeyObj
= NULL
;
160 This
->bindCtxTable
[lastIndex
].regType
= 0;
161 lastIndex
= ++This
->bindCtxTableLastIndex
;
166 /******************************************************************************
167 * BindCtx_RevokeObjectBound
168 ******************************************************************************/
169 static HRESULT WINAPI
170 BindCtxImpl_RevokeObjectBound(IBindCtx
* iface
, IUnknown
* punk
)
174 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
176 TRACE("(%p,%p)\n",This
,punk
);
181 /* check if the object was registered or not */
182 if (BindCtxImpl_GetObjectIndex(This
,punk
,NULL
,&index
)==S_FALSE
)
183 return MK_E_NOTBOUND
;
185 if(This
->bindCtxTable
[index
].pObj
)
186 IUnknown_Release(This
->bindCtxTable
[index
].pObj
);
187 HeapFree(GetProcessHeap(),0,This
->bindCtxTable
[index
].pkeyObj
);
189 /* left-shift all elements in the right side of the current revoked object */
190 for(j
=index
; j
<This
->bindCtxTableLastIndex
-1; j
++)
191 This
->bindCtxTable
[j
]= This
->bindCtxTable
[j
+1];
193 This
->bindCtxTableLastIndex
--;
198 /******************************************************************************
199 * BindCtx_ReleaseBoundObjects
200 ******************************************************************************/
201 static HRESULT WINAPI
202 BindCtxImpl_ReleaseBoundObjects(IBindCtx
* iface
)
206 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
208 TRACE("(%p)\n",This
);
210 for(i
=0;i
<This
->bindCtxTableLastIndex
;i
++)
212 if(This
->bindCtxTable
[i
].pObj
)
213 IUnknown_Release(This
->bindCtxTable
[i
].pObj
);
214 HeapFree(GetProcessHeap(),0,This
->bindCtxTable
[i
].pkeyObj
);
217 This
->bindCtxTableLastIndex
= 0;
222 /******************************************************************************
223 * BindCtx_SetBindOptions
224 ******************************************************************************/
225 static HRESULT WINAPI
226 BindCtxImpl_SetBindOptions(IBindCtx
* iface
,BIND_OPTS
*pbindopts
)
228 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
230 TRACE("(%p,%p)\n",This
, pbindopts
);
235 if (pbindopts
->cbStruct
> sizeof(This
->options
))
237 WARN("invalid size %lu.\n", pbindopts
->cbStruct
);
240 memcpy(&This
->options
, pbindopts
, pbindopts
->cbStruct
);
244 /******************************************************************************
245 * BindCtx_GetBindOptions
246 ******************************************************************************/
247 static HRESULT WINAPI
248 BindCtxImpl_GetBindOptions(IBindCtx
* iface
,BIND_OPTS
*pbindopts
)
250 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
253 TRACE("(%p,%p)\n",This
,pbindopts
);
258 size
= min(pbindopts
->cbStruct
, sizeof(This
->options
));
259 memcpy(pbindopts
, &This
->options
, size
);
260 pbindopts
->cbStruct
= size
;
265 /******************************************************************************
266 * BindCtx_GetRunningObjectTable
267 ******************************************************************************/
268 static HRESULT WINAPI
269 BindCtxImpl_GetRunningObjectTable(IBindCtx
* iface
,IRunningObjectTable
** pprot
)
271 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
273 TRACE("(%p,%p)\n",This
,pprot
);
278 return GetRunningObjectTable(0, pprot
);
281 /******************************************************************************
282 * BindCtx_RegisterObjectParam
283 ******************************************************************************/
284 static HRESULT WINAPI
285 BindCtxImpl_RegisterObjectParam(IBindCtx
* iface
,LPOLESTR pszkey
, IUnknown
* punk
)
288 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
290 TRACE("(%p,%s,%p)\n",This
,debugstr_w(pszkey
),punk
);
295 if (pszkey
!=NULL
&& BindCtxImpl_GetObjectIndex(This
,NULL
,pszkey
,&index
)==S_OK
)
297 TRACE("Overwriting existing key\n");
298 if(This
->bindCtxTable
[index
].pObj
!=NULL
)
299 IUnknown_Release(This
->bindCtxTable
[index
].pObj
);
300 This
->bindCtxTable
[index
].pObj
=punk
;
301 IUnknown_AddRef(punk
);
305 if (This
->bindCtxTableLastIndex
== This
->bindCtxTableSize
)
307 HRESULT hr
= BindCtxImpl_ExpandTable(This
);
312 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pObj
= punk
;
313 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].regType
= 1;
317 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
=NULL
;
322 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
=
323 HeapAlloc(GetProcessHeap(),0,(sizeof(WCHAR
)*(1+lstrlenW(pszkey
))));
325 if (This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
==NULL
)
326 return E_OUTOFMEMORY
;
327 lstrcpyW(This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
,pszkey
);
330 This
->bindCtxTableLastIndex
++;
332 IUnknown_AddRef(punk
);
336 /******************************************************************************
337 * BindCtx_GetObjectParam
338 ******************************************************************************/
339 static HRESULT WINAPI
340 BindCtxImpl_GetObjectParam(IBindCtx
* iface
,LPOLESTR pszkey
, IUnknown
** punk
)
343 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
345 TRACE("(%p,%s,%p)\n",This
,debugstr_w(pszkey
),punk
);
352 if (BindCtxImpl_GetObjectIndex(This
,NULL
,pszkey
,&index
)==S_FALSE
)
355 IUnknown_AddRef(This
->bindCtxTable
[index
].pObj
);
357 *punk
= This
->bindCtxTable
[index
].pObj
;
362 /******************************************************************************
363 * BindCtx_RevokeObjectParam
364 ******************************************************************************/
365 static HRESULT WINAPI
366 BindCtxImpl_RevokeObjectParam(IBindCtx
* iface
,LPOLESTR ppenum
)
370 BindCtxImpl
*This
= impl_from_IBindCtx(iface
);
372 TRACE("(%p,%s)\n",This
,debugstr_w(ppenum
));
374 if (BindCtxImpl_GetObjectIndex(This
,NULL
,ppenum
,&index
)==S_FALSE
)
377 /* release the object if it's found */
378 if(This
->bindCtxTable
[index
].pObj
)
379 IUnknown_Release(This
->bindCtxTable
[index
].pObj
);
380 HeapFree(GetProcessHeap(),0,This
->bindCtxTable
[index
].pkeyObj
);
382 /* remove the object from the table with a left-shifting of all objects in the right side */
383 for(j
=index
; j
<This
->bindCtxTableLastIndex
-1; j
++)
384 This
->bindCtxTable
[j
]= This
->bindCtxTable
[j
+1];
386 This
->bindCtxTableLastIndex
--;
391 /******************************************************************************
392 * BindCtx_EnumObjectParam
393 ******************************************************************************/
394 static HRESULT WINAPI
395 BindCtxImpl_EnumObjectParam(IBindCtx
* iface
,IEnumString
** pszkey
)
397 TRACE("(%p,%p)\n",iface
,pszkey
);
401 /* not implemented in native either */
405 /********************************************************************************
406 * GetObjectIndex (local function)
407 ********************************************************************************/
408 static HRESULT
BindCtxImpl_GetObjectIndex(BindCtxImpl
* This
,
416 TRACE("(%p,%p,%p,%p)\n",This
,punk
,pszkey
,index
);
419 /* search object identified by a register key */
420 for(i
=0; ( (i
<This
->bindCtxTableLastIndex
) && (!found
));i
++)
422 if(This
->bindCtxTable
[i
].regType
==1){
424 if ( ( (This
->bindCtxTable
[i
].pkeyObj
==NULL
) && (pszkey
==NULL
) ) ||
425 ( (This
->bindCtxTable
[i
].pkeyObj
!=NULL
) &&
427 (wcscmp(This
->bindCtxTable
[i
].pkeyObj
,pszkey
)==0)
435 /* search object identified by a moniker*/
436 for(i
=0; ( (i
<This
->bindCtxTableLastIndex
) && (!found
));i
++)
437 if(This
->bindCtxTable
[i
].pObj
==punk
)
445 TRACE("key not found\n");
449 static HRESULT
BindCtxImpl_ExpandTable(BindCtxImpl
*This
)
451 if (!This
->bindCtxTableSize
)
453 This
->bindCtxTableSize
= BINDCTX_FIRST_TABLE_SIZE
;
454 This
->bindCtxTable
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,
455 This
->bindCtxTableSize
* sizeof(BindCtxObject
));
459 This
->bindCtxTableSize
*= 2;
461 This
->bindCtxTable
= HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,This
->bindCtxTable
,
462 This
->bindCtxTableSize
* sizeof(BindCtxObject
));
465 if (!This
->bindCtxTable
)
466 return E_OUTOFMEMORY
;
471 static const IBindCtxVtbl VT_BindCtxImpl
=
473 BindCtxImpl_QueryInterface
,
476 BindCtxImpl_RegisterObjectBound
,
477 BindCtxImpl_RevokeObjectBound
,
478 BindCtxImpl_ReleaseBoundObjects
,
479 BindCtxImpl_SetBindOptions
,
480 BindCtxImpl_GetBindOptions
,
481 BindCtxImpl_GetRunningObjectTable
,
482 BindCtxImpl_RegisterObjectParam
,
483 BindCtxImpl_GetObjectParam
,
484 BindCtxImpl_EnumObjectParam
,
485 BindCtxImpl_RevokeObjectParam
488 /******************************************************************************
489 * CreateBindCtx (OLE32.@)
491 HRESULT WINAPI
CreateBindCtx(DWORD reserved
, IBindCtx
**bind_context
)
495 TRACE("%#lx, %p.\n", reserved
, bind_context
);
497 if (!bind_context
) return E_INVALIDARG
;
499 *bind_context
= NULL
;
503 WARN("reserved should be 0, not %#lx.\n", reserved
);
507 if (!(object
= heap_alloc_zero(sizeof(*object
))))
508 return E_OUTOFMEMORY
;
510 object
->IBindCtx_iface
.lpVtbl
= &VT_BindCtxImpl
;
512 object
->options
.cbStruct
= sizeof(object
->options
);
513 object
->options
.grfMode
= STGM_READWRITE
;
514 object
->options
.dwClassContext
= CLSCTX_SERVER
;
515 object
->options
.locale
= GetThreadLocale();
517 *bind_context
= &object
->IBindCtx_iface
;
522 /******************************************************************************
523 * BindMoniker [OLE32.@]
525 * Binds to a moniker.
528 * pmk [I] Moniker to bind to.
529 * grfOpt [I] Reserved option flags. Set to 0.
530 * riid [I] ID of the interface to bind to.
531 * pvResult [O] Address that receives the interface of the object that was bound to.
535 * Failure: Any HRESULT code.
537 HRESULT WINAPI
BindMoniker(LPMONIKER pmk
, DWORD grfOpt
, REFIID riid
, LPVOID
* ppvResult
)
542 TRACE("%p, %lx, %s, %p.\n", pmk
, grfOpt
, debugstr_guid(riid
), ppvResult
);
544 res
= CreateBindCtx(grfOpt
, &pbc
);
547 res
= IMoniker_BindToObject(pmk
, pbc
, NULL
, riid
, ppvResult
);
548 IBindCtx_Release(pbc
);