dsdmo: Add Flanger effect stub.
[wine.git] / dlls / rpcrt4 / ndr_contexthandle.c
blob1bff1e8293672d39da304cd08011331bf1ddec5a
1 /*
2 * NDR data marshalling
4 * Copyright 2006 Mike McCormack (for CodeWeavers)
5 * Copyright 2006-2007 Robert Shearman (for CodeWeavers)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdlib.h>
24 #include "ndr_misc.h"
25 #include "rpc_assoc.h"
26 #include "rpcndr.h"
27 #include "cguid.h"
29 #include "wine/debug.h"
30 #include "wine/list.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(ole);
34 #define NDR_CONTEXT_HANDLE_MAGIC 0x4352444e
36 typedef struct ndr_context_handle
38 ULONG attributes;
39 GUID uuid;
40 } ndr_context_handle;
42 struct context_handle_entry
44 struct list entry;
45 DWORD magic;
46 RPC_BINDING_HANDLE handle;
47 ndr_context_handle wire_data;
50 static struct list context_handle_list = LIST_INIT(context_handle_list);
52 static CRITICAL_SECTION ndr_context_cs;
53 static CRITICAL_SECTION_DEBUG ndr_context_debug =
55 0, 0, &ndr_context_cs,
56 { &ndr_context_debug.ProcessLocksList, &ndr_context_debug.ProcessLocksList },
57 0, 0, { (DWORD_PTR)(__FILE__ ": ndr_context") }
59 static CRITICAL_SECTION ndr_context_cs = { &ndr_context_debug, -1, 0, 0, 0, 0 };
61 static struct context_handle_entry *get_context_entry(NDR_CCONTEXT CContext)
63 struct context_handle_entry *che = CContext;
65 if (che->magic != NDR_CONTEXT_HANDLE_MAGIC)
66 return NULL;
67 return che;
70 static struct context_handle_entry *context_entry_from_guid(LPCGUID uuid)
72 struct context_handle_entry *che;
73 LIST_FOR_EACH_ENTRY(che, &context_handle_list, struct context_handle_entry, entry)
74 if (IsEqualGUID(&che->wire_data.uuid, uuid))
75 return che;
76 return NULL;
79 RPC_BINDING_HANDLE WINAPI NDRCContextBinding(NDR_CCONTEXT CContext)
81 struct context_handle_entry *che;
82 RPC_BINDING_HANDLE handle = NULL;
84 TRACE("%p\n", CContext);
86 EnterCriticalSection(&ndr_context_cs);
87 che = get_context_entry(CContext);
88 if (che)
89 handle = che->handle;
90 LeaveCriticalSection(&ndr_context_cs);
92 if (!handle)
94 ERR("invalid handle %p\n", CContext);
95 RpcRaiseException(RPC_X_SS_CONTEXT_MISMATCH);
97 return handle;
100 void WINAPI NDRCContextMarshall(NDR_CCONTEXT CContext, void *pBuff)
102 struct context_handle_entry *che;
104 TRACE("%p %p\n", CContext, pBuff);
106 if (CContext)
108 EnterCriticalSection(&ndr_context_cs);
109 che = get_context_entry(CContext);
110 memcpy(pBuff, &che->wire_data, sizeof (ndr_context_handle));
111 LeaveCriticalSection(&ndr_context_cs);
113 else
115 ndr_context_handle *wire_data = pBuff;
116 wire_data->attributes = 0;
117 wire_data->uuid = GUID_NULL;
121 /***********************************************************************
122 * RpcSmDestroyClientContext [RPCRT4.@]
124 RPC_STATUS WINAPI RpcSmDestroyClientContext(void **ContextHandle)
126 RPC_STATUS status = RPC_X_SS_CONTEXT_MISMATCH;
127 struct context_handle_entry *che = NULL;
129 TRACE("(%p)\n", ContextHandle);
131 EnterCriticalSection(&ndr_context_cs);
132 che = get_context_entry(*ContextHandle);
133 *ContextHandle = NULL;
134 if (che)
136 status = RPC_S_OK;
137 list_remove(&che->entry);
140 LeaveCriticalSection(&ndr_context_cs);
142 if (che)
144 RpcBindingFree(&che->handle);
145 free(che);
148 return status;
151 /***********************************************************************
152 * RpcSsDestroyClientContext [RPCRT4.@]
154 void WINAPI RpcSsDestroyClientContext(void **ContextHandle)
156 RPC_STATUS status = RpcSmDestroyClientContext(ContextHandle);
157 if (status != RPC_S_OK)
158 RpcRaiseException(status);
161 /***********************************************************************
162 * RpcSsDontSerializeContext [RPCRT4.@]
164 void WINAPI RpcSsDontSerializeContext(void)
166 FIXME("stub\n");
169 static RPC_STATUS ndr_update_context_handle(NDR_CCONTEXT *CContext,
170 RPC_BINDING_HANDLE hBinding,
171 const ndr_context_handle *chi)
173 struct context_handle_entry *che = NULL;
175 /* a null UUID means we should free the context handle */
176 if (IsEqualGUID(&chi->uuid, &GUID_NULL))
178 if (*CContext)
180 che = get_context_entry(*CContext);
181 if (!che)
182 return RPC_X_SS_CONTEXT_MISMATCH;
183 list_remove(&che->entry);
184 RpcBindingFree(&che->handle);
185 free(che);
186 che = NULL;
189 /* if there's no existing entry matching the GUID, allocate one */
190 else if (!(che = context_entry_from_guid(&chi->uuid)))
192 che = malloc(sizeof *che);
193 if (!che)
194 return RPC_X_NO_MEMORY;
195 che->magic = NDR_CONTEXT_HANDLE_MAGIC;
196 RpcBindingCopy(hBinding, &che->handle);
197 list_add_tail(&context_handle_list, &che->entry);
198 che->wire_data = *chi;
201 *CContext = che;
203 return RPC_S_OK;
206 /***********************************************************************
207 * NDRCContextUnmarshall [RPCRT4.@]
209 void WINAPI NDRCContextUnmarshall(NDR_CCONTEXT *CContext,
210 RPC_BINDING_HANDLE hBinding,
211 void *pBuff, ULONG DataRepresentation)
213 RPC_STATUS status;
215 TRACE("*%p=(%p) %p %p %08lx\n",
216 CContext, *CContext, hBinding, pBuff, DataRepresentation);
218 EnterCriticalSection(&ndr_context_cs);
219 status = ndr_update_context_handle(CContext, hBinding, pBuff);
220 LeaveCriticalSection(&ndr_context_cs);
221 if (status)
222 RpcRaiseException(status);
225 /***********************************************************************
226 * NDRSContextMarshall [RPCRT4.@]
228 void WINAPI NDRSContextMarshall(NDR_SCONTEXT SContext,
229 void *pBuff,
230 NDR_RUNDOWN userRunDownIn)
232 TRACE("(%p %p %p)\n", SContext, pBuff, userRunDownIn);
233 NDRSContextMarshall2(I_RpcGetCurrentCallHandle(), SContext, pBuff,
234 userRunDownIn, NULL, RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
237 /***********************************************************************
238 * NDRSContextMarshallEx [RPCRT4.@]
240 void WINAPI NDRSContextMarshallEx(RPC_BINDING_HANDLE hBinding,
241 NDR_SCONTEXT SContext,
242 void *pBuff,
243 NDR_RUNDOWN userRunDownIn)
245 TRACE("(%p %p %p %p)\n", hBinding, SContext, pBuff, userRunDownIn);
246 NDRSContextMarshall2(hBinding, SContext, pBuff, userRunDownIn, NULL,
247 RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
250 /***********************************************************************
251 * NDRSContextMarshall2 [RPCRT4.@]
253 void WINAPI NDRSContextMarshall2(RPC_BINDING_HANDLE hBinding,
254 NDR_SCONTEXT SContext,
255 void *pBuff,
256 NDR_RUNDOWN userRunDownIn,
257 void *CtxGuard, ULONG Flags)
259 RpcBinding *binding = hBinding;
260 RPC_STATUS status;
261 ndr_context_handle *ndr = pBuff;
263 TRACE("(%p %p %p %p %p %lu)\n",
264 hBinding, SContext, pBuff, userRunDownIn, CtxGuard, Flags);
266 if (!binding->server || !binding->Assoc)
267 RpcRaiseException(RPC_S_INVALID_BINDING);
269 if (SContext->userContext)
271 status = RpcServerAssoc_UpdateContextHandle(binding->Assoc, SContext, CtxGuard, userRunDownIn);
272 if (status != RPC_S_OK)
273 RpcRaiseException(status);
274 ndr->attributes = 0;
275 RpcContextHandle_GetUuid(SContext, &ndr->uuid);
277 RPCRT4_RemoveThreadContextHandle(SContext);
278 RpcServerAssoc_ReleaseContextHandle(binding->Assoc, SContext, TRUE);
280 else
282 if (!RpcContextHandle_IsGuardCorrect(SContext, CtxGuard))
283 RpcRaiseException(RPC_X_SS_CONTEXT_MISMATCH);
284 memset(ndr, 0, sizeof(*ndr));
286 RPCRT4_RemoveThreadContextHandle(SContext);
287 /* Note: release the context handle twice in this case to release
288 * one ref being kept around for the data and one ref for the
289 * unmarshall/marshall sequence */
290 if (!RpcServerAssoc_ReleaseContextHandle(binding->Assoc, SContext, TRUE))
291 return; /* this is to cope with the case of the data not being valid
292 * before and so not having a further reference */
293 RpcServerAssoc_ReleaseContextHandle(binding->Assoc, SContext, FALSE);
297 /***********************************************************************
298 * NDRSContextUnmarshall [RPCRT4.@]
300 NDR_SCONTEXT WINAPI NDRSContextUnmarshall(void *pBuff,
301 ULONG DataRepresentation)
303 TRACE("(%p %08lx)\n", pBuff, DataRepresentation);
304 return NDRSContextUnmarshall2(I_RpcGetCurrentCallHandle(), pBuff,
305 DataRepresentation, NULL,
306 RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
309 /***********************************************************************
310 * NDRSContextUnmarshallEx [RPCRT4.@]
312 NDR_SCONTEXT WINAPI NDRSContextUnmarshallEx(RPC_BINDING_HANDLE hBinding,
313 void *pBuff,
314 ULONG DataRepresentation)
316 TRACE("(%p %p %08lx)\n", hBinding, pBuff, DataRepresentation);
317 return NDRSContextUnmarshall2(hBinding, pBuff, DataRepresentation, NULL,
318 RPC_CONTEXT_HANDLE_DEFAULT_FLAGS);
321 /***********************************************************************
322 * NDRSContextUnmarshall2 [RPCRT4.@]
324 NDR_SCONTEXT WINAPI NDRSContextUnmarshall2(RPC_BINDING_HANDLE hBinding,
325 void *pBuff,
326 ULONG DataRepresentation,
327 void *CtxGuard, ULONG Flags)
329 RpcBinding *binding = hBinding;
330 NDR_SCONTEXT SContext;
331 RPC_STATUS status;
332 const ndr_context_handle *context_ndr = pBuff;
334 TRACE("(%p %p %08lx %p %lu)\n",
335 hBinding, pBuff, DataRepresentation, CtxGuard, Flags);
337 if (!binding->server || !binding->Assoc)
338 RpcRaiseException(RPC_S_INVALID_BINDING);
340 if (!pBuff || (!context_ndr->attributes &&
341 UuidIsNil((UUID *)&context_ndr->uuid, &status)))
342 status = RpcServerAssoc_AllocateContextHandle(binding->Assoc, CtxGuard,
343 &SContext);
344 else
346 if (context_ndr->attributes)
348 ERR("non-null attributes 0x%lx\n", context_ndr->attributes);
349 status = RPC_X_SS_CONTEXT_MISMATCH;
351 else
352 status = RpcServerAssoc_FindContextHandle(binding->Assoc,
353 &context_ndr->uuid,
354 CtxGuard, Flags,
355 &SContext);
358 if (status != RPC_S_OK)
359 RpcRaiseException(status);
361 RPCRT4_PushThreadContextHandle(SContext);
362 return SContext;