usp10: Free default_language items when freeing script cache.
[wine.git] / dlls / ole32 / bindctx.c
blobed6269d3e97701b47be36c5a6fe52cd5248a43f2
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 #define BINDCTX_FIRST_TABLE_SIZE 4
38 /* data structure of the BindCtx table elements */
39 typedef struct BindCtxObject{
41 IUnknown* pObj; /* point on a bound object */
43 LPOLESTR pkeyObj; /* key associated to this bound object */
45 BYTE regType; /* registration type: 1 if RegisterObjectParam and 0 if RegisterObjectBound */
47 } BindCtxObject;
49 /* BindCtx data structure */
50 typedef struct BindCtxImpl{
52 IBindCtx IBindCtx_iface;
54 LONG ref; /* reference counter for this object */
56 BindCtxObject* bindCtxTable; /* this is a table in which all bounded objects are stored*/
57 DWORD bindCtxTableLastIndex; /* first free index in the table */
58 DWORD bindCtxTableSize; /* size table */
60 BIND_OPTS2 bindOption2; /* a structure which contains the bind options*/
62 } BindCtxImpl;
64 /* IBindCtx prototype functions : */
65 static HRESULT WINAPI BindCtxImpl_ReleaseBoundObjects(IBindCtx*);
66 static HRESULT BindCtxImpl_GetObjectIndex(BindCtxImpl*, IUnknown*, LPOLESTR, DWORD *);
67 static HRESULT BindCtxImpl_ExpandTable(BindCtxImpl *);
69 static inline BindCtxImpl *impl_from_IBindCtx(IBindCtx *iface)
71 return CONTAINING_RECORD(iface, BindCtxImpl, IBindCtx_iface);
74 /*******************************************************************************
75 * BindCtx_QueryInterface
76 *******************************************************************************/
77 static HRESULT WINAPI
78 BindCtxImpl_QueryInterface(IBindCtx* iface,REFIID riid,void** ppvObject)
80 BindCtxImpl *This = impl_from_IBindCtx(iface);
82 TRACE("(%p %s %p)\n",This, debugstr_guid(riid), ppvObject);
84 /* Perform a sanity check on the parameters.*/
85 if (!ppvObject)
86 return E_POINTER;
88 /* Initialize the return parameter.*/
89 *ppvObject = 0;
91 /* Compare the riid with the interface IDs implemented by this object.*/
92 if (IsEqualIID(&IID_IUnknown, riid) ||
93 IsEqualIID(&IID_IBindCtx, riid))
95 *ppvObject = This;
96 IBindCtx_AddRef(iface);
97 return S_OK;
100 return E_NOINTERFACE;
103 /******************************************************************************
104 * BindCtx_AddRef
105 ******************************************************************************/
106 static ULONG WINAPI BindCtxImpl_AddRef(IBindCtx* iface)
108 BindCtxImpl *This = impl_from_IBindCtx(iface);
110 TRACE("(%p)\n",This);
112 return InterlockedIncrement(&This->ref);
115 /******************************************************************************
116 * BindCtx_Destroy (local function)
117 *******************************************************************************/
118 static HRESULT BindCtxImpl_Destroy(BindCtxImpl* This)
120 TRACE("(%p)\n",This);
122 /* free the table space memory */
123 HeapFree(GetProcessHeap(),0,This->bindCtxTable);
125 /* free the bindctx structure */
126 HeapFree(GetProcessHeap(),0,This);
128 return S_OK;
131 /******************************************************************************
132 * BindCtx_Release
133 ******************************************************************************/
134 static ULONG WINAPI BindCtxImpl_Release(IBindCtx* iface)
136 BindCtxImpl *This = impl_from_IBindCtx(iface);
137 ULONG ref;
139 TRACE("(%p)\n",This);
141 ref = InterlockedDecrement(&This->ref);
142 if (ref == 0)
144 /* release all registered objects */
145 BindCtxImpl_ReleaseBoundObjects(&This->IBindCtx_iface);
147 BindCtxImpl_Destroy(This);
149 return ref;
153 /******************************************************************************
154 * BindCtx_RegisterObjectBound
155 ******************************************************************************/
156 static HRESULT WINAPI
157 BindCtxImpl_RegisterObjectBound(IBindCtx* iface,IUnknown* punk)
159 BindCtxImpl *This = impl_from_IBindCtx(iface);
160 DWORD lastIndex=This->bindCtxTableLastIndex;
162 TRACE("(%p,%p)\n",This,punk);
164 if (punk==NULL)
165 return S_OK;
167 if (lastIndex == This->bindCtxTableSize)
169 HRESULT hr = BindCtxImpl_ExpandTable(This);
170 if (FAILED(hr))
171 return hr;
174 IUnknown_AddRef(punk);
176 /* put the object in the first free element in the table */
177 This->bindCtxTable[lastIndex].pObj = punk;
178 This->bindCtxTable[lastIndex].pkeyObj = NULL;
179 This->bindCtxTable[lastIndex].regType = 0;
180 lastIndex= ++This->bindCtxTableLastIndex;
182 return S_OK;
185 /******************************************************************************
186 * BindCtx_RevokeObjectBound
187 ******************************************************************************/
188 static HRESULT WINAPI
189 BindCtxImpl_RevokeObjectBound(IBindCtx* iface, IUnknown* punk)
191 DWORD index,j;
193 BindCtxImpl *This = impl_from_IBindCtx(iface);
195 TRACE("(%p,%p)\n",This,punk);
197 if (!punk)
198 return E_INVALIDARG;
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 = impl_from_IBindCtx(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 = impl_from_IBindCtx(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 = impl_from_IBindCtx(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 BindCtxImpl *This = impl_from_IBindCtx(iface);
295 TRACE("(%p,%p)\n",This,pprot);
297 if (pprot==NULL)
298 return E_POINTER;
300 return GetRunningObjectTable(0, pprot);
303 /******************************************************************************
304 * BindCtx_RegisterObjectParam
305 ******************************************************************************/
306 static HRESULT WINAPI
307 BindCtxImpl_RegisterObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown* punk)
309 DWORD index=0;
310 BindCtxImpl *This = impl_from_IBindCtx(iface);
312 TRACE("(%p,%s,%p)\n",This,debugstr_w(pszkey),punk);
314 if (punk==NULL)
315 return E_INVALIDARG;
317 if (pszkey!=NULL && BindCtxImpl_GetObjectIndex(This,NULL,pszkey,&index)==S_OK)
319 TRACE("Overwriting existing key\n");
320 if(This->bindCtxTable[index].pObj!=NULL)
321 IUnknown_Release(This->bindCtxTable[index].pObj);
322 This->bindCtxTable[index].pObj=punk;
323 IUnknown_AddRef(punk);
324 return S_OK;
327 if (This->bindCtxTableLastIndex == This->bindCtxTableSize)
329 HRESULT hr = BindCtxImpl_ExpandTable(This);
330 if (FAILED(hr))
331 return hr;
334 This->bindCtxTable[This->bindCtxTableLastIndex].pObj = punk;
335 This->bindCtxTable[This->bindCtxTableLastIndex].regType = 1;
337 if (pszkey==NULL)
339 This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj=NULL;
341 else
344 This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj=
345 HeapAlloc(GetProcessHeap(),0,(sizeof(WCHAR)*(1+lstrlenW(pszkey))));
347 if (This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj==NULL)
348 return E_OUTOFMEMORY;
349 lstrcpyW(This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj,pszkey);
352 This->bindCtxTableLastIndex++;
354 IUnknown_AddRef(punk);
355 return S_OK;
358 /******************************************************************************
359 * BindCtx_GetObjectParam
360 ******************************************************************************/
361 static HRESULT WINAPI
362 BindCtxImpl_GetObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown** punk)
364 DWORD index;
365 BindCtxImpl *This = impl_from_IBindCtx(iface);
367 TRACE("(%p,%s,%p)\n",This,debugstr_w(pszkey),punk);
369 if (punk==NULL)
370 return E_POINTER;
372 *punk=0;
374 if (BindCtxImpl_GetObjectIndex(This,NULL,pszkey,&index)==S_FALSE)
375 return E_FAIL;
377 IUnknown_AddRef(This->bindCtxTable[index].pObj);
379 *punk = This->bindCtxTable[index].pObj;
381 return S_OK;
384 /******************************************************************************
385 * BindCtx_RevokeObjectParam
386 ******************************************************************************/
387 static HRESULT WINAPI
388 BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR ppenum)
390 DWORD index,j;
392 BindCtxImpl *This = impl_from_IBindCtx(iface);
394 TRACE("(%p,%s)\n",This,debugstr_w(ppenum));
396 if (BindCtxImpl_GetObjectIndex(This,NULL,ppenum,&index)==S_FALSE)
397 return E_FAIL;
399 /* release the object if it's found */
400 if(This->bindCtxTable[index].pObj)
401 IUnknown_Release(This->bindCtxTable[index].pObj);
402 HeapFree(GetProcessHeap(),0,This->bindCtxTable[index].pkeyObj);
404 /* remove the object from the table with a left-shifting of all objects in the right side */
405 for(j=index; j<This->bindCtxTableLastIndex-1; j++)
406 This->bindCtxTable[j]= This->bindCtxTable[j+1];
408 This->bindCtxTableLastIndex--;
410 return S_OK;
413 /******************************************************************************
414 * BindCtx_EnumObjectParam
415 ******************************************************************************/
416 static HRESULT WINAPI
417 BindCtxImpl_EnumObjectParam(IBindCtx* iface,IEnumString** pszkey)
419 TRACE("(%p,%p)\n",iface,pszkey);
421 *pszkey = NULL;
423 /* not implemented in native either */
424 return E_NOTIMPL;
427 /********************************************************************************
428 * GetObjectIndex (local function)
429 ********************************************************************************/
430 static HRESULT BindCtxImpl_GetObjectIndex(BindCtxImpl* This,
431 IUnknown* punk,
432 LPOLESTR pszkey,
433 DWORD *index)
436 DWORD i;
437 BYTE found=0;
439 TRACE("(%p,%p,%p,%p)\n",This,punk,pszkey,index);
441 if (punk==NULL)
442 /* search object identified by a register key */
443 for(i=0; ( (i<This->bindCtxTableLastIndex) && (!found));i++)
445 if(This->bindCtxTable[i].regType==1){
447 if ( ( (This->bindCtxTable[i].pkeyObj==NULL) && (pszkey==NULL) ) ||
448 ( (This->bindCtxTable[i].pkeyObj!=NULL) &&
449 (pszkey!=NULL) &&
450 (lstrcmpW(This->bindCtxTable[i].pkeyObj,pszkey)==0)
454 found=1;
457 else
458 /* search object identified by a moniker*/
459 for(i=0; ( (i<This->bindCtxTableLastIndex) && (!found));i++)
460 if(This->bindCtxTable[i].pObj==punk)
461 found=1;
463 if (index != NULL)
464 *index=i-1;
466 if (found)
467 return S_OK;
468 TRACE("key not found\n");
469 return S_FALSE;
472 static HRESULT BindCtxImpl_ExpandTable(BindCtxImpl *This)
474 if (!This->bindCtxTableSize)
476 This->bindCtxTableSize = BINDCTX_FIRST_TABLE_SIZE;
477 This->bindCtxTable = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
478 This->bindCtxTableSize * sizeof(BindCtxObject));
480 else
482 This->bindCtxTableSize *= 2;
484 This->bindCtxTable = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->bindCtxTable,
485 This->bindCtxTableSize * sizeof(BindCtxObject));
488 if (!This->bindCtxTable)
489 return E_OUTOFMEMORY;
491 return S_OK;
495 /* Virtual function table for the BindCtx class. */
496 static const IBindCtxVtbl VT_BindCtxImpl =
498 BindCtxImpl_QueryInterface,
499 BindCtxImpl_AddRef,
500 BindCtxImpl_Release,
501 BindCtxImpl_RegisterObjectBound,
502 BindCtxImpl_RevokeObjectBound,
503 BindCtxImpl_ReleaseBoundObjects,
504 BindCtxImpl_SetBindOptions,
505 BindCtxImpl_GetBindOptions,
506 BindCtxImpl_GetRunningObjectTable,
507 BindCtxImpl_RegisterObjectParam,
508 BindCtxImpl_GetObjectParam,
509 BindCtxImpl_EnumObjectParam,
510 BindCtxImpl_RevokeObjectParam
513 /******************************************************************************
514 * BindCtx_Construct (local function)
515 *******************************************************************************/
516 static HRESULT BindCtxImpl_Construct(BindCtxImpl* This)
518 TRACE("(%p)\n",This);
520 /* Initialize the virtual function table.*/
521 This->IBindCtx_iface.lpVtbl = &VT_BindCtxImpl;
522 This->ref = 0;
524 /* Initialize the BIND_OPTS2 structure */
525 This->bindOption2.cbStruct = sizeof(BIND_OPTS2);
526 This->bindOption2.grfFlags = 0;
527 This->bindOption2.grfMode = STGM_READWRITE;
528 This->bindOption2.dwTickCountDeadline = 0;
530 This->bindOption2.dwTrackFlags = 0;
531 This->bindOption2.dwClassContext = CLSCTX_SERVER;
532 This->bindOption2.locale = GetThreadLocale();
533 This->bindOption2.pServerInfo = 0;
535 /* Initialize the bindctx table */
536 This->bindCtxTableSize=0;
537 This->bindCtxTableLastIndex=0;
538 This->bindCtxTable = NULL;
540 return S_OK;
543 /******************************************************************************
544 * CreateBindCtx (OLE32.@)
546 * Creates a bind context. A bind context encompasses information and options
547 * used when binding to a moniker.
549 * PARAMS
550 * reserved [I] Reserved. Set to 0.
551 * ppbc [O] Address that receives the bind context object.
553 * RETURNS
554 * Success: S_OK.
555 * Failure: Any HRESULT code.
557 HRESULT WINAPI CreateBindCtx(DWORD reserved, LPBC * ppbc)
559 BindCtxImpl* newBindCtx;
560 HRESULT hr;
562 TRACE("(%d,%p)\n",reserved,ppbc);
564 if (!ppbc) return E_INVALIDARG;
566 *ppbc = NULL;
568 if (reserved != 0)
570 ERR("reserved should be 0, not 0x%x\n", reserved);
571 return E_INVALIDARG;
574 newBindCtx = HeapAlloc(GetProcessHeap(), 0, sizeof(BindCtxImpl));
575 if (newBindCtx == 0)
576 return E_OUTOFMEMORY;
578 hr = BindCtxImpl_Construct(newBindCtx);
579 if (FAILED(hr))
581 HeapFree(GetProcessHeap(),0,newBindCtx);
582 return hr;
585 return BindCtxImpl_QueryInterface(&newBindCtx->IBindCtx_iface,&IID_IBindCtx,(void**)ppbc);
588 /******************************************************************************
589 * BindMoniker [OLE32.@]
591 * Binds to a moniker.
593 * PARAMS
594 * pmk [I] Moniker to bind to.
595 * grfOpt [I] Reserved option flags. Set to 0.
596 * riid [I] ID of the interface to bind to.
597 * pvResult [O] Address that receives the interface of the object that was bound to.
599 * RETURNS
600 * Success: S_OK.
601 * Failure: Any HRESULT code.
603 HRESULT WINAPI BindMoniker(LPMONIKER pmk, DWORD grfOpt, REFIID riid, LPVOID * ppvResult)
605 HRESULT res;
606 IBindCtx * pbc;
608 TRACE("(%p, %x, %s, %p)\n", pmk, grfOpt, debugstr_guid(riid), ppvResult);
610 res = CreateBindCtx(grfOpt, &pbc);
611 if (SUCCEEDED(res))
613 res = IMoniker_BindToObject(pmk, pbc, NULL, riid, ppvResult);
614 IBindCtx_Release(pbc);
616 return res;