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 /* represent the first size table and it's increment block size */
37 #define BLOCK_TAB_SIZE 10
38 #define MAX_TAB_SIZE 0xFFFFFFFF
40 /* data structure of the BindCtx table elements */
41 typedef struct BindCtxObject
{
43 IUnknown
* pObj
; /* point on a bound object */
45 LPOLESTR pkeyObj
; /* key associated to this bound object */
47 BYTE regType
; /* registration type: 1 if RegisterObjectParam and 0 if RegisterObjectBound */
51 /* BindCtx data strucrture */
52 typedef struct BindCtxImpl
{
54 const IBindCtxVtbl
*lpVtbl
; /* VTable relative to the IBindCtx interface.*/
56 LONG ref
; /* reference counter for this object */
58 BindCtxObject
* bindCtxTable
; /* this is a table in which all bounded objects are stored*/
59 DWORD bindCtxTableLastIndex
; /* first free index in the table */
60 DWORD bindCtxTableSize
; /* size table */
62 BIND_OPTS2 bindOption2
; /* a structure which contains the bind options*/
66 /* IBindCtx prototype functions : */
67 static HRESULT WINAPI
BindCtxImpl_ReleaseBoundObjects(IBindCtx
*);
68 static HRESULT
BindCtxImpl_GetObjectIndex(BindCtxImpl
*, IUnknown
*, LPOLESTR
, DWORD
*);
70 /*******************************************************************************
71 * BindCtx_QueryInterface
72 *******************************************************************************/
74 BindCtxImpl_QueryInterface(IBindCtx
* iface
,REFIID riid
,void** ppvObject
)
76 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
78 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
80 /* Perform a sanity check on the parameters.*/
81 if ( (This
==0) || (ppvObject
==0) )
84 /* Initialize the return parameter.*/
87 /* Compare the riid with the interface IDs implemented by this object.*/
88 if (IsEqualIID(&IID_IUnknown
, riid
) ||
89 IsEqualIID(&IID_IBindCtx
, riid
))
91 *ppvObject
= (IBindCtx
*)This
;
92 IBindCtx_AddRef(iface
);
99 /******************************************************************************
101 ******************************************************************************/
102 static ULONG WINAPI
BindCtxImpl_AddRef(IBindCtx
* iface
)
104 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
106 TRACE("(%p)\n",This
);
108 return InterlockedIncrement(&This
->ref
);
111 /******************************************************************************
112 * BindCtx_Destroy (local function)
113 *******************************************************************************/
114 static HRESULT
BindCtxImpl_Destroy(BindCtxImpl
* This
)
116 TRACE("(%p)\n",This
);
118 /* free the table space memory */
119 HeapFree(GetProcessHeap(),0,This
->bindCtxTable
);
121 /* free the bindctx structure */
122 HeapFree(GetProcessHeap(),0,This
);
127 /******************************************************************************
129 ******************************************************************************/
130 static ULONG WINAPI
BindCtxImpl_Release(IBindCtx
* iface
)
132 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
135 TRACE("(%p)\n",This
);
137 ref
= InterlockedDecrement(&This
->ref
);
140 /* release all registered objects */
141 BindCtxImpl_ReleaseBoundObjects((IBindCtx
*)This
);
143 BindCtxImpl_Destroy(This
);
149 /******************************************************************************
150 * BindCtx_RegisterObjectBound
151 ******************************************************************************/
152 static HRESULT WINAPI
153 BindCtxImpl_RegisterObjectBound(IBindCtx
* iface
,IUnknown
* punk
)
155 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
156 DWORD lastIndex
=This
->bindCtxTableLastIndex
;
158 TRACE("(%p,%p)\n",This
,punk
);
163 IUnknown_AddRef(punk
);
165 /* put the object in the first free element in the table */
166 This
->bindCtxTable
[lastIndex
].pObj
= punk
;
167 This
->bindCtxTable
[lastIndex
].pkeyObj
= NULL
;
168 This
->bindCtxTable
[lastIndex
].regType
= 0;
169 lastIndex
= ++This
->bindCtxTableLastIndex
;
171 if (lastIndex
== This
->bindCtxTableSize
){ /* the table is full so it must be resized */
173 if (This
->bindCtxTableSize
> (MAX_TAB_SIZE
-BLOCK_TAB_SIZE
)){
174 FIXME("This->bindCtxTableSize: %d is out of data limite\n", This
->bindCtxTableSize
);
178 This
->bindCtxTableSize
+=BLOCK_TAB_SIZE
; /* new table size */
180 This
->bindCtxTable
= HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,This
->bindCtxTable
,
181 This
->bindCtxTableSize
* sizeof(BindCtxObject
));
182 if (!This
->bindCtxTable
)
183 return E_OUTOFMEMORY
;
188 /******************************************************************************
189 * BindCtx_RevokeObjectBound
190 ******************************************************************************/
191 static HRESULT WINAPI
192 BindCtxImpl_RevokeObjectBound(IBindCtx
* iface
, IUnknown
* punk
)
196 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
198 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
= (BindCtxImpl
*)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
= (BindCtxImpl
*)iface
;
249 TRACE("(%p,%p)\n",This
,pbindopts
);
254 if (pbindopts
->cbStruct
> sizeof(BIND_OPTS2
))
256 WARN("invalid size\n");
257 return E_INVALIDARG
; /* FIXME : not verified */
259 memcpy(&This
->bindOption2
, pbindopts
, pbindopts
->cbStruct
);
263 /******************************************************************************
264 * BindCtx_GetBindOptions
265 ******************************************************************************/
266 static HRESULT WINAPI
267 BindCtxImpl_GetBindOptions(IBindCtx
* iface
,BIND_OPTS
*pbindopts
)
269 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
272 TRACE("(%p,%p)\n",This
,pbindopts
);
277 cbStruct
= pbindopts
->cbStruct
;
278 if (cbStruct
> sizeof(BIND_OPTS2
))
279 cbStruct
= sizeof(BIND_OPTS2
);
281 memcpy(pbindopts
, &This
->bindOption2
, cbStruct
);
282 pbindopts
->cbStruct
= cbStruct
;
287 /******************************************************************************
288 * BindCtx_GetRunningObjectTable
289 ******************************************************************************/
290 static HRESULT WINAPI
291 BindCtxImpl_GetRunningObjectTable(IBindCtx
* iface
,IRunningObjectTable
** pprot
)
295 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
297 TRACE("(%p,%p)\n",This
,pprot
);
302 res
=GetRunningObjectTable(0, pprot
);
307 /******************************************************************************
308 * BindCtx_RegisterObjectParam
309 ******************************************************************************/
310 static HRESULT WINAPI
311 BindCtxImpl_RegisterObjectParam(IBindCtx
* iface
,LPOLESTR pszkey
, IUnknown
* punk
)
314 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
316 TRACE("(%p,%s,%p)\n",This
,debugstr_w(pszkey
),punk
);
321 if (pszkey
!=NULL
&& BindCtxImpl_GetObjectIndex(This
,NULL
,pszkey
,&index
)==S_OK
)
323 TRACE("Overwriting existing key\n");
324 if(This
->bindCtxTable
[index
].pObj
!=NULL
)
325 IUnknown_Release(This
->bindCtxTable
[index
].pObj
);
326 This
->bindCtxTable
[index
].pObj
=punk
;
327 IUnknown_AddRef(punk
);
330 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pObj
= punk
;
331 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].regType
= 1;
335 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
=NULL
;
340 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
=
341 HeapAlloc(GetProcessHeap(),0,(sizeof(WCHAR
)*(1+lstrlenW(pszkey
))));
343 if (This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
==NULL
)
344 return E_OUTOFMEMORY
;
345 lstrcpyW(This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
,pszkey
);
348 This
->bindCtxTableLastIndex
++;
350 if (This
->bindCtxTableLastIndex
== This
->bindCtxTableSize
)
352 /* table is full ! must be resized */
354 This
->bindCtxTableSize
+=BLOCK_TAB_SIZE
; /* new table size */
355 if (This
->bindCtxTableSize
> (MAX_TAB_SIZE
-BLOCK_TAB_SIZE
))
357 FIXME("This->bindCtxTableSize: %d is out of data limite\n", This
->bindCtxTableSize
);
360 This
->bindCtxTable
= HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,This
->bindCtxTable
,
361 This
->bindCtxTableSize
* sizeof(BindCtxObject
));
362 if (!This
->bindCtxTable
)
363 return E_OUTOFMEMORY
;
365 IUnknown_AddRef(punk
);
369 /******************************************************************************
370 * BindCtx_GetObjectParam
371 ******************************************************************************/
372 static HRESULT WINAPI
373 BindCtxImpl_GetObjectParam(IBindCtx
* iface
,LPOLESTR pszkey
, IUnknown
** punk
)
376 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
378 TRACE("(%p,%s,%p)\n",This
,debugstr_w(pszkey
),punk
);
385 if (BindCtxImpl_GetObjectIndex(This
,NULL
,pszkey
,&index
)==S_FALSE
)
388 IUnknown_AddRef(This
->bindCtxTable
[index
].pObj
);
390 *punk
= This
->bindCtxTable
[index
].pObj
;
395 /******************************************************************************
396 * BindCtx_RevokeObjectParam
397 ******************************************************************************/
398 static HRESULT WINAPI
399 BindCtxImpl_RevokeObjectParam(IBindCtx
* iface
,LPOLESTR ppenum
)
403 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
405 TRACE("(%p,%s)\n",This
,debugstr_w(ppenum
));
407 if (BindCtxImpl_GetObjectIndex(This
,NULL
,ppenum
,&index
)==S_FALSE
)
410 /* release the object if it's found */
411 if(This
->bindCtxTable
[index
].pObj
)
412 IUnknown_Release(This
->bindCtxTable
[index
].pObj
);
413 HeapFree(GetProcessHeap(),0,This
->bindCtxTable
[index
].pkeyObj
);
415 /* remove the object from the table with a left-shifting of all objects in the right side */
416 for(j
=index
; j
<This
->bindCtxTableLastIndex
-1; j
++)
417 This
->bindCtxTable
[j
]= This
->bindCtxTable
[j
+1];
419 This
->bindCtxTableLastIndex
--;
424 /******************************************************************************
425 * BindCtx_EnumObjectParam
426 ******************************************************************************/
427 static HRESULT WINAPI
428 BindCtxImpl_EnumObjectParam(IBindCtx
* iface
,IEnumString
** pszkey
)
430 TRACE("(%p,%p)\n",iface
,pszkey
);
434 /* not implemented in native either */
438 /********************************************************************************
439 * GetObjectIndex (local function)
440 ********************************************************************************/
441 static HRESULT
BindCtxImpl_GetObjectIndex(BindCtxImpl
* This
,
450 TRACE("(%p,%p,%p,%p)\n",This
,punk
,pszkey
,index
);
453 /* search object identified by a register key */
454 for(i
=0; ( (i
<This
->bindCtxTableLastIndex
) && (!found
));i
++)
456 if(This
->bindCtxTable
[i
].regType
==1){
458 if ( ( (This
->bindCtxTable
[i
].pkeyObj
==NULL
) && (pszkey
==NULL
) ) ||
459 ( (This
->bindCtxTable
[i
].pkeyObj
!=NULL
) &&
461 (lstrcmpW(This
->bindCtxTable
[i
].pkeyObj
,pszkey
)==0)
469 /* search object identified by a moniker*/
470 for(i
=0; ( (i
<This
->bindCtxTableLastIndex
) && (!found
));i
++)
471 if(This
->bindCtxTable
[i
].pObj
==punk
)
479 TRACE("key not found\n");
483 /* Virtual function table for the BindCtx class. */
484 static const IBindCtxVtbl VT_BindCtxImpl
=
486 BindCtxImpl_QueryInterface
,
489 BindCtxImpl_RegisterObjectBound
,
490 BindCtxImpl_RevokeObjectBound
,
491 BindCtxImpl_ReleaseBoundObjects
,
492 BindCtxImpl_SetBindOptions
,
493 BindCtxImpl_GetBindOptions
,
494 BindCtxImpl_GetRunningObjectTable
,
495 BindCtxImpl_RegisterObjectParam
,
496 BindCtxImpl_GetObjectParam
,
497 BindCtxImpl_EnumObjectParam
,
498 BindCtxImpl_RevokeObjectParam
501 /******************************************************************************
502 * BindCtx_Construct (local function)
503 *******************************************************************************/
504 static HRESULT
BindCtxImpl_Construct(BindCtxImpl
* This
)
506 TRACE("(%p)\n",This
);
508 /* Initialize the virtual function table.*/
509 This
->lpVtbl
= &VT_BindCtxImpl
;
512 /* Initialize the BIND_OPTS2 structure */
513 This
->bindOption2
.cbStruct
= sizeof(BIND_OPTS2
);
514 This
->bindOption2
.grfFlags
= 0;
515 This
->bindOption2
.grfMode
= STGM_READWRITE
;
516 This
->bindOption2
.dwTickCountDeadline
= 0;
518 This
->bindOption2
.dwTrackFlags
= 0;
519 This
->bindOption2
.dwClassContext
= CLSCTX_SERVER
;
520 This
->bindOption2
.locale
= GetThreadLocale();
521 This
->bindOption2
.pServerInfo
= 0;
523 /* Initialize the bindctx table */
524 This
->bindCtxTableSize
=BLOCK_TAB_SIZE
;
525 This
->bindCtxTableLastIndex
=0;
526 This
->bindCtxTable
= HeapAlloc(GetProcessHeap(), 0,
527 This
->bindCtxTableSize
*sizeof(BindCtxObject
));
529 if (This
->bindCtxTable
==NULL
)
530 return E_OUTOFMEMORY
;
535 /******************************************************************************
536 * CreateBindCtx (OLE32.@)
537 ******************************************************************************/
538 HRESULT WINAPI
CreateBindCtx(DWORD reserved
, LPBC
* ppbc
)
540 BindCtxImpl
* newBindCtx
= 0;
542 IID riid
=IID_IBindCtx
;
544 TRACE("(%d,%p)\n",reserved
,ppbc
);
546 if (!ppbc
) return E_INVALIDARG
;
552 ERR("reserved should be 0, not 0x%x\n", reserved
);
556 newBindCtx
= HeapAlloc(GetProcessHeap(), 0, sizeof(BindCtxImpl
));
558 return E_OUTOFMEMORY
;
560 hr
= BindCtxImpl_Construct(newBindCtx
);
563 HeapFree(GetProcessHeap(),0,newBindCtx
);
567 hr
= BindCtxImpl_QueryInterface((IBindCtx
*)newBindCtx
,&riid
,(void**)ppbc
);
572 HRESULT WINAPI
BindMoniker(LPMONIKER pmk
, DWORD grfOpt
, REFIID riid
, LPVOID
* ppvResult
)
577 TRACE("(%p, %x, %s, %p)\n", pmk
, grfOpt
, debugstr_guid(riid
), ppvResult
);
579 res
= CreateBindCtx(grfOpt
, &pbc
);
581 res
= IMoniker_BindToObject(pmk
, pbc
, NULL
, riid
, ppvResult
);