| 1 | // Licensed to the .NET Foundation under one or more agreements. |
| 2 | // The .NET Foundation licenses this file to you under the MIT license. |
| 3 | // See the LICENSE file in the project root for more information. |
| 4 | // |
| 5 | // File: CustomMarshalerInfo.cpp |
| 6 | // |
| 7 | |
| 8 | // |
| 9 | // Custom marshaler information used when marshaling |
| 10 | // a parameter with a custom marshaler. |
| 11 | // |
| 12 | |
| 13 | |
| 14 | #include "common.h" |
| 15 | |
| 16 | |
| 17 | #include "custommarshalerinfo.h" |
| 18 | #include "mlinfo.h" |
| 19 | #include "mdaassistants.h" |
| 20 | #include "sigbuilder.h" |
| 21 | |
| 22 | //========================================================================== |
| 23 | // Implementation of the custom marshaler info class. |
| 24 | //========================================================================== |
| 25 | |
| 26 | CustomMarshalerInfo::CustomMarshalerInfo(BaseDomain *pDomain, TypeHandle hndCustomMarshalerType, TypeHandle hndManagedType, LPCUTF8 strCookie, DWORD cCookieStrBytes) |
| 27 | : m_NativeSize(0) |
| 28 | , m_hndManagedType(hndManagedType) |
| 29 | , m_hndCustomMarshaler(NULL) |
| 30 | , m_pMarshalNativeToManagedMD(NULL) |
| 31 | , m_pMarshalManagedToNativeMD(NULL) |
| 32 | , m_pCleanUpNativeDataMD(NULL) |
| 33 | , m_pCleanUpManagedDataMD(NULL) |
| 34 | , m_bDataIsByValue(FALSE) |
| 35 | { |
| 36 | CONTRACTL |
| 37 | { |
| 38 | THROWS; |
| 39 | GC_TRIGGERS; |
| 40 | MODE_COOPERATIVE; |
| 41 | PRECONDITION(CheckPointer(pDomain)); |
| 42 | } |
| 43 | CONTRACTL_END; |
| 44 | |
| 45 | |
| 46 | // Make sure the custom marshaller implements ICustomMarshaler. |
| 47 | if (!hndCustomMarshalerType.GetMethodTable()->CanCastToNonVariantInterface(MscorlibBinder::GetClass(CLASS__ICUSTOM_MARSHALER))) |
| 48 | { |
| 49 | DefineFullyQualifiedNameForClassW() |
| 50 | COMPlusThrow(kApplicationException, |
| 51 | IDS_EE_ICUSTOMMARSHALERNOTIMPL, |
| 52 | GetFullyQualifiedNameForClassW(hndCustomMarshalerType.GetMethodTable())); |
| 53 | } |
| 54 | |
| 55 | // Determine if this type is a value class. |
| 56 | m_bDataIsByValue = m_hndManagedType.GetMethodTable()->IsValueType(); |
| 57 | |
| 58 | // Custom marshalling of value classes is not currently supported. |
| 59 | if (m_bDataIsByValue) |
| 60 | COMPlusThrow(kNotSupportedException, W("NotSupported_ValueClassCM" )); |
| 61 | |
| 62 | #ifndef CROSSGEN_COMPILE |
| 63 | // Run the <clinit> on the marshaler since it might not have run yet. |
| 64 | hndCustomMarshalerType.GetMethodTable()->EnsureInstanceActive(); |
| 65 | hndCustomMarshalerType.GetMethodTable()->CheckRunClassInitThrowing(); |
| 66 | |
| 67 | // Create a COM+ string that will contain the string cookie. |
| 68 | STRINGREF CookieStringObj = StringObject::NewString(strCookie, cCookieStrBytes); |
| 69 | GCPROTECT_BEGIN(CookieStringObj); |
| 70 | #endif |
| 71 | |
| 72 | // Load the method desc's for all the methods in the ICustomMarshaler interface. |
| 73 | m_pMarshalNativeToManagedMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalNativeToManaged, hndCustomMarshalerType); |
| 74 | m_pMarshalManagedToNativeMD = GetCustomMarshalerMD(CustomMarshalerMethods_MarshalManagedToNative, hndCustomMarshalerType); |
| 75 | m_pCleanUpNativeDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpNativeData, hndCustomMarshalerType); |
| 76 | m_pCleanUpManagedDataMD = GetCustomMarshalerMD(CustomMarshalerMethods_CleanUpManagedData, hndCustomMarshalerType); |
| 77 | |
| 78 | // Load the method desc for the static method to retrieve the instance. |
| 79 | MethodDesc *pGetCustomMarshalerMD = GetCustomMarshalerMD(CustomMarshalerMethods_GetInstance, hndCustomMarshalerType); |
| 80 | |
| 81 | // If the GetInstance method is generic, get an instantiating stub for it - |
| 82 | // the CallDescr infrastructure doesn't know how to pass secret generic arguments. |
| 83 | if (pGetCustomMarshalerMD->RequiresInstMethodTableArg()) |
| 84 | { |
| 85 | pGetCustomMarshalerMD = MethodDesc::FindOrCreateAssociatedMethodDesc( |
| 86 | pGetCustomMarshalerMD, |
| 87 | hndCustomMarshalerType.GetMethodTable(), |
| 88 | FALSE, // forceBoxedEntryPoint |
| 89 | Instantiation(), // methodInst |
| 90 | FALSE, // allowInstParam |
| 91 | FALSE); // forceRemotableMethod |
| 92 | |
| 93 | _ASSERTE(!pGetCustomMarshalerMD->RequiresInstMethodTableArg()); |
| 94 | } |
| 95 | |
| 96 | #ifndef CROSSGEN_COMPILE |
| 97 | MethodDescCallSite getCustomMarshaler(pGetCustomMarshalerMD, (OBJECTREF*)&CookieStringObj); |
| 98 | |
| 99 | pGetCustomMarshalerMD->EnsureActive(); |
| 100 | |
| 101 | // Prepare the arguments that will be passed to GetCustomMarshaler. |
| 102 | ARG_SLOT GetCustomMarshalerArgs[] = { |
| 103 | ObjToArgSlot(CookieStringObj) |
| 104 | }; |
| 105 | |
| 106 | // Call the GetCustomMarshaler method to retrieve the custom marshaler to use. |
| 107 | OBJECTREF CustomMarshalerObj = getCustomMarshaler.Call_RetOBJECTREF(GetCustomMarshalerArgs); |
| 108 | if (!CustomMarshalerObj) |
| 109 | { |
| 110 | DefineFullyQualifiedNameForClassW() |
| 111 | COMPlusThrow(kApplicationException, |
| 112 | IDS_EE_NOCUSTOMMARSHALER, |
| 113 | GetFullyQualifiedNameForClassW(hndCustomMarshalerType.GetMethodTable())); |
| 114 | } |
| 115 | m_hndCustomMarshaler = pDomain->CreateHandle(CustomMarshalerObj); |
| 116 | |
| 117 | // Retrieve the size of the native data. |
| 118 | if (m_bDataIsByValue) |
| 119 | { |
| 120 | // <TODO>@TODO(DM): Call GetNativeDataSize() to retrieve the size of the native data.</TODO> |
| 121 | _ASSERTE(!"Value classes are not yet supported by the custom marshaler!" ); |
| 122 | } |
| 123 | else |
| 124 | { |
| 125 | m_NativeSize = sizeof(void *); |
| 126 | } |
| 127 | |
| 128 | GCPROTECT_END(); |
| 129 | #endif |
| 130 | } |
| 131 | |
| 132 | |
| 133 | CustomMarshalerInfo::~CustomMarshalerInfo() |
| 134 | { |
| 135 | WRAPPER_NO_CONTRACT; |
| 136 | #ifndef CROSSGEN_COMPILE |
| 137 | if (m_hndCustomMarshaler) |
| 138 | { |
| 139 | DestroyHandle(m_hndCustomMarshaler); |
| 140 | m_hndCustomMarshaler = NULL; |
| 141 | } |
| 142 | #endif |
| 143 | } |
| 144 | |
| 145 | |
| 146 | void *CustomMarshalerInfo::operator new(size_t size, LoaderHeap *pHeap) |
| 147 | { |
| 148 | CONTRACTL |
| 149 | { |
| 150 | THROWS; |
| 151 | GC_NOTRIGGER; |
| 152 | MODE_ANY; |
| 153 | INJECT_FAULT(COMPlusThrowOM()); |
| 154 | PRECONDITION(CheckPointer(pHeap)); |
| 155 | } |
| 156 | CONTRACTL_END; |
| 157 | |
| 158 | return pHeap->AllocMem(S_SIZE_T(sizeof(CustomMarshalerInfo))); |
| 159 | } |
| 160 | |
| 161 | |
| 162 | void CustomMarshalerInfo::operator delete(void *pMem) |
| 163 | { |
| 164 | // Instances of this class are always allocated on the loader heap so |
| 165 | // the delete operator has nothing to do. |
| 166 | LIMITED_METHOD_CONTRACT; |
| 167 | } |
| 168 | |
| 169 | #ifndef CROSSGEN_COMPILE |
| 170 | OBJECTREF CustomMarshalerInfo::InvokeMarshalNativeToManagedMeth(void *pNative) |
| 171 | { |
| 172 | CONTRACTL |
| 173 | { |
| 174 | THROWS; |
| 175 | GC_TRIGGERS; |
| 176 | MODE_COOPERATIVE; |
| 177 | PRECONDITION(CheckPointer(pNative, NULL_OK)); |
| 178 | } |
| 179 | CONTRACTL_END; |
| 180 | |
| 181 | if (!pNative) |
| 182 | return NULL; |
| 183 | |
| 184 | MethodDescCallSite marshalNativeToManaged(m_pMarshalNativeToManagedMD, m_hndCustomMarshaler); |
| 185 | |
| 186 | ARG_SLOT Args[] = { |
| 187 | ObjToArgSlot(ObjectFromHandle(m_hndCustomMarshaler)), |
| 188 | PtrToArgSlot(pNative) |
| 189 | }; |
| 190 | |
| 191 | return marshalNativeToManaged.Call_RetOBJECTREF(Args); |
| 192 | } |
| 193 | |
| 194 | |
| 195 | void *CustomMarshalerInfo::InvokeMarshalManagedToNativeMeth(OBJECTREF MngObj) |
| 196 | { |
| 197 | CONTRACTL |
| 198 | { |
| 199 | THROWS; |
| 200 | GC_TRIGGERS; |
| 201 | MODE_COOPERATIVE; |
| 202 | } |
| 203 | CONTRACTL_END; |
| 204 | |
| 205 | void *RetVal = NULL; |
| 206 | |
| 207 | if (!MngObj) |
| 208 | return NULL; |
| 209 | |
| 210 | GCPROTECT_BEGIN (MngObj); |
| 211 | MethodDescCallSite marshalManagedToNative(m_pMarshalManagedToNativeMD, m_hndCustomMarshaler); |
| 212 | |
| 213 | ARG_SLOT Args[] = { |
| 214 | ObjToArgSlot(ObjectFromHandle(m_hndCustomMarshaler)), |
| 215 | ObjToArgSlot(MngObj) |
| 216 | }; |
| 217 | |
| 218 | RetVal = marshalManagedToNative.Call_RetLPVOID(Args); |
| 219 | GCPROTECT_END (); |
| 220 | |
| 221 | return RetVal; |
| 222 | } |
| 223 | |
| 224 | |
| 225 | void CustomMarshalerInfo::InvokeCleanUpNativeMeth(void *pNative) |
| 226 | { |
| 227 | CONTRACTL |
| 228 | { |
| 229 | THROWS; |
| 230 | GC_TRIGGERS; |
| 231 | MODE_COOPERATIVE; |
| 232 | PRECONDITION(CheckPointer(pNative, NULL_OK)); |
| 233 | } |
| 234 | CONTRACTL_END; |
| 235 | |
| 236 | if (!pNative) |
| 237 | return; |
| 238 | |
| 239 | MethodDescCallSite cleanUpNativeData(m_pCleanUpNativeDataMD, m_hndCustomMarshaler); |
| 240 | |
| 241 | ARG_SLOT Args[] = { |
| 242 | ObjToArgSlot(ObjectFromHandle(m_hndCustomMarshaler)), |
| 243 | PtrToArgSlot(pNative) |
| 244 | }; |
| 245 | |
| 246 | cleanUpNativeData.Call(Args); |
| 247 | } |
| 248 | |
| 249 | |
| 250 | void CustomMarshalerInfo::InvokeCleanUpManagedMeth(OBJECTREF MngObj) |
| 251 | { |
| 252 | CONTRACTL |
| 253 | { |
| 254 | THROWS; |
| 255 | GC_TRIGGERS; |
| 256 | MODE_COOPERATIVE; |
| 257 | } |
| 258 | CONTRACTL_END; |
| 259 | |
| 260 | if (!MngObj) |
| 261 | return; |
| 262 | |
| 263 | GCPROTECT_BEGIN (MngObj); |
| 264 | MethodDescCallSite cleanUpManagedData(m_pCleanUpManagedDataMD, m_hndCustomMarshaler); |
| 265 | |
| 266 | ARG_SLOT Args[] = { |
| 267 | ObjToArgSlot(ObjectFromHandle(m_hndCustomMarshaler)), |
| 268 | ObjToArgSlot(MngObj) |
| 269 | }; |
| 270 | |
| 271 | cleanUpManagedData.Call(Args); |
| 272 | GCPROTECT_END (); |
| 273 | } |
| 274 | |
| 275 | #endif // CROSSGEN_COMPILE |
| 276 | MethodDesc *CustomMarshalerInfo::GetCustomMarshalerMD(EnumCustomMarshalerMethods Method, TypeHandle hndCustomMarshalertype) |
| 277 | { |
| 278 | CONTRACTL |
| 279 | { |
| 280 | THROWS; |
| 281 | GC_TRIGGERS; |
| 282 | MODE_COOPERATIVE; |
| 283 | } |
| 284 | CONTRACTL_END; |
| 285 | |
| 286 | |
| 287 | MethodTable *pMT = hndCustomMarshalertype.AsMethodTable(); |
| 288 | |
| 289 | _ASSERTE(pMT->CanCastToNonVariantInterface(MscorlibBinder::GetClass(CLASS__ICUSTOM_MARSHALER))); |
| 290 | |
| 291 | MethodDesc *pMD = NULL; |
| 292 | |
| 293 | switch (Method) |
| 294 | { |
| 295 | case CustomMarshalerMethods_MarshalNativeToManaged: |
| 296 | pMD = pMT->GetMethodDescForInterfaceMethod( |
| 297 | MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__MARSHAL_NATIVE_TO_MANAGED), |
| 298 | TRUE /* throwOnConflict */); |
| 299 | break; |
| 300 | case CustomMarshalerMethods_MarshalManagedToNative: |
| 301 | pMD = pMT->GetMethodDescForInterfaceMethod( |
| 302 | MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__MARSHAL_MANAGED_TO_NATIVE), |
| 303 | TRUE /* throwOnConflict */); |
| 304 | break; |
| 305 | case CustomMarshalerMethods_CleanUpNativeData: |
| 306 | pMD = pMT->GetMethodDescForInterfaceMethod( |
| 307 | MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__CLEANUP_NATIVE_DATA), |
| 308 | TRUE /* throwOnConflict */); |
| 309 | break; |
| 310 | |
| 311 | case CustomMarshalerMethods_CleanUpManagedData: |
| 312 | pMD = pMT->GetMethodDescForInterfaceMethod( |
| 313 | MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__CLEANUP_MANAGED_DATA), |
| 314 | TRUE /* throwOnConflict */); |
| 315 | break; |
| 316 | case CustomMarshalerMethods_GetNativeDataSize: |
| 317 | pMD = pMT->GetMethodDescForInterfaceMethod( |
| 318 | MscorlibBinder::GetMethod(METHOD__ICUSTOM_MARSHALER__GET_NATIVE_DATA_SIZE), |
| 319 | TRUE /* throwOnConflict */); |
| 320 | break; |
| 321 | case CustomMarshalerMethods_GetInstance: |
| 322 | // Must look this up by name since it's static |
| 323 | pMD = MemberLoader::FindMethod(pMT, "GetInstance" , &gsig_SM_Str_RetICustomMarshaler); |
| 324 | if (!pMD) |
| 325 | { |
| 326 | DefineFullyQualifiedNameForClassW() |
| 327 | COMPlusThrow(kApplicationException, |
| 328 | IDS_EE_GETINSTANCENOTIMPL, |
| 329 | GetFullyQualifiedNameForClassW(pMT)); |
| 330 | } |
| 331 | break; |
| 332 | default: |
| 333 | _ASSERTE(!"Unknown custom marshaler method" ); |
| 334 | } |
| 335 | |
| 336 | _ASSERTE(pMD && "Unable to find specified CustomMarshaler method" ); |
| 337 | |
| 338 | // Ensure that the value types in the signature are loaded. |
| 339 | MetaSig::EnsureSigValueTypesLoaded(pMD); |
| 340 | |
| 341 | // Return the specified method desc. |
| 342 | return pMD; |
| 343 | } |
| 344 | |
| 345 | #ifndef CROSSGEN_COMPILE |
| 346 | |
| 347 | //========================================================================== |
| 348 | // Implementation of the custom marshaler hashtable helper. |
| 349 | //========================================================================== |
| 350 | |
| 351 | EEHashEntry_t * EECMHelperHashtableHelper::AllocateEntry(EECMHelperHashtableKey *pKey, BOOL bDeepCopy, void* pHeap) |
| 352 | { |
| 353 | CONTRACTL |
| 354 | { |
| 355 | NOTHROW; |
| 356 | GC_NOTRIGGER; |
| 357 | MODE_ANY; |
| 358 | INJECT_FAULT(return NULL;); |
| 359 | } |
| 360 | CONTRACTL_END; |
| 361 | |
| 362 | EEHashEntry_t *pEntry; |
| 363 | |
| 364 | if (bDeepCopy) |
| 365 | { |
| 366 | S_SIZE_T cbEntry = S_SIZE_T(sizeof(EEHashEntry) - 1 + sizeof(EECMHelperHashtableKey)); |
| 367 | cbEntry += S_SIZE_T(pKey->GetMarshalerTypeNameByteCount()); |
| 368 | cbEntry += S_SIZE_T(pKey->GetCookieStringByteCount()); |
| 369 | cbEntry += S_SIZE_T(pKey->GetMarshalerInstantiation().GetNumArgs()) * S_SIZE_T(sizeof(LPVOID)); |
| 370 | |
| 371 | if (cbEntry.IsOverflow()) |
| 372 | return NULL; |
| 373 | |
| 374 | pEntry = (EEHashEntry_t *) new (nothrow) BYTE[cbEntry.Value()]; |
| 375 | if (!pEntry) |
| 376 | return NULL; |
| 377 | |
| 378 | EECMHelperHashtableKey *pEntryKey = (EECMHelperHashtableKey *) pEntry->Key; |
| 379 | pEntryKey->m_cMarshalerTypeNameBytes = pKey->GetMarshalerTypeNameByteCount(); |
| 380 | pEntryKey->m_strMarshalerTypeName = (LPSTR) pEntry->Key + sizeof(EECMHelperHashtableKey); |
| 381 | pEntryKey->m_cCookieStrBytes = pKey->GetCookieStringByteCount(); |
| 382 | pEntryKey->m_strCookie = (LPSTR) pEntry->Key + sizeof(EECMHelperHashtableKey) + pEntryKey->m_cMarshalerTypeNameBytes; |
| 383 | pEntryKey->m_Instantiation = Instantiation( |
| 384 | (TypeHandle *) (pEntryKey->m_strCookie + pEntryKey->m_cCookieStrBytes), |
| 385 | pKey->GetMarshalerInstantiation().GetNumArgs()); |
| 386 | memcpy((void*)pEntryKey->m_strMarshalerTypeName, pKey->GetMarshalerTypeName(), pKey->GetMarshalerTypeNameByteCount()); |
| 387 | memcpy((void*)pEntryKey->m_strCookie, pKey->GetCookieString(), pKey->GetCookieStringByteCount()); |
| 388 | memcpy((void*)pEntryKey->m_Instantiation.GetRawArgs(), pKey->GetMarshalerInstantiation().GetRawArgs(), |
| 389 | pEntryKey->m_Instantiation.GetNumArgs() * sizeof(LPVOID)); |
| 390 | } |
| 391 | else |
| 392 | { |
| 393 | pEntry = (EEHashEntry_t *) |
| 394 | new (nothrow) BYTE[sizeof(EEHashEntry) - 1 + sizeof(EECMHelperHashtableKey)]; |
| 395 | if (!pEntry) |
| 396 | return NULL; |
| 397 | |
| 398 | EECMHelperHashtableKey *pEntryKey = (EECMHelperHashtableKey *) pEntry->Key; |
| 399 | pEntryKey->m_cMarshalerTypeNameBytes = pKey->GetMarshalerTypeNameByteCount(); |
| 400 | pEntryKey->m_strMarshalerTypeName = pKey->GetMarshalerTypeName(); |
| 401 | pEntryKey->m_cCookieStrBytes = pKey->GetCookieStringByteCount(); |
| 402 | pEntryKey->m_strCookie = pKey->GetCookieString(); |
| 403 | pEntryKey->m_Instantiation = Instantiation(pKey->GetMarshalerInstantiation()); |
| 404 | } |
| 405 | |
| 406 | return pEntry; |
| 407 | } |
| 408 | |
| 409 | |
| 410 | void EECMHelperHashtableHelper::DeleteEntry(EEHashEntry_t *pEntry, void* pHeap) |
| 411 | { |
| 412 | CONTRACTL |
| 413 | { |
| 414 | NOTHROW; |
| 415 | GC_NOTRIGGER; |
| 416 | MODE_ANY; |
| 417 | PRECONDITION(CheckPointer(pEntry)); |
| 418 | } |
| 419 | CONTRACTL_END; |
| 420 | |
| 421 | delete[] (BYTE*)pEntry; |
| 422 | } |
| 423 | |
| 424 | |
| 425 | BOOL EECMHelperHashtableHelper::CompareKeys(EEHashEntry_t *pEntry, EECMHelperHashtableKey *pKey) |
| 426 | { |
| 427 | CONTRACTL |
| 428 | { |
| 429 | NOTHROW; |
| 430 | GC_NOTRIGGER; |
| 431 | MODE_ANY; |
| 432 | PRECONDITION(CheckPointer(pEntry)); |
| 433 | PRECONDITION(CheckPointer(pKey)); |
| 434 | } |
| 435 | CONTRACTL_END; |
| 436 | |
| 437 | EECMHelperHashtableKey *pEntryKey = (EECMHelperHashtableKey *) pEntry->Key; |
| 438 | |
| 439 | if (pEntryKey->GetMarshalerTypeNameByteCount() != pKey->GetMarshalerTypeNameByteCount()) |
| 440 | return FALSE; |
| 441 | |
| 442 | if (memcmp(pEntryKey->GetMarshalerTypeName(), pKey->GetMarshalerTypeName(), pEntryKey->GetMarshalerTypeNameByteCount()) != 0) |
| 443 | return FALSE; |
| 444 | |
| 445 | if (pEntryKey->GetCookieStringByteCount() != pKey->GetCookieStringByteCount()) |
| 446 | return FALSE; |
| 447 | |
| 448 | if (memcmp(pEntryKey->GetCookieString(), pKey->GetCookieString(), pEntryKey->GetCookieStringByteCount()) != 0) |
| 449 | return FALSE; |
| 450 | |
| 451 | DWORD dwNumTypeArgs = pEntryKey->GetMarshalerInstantiation().GetNumArgs(); |
| 452 | if (dwNumTypeArgs != pKey->GetMarshalerInstantiation().GetNumArgs()) |
| 453 | return FALSE; |
| 454 | |
| 455 | for (DWORD i = 0; i < dwNumTypeArgs; i++) |
| 456 | { |
| 457 | if (pEntryKey->GetMarshalerInstantiation()[i] != pKey->GetMarshalerInstantiation()[i]) |
| 458 | return FALSE; |
| 459 | } |
| 460 | |
| 461 | return TRUE; |
| 462 | } |
| 463 | |
| 464 | |
| 465 | DWORD EECMHelperHashtableHelper::Hash(EECMHelperHashtableKey *pKey) |
| 466 | { |
| 467 | WRAPPER_NO_CONTRACT; |
| 468 | |
| 469 | return (DWORD) |
| 470 | (HashBytes((const BYTE *) pKey->GetMarshalerTypeName(), pKey->GetMarshalerTypeNameByteCount()) + |
| 471 | HashBytes((const BYTE *) pKey->GetCookieString(), pKey->GetCookieStringByteCount()) + |
| 472 | HashBytes((const BYTE *) pKey->GetMarshalerInstantiation().GetRawArgs(), pKey->GetMarshalerInstantiation().GetNumArgs() * sizeof(LPVOID))); |
| 473 | } |
| 474 | |
| 475 | |
| 476 | OBJECTREF CustomMarshalerHelper::InvokeMarshalNativeToManagedMeth(void *pNative) |
| 477 | { |
| 478 | WRAPPER_NO_CONTRACT; |
| 479 | return GetCustomMarshalerInfo()->InvokeMarshalNativeToManagedMeth(pNative); |
| 480 | } |
| 481 | |
| 482 | |
| 483 | void *CustomMarshalerHelper::InvokeMarshalManagedToNativeMeth(OBJECTREF MngObj) |
| 484 | { |
| 485 | CONTRACTL |
| 486 | { |
| 487 | THROWS; |
| 488 | GC_TRIGGERS; |
| 489 | MODE_COOPERATIVE; |
| 490 | } |
| 491 | CONTRACTL_END; |
| 492 | |
| 493 | void *RetVal = NULL; |
| 494 | |
| 495 | GCPROTECT_BEGIN(MngObj) |
| 496 | { |
| 497 | CustomMarshalerInfo *pCMInfo = GetCustomMarshalerInfo(); |
| 498 | RetVal = pCMInfo->InvokeMarshalManagedToNativeMeth(MngObj); |
| 499 | } |
| 500 | GCPROTECT_END(); |
| 501 | |
| 502 | return RetVal; |
| 503 | } |
| 504 | |
| 505 | |
| 506 | void CustomMarshalerHelper::InvokeCleanUpNativeMeth(void *pNative) |
| 507 | { |
| 508 | CONTRACTL |
| 509 | { |
| 510 | THROWS; |
| 511 | GC_TRIGGERS; |
| 512 | MODE_COOPERATIVE; |
| 513 | } |
| 514 | CONTRACTL_END; |
| 515 | |
| 516 | OBJECTREF ExceptionObj = NULL; |
| 517 | GCPROTECT_BEGIN(ExceptionObj) |
| 518 | { |
| 519 | EX_TRY |
| 520 | { |
| 521 | GetCustomMarshalerInfo()->InvokeCleanUpNativeMeth(pNative); |
| 522 | } |
| 523 | EX_CATCH |
| 524 | { |
| 525 | ExceptionObj = GET_THROWABLE(); |
| 526 | } |
| 527 | EX_END_CATCH(SwallowAllExceptions); |
| 528 | |
| 529 | #ifdef MDA_SUPPORTED |
| 530 | if (ExceptionObj != NULL) |
| 531 | { |
| 532 | TypeHandle typeCustomMarshaler = GetCustomMarshalerInfo()->GetCustomMarshalerType(); |
| 533 | MDA_TRIGGER_ASSISTANT(MarshalCleanupError, ReportErrorCustomMarshalerCleanup(typeCustomMarshaler, &ExceptionObj)); |
| 534 | } |
| 535 | #endif |
| 536 | } |
| 537 | GCPROTECT_END(); |
| 538 | } |
| 539 | |
| 540 | |
| 541 | void CustomMarshalerHelper::InvokeCleanUpManagedMeth(OBJECTREF MngObj) |
| 542 | { |
| 543 | CONTRACTL |
| 544 | { |
| 545 | THROWS; |
| 546 | GC_TRIGGERS; |
| 547 | MODE_COOPERATIVE; |
| 548 | } |
| 549 | CONTRACTL_END; |
| 550 | |
| 551 | GCPROTECT_BEGIN(MngObj) |
| 552 | { |
| 553 | CustomMarshalerInfo *pCMInfo = GetCustomMarshalerInfo(); |
| 554 | pCMInfo->InvokeCleanUpManagedMeth(MngObj); |
| 555 | } |
| 556 | GCPROTECT_END(); |
| 557 | } |
| 558 | |
| 559 | |
| 560 | void *NonSharedCustomMarshalerHelper::operator new(size_t size, LoaderHeap *pHeap) |
| 561 | { |
| 562 | CONTRACTL |
| 563 | { |
| 564 | THROWS; |
| 565 | GC_NOTRIGGER; |
| 566 | MODE_ANY; |
| 567 | INJECT_FAULT(COMPlusThrowOM()); |
| 568 | PRECONDITION(CheckPointer(pHeap)); |
| 569 | } |
| 570 | CONTRACTL_END; |
| 571 | |
| 572 | return pHeap->AllocMem(S_SIZE_T(sizeof(NonSharedCustomMarshalerHelper))); |
| 573 | } |
| 574 | |
| 575 | |
| 576 | void NonSharedCustomMarshalerHelper::operator delete(void *pMem) |
| 577 | { |
| 578 | // Instances of this class are always allocated on the loader heap so |
| 579 | // the delete operator has nothing to do. |
| 580 | LIMITED_METHOD_CONTRACT; |
| 581 | } |
| 582 | |
| 583 | |
| 584 | SharedCustomMarshalerHelper::SharedCustomMarshalerHelper(Assembly *pAssembly, TypeHandle hndManagedType, LPCUTF8 strMarshalerTypeName, DWORD cMarshalerTypeNameBytes, LPCUTF8 strCookie, DWORD cCookieStrBytes) |
| 585 | : m_pAssembly(pAssembly) |
| 586 | , m_hndManagedType(hndManagedType) |
| 587 | , m_cMarshalerTypeNameBytes(cMarshalerTypeNameBytes) |
| 588 | , m_strMarshalerTypeName(strMarshalerTypeName) |
| 589 | , m_cCookieStrBytes(cCookieStrBytes) |
| 590 | , m_strCookie(strCookie) |
| 591 | { |
| 592 | WRAPPER_NO_CONTRACT; |
| 593 | } |
| 594 | |
| 595 | |
| 596 | void *SharedCustomMarshalerHelper::operator new(size_t size, LoaderHeap *pHeap) |
| 597 | { |
| 598 | CONTRACTL |
| 599 | { |
| 600 | THROWS; |
| 601 | GC_NOTRIGGER; |
| 602 | MODE_ANY; |
| 603 | INJECT_FAULT(COMPlusThrowOM()); |
| 604 | PRECONDITION(CheckPointer(pHeap)); |
| 605 | } |
| 606 | CONTRACTL_END; |
| 607 | |
| 608 | return pHeap->AllocMem(S_SIZE_T(sizeof(SharedCustomMarshalerHelper))); |
| 609 | } |
| 610 | |
| 611 | |
| 612 | void SharedCustomMarshalerHelper::operator delete(void *pMem) |
| 613 | { |
| 614 | // Instances of this class are always allocated on the loader heap so |
| 615 | // the delete operator has nothing to do. |
| 616 | LIMITED_METHOD_CONTRACT; |
| 617 | } |
| 618 | |
| 619 | |
| 620 | CustomMarshalerInfo *SharedCustomMarshalerHelper::GetCustomMarshalerInfo() |
| 621 | { |
| 622 | CONTRACTL |
| 623 | { |
| 624 | THROWS; |
| 625 | GC_TRIGGERS; |
| 626 | MODE_COOPERATIVE; |
| 627 | } |
| 628 | CONTRACTL_END; |
| 629 | |
| 630 | // Retrieve the marshalling data for the current app domain. |
| 631 | EEMarshalingData *pMarshalingData = GetThread()->GetDomain()->GetMarshalingData(); |
| 632 | |
| 633 | // Retrieve the custom marshaling information for the current shared custom |
| 634 | // marshaling helper. |
| 635 | return pMarshalingData->GetCustomMarshalerInfo(this); |
| 636 | } |
| 637 | |
| 638 | |
| 639 | #endif // CROSSGEN_COMPILE |
| 640 | |
| 641 | |