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
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
35 /* represent the first size table and it's increment block size */
36 #define BLOCK_TAB_SIZE 10
37 #define MAX_TAB_SIZE 0xFFFFFFFF
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 strucrture */
51 typedef struct BindCtxImpl
{
53 const IBindCtxVtbl
*lpVtbl
; /* VTable relative to the IBindCtx interface.*/
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 */
61 BIND_OPTS2 bindOption2
; /* a structure which contains the bind options*/
65 /* IBindCtx prototype functions : */
66 static HRESULT WINAPI
BindCtxImpl_ReleaseBoundObjects(IBindCtx
*);
67 static HRESULT
BindCtxImpl_GetObjectIndex(BindCtxImpl
*, IUnknown
*, LPOLESTR
, DWORD
*);
69 /*******************************************************************************
70 * BindCtx_QueryInterface
71 *******************************************************************************/
73 BindCtxImpl_QueryInterface(IBindCtx
* iface
,REFIID riid
,void** ppvObject
)
75 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
77 TRACE("(%p,%p,%p)\n",This
,riid
,ppvObject
);
79 /* Perform a sanity check on the parameters.*/
80 if ( (This
==0) || (ppvObject
==0) )
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 IUnknown_AddRef(punk
);
164 /* put the object in the first free element in the table */
165 This
->bindCtxTable
[lastIndex
].pObj
= punk
;
166 This
->bindCtxTable
[lastIndex
].pkeyObj
= NULL
;
167 This
->bindCtxTable
[lastIndex
].regType
= 0;
168 lastIndex
= ++This
->bindCtxTableLastIndex
;
170 if (lastIndex
== This
->bindCtxTableSize
){ /* the table is full so it must be resized */
172 if (This
->bindCtxTableSize
> (MAX_TAB_SIZE
-BLOCK_TAB_SIZE
)){
173 FIXME("This->bindCtxTableSize: %ld is out of data limite\n", This
->bindCtxTableSize
);
177 This
->bindCtxTableSize
+=BLOCK_TAB_SIZE
; /* new table size */
179 This
->bindCtxTable
= HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,This
->bindCtxTable
,
180 This
->bindCtxTableSize
* sizeof(BindCtxObject
));
181 if (!This
->bindCtxTable
)
182 return E_OUTOFMEMORY
;
187 /******************************************************************************
188 * BindCtx_RevokeObjectBound
189 ******************************************************************************/
190 static HRESULT WINAPI
191 BindCtxImpl_RevokeObjectBound(IBindCtx
* iface
, IUnknown
* punk
)
195 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
197 TRACE("(%p,%p)\n",This
,punk
);
199 /* check if the object was registered or not */
200 if (BindCtxImpl_GetObjectIndex(This
,punk
,NULL
,&index
)==S_FALSE
)
201 return MK_E_NOTBOUND
;
203 if(This
->bindCtxTable
[index
].pObj
)
204 IUnknown_Release(This
->bindCtxTable
[index
].pObj
);
205 HeapFree(GetProcessHeap(),0,This
->bindCtxTable
[index
].pkeyObj
);
207 /* left-shift all elements in the right side of the current revoked object */
208 for(j
=index
; j
<This
->bindCtxTableLastIndex
-1; j
++)
209 This
->bindCtxTable
[j
]= This
->bindCtxTable
[j
+1];
211 This
->bindCtxTableLastIndex
--;
216 /******************************************************************************
217 * BindCtx_ReleaseBoundObjects
218 ******************************************************************************/
219 static HRESULT WINAPI
220 BindCtxImpl_ReleaseBoundObjects(IBindCtx
* iface
)
224 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
226 TRACE("(%p)\n",This
);
228 for(i
=0;i
<This
->bindCtxTableLastIndex
;i
++)
230 if(This
->bindCtxTable
[i
].pObj
)
231 IUnknown_Release(This
->bindCtxTable
[i
].pObj
);
232 HeapFree(GetProcessHeap(),0,This
->bindCtxTable
[i
].pkeyObj
);
235 This
->bindCtxTableLastIndex
= 0;
240 /******************************************************************************
241 * BindCtx_SetBindOptions
242 ******************************************************************************/
243 static HRESULT WINAPI
244 BindCtxImpl_SetBindOptions(IBindCtx
* iface
,BIND_OPTS
*pbindopts
)
246 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
248 TRACE("(%p,%p)\n",This
,pbindopts
);
253 if (pbindopts
->cbStruct
> sizeof(BIND_OPTS2
))
255 WARN("invalid size\n");
256 return E_INVALIDARG
; /* FIXME : not verified */
258 memcpy(&This
->bindOption2
, pbindopts
, pbindopts
->cbStruct
);
262 /******************************************************************************
263 * BindCtx_GetBindOptions
264 ******************************************************************************/
265 static HRESULT WINAPI
266 BindCtxImpl_GetBindOptions(IBindCtx
* iface
,BIND_OPTS
*pbindopts
)
268 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
270 TRACE("(%p,%p)\n",This
,pbindopts
);
275 if (pbindopts
->cbStruct
> sizeof(BIND_OPTS2
))
277 WARN("invalid size\n");
278 return E_INVALIDARG
; /* FIXME : not verified */
280 memcpy(pbindopts
, &This
->bindOption2
, pbindopts
->cbStruct
);
284 /******************************************************************************
285 * BindCtx_GetRunningObjectTable
286 ******************************************************************************/
287 static HRESULT WINAPI
288 BindCtxImpl_GetRunningObjectTable(IBindCtx
* iface
,IRunningObjectTable
** pprot
)
292 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
294 TRACE("(%p,%p)\n",This
,pprot
);
299 res
=GetRunningObjectTable(0, pprot
);
304 /******************************************************************************
305 * BindCtx_RegisterObjectParam
306 ******************************************************************************/
307 static HRESULT WINAPI
308 BindCtxImpl_RegisterObjectParam(IBindCtx
* iface
,LPOLESTR pszkey
, IUnknown
* punk
)
311 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
313 TRACE("(%p,%s,%p)\n",This
,debugstr_w(pszkey
),punk
);
318 if (pszkey
!=NULL
&& BindCtxImpl_GetObjectIndex(This
,NULL
,pszkey
,&index
)==S_OK
)
320 TRACE("Overwriting existing key\n");
321 if(This
->bindCtxTable
[index
].pObj
!=NULL
)
322 IUnknown_Release(This
->bindCtxTable
[index
].pObj
);
323 This
->bindCtxTable
[index
].pObj
=punk
;
324 IUnknown_AddRef(punk
);
327 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pObj
= punk
;
328 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].regType
= 1;
332 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
=NULL
;
337 This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
=
338 HeapAlloc(GetProcessHeap(),0,(sizeof(WCHAR
)*(1+lstrlenW(pszkey
))));
340 if (This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
==NULL
)
341 return E_OUTOFMEMORY
;
342 lstrcpyW(This
->bindCtxTable
[This
->bindCtxTableLastIndex
].pkeyObj
,pszkey
);
345 This
->bindCtxTableLastIndex
++;
347 if (This
->bindCtxTableLastIndex
== This
->bindCtxTableSize
)
349 /* table is full ! must be resized */
351 This
->bindCtxTableSize
+=BLOCK_TAB_SIZE
; /* new table size */
352 if (This
->bindCtxTableSize
> (MAX_TAB_SIZE
-BLOCK_TAB_SIZE
))
354 FIXME("This->bindCtxTableSize: %ld is out of data limite\n", This
->bindCtxTableSize
);
357 This
->bindCtxTable
= HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,This
->bindCtxTable
,
358 This
->bindCtxTableSize
* sizeof(BindCtxObject
));
359 if (!This
->bindCtxTable
)
360 return E_OUTOFMEMORY
;
362 IUnknown_AddRef(punk
);
366 /******************************************************************************
367 * BindCtx_GetObjectParam
368 ******************************************************************************/
369 static HRESULT WINAPI
370 BindCtxImpl_GetObjectParam(IBindCtx
* iface
,LPOLESTR pszkey
, IUnknown
** punk
)
373 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
375 TRACE("(%p,%s,%p)\n",This
,debugstr_w(pszkey
),punk
);
382 if (BindCtxImpl_GetObjectIndex(This
,NULL
,pszkey
,&index
)==S_FALSE
)
385 IUnknown_AddRef(This
->bindCtxTable
[index
].pObj
);
387 *punk
= This
->bindCtxTable
[index
].pObj
;
392 /******************************************************************************
393 * BindCtx_RevokeObjectParam
394 ******************************************************************************/
395 static HRESULT WINAPI
396 BindCtxImpl_RevokeObjectParam(IBindCtx
* iface
,LPOLESTR ppenum
)
400 BindCtxImpl
*This
= (BindCtxImpl
*)iface
;
402 TRACE("(%p,%s)\n",This
,debugstr_w(ppenum
));
404 if (BindCtxImpl_GetObjectIndex(This
,NULL
,ppenum
,&index
)==S_FALSE
)
407 /* release the object if it's found */
408 if(This
->bindCtxTable
[index
].pObj
)
409 IUnknown_Release(This
->bindCtxTable
[index
].pObj
);
410 HeapFree(GetProcessHeap(),0,This
->bindCtxTable
[index
].pkeyObj
);
412 /* remove the object from the table with a left-shifting of all objects in the right side */
413 for(j
=index
; j
<This
->bindCtxTableLastIndex
-1; j
++)
414 This
->bindCtxTable
[j
]= This
->bindCtxTable
[j
+1];
416 This
->bindCtxTableLastIndex
--;
421 /******************************************************************************
422 * BindCtx_EnumObjectParam
423 ******************************************************************************/
424 static HRESULT WINAPI
425 BindCtxImpl_EnumObjectParam(IBindCtx
* iface
,IEnumString
** pszkey
)
427 FIXME("(%p,%p),stub!\n",iface
,pszkey
);
431 /********************************************************************************
432 * GetObjectIndex (local function)
433 ********************************************************************************/
434 static HRESULT
BindCtxImpl_GetObjectIndex(BindCtxImpl
* This
,
443 TRACE("(%p,%p,%p,%p)\n",This
,punk
,pszkey
,index
);
446 /* search object identified by a register key */
447 for(i
=0; ( (i
<This
->bindCtxTableLastIndex
) && (!found
));i
++)
449 if(This
->bindCtxTable
[i
].regType
==1){
451 if ( ( (This
->bindCtxTable
[i
].pkeyObj
==NULL
) && (pszkey
==NULL
) ) ||
452 ( (This
->bindCtxTable
[i
].pkeyObj
!=NULL
) &&
454 (lstrcmpW(This
->bindCtxTable
[i
].pkeyObj
,pszkey
)==0)
462 /* search object identified by a moniker*/
463 for(i
=0; ( (i
<This
->bindCtxTableLastIndex
) && (!found
));i
++)
464 if(This
->bindCtxTable
[i
].pObj
==punk
)
472 TRACE("key not found\n");
476 /* Virtual function table for the BindCtx class. */
477 static const IBindCtxVtbl VT_BindCtxImpl
=
479 BindCtxImpl_QueryInterface
,
482 BindCtxImpl_RegisterObjectBound
,
483 BindCtxImpl_RevokeObjectBound
,
484 BindCtxImpl_ReleaseBoundObjects
,
485 BindCtxImpl_SetBindOptions
,
486 BindCtxImpl_GetBindOptions
,
487 BindCtxImpl_GetRunningObjectTable
,
488 BindCtxImpl_RegisterObjectParam
,
489 BindCtxImpl_GetObjectParam
,
490 BindCtxImpl_EnumObjectParam
,
491 BindCtxImpl_RevokeObjectParam
494 /******************************************************************************
495 * BindCtx_Construct (local function)
496 *******************************************************************************/
497 static HRESULT
BindCtxImpl_Construct(BindCtxImpl
* This
)
499 TRACE("(%p)\n",This
);
501 /* Initialize the virtual function table.*/
502 This
->lpVtbl
= &VT_BindCtxImpl
;
505 /* Initialize the BIND_OPTS2 structure */
506 This
->bindOption2
.cbStruct
= sizeof(BIND_OPTS2
);
507 This
->bindOption2
.grfFlags
= 0;
508 This
->bindOption2
.grfMode
= STGM_READWRITE
;
509 This
->bindOption2
.dwTickCountDeadline
= 0;
511 This
->bindOption2
.dwTrackFlags
= 0;
512 This
->bindOption2
.dwClassContext
= CLSCTX_SERVER
;
513 This
->bindOption2
.locale
= 1033;
514 This
->bindOption2
.pServerInfo
= 0;
516 /* Initialize the bindctx table */
517 This
->bindCtxTableSize
=BLOCK_TAB_SIZE
;
518 This
->bindCtxTableLastIndex
=0;
519 This
->bindCtxTable
= HeapAlloc(GetProcessHeap(), 0,
520 This
->bindCtxTableSize
*sizeof(BindCtxObject
));
522 if (This
->bindCtxTable
==NULL
)
523 return E_OUTOFMEMORY
;
528 /******************************************************************************
529 * CreateBindCtx (OLE32.@)
530 ******************************************************************************/
531 HRESULT WINAPI
CreateBindCtx(DWORD reserved
, LPBC
* ppbc
)
533 BindCtxImpl
* newBindCtx
= 0;
535 IID riid
=IID_IBindCtx
;
537 TRACE("(%ld,%p)\n",reserved
,ppbc
);
539 newBindCtx
= HeapAlloc(GetProcessHeap(), 0, sizeof(BindCtxImpl
));
541 return E_OUTOFMEMORY
;
543 hr
= BindCtxImpl_Construct(newBindCtx
);
546 HeapFree(GetProcessHeap(),0,newBindCtx
);
550 hr
= BindCtxImpl_QueryInterface((IBindCtx
*)newBindCtx
,&riid
,(void**)ppbc
);
555 HRESULT WINAPI
BindMoniker(LPMONIKER pmk
, DWORD grfOpt
, REFIID riid
, LPVOID
* ppvResult
)
560 TRACE("(%p, %lx, %s, %p)\n", pmk
, grfOpt
, debugstr_guid(riid
), ppvResult
);
562 res
= CreateBindCtx(grfOpt
, &pbc
);
564 res
= IMoniker_BindToObject(pmk
, pbc
, NULL
, riid
, ppvResult
);