ole32: Fix cbStruct handling in IBindCtx:GetBindOptions.
[wine/gsoc_dplay.git] / dlls / ole32 / bindctx.c
blob464d02e449e051f4a09d099119c186363d24554d
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>
24 #define COBJMACROS
26 #include "winerror.h"
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winnls.h"
30 #include "objbase.h"
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 */
49 } BindCtxObject;
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*/
64 } BindCtxImpl;
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 *******************************************************************************/
73 static HRESULT WINAPI
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) )
82 return E_INVALIDARG;
84 /* Initialize the return parameter.*/
85 *ppvObject = 0;
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);
93 return S_OK;
96 return E_NOINTERFACE;
99 /******************************************************************************
100 * BindCtx_AddRef
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);
124 return S_OK;
127 /******************************************************************************
128 * BindCtx_Release
129 ******************************************************************************/
130 static ULONG WINAPI BindCtxImpl_Release(IBindCtx* iface)
132 BindCtxImpl *This = (BindCtxImpl *)iface;
133 ULONG ref;
135 TRACE("(%p)\n",This);
137 ref = InterlockedDecrement(&This->ref);
138 if (ref == 0)
140 /* release all registered objects */
141 BindCtxImpl_ReleaseBoundObjects((IBindCtx*)This);
143 BindCtxImpl_Destroy(This);
145 return ref;
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);
160 if (punk==NULL)
161 return E_POINTER;
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);
175 return E_FAIL;
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;
185 return S_OK;
188 /******************************************************************************
189 * BindCtx_RevokeObjectBound
190 ******************************************************************************/
191 static HRESULT WINAPI
192 BindCtxImpl_RevokeObjectBound(IBindCtx* iface, IUnknown* punk)
194 DWORD index,j;
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--;
214 return S_OK;
217 /******************************************************************************
218 * BindCtx_ReleaseBoundObjects
219 ******************************************************************************/
220 static HRESULT WINAPI
221 BindCtxImpl_ReleaseBoundObjects(IBindCtx* iface)
223 DWORD i;
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;
238 return S_OK;
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);
251 if (pbindopts==NULL)
252 return E_POINTER;
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);
260 return S_OK;
263 /******************************************************************************
264 * BindCtx_GetBindOptions
265 ******************************************************************************/
266 static HRESULT WINAPI
267 BindCtxImpl_GetBindOptions(IBindCtx* iface,BIND_OPTS *pbindopts)
269 BindCtxImpl *This = (BindCtxImpl *)iface;
270 ULONG cbStruct;
272 TRACE("(%p,%p)\n",This,pbindopts);
274 if (pbindopts==NULL)
275 return E_POINTER;
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;
284 return S_OK;
287 /******************************************************************************
288 * BindCtx_GetRunningObjectTable
289 ******************************************************************************/
290 static HRESULT WINAPI
291 BindCtxImpl_GetRunningObjectTable(IBindCtx* iface,IRunningObjectTable** pprot)
293 HRESULT res;
295 BindCtxImpl *This = (BindCtxImpl *)iface;
297 TRACE("(%p,%p)\n",This,pprot);
299 if (pprot==NULL)
300 return E_POINTER;
302 res=GetRunningObjectTable(0, pprot);
304 return res;
307 /******************************************************************************
308 * BindCtx_RegisterObjectParam
309 ******************************************************************************/
310 static HRESULT WINAPI
311 BindCtxImpl_RegisterObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown* punk)
313 DWORD index=0;
314 BindCtxImpl *This = (BindCtxImpl *)iface;
316 TRACE("(%p,%s,%p)\n",This,debugstr_w(pszkey),punk);
318 if (punk==NULL)
319 return E_INVALIDARG;
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);
328 return S_OK;
330 This->bindCtxTable[This->bindCtxTableLastIndex].pObj = punk;
331 This->bindCtxTable[This->bindCtxTableLastIndex].regType = 1;
333 if (pszkey==NULL)
335 This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj=NULL;
337 else
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);
358 return E_FAIL;
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);
366 return S_OK;
369 /******************************************************************************
370 * BindCtx_GetObjectParam
371 ******************************************************************************/
372 static HRESULT WINAPI
373 BindCtxImpl_GetObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown** punk)
375 DWORD index;
376 BindCtxImpl *This = (BindCtxImpl *)iface;
378 TRACE("(%p,%s,%p)\n",This,debugstr_w(pszkey),punk);
380 if (punk==NULL)
381 return E_POINTER;
383 *punk=0;
385 if (BindCtxImpl_GetObjectIndex(This,NULL,pszkey,&index)==S_FALSE)
386 return E_FAIL;
388 IUnknown_AddRef(This->bindCtxTable[index].pObj);
390 *punk = This->bindCtxTable[index].pObj;
392 return S_OK;
395 /******************************************************************************
396 * BindCtx_RevokeObjectParam
397 ******************************************************************************/
398 static HRESULT WINAPI
399 BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR ppenum)
401 DWORD index,j;
403 BindCtxImpl *This = (BindCtxImpl *)iface;
405 TRACE("(%p,%s)\n",This,debugstr_w(ppenum));
407 if (BindCtxImpl_GetObjectIndex(This,NULL,ppenum,&index)==S_FALSE)
408 return E_FAIL;
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--;
421 return S_OK;
424 /******************************************************************************
425 * BindCtx_EnumObjectParam
426 ******************************************************************************/
427 static HRESULT WINAPI
428 BindCtxImpl_EnumObjectParam(IBindCtx* iface,IEnumString** pszkey)
430 TRACE("(%p,%p)\n",iface,pszkey);
432 *pszkey = NULL;
434 /* not implemented in native either */
435 return E_NOTIMPL;
438 /********************************************************************************
439 * GetObjectIndex (local function)
440 ********************************************************************************/
441 static HRESULT BindCtxImpl_GetObjectIndex(BindCtxImpl* This,
442 IUnknown* punk,
443 LPOLESTR pszkey,
444 DWORD *index)
447 DWORD i;
448 BYTE found=0;
450 TRACE("(%p,%p,%p,%p)\n",This,punk,pszkey,index);
452 if (punk==NULL)
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) &&
460 (pszkey!=NULL) &&
461 (lstrcmpW(This->bindCtxTable[i].pkeyObj,pszkey)==0)
465 found=1;
468 else
469 /* search object identified by a moniker*/
470 for(i=0; ( (i<This->bindCtxTableLastIndex) && (!found));i++)
471 if(This->bindCtxTable[i].pObj==punk)
472 found=1;
474 if (index != NULL)
475 *index=i-1;
477 if (found)
478 return S_OK;
479 TRACE("key not found\n");
480 return S_FALSE;
483 /* Virtual function table for the BindCtx class. */
484 static const IBindCtxVtbl VT_BindCtxImpl =
486 BindCtxImpl_QueryInterface,
487 BindCtxImpl_AddRef,
488 BindCtxImpl_Release,
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;
510 This->ref = 0;
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;
532 return S_OK;
535 /******************************************************************************
536 * CreateBindCtx (OLE32.@)
537 ******************************************************************************/
538 HRESULT WINAPI CreateBindCtx(DWORD reserved, LPBC * ppbc)
540 BindCtxImpl* newBindCtx = 0;
541 HRESULT hr;
542 IID riid=IID_IBindCtx;
544 TRACE("(%d,%p)\n",reserved,ppbc);
546 if (!ppbc) return E_INVALIDARG;
548 *ppbc = NULL;
550 if (reserved != 0)
552 ERR("reserved should be 0, not 0x%x\n", reserved);
553 return E_INVALIDARG;
556 newBindCtx = HeapAlloc(GetProcessHeap(), 0, sizeof(BindCtxImpl));
557 if (newBindCtx == 0)
558 return E_OUTOFMEMORY;
560 hr = BindCtxImpl_Construct(newBindCtx);
561 if (FAILED(hr))
563 HeapFree(GetProcessHeap(),0,newBindCtx);
564 return hr;
567 hr = BindCtxImpl_QueryInterface((IBindCtx*)newBindCtx,&riid,(void**)ppbc);
569 return hr;
572 HRESULT WINAPI BindMoniker(LPMONIKER pmk, DWORD grfOpt, REFIID riid, LPVOID * ppvResult)
574 HRESULT res;
575 IBindCtx * pbc;
577 TRACE("(%p, %x, %s, %p)\n", pmk, grfOpt, debugstr_guid(riid), ppvResult);
579 res = CreateBindCtx(grfOpt, &pbc);
580 if (SUCCEEDED(res))
581 res = IMoniker_BindToObject(pmk, pbc, NULL, riid, ppvResult);
582 return res;