winex11: Use SetWindowPos to invalidate DCEs when changing the pixel format.
[wine] / programs / rpcss / irotp.c
1 /*
2  *      Running Object Table
3  *
4  *      Copyright 2007  Robert Shearman
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <stdarg.h>
22 #include <string.h>
23
24 #include "winerror.h"
25 #include "windef.h"
26 #include "winbase.h"
27
28 #include "irot.h"
29
30 #include "wine/list.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(rpcss);
34
35 /* define the structure of the running object table elements */
36 struct rot_entry
37 {
38     struct list        entry;
39     InterfaceData *object; /* marshaled running object*/
40     InterfaceData *moniker; /* marshaled moniker that identifies this object */
41     MonikerComparisonData *moniker_data; /* moniker comparison data that identifies this object */
42     DWORD              cookie; /* cookie identifying this object */
43     FILETIME           last_modified;
44     LONG               refs;
45 };
46
47 static struct list RunningObjectTable = LIST_INIT(RunningObjectTable);
48
49 static CRITICAL_SECTION csRunningObjectTable;
50 static CRITICAL_SECTION_DEBUG critsect_debug =
51 {
52     0, 0, &csRunningObjectTable,
53     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
54       0, 0, { (DWORD_PTR)(__FILE__ ": csRunningObjectTable") }
55 };
56 static CRITICAL_SECTION csRunningObjectTable = { &critsect_debug, -1, 0, 0, 0, 0 };
57
58 static LONG last_cookie = 1;
59
60 static inline void rot_entry_release(struct rot_entry *rot_entry)
61 {
62     if (!InterlockedDecrement(&rot_entry->refs))
63     {
64         HeapFree(GetProcessHeap(), 0, rot_entry->object);
65         HeapFree(GetProcessHeap(), 0, rot_entry->moniker);
66         HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data);
67         HeapFree(GetProcessHeap(), 0, rot_entry);
68     }
69 }
70
71 HRESULT IrotRegister(
72     IrotHandle h,
73     const MonikerComparisonData *data,
74     const InterfaceData *obj,
75     const InterfaceData *mk,
76     const FILETIME *time,
77     DWORD grfFlags,
78     IrotCookie *cookie,
79     IrotContextHandle *ctxt_handle)
80 {
81     struct rot_entry *rot_entry;
82     struct rot_entry *existing_rot_entry;
83     HRESULT hr;
84
85     if (grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT))
86     {
87         WINE_ERR("Invalid grfFlags: 0x%08x\n", grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT));
88         return E_INVALIDARG;
89     }
90
91     rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry));
92     if (!rot_entry)
93         return E_OUTOFMEMORY;
94
95     rot_entry->refs = 1;
96     rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[obj->ulCntData]));
97     if (!rot_entry->object)
98     {
99         rot_entry_release(rot_entry);
100         return E_OUTOFMEMORY;
101     }
102     rot_entry->object->ulCntData = obj->ulCntData;
103     memcpy(&rot_entry->object->abData, obj->abData, obj->ulCntData);
104
105     rot_entry->last_modified = *time;
106
107     rot_entry->moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[mk->ulCntData]));
108     if (!rot_entry->moniker)
109     {
110         rot_entry_release(rot_entry);
111         return E_OUTOFMEMORY;
112     }
113     rot_entry->moniker->ulCntData = mk->ulCntData;
114     memcpy(&rot_entry->moniker->abData, mk->abData, mk->ulCntData);
115
116     rot_entry->moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MonikerComparisonData, abData[data->ulCntData]));
117     if (!rot_entry->moniker_data)
118     {
119         rot_entry_release(rot_entry);
120         return E_OUTOFMEMORY;
121     }
122     rot_entry->moniker_data->ulCntData = data->ulCntData;
123     memcpy(&rot_entry->moniker_data->abData, data->abData, data->ulCntData);
124
125     EnterCriticalSection(&csRunningObjectTable);
126
127     hr = S_OK;
128
129     LIST_FOR_EACH_ENTRY(existing_rot_entry, &RunningObjectTable, struct rot_entry, entry)
130     {
131         if ((existing_rot_entry->moniker_data->ulCntData == data->ulCntData) &&
132             !memcmp(&data->abData, &existing_rot_entry->moniker_data->abData, data->ulCntData))
133         {
134             hr = MK_S_MONIKERALREADYREGISTERED;
135             WINE_TRACE("moniker already registered with cookie %d\n", existing_rot_entry->cookie);
136             break;
137         }
138     }
139
140     if (hr == S_OK)
141     {
142         list_add_tail(&RunningObjectTable, &rot_entry->entry);
143         /* gives a registration identifier to the registered object*/
144         *cookie = rot_entry->cookie = InterlockedIncrement(&last_cookie);
145         *ctxt_handle = rot_entry;
146     }
147     else
148     {
149         rot_entry_release(rot_entry);
150         *cookie = existing_rot_entry->cookie;
151         InterlockedIncrement(&existing_rot_entry->refs);
152         *ctxt_handle = existing_rot_entry;
153     }
154
155
156     LeaveCriticalSection(&csRunningObjectTable);
157
158     return hr;
159 }
160
161 HRESULT IrotRevoke(
162     IrotHandle h,
163     IrotCookie cookie,
164     IrotContextHandle *ctxt_handle,
165     PInterfaceData *obj,
166     PInterfaceData *mk)
167 {
168     struct rot_entry *rot_entry;
169
170     WINE_TRACE("%d\n", cookie);
171
172     EnterCriticalSection(&csRunningObjectTable);
173     LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, struct rot_entry, entry)
174     {
175         if (rot_entry->cookie == cookie)
176         {
177             HRESULT hr = S_OK;
178
179             list_remove(&rot_entry->entry);
180             LeaveCriticalSection(&csRunningObjectTable);
181
182             *obj = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->object->ulCntData]));
183             *mk = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->moniker->ulCntData]));
184             if (*obj && *mk)
185             {
186                 (*obj)->ulCntData = rot_entry->object->ulCntData;
187                 memcpy((*obj)->abData, rot_entry->object->abData, (*obj)->ulCntData);
188                 (*mk)->ulCntData = rot_entry->moniker->ulCntData;
189                 memcpy((*mk)->abData, rot_entry->moniker->abData, (*mk)->ulCntData);
190             }
191             else
192             {
193                 MIDL_user_free(*obj);
194                 MIDL_user_free(*mk);
195                 hr = E_OUTOFMEMORY;
196             }
197
198             rot_entry_release(rot_entry);
199             *ctxt_handle = NULL;
200             return hr;
201         }
202     }
203     LeaveCriticalSection(&csRunningObjectTable);
204
205     return E_INVALIDARG;
206 }
207
208 HRESULT IrotIsRunning(
209     IrotHandle h,
210     const MonikerComparisonData *data)
211 {
212     const struct rot_entry *rot_entry;
213     HRESULT hr = S_FALSE;
214
215     WINE_TRACE("\n");
216
217     EnterCriticalSection(&csRunningObjectTable);
218
219     LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
220     {
221         if ((rot_entry->moniker_data->ulCntData == data->ulCntData) &&
222             !memcmp(&data->abData, &rot_entry->moniker_data->abData, data->ulCntData))
223         {
224             hr = S_OK;
225             break;
226         }
227     }
228     LeaveCriticalSection(&csRunningObjectTable);
229
230     return hr;
231 }
232
233 HRESULT IrotGetObject(
234     IrotHandle h,
235     const MonikerComparisonData *moniker_data,
236     PInterfaceData *obj,
237     IrotCookie *cookie)
238 {
239     const struct rot_entry *rot_entry;
240
241     WINE_TRACE("%p\n", moniker_data);
242
243     *cookie = 0;
244
245     EnterCriticalSection(&csRunningObjectTable);
246
247     LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
248     {
249         HRESULT hr = S_OK;
250         if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
251             !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
252         {
253             *obj = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->object->ulCntData]));
254             if (*obj)
255             {
256                 (*obj)->ulCntData = rot_entry->object->ulCntData;
257                 memcpy((*obj)->abData, rot_entry->object->abData, (*obj)->ulCntData);
258
259                 *cookie = rot_entry->cookie;
260             }
261             else
262                 hr = E_OUTOFMEMORY;
263
264             LeaveCriticalSection(&csRunningObjectTable);
265
266             return hr;
267         }
268     }
269
270     LeaveCriticalSection(&csRunningObjectTable);
271
272     return MK_E_UNAVAILABLE;
273 }
274
275 HRESULT IrotNoteChangeTime(
276     IrotHandle h,
277     IrotCookie cookie,
278     const FILETIME *last_modified_time)
279 {
280     struct rot_entry *rot_entry;
281
282     WINE_TRACE("%d %p\n", cookie, last_modified_time);
283
284     EnterCriticalSection(&csRunningObjectTable);
285     LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, struct rot_entry, entry)
286     {
287         if (rot_entry->cookie == cookie)
288         {
289             rot_entry->last_modified = *last_modified_time;
290             LeaveCriticalSection(&csRunningObjectTable);
291             return S_OK;
292         }
293     }
294     LeaveCriticalSection(&csRunningObjectTable);
295
296     return E_INVALIDARG;
297 }
298
299 HRESULT IrotGetTimeOfLastChange(
300     IrotHandle h,
301     const MonikerComparisonData *moniker_data,
302     FILETIME *time)
303 {
304     const struct rot_entry *rot_entry;
305     HRESULT hr = MK_E_UNAVAILABLE;
306
307     WINE_TRACE("%p\n", moniker_data);
308
309     memset(time, 0, sizeof(*time));
310
311     EnterCriticalSection(&csRunningObjectTable);
312     LIST_FOR_EACH_ENTRY(rot_entry, &RunningObjectTable, const struct rot_entry, entry)
313     {
314         if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
315             !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
316         {
317             *time = rot_entry->last_modified;
318             hr = S_OK;
319             break;
320         }
321     }
322     LeaveCriticalSection(&csRunningObjectTable);
323
324     return hr;
325 }
326
327 HRESULT IrotEnumRunning(
328     IrotHandle h,
329     PInterfaceList *list)
330 {
331     const struct rot_entry *rot_entry;
332     HRESULT hr = S_OK;
333     ULONG moniker_count = 0;
334     ULONG i = 0;
335
336     WINE_TRACE("\n");
337
338     EnterCriticalSection(&csRunningObjectTable);
339
340     LIST_FOR_EACH_ENTRY( rot_entry, &RunningObjectTable, const struct rot_entry, entry )
341         moniker_count++;
342
343     *list = MIDL_user_allocate(FIELD_OFFSET(InterfaceList, interfaces[moniker_count]));
344     if (*list)
345     {
346         (*list)->size = moniker_count;
347         LIST_FOR_EACH_ENTRY( rot_entry, &RunningObjectTable, const struct rot_entry, entry )
348         {
349             (*list)->interfaces[i] = MIDL_user_allocate(FIELD_OFFSET(InterfaceData, abData[rot_entry->moniker->ulCntData]));
350             if (!(*list)->interfaces[i])
351             {
352                 ULONG end = i - 1;
353                 for (i = 0; i < end; i++)
354                     MIDL_user_free((*list)->interfaces[i]);
355                 MIDL_user_free(*list);
356                 hr = E_OUTOFMEMORY;
357                 break;
358             }
359             (*list)->interfaces[i]->ulCntData = rot_entry->moniker->ulCntData;
360             memcpy((*list)->interfaces[i]->abData, rot_entry->moniker->abData, rot_entry->moniker->ulCntData);
361             i++;
362         }
363     }
364     else
365         hr = E_OUTOFMEMORY;
366
367     LeaveCriticalSection(&csRunningObjectTable);
368
369     return hr;
370 }
371
372 void __RPC_USER IrotContextHandle_rundown(IrotContextHandle ctxt_handle)
373 {
374     struct rot_entry *rot_entry = ctxt_handle;
375     EnterCriticalSection(&csRunningObjectTable);
376     list_remove(&rot_entry->entry);
377     LeaveCriticalSection(&csRunningObjectTable);
378     rot_entry_release(rot_entry);
379 }
380
381 void * __RPC_USER MIDL_user_allocate(size_t size)
382 {
383     return HeapAlloc(GetProcessHeap(), 0, size);
384 }
385
386 void __RPC_USER MIDL_user_free(void * p)
387 {
388     HeapFree(GetProcessHeap(), 0, p);
389 }