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