Fixed cut&paste problem in SETRTS.
[wine] / dlls / ole32 / bindctx.c
1 /***************************************************************************************
2  *                            BindCtx implementation
3  *
4  *  Copyright 1999  Noomen Hamza
5  ***************************************************************************************/
6
7 #include <string.h>
8 #include <assert.h>
9 #include "winerror.h"
10 #include "winbase.h"
11 #include "wine/unicode.h"
12 #include "wine/obj_base.h"
13 #include "wine/obj_misc.h"
14 #include "wine/obj_storage.h"
15 #include "wine/obj_moniker.h"
16 #include "debugtools.h"
17
18 DEFAULT_DEBUG_CHANNEL(ole);
19
20 /* represent the first size table and it's increment block size */
21 #define  BLOCK_TAB_SIZE 10 
22 #define  MAX_TAB_SIZE   0xFFFFFFFF
23
24 /* data structure of the BindCtx table elements */
25 typedef struct BindCtxObject{
26
27     IUnknown*   pObj; /* point on a bound object */
28
29     LPOLESTR  pkeyObj; /* key associated to this bound object */
30
31     BYTE regType; /* registration type: 1 if RegisterObjectParam and 0 if RegisterObjectBound */
32
33 } BindCtxObject;
34
35 /* BindCtx data strucrture */
36 typedef struct BindCtxImpl{
37
38     ICOM_VFIELD(IBindCtx); /* VTable relative to the IBindCtx interface.*/
39                                      
40     ULONG ref; /* reference counter for this object */
41
42     BindCtxObject* bindCtxTable; /* this is a table in which all bounded objects are stored*/
43     DWORD          bindCtxTableLastIndex;  /* first free index in the table */
44     DWORD          bindCtxTableSize;   /* size table */
45
46     BIND_OPTS2 bindOption2; /* a structure which contains the bind options*/
47
48 } BindCtxImpl;
49
50 /* IBindCtx prototype functions : */
51
52 /* IUnknown functions*/
53 static HRESULT WINAPI BindCtxImpl_QueryInterface(IBindCtx* iface,REFIID riid,void** ppvObject);
54 static ULONG   WINAPI BindCtxImpl_AddRef(IBindCtx* iface);
55 static ULONG   WINAPI BindCtxImpl_Release(IBindCtx* iface);
56 /* IBindCtx functions */
57 static HRESULT WINAPI BindCtxImpl_RegisterObjectBound(IBindCtx* iface,IUnknown* punk);
58 static HRESULT WINAPI BindCtxImpl_RevokeObjectBound(IBindCtx* iface, IUnknown* punk);
59 static HRESULT WINAPI BindCtxImpl_ReleaseBoundObjects(IBindCtx* iface);
60 static HRESULT WINAPI BindCtxImpl_SetBindOptions(IBindCtx* iface,LPBIND_OPTS2 pbindopts);
61 static HRESULT WINAPI BindCtxImpl_GetBindOptions(IBindCtx* iface,LPBIND_OPTS2 pbindopts);
62 static HRESULT WINAPI BindCtxImpl_GetRunningObjectTable(IBindCtx* iface,IRunningObjectTable** pprot);
63 static HRESULT WINAPI BindCtxImpl_RegisterObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown* punk);
64 static HRESULT WINAPI BindCtxImpl_GetObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown** punk);
65 static HRESULT WINAPI BindCtxImpl_EnumObjectParam(IBindCtx* iface,IEnumString** ppenum);
66 static HRESULT WINAPI BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR pszkey);
67 /* Local functions*/
68 HRESULT WINAPI BindCtxImpl_Construct(BindCtxImpl* This);
69 HRESULT WINAPI BindCtxImpl_Destroy(BindCtxImpl* This);
70 HRESULT WINAPI BindCtxImpl_GetObjectIndex(BindCtxImpl* This,IUnknown* punk,LPOLESTR pszkey,DWORD *index);
71
72 /* Virtual function table for the BindCtx class. */
73 static ICOM_VTABLE(IBindCtx) VT_BindCtxImpl =
74     {
75     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
76     BindCtxImpl_QueryInterface,
77     BindCtxImpl_AddRef,
78     BindCtxImpl_Release,
79     BindCtxImpl_RegisterObjectBound,
80     BindCtxImpl_RevokeObjectBound,
81     BindCtxImpl_ReleaseBoundObjects,
82     BindCtxImpl_SetBindOptions,
83     BindCtxImpl_GetBindOptions,
84     BindCtxImpl_GetRunningObjectTable,
85     BindCtxImpl_RegisterObjectParam,
86     BindCtxImpl_GetObjectParam,
87     BindCtxImpl_EnumObjectParam,
88     BindCtxImpl_RevokeObjectParam
89 };
90
91 /*******************************************************************************
92  *        BindCtx_QueryInterface
93  *******************************************************************************/
94 HRESULT WINAPI BindCtxImpl_QueryInterface(IBindCtx* iface,REFIID riid,void** ppvObject)
95 {
96   ICOM_THIS(BindCtxImpl,iface);
97
98   TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
99
100   /* Perform a sanity check on the parameters.*/
101   if ( (This==0) || (ppvObject==0) )
102       return E_INVALIDARG;
103   
104   /* Initialize the return parameter.*/
105   *ppvObject = 0;
106
107   /* Compare the riid with the interface IDs implemented by this object.*/
108   if (IsEqualIID(&IID_IUnknown, riid))
109       *ppvObject = (IBindCtx*)This;
110   else
111       if (IsEqualIID(&IID_IBindCtx, riid))
112           *ppvObject = (IBindCtx*)This;
113
114   /* Check that we obtained an interface.*/
115   if ((*ppvObject)==0)
116       return E_NOINTERFACE;
117   
118    /* Query Interface always increases the reference count by one when it is successful */
119   BindCtxImpl_AddRef(iface);
120
121   return S_OK;
122 }
123
124 /******************************************************************************
125  *       BindCtx_AddRef
126  ******************************************************************************/
127 ULONG WINAPI BindCtxImpl_AddRef(IBindCtx* iface)
128 {
129     ICOM_THIS(BindCtxImpl,iface);
130
131     TRACE("(%p)\n",This);
132
133     return ++(This->ref);
134 }
135
136 /******************************************************************************
137  *        BindCtx_Release
138  ******************************************************************************/
139 ULONG WINAPI BindCtxImpl_Release(IBindCtx* iface)
140 {
141     ICOM_THIS(BindCtxImpl,iface);
142
143     TRACE("(%p)\n",This);
144
145     This->ref--;
146
147     if (This->ref==0){
148
149         /* release all registered objects */
150         BindCtxImpl_ReleaseBoundObjects((IBindCtx*)This);
151
152         BindCtxImpl_Destroy(This);
153
154         return 0;
155     }
156     return This->ref;;
157 }
158
159
160 /******************************************************************************
161  *         BindCtx_Construct (local function)
162  *******************************************************************************/
163 HRESULT WINAPI BindCtxImpl_Construct(BindCtxImpl* This)
164 {
165     TRACE("(%p)\n",This);
166
167     /* Initialize the virtual function table.*/
168     ICOM_VTBL(This)    = &VT_BindCtxImpl;
169     This->ref          = 0;
170
171     /* Initialize the BIND_OPTS2 structure */
172     This->bindOption2.cbStruct  = sizeof(BIND_OPTS2);
173     This->bindOption2.grfFlags = 0;
174     This->bindOption2.grfMode = STGM_READWRITE;
175     This->bindOption2.dwTickCountDeadline = 0;
176
177     This->bindOption2.dwTrackFlags = 0;
178     This->bindOption2.dwClassContext = CLSCTX_SERVER;
179     This->bindOption2.locale = 1033;
180     This->bindOption2.pServerInfo = 0;
181
182     /* Initialize the bindctx table */
183     This->bindCtxTableSize=BLOCK_TAB_SIZE;
184     This->bindCtxTableLastIndex=0;
185     This->bindCtxTable= HeapAlloc(GetProcessHeap(), 0,This->bindCtxTableSize*sizeof(BindCtxObject));
186
187     if (This->bindCtxTable==NULL)
188         return E_OUTOFMEMORY;
189
190     return S_OK;
191 }
192
193 /******************************************************************************
194  *        BindCtx_Destroy    (local function)
195  *******************************************************************************/
196 HRESULT WINAPI BindCtxImpl_Destroy(BindCtxImpl* This)
197 {
198     TRACE("(%p)\n",This);
199
200     /* free the table space memory */
201     HeapFree(GetProcessHeap(),0,This->bindCtxTable);
202
203     /* free the bindctx structure */
204     HeapFree(GetProcessHeap(),0,This);
205
206     return S_OK;
207 }
208
209
210 /******************************************************************************
211  *        BindCtx_RegisterObjectBound
212  ******************************************************************************/
213 HRESULT WINAPI BindCtxImpl_RegisterObjectBound(IBindCtx* iface,IUnknown* punk)
214 {
215
216     ICOM_THIS(BindCtxImpl,iface);
217     DWORD lastIndex=This->bindCtxTableLastIndex;
218     BindCtxObject cell;
219
220     TRACE("(%p,%p)\n",This,punk);
221
222     if (punk==NULL)
223         return E_POINTER;
224     
225     IUnknown_AddRef(punk);
226     
227     /* put the object in the first free element in the table */
228     This->bindCtxTable[lastIndex].pObj = punk;
229     This->bindCtxTable[lastIndex].pkeyObj = NULL;
230     This->bindCtxTable[lastIndex].regType = 0;
231     cell=This->bindCtxTable[lastIndex];
232     lastIndex= ++This->bindCtxTableLastIndex;
233
234     if (lastIndex == This->bindCtxTableSize){ /* the table is full so it must be resized */
235
236         if (This->bindCtxTableSize > (MAX_TAB_SIZE-BLOCK_TAB_SIZE)){
237             FIXME("This->bindCtxTableSize: %ld is out of data limite \n",This->bindCtxTableSize);
238             return E_FAIL;
239         }
240
241         This->bindCtxTableSize+=BLOCK_TAB_SIZE; /* new table size */
242
243         This->bindCtxTable = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->bindCtxTable,
244                                          This->bindCtxTableSize * sizeof(BindCtxObject));
245         if (!This->bindCtxTable)
246             return E_OUTOFMEMORY;
247     }
248     return S_OK;
249 }
250
251 /******************************************************************************
252  *        BindCtx_RevokeObjectBound
253  ******************************************************************************/
254 HRESULT WINAPI BindCtxImpl_RevokeObjectBound(IBindCtx* iface, IUnknown* punk)
255 {
256     DWORD index,j;
257
258     ICOM_THIS(BindCtxImpl,iface);
259
260     TRACE("(%p,%p)\n",This,punk);
261
262     /* check if the object was registred or not */
263     if (BindCtxImpl_GetObjectIndex(This,punk,NULL,&index)==S_FALSE)
264         
265         return MK_E_NOTBOUND;
266
267     IUnknown_Release(This->bindCtxTable[index].pObj);
268     
269     /* left-shift all elements in the right side of the current revoked object */
270     for(j=index; j<This->bindCtxTableLastIndex-1; j++)
271         This->bindCtxTable[j]= This->bindCtxTable[j+1];
272     
273     This->bindCtxTableLastIndex--;
274
275     return S_OK;
276 }
277
278 /******************************************************************************
279  *        BindCtx_ReleaseBoundObjects
280  ******************************************************************************/
281 HRESULT WINAPI BindCtxImpl_ReleaseBoundObjects(IBindCtx* iface)
282 {
283     DWORD i;
284
285     ICOM_THIS(BindCtxImpl,iface);
286
287     TRACE("(%p)\n",This);
288
289     for(i=0;i<This->bindCtxTableLastIndex;i++)
290        IUnknown_Release(This->bindCtxTable[i].pObj);
291
292     This->bindCtxTableLastIndex = 0;
293
294     return S_OK;
295 }
296
297 /******************************************************************************
298  *        BindCtx_SetBindOptions
299  ******************************************************************************/
300 HRESULT WINAPI BindCtxImpl_SetBindOptions(IBindCtx* iface,LPBIND_OPTS2 pbindopts)
301 {
302     ICOM_THIS(BindCtxImpl,iface);
303
304     TRACE("(%p,%p)\n",This,pbindopts);
305
306     if (pbindopts==NULL)
307         return E_POINTER;
308     
309     if (pbindopts->cbStruct > sizeof(BIND_OPTS2))
310     {
311         WARN("invalid size\n");
312         return E_INVALIDARG; /* FIXME : not verified */
313     }
314     memcpy(&This->bindOption2, pbindopts, pbindopts->cbStruct);
315     return S_OK;
316 }
317
318 /******************************************************************************
319  *        BindCtx_GetBindOptions
320  ******************************************************************************/
321 HRESULT WINAPI BindCtxImpl_GetBindOptions(IBindCtx* iface,LPBIND_OPTS2 pbindopts)
322 {
323     ICOM_THIS(BindCtxImpl,iface);
324
325     TRACE("(%p,%p)\n",This,pbindopts);
326
327     if (pbindopts==NULL)
328         return E_POINTER;
329
330     if (pbindopts->cbStruct > sizeof(BIND_OPTS2))
331     {
332         WARN("invalid size\n");
333         return E_INVALIDARG; /* FIXME : not verified */
334     }
335     memcpy(pbindopts, &This->bindOption2, pbindopts->cbStruct);
336     return S_OK;
337 }
338
339 /******************************************************************************
340  *        BindCtx_GetRunningObjectTable
341  ******************************************************************************/
342 HRESULT WINAPI BindCtxImpl_GetRunningObjectTable(IBindCtx* iface,IRunningObjectTable** pprot)
343 {
344     HRESULT res;
345
346     ICOM_THIS(BindCtxImpl,iface);
347
348     TRACE("(%p,%p)\n",This,pprot);
349
350     if (pprot==NULL)
351         return E_POINTER;
352     
353     res=GetRunningObjectTable(0, pprot);
354
355     return res;
356 }
357
358 /******************************************************************************
359  *        BindCtx_RegisterObjectParam
360  ******************************************************************************/
361 HRESULT WINAPI BindCtxImpl_RegisterObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown* punk)
362 {
363     ICOM_THIS(BindCtxImpl,iface);
364
365     TRACE("(%p,%p,%p)\n",This,pszkey,punk);
366
367     if (punk==NULL)
368         return E_INVALIDARG;
369     
370     IUnknown_AddRef(punk);
371
372     This->bindCtxTable[This->bindCtxTableLastIndex].pObj = punk;
373     This->bindCtxTable[This->bindCtxTableLastIndex].regType = 1;
374
375     if (pszkey==NULL)
376
377         This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj=NULL;
378
379     else{
380
381         This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj=
382             HeapAlloc(GetProcessHeap(),0,(sizeof(WCHAR)*(1+lstrlenW(pszkey))));
383
384         if (This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj==NULL)
385             return E_OUTOFMEMORY;
386         strcpyW(This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj,pszkey);
387     }
388
389     This->bindCtxTableLastIndex++;
390     
391     if (This->bindCtxTableLastIndex == This->bindCtxTableSize){ /* table is full ! must be resized */
392
393         This->bindCtxTableSize+=BLOCK_TAB_SIZE; /* new table size */
394
395         if (This->bindCtxTableSize > (MAX_TAB_SIZE-BLOCK_TAB_SIZE)){
396             FIXME("This->bindCtxTableSize: %ld is out of data limite \n",This->bindCtxTableSize);
397             return E_FAIL;
398         }
399         This->bindCtxTable = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->bindCtxTable,
400                                          This->bindCtxTableSize * sizeof(BindCtxObject));
401         if (!This->bindCtxTable)
402             return E_OUTOFMEMORY;
403     }
404     return S_OK;
405 }
406 /******************************************************************************
407  *        BindCtx_GetObjectParam
408  ******************************************************************************/
409 HRESULT WINAPI BindCtxImpl_GetObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown** punk)
410 {
411     DWORD index;
412     ICOM_THIS(BindCtxImpl,iface);
413
414     TRACE("(%p,%p,%p)\n",This,pszkey,punk);
415
416     if (punk==NULL)
417         return E_POINTER;
418
419     *punk=0;
420     
421     if (BindCtxImpl_GetObjectIndex(This,NULL,pszkey,&index)==S_FALSE)
422         return E_FAIL;
423
424     IUnknown_AddRef(This->bindCtxTable[index].pObj);
425     
426     *punk = This->bindCtxTable[index].pObj;
427
428     return S_OK;
429 }
430
431 /******************************************************************************
432  *        BindCtx_RevokeObjectParam
433  ******************************************************************************/
434 HRESULT WINAPI BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR ppenum)
435 {
436     DWORD index,j;
437
438     ICOM_THIS(BindCtxImpl,iface);
439
440     TRACE("(%p,%p)\n",This,ppenum);
441
442     if (BindCtxImpl_GetObjectIndex(This,NULL,ppenum,&index)==S_FALSE)
443         return E_FAIL;
444
445     /* release the object if it's found */
446     IUnknown_Release(This->bindCtxTable[index].pObj);
447     
448     /* remove the object from the table with a left-shifting of all objects in the right side */
449     for(j=index; j<This->bindCtxTableLastIndex-1; j++)
450         This->bindCtxTable[j]= This->bindCtxTable[j+1];
451     
452     This->bindCtxTableLastIndex--;
453
454     return S_OK;
455 }
456
457 /******************************************************************************
458  *        BindCtx_EnumObjectParam
459  ******************************************************************************/
460 HRESULT WINAPI BindCtxImpl_EnumObjectParam(IBindCtx* iface,IEnumString** pszkey)
461 {
462     FIXME("(%p,%p),stub!\n",iface,pszkey);
463     return E_NOTIMPL;
464 }
465
466 /********************************************************************************
467  *        GetObjectIndex (local function)
468  ********************************************************************************/
469 HRESULT WINAPI BindCtxImpl_GetObjectIndex(BindCtxImpl* This,
470                                           IUnknown* punk,
471                                           LPOLESTR pszkey,
472                                           DWORD *index)
473 {
474
475     DWORD i;
476     BYTE found=0;
477     
478     TRACE("(%p,%p,%p,%p)\n",This,punk,pszkey,index);
479
480     if (punk==NULL)
481         /* search object identified by a register key */
482         for(i=0; ( (i<This->bindCtxTableLastIndex) && (!found));i++){
483
484             if(This->bindCtxTable[i].regType==1){
485
486                 if ( ( (This->bindCtxTable[i].pkeyObj==NULL) && (pszkey==NULL) ) ||
487                      ( (This->bindCtxTable[i].pkeyObj!=NULL) &&
488                        (pszkey!=NULL) &&
489                        (lstrcmpW(This->bindCtxTable[i].pkeyObj,pszkey)==0)
490                      )
491                    )
492
493                     found=1;
494             }
495         }
496     else
497         /* search object identified by a moniker*/
498         for(i=0; ( (i<This->bindCtxTableLastIndex) && (!found));i++)
499             if(This->bindCtxTable[i].pObj==punk)
500                 found=1;
501
502     if (index != NULL)
503         *index=i-1;
504
505     if (found)
506         return S_OK;
507     else
508         return S_FALSE;
509 }
510
511 /******************************************************************************
512  *        CreateBindCtx16
513  ******************************************************************************/
514 HRESULT WINAPI CreateBindCtx16(DWORD reserved, LPBC * ppbc)
515 {
516     FIXME("(%ld,%p),stub!\n",reserved,ppbc);
517     return E_NOTIMPL;
518 }
519
520 /******************************************************************************
521  *        CreateBindCtx (OLE32.52)
522  ******************************************************************************/
523 HRESULT WINAPI CreateBindCtx(DWORD reserved, LPBC * ppbc)
524 {
525     BindCtxImpl* newBindCtx = 0;
526     HRESULT hr;
527     IID riid=IID_IBindCtx;
528
529     TRACE("(%ld,%p)\n",reserved,ppbc);
530
531     newBindCtx = HeapAlloc(GetProcessHeap(), 0, sizeof(BindCtxImpl));
532
533     if (newBindCtx == 0)
534         return E_OUTOFMEMORY;
535
536     hr = BindCtxImpl_Construct(newBindCtx);
537
538     if (FAILED(hr)){
539
540         HeapFree(GetProcessHeap(),0,newBindCtx);
541         return hr;
542     }
543
544     hr = BindCtxImpl_QueryInterface((IBindCtx*)newBindCtx,&riid,(void**)ppbc);
545
546     return hr;
547 }