Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenndr_contexthandle.c
Go to the documentation of this file.
00001 /* 00002 * NDR data marshalling 00003 * 00004 * Copyright 2006 Mike McCormack (for CodeWeavers) 00005 * Copyright 2006-2007 Robert Shearman (for CodeWeavers) 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include "ndr_misc.h" 00023 #include "rpc_assoc.h" 00024 #include "rpcndr.h" 00025 00026 #include "wine/rpcfc.h" 00027 00028 #include "wine/debug.h" 00029 #include "wine/list.h" 00030 00031 WINE_DEFAULT_DEBUG_CHANNEL(ole); 00032 00033 #define NDR_CONTEXT_HANDLE_MAGIC 0x4352444e 00034 00035 typedef struct ndr_context_handle 00036 { 00037 ULONG attributes; 00038 GUID uuid; 00039 } ndr_context_handle; 00040 00041 struct context_handle_entry 00042 { 00043 struct list entry; 00044 DWORD magic; 00045 RPC_BINDING_HANDLE handle; 00046 ndr_context_handle wire_data; 00047 }; 00048 00049 static struct list context_handle_list = LIST_INIT(context_handle_list); 00050 00051 static CRITICAL_SECTION ndr_context_cs; 00052 static CRITICAL_SECTION_DEBUG ndr_context_debug = 00053 { 00054 0, 0, &ndr_context_cs, 00055 { &ndr_context_debug.ProcessLocksList, &ndr_context_debug.ProcessLocksList }, 00056 0, 0, { (DWORD_PTR)(__FILE__ ": ndr_context") } 00057 }; 00058 static CRITICAL_SECTION ndr_context_cs = { &ndr_context_debug, -1, 0, 0, 0, 0 }; 00059 00060 static struct context_handle_entry *get_context_entry(NDR_CCONTEXT CContext) 00061 { 00062 struct context_handle_entry *che = CContext; 00063 00064 if (che->magic != NDR_CONTEXT_HANDLE_MAGIC) 00065 return NULL; 00066 return che; 00067 } 00068 00069 static struct context_handle_entry *context_entry_from_guid(LPCGUID uuid) 00070 { 00071 struct context_handle_entry *che; 00072 LIST_FOR_EACH_ENTRY(che, &context_handle_list, struct context_handle_entry, entry) 00073 if (IsEqualGUID(&che->wire_data.uuid, uuid)) 00074 return che; 00075 return NULL; 00076 } 00077 00078 RPC_BINDING_HANDLE WINAPI NDRCContextBinding(NDR_CCONTEXT CContext) 00079 { 00080 struct context_handle_entry *che; 00081 RPC_BINDING_HANDLE handle = NULL; 00082 00083 TRACE("%p\n", CContext); 00084 00085 EnterCriticalSection(&ndr_context_cs); 00086 che = get_context_entry(CContext); 00087 if (che) 00088 handle = che->handle; 00089 LeaveCriticalSection(&ndr_context_cs); 00090 00091 if (!handle) 00092 { 00093 ERR("invalid handle %p\n", CContext); 00094 RpcRaiseException(ERROR_INVALID_HANDLE); 00095 } 00096 return handle; 00097 } 00098 00099 void WINAPI NDRCContextMarshall(NDR_CCONTEXT CContext, void *pBuff) 00100 { 00101 struct context_handle_entry *che; 00102 00103 TRACE("%p %p\n", CContext, pBuff); 00104 00105 if (CContext) 00106 { 00107 EnterCriticalSection(&ndr_context_cs); 00108 che = get_context_entry(CContext); 00109 memcpy(pBuff, &che->wire_data, sizeof (ndr_context_handle)); 00110 LeaveCriticalSection(&ndr_context_cs); 00111 } 00112 else 00113 { 00114 ndr_context_handle *wire_data = pBuff; 00115 wire_data->attributes = 0; 00116 wire_data->uuid = GUID_NULL; 00117 } 00118 } 00119 00120 /*********************************************************************** 00121 * RpcSmDestroyClientContext [RPCRT4.@] 00122 */ 00123 RPC_STATUS WINAPI RpcSmDestroyClientContext(void **ContextHandle) 00124 { 00125 RPC_STATUS status = RPC_X_SS_CONTEXT_MISMATCH; 00126 struct context_handle_entry *che = NULL; 00127 00128 TRACE("(%p)\n", ContextHandle); 00129 00130 EnterCriticalSection(&ndr_context_cs); 00131 che = get_context_entry(*ContextHandle); 00132 *ContextHandle = NULL; 00133 if (che) 00134 { 00135 status = RPC_S_OK; 00136 list_remove(&che->entry); 00137 } 00138 00139 LeaveCriticalSection(&ndr_context_cs); 00140 00141 if (che) 00142 { 00143 RpcBindingFree(&che->handle); 00144 HeapFree(GetProcessHeap(), 0, che); 00145 } 00146 00147 return status; 00148 } 00149 00150 /*********************************************************************** 00151 * RpcSsDestroyClientContext [RPCRT4.@] 00152 */ 00153 void WINAPI RpcSsDestroyClientContext(void **ContextHandle) 00154 { 00155 RPC_STATUS status = RpcSmDestroyClientContext(ContextHandle); 00156 if (status != RPC_S_OK) 00157 RpcRaiseException(status); 00158 } 00159 00160 static UINT ndr_update_context_handle(NDR_CCONTEXT *CContext, 00161 RPC_BINDING_HANDLE hBinding, 00162 const ndr_context_handle *chi) 00163 { 00164 struct context_handle_entry *che = NULL; 00165 00166 /* a null UUID means we should free the context handle */ 00167 if (IsEqualGUID(&chi->uuid, &GUID_NULL)) 00168 { 00169 if (*CContext) 00170 { 00171 che = get_context_entry(*CContext); 00172 if (!che) 00173 return ERROR_INVALID_HANDLE; 00174 list_remove(&che->entry); 00175 RpcBindingFree(&che->handle); 00176 HeapFree(GetProcessHeap(), 0, che); 00177 che = NULL; 00178 } 00179 } 00180 /* if there's no existing entry matching the GUID, allocate one */ 00181 else if (!(che = context_entry_from_guid(&chi->uuid))) 00182 { 00183 che = HeapAlloc(GetProcessHeap(), 0, sizeof *che); 00184 if (!che) 00185 return ERROR_NOT_ENOUGH_MEMORY; 00186 che->magic = NDR_CONTEXT_HANDLE_MAGIC; 00187 RpcBindingCopy(hBinding, &che->handle); 00188 list_add_tail(&context_handle_list, &che->entry); 00189 che->wire_data = *chi; 00190 } 00191 00192 *CContext = che; 00193 00194 return ERROR_SUCCESS; 00195 } 00196 00197 /*********************************************************************** 00198 * NDRCContextUnmarshall [RPCRT4.@] 00199 */ 00200 void WINAPI NDRCContextUnmarshall(NDR_CCONTEXT *CContext, 00201 RPC_BINDING_HANDLE hBinding, 00202 void *pBuff, ULONG DataRepresentation) 00203 { 00204 UINT r; 00205 00206 TRACE("*%p=(%p) %p %p %08x\n", 00207 CContext, *CContext, hBinding, pBuff, DataRepresentation); 00208 00209 EnterCriticalSection(&ndr_context_cs); 00210 r = ndr_update_context_handle(CContext, hBinding, pBuff); 00211 LeaveCriticalSection(&ndr_context_cs); 00212 if (r) 00213 RpcRaiseException(r); 00214 } 00215 00216 /*********************************************************************** 00217 * NDRSContextMarshall [RPCRT4.@] 00218 */ 00219 void WINAPI NDRSContextMarshall(NDR_SCONTEXT SContext, 00220 void *pBuff, 00221 NDR_RUNDOWN userRunDownIn) 00222 { 00223 TRACE("(%p %p %p)\n", SContext, pBuff, userRunDownIn); 00224 NDRSContextMarshall2(I_RpcGetCurrentCallHandle(), SContext, pBuff, 00225 userRunDownIn, NULL, RPC_CONTEXT_HANDLE_DEFAULT_FLAGS); 00226 } 00227 00228 /*********************************************************************** 00229 * NDRSContextMarshallEx [RPCRT4.@] 00230 */ 00231 void WINAPI NDRSContextMarshallEx(RPC_BINDING_HANDLE hBinding, 00232 NDR_SCONTEXT SContext, 00233 void *pBuff, 00234 NDR_RUNDOWN userRunDownIn) 00235 { 00236 TRACE("(%p %p %p %p)\n", hBinding, SContext, pBuff, userRunDownIn); 00237 NDRSContextMarshall2(hBinding, SContext, pBuff, userRunDownIn, NULL, 00238 RPC_CONTEXT_HANDLE_DEFAULT_FLAGS); 00239 } 00240 00241 /*********************************************************************** 00242 * NDRSContextMarshall2 [RPCRT4.@] 00243 */ 00244 void WINAPI NDRSContextMarshall2(RPC_BINDING_HANDLE hBinding, 00245 NDR_SCONTEXT SContext, 00246 void *pBuff, 00247 NDR_RUNDOWN userRunDownIn, 00248 void *CtxGuard, ULONG Flags) 00249 { 00250 RpcBinding *binding = hBinding; 00251 RPC_STATUS status; 00252 ndr_context_handle *ndr = pBuff; 00253 00254 TRACE("(%p %p %p %p %p %u)\n", 00255 hBinding, SContext, pBuff, userRunDownIn, CtxGuard, Flags); 00256 00257 if (!binding->server || !binding->Assoc) 00258 RpcRaiseException(ERROR_INVALID_HANDLE); 00259 00260 if (Flags & RPC_CONTEXT_HANDLE_FLAGS) 00261 FIXME("unimplemented flags: 0x%x\n", Flags & RPC_CONTEXT_HANDLE_FLAGS); 00262 00263 if (SContext->userContext) 00264 { 00265 status = RpcServerAssoc_UpdateContextHandle(binding->Assoc, SContext, CtxGuard, userRunDownIn); 00266 if (status != RPC_S_OK) 00267 RpcRaiseException(status); 00268 ndr->attributes = 0; 00269 RpcContextHandle_GetUuid(SContext, &ndr->uuid); 00270 00271 RPCRT4_RemoveThreadContextHandle(SContext); 00272 RpcServerAssoc_ReleaseContextHandle(binding->Assoc, SContext, TRUE); 00273 } 00274 else 00275 { 00276 if (!RpcContextHandle_IsGuardCorrect(SContext, CtxGuard)) 00277 RpcRaiseException(ERROR_INVALID_HANDLE); 00278 memset(ndr, 0, sizeof(*ndr)); 00279 00280 RPCRT4_RemoveThreadContextHandle(SContext); 00281 /* Note: release the context handle twice in this case to release 00282 * one ref being kept around for the data and one ref for the 00283 * unmarshall/marshall sequence */ 00284 if (!RpcServerAssoc_ReleaseContextHandle(binding->Assoc, SContext, TRUE)) 00285 return; /* this is to cope with the case of the data not being valid 00286 * before and so not having a further reference */ 00287 RpcServerAssoc_ReleaseContextHandle(binding->Assoc, SContext, FALSE); 00288 } 00289 } 00290 00291 /*********************************************************************** 00292 * NDRSContextUnmarshall [RPCRT4.@] 00293 */ 00294 NDR_SCONTEXT WINAPI NDRSContextUnmarshall(void *pBuff, 00295 ULONG DataRepresentation) 00296 { 00297 TRACE("(%p %08x)\n", pBuff, DataRepresentation); 00298 return NDRSContextUnmarshall2(I_RpcGetCurrentCallHandle(), pBuff, 00299 DataRepresentation, NULL, 00300 RPC_CONTEXT_HANDLE_DEFAULT_FLAGS); 00301 } 00302 00303 /*********************************************************************** 00304 * NDRSContextUnmarshallEx [RPCRT4.@] 00305 */ 00306 NDR_SCONTEXT WINAPI NDRSContextUnmarshallEx(RPC_BINDING_HANDLE hBinding, 00307 void *pBuff, 00308 ULONG DataRepresentation) 00309 { 00310 TRACE("(%p %p %08x)\n", hBinding, pBuff, DataRepresentation); 00311 return NDRSContextUnmarshall2(hBinding, pBuff, DataRepresentation, NULL, 00312 RPC_CONTEXT_HANDLE_DEFAULT_FLAGS); 00313 } 00314 00315 /*********************************************************************** 00316 * NDRSContextUnmarshall2 [RPCRT4.@] 00317 */ 00318 NDR_SCONTEXT WINAPI NDRSContextUnmarshall2(RPC_BINDING_HANDLE hBinding, 00319 void *pBuff, 00320 ULONG DataRepresentation, 00321 void *CtxGuard, ULONG Flags) 00322 { 00323 RpcBinding *binding = hBinding; 00324 NDR_SCONTEXT SContext; 00325 RPC_STATUS status; 00326 const ndr_context_handle *context_ndr = pBuff; 00327 00328 TRACE("(%p %p %08x %p %u)\n", 00329 hBinding, pBuff, DataRepresentation, CtxGuard, Flags); 00330 00331 if (!binding->server || !binding->Assoc) 00332 RpcRaiseException(ERROR_INVALID_HANDLE); 00333 00334 if (Flags & RPC_CONTEXT_HANDLE_FLAGS) 00335 FIXME("unimplemented flags: 0x%x\n", Flags & RPC_CONTEXT_HANDLE_FLAGS); 00336 00337 if (!pBuff || (!context_ndr->attributes && 00338 UuidIsNil((UUID *)&context_ndr->uuid, &status))) 00339 status = RpcServerAssoc_AllocateContextHandle(binding->Assoc, CtxGuard, 00340 &SContext); 00341 else 00342 { 00343 if (context_ndr->attributes) 00344 { 00345 ERR("non-null attributes 0x%x\n", context_ndr->attributes); 00346 status = ERROR_INVALID_HANDLE; 00347 } 00348 else 00349 status = RpcServerAssoc_FindContextHandle(binding->Assoc, 00350 &context_ndr->uuid, 00351 CtxGuard, Flags, 00352 &SContext); 00353 } 00354 00355 if (status != RPC_S_OK) 00356 RpcRaiseException(status); 00357 00358 RPCRT4_PushThreadContextHandle(SContext); 00359 return SContext; 00360 } Generated on Sun May 27 2012 04:26:01 for ReactOS by
1.7.6.1
|