Release 0.9.14.
[wine/multimedia.git] / dlls / ole32 / bindctx.c
blobd83ffabbdbc171247cc027414f1b614829ae1f40
1 /*
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
21 #include <stdarg.h>
22 #include <string.h>
23 #include <assert.h>
25 #define COBJMACROS
27 #include "winerror.h"
28 #include "windef.h"
29 #include "winbase.h"
30 #include "objbase.h"
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 */
48 } BindCtxObject;
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*/
63 } BindCtxImpl;
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 *******************************************************************************/
72 static HRESULT WINAPI
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) )
81 return E_INVALIDARG;
83 /* Initialize the return parameter.*/
84 *ppvObject = 0;
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);
92 return S_OK;
95 return E_NOINTERFACE;
98 /******************************************************************************
99 * BindCtx_AddRef
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);
123 return S_OK;
126 /******************************************************************************
127 * BindCtx_Release
128 ******************************************************************************/
129 static ULONG WINAPI BindCtxImpl_Release(IBindCtx* iface)
131 BindCtxImpl *This = (BindCtxImpl *)iface;
132 ULONG ref;
134 TRACE("(%p)\n",This);
136 ref = InterlockedDecrement(&This->ref);
137 if (ref == 0)
139 /* release all registered objects */
140 BindCtxImpl_ReleaseBoundObjects((IBindCtx*)This);
142 BindCtxImpl_Destroy(This);
144 return ref;
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);
159 if (punk==NULL)
160 return E_POINTER;
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);
174 return E_FAIL;
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;
184 return S_OK;
187 /******************************************************************************
188 * BindCtx_RevokeObjectBound
189 ******************************************************************************/
190 static HRESULT WINAPI
191 BindCtxImpl_RevokeObjectBound(IBindCtx* iface, IUnknown* punk)
193 DWORD index,j;
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--;
213 return S_OK;
216 /******************************************************************************
217 * BindCtx_ReleaseBoundObjects
218 ******************************************************************************/
219 static HRESULT WINAPI
220 BindCtxImpl_ReleaseBoundObjects(IBindCtx* iface)
222 DWORD i;
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;
237 return S_OK;
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);
250 if (pbindopts==NULL)
251 return E_POINTER;
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);
259 return S_OK;
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);
272 if (pbindopts==NULL)
273 return E_POINTER;
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);
281 return S_OK;
284 /******************************************************************************
285 * BindCtx_GetRunningObjectTable
286 ******************************************************************************/
287 static HRESULT WINAPI
288 BindCtxImpl_GetRunningObjectTable(IBindCtx* iface,IRunningObjectTable** pprot)
290 HRESULT res;
292 BindCtxImpl *This = (BindCtxImpl *)iface;
294 TRACE("(%p,%p)\n",This,pprot);
296 if (pprot==NULL)
297 return E_POINTER;
299 res=GetRunningObjectTable(0, pprot);
301 return res;
304 /******************************************************************************
305 * BindCtx_RegisterObjectParam
306 ******************************************************************************/
307 static HRESULT WINAPI
308 BindCtxImpl_RegisterObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown* punk)
310 DWORD index=0;
311 BindCtxImpl *This = (BindCtxImpl *)iface;
313 TRACE("(%p,%s,%p)\n",This,debugstr_w(pszkey),punk);
315 if (punk==NULL)
316 return E_INVALIDARG;
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);
325 return S_OK;
327 This->bindCtxTable[This->bindCtxTableLastIndex].pObj = punk;
328 This->bindCtxTable[This->bindCtxTableLastIndex].regType = 1;
330 if (pszkey==NULL)
332 This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj=NULL;
334 else
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);
355 return E_FAIL;
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);
363 return S_OK;
366 /******************************************************************************
367 * BindCtx_GetObjectParam
368 ******************************************************************************/
369 static HRESULT WINAPI
370 BindCtxImpl_GetObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown** punk)
372 DWORD index;
373 BindCtxImpl *This = (BindCtxImpl *)iface;
375 TRACE("(%p,%s,%p)\n",This,debugstr_w(pszkey),punk);
377 if (punk==NULL)
378 return E_POINTER;
380 *punk=0;
382 if (BindCtxImpl_GetObjectIndex(This,NULL,pszkey,&index)==S_FALSE)
383 return E_FAIL;
385 IUnknown_AddRef(This->bindCtxTable[index].pObj);
387 *punk = This->bindCtxTable[index].pObj;
389 return S_OK;
392 /******************************************************************************
393 * BindCtx_RevokeObjectParam
394 ******************************************************************************/
395 static HRESULT WINAPI
396 BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR ppenum)
398 DWORD index,j;
400 BindCtxImpl *This = (BindCtxImpl *)iface;
402 TRACE("(%p,%s)\n",This,debugstr_w(ppenum));
404 if (BindCtxImpl_GetObjectIndex(This,NULL,ppenum,&index)==S_FALSE)
405 return E_FAIL;
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--;
418 return S_OK;
421 /******************************************************************************
422 * BindCtx_EnumObjectParam
423 ******************************************************************************/
424 static HRESULT WINAPI
425 BindCtxImpl_EnumObjectParam(IBindCtx* iface,IEnumString** pszkey)
427 FIXME("(%p,%p),stub!\n",iface,pszkey);
428 return E_NOTIMPL;
431 /********************************************************************************
432 * GetObjectIndex (local function)
433 ********************************************************************************/
434 static HRESULT BindCtxImpl_GetObjectIndex(BindCtxImpl* This,
435 IUnknown* punk,
436 LPOLESTR pszkey,
437 DWORD *index)
440 DWORD i;
441 BYTE found=0;
443 TRACE("(%p,%p,%p,%p)\n",This,punk,pszkey,index);
445 if (punk==NULL)
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) &&
453 (pszkey!=NULL) &&
454 (lstrcmpW(This->bindCtxTable[i].pkeyObj,pszkey)==0)
458 found=1;
461 else
462 /* search object identified by a moniker*/
463 for(i=0; ( (i<This->bindCtxTableLastIndex) && (!found));i++)
464 if(This->bindCtxTable[i].pObj==punk)
465 found=1;
467 if (index != NULL)
468 *index=i-1;
470 if (found)
471 return S_OK;
472 TRACE("key not found\n");
473 return S_FALSE;
476 /* Virtual function table for the BindCtx class. */
477 static const IBindCtxVtbl VT_BindCtxImpl =
479 BindCtxImpl_QueryInterface,
480 BindCtxImpl_AddRef,
481 BindCtxImpl_Release,
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;
503 This->ref = 0;
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;
525 return S_OK;
528 /******************************************************************************
529 * CreateBindCtx (OLE32.@)
530 ******************************************************************************/
531 HRESULT WINAPI CreateBindCtx(DWORD reserved, LPBC * ppbc)
533 BindCtxImpl* newBindCtx = 0;
534 HRESULT hr;
535 IID riid=IID_IBindCtx;
537 TRACE("(%ld,%p)\n",reserved,ppbc);
539 newBindCtx = HeapAlloc(GetProcessHeap(), 0, sizeof(BindCtxImpl));
540 if (newBindCtx == 0)
541 return E_OUTOFMEMORY;
543 hr = BindCtxImpl_Construct(newBindCtx);
544 if (FAILED(hr))
546 HeapFree(GetProcessHeap(),0,newBindCtx);
547 return hr;
550 hr = BindCtxImpl_QueryInterface((IBindCtx*)newBindCtx,&riid,(void**)ppbc);
552 return hr;
555 HRESULT WINAPI BindMoniker(LPMONIKER pmk, DWORD grfOpt, REFIID riid, LPVOID * ppvResult)
557 HRESULT res;
558 IBindCtx * pbc;
560 TRACE("(%p, %lx, %s, %p)\n", pmk, grfOpt, debugstr_guid(riid), ppvResult);
562 res = CreateBindCtx(grfOpt, &pbc);
563 if (SUCCEEDED(res))
564 res = IMoniker_BindToObject(pmk, pbc, NULL, riid, ppvResult);
565 return res;