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.
13 #include "dllimport.h"
14 #include "sigformat.h"
17 #include "../dlls/mscorrc/resource.h"
18 #include "mdaassistants.h"
19 #include "typeparse.h"
20 #include "comdelegate.h"
21 #include "olevariant.h"
22 #include "ilmarshalers.h"
23 #include "interoputil.h"
26 #include "dataimage.h"
29 #ifdef FEATURE_COMINTEROP
30 #include "comcallablewrapper.h"
31 #include "runtimecallablewrapper.h"
32 #include "dispparammarshaler.h"
33 #include "winrttypenameconverter.h"
34 #endif // FEATURE_COMINTEROP
38 #define lengthof(rg) (sizeof(rg)/sizeof(rg[0]))
42 #ifdef FEATURE_COMINTEROP
43 DEFINE_ASM_QUAL_TYPE_NAME(ENUMERATOR_TO_ENUM_VARIANT_CM_NAME, g_EnumeratorToEnumClassName, g_CorelibAsmName, VER_ASSEMBLYVERSION_STR, g_ECMAKeyToken);
45 static const int ENUMERATOR_TO_ENUM_VARIANT_CM_NAME_LEN = lengthof(ENUMERATOR_TO_ENUM_VARIANT_CM_NAME);
46 static const char ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE[] = {""};
47 static const int ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE_LEN = lengthof(ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE);
49 DEFINE_ASM_QUAL_TYPE_NAME(COLOR_TRANSLATOR_ASM_QUAL_TYPE_NAME, g_ColorTranslatorClassName, g_DrawingAsmName, VER_ASSEMBLYVERSION_STR, g_FXKeyToken);
50 DEFINE_ASM_QUAL_TYPE_NAME(COLOR_ASM_QUAL_TYPE_NAME, g_ColorClassName, g_DrawingAsmName, VER_ASSEMBLYVERSION_STR, g_FXKeyToken);
52 DEFINE_ASM_QUAL_TYPE_NAME(URI_ASM_QUAL_TYPE_NAME, g_SystemUriClassName, g_SystemRuntimeAsmName, VER_ASSEMBLYVERSION_STR, g_FXKeyToken);
54 DEFINE_ASM_QUAL_TYPE_NAME(NCCEVENTARGS_ASM_QUAL_TYPE_NAME, g_NotifyCollectionChangedEventArgsName, g_ObjectModelAsmName, VER_ASSEMBLYVERSION_STR, g_FXKeyToken);
55 DEFINE_ASM_QUAL_TYPE_NAME(NCCEVENTARGS_MARSHALER_ASM_QUAL_TYPE_NAME, g_NotifyCollectionChangedEventArgsMarshalerName, g_SystemRuntimeWindowsRuntimeAsmName, VER_ASSEMBLYVERSION_STR, g_ECMAKeyToken);
58 DEFINE_ASM_QUAL_TYPE_NAME(PCEVENTARGS_ASM_QUAL_TYPE_NAME, g_PropertyChangedEventArgsName, g_ObjectModelAsmName, VER_ASSEMBLYVERSION_STR, g_FXKeyToken);
59 DEFINE_ASM_QUAL_TYPE_NAME(PCEVENTARGS_MARSHALER_ASM_QUAL_TYPE_NAME, g_PropertyChangedEventArgsMarshalerName, g_SystemRuntimeWindowsRuntimeAsmName, VER_ASSEMBLYVERSION_STR, g_ECMAKeyToken);
62 #define OLECOLOR_TO_SYSTEMCOLOR_METH_NAME "FromOle"
63 #define SYSTEMCOLOR_TO_OLECOLOR_METH_NAME "ToOle"
65 #define EVENTARGS_TO_WINRT_EVENTARGS_METH_NAME "ConvertToNative"
66 #define WINRT_EVENTARGS_TO_EVENTARGS_METH_NAME "ConvertToManaged"
68 #define ORIGINALSTRING_PROPERTY_NAME "OriginalString"
69 #endif // FEATURE_COMINTEROP
73 #define INITIAL_NUM_CMHELPER_HASHTABLE_BUCKETS 32
74 #define INITIAL_NUM_CMINFO_HASHTABLE_BUCKETS 32
75 #define DEBUG_CONTEXT_STR_LEN 2000
78 //-------------------------------------------------------------------------------------
79 // Return the copy ctor for a VC class (if any exists)
80 //-------------------------------------------------------------------------------------
81 void FindCopyCtor(Module *pModule, MethodTable *pMT, MethodDesc **pMDOut)
86 GC_TRIGGERS; // CompareTypeTokens may trigger GC
95 mdTypeDef cl = pMT->GetCl();
96 TypeHandle th = TypeHandle(pMT);
97 SigTypeContext typeContext(th);
99 IMDInternalImport *pInternalImport = pModule->GetMDImport();
100 MDEnumHolder hEnumMethod(pInternalImport);
103 // First try for the new syntax: <MarshalCopy>
105 IfFailThrow(pInternalImport->EnumInit(mdtMethodDef, cl, &hEnumMethod));
107 while (pInternalImport->EnumNext(&hEnumMethod, &tk))
109 _ASSERTE(TypeFromToken(tk) == mdtMethodDef);
111 IfFailThrow(pInternalImport->GetMethodDefProps(tk, &dwMemberAttrs));
113 if (IsMdSpecialName(dwMemberAttrs))
116 PCCOR_SIGNATURE pSig;
118 IfFailThrow(pInternalImport->GetNameAndSigOfMethodDef(tk, &pSig, &cSig, &pName));
120 const char *pBaseName = "<MarshalCopy>";
121 int ncBaseName = (int)strlen(pBaseName);
122 int nc = (int)strlen(pName);
123 if (nc >= ncBaseName && 0 == strcmp(pName + nc - ncBaseName, pBaseName))
125 MetaSig msig(pSig, cSig, pModule, &typeContext);
127 // Looking for the prototype void <MarshalCopy>(Ptr VC, Ptr VC);
128 if (msig.NumFixedArgs() == 2)
130 if (msig.GetReturnType() == ELEMENT_TYPE_VOID)
132 if (msig.NextArg() == ELEMENT_TYPE_PTR)
134 SigPointer sp1 = msig.GetArgProps();
135 IfFailThrow(sp1.GetElemType(NULL));
136 CorElementType eType;
137 IfFailThrow(sp1.GetElemType(&eType));
138 if (eType == ELEMENT_TYPE_VALUETYPE)
141 IfFailThrow(sp1.GetToken(&tk1));
142 hr = CompareTypeTokensNT(tk1, cl, pModule, pModule);
145 pInternalImport->EnumClose(&hEnumMethod);
151 if (msig.NextArg() == ELEMENT_TYPE_PTR)
153 SigPointer sp2 = msig.GetArgProps();
154 IfFailThrow(sp2.GetElemType(NULL));
155 IfFailThrow(sp2.GetElemType(&eType));
156 if (eType == ELEMENT_TYPE_VALUETYPE)
159 IfFailThrow(sp2.GetToken(&tk2));
161 hr = (tk2 == tk1) ? S_OK : CompareTypeTokensNT(tk2, cl, pModule, pModule);
164 *pMDOut = pModule->LookupMethodDef(tk);
179 // Next try the old syntax: global .__ctor
181 IfFailThrow(pInternalImport->EnumGlobalFunctionsInit(&hEnumMethod));
183 while (pInternalImport->EnumNext(&hEnumMethod, &tk))
185 _ASSERTE(TypeFromToken(tk) == mdtMethodDef);
187 IfFailThrow(pInternalImport->GetMethodDefProps(tk, &dwMemberAttrs));
189 if (IsMdSpecialName(dwMemberAttrs))
192 PCCOR_SIGNATURE pSig;
194 IfFailThrow(pInternalImport->GetNameAndSigOfMethodDef(tk, &pSig, &cSig, &pName));
196 const char *pBaseName = ".__ctor";
197 int ncBaseName = (int)strlen(pBaseName);
198 int nc = (int)strlen(pName);
199 if (nc >= ncBaseName && 0 == strcmp(pName + nc - ncBaseName, pBaseName))
202 MetaSig msig(pSig, cSig, pModule, &typeContext);
204 // Looking for the prototype Ptr VC __ctor(Ptr VC, ByRef VC);
205 if (msig.NumFixedArgs() == 2)
207 if (msig.GetReturnType() == ELEMENT_TYPE_PTR)
209 SigPointer spret = msig.GetReturnProps();
210 IfFailThrow(spret.GetElemType(NULL));
211 CorElementType eType;
212 IfFailThrow(spret.GetElemType(&eType));
213 if (eType == ELEMENT_TYPE_VALUETYPE)
216 IfFailThrow(spret.GetToken(&tk0));
217 hr = CompareTypeTokensNT(tk0, cl, pModule, pModule);
220 pInternalImport->EnumClose(&hEnumMethod);
226 if (msig.NextArg() == ELEMENT_TYPE_PTR)
228 SigPointer sp1 = msig.GetArgProps();
229 IfFailThrow(sp1.GetElemType(NULL));
230 IfFailThrow(sp1.GetElemType(&eType));
231 if (eType == ELEMENT_TYPE_VALUETYPE)
234 IfFailThrow(sp1.GetToken(&tk1));
235 hr = (tk1 == tk0) ? S_OK : CompareTypeTokensNT(tk1, cl, pModule, pModule);
238 pInternalImport->EnumClose(&hEnumMethod);
244 if (msig.NextArg() == ELEMENT_TYPE_PTR &&
245 msig.GetArgProps().HasCustomModifier(pModule, "Microsoft.VisualC.IsCXXReferenceModifier", ELEMENT_TYPE_CMOD_OPT))
247 SigPointer sp2 = msig.GetArgProps();
248 IfFailThrow(sp2.GetElemType(NULL));
249 IfFailThrow(sp2.GetElemType(&eType));
250 if (eType == ELEMENT_TYPE_VALUETYPE)
253 IfFailThrow(sp2.GetToken(&tk2));
255 hr = (tk2 == tk0) ? S_OK : CompareTypeTokensNT(tk2, cl, pModule, pModule);
258 *pMDOut = pModule->LookupMethodDef(tk);
276 //-------------------------------------------------------------------------------------
277 // Return the destructor for a VC class (if any exists)
278 //-------------------------------------------------------------------------------------
279 void FindDtor(Module *pModule, MethodTable *pMT, MethodDesc **pMDOut)
284 GC_TRIGGERS; // CompareTypeTokens may trigger GC
293 mdTypeDef cl = pMT->GetCl();
294 TypeHandle th = TypeHandle(pMT);
295 SigTypeContext typeContext(th);
297 IMDInternalImport *pInternalImport = pModule->GetMDImport();
298 MDEnumHolder hEnumMethod(pInternalImport);
301 // First try for the new syntax: <MarshalDestroy>
303 IfFailThrow(pInternalImport->EnumInit(mdtMethodDef, cl, &hEnumMethod));
305 while (pInternalImport->EnumNext(&hEnumMethod, &tk))
307 _ASSERTE(TypeFromToken(tk) == mdtMethodDef);
309 IfFailThrow(pInternalImport->GetMethodDefProps(tk, &dwMemberAttrs));
311 if (IsMdSpecialName(dwMemberAttrs))
314 PCCOR_SIGNATURE pSig;
316 IfFailThrow(pInternalImport->GetNameAndSigOfMethodDef(tk, &pSig, &cSig, &pName));
318 const char *pBaseName = "<MarshalDestroy>";
319 int ncBaseName = (int)strlen(pBaseName);
320 int nc = (int)strlen(pName);
321 if (nc >= ncBaseName && 0 == strcmp(pName + nc - ncBaseName, pBaseName))
323 MetaSig msig(pSig, cSig, pModule, &typeContext);
325 // Looking for the prototype void <MarshalDestroy>(Ptr VC);
326 if (msig.NumFixedArgs() == 1)
328 if (msig.GetReturnType() == ELEMENT_TYPE_VOID)
330 if (msig.NextArg() == ELEMENT_TYPE_PTR)
332 SigPointer sp1 = msig.GetArgProps();
333 IfFailThrow(sp1.GetElemType(NULL));
334 CorElementType eType;
335 IfFailThrow(sp1.GetElemType(&eType));
336 if (eType == ELEMENT_TYPE_VALUETYPE)
339 IfFailThrow(sp1.GetToken(&tk1));
341 hr = CompareTypeTokensNT(tk1, cl, pModule, pModule);
346 *pMDOut = pModule->LookupMethodDef(tk);
359 // Next try the old syntax: global .__dtor
361 IfFailThrow(pInternalImport->EnumGlobalFunctionsInit(&hEnumMethod));
363 while (pInternalImport->EnumNext(&hEnumMethod, &tk))
365 _ASSERTE(TypeFromToken(tk) == mdtMethodDef);
367 PCCOR_SIGNATURE pSig;
369 IfFailThrow(pInternalImport->GetNameAndSigOfMethodDef(tk, &pSig, &cSig, &pName));
371 const char *pBaseName = ".__dtor";
372 int ncBaseName = (int)strlen(pBaseName);
373 int nc = (int)strlen(pName);
374 if (nc >= ncBaseName && 0 == strcmp(pName + nc - ncBaseName, pBaseName))
376 MetaSig msig(pSig, cSig, pModule, &typeContext);
378 // Looking for the prototype void __dtor(Ptr VC);
379 if (msig.NumFixedArgs() == 1)
381 if (msig.GetReturnType() == ELEMENT_TYPE_VOID)
383 if (msig.NextArg() == ELEMENT_TYPE_PTR)
385 SigPointer sp1 = msig.GetArgProps();
386 IfFailThrow(sp1.GetElemType(NULL));
387 CorElementType eType;
388 IfFailThrow(sp1.GetElemType(&eType));
389 if (eType == ELEMENT_TYPE_VALUETYPE)
392 IfFailThrow(sp1.GetToken(&tk1));
393 hr = CompareTypeTokensNT(tk1, cl, pModule, pModule);
396 pInternalImport->EnumClose(&hEnumMethod);
402 *pMDOut = pModule->LookupMethodDef(tk);
413 //==========================================================================
414 // Set's up the custom marshaler information.
415 //==========================================================================
416 CustomMarshalerHelper *SetupCustomMarshalerHelper(LPCUTF8 strMarshalerTypeName, DWORD cMarshalerTypeNameBytes, LPCUTF8 strCookie, DWORD cCookieStrBytes, Assembly *pAssembly, TypeHandle hndManagedType)
418 #ifndef CROSSGEN_COMPILE
419 CONTRACT (CustomMarshalerHelper*)
424 PRECONDITION(CheckPointer(pAssembly));
425 POSTCONDITION(CheckPointer(RETVAL));
429 EEMarshalingData *pMarshalingData = NULL;
431 // The assembly is not shared so we use the current app domain's marshaling data.
432 pMarshalingData = pAssembly->GetLoaderAllocator()->GetMarshalingData();
434 // Retrieve the custom marshaler helper from the EE marshaling data.
435 RETURN pMarshalingData->GetCustomMarshalerHelper(pAssembly, hndManagedType, strMarshalerTypeName, cMarshalerTypeNameBytes, strCookie, cCookieStrBytes);
442 //==========================================================================
443 // Return: S_OK if there is valid data to compress
444 // S_FALSE if at end of data block
445 // E_FAIL if corrupt data found
446 //==========================================================================
447 HRESULT CheckForCompressedData(PCCOR_SIGNATURE pvNativeTypeStart, PCCOR_SIGNATURE pvNativeType, ULONG cbNativeType)
457 if (pvNativeTypeStart + cbNativeType == pvNativeType)
458 { // end of data block
464 return CPackedLen::SafeGetLength((BYTE const *)pvNativeType,
465 (BYTE const *)pvNativeTypeStart + cbNativeType,
470 //==========================================================================
471 // Parse and validate the NATIVE_TYPE_ metadata.
472 // Note! NATIVE_TYPE_ metadata is optional. If it's not present, this
473 // routine sets NativeTypeParamInfo->m_NativeType to NATIVE_TYPE_DEFAULT.
474 //==========================================================================
475 BOOL ParseNativeTypeInfo(NativeTypeParamInfo* pParamInfo, PCCOR_SIGNATURE pvNativeType, ULONG cbNativeType);
477 BOOL ParseNativeTypeInfo(mdToken token,
478 IMDInternalImport* pScope,
479 NativeTypeParamInfo* pParamInfo)
489 PCCOR_SIGNATURE pvNativeType;
492 if (token == mdParamDefNil || pScope->GetFieldMarshal(token, &pvNativeType, &cbNativeType) != S_OK)
495 return ParseNativeTypeInfo(pParamInfo, pvNativeType, cbNativeType);
498 BOOL ParseNativeTypeInfo(NativeTypeParamInfo* pParamInfo,
499 PCCOR_SIGNATURE pvNativeType,
502 LIMITED_METHOD_CONTRACT;
505 PCCOR_SIGNATURE pvNativeTypeStart = pvNativeType;
506 PCCOR_SIGNATURE pvNativeTypeEnd = pvNativeType + cbNativeType;
508 if (cbNativeType == 0)
509 return FALSE; // Zero-length NATIVE_TYPE block
511 pParamInfo->m_NativeType = (CorNativeType)*(pvNativeType++);
514 // Retrieve any extra information associated with the native type.
515 switch (pParamInfo->m_NativeType)
517 #ifdef FEATURE_COMINTEROP
518 case NATIVE_TYPE_INTF:
519 case NATIVE_TYPE_IUNKNOWN:
520 case NATIVE_TYPE_IDISPATCH:
521 if (S_OK != CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
524 pParamInfo->m_IidParamIndex = (int)CorSigUncompressData(pvNativeType);
528 case NATIVE_TYPE_FIXEDARRAY:
530 if (S_OK != CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
533 pParamInfo->m_Additive = CorSigUncompressData(pvNativeType);
535 if (S_OK != CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
538 pParamInfo->m_ArrayElementType = (CorNativeType)CorSigUncompressData(pvNativeType);
541 case NATIVE_TYPE_FIXEDSYSSTRING:
542 if (S_OK != CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
545 pParamInfo->m_Additive = CorSigUncompressData(pvNativeType);
548 #ifdef FEATURE_COMINTEROP
549 case NATIVE_TYPE_SAFEARRAY:
550 // Check for the safe array element type.
551 hr = CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType);
556 pParamInfo->m_SafeArrayElementVT = (VARTYPE) (CorSigUncompressData(/*modifies*/pvNativeType));
558 // Extract the name of the record type's.
559 if (S_OK == CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
561 hr = CPackedLen::SafeGetData((BYTE const *)pvNativeType,
562 (BYTE const *)pvNativeTypeEnd,
564 (BYTE const **)&pvNativeType);
570 pParamInfo->m_strSafeArrayUserDefTypeName = (LPUTF8)pvNativeType;
571 pParamInfo->m_cSafeArrayUserDefTypeNameBytes = strLen;
572 _ASSERTE((ULONG)(pvNativeType + strLen - pvNativeTypeStart) == cbNativeType);
576 #endif // FEATURE_COMINTEROP
578 case NATIVE_TYPE_ARRAY:
579 hr = CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType);
584 pParamInfo->m_ArrayElementType = (CorNativeType) (CorSigUncompressData(/*modifies*/pvNativeType));
586 // Check for "sizeis" param index
587 hr = CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType);
593 pParamInfo->m_SizeIsSpecified = TRUE;
594 pParamInfo->m_CountParamIdx = (UINT16)(CorSigUncompressData(/*modifies*/pvNativeType));
596 // If an "sizeis" param index is present, the defaults for multiplier and additive change
597 pParamInfo->m_Multiplier = 1;
598 pParamInfo->m_Additive = 0;
600 // Check for "sizeis" additive
601 hr = CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType);
607 // Extract the additive.
608 pParamInfo->m_Additive = (DWORD)CorSigUncompressData(/*modifies*/pvNativeType);
610 // Check to see if the flags field is present.
611 hr = CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType);
617 // If the param index specified flag isn't set then we need to reset the
618 // multiplier to 0 to indicate no size param index was specified.
619 NativeTypeArrayFlags flags = (NativeTypeArrayFlags)CorSigUncompressData(/*modifies*/pvNativeType);;
620 if (!(flags & ntaSizeParamIndexSpecified))
621 pParamInfo->m_Multiplier = 0;
628 case NATIVE_TYPE_CUSTOMMARSHALER:
629 // Skip the typelib guid.
630 if (S_OK != CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
633 if (FAILED(CPackedLen::SafeGetData(pvNativeType, pvNativeTypeEnd, &strLen, (void const **)&pvNativeType)))
636 pvNativeType += strLen;
637 _ASSERTE((ULONG)(pvNativeType - pvNativeTypeStart) < cbNativeType);
639 // Skip the name of the native type.
640 if (S_OK != CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
643 if (FAILED(CPackedLen::SafeGetData(pvNativeType, pvNativeTypeEnd, &strLen, (void const **)&pvNativeType)))
646 pvNativeType += strLen;
647 _ASSERTE((ULONG)(pvNativeType - pvNativeTypeStart) < cbNativeType);
649 // Extract the name of the custom marshaler.
650 if (S_OK != CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
653 if (FAILED(CPackedLen::SafeGetData(pvNativeType, pvNativeTypeEnd, &strLen, (void const **)&pvNativeType)))
656 pParamInfo->m_strCMMarshalerTypeName = (LPUTF8)pvNativeType;
657 pParamInfo->m_cCMMarshalerTypeNameBytes = strLen;
658 pvNativeType += strLen;
659 _ASSERTE((ULONG)(pvNativeType - pvNativeTypeStart) < cbNativeType);
661 // Extract the cookie string.
662 if (S_OK != CheckForCompressedData(pvNativeTypeStart, pvNativeType, cbNativeType))
665 if (FAILED(CPackedLen::SafeGetData(pvNativeType, pvNativeTypeEnd, &strLen, (void const **)&pvNativeType)))
668 pParamInfo->m_strCMCookie = (LPUTF8)pvNativeType;
669 pParamInfo->m_cCMCookieStrBytes = strLen;
670 _ASSERTE((ULONG)(pvNativeType + strLen - pvNativeTypeStart) == cbNativeType);
680 //==========================================================================
681 // Determines whether *pManagedElemType is really normalized (i.e. differs
682 // from what sigPtr points to modulo generic instantiation). If it is the
683 // case, all types that have been normalized away are checked for valid
684 // managed/unmanaged type combination, and *pNativeType is updated to contain
685 // the native type of the primitive type field inside. On error (a generic
686 // type is encountered or managed/unmanaged type mismatch) or non-default
687 // native type of the primitive type inside, *pManagedElemType is un-normalized
688 // so that the calling code can deal with the situation in its own way.
689 //==========================================================================
690 void VerifyAndAdjustNormalizedType(
693 const SigTypeContext * pTypeContext,
694 CorElementType * pManagedElemType,
695 CorNativeType * pNativeType)
697 CorElementType sigElemType = sigPtr.PeekElemTypeClosed(pModule, pTypeContext);
699 if (*pManagedElemType != sigElemType)
701 // Normalized element type differs from closed element type, which means that
702 // normalization has occurred.
703 _ASSERTE(sigElemType == ELEMENT_TYPE_VALUETYPE);
705 // Now we know that this is a normalized value type - we have to verify the removed
706 // value type(s) and get to the true primitive type inside.
707 TypeHandle th = sigPtr.GetTypeHandleThrowing(pModule,
709 ClassLoader::LoadTypes,
710 CLASS_LOAD_UNRESTORED,
712 _ASSERTE(!th.IsNull() && !th.IsTypeDesc());
714 CorNativeType ntype = *pNativeType;
716 if (!th.AsMethodTable()->IsTruePrimitive() &&
719 // This is a trivial (yet non-primitive) value type that has been normalized.
720 // Loop until we eventually hit the primitive type or enum inside.
723 if (th.HasInstantiation())
725 // generic structures are either not marshalable or special-cased - the caller needs to know either way
726 *pManagedElemType = sigElemType;
730 // verify the native type of the value type (must be default or Struct)
731 if (!(ntype == NATIVE_TYPE_DEFAULT || ntype == NATIVE_TYPE_STRUCT))
733 *pManagedElemType = sigElemType;
737 MethodTable *pMT = th.GetMethodTable();
738 _ASSERTE(pMT != NULL && pMT->IsValueType() && pMT->GetNumInstanceFields() == 1);
740 // get the only instance field
741 PTR_FieldDesc fieldDesc = pMT->GetApproxFieldDescListRaw();
743 // retrieve the MarshalAs of the field
744 NativeTypeParamInfo paramInfo;
745 if (!ParseNativeTypeInfo(fieldDesc->GetMemberDef(), th.GetModule()->GetMDImport(), ¶mInfo))
747 *pManagedElemType = sigElemType;
751 ntype = paramInfo.m_NativeType;
753 th = fieldDesc->GetApproxFieldTypeHandleThrowing();
755 while (!th.IsTypeDesc() &&
756 !th.AsMethodTable()->IsTruePrimitive() &&
759 // now ntype contains the native type of *pManagedElemType
760 if (ntype == NATIVE_TYPE_DEFAULT)
762 // Let's update the caller's native type with default type only.
763 // Updating with a non-default native type that is not allowed
764 // for the given managed type would result in confusing exception
766 *pNativeType = ntype;
770 *pManagedElemType = sigElemType;
776 VOID ThrowInteropParamException(UINT resID, UINT paramIdx)
788 paramString.Set(W("return value"));
790 paramString.Printf(W("parameter #%u"), paramIdx);
792 SString errorString(W("Unknown error."));
793 errorString.LoadResource(CCompRC::Error, resID);
795 COMPlusThrow(kMarshalDirectiveException, IDS_EE_BADMARSHAL_ERROR_MSG, paramString.GetUnicode(), errorString.GetUnicode());
798 //===============================================================
799 // Collects paraminfo's in an indexed array so that:
801 // aParams[0] == param token for return value
802 // aParams[1] == param token for argument #1...
803 // aParams[numargs] == param token for argument #n...
805 // If no param token exists, the corresponding array element
806 // is set to mdParamDefNil.
809 // pInternalImport -- ifc for metadata api
810 // md -- token of method. If token is mdMethodNil,
811 // all aParam elements will be set to mdParamDefNil.
812 // numargs -- # of arguments in mdMethod
813 // aParams -- uninitialized array with numargs+1 elements.
814 // on exit, will be filled with param tokens.
815 //===============================================================
816 VOID CollateParamTokens(IMDInternalImport *pInternalImport, mdMethodDef md, ULONG numargs, mdParamDef *aParams)
826 for (ULONG i = 0; i < numargs + 1; i++)
827 aParams[i] = mdParamDefNil;
829 if (md != mdMethodDefNil)
831 MDEnumHolder hEnumParams(pInternalImport);
832 HRESULT hr = pInternalImport->EnumInit(mdtParamDef, md, &hEnumParams);
835 // no param info: nothing left to do here
839 mdParamDef CurrParam = mdParamDefNil;
840 while (pInternalImport->EnumNext(&hEnumParams, &CurrParam))
844 LPCSTR szParamName_Ignore;
845 if (SUCCEEDED(pInternalImport->GetParamDefProps(CurrParam, &usSequence, &dwAttr, &szParamName_Ignore)))
847 if (usSequence > numargs)
848 { // Invalid argument index
849 ThrowHR(COR_E_BADIMAGEFORMAT);
851 if (aParams[usSequence] != mdParamDefNil)
852 { // Duplicit argument index
853 ThrowHR(COR_E_BADIMAGEFORMAT);
855 aParams[usSequence] = CurrParam;
863 #ifdef FEATURE_COMINTEROP
865 void *EventArgsMarshalingInfo::operator new(size_t size, LoaderHeap *pHeap)
872 INJECT_FAULT(COMPlusThrowOM());
873 PRECONDITION(CheckPointer(pHeap));
874 POSTCONDITION(CheckPointer(RETVAL));
878 void* mem = pHeap->AllocMem(S_SIZE_T(size));
883 void EventArgsMarshalingInfo::operator delete(void *pMem)
885 LIMITED_METHOD_CONTRACT;
886 // Instances of this class are always allocated on the loader heap so
887 // the delete operator has nothing to do.
890 EventArgsMarshalingInfo::EventArgsMarshalingInfo()
900 // Load the System.Collections.Specialized.NotifyCollectionChangedEventArgs class.
901 SString qualifiedNCCEventArgsTypeName(SString::Utf8, NCCEVENTARGS_ASM_QUAL_TYPE_NAME);
902 m_hndSystemNCCEventArgsType = TypeName::GetTypeFromAsmQualifiedName(qualifiedNCCEventArgsTypeName.GetUnicode());
903 _ASSERTE(!m_hndSystemNCCEventArgsType.IsNull() && "Cannot load System.Collections.Specialized.NotifyCollectionChangedEventArgs!");
905 // Load the System.ComponentModel.PropertyChangedEventArgs class.
906 SString qualifiedPCEventArgsTypeName(SString::Utf8, PCEVENTARGS_ASM_QUAL_TYPE_NAME);
907 m_hndSystemPCEventArgsType = TypeName::GetTypeFromAsmQualifiedName(qualifiedPCEventArgsTypeName.GetUnicode());
908 _ASSERTE(!m_hndSystemPCEventArgsType.IsNull() && "Cannot load System.ComponentModel.PropertyChangedEventArgs!");
910 // Load the NCCEventArgs marshaler class.
911 SString qualifiedNCCEventArgsMarshalerTypeName(SString::Utf8, NCCEVENTARGS_MARSHALER_ASM_QUAL_TYPE_NAME);
912 TypeHandle hndNCCEventArgsMarshalerType = TypeName::GetTypeFromAsmQualifiedName(qualifiedNCCEventArgsMarshalerTypeName.GetUnicode());
914 // Retrieve the method to convert a .NET NCCEventArgs to a WinRT NCCEventArgs.
915 m_pSystemNCCEventArgsToWinRTNCCEventArgsMD = MemberLoader::FindMethodByName(hndNCCEventArgsMarshalerType.GetMethodTable(), EVENTARGS_TO_WINRT_EVENTARGS_METH_NAME);
916 _ASSERTE(m_pSystemNCCEventArgsToWinRTNCCEventArgsMD && "Unable to find the marshaler method to convert a .NET NCCEventArgs to a WinRT NCCEventArgs!");
918 // Retrieve the method to convert a WinRT NCCEventArgs to a .NET NCCEventArgs.
919 m_pWinRTNCCEventArgsToSystemNCCEventArgsMD = MemberLoader::FindMethodByName(hndNCCEventArgsMarshalerType.GetMethodTable(), WINRT_EVENTARGS_TO_EVENTARGS_METH_NAME);
920 _ASSERTE(m_pWinRTNCCEventArgsToSystemNCCEventArgsMD && "Unable to find the marshaler method to convert a WinRT NCCEventArgs to a .NET NCCEventArgs!");
922 // Load the PCEventArgs marshaler class.
923 SString qualifiedPCEventArgsMarshalerTypeName(SString::Utf8, PCEVENTARGS_MARSHALER_ASM_QUAL_TYPE_NAME);
924 TypeHandle hndPCEventArgsMarshalerType = TypeName::GetTypeFromAsmQualifiedName(qualifiedPCEventArgsMarshalerTypeName.GetUnicode());
926 // Retrieve the method to convert a .NET PCEventArgs to a WinRT PCEventArgs.
927 m_pSystemPCEventArgsToWinRTPCEventArgsMD = MemberLoader::FindMethodByName(hndPCEventArgsMarshalerType.GetMethodTable(), EVENTARGS_TO_WINRT_EVENTARGS_METH_NAME);
928 _ASSERTE(m_pSystemPCEventArgsToWinRTPCEventArgsMD && "Unable to find the marshaler method to convert a .NET PCEventArgs to a WinRT PCEventArgs!");
930 // Retrieve the method to convert a WinRT PCEventArgs to a .NET PCEventArgs.
931 m_pWinRTPCEventArgsToSystemPCEventArgsMD = MemberLoader::FindMethodByName(hndPCEventArgsMarshalerType.GetMethodTable(), WINRT_EVENTARGS_TO_EVENTARGS_METH_NAME);
932 _ASSERTE(m_pWinRTPCEventArgsToSystemPCEventArgsMD && "Unable to find the marshaler method to convert a WinRT PCEventArgs to a .NET PCEventArgs!");
935 EventArgsMarshalingInfo::~EventArgsMarshalingInfo()
937 LIMITED_METHOD_CONTRACT;
940 void *UriMarshalingInfo::operator new(size_t size, LoaderHeap *pHeap)
947 INJECT_FAULT(COMPlusThrowOM());
948 PRECONDITION(CheckPointer(pHeap));
949 POSTCONDITION(CheckPointer(RETVAL));
953 void* mem = pHeap->AllocMem(S_SIZE_T(size));
959 void UriMarshalingInfo::operator delete(void *pMem)
961 LIMITED_METHOD_CONTRACT;
962 // Instances of this class are always allocated on the loader heap so
963 // the delete operator has nothing to do.
966 UriMarshalingInfo::UriMarshalingInfo()
976 // Create on-demand as we don't want to create the factories in NGEN time
977 m_pUriFactory = NULL;
979 // Load the System.Uri class.
980 SString qualifiedUriTypeName(SString::Utf8, URI_ASM_QUAL_TYPE_NAME);
981 m_hndSystemUriType = TypeName::GetTypeFromAsmQualifiedName(qualifiedUriTypeName.GetUnicode());
982 _ASSERTE(!m_hndSystemUriType.IsNull() && "Cannot load System.Uri!");
984 m_SystemUriOriginalStringGetterMD = MemberLoader::FindPropertyMethod(m_hndSystemUriType.GetMethodTable(), ORIGINALSTRING_PROPERTY_NAME, PropertyGet);
985 _ASSERTE(m_SystemUriOriginalStringGetterMD && "Unable to find the System.Uri.get_OriginalString()!");
986 _ASSERTE(!m_SystemUriOriginalStringGetterMD->IsStatic() && "System.Uri.get_OriginalString() is static!");
988 // Windows.Foundation.Uri..ctor(string) and System.Uri..ctor(string)
989 MethodTable* pSystemUriMT = m_hndSystemUriType.AsMethodTable();
990 m_SystemUriCtorMD = MemberLoader::FindConstructor(pSystemUriMT, &gsig_IM_Str_RetVoid);
991 _ASSERTE(m_SystemUriCtorMD && "Unable to find the constructor on System.Uri that takes a string!");
992 _ASSERTE(m_SystemUriCtorMD->IsClassConstructorOrCtor() && !m_SystemUriCtorMD->IsStatic() && "The method retrieved from System.Uri is not a constructor!");
995 UriMarshalingInfo::~UriMarshalingInfo()
1004 #ifndef CROSSGEN_COMPILE
1007 SafeRelease(m_pUriFactory);
1008 m_pUriFactory = NULL;
1013 OleColorMarshalingInfo::OleColorMarshalingInfo() :
1014 m_OleColorToSystemColorMD(NULL),
1015 m_SystemColorToOleColorMD(NULL)
1025 SString qualifiedColorTranslatorTypeName(SString::Utf8, COLOR_TRANSLATOR_ASM_QUAL_TYPE_NAME);
1027 // Load the color translator class.
1028 TypeHandle hndColorTranslatorType = TypeName::GetTypeFromAsmQualifiedName(qualifiedColorTranslatorTypeName.GetUnicode());
1031 SString qualifiedColorTypeName(SString::Utf8, COLOR_ASM_QUAL_TYPE_NAME);
1032 // Load the color class.
1033 m_hndColorType = TypeName::GetTypeFromAsmQualifiedName(qualifiedColorTypeName.GetUnicode());
1035 // Retrieve the method to convert an OLE_COLOR to a System.Drawing.Color.
1036 m_OleColorToSystemColorMD = MemberLoader::FindMethodByName(hndColorTranslatorType.GetMethodTable(), OLECOLOR_TO_SYSTEMCOLOR_METH_NAME);
1037 _ASSERTE(m_OleColorToSystemColorMD && "Unable to find the translator method to convert an OLE_COLOR to a System.Drawing.Color!");
1038 _ASSERTE(m_OleColorToSystemColorMD->IsStatic() && "The translator method to convert an OLE_COLOR to a System.Drawing.Color must be static!");
1040 // Retrieve the method to convert a System.Drawing.Color to an OLE_COLOR.
1041 m_SystemColorToOleColorMD = MemberLoader::FindMethodByName(hndColorTranslatorType.GetMethodTable(), SYSTEMCOLOR_TO_OLECOLOR_METH_NAME);
1042 _ASSERTE(m_SystemColorToOleColorMD && "Unable to find the translator method to convert a System.Drawing.Color to an OLE_COLOR!");
1043 _ASSERTE(m_SystemColorToOleColorMD->IsStatic() && "The translator method to convert a System.Drawing.Color to an OLE_COLOR must be static!");
1047 void *OleColorMarshalingInfo::operator new(size_t size, LoaderHeap *pHeap)
1054 INJECT_FAULT(COMPlusThrowOM());
1055 PRECONDITION(CheckPointer(pHeap));
1056 POSTCONDITION(CheckPointer(RETVAL));
1060 void* mem = pHeap->AllocMem(S_SIZE_T(size));
1066 void OleColorMarshalingInfo::operator delete(void *pMem)
1068 LIMITED_METHOD_CONTRACT;
1069 // Instances of this class are always allocated on the loader heap so
1070 // the delete operator has nothing to do.
1073 #endif // FEATURE_COMINTEROP
1075 EEMarshalingData::EEMarshalingData(LoaderAllocator* pAllocator, CrstBase *pCrst) :
1076 m_pAllocator(pAllocator),
1077 m_pHeap(pAllocator->GetLowFrequencyHeap()),
1088 LockOwner lock = {pCrst, IsOwnerOfCrst};
1089 #ifndef CROSSGEN_COMPILE
1090 m_CMHelperHashtable.Init(INITIAL_NUM_CMHELPER_HASHTABLE_BUCKETS, &lock);
1091 m_SharedCMHelperToCMInfoMap.Init(INITIAL_NUM_CMINFO_HASHTABLE_BUCKETS, &lock);
1092 #endif // CROSSGEN_COMPILE
1096 EEMarshalingData::~EEMarshalingData()
1098 WRAPPER_NO_CONTRACT;
1100 CustomMarshalerInfo *pCMInfo;
1102 // <TODO>@TODO(DM): Remove the linked list of CMInfo's and instead hang the OBJECTHANDLE
1103 // contained inside the CMInfo off the AppDomain directly. The AppDomain can have
1104 // a list of tasks to do when it gets teared down and we could leverage that
1105 // to release the object handles.</TODO>
1107 // Walk through the linked list and delete all the custom marshaler info's.
1108 while ((pCMInfo = m_pCMInfoList.RemoveHead()) != NULL)
1111 #ifdef FEATURE_COMINTEROP
1112 if (m_pOleColorInfo)
1114 delete m_pOleColorInfo;
1115 m_pOleColorInfo = NULL;
1124 if (m_pEventArgsInfo)
1126 delete m_pEventArgsInfo;
1127 m_pEventArgsInfo = NULL;
1133 void *EEMarshalingData::operator new(size_t size, LoaderHeap *pHeap)
1140 INJECT_FAULT(COMPlusThrowOM());
1141 PRECONDITION(CheckPointer(pHeap));
1142 POSTCONDITION(CheckPointer(RETVAL));
1146 void* mem = pHeap->AllocMem(S_SIZE_T(sizeof(EEMarshalingData)));
1152 void EEMarshalingData::operator delete(void *pMem)
1154 LIMITED_METHOD_CONTRACT;
1155 // Instances of this class are always allocated on the loader heap so
1156 // the delete operator has nothing to do.
1159 #ifndef CROSSGEN_COMPILE
1161 CustomMarshalerHelper *EEMarshalingData::GetCustomMarshalerHelper(Assembly *pAssembly, TypeHandle hndManagedType, LPCUTF8 strMarshalerTypeName, DWORD cMarshalerTypeNameBytes, LPCUTF8 strCookie, DWORD cCookieStrBytes)
1163 CONTRACT (CustomMarshalerHelper*)
1168 INJECT_FAULT(COMPlusThrowOM());
1169 PRECONDITION(CheckPointer(pAssembly));
1170 POSTCONDITION(CheckPointer(RETVAL));
1174 CustomMarshalerHelper *pCMHelper = NULL;
1175 CustomMarshalerHelper* pNewCMHelper = NULL;
1176 NewHolder<CustomMarshalerInfo> pNewCMInfo(NULL);
1178 TypeHandle hndCustomMarshalerType;
1180 // Create the key that will be used to lookup in the hashtable.
1181 EECMHelperHashtableKey Key(cMarshalerTypeNameBytes, strMarshalerTypeName, cCookieStrBytes, strCookie, hndManagedType.GetInstantiation(), pAssembly);
1183 // Lookup the custom marshaler helper in the hashtable.
1184 if (m_CMHelperHashtable.GetValue(&Key, (HashDatum*)&pCMHelper))
1190 // Validate the arguments.
1191 _ASSERTE(strMarshalerTypeName && strCookie && !hndManagedType.IsNull());
1193 // Append a NULL terminator to the marshaler type name.
1194 SString strCMMarshalerTypeName(SString::Utf8, strMarshalerTypeName, cMarshalerTypeNameBytes);
1196 // Load the custom marshaler class.
1197 BOOL fNameIsAsmQualified = FALSE;
1198 hndCustomMarshalerType = TypeName::GetTypeUsingCASearchRules(strCMMarshalerTypeName.GetUTF8NoConvert(), pAssembly, &fNameIsAsmQualified);
1200 if (hndCustomMarshalerType.IsGenericTypeDefinition())
1202 // Instantiate generic custom marshalers using the instantiation of the type being marshaled.
1203 hndCustomMarshalerType = hndCustomMarshalerType.Instantiate(hndManagedType.GetInstantiation());
1206 // Set the assembly to null to indicate that the custom marshaler name is assembly
1208 if (fNameIsAsmQualified)
1212 // Create the custom marshaler info in the specified heap.
1213 pNewCMInfo = new (m_pHeap) CustomMarshalerInfo(m_pAllocator, hndCustomMarshalerType, hndManagedType, strCookie, cCookieStrBytes);
1215 // Create the custom marshaler helper in the specified heap.
1216 pNewCMHelper = new (m_pHeap) NonSharedCustomMarshalerHelper(pNewCMInfo);
1220 CrstHolder lock(m_lock);
1222 // Verify that the custom marshaler helper has not already been added by another thread.
1223 if (m_CMHelperHashtable.GetValue(&Key, (HashDatum*)&pCMHelper))
1228 // Add the custom marshaler helper to the hash table.
1229 m_CMHelperHashtable.InsertValue(&Key, pNewCMHelper, FALSE);
1231 // If we create the CM info, then add it to the linked list.
1234 m_pCMInfoList.InsertHead(pNewCMInfo);
1235 pNewCMInfo.SuppressRelease();
1238 // Release the lock and return the custom marshaler info.
1241 RETURN pNewCMHelper;
1244 CustomMarshalerInfo *EEMarshalingData::GetCustomMarshalerInfo(SharedCustomMarshalerHelper *pSharedCMHelper)
1246 CONTRACT (CustomMarshalerInfo*)
1251 INJECT_FAULT(COMPlusThrowOM());
1252 POSTCONDITION(CheckPointer(RETVAL));
1256 CustomMarshalerInfo *pCMInfo = NULL;
1257 NewHolder<CustomMarshalerInfo> pNewCMInfo(NULL);
1258 TypeHandle hndCustomMarshalerType;
1260 // Lookup the custom marshaler helper in the hashtable.
1261 if (m_SharedCMHelperToCMInfoMap.GetValue(pSharedCMHelper, (HashDatum*)&pCMInfo))
1264 // Append a NULL terminator to the marshaler type name.
1265 CQuickArray<char> strCMMarshalerTypeName;
1266 DWORD strLen = pSharedCMHelper->GetMarshalerTypeNameByteCount();
1267 strCMMarshalerTypeName.ReSizeThrows(pSharedCMHelper->GetMarshalerTypeNameByteCount() + 1);
1268 memcpy(strCMMarshalerTypeName.Ptr(), pSharedCMHelper->GetMarshalerTypeName(), strLen);
1269 strCMMarshalerTypeName[strLen] = 0;
1271 // Load the custom marshaler class.
1272 hndCustomMarshalerType = TypeName::GetTypeUsingCASearchRules(strCMMarshalerTypeName.Ptr(), pSharedCMHelper->GetAssembly());
1273 if (hndCustomMarshalerType.IsGenericTypeDefinition())
1275 // Instantiate generic custom marshalers using the instantiation of the type being marshaled.
1276 hndCustomMarshalerType = hndCustomMarshalerType.Instantiate(pSharedCMHelper->GetManagedType().GetInstantiation());
1279 // Create the custom marshaler info in the specified heap.
1280 pNewCMInfo = new (m_pHeap) CustomMarshalerInfo(m_pAllocator,
1281 hndCustomMarshalerType,
1282 pSharedCMHelper->GetManagedType(),
1283 pSharedCMHelper->GetCookieString(),
1284 pSharedCMHelper->GetCookieStringByteCount());
1287 CrstHolder lock(m_lock);
1289 // Verify that the custom marshaler info has not already been added by another thread.
1290 if (m_SharedCMHelperToCMInfoMap.GetValue(pSharedCMHelper, (HashDatum*)&pCMInfo))
1295 // Add the custom marshaler helper to the hash table.
1296 m_SharedCMHelperToCMInfoMap.InsertValue(pSharedCMHelper, pNewCMInfo, FALSE);
1298 // Add the custom marshaler into the linked list.
1299 m_pCMInfoList.InsertHead(pNewCMInfo);
1301 // Release the lock and return the custom marshaler info.
1304 pNewCMInfo.SuppressRelease();
1307 #endif // CROSSGEN_COMPILE
1309 #ifdef FEATURE_COMINTEROP
1310 UriMarshalingInfo *EEMarshalingData::GetUriMarshalingInfo()
1312 CONTRACT (UriMarshalingInfo*)
1317 INJECT_FAULT(COMPlusThrowOM());
1318 POSTCONDITION(CheckPointer(RETVAL));
1322 if (m_pUriInfo == NULL)
1324 UriMarshalingInfo *pUriInfo = new (m_pHeap) UriMarshalingInfo();
1326 if (InterlockedCompareExchangeT(&m_pUriInfo, pUriInfo, NULL) != NULL)
1328 // Another thread beat us to it. Delete on UriMarshalingInfo is an empty operation
1329 // which is OK, since the possible leak is rare, small, and constant. This is the same
1330 // pattern as in code:GetCustomMarshalerInfo.
1338 EventArgsMarshalingInfo *EEMarshalingData::GetEventArgsMarshalingInfo()
1340 CONTRACT (EventArgsMarshalingInfo*)
1345 INJECT_FAULT(COMPlusThrowOM());
1346 POSTCONDITION(CheckPointer(RETVAL));
1350 if (m_pEventArgsInfo == NULL)
1352 EventArgsMarshalingInfo *pEventArgsInfo = new (m_pHeap) EventArgsMarshalingInfo();
1354 if (InterlockedCompareExchangeT(&m_pEventArgsInfo, pEventArgsInfo, NULL) != NULL)
1356 // Another thread beat us to it. Delete on EventArgsMarshalingInfo is an empty operation
1357 // which is OK, since the possible leak is rare, small, and constant. This is the same
1358 // pattern as in code:GetCustomMarshalerInfo.
1359 delete pEventArgsInfo;
1363 RETURN m_pEventArgsInfo;
1366 OleColorMarshalingInfo *EEMarshalingData::GetOleColorMarshalingInfo()
1368 CONTRACT (OleColorMarshalingInfo*)
1373 INJECT_FAULT(COMPlusThrowOM());
1374 POSTCONDITION(CheckPointer(RETVAL));
1378 if (m_pOleColorInfo == NULL)
1380 OleColorMarshalingInfo *pOleColorInfo = new (m_pHeap) OleColorMarshalingInfo();
1382 if (InterlockedCompareExchangeT(&m_pOleColorInfo, pOleColorInfo, NULL) != NULL)
1384 // Another thread beat us to it. Delete on OleColorMarshalingInfo is an empty operation
1385 // which is OK, since the possible leak is rare, small, and constant. This is the same
1386 // pattern as in code:GetCustomMarshalerInfo.
1387 delete pOleColorInfo;
1391 RETURN m_pOleColorInfo;
1393 #endif // FEATURE_COMINTEROP
1395 //==========================================================================
1396 // Constructs MarshalInfo.
1397 //==========================================================================
1399 #pragma warning(push)
1400 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
1402 MarshalInfo::MarshalInfo(Module* pModule,
1404 const SigTypeContext *pTypeContext,
1407 CorNativeLinkType nlType,
1408 CorNativeLinkFlags nlFlags,
1410 UINT paramidx, // parameter # for use in error messages (ignored if not parameter)
1411 UINT numArgs, // number of arguments
1413 BOOL ThrowOnUnmappableChar,
1415 BOOL onInstanceMethod,
1417 BOOL fLoadCustomMarshal
1421 LPCUTF8 pDebugClassName,
1422 UINT argidx // 0 for return value, -1 for field
1426 STANDARD_VM_CONTRACT;
1429 NativeTypeParamInfo ParamInfo;
1431 // we expect a 1-based paramidx, but we like to use a 0-based paramidx
1432 m_paramidx = paramidx - 1;
1434 // if no one overwrites this with a better message, we'll still at least say something
1435 m_resID = IDS_EE_BADMARSHAL_GENERIC;
1437 // flag for uninitialized type
1438 m_type = MARSHAL_TYPE_UNKNOWN;
1440 CorNativeType nativeType = NATIVE_TYPE_DEFAULT;
1441 Assembly *pAssembly = pModule->GetAssembly();
1442 BOOL fNeedsCopyCtor = FALSE;
1443 m_BestFit = BestFit;
1444 m_ThrowOnUnmappableChar = ThrowOnUnmappableChar;
1446 m_fAnsi = (ms == MARSHAL_SCENARIO_NDIRECT) && (nlType == nltAnsi);
1447 m_managedArgSize = 0;
1448 m_nativeArgSize = 0;
1451 m_args.m_pMarshalInfo = this;
1452 m_args.m_pMT = NULL;
1453 m_pModule = pModule;
1454 CorElementType mtype = ELEMENT_TYPE_END;
1455 CorElementType corElemType = ELEMENT_TYPE_END;
1459 #ifdef FEATURE_COMINTEROP
1462 m_fErrorNativeType = FALSE;
1463 m_hiddenLengthParamIndex = (UINT16)-1;
1464 m_dwHiddenLengthManagedHomeLocal= 0xFFFFFFFF;
1465 m_dwHiddenLengthNativeHomeLocal = 0xFFFFFFFF;
1467 m_pDefaultItfMT = NULL;
1468 #endif // FEATURE_COMINTEROP
1473 CHAR achDbgContext[DEBUG_CONTEXT_STR_LEN] = "";
1476 strncpy_s(achDbgContext, COUNTOF(achDbgContext), "<Unknown>", _TRUNCATE);
1480 strncat_s(achDbgContext, COUNTOF(achDbgContext), pDebugClassName, _TRUNCATE);
1481 strncat_s(achDbgContext, COUNTOF(achDbgContext), NAMESPACE_SEPARATOR_STR, _TRUNCATE);
1482 strncat_s(achDbgContext, COUNTOF(achDbgContext), pDebugName, _TRUNCATE);
1483 strncat_s(achDbgContext, COUNTOF(achDbgContext), " ", _TRUNCATE);
1487 strncat_s(achDbgContext, COUNTOF(achDbgContext), "field", _TRUNCATE);
1490 strncat_s(achDbgContext, COUNTOF(achDbgContext), "return value", _TRUNCATE);
1495 sprintf_s(buf, COUNTOF(buf), "param #%lu", (ULONG)argidx);
1496 strncat_s(achDbgContext, COUNTOF(achDbgContext), buf, _TRUNCATE);
1501 m_strDebugMethName = pDebugName;
1502 m_strDebugClassName = pDebugClassName;
1505 m_in = m_out = FALSE;
1511 // Retrieve the native type for the current parameter.
1512 if (!ParseNativeTypeInfo(token, pModule->GetMDImport(), &ParamInfo))
1514 IfFailGoto(E_FAIL, lFail);
1517 nativeType = ParamInfo.m_NativeType;
1519 corElemType = sig.PeekElemTypeNormalized(pModule, pTypeContext);
1520 mtype = corElemType;
1522 #ifdef FEATURE_COMINTEROP
1523 if (IsWinRTScenario() && nativeType != NATIVE_TYPE_DEFAULT)
1525 // Do not allow any MarshalAs in WinRT scenarios - marshaling is fully described by the parameter type.
1526 m_type = MARSHAL_TYPE_UNKNOWN;
1527 m_resID = IDS_EE_BADMARSHAL_WINRT_MARSHAL_AS;
1528 IfFailGoto(E_FAIL, lFail);
1530 #endif // FEATURE_COMINTEROP
1532 // Make sure SizeParamIndex < numArgs when marshalling native arrays
1533 if (nativeType == NATIVE_TYPE_ARRAY && ParamInfo.m_SizeIsSpecified)
1535 if (ParamInfo.m_Multiplier > 0 && ParamInfo.m_CountParamIdx >= numArgs)
1537 // Do not throw exception here.
1538 // We'll use EmitOrThrowInteropException to throw exception in non-COM interop
1539 // and emit exception throwing code directly in STUB in COM interop
1540 m_type = MARSHAL_TYPE_UNKNOWN;
1541 m_resID = IDS_EE_SIZECONTROLOUTOFRANGE;
1542 IfFailGoto(E_FAIL, lFail);
1546 // Parse ET_BYREF signature
1547 if (mtype == ELEMENT_TYPE_BYREF)
1550 SigPointer sigtmp = sig;
1551 IfFailGoto(sig.GetElemType(NULL), lFail);
1552 mtype = sig.PeekElemTypeNormalized(pModule, pTypeContext);
1554 // Check for Copy Constructor Modifier - peek closed elem type here to prevent ELEMENT_TYPE_VALUETYPE
1555 // turning into a primitive.
1556 if (sig.PeekElemTypeClosed(pModule, pTypeContext) == ELEMENT_TYPE_VALUETYPE)
1559 IfFailGoto(sigtmp.GetByte(NULL), lFail);
1561 if (sigtmp.HasCustomModifier(pModule, "Microsoft.VisualC.NeedsCopyConstructorModifier", ELEMENT_TYPE_CMOD_REQD) ||
1562 sigtmp.HasCustomModifier(pModule, "System.Runtime.CompilerServices.IsCopyConstructed", ELEMENT_TYPE_CMOD_REQD) )
1564 mtype = ELEMENT_TYPE_VALUETYPE;
1565 fNeedsCopyCtor = TRUE;
1575 // Check for valid ET_PTR signature
1576 if (mtype == ELEMENT_TYPE_PTR)
1578 #ifdef FEATURE_COMINTEROP
1579 // WinRT does not support ET_PTR
1580 if (IsWinRTScenario())
1582 m_type = MARSHAL_TYPE_UNKNOWN;
1583 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
1584 IfFailGoto(E_FAIL, lFail);
1586 #endif // FEATURE_COMINTEROP
1588 SigPointer sigtmp = sig;
1589 IfFailGoto(sigtmp.GetElemType(NULL), lFail);
1591 // Peek closed elem type here to prevent ELEMENT_TYPE_VALUETYPE turning into a primitive.
1592 CorElementType mtype2 = sigtmp.PeekElemTypeClosed(pModule, pTypeContext);
1594 if (mtype2 == ELEMENT_TYPE_VALUETYPE)
1597 TypeHandle th = sigtmp.GetTypeHandleThrowing(pModule, pTypeContext);
1598 _ASSERTE(!th.IsNull());
1600 // We want to leave out enums as they surely don't have copy constructors
1601 // plus they are not marked as blittable.
1604 // It should be blittable
1605 if (!th.IsBlittable())
1607 m_resID = IDS_EE_BADMARSHAL_PTRNONBLITTABLE;
1608 IfFailGoto(E_FAIL, lFail);
1611 // Check for Copy Constructor Modifier
1612 if (sigtmp.HasCustomModifier(pModule, "Microsoft.VisualC.NeedsCopyConstructorModifier", ELEMENT_TYPE_CMOD_REQD) ||
1613 sigtmp.HasCustomModifier(pModule, "System.Runtime.CompilerServices.IsCopyConstructed", ELEMENT_TYPE_CMOD_REQD) )
1617 // Keep the sig pointer in sync with mtype (skip ELEMENT_TYPE_PTR) because for the rest
1618 // of this method we are pretending that the parameter is a value type passed by-value.
1619 IfFailGoto(sig.GetElemType(NULL), lFail);
1621 fNeedsCopyCtor = TRUE;
1628 if (!(mtype2 != ELEMENT_TYPE_CLASS &&
1629 mtype2 != ELEMENT_TYPE_STRING &&
1630 mtype2 != ELEMENT_TYPE_OBJECT &&
1631 mtype2 != ELEMENT_TYPE_SZARRAY))
1633 m_resID = IDS_EE_BADMARSHAL_PTRSUBTYPE;
1634 IfFailGoto(E_FAIL, lFail);
1640 // System primitive types (System.Int32, et.al.) will be marshaled as expected
1641 // because the mtype CorElementType is normalized (e.g. ELEMENT_TYPE_I4).
1643 // We however need to detect if such a normalization occurred for non-system
1644 // trivial value types, because we hold CorNativeType belonging to the original
1645 // "un-normalized" signature type. It has to be verified that all the value types
1646 // that have been normalized away have default marshaling or MarshalAs(Struct).
1647 // In addition, the nativeType must be updated with the type of the real primitive inside.
1648 // We don't normalize on return values of member functions since struct return values need to be treated as structures.
1649 if (isParam || !onInstanceMethod)
1651 VerifyAndAdjustNormalizedType(pModule, sig, pTypeContext, &mtype, &nativeType);
1655 SigPointer sigtmp = sig;
1656 CorElementType closedElemType = sigtmp.PeekElemTypeClosed(pModule, pTypeContext);
1657 if (closedElemType == ELEMENT_TYPE_VALUETYPE)
1659 TypeHandle th = sigtmp.GetTypeHandleThrowing(pModule, pTypeContext);
1660 // If the return type of an instance method is a value-type we need the actual return type.
1661 // However, if the return type is an enum, we can normalize it.
1664 mtype = closedElemType;
1669 #endif // _TARGET_X86_
1672 if (nativeType == NATIVE_TYPE_CUSTOMMARSHALER)
1676 case ELEMENT_TYPE_VAR:
1677 case ELEMENT_TYPE_CLASS:
1678 case ELEMENT_TYPE_OBJECT:
1679 m_CMVt = VT_UNKNOWN;
1682 case ELEMENT_TYPE_STRING:
1683 case ELEMENT_TYPE_SZARRAY:
1684 case ELEMENT_TYPE_ARRAY:
1689 m_resID = IDS_EE_BADMARSHAL_CUSTOMMARSHALER;
1690 IfFailGoto(E_FAIL, lFail);
1693 // Set m_type to MARSHAL_TYPE_UNKNOWN in case SetupCustomMarshalerHelper throws.
1694 m_type = MARSHAL_TYPE_UNKNOWN;
1696 if (fLoadCustomMarshal)
1698 // Set up the custom marshaler info.
1699 TypeHandle hndManagedType = sig.GetTypeHandleThrowing(pModule, pTypeContext);
1703 m_pCMHelper = SetupCustomMarshalerHelper(ParamInfo.m_strCMMarshalerTypeName,
1704 ParamInfo.m_cCMMarshalerTypeNameBytes,
1705 ParamInfo.m_strCMCookie,
1706 ParamInfo.m_cCMCookieStrBytes,
1713 MethodDesc* pMDforModule = pMD;
1714 if (pMD->IsILStub())
1716 pMDforModule = pMD->AsDynamicMethodDesc()->GetILStubResolver()->GetStubTargetMethodDesc();
1718 m_args.rcm.m_pMD = pMDforModule;
1719 m_args.rcm.m_paramToken = token;
1720 m_args.rcm.m_hndManagedType = hndManagedType.AsPtr();
1721 CONSISTENCY_CHECK(pModule == pMDforModule->GetModule());
1725 // Specify which custom marshaler to use.
1726 m_type = MARSHAL_TYPE_REFERENCECUSTOMMARSHALER;
1733 case ELEMENT_TYPE_BOOLEAN:
1736 case NATIVE_TYPE_BOOLEAN:
1737 m_type = MARSHAL_TYPE_WINBOOL;
1740 #ifdef FEATURE_COMINTEROP
1741 case NATIVE_TYPE_VARIANTBOOL:
1742 m_type = MARSHAL_TYPE_VTBOOL;
1744 #endif // FEATURE_COMINTEROP
1746 case NATIVE_TYPE_U1:
1747 case NATIVE_TYPE_I1:
1748 m_type = MARSHAL_TYPE_CBOOL;
1751 case NATIVE_TYPE_DEFAULT:
1752 #ifdef FEATURE_COMINTEROP
1753 if (m_ms == MARSHAL_SCENARIO_COMINTEROP)
1755 // 2-byte COM VARIANT_BOOL
1756 m_type = MARSHAL_TYPE_VTBOOL;
1758 else if (m_ms == MARSHAL_SCENARIO_WINRT)
1760 // 1-byte WinRT bool
1761 m_type = MARSHAL_TYPE_CBOOL;
1764 #endif // FEATURE_COMINTEROP
1766 // 4-byte Windows BOOL
1767 _ASSERTE(m_ms == MARSHAL_SCENARIO_NDIRECT);
1768 m_type = MARSHAL_TYPE_WINBOOL;
1773 m_resID = IDS_EE_BADMARSHAL_BOOLEAN;
1774 IfFailGoto(E_FAIL, lFail);
1778 case ELEMENT_TYPE_CHAR:
1781 case NATIVE_TYPE_I1: //fallthru
1782 case NATIVE_TYPE_U1:
1783 m_type = MARSHAL_TYPE_ANSICHAR;
1786 case NATIVE_TYPE_I2: //fallthru
1787 case NATIVE_TYPE_U2:
1788 m_type = MARSHAL_TYPE_GENERIC_U2;
1791 case NATIVE_TYPE_DEFAULT:
1792 m_type = ( (m_ms == MARSHAL_SCENARIO_NDIRECT && m_fAnsi) ? MARSHAL_TYPE_ANSICHAR : MARSHAL_TYPE_GENERIC_U2 );
1796 m_resID = IDS_EE_BADMARSHAL_CHAR;
1797 IfFailGoto(E_FAIL, lFail);
1802 case ELEMENT_TYPE_I1:
1803 if (!(nativeType == NATIVE_TYPE_I1 || nativeType == NATIVE_TYPE_U1 || nativeType == NATIVE_TYPE_DEFAULT))
1805 m_resID = IDS_EE_BADMARSHAL_I1;
1806 IfFailGoto(E_FAIL, lFail);
1808 m_type = MARSHAL_TYPE_GENERIC_1;
1811 case ELEMENT_TYPE_U1:
1812 if (!(nativeType == NATIVE_TYPE_U1 || nativeType == NATIVE_TYPE_I1 || nativeType == NATIVE_TYPE_DEFAULT))
1814 m_resID = IDS_EE_BADMARSHAL_I1;
1815 IfFailGoto(E_FAIL, lFail);
1817 m_type = MARSHAL_TYPE_GENERIC_U1;
1820 case ELEMENT_TYPE_I2:
1821 if (!(nativeType == NATIVE_TYPE_I2 || nativeType == NATIVE_TYPE_U2 || nativeType == NATIVE_TYPE_DEFAULT))
1823 m_resID = IDS_EE_BADMARSHAL_I2;
1824 IfFailGoto(E_FAIL, lFail);
1826 m_type = MARSHAL_TYPE_GENERIC_2;
1829 case ELEMENT_TYPE_U2:
1830 if (!(nativeType == NATIVE_TYPE_U2 || nativeType == NATIVE_TYPE_I2 || nativeType == NATIVE_TYPE_DEFAULT))
1832 m_resID = IDS_EE_BADMARSHAL_I2;
1833 IfFailGoto(E_FAIL, lFail);
1835 m_type = MARSHAL_TYPE_GENERIC_U2;
1838 case ELEMENT_TYPE_I4:
1841 case NATIVE_TYPE_I4:
1842 case NATIVE_TYPE_U4:
1843 case NATIVE_TYPE_DEFAULT:
1846 #ifdef FEATURE_COMINTEROP
1847 case NATIVE_TYPE_ERROR:
1848 m_fErrorNativeType = TRUE;
1850 #endif // FEATURE_COMINTEROP
1853 m_resID = IDS_EE_BADMARSHAL_I4;
1854 IfFailGoto(E_FAIL, lFail);
1856 m_type = MARSHAL_TYPE_GENERIC_4;
1859 case ELEMENT_TYPE_U4:
1862 case NATIVE_TYPE_I4:
1863 case NATIVE_TYPE_U4:
1864 case NATIVE_TYPE_DEFAULT:
1867 #ifdef FEATURE_COMINTEROP
1868 case NATIVE_TYPE_ERROR:
1869 m_fErrorNativeType = TRUE;
1871 #endif // FEATURE_COMINTEROP
1874 m_resID = IDS_EE_BADMARSHAL_I4;
1875 IfFailGoto(E_FAIL, lFail);
1877 m_type = MARSHAL_TYPE_GENERIC_4;
1880 case ELEMENT_TYPE_I8:
1881 if (!(nativeType == NATIVE_TYPE_I8 || nativeType == NATIVE_TYPE_U8 || nativeType == NATIVE_TYPE_DEFAULT))
1883 m_resID = IDS_EE_BADMARSHAL_I8;
1884 IfFailGoto(E_FAIL, lFail);
1886 m_type = MARSHAL_TYPE_GENERIC_8;
1889 case ELEMENT_TYPE_U8:
1890 if (!(nativeType == NATIVE_TYPE_U8 || nativeType == NATIVE_TYPE_I8 || nativeType == NATIVE_TYPE_DEFAULT))
1892 m_resID = IDS_EE_BADMARSHAL_I8;
1893 IfFailGoto(E_FAIL, lFail);
1895 m_type = MARSHAL_TYPE_GENERIC_8;
1898 case ELEMENT_TYPE_I:
1899 // Technically the "native int" and "native uint" types aren't supported in the WinRT scenario,
1900 // but we need to not block ourselves from using them to enable accurate managed->native marshalling of
1901 // projected types such as NotifyCollectionChangedEventArgs and NotifyPropertyChangedEventArgs.
1903 if (!(nativeType == NATIVE_TYPE_INT || nativeType == NATIVE_TYPE_UINT || nativeType == NATIVE_TYPE_DEFAULT))
1905 m_resID = IDS_EE_BADMARSHAL_I;
1906 IfFailGoto(E_FAIL, lFail);
1908 m_type = (sizeof(LPVOID) == 4 ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8);
1911 case ELEMENT_TYPE_U:
1913 if (!(nativeType == NATIVE_TYPE_UINT || nativeType == NATIVE_TYPE_INT || nativeType == NATIVE_TYPE_DEFAULT))
1915 m_resID = IDS_EE_BADMARSHAL_I;
1916 IfFailGoto(E_FAIL, lFail);
1918 m_type = (sizeof(LPVOID) == 4 ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8);
1922 case ELEMENT_TYPE_R4:
1923 if (!(nativeType == NATIVE_TYPE_R4 || nativeType == NATIVE_TYPE_DEFAULT))
1925 m_resID = IDS_EE_BADMARSHAL_R4;
1926 IfFailGoto(E_FAIL, lFail);
1928 m_type = MARSHAL_TYPE_FLOAT;
1931 case ELEMENT_TYPE_R8:
1932 if (!(nativeType == NATIVE_TYPE_R8 || nativeType == NATIVE_TYPE_DEFAULT))
1934 m_resID = IDS_EE_BADMARSHAL_R8;
1935 IfFailGoto(E_FAIL, lFail);
1937 m_type = MARSHAL_TYPE_DOUBLE;
1940 case ELEMENT_TYPE_PTR:
1941 #ifdef FEATURE_COMINTEROP
1942 _ASSERTE(!IsWinRTScenario()); // we checked for this earlier
1943 #endif // FEATURE_COMINTEROP
1945 if (nativeType != NATIVE_TYPE_DEFAULT)
1947 m_resID = IDS_EE_BADMARSHAL_PTR;
1948 IfFailGoto(E_FAIL, lFail);
1950 m_type = ( (sizeof(void*)==4) ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8 );
1953 case ELEMENT_TYPE_FNPTR:
1954 #ifdef FEATURE_COMINTEROP
1955 if (IsWinRTScenario())
1957 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
1958 IfFailGoto(E_FAIL, lFail);
1960 #endif // FEATURE_COMINTEROP
1962 if (!(nativeType == NATIVE_TYPE_FUNC || nativeType == NATIVE_TYPE_DEFAULT))
1964 m_resID = IDS_EE_BADMARSHAL_FNPTR;
1965 IfFailGoto(E_FAIL, lFail);
1967 m_type = ( (sizeof(void*)==4) ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8 );
1970 case ELEMENT_TYPE_OBJECT:
1971 case ELEMENT_TYPE_STRING:
1972 case ELEMENT_TYPE_CLASS:
1973 case ELEMENT_TYPE_VAR:
1975 TypeHandle sigTH = sig.GetTypeHandleThrowing(pModule, pTypeContext);
1977 // Disallow marshaling generic types except for WinRT interfaces.
1978 if (sigTH.HasInstantiation())
1980 #ifdef FEATURE_COMINTEROP
1981 if (!sigTH.SupportsGenericInterop(TypeHandle::Interop_NativeToManaged))
1982 #endif // FEATURE_COMINTEROP
1984 m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
1985 IfFailGoto(E_FAIL, lFail);
1989 m_pMT = sigTH.GetMethodTable();
1991 IfFailGoto(COR_E_TYPELOAD, lFail);
1993 #ifdef FEATURE_COMINTEROP
1994 MethodTable* pDefaultMT = NULL;
1996 // Look for marshaling of WinRT runtime classes
1997 if ((m_pMT->IsProjectedFromWinRT() || m_pMT->IsExportedToWinRT()) && !m_pMT->HasExplicitGuid())
1999 // The type loader guarantees that there are no WinRT interfaces without explicit GUID
2000 _ASSERTE(!m_pMT->IsInterface());
2002 // Make sure that this is really a legal runtime class and not a custom attribute or delegate
2003 if (!m_pMT->IsLegalNonArrayWinRTType() || m_pMT->IsDelegate())
2005 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2006 IfFailGoto(E_FAIL, lFail);
2009 // This class must have a default interface that describes how it is marshaled
2010 pDefaultMT = m_pMT->GetDefaultWinRTInterface();
2011 if (pDefaultMT == NULL)
2013 m_resID = IDS_EE_BADMARSHAL_WINRT_MISSING_GUID;
2014 IfFailGoto(E_FAIL, lFail);
2018 if (nativeType == NATIVE_TYPE_INTF)
2021 if (sig.IsStringType(pModule, pTypeContext))
2023 m_resID = IDS_EE_BADMARSHALPARAM_STRING;
2024 IfFailGoto(E_FAIL, lFail);
2027 if (COMDelegate::IsDelegate(m_pMT))
2029 if (m_ms == MARSHAL_SCENARIO_WINRT)
2031 // In WinRT scenarios delegates must be WinRT delegates
2032 if (!m_pMT->IsProjectedFromWinRT() && !WinRTTypeNameConverter::IsRedirectedType(m_pMT))
2034 m_resID = IDS_EE_BADMARSHAL_WINRT_DELEGATE;
2035 IfFailGoto(E_FAIL, lFail);
2040 // UnmanagedType.Interface for delegates used to mean the .NET Framework _Delegate interface.
2041 // We don't support that interface in .NET Core, so we disallow marshalling as it here.
2042 // The user can specify UnmanagedType.IDispatch and use the delegate through the IDispatch interface
2043 // if they need an interface pointer.
2044 m_resID = IDS_EE_BADMARSHAL_DELEGATE_TLB_INTERFACE;
2045 IfFailGoto(E_FAIL, lFail);
2048 m_type = MARSHAL_TYPE_INTERFACE;
2050 else if (pDefaultMT != NULL && nativeType == NATIVE_TYPE_DEFAULT)
2052 // Pretend this is really marshaling as the default interface type
2054 // Validate it's a WinRT interface with GUID
2055 if (!pDefaultMT->IsInterface() ||
2056 (!pDefaultMT->IsProjectedFromWinRT() && !pDefaultMT->IsExportedToWinRT()) ||
2057 !pDefaultMT->HasExplicitGuid())
2059 // This might also be a redirected interface - which is also allowed
2060 if (!pDefaultMT->IsWinRTRedirectedInterface(TypeHandle::Interop_NativeToManaged))
2062 m_resID = IDS_EE_BADMARSHAL_DEFAULTIFACE_NOT_WINRT_IFACE;
2063 IfFailGoto(E_FAIL, lFail);
2067 // Validate that it's one of the component interfaces of the class in the signature
2068 if (!m_pMT->ImplementsEquivalentInterface(pDefaultMT))
2070 m_resID = IDS_EE_BADMARSHAL_DEFAULTIFACE_NOT_SUBTYPE;
2071 IfFailGoto(E_FAIL, lFail);
2074 // Make sure it's not an unexpected generic case (not clear we can actually get here in practice due
2075 // to the above Implements check)
2076 if (pDefaultMT->HasInstantiation() && !pDefaultMT->SupportsGenericInterop(TypeHandle::Interop_NativeToManaged))
2078 m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
2079 IfFailGoto(E_FAIL, lFail);
2082 // Store the marshal data just as if we were marshaling as this default interface type
2083 m_type = MARSHAL_TYPE_INTERFACE;
2084 m_pDefaultItfMT = pDefaultMT;
2087 #endif // FEATURE_COMINTEROP
2089 bool builder = false;
2090 if (sig.IsStringTypeThrowing(pModule, pTypeContext)
2091 || ((builder = true), 0)
2092 || sig.IsClassThrowing(pModule, g_StringBufferClassName, pTypeContext)
2095 switch ( nativeType )
2097 case NATIVE_TYPE_LPWSTR:
2098 m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_LPWSTR;
2101 case NATIVE_TYPE_LPSTR:
2102 m_type = builder ? MARSHAL_TYPE_LPSTR_BUFFER : MARSHAL_TYPE_LPSTR;
2105 case NATIVE_TYPE_LPUTF8STR:
2106 m_type = builder ? MARSHAL_TYPE_UTF8_BUFFER : MARSHAL_TYPE_LPUTF8STR;
2109 case NATIVE_TYPE_LPTSTR:
2111 #ifdef FEATURE_COMINTEROP
2112 if (m_ms != MARSHAL_SCENARIO_NDIRECT)
2114 _ASSERTE(m_ms == MARSHAL_SCENARIO_COMINTEROP);
2115 // We disallow NATIVE_TYPE_LPTSTR for COM.
2116 IfFailGoto(E_FAIL, lFail);
2118 #endif // FEATURE_COMINTEROP
2119 // We no longer support Win9x so LPTSTR always maps to a Unicode string.
2120 m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_LPWSTR;
2124 case NATIVE_TYPE_BSTR:
2127 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2128 IfFailGoto(E_FAIL, lFail);
2130 m_type = MARSHAL_TYPE_BSTR;
2133 case NATIVE_TYPE_ANSIBSTR:
2136 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2137 IfFailGoto(E_FAIL, lFail);
2139 m_type = MARSHAL_TYPE_ANSIBSTR;
2142 case NATIVE_TYPE_TBSTR:
2146 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2147 IfFailGoto(E_FAIL, lFail);
2150 // We no longer support Win9x so TBSTR always maps to a normal (unicode) BSTR.
2151 m_type = MARSHAL_TYPE_BSTR;
2155 #ifdef FEATURE_COMINTEROP
2156 case NATIVE_TYPE_BYVALSTR:
2160 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2161 IfFailGoto(E_FAIL, lFail);
2163 m_type = m_fAnsi ? MARSHAL_TYPE_VBBYVALSTR : MARSHAL_TYPE_VBBYVALSTRW;
2167 case NATIVE_TYPE_HSTRING:
2171 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2172 IfFailGoto(E_FAIL, lFail);
2175 m_type = MARSHAL_TYPE_HSTRING;
2178 #endif // FEATURE_COMINTEROP
2180 case NATIVE_TYPE_DEFAULT:
2182 #ifdef FEATURE_COMINTEROP
2183 if (m_ms == MARSHAL_SCENARIO_WINRT)
2187 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2188 IfFailGoto(E_FAIL, lFail);
2191 m_type = MARSHAL_TYPE_HSTRING;
2193 else if (m_ms != MARSHAL_SCENARIO_NDIRECT)
2195 _ASSERTE(m_ms == MARSHAL_SCENARIO_COMINTEROP);
2196 m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_BSTR;
2199 #endif // FEATURE_COMINTEROP
2202 m_type = builder ? MARSHAL_TYPE_LPSTR_BUFFER : MARSHAL_TYPE_LPSTR;
2206 m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_LPWSTR;
2212 m_resID = builder ? IDS_EE_BADMARSHALPARAM_STRINGBUILDER : IDS_EE_BADMARSHALPARAM_STRING;
2213 IfFailGoto(E_FAIL, lFail);
2217 #ifdef FEATURE_COMINTEROP
2218 else if (sig.IsClassThrowing(pModule, g_CollectionsEnumeratorClassName, pTypeContext) &&
2219 nativeType == NATIVE_TYPE_DEFAULT)
2221 m_CMVt = VT_UNKNOWN;
2222 m_type = MARSHAL_TYPE_REFERENCECUSTOMMARSHALER;
2224 if (fLoadCustomMarshal)
2228 m_pCMHelper = SetupCustomMarshalerHelper(ENUMERATOR_TO_ENUM_VARIANT_CM_NAME,
2229 ENUMERATOR_TO_ENUM_VARIANT_CM_NAME_LEN,
2230 ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE,
2231 ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE_LEN,
2237 MethodDesc* pMDforModule = pMD;
2238 if (pMD->IsILStub())
2240 pMDforModule = pMD->AsDynamicMethodDesc()->GetILStubResolver()->GetStubTargetMethodDesc();
2242 m_args.rcm.m_pMD = pMDforModule;
2243 m_args.rcm.m_paramToken = token;
2244 m_args.rcm.m_hndManagedType = sigTH.AsPtr();
2245 CONSISTENCY_CHECK(pModule == pMDforModule->GetModule());
2249 #endif // FEATURE_COMINTEROP
2250 else if (sigTH.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE))))
2252 if (nativeType != NATIVE_TYPE_DEFAULT)
2254 m_resID = IDS_EE_BADMARSHAL_SAFEHANDLE;
2255 IfFailGoto(E_FAIL, lFail);
2257 m_args.m_pMT = m_pMT;
2258 m_type = MARSHAL_TYPE_SAFEHANDLE;
2260 else if (sigTH.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__CRITICAL_HANDLE))))
2262 if (nativeType != NATIVE_TYPE_DEFAULT)
2264 m_resID = IDS_EE_BADMARSHAL_CRITICALHANDLE;
2265 IfFailGoto(E_FAIL, lFail);
2267 m_args.m_pMT = m_pMT;
2268 m_type = MARSHAL_TYPE_CRITICALHANDLE;
2270 else if (sig.IsClassThrowing(pModule, g_ReflectionMethodInterfaceName, pTypeContext))
2272 if (nativeType != NATIVE_TYPE_DEFAULT)
2274 IfFailGoto(E_FAIL, lFail);
2277 m_type = MARSHAL_TYPE_RUNTIMEMETHODINFO;
2279 #ifdef FEATURE_COMINTEROP
2280 else if (m_pMT->IsInterface())
2282 if (!(nativeType == NATIVE_TYPE_DEFAULT ||
2283 nativeType == NATIVE_TYPE_INTF))
2285 m_resID = IDS_EE_BADMARSHAL_INTERFACE;
2286 IfFailGoto(E_FAIL, lFail);
2288 m_type = MARSHAL_TYPE_INTERFACE;
2290 if (m_ms == MARSHAL_SCENARIO_WINRT)
2292 // all interfaces marshaled in WinRT scenarios are IInspectable-based
2296 // Check for Windows.Foundation.HResult <-> Exception
2297 else if (m_ms == MARSHAL_SCENARIO_WINRT && MscorlibBinder::IsClass(m_pMT, CLASS__EXCEPTION))
2299 m_args.m_pMT = m_pMT;
2300 m_type = MARSHAL_TYPE_EXCEPTION;
2302 #endif // FEATURE_COMINTEROP
2303 else if (COMDelegate::IsDelegate(m_pMT))
2305 m_args.m_pMT = m_pMT;
2306 #ifdef FEATURE_COMINTEROP
2307 if (m_ms == MARSHAL_SCENARIO_WINRT)
2309 // Delegates must be imported from WinRT and marshaled as Interface
2310 if (!m_pMT->IsProjectedFromWinRT() && !WinRTTypeNameConverter::IsRedirectedType(m_pMT))
2312 m_resID = IDS_EE_BADMARSHAL_WINRT_DELEGATE;
2313 IfFailGoto(E_FAIL, lFail);
2316 #endif // FEATURE_COMINTEROP
2320 case NATIVE_TYPE_FUNC:
2321 m_type = MARSHAL_TYPE_DELEGATE;
2324 case NATIVE_TYPE_DEFAULT:
2325 #ifdef FEATURE_COMINTEROP
2326 if (m_ms == MARSHAL_SCENARIO_WINRT)
2328 m_type = MARSHAL_TYPE_INTERFACE;
2330 else if (m_ms == MARSHAL_SCENARIO_COMINTEROP)
2332 // Default for COM marshalling for delegates used to mean the .NET Framework _Delegate interface.
2333 // We don't support that interface in .NET Core, so we disallow marshalling as it here.
2334 // The user can specify UnmanagedType.IDispatch and use the delegate through the IDispatch interface
2335 // if they need an interface pointer.
2336 m_resID = IDS_EE_BADMARSHAL_DELEGATE_TLB_INTERFACE;
2337 IfFailGoto(E_FAIL, lFail);
2340 #endif // FEATURE_COMINTEROP
2341 m_type = MARSHAL_TYPE_DELEGATE;
2344 #ifdef FEATURE_COMINTEROP
2345 case NATIVE_TYPE_IDISPATCH:
2346 m_type = MARSHAL_TYPE_INTERFACE;
2350 m_resID = IDS_EE_BADMARSHAL_DELEGATE;
2351 IfFailGoto(E_FAIL, lFail);
2355 else if (m_pMT->IsBlittable())
2357 if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_LPSTRUCT))
2359 m_resID = IDS_EE_BADMARSHAL_CLASS;
2360 IfFailGoto(E_FAIL, lFail);
2362 m_type = MARSHAL_TYPE_BLITTABLEPTR;
2363 m_args.m_pMT = m_pMT;
2365 else if (m_pMT->HasLayout())
2367 if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_LPSTRUCT))
2369 m_resID = IDS_EE_BADMARSHAL_CLASS;
2370 IfFailGoto(E_FAIL, lFail);
2372 m_type = MARSHAL_TYPE_LAYOUTCLASSPTR;
2373 m_args.m_pMT = m_pMT;
2375 else if (sig.IsClassThrowing(pModule, g_ReflectionModuleName, pTypeContext))
2377 if (nativeType != NATIVE_TYPE_DEFAULT)
2379 IfFailGoto(E_FAIL, lFail);
2382 m_type = MARSHAL_TYPE_RUNTIMEMODULE;
2384 else if (sig.IsClassThrowing(pModule, g_ReflectionAssemblyName, pTypeContext))
2386 if (nativeType != NATIVE_TYPE_DEFAULT)
2388 IfFailGoto(E_FAIL, lFail);
2391 m_type = MARSHAL_TYPE_RUNTIMEASSEMBLY;
2393 #ifdef FEATURE_COMINTEROP
2394 else if (m_ms == MARSHAL_SCENARIO_WINRT && sig.IsClassThrowing(pModule, g_SystemUriClassName, pTypeContext))
2396 m_type = MARSHAL_TYPE_URI;
2398 else if (m_ms == MARSHAL_SCENARIO_WINRT && sig.IsClassThrowing(pModule, g_NotifyCollectionChangedEventArgsName, pTypeContext))
2400 m_type = MARSHAL_TYPE_NCCEVENTARGS;
2402 else if (m_ms == MARSHAL_SCENARIO_WINRT && sig.IsClassThrowing(pModule, g_PropertyChangedEventArgsName, pTypeContext))
2404 m_type = MARSHAL_TYPE_PCEVENTARGS;
2406 #endif // FEATURE_COMINTEROP
2407 else if (m_pMT->IsObjectClass())
2411 #ifdef FEATURE_COMINTEROP
2412 case NATIVE_TYPE_DEFAULT:
2413 if (ms == MARSHAL_SCENARIO_WINRT)
2416 m_type = MARSHAL_TYPE_INTERFACE;
2420 case NATIVE_TYPE_STRUCT:
2421 m_type = MARSHAL_TYPE_OBJECT;
2424 case NATIVE_TYPE_INTF:
2425 case NATIVE_TYPE_IUNKNOWN:
2426 m_type = MARSHAL_TYPE_INTERFACE;
2429 case NATIVE_TYPE_IDISPATCH:
2431 m_type = MARSHAL_TYPE_INTERFACE;
2434 case NATIVE_TYPE_IINSPECTABLE:
2436 m_type = MARSHAL_TYPE_INTERFACE;
2439 case NATIVE_TYPE_DEFAULT:
2440 case NATIVE_TYPE_STRUCT:
2441 m_resID = IDS_EE_OBJECT_TO_VARIANT_NOT_SUPPORTED;
2442 IfFailGoto(E_FAIL, lFail);
2444 case NATIVE_TYPE_INTF:
2445 case NATIVE_TYPE_IUNKNOWN:
2446 case NATIVE_TYPE_IDISPATCH:
2447 m_resID = IDS_EE_OBJECT_TO_ITF_NOT_SUPPORTED;
2448 IfFailGoto(E_FAIL, lFail);
2449 #endif // FEATURE_COMINTEROP
2451 case NATIVE_TYPE_ASANY:
2452 m_type = m_fAnsi ? MARSHAL_TYPE_ASANYA : MARSHAL_TYPE_ASANYW;
2456 m_resID = IDS_EE_BADMARSHAL_OBJECT;
2457 IfFailGoto(E_FAIL, lFail);
2461 #ifdef FEATURE_COMINTEROP
2462 else if (sig.IsClassThrowing(pModule, g_ArrayClassName, pTypeContext))
2464 if (IsWinRTScenario())
2466 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2467 IfFailGoto(E_FAIL, lFail);
2472 case NATIVE_TYPE_DEFAULT:
2473 case NATIVE_TYPE_INTF:
2474 m_type = MARSHAL_TYPE_INTERFACE;
2477 case NATIVE_TYPE_SAFEARRAY:
2479 TypeHandle thElement = TypeHandle(g_pObjectClass);
2481 if (ParamInfo.m_SafeArrayElementVT != VT_EMPTY)
2483 if (ParamInfo.m_cSafeArrayUserDefTypeNameBytes > 0)
2485 // Load the type. Use an SString for the string since we need to NULL terminate the string
2486 // that comes from the metadata.
2487 StackScratchBuffer utf8Name;
2488 SString safeArrayUserDefTypeName(SString::Utf8, ParamInfo.m_strSafeArrayUserDefTypeName, ParamInfo.m_cSafeArrayUserDefTypeNameBytes);
2489 thElement = TypeName::GetTypeUsingCASearchRules(safeArrayUserDefTypeName.GetUTF8(utf8Name), pAssembly);
2494 // Compat: If no safe array VT was specified, default to VT_VARIANT.
2495 ParamInfo.m_SafeArrayElementVT = VT_VARIANT;
2498 IfFailGoto(HandleArrayElemType(&ParamInfo, thElement, -1, FALSE, isParam, pAssembly), lFail);
2503 m_resID = IDS_EE_BADMARSHAL_SYSARRAY;
2504 IfFailGoto(E_FAIL, lFail);
2509 else if (m_pMT->IsArray())
2511 _ASSERTE(!"This invalid signature should never be hit!");
2512 IfFailGoto(E_FAIL, lFail);
2514 else if ((m_ms == MARSHAL_SCENARIO_WINRT) && sig.IsClassThrowing(pModule, g_TypeClassName, pTypeContext))
2516 m_type = MARSHAL_TYPE_SYSTEMTYPE;
2518 #endif // FEATURE_COMINTEROP
2519 else if (!m_pMT->IsValueType())
2521 #ifdef FEATURE_COMINTEROP
2522 if (IsWinRTScenario() && !m_pMT->IsLegalNonArrayWinRTType())
2524 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2525 IfFailGoto(E_FAIL, lFail);
2527 #endif // FEATURE_COMINTEROP
2529 if (!(nativeType == NATIVE_TYPE_INTF || nativeType == NATIVE_TYPE_DEFAULT))
2531 m_resID = IDS_EE_BADMARSHAL_NOLAYOUT;
2532 IfFailGoto(E_FAIL, lFail);
2534 #ifdef FEATURE_COMINTEROP
2535 // default marshalling is interface
2536 m_type = MARSHAL_TYPE_INTERFACE;
2537 #else // FEATURE_COMINTEROP
2538 m_resID = IDS_EE_OBJECT_TO_ITF_NOT_SUPPORTED;
2539 IfFailGoto(E_FAIL, lFail);
2540 #endif // FEATURE_COMINTEROP
2545 _ASSERTE(m_pMT->IsValueType());
2553 case ELEMENT_TYPE_VALUETYPE:
2556 if (sig.IsClassThrowing(pModule, g_DecimalClassName, pTypeContext))
2560 case NATIVE_TYPE_DEFAULT:
2561 case NATIVE_TYPE_STRUCT:
2562 m_type = MARSHAL_TYPE_DECIMAL;
2565 case NATIVE_TYPE_LPSTRUCT:
2566 m_type = MARSHAL_TYPE_DECIMAL_PTR;
2569 case NATIVE_TYPE_CURRENCY:
2570 m_type = MARSHAL_TYPE_CURRENCY;
2574 m_resID = IDS_EE_BADMARSHALPARAM_DECIMAL;
2575 IfFailGoto(E_FAIL, lFail);
2578 else if (sig.IsClassThrowing(pModule, g_GuidClassName, pTypeContext))
2582 case NATIVE_TYPE_DEFAULT:
2583 case NATIVE_TYPE_STRUCT:
2584 m_type = MARSHAL_TYPE_GUID;
2587 case NATIVE_TYPE_LPSTRUCT:
2588 m_type = MARSHAL_TYPE_GUID_PTR;
2592 m_resID = IDS_EE_BADMARSHAL_GUID;
2593 IfFailGoto(E_FAIL, lFail);
2596 #ifdef FEATURE_COMINTEROP
2597 else if (sig.IsClassThrowing(pModule, g_DateTimeOffsetClassName, pTypeContext))
2599 if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_STRUCT))
2601 m_resID = IDS_EE_BADMARSHAL_DATETIMEOFFSET;
2602 IfFailGoto(E_FAIL, lFail);
2604 m_type = MARSHAL_TYPE_DATETIME;
2605 m_pMT = MscorlibBinder::GetClass(CLASS__DATE_TIME_OFFSET);
2607 #endif // FEATURE_COMINTEROP
2608 else if (sig.IsClassThrowing(pModule, g_DateClassName, pTypeContext))
2610 if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_STRUCT))
2612 m_resID = IDS_EE_BADMARSHAL_DATETIME;
2613 IfFailGoto(E_FAIL, lFail);
2615 m_type = MARSHAL_TYPE_DATE;
2617 else if (sig.IsClassThrowing(pModule, "System.Runtime.InteropServices.ArrayWithOffset", pTypeContext))
2619 if (!(nativeType == NATIVE_TYPE_DEFAULT))
2621 IfFailGoto(E_FAIL, lFail);
2623 m_type = MARSHAL_TYPE_ARRAYWITHOFFSET;
2625 else if (sig.IsClassThrowing(pModule, "System.Runtime.InteropServices.HandleRef", pTypeContext))
2627 if (!(nativeType == NATIVE_TYPE_DEFAULT))
2629 IfFailGoto(E_FAIL, lFail);
2631 m_type = MARSHAL_TYPE_HANDLEREF;
2633 else if (sig.IsClassThrowing(pModule, "System.ArgIterator", pTypeContext))
2635 if (!(nativeType == NATIVE_TYPE_DEFAULT))
2637 IfFailGoto(E_FAIL, lFail);
2639 m_type = MARSHAL_TYPE_ARGITERATOR;
2641 #ifdef FEATURE_COMINTEROP
2642 else if (sig.IsClassThrowing(pModule, g_ColorClassName, pTypeContext))
2644 if (!(nativeType == NATIVE_TYPE_DEFAULT))
2646 IfFailGoto(E_FAIL, lFail);
2649 // This is only supported for COM interop.
2650 if (m_ms != MARSHAL_SCENARIO_COMINTEROP)
2652 IfFailGoto(E_FAIL, lFail);
2655 m_type = MARSHAL_TYPE_OLECOLOR;
2657 #endif // FEATURE_COMINTEROP
2658 else if (sig.IsClassThrowing(pModule, g_RuntimeTypeHandleClassName, pTypeContext))
2660 if (nativeType != NATIVE_TYPE_DEFAULT)
2662 IfFailGoto(E_FAIL, lFail);
2665 m_type = MARSHAL_TYPE_RUNTIMETYPEHANDLE;
2667 else if (sig.IsClassThrowing(pModule, g_RuntimeFieldHandleClassName, pTypeContext))
2669 if (nativeType != NATIVE_TYPE_DEFAULT)
2671 IfFailGoto(E_FAIL, lFail);
2674 m_type = MARSHAL_TYPE_RUNTIMEFIELDHANDLE;
2676 else if (sig.IsClassThrowing(pModule, g_RuntimeMethodHandleClassName, pTypeContext))
2678 if (nativeType != NATIVE_TYPE_DEFAULT)
2680 IfFailGoto(E_FAIL, lFail);
2683 m_type = MARSHAL_TYPE_RUNTIMEMETHODHANDLE;
2687 m_pMT = sig.GetTypeHandleThrowing(pModule, pTypeContext).GetMethodTable();
2691 #ifdef FEATURE_COMINTEROP
2692 // Handle Nullable<T> and KeyValuePair<K, V> for WinRT
2693 if (m_ms == MARSHAL_SCENARIO_WINRT)
2695 if (m_pMT->HasSameTypeDefAs(g_pNullableClass))
2697 m_type = MARSHAL_TYPE_NULLABLE;
2698 m_args.m_pMT = m_pMT;
2702 if (m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__KEYVALUEPAIRGENERIC)))
2704 m_type = MARSHAL_TYPE_KEYVALUEPAIR;
2705 m_args.m_pMT = m_pMT;
2709 if (!m_pMT->IsLegalNonArrayWinRTType())
2711 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2712 IfFailGoto(E_FAIL, lFail);
2715 #endif // FEATURE_COMINTEROP
2717 if (m_pMT->HasInstantiation())
2719 m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
2720 IfFailGoto(E_FAIL, lFail);
2723 UINT managedSize = m_pMT->GetAlignedNumInstanceFieldBytes();
2724 UINT nativeSize = m_pMT->GetNativeSize();
2726 if ( nativeSize > 0xfff0 ||
2727 managedSize > 0xfff0)
2729 m_resID = IDS_EE_STRUCTTOOCOMPLEX;
2730 IfFailGoto(E_FAIL, lFail);
2733 if (m_pMT->IsBlittable())
2735 if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_STRUCT))
2737 m_resID = IDS_EE_BADMARSHAL_VALUETYPE;
2738 IfFailGoto(E_FAIL, lFail);
2741 if (m_byref && !isParam)
2743 // Override the prohibition on byref returns so that IJW works
2745 m_type = ((sizeof(void*) == 4) ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8);
2751 #ifdef FEATURE_COMINTEROP
2752 if (m_ms == MARSHAL_SCENARIO_WINRT)
2754 // our WinRT-optimized GetCOMIPFromRCW helpers don't support copy
2755 // constructor stubs so make sure that this marshaler will not be used
2756 m_resID = IDS_EE_BADMARSHAL_WINRT_COPYCTOR;
2757 IfFailGoto(E_FAIL, lFail);
2761 MethodDesc *pCopyCtor;
2763 FindCopyCtor(pModule, m_pMT, &pCopyCtor);
2764 FindDtor(pModule, m_pMT, &pDtor);
2766 m_args.mm.m_pMT = m_pMT;
2767 m_args.mm.m_pCopyCtor = pCopyCtor;
2768 m_args.mm.m_pDtor = pDtor;
2769 m_type = MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR;
2773 // JIT64 is not aware of normalized value types and this optimization
2774 // (returning small value types by value in registers) is already done in JIT64.
2775 if ( !m_byref // Permit register-sized structs as return values
2777 && !onInstanceMethod
2778 && CorIsPrimitiveType(m_pMT->GetInternalCorElementType())
2779 && !IsUnmanagedValueTypeReturnedByRef(nativeSize)
2780 && managedSize <= sizeof(void*)
2781 && nativeSize <= sizeof(void*))
2783 m_type = MARSHAL_TYPE_GENERIC_4;
2784 m_args.m_pMT = m_pMT;
2787 #endif // _TARGET_X86_
2789 m_args.m_pMT = m_pMT;
2790 m_type = MARSHAL_TYPE_BLITTABLEVALUECLASS;
2794 else if (m_pMT->HasLayout())
2796 if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_STRUCT))
2798 m_resID = IDS_EE_BADMARSHAL_VALUETYPE;
2799 IfFailGoto(E_FAIL, lFail);
2802 m_args.m_pMT = m_pMT;
2803 m_type = MARSHAL_TYPE_VALUECLASS;
2809 case ELEMENT_TYPE_SZARRAY:
2810 case ELEMENT_TYPE_ARRAY:
2812 // Get class info from array.
2813 TypeHandle arrayTypeHnd = sig.GetTypeHandleThrowing(pModule, pTypeContext);
2814 _ASSERTE(!arrayTypeHnd.IsNull());
2816 ArrayTypeDesc* asArray = arrayTypeHnd.AsArray();
2817 if (asArray == NULL)
2818 IfFailGoto(E_FAIL, lFail);
2820 TypeHandle thElement = asArray->GetTypeParam();
2822 #ifdef FEATURE_COMINTEROP
2823 if (m_ms != MARSHAL_SCENARIO_WINRT)
2824 #endif // FEATURE_COMINTEROP
2826 if (thElement.HasInstantiation())
2828 m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
2829 IfFailGoto(E_FAIL, lFail);
2833 // Handle retrieving the information for the array type.
2834 IfFailGoto(HandleArrayElemType(&ParamInfo, thElement, asArray->GetRank(), mtype == ELEMENT_TYPE_SZARRAY, isParam, pAssembly), lFail);
2839 m_resID = IDS_EE_BADMARSHAL_BADMANAGED;
2843 #ifdef FEATURE_COMINTEROP
2844 //Field scenario is not blocked here because we don't want to block loading structs that
2845 //have the types which we are blocking, but never pass it to Interop.
2847 if (AppX::IsAppXProcess() && ms != MarshalInfo::MARSHAL_SCENARIO_FIELD)
2849 bool set_error = false;
2852 case MARSHAL_TYPE_ANSIBSTR:
2853 m_resID = IDS_EE_BADMARSHAL_TYPE_ANSIBSTR;
2856 case MARSHAL_TYPE_VBBYVALSTR:
2857 case MARSHAL_TYPE_VBBYVALSTRW:
2858 m_resID = IDS_EE_BADMARSHAL_TYPE_VBBYVALSTR;
2861 case MARSHAL_TYPE_REFERENCECUSTOMMARSHALER:
2862 m_resID = IDS_EE_BADMARSHAL_TYPE_REFERENCECUSTOMMARSHALER;
2865 case MARSHAL_TYPE_ASANYA:
2866 case MARSHAL_TYPE_ASANYW:
2867 m_resID = IDS_EE_BADMARSHAL_TYPE_ASANYA;
2870 case MARSHAL_TYPE_INTERFACE:
2873 m_resID = IDS_EE_BADMARSHAL_TYPE_IDISPATCH;
2880 COMPlusThrow(kPlatformNotSupportedException, m_resID);
2884 if (IsWinRTScenario() && !IsSupportedForWinRT(m_type))
2886 // the marshaler we came up with is not supported in WinRT scenarios
2887 m_type = MARSHAL_TYPE_UNKNOWN;
2888 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2891 #endif // FEATURE_COMINTEROP
2893 if (m_byref && !isParam)
2895 // byref returns don't work: the thing pointed to lives on
2896 // a stack that disappears!
2897 m_type = MARSHAL_TYPE_UNKNOWN;
2901 //---------------------------------------------------------------------
2902 // Now, figure out the IN/OUT status.
2903 // Also set the m_fOleVarArgCandidate here to save perf of invoking Metadata API
2904 //---------------------------------------------------------------------
2905 m_fOleVarArgCandidate = FALSE;
2906 if (m_type != MARSHAL_TYPE_UNKNOWN && IsInOnly(m_type) && !m_byref)
2908 // If we got here, the parameter is something like an "int" where
2909 // [in] is the only semantically valid choice. Since there is no
2910 // possible way to interpret an [out] for such a type, we will ignore
2911 // the metadata and force the bits to "in". We could have defined
2912 // it as an error instead but this is less likely to cause problems
2913 // with metadata autogenerated from typelibs and poorly
2914 // defined C headers.
2922 // Capture and save away "In/Out" bits. If none is present, set both to FALSE (they will be properly defaulted downstream)
2923 if (token == mdParamDefNil)
2928 else if (TypeFromToken(token) != mdtParamDef)
2930 _ASSERTE(TypeFromToken(token) == mdtFieldDef);
2932 // Field setters are always In, the flags are ignored for return values of getters
2938 IMDInternalImport *pInternalImport = pModule->GetMDImport();
2941 LPCSTR szParamName_Ignore;
2943 if (FAILED(pInternalImport->GetParamDefProps(token, &usSequence, &dwAttr, &szParamName_Ignore)))
2950 m_in = IsPdIn(dwAttr) != 0;
2951 m_out = IsPdOut(dwAttr) != 0;
2952 #ifdef FEATURE_COMINTEROP
2953 // set m_fOleVarArgCandidate. The rule is same as the one defined in vm\tlbexp.cpp
2954 if(paramidx == numArgs && // arg is the last arg of the method
2955 !(dwAttr & PARAMFLAG_FOPT) && // arg is not a optional arg
2956 !IsNilToken(token) && // token is not a nil token
2957 (m_type == MARSHAL_TYPE_SAFEARRAY) && // arg is marshaled as SafeArray
2958 (m_arrayElementType == VT_VARIANT)) // the element of the safearray is VARIANT
2960 // check if it has default value
2961 MDDefaultValue defaultValue;
2962 if (SUCCEEDED(pInternalImport->GetDefaultValue(token, &defaultValue)) && defaultValue.m_bType == ELEMENT_TYPE_VOID)
2964 // check if it has params attribute
2965 if (pInternalImport->GetCustomAttributeByName(token, INTEROP_PARAMARRAY_TYPE, 0,0) == S_OK)
2966 m_fOleVarArgCandidate = TRUE;
2973 // If neither IN nor OUT are true, this signals the URT to use the default
2975 if (!m_in && !m_out)
2978 (mtype == ELEMENT_TYPE_CLASS
2979 && !(sig.IsStringType(pModule, pTypeContext))
2980 && sig.IsClass(pModule, g_StringBufferClassName, pTypeContext)))
2997 DumpMarshalInfo(pModule, sig, pTypeContext, token, ms, nlType, nlFlags);
3003 // We got here because of an illegal ELEMENT_TYPE/NATIVE_TYPE combo.
3004 m_type = MARSHAL_TYPE_UNKNOWN;
3005 //_ASSERTE(!"Invalid ELEMENT_TYPE/NATIVE_TYPE combination");
3009 #pragma warning(pop)
3012 VOID MarshalInfo::EmitOrThrowInteropParamException(NDirectStubLinker* psl, BOOL fMngToNative, UINT resID, UINT paramIdx)
3022 #ifdef FEATURE_COMINTEROP
3023 // If this is not forward COM interop, throw the exception right away. We rely on this
3024 // for example in code:ComPreStubWorker when we fire the InvalidMemberDeclaration MDA.
3025 if ((m_ms == MARSHAL_SCENARIO_COMINTEROP || m_ms == MARSHAL_SCENARIO_WINRT) && fMngToNative)
3027 psl->SetInteropParamExceptionInfo(resID, paramIdx);
3030 #endif // FEATURE_COMINTEROP
3032 ThrowInteropParamException(resID, paramIdx);
3036 HRESULT MarshalInfo::HandleArrayElemType(NativeTypeParamInfo *pParamInfo, TypeHandle thElement, int iRank, BOOL fNoLowerBounds, BOOL isParam, Assembly *pAssembly)
3041 PRECONDITION(CheckPointer(pParamInfo));
3045 ArrayMarshalInfo arrayMarshalInfo(amiRuntime);
3049 // Store rank and bound information.
3052 m_iArrayRank = iRank;
3053 m_nolowerbounds = fNoLowerBounds;
3057 // Determine which type of marshaler to use.
3060 #ifdef FEATURE_COMINTEROP
3061 if (m_ms == MARSHAL_SCENARIO_WINRT)
3063 m_type = MARSHAL_TYPE_HIDDENLENGTHARRAY;
3065 else if (pParamInfo->m_NativeType == NATIVE_TYPE_SAFEARRAY)
3067 m_type = MARSHAL_TYPE_SAFEARRAY;
3070 #endif // FEATURE_COMINTEROP
3071 if (pParamInfo->m_NativeType == NATIVE_TYPE_ARRAY)
3073 m_type = MARSHAL_TYPE_NATIVEARRAY;
3075 else if (pParamInfo->m_NativeType == NATIVE_TYPE_DEFAULT)
3077 #ifdef FEATURE_COMINTEROP
3078 if (m_ms != MARSHAL_SCENARIO_NDIRECT)
3080 m_type = MARSHAL_TYPE_SAFEARRAY;
3083 #endif // FEATURE_COMINTEROP
3085 m_type = MARSHAL_TYPE_NATIVEARRAY;
3090 m_resID = IDS_EE_BADMARSHAL_ARRAY;
3094 #ifdef FEATURE_COMINTEROP
3095 if (m_type == MARSHAL_TYPE_SAFEARRAY)
3097 arrayMarshalInfo.InitForSafeArray(m_ms, thElement, pParamInfo->m_SafeArrayElementVT, m_fAnsi);
3099 else if (m_type == MARSHAL_TYPE_HIDDENLENGTHARRAY)
3101 arrayMarshalInfo.InitForHiddenLengthArray(thElement);
3104 #endif // FEATURE_COMINTEROP
3106 _ASSERTE(m_type == MARSHAL_TYPE_NATIVEARRAY);
3107 arrayMarshalInfo.InitForNativeArray(m_ms, thElement, pParamInfo->m_ArrayElementType, m_fAnsi);
3110 // Make sure the marshalling information is valid.
3111 if (!arrayMarshalInfo.IsValid())
3113 m_resID = arrayMarshalInfo.GetErrorResourceId();
3117 // Set the array type handle and VARTYPE to use for marshalling.
3118 m_hndArrayElemType = arrayMarshalInfo.GetElementTypeHandle();
3119 m_arrayElementType = arrayMarshalInfo.GetElementVT();
3121 if (m_type == MARSHAL_TYPE_NATIVEARRAY)
3123 // Retrieve the extra information associated with the native array marshaling.
3124 m_args.na.m_vt = m_arrayElementType;
3125 m_countParamIdx = pParamInfo->m_CountParamIdx;
3126 m_multiplier = pParamInfo->m_Multiplier;
3127 m_additive = pParamInfo->m_Additive;
3129 #ifdef FEATURE_COMINTEROP
3130 else if (m_type == MARSHAL_TYPE_HIDDENLENGTHARRAY)
3132 m_args.na.m_vt = m_arrayElementType;
3133 m_args.na.m_cbElementSize = arrayMarshalInfo.GetElementSize();
3134 m_args.na.m_redirectedTypeIndex = arrayMarshalInfo.GetRedirectedTypeIndex();
3136 #endif // FEATURE_COMINTEROP
3141 ILMarshaler* CreateILMarshaler(MarshalInfo::MarshalType mtype, NDirectStubLinker* psl)
3150 ILMarshaler* pMarshaler = NULL;
3154 #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) \
3155 case MarshalInfo::mt: \
3156 pMarshaler = new IL##mclass(); \
3159 #undef DEFINE_MARSHALER_TYPE
3162 UNREACHABLE_MSG("unexpected MarshalType passed to CreateILMarshaler");
3165 pMarshaler->SetNDirectStubLinker(psl);
3171 DWORD CalculateArgumentMarshalFlags(BOOL byref, BOOL in, BOOL out, BOOL fMngToNative)
3173 LIMITED_METHOD_CONTRACT;
3174 DWORD dwMarshalFlags = 0;
3178 dwMarshalFlags |= MARSHAL_FLAG_BYREF;
3183 dwMarshalFlags |= MARSHAL_FLAG_IN;
3188 dwMarshalFlags |= MARSHAL_FLAG_OUT;
3193 dwMarshalFlags |= MARSHAL_FLAG_CLR_TO_NATIVE;
3196 return dwMarshalFlags;
3199 DWORD CalculateReturnMarshalFlags(BOOL hrSwap, BOOL fMngToNative)
3201 LIMITED_METHOD_CONTRACT;
3202 DWORD dwMarshalFlags = MARSHAL_FLAG_RETVAL;
3206 dwMarshalFlags |= MARSHAL_FLAG_HRESULT_SWAP;
3211 dwMarshalFlags |= MARSHAL_FLAG_CLR_TO_NATIVE;
3214 return dwMarshalFlags;
3217 void MarshalInfo::GenerateArgumentIL(NDirectStubLinker* psl,
3218 int argOffset, // the argument's index is m_paramidx + argOffset
3219 UINT nativeStackOffset, // offset of the argument on the native stack
3225 PRECONDITION(CheckPointer(psl));
3229 if (m_type == MARSHAL_TYPE_UNKNOWN)
3231 EmitOrThrowInteropParamException(psl, fMngToNative, m_resID, m_paramidx + 1); // m_paramidx is 0-based, but the user wants to see a 1-based index
3235 // set up m_corArgSize and m_nativeArgSize
3236 SetupArgumentSizes();
3238 MarshalerOverrideStatus amostat;
3239 UINT resID = IDS_EE_BADMARSHAL_RESTRICTION;
3240 amostat = (GetArgumentOverrideProc(m_type)) (psl,
3247 m_paramidx + argOffset,
3251 if (amostat == OVERRIDDEN)
3256 if (amostat == DISALLOWED)
3258 EmitOrThrowInteropParamException(psl, fMngToNative, resID, m_paramidx + 1); // m_paramidx is 0-based, but the user wants to see a 1-based index
3262 CONSISTENCY_CHECK(amostat == HANDLEASNORMAL);
3264 NewHolder<ILMarshaler> pMarshaler = CreateILMarshaler(m_type, psl);
3265 DWORD dwMarshalFlags = CalculateArgumentMarshalFlags(m_byref, m_in, m_out, fMngToNative);
3267 if (!pMarshaler->SupportsArgumentMarshal(dwMarshalFlags, &resID))
3269 EmitOrThrowInteropParamException(psl, fMngToNative, resID, m_paramidx + 1); // m_paramidx is 0-based, but the user wants to see a 1-based index
3273 ILCodeStream* pcsMarshal = psl->GetMarshalCodeStream();
3274 ILCodeStream* pcsUnmarshal = psl->GetUnmarshalCodeStream();
3275 ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream();
3277 pcsMarshal->EmitNOP("// argument { ");
3278 pcsUnmarshal->EmitNOP("// argument { ");
3280 pMarshaler->EmitMarshalArgument(pcsMarshal, pcsUnmarshal, m_paramidx + argOffset, dwMarshalFlags, &m_args);
3283 // Increment a counter so that when the finally clause
3284 // is run, we only run the cleanup that is needed.
3286 if (pMarshaler->NeedsMarshalCleanupIndex())
3288 // we don't bother writing to the counter if marshaling does not need cleanup
3289 psl->EmitSetArgMarshalIndex(pcsMarshal, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_paramidx + argOffset);
3291 if (pMarshaler->NeedsUnmarshalCleanupIndex())
3293 // we don't bother writing to the counter if unmarshaling does not need exception cleanup
3294 psl->EmitSetArgMarshalIndex(pcsUnmarshal, NDirectStubLinker::CLEANUP_INDEX_ARG0_UNMARSHAL + m_paramidx + argOffset);
3297 pcsMarshal->EmitNOP("// } argument");
3298 pcsUnmarshal->EmitNOP("// } argument");
3300 pMarshaler->EmitSetupArgument(pcsDispatch);
3301 if (m_paramidx == 0)
3303 CorCallingConvention callConv = psl->GetStubTargetCallingConv();
3304 if ((callConv & IMAGE_CEE_CS_CALLCONV_MASK) == IMAGE_CEE_UNMANAGED_CALLCONV_THISCALL)
3306 // Make sure the 'this' argument to thiscall is of native int type; JIT asserts this.
3307 pcsDispatch->EmitCONV_I();
3312 void MarshalInfo::GenerateReturnIL(NDirectStubLinker* psl,
3321 PRECONDITION(CheckPointer(psl));
3325 MarshalerOverrideStatus amostat;
3326 UINT resID = IDS_EE_BADMARSHAL_RESTRICTION;
3328 if (m_type == MARSHAL_TYPE_UNKNOWN)
3330 amostat = HANDLEASNORMAL;
3334 amostat = (GetReturnOverrideProc(m_type)) (psl,
3341 if (amostat == DISALLOWED)
3343 EmitOrThrowInteropParamException(psl, fMngToNative, resID, 0);
3347 if (amostat == HANDLEASNORMAL)
3349 // Historically we have always allowed reading fields that are marshaled as C arrays.
3350 if (m_type == MARSHAL_TYPE_UNKNOWN || (!fieldGetter && m_type == MARSHAL_TYPE_NATIVEARRAY))
3352 EmitOrThrowInteropParamException(psl, fMngToNative, m_resID, 0);
3356 NewHolder<ILMarshaler> pMarshaler = CreateILMarshaler(m_type, psl);
3357 DWORD dwMarshalFlags = CalculateReturnMarshalFlags(retval, fMngToNative);
3359 if (!pMarshaler->SupportsReturnMarshal(dwMarshalFlags, &resID))
3361 EmitOrThrowInteropParamException(psl, fMngToNative, resID, 0);
3365 ILCodeStream* pcsMarshal = psl->GetMarshalCodeStream();
3366 ILCodeStream* pcsUnmarshal = psl->GetReturnUnmarshalCodeStream();
3367 ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream();
3369 pcsMarshal->EmitNOP("// return { ");
3370 pcsUnmarshal->EmitNOP("// return { ");
3372 UINT16 wNativeSize = GetNativeSize(m_type, m_ms);
3374 // The following statement behaviour has existed for a long time. By aligning the size of the return
3375 // value up to stack slot size, we prevent EmitMarshalReturnValue from distinguishing between, say, 3-byte
3376 // structure and 4-byte structure. The former is supposed to be returned by-ref using a secret argument
3377 // (at least in MSVC compiled code) while the latter is returned in EAX. We are keeping the behavior for
3378 // now for backward compatibility.
3379 X86_ONLY(wNativeSize = StackElemSize(wNativeSize));
3381 pMarshaler->EmitMarshalReturnValue(pcsMarshal, pcsUnmarshal, pcsDispatch, m_paramidx + argOffset, wNativeSize, dwMarshalFlags, &m_args);
3383 pcsMarshal->EmitNOP("// } return");
3384 pcsUnmarshal->EmitNOP("// } return");
3390 void MarshalInfo::SetupArgumentSizes()
3402 m_managedArgSize = StackElemSize(sizeof(void*));
3403 m_nativeArgSize = StackElemSize(sizeof(void*));
3407 m_managedArgSize = StackElemSize(GetManagedSize(m_type, m_ms));
3408 m_nativeArgSize = StackElemSize(GetNativeSize(m_type, m_ms));
3411 #ifdef ENREGISTERED_PARAMTYPE_MAXSIZE
3412 if (m_managedArgSize > ENREGISTERED_PARAMTYPE_MAXSIZE)
3413 m_managedArgSize = StackElemSize(sizeof(void*));
3415 if (m_nativeArgSize > ENREGISTERED_PARAMTYPE_MAXSIZE)
3416 m_nativeArgSize = StackElemSize(sizeof(void*));
3417 #endif // ENREGISTERED_PARAMTYPE_MAXSIZE
3420 UINT16 MarshalInfo::GetManagedSize(MarshalType mtype, MarshalScenario ms)
3430 static const BYTE managedSizes[]=
3432 #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::c_CLRSize,
3436 _ASSERTE((SIZE_T)mtype < COUNTOF(managedSizes));
3437 BYTE managedSize = managedSizes[mtype];
3439 if (managedSize == VARIABLESIZE)
3444 case MARSHAL_TYPE_BLITTABLEVALUECLASS:
3445 case MARSHAL_TYPE_VALUECLASS:
3446 #ifdef FEATURE_COMINTEROP
3447 case MARSHAL_TYPE_DATETIME:
3448 case MARSHAL_TYPE_NULLABLE:
3449 case MARSHAL_TYPE_KEYVALUEPAIR:
3450 #endif // FEATURE_COMINTEROP
3451 return (UINT16) m_pMT->GetAlignedNumInstanceFieldBytes();
3462 UINT16 MarshalInfo::GetNativeSize(MarshalType mtype, MarshalScenario ms)
3472 static const BYTE nativeSizes[]=
3474 #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::c_nativeSize,
3478 _ASSERTE((SIZE_T)mtype < COUNTOF(nativeSizes));
3479 BYTE nativeSize = nativeSizes[mtype];
3481 if (nativeSize == VARIABLESIZE)
3485 case MARSHAL_TYPE_BLITTABLEVALUECLASS:
3486 case MARSHAL_TYPE_VALUECLASS:
3487 case MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR:
3488 return (UINT16) m_pMT->GetNativeSize();
3498 bool MarshalInfo::IsInOnly(MarshalType mtype)
3508 static const bool ILMarshalerIsInOnly[] =
3510 #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) \
3511 (IL##mclass::c_fInOnly ? true : false),
3516 return ILMarshalerIsInOnly[mtype];
3519 bool MarshalInfo::IsSupportedForWinRT(MarshalType mtype)
3529 static const bool MarshalerSupportsWinRT[] =
3531 #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) \
3537 return MarshalerSupportsWinRT[mtype];
3540 OVERRIDEPROC MarshalInfo::GetArgumentOverrideProc(MarshalType mtype)
3550 static const OVERRIDEPROC ILArgumentOverrideProcs[] =
3552 #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::ArgumentOverride,
3556 _ASSERTE((SIZE_T)mtype < COUNTOF(ILArgumentOverrideProcs));
3557 return ILArgumentOverrideProcs[mtype];
3560 RETURNOVERRIDEPROC MarshalInfo::GetReturnOverrideProc(MarshalType mtype)
3570 static const RETURNOVERRIDEPROC ILReturnOverrideProcs[] =
3572 #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::ReturnOverride,
3576 _ASSERTE((SIZE_T)mtype < COUNTOF(ILReturnOverrideProcs));
3577 return ILReturnOverrideProcs[mtype];
3580 void MarshalInfo::GetItfMarshalInfo(ItfMarshalInfo* pInfo)
3582 STANDARD_VM_CONTRACT;
3584 GetItfMarshalInfo(TypeHandle(m_pMT),
3585 #ifdef FEATURE_COMINTEROP
3586 TypeHandle(m_pDefaultItfMT),
3587 #else // FEATURE_COMINTEROP
3589 #endif // FEATURE_COMINTEROP
3596 void MarshalInfo::GetItfMarshalInfo(TypeHandle th, TypeHandle thItf, BOOL fDispItf, BOOL fInspItf, MarshalScenario ms, ItfMarshalInfo *pInfo)
3603 PRECONDITION(CheckPointer(pInfo));
3604 PRECONDITION(!th.IsNull());
3605 PRECONDITION(!th.IsTypeDesc());
3609 #ifdef FEATURE_COMINTEROP
3611 // Initialize the output parameter.
3613 pInfo->thItf = TypeHandle();
3614 pInfo->thClass = TypeHandle();
3616 if (!th.IsInterface())
3618 // If the parameter is not System.Object.
3619 if (!th.IsObjectType())
3621 // Set the class method table.
3622 pInfo->thClass = th;
3624 if (th.IsTypeDesc() || !th.AsMethodTable()->IsWinRTDelegate())
3626 // If this is not a WinRT delegate, retrieve the default interface method table.
3627 TypeHandle hndDefItfClass;
3628 DefaultInterfaceType DefItfType;
3630 if (!thItf.IsNull())
3632 hndDefItfClass = thItf;
3633 DefItfType = DefaultInterfaceType_Explicit;
3635 else if (th.IsProjectedFromWinRT() || th.IsExportedToWinRT())
3637 // WinRT classes use their WinRT default interface
3638 hndDefItfClass = th.GetMethodTable()->GetDefaultWinRTInterface();
3639 DefItfType = DefaultInterfaceType_Explicit;
3643 DefItfType = GetDefaultInterfaceForClassWrapper(th, &hndDefItfClass);
3647 case DefaultInterfaceType_Explicit:
3649 pInfo->thItf = hndDefItfClass;
3650 switch (hndDefItfClass.GetComInterfaceType())
3654 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3658 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3664 case DefaultInterfaceType_AutoDual:
3666 pInfo->thItf = hndDefItfClass;
3667 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3671 case DefaultInterfaceType_IUnknown:
3672 case DefaultInterfaceType_BaseComClass:
3677 case DefaultInterfaceType_AutoDispatch:
3679 pInfo->thItf = hndDefItfClass;
3680 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3686 _ASSERTE(!"Invalid default interface type!");
3694 // The type will be marshalled as an IUnknown, IInspectable, or IDispatch pointer depending
3695 // on the value of fDispItf and fInspItf
3698 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3702 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3705 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_USE_BASIC_ITF;
3710 // IInspectable-based interfaces are simple
3712 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3716 // Determine the interface this type will be marshalled as.
3717 if (th.IsComClassInterface())
3718 pInfo->thItf = th.GetDefItfForComClassItf();
3722 // Determine if we are dealing with an IDispatch, IInspectable, or IUnknown based interface.
3723 switch (pInfo->thItf.GetComInterfaceType())
3727 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3731 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3735 // Look to see if the interface has a coclass defined
3736 pInfo->thClass = th.GetCoClassForInterface();
3737 if (!pInfo->thClass.IsNull())
3739 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_CLASS_IS_HINT;
3743 // store the pre-redirection interface type as thNativeItf
3744 pInfo->thNativeItf = pInfo->thItf;
3746 if (ms == MARSHAL_SCENARIO_WINRT)
3748 // Use the "class is hint" flag so GetObjectRefFromComIP doesn't verify that the
3749 // WinRT object really supports IInspectable - note that we'll do the verification
3750 // in UnmarshalObjectFromInterface for this exact pInfo->thItf.
3751 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_CLASS_IS_HINT;
3753 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_WINRT_SCENARIO;
3755 // Perform interface redirection statically here. When the resulting ItfMarshalInfo
3756 // is used for CLR->WinRT marshaling, this is necessary so we know which COM vtable
3757 // to pass out (for instance IList could be marshaled out as IList or IBindableVector
3758 // depending on the marshal scenario). In the WinRT->CLR direction, it's just an
3759 // optimization which saves us from performing redirection at run-time.
3761 if (!pInfo->thItf.IsNull())
3763 MethodTable *pNewItfMT1;
3764 MethodTable *pNewItfMT2;
3765 switch (RCW::GetInterfacesForQI(pInfo->thItf.GetMethodTable(), &pNewItfMT1, &pNewItfMT2))
3767 case RCW::InterfaceRedirection_None:
3768 case RCW::InterfaceRedirection_UnresolvedIEnumerable:
3771 case RCW::InterfaceRedirection_IEnumerable_RetryOnFailure:
3772 case RCW::InterfaceRedirection_IEnumerable:
3773 case RCW::InterfaceRedirection_Other:
3774 pInfo->thNativeItf = pNewItfMT1;
3777 case RCW::InterfaceRedirection_Other_RetryOnFailure:
3778 pInfo->thNativeItf = pNewItfMT2;
3783 if (!pInfo->thNativeItf.IsNull())
3785 // The native interface is redirected WinRT interface - need to change the flags
3786 _ASSERTE(pInfo->thNativeItf.AsMethodTable()->IsProjectedFromWinRT());
3788 pInfo->dwFlags &= ~ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3789 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3793 #else // FEATURE_COMINTEROP
3794 if (!th.IsInterface())
3795 pInfo->thClass = th;
3798 #endif // FEATURE_COMINTEROP
3801 HRESULT MarshalInfo::TryGetItfMarshalInfo(TypeHandle th, BOOL fDispItf, BOOL fInspItf, ItfMarshalInfo *pInfo)
3806 PRECONDITION(!th.IsNull());
3807 PRECONDITION(CheckPointer(pInfo));
3815 GetItfMarshalInfo(th, TypeHandle(), fDispItf, fInspItf,
3816 #ifdef FEATURE_COMINTEROP
3817 MARSHAL_SCENARIO_COMINTEROP,
3818 #else // FEATURE_COMINTEROP
3819 MARSHAL_SCENARIO_NDIRECT,
3820 #endif // FEATURE_COMINTEROP
3825 hr = GET_EXCEPTION()->GetHR();
3827 EX_END_CATCH(RethrowTerminalExceptions);
3833 VOID MarshalInfo::DumpMarshalInfo(Module* pModule, SigPointer sig, const SigTypeContext *pTypeContext, mdToken token,
3834 MarshalScenario ms, CorNativeLinkType nlType, CorNativeLinkFlags nlFlags)
3844 if (LoggingOn(LF_MARSHALER, LL_INFO10))
3847 StackScratchBuffer scratch;
3849 IMDInternalImport *pInternalImport = pModule->GetMDImport();
3851 logbuf.AppendASCII("------------------------------------------------------------\n");
3852 LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch)));
3855 logbuf.AppendASCII("Managed type: ");
3857 logbuf.AppendASCII("Byref ");
3859 TypeHandle th = sig.GetTypeHandleNT(pModule, pTypeContext);
3861 logbuf.AppendASCII("<error>");
3866 logbuf.AppendUTF8(sigfmt.GetCString());
3869 logbuf.AppendASCII("\n");
3870 LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch)));
3873 logbuf.AppendASCII("NativeType : ");
3874 PCCOR_SIGNATURE pvNativeType;
3876 if (token == mdParamDefNil
3877 || pInternalImport->GetFieldMarshal(token,
3879 &cbNativeType) != S_OK)
3881 logbuf.AppendASCII("<absent>");
3886 while (cbNativeType--)
3889 sprintf_s(num, COUNTOF(num), "0x%lx ", (ULONG)*pvNativeType);
3890 logbuf.AppendASCII(num);
3891 switch (*(pvNativeType++))
3893 #define XXXXX(nt) case nt: logbuf.AppendASCII("(" #nt ")"); break;
3895 XXXXX(NATIVE_TYPE_BOOLEAN)
3896 XXXXX(NATIVE_TYPE_I1)
3898 XXXXX(NATIVE_TYPE_U1)
3899 XXXXX(NATIVE_TYPE_I2)
3900 XXXXX(NATIVE_TYPE_U2)
3901 XXXXX(NATIVE_TYPE_I4)
3903 XXXXX(NATIVE_TYPE_U4)
3904 XXXXX(NATIVE_TYPE_I8)
3905 XXXXX(NATIVE_TYPE_U8)
3906 XXXXX(NATIVE_TYPE_R4)
3908 XXXXX(NATIVE_TYPE_R8)
3910 XXXXX(NATIVE_TYPE_LPSTR)
3911 XXXXX(NATIVE_TYPE_LPWSTR)
3912 XXXXX(NATIVE_TYPE_LPTSTR)
3913 XXXXX(NATIVE_TYPE_FIXEDSYSSTRING)
3915 XXXXX(NATIVE_TYPE_STRUCT)
3917 XXXXX(NATIVE_TYPE_INT)
3918 XXXXX(NATIVE_TYPE_FIXEDARRAY)
3920 XXXXX(NATIVE_TYPE_UINT)
3922 XXXXX(NATIVE_TYPE_FUNC)
3924 XXXXX(NATIVE_TYPE_ASANY)
3926 XXXXX(NATIVE_TYPE_ARRAY)
3927 XXXXX(NATIVE_TYPE_LPSTRUCT)
3929 XXXXX(NATIVE_TYPE_IUNKNOWN)
3931 XXXXX(NATIVE_TYPE_BSTR)
3932 #ifdef FEATURE_COMINTEROP
3933 XXXXX(NATIVE_TYPE_TBSTR)
3934 XXXXX(NATIVE_TYPE_ANSIBSTR)
3935 XXXXX(NATIVE_TYPE_HSTRING)
3936 XXXXX(NATIVE_TYPE_BYVALSTR)
3938 XXXXX(NATIVE_TYPE_VARIANTBOOL)
3939 XXXXX(NATIVE_TYPE_SAFEARRAY)
3941 XXXXX(NATIVE_TYPE_IDISPATCH)
3942 XXXXX(NATIVE_TYPE_INTF)
3943 #endif // FEATURE_COMINTEROP
3948 case NATIVE_TYPE_CUSTOMMARSHALER:
3951 logbuf.AppendASCII("(NATIVE_TYPE_CUSTOMMARSHALER)");
3953 // Skip the typelib guid.
3954 logbuf.AppendASCII(" ");
3956 strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType);
3959 BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen);
3960 memcpyNoGCRefs(p, pvNativeType, strLen);
3961 logbuf.CloseBuffer();
3962 logbuf.AppendASCII("\0");
3964 pvNativeType += strLen;
3965 cbNativeType -= strLen + 1;
3967 // Skip the name of the native type.
3968 logbuf.AppendASCII(" ");
3972 strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType);
3975 BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen);
3976 memcpyNoGCRefs(p, pvNativeType, strLen);
3977 logbuf.CloseBuffer();
3978 logbuf.AppendASCII("\0");
3980 pvNativeType += strLen;
3981 cbNativeType -= strLen + 1;
3983 // Extract the name of the custom marshaler.
3984 logbuf.AppendASCII(" ");
3988 strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType);
3991 BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen);
3992 memcpyNoGCRefs(p, pvNativeType, strLen);
3993 logbuf.CloseBuffer();
3994 logbuf.AppendASCII("\0");
3996 pvNativeType += strLen;
3997 cbNativeType -= strLen + 1;
3999 // Extract the cookie string.
4000 logbuf.AppendASCII(" ");
4003 strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType);
4006 BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen);
4007 memcpyNoGCRefs(p, pvNativeType, strLen);
4008 logbuf.CloseBuffer();
4009 logbuf.AppendASCII("\0");
4011 pvNativeType += strLen;
4012 cbNativeType -= strLen + 1;
4019 logbuf.AppendASCII("(?)");
4022 logbuf.AppendASCII(" ");
4025 logbuf.AppendASCII("\n");
4026 LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch)));
4029 logbuf.AppendASCII("MarshalType : ");
4032 sprintf_s(num, COUNTOF(num), "0x%lx ", (ULONG)m_type);
4033 logbuf.AppendASCII(num);
4037 #define DEFINE_MARSHALER_TYPE(mt, mc, fWinRTSupported) case mt: logbuf.AppendASCII( #mt " (IL" #mc ")"); break;
4040 case MARSHAL_TYPE_UNKNOWN:
4041 logbuf.AppendASCII("MARSHAL_TYPE_UNKNOWN (illegal combination)");
4045 logbuf.AppendASCII("MARSHAL_TYPE_???");
4049 logbuf.AppendASCII("\n");
4052 logbuf.AppendASCII("Metadata In/Out : ");
4053 if (TypeFromToken(token) != mdtParamDef || token == mdParamDefNil)
4054 logbuf.AppendASCII("<absent>");
4060 LPCSTR szParamName_Ignore;
4061 if (FAILED(pInternalImport->GetParamDefProps(token, &usSequence, &dwAttr, &szParamName_Ignore)))
4063 logbuf.AppendASCII("Invalid ParamDef record ");
4068 logbuf.AppendASCII("In ");
4070 if (IsPdOut(dwAttr))
4071 logbuf.AppendASCII("Out ");
4075 logbuf.AppendASCII("\n");
4077 logbuf.AppendASCII("Effective In/Out : ");
4079 logbuf.AppendASCII("In ");
4082 logbuf.AppendASCII("Out ");
4084 logbuf.AppendASCII("\n");
4086 LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch)));
4089 } // MarshalInfo::DumpMarshalInfo
4092 #ifndef CROSSGEN_COMPILE
4093 #ifdef FEATURE_COMINTEROP
4094 DispParamMarshaler *MarshalInfo::GenerateDispParamMarshaler()
4096 CONTRACT (DispParamMarshaler*)
4101 INJECT_FAULT(COMPlusThrowOM());
4102 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
4106 NewHolder<DispParamMarshaler> pDispParamMarshaler = NULL;
4110 case MARSHAL_TYPE_OLECOLOR:
4111 pDispParamMarshaler = new DispParamOleColorMarshaler();
4114 case MARSHAL_TYPE_CURRENCY:
4115 pDispParamMarshaler = new DispParamCurrencyMarshaler();
4118 case MARSHAL_TYPE_GENERIC_4:
4119 if (m_fErrorNativeType)
4120 pDispParamMarshaler = new DispParamErrorMarshaler();
4123 case MARSHAL_TYPE_INTERFACE:
4125 ItfMarshalInfo itfInfo;
4126 GetItfMarshalInfo(TypeHandle(m_pMT), TypeHandle(m_pDefaultItfMT), m_fDispItf, m_fInspItf, m_ms, &itfInfo);
4127 pDispParamMarshaler = new DispParamInterfaceMarshaler(
4128 itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF,
4129 itfInfo.thItf.GetMethodTable(),
4130 itfInfo.thClass.GetMethodTable(),
4131 itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_CLASS_IS_HINT);
4135 case MARSHAL_TYPE_VALUECLASS:
4136 case MARSHAL_TYPE_BLITTABLEVALUECLASS:
4137 case MARSHAL_TYPE_BLITTABLEPTR:
4138 case MARSHAL_TYPE_LAYOUTCLASSPTR:
4139 case MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR:
4140 pDispParamMarshaler = new DispParamRecordMarshaler(m_pMT);
4143 #ifdef FEATURE_CLASSIC_COMINTEROP
4144 case MARSHAL_TYPE_SAFEARRAY:
4145 pDispParamMarshaler = new DispParamArrayMarshaler(m_arrayElementType, m_hndArrayElemType.GetMethodTable());
4149 case MARSHAL_TYPE_DELEGATE:
4150 pDispParamMarshaler = new DispParamDelegateMarshaler(m_pMT);
4153 case MARSHAL_TYPE_REFERENCECUSTOMMARSHALER:
4154 pDispParamMarshaler = new DispParamCustomMarshaler(m_pCMHelper, m_CMVt);
4158 pDispParamMarshaler.SuppressRelease();
4159 RETURN pDispParamMarshaler;
4163 DispatchWrapperType MarshalInfo::GetDispWrapperType()
4165 STANDARD_VM_CONTRACT;
4167 DispatchWrapperType WrapperType = (DispatchWrapperType)0;
4171 case MARSHAL_TYPE_CURRENCY:
4172 WrapperType = DispatchWrapperType_Currency;
4175 case MARSHAL_TYPE_BSTR:
4176 WrapperType = DispatchWrapperType_BStr;
4179 case MARSHAL_TYPE_GENERIC_4:
4180 if (m_fErrorNativeType)
4181 WrapperType = DispatchWrapperType_Error;
4184 case MARSHAL_TYPE_INTERFACE:
4186 ItfMarshalInfo itfInfo;
4187 GetItfMarshalInfo(TypeHandle(m_pMT), TypeHandle(m_pDefaultItfMT), m_fDispItf, m_fInspItf, m_ms, &itfInfo);
4188 WrapperType = !!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF) ? DispatchWrapperType_Dispatch : DispatchWrapperType_Unknown;
4192 case MARSHAL_TYPE_SAFEARRAY:
4193 switch (m_arrayElementType)
4196 WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_Currency);
4199 WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_Unknown);
4202 WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_Dispatch);
4205 WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_Error);
4208 WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_BStr);
4217 #endif // FEATURE_COMINTEROP
4220 VOID MarshalInfo::MarshalTypeToString(SString& strMarshalType, BOOL fSizeIsSpecified)
4232 if (m_type == MARSHAL_TYPE_NATIVEARRAY)
4235 VarTypeToString(m_arrayElementType, strVarType);
4237 if (!fSizeIsSpecified)
4239 strMarshalType.Printf(W("native array of %s (size not specified by a parameter)"),
4240 strVarType.GetUnicode());
4244 strMarshalType.Printf(W("native array of %s (size specified by parameter %i)"),
4245 strVarType.GetUnicode(), m_countParamIdx);
4250 #ifdef FEATURE_COMINTEROP
4251 // Some MarshalTypes have extra information and require special handling
4252 else if (m_type == MARSHAL_TYPE_INTERFACE)
4254 ItfMarshalInfo itfInfo;
4255 GetItfMarshalInfo(TypeHandle(m_pMT), TypeHandle(m_pDefaultItfMT), m_fDispItf, m_fInspItf, m_ms, &itfInfo);
4257 if (!itfInfo.thItf.IsNull())
4259 StackSString ssClassName;
4260 itfInfo.thItf.GetMethodTable()->_GetFullyQualifiedNameForClass(ssClassName);
4262 if (!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF))
4264 strMarshalType.SetLiteral(W("IDispatch "));
4266 else if (!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_INSP_ITF))
4268 strMarshalType.SetLiteral(W("IInspectable"));
4272 strMarshalType.SetLiteral(W("IUnknown "));
4275 if (itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_USE_BASIC_ITF)
4277 strMarshalType.Append(W("(basic) "));
4280 strMarshalType.Append(ssClassName);
4285 if (!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF))
4286 strRetVal = W("IDispatch");
4287 else if (!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_INSP_ITF))
4288 strRetVal = W("IInspectable");
4290 strRetVal = W("IUnknown");
4293 else if (m_type == MARSHAL_TYPE_SAFEARRAY)
4295 StackSString strVarType;
4296 VarTypeToString(m_arrayElementType, strVarType);
4298 strMarshalType = SL(W("SafeArray of "));
4299 strMarshalType.Append(strVarType);
4303 #endif // FEATURE_COMINTEROP
4304 else if (m_type == MARSHAL_TYPE_REFERENCECUSTOMMARSHALER)
4308 OBJECTHANDLE objHandle = m_pCMHelper->GetCustomMarshalerInfo()->GetCustomMarshaler();
4310 OBJECTREF pObjRef = ObjectFromHandle(objHandle);
4311 DefineFullyQualifiedNameForClassW();
4313 strMarshalType.Printf(W("custom marshaler (%s)"),
4314 GetFullyQualifiedNameForClassW(pObjRef->GetMethodTable()));
4321 // All other MarshalTypes with no special handling
4324 case MARSHAL_TYPE_GENERIC_1:
4325 strRetVal = W("BYTE");
4327 case MARSHAL_TYPE_GENERIC_U1:
4328 strRetVal = W("unsigned BYTE");
4330 case MARSHAL_TYPE_GENERIC_2:
4331 strRetVal = W("WORD");
4333 case MARSHAL_TYPE_GENERIC_U2:
4334 strRetVal = W("unsigned WORD");
4336 case MARSHAL_TYPE_GENERIC_4:
4337 strRetVal = W("DWORD");
4339 case MARSHAL_TYPE_GENERIC_8:
4340 strRetVal = W("QUADWORD");
4342 case MARSHAL_TYPE_WINBOOL:
4343 strRetVal = W("Windows Bool");
4345 #ifdef FEATURE_COMINTEROP
4346 case MARSHAL_TYPE_VTBOOL:
4347 strRetVal = W("VARIANT Bool");
4349 #endif // FEATURE_COMINTEROP
4350 case MARSHAL_TYPE_ANSICHAR:
4351 strRetVal = W("Ansi character");
4353 case MARSHAL_TYPE_CBOOL:
4354 strRetVal = W("CBool");
4356 case MARSHAL_TYPE_FLOAT:
4357 strRetVal = W("float");
4359 case MARSHAL_TYPE_DOUBLE:
4360 strRetVal = W("double");
4362 case MARSHAL_TYPE_CURRENCY:
4363 strRetVal = W("CURRENCY");
4365 case MARSHAL_TYPE_DECIMAL:
4366 strRetVal = W("DECIMAL");
4368 case MARSHAL_TYPE_DECIMAL_PTR:
4369 strRetVal = W("DECIMAL pointer");
4371 case MARSHAL_TYPE_GUID:
4372 strRetVal = W("GUID");
4374 case MARSHAL_TYPE_GUID_PTR:
4375 strRetVal = W("GUID pointer");
4377 case MARSHAL_TYPE_DATE:
4378 strRetVal = W("DATE");
4380 case MARSHAL_TYPE_BSTR:
4381 strRetVal = W("BSTR");
4383 case MARSHAL_TYPE_LPWSTR:
4384 strRetVal = W("LPWSTR");
4386 case MARSHAL_TYPE_LPSTR:
4387 strRetVal = W("LPSTR");
4389 case MARSHAL_TYPE_LPUTF8STR:
4390 strRetVal = W("LPUTF8STR");
4392 #ifdef FEATURE_COMINTEROP
4393 case MARSHAL_TYPE_ANSIBSTR:
4394 strRetVal = W("AnsiBStr");
4396 #endif // FEATURE_COMINTEROP
4397 case MARSHAL_TYPE_LPWSTR_BUFFER:
4398 strRetVal = W("LPWSTR buffer");
4400 case MARSHAL_TYPE_LPSTR_BUFFER:
4401 strRetVal = W("LPSTR buffer");
4403 case MARSHAL_TYPE_UTF8_BUFFER:
4404 strRetVal = W("UTF8 buffer");
4406 case MARSHAL_TYPE_ASANYA:
4407 strRetVal = W("AsAnyA");
4409 case MARSHAL_TYPE_ASANYW:
4410 strRetVal = W("AsAnyW");
4412 case MARSHAL_TYPE_DELEGATE:
4413 strRetVal = W("Delegate");
4415 case MARSHAL_TYPE_BLITTABLEPTR:
4416 strRetVal = W("blittable pointer");
4418 #ifdef FEATURE_COMINTEROP
4419 case MARSHAL_TYPE_VBBYVALSTR:
4420 strRetVal = W("VBByValStr");
4422 case MARSHAL_TYPE_VBBYVALSTRW:
4423 strRetVal = W("VBByRefStr");
4425 #endif // FEATURE_COMINTEROP
4426 case MARSHAL_TYPE_LAYOUTCLASSPTR:
4427 strRetVal = W("Layout class pointer");
4429 case MARSHAL_TYPE_ARRAYWITHOFFSET:
4430 strRetVal = W("ArrayWithOffset");
4432 case MARSHAL_TYPE_BLITTABLEVALUECLASS:
4433 strRetVal = W("blittable value class");
4435 case MARSHAL_TYPE_VALUECLASS:
4436 strRetVal = W("value class");
4438 case MARSHAL_TYPE_ARGITERATOR:
4439 strRetVal = W("ArgIterator");
4441 case MARSHAL_TYPE_BLITTABLEVALUECLASSWITHCOPYCTOR:
4442 strRetVal = W("blittable value class with copy constructor");
4444 #ifdef FEATURE_COMINTEROP
4445 case MARSHAL_TYPE_OBJECT:
4446 strRetVal = W("VARIANT");
4448 #endif // FEATURE_COMINTEROP
4449 case MARSHAL_TYPE_HANDLEREF:
4450 strRetVal = W("HandleRef");
4452 #ifdef FEATURE_COMINTEROP
4453 case MARSHAL_TYPE_OLECOLOR:
4454 strRetVal = W("OLE_COLOR");
4456 #endif // FEATURE_COMINTEROP
4457 case MARSHAL_TYPE_RUNTIMETYPEHANDLE:
4458 strRetVal = W("RuntimeTypeHandle");
4460 case MARSHAL_TYPE_RUNTIMEFIELDHANDLE:
4461 strRetVal = W("RuntimeFieldHandle");
4463 case MARSHAL_TYPE_RUNTIMEMETHODHANDLE:
4464 strRetVal = W("RuntimeMethodHandle");
4466 case MARSHAL_TYPE_RUNTIMEMETHODINFO:
4467 strRetVal = W("RuntimeMethodInfo");
4469 case MARSHAL_TYPE_RUNTIMEMODULE:
4470 strRetVal = W("RuntimeModule");
4472 case MARSHAL_TYPE_RUNTIMEASSEMBLY:
4473 strRetVal = W("RuntimeAssembly");
4476 strRetVal = W("<UNKNOWN>");
4481 strMarshalType.Set(strRetVal);
4485 VOID MarshalInfo::VarTypeToString(VARTYPE vt, SString& strVarType)
4501 strRetVal = W("2-byte signed int");
4504 strRetVal = W("4-byte signed int");
4507 strRetVal = W("4-byte real");
4510 strRetVal = W("8-byte real");
4513 strRetVal = W("currency");
4516 strRetVal = W("date");
4519 strRetVal = W("binary string");
4522 strRetVal = W("IDispatch *");
4525 strRetVal = W("Scode");
4528 strRetVal = W("boolean");
4531 strRetVal = W("VARIANT *");
4534 strRetVal = W("IUnknown *");
4537 strRetVal = W("16-byte fixed point");
4540 strRetVal = W("user defined structure");
4543 strRetVal = W("signed char");
4546 strRetVal = W("unsigned char");
4549 strRetVal = W("unsigned short");
4552 strRetVal = W("unsigned short");
4555 strRetVal = W("signed int");
4558 strRetVal = W("unsigned int");
4561 strRetVal = W("LPSTR");
4564 strRetVal = W("LPWSTR");
4567 strRetVal = W("HResult");
4570 strRetVal = W("8-byte signed int");
4573 strRetVal = W("null");
4576 strRetVal = W("8-byte unsigned int");
4579 strRetVal = W("void");
4581 case VTHACK_WINBOOL:
4582 strRetVal = W("boolean");
4584 case VTHACK_ANSICHAR:
4585 strRetVal = W("char");
4588 strRetVal = W("1-byte C bool");
4591 strRetVal = W("unknown");
4595 strVarType.Set(strRetVal);
4599 #endif // CROSSGEN_COMPILE
4601 // Returns true if the marshaler represented by this instance requires COM to have been started.
4602 bool MarshalInfo::MarshalerRequiresCOM()
4604 LIMITED_METHOD_CONTRACT;
4606 #ifdef FEATURE_COMINTEROP
4609 case MARSHAL_TYPE_REFERENCECUSTOMMARSHALER:
4611 case MARSHAL_TYPE_BSTR:
4612 case MARSHAL_TYPE_ANSIBSTR:
4613 case MARSHAL_TYPE_OBJECT:
4614 case MARSHAL_TYPE_OLECOLOR:
4615 case MARSHAL_TYPE_SAFEARRAY:
4616 case MARSHAL_TYPE_INTERFACE:
4618 case MARSHAL_TYPE_URI:
4619 case MARSHAL_TYPE_KEYVALUEPAIR:
4620 case MARSHAL_TYPE_NULLABLE:
4621 case MARSHAL_TYPE_SYSTEMTYPE:
4622 case MARSHAL_TYPE_EXCEPTION:
4623 case MARSHAL_TYPE_HIDDENLENGTHARRAY:
4624 case MARSHAL_TYPE_HSTRING:
4625 case MARSHAL_TYPE_NCCEVENTARGS:
4626 case MARSHAL_TYPE_PCEVENTARGS:
4628 // some of these types do not strictly require COM for the actual marshaling
4629 // but they tend to be used in COM context so we keep the logic we had in
4630 // previous versions and return true here
4634 case MARSHAL_TYPE_LAYOUTCLASSPTR:
4635 case MARSHAL_TYPE_VALUECLASS:
4637 // pessimistic guess, but in line with previous versions
4641 case MARSHAL_TYPE_NATIVEARRAY:
4643 return (m_arrayElementType == VT_UNKNOWN ||
4644 m_arrayElementType == VT_DISPATCH ||
4645 m_arrayElementType == VT_VARIANT);
4648 #endif // FEATURE_COMINTEROP
4653 #ifdef FEATURE_COMINTEROP
4654 MarshalInfo::MarshalType MarshalInfo::GetHiddenLengthParamMarshalType()
4656 LIMITED_METHOD_CONTRACT;
4657 return MARSHAL_TYPE_GENERIC_U4;
4660 CorElementType MarshalInfo::GetHiddenLengthParamElementType()
4662 LIMITED_METHOD_CONTRACT;
4663 return ELEMENT_TYPE_U4;
4666 UINT16 MarshalInfo::GetHiddenLengthParamStackSize()
4668 LIMITED_METHOD_CONTRACT;
4669 return StackElemSize(GetNativeSize(GetHiddenLengthParamMarshalType(), m_ms));
4672 void MarshalInfo::MarshalHiddenLengthArgument(NDirectStubLinker *psl, BOOL managedToNative, BOOL isForReturnArray)
4677 PRECONDITION(CheckPointer(psl));
4678 PRECONDITION(m_type == MARSHAL_TYPE_HIDDENLENGTHARRAY);
4679 PRECONDITION(m_dwHiddenLengthManagedHomeLocal == 0xFFFFFFFF);
4680 PRECONDITION(m_dwHiddenLengthNativeHomeLocal == 0xFFFFFFFF);
4684 NewHolder<ILMarshaler> pHiddenLengthMarshaler = CreateILMarshaler(GetHiddenLengthParamMarshalType(), psl);
4687 ILCodeStream *pcsMarshal = psl->GetMarshalCodeStream();
4688 ILCodeStream *pcsUnmarshal = psl->GetUnmarshalCodeStream();
4690 pcsMarshal->EmitNOP("// hidden length argument { ");
4691 pcsUnmarshal->EmitNOP("// hidden length argument { ");
4693 DWORD dwMarshalFlags = MARSHAL_FLAG_HIDDENLENPARAM;
4694 if (isForReturnArray)
4696 // This is a hidden length argument for an [out, retval] argument, so setup flags to match that
4697 dwMarshalFlags |= CalculateArgumentMarshalFlags(TRUE, FALSE, TRUE, managedToNative);
4701 // The length parameter needs to be an [in] parameter if the array itself is an [in] parameter.
4702 // Additionally, in order to support the FillArray pattern:
4703 // FillArray([in] UInt32 length, [out, size_is(length)] ElementType* value)
4705 // We need to make sure that the length parameter is [in] if the array pointer is not byref, since
4706 // this means that the caller is allocating the array. This includes array buffers which are [out]
4707 // but not byref, since the [out] marshaling applies to the array contents but not the array pointer
4709 BOOL marshalHiddenLengthIn = m_in || !m_byref;
4710 dwMarshalFlags |= CalculateArgumentMarshalFlags(m_byref, marshalHiddenLengthIn, m_out, managedToNative);
4712 pHiddenLengthMarshaler->EmitMarshalHiddenLengthArgument(pcsMarshal,
4717 HiddenLengthParamIndex(),
4719 &m_dwHiddenLengthManagedHomeLocal,
4720 &m_dwHiddenLengthNativeHomeLocal);
4722 pcsMarshal->EmitNOP("// } hidden length argument");
4723 pcsUnmarshal->EmitNOP("// } hidden length argument");
4725 // Only emit into the dispatch stream for CLR -> Native cases - in the reverse, there is no argument
4726 // to pass to the managed method. Instead, the length is encoded in the marshaled array.
4727 if (managedToNative)
4729 ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream();
4730 pHiddenLengthMarshaler->EmitSetupArgument(pcsDispatch);
4734 #endif // FEATURE_COMINTEROP
4736 #define ReportInvalidArrayMarshalInfo(resId) \
4739 m_vtElement = VT_EMPTY; \
4740 m_errorResourceId = resId; \
4741 m_thElement = TypeHandle(); \
4746 void ArrayMarshalInfo::InitForNativeArray(MarshalInfo::MarshalScenario ms, TypeHandle thElement, CorNativeType ntElement, BOOL isAnsi)
4748 WRAPPER_NO_CONTRACT;
4749 InitElementInfo(NATIVE_TYPE_ARRAY, ms, thElement, ntElement, isAnsi);
4752 void ArrayMarshalInfo::InitForFixedArray(TypeHandle thElement, CorNativeType ntElement, BOOL isAnsi)
4754 WRAPPER_NO_CONTRACT;
4755 InitElementInfo(NATIVE_TYPE_FIXEDARRAY, MarshalInfo::MARSHAL_SCENARIO_FIELD, thElement, ntElement, isAnsi);
4758 #ifdef FEATURE_COMINTEROP
4759 void ArrayMarshalInfo::InitForSafeArray(MarshalInfo::MarshalScenario ms, TypeHandle thElement, VARTYPE vtElement, BOOL isAnsi)
4761 STANDARD_VM_CONTRACT;
4763 InitElementInfo(NATIVE_TYPE_SAFEARRAY, ms, thElement, NATIVE_TYPE_DEFAULT, isAnsi);
4765 if (IsValid() && vtElement != VT_EMPTY)
4767 if (vtElement == VT_USERDEFINED)
4769 // If the user explicitly sets the VARTYPE to VT_USERDEFINED, we simply ignore it
4770 // since the exporter will take care of transforming the vt to VT_USERDEFINED and the
4771 // marshallers needs the actual type.
4775 m_flags = (ArrayMarshalInfoFlags)(m_flags | amiSafeArraySubTypeExplicitlySpecified);
4776 m_vtElement = vtElement;
4781 void ArrayMarshalInfo::InitForHiddenLengthArray(TypeHandle thElement)
4783 STANDARD_VM_CONTRACT;
4785 MethodTable *pMT = NULL;
4787 // WinRT supports arrays of any WinRT-legal types
4788 if (thElement.IsArray())
4790 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_NESTEDARRAY);
4792 else if (thElement.IsTypeDesc() || !thElement.GetMethodTable()->IsLegalNonArrayWinRTType())
4794 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE);
4797 m_thElement = thElement;
4799 pMT = thElement.GetMethodTable();
4800 if (pMT->IsString())
4802 m_vtElement = VTHACK_HSTRING;
4803 m_cbElementSize = sizeof(HSTRING);
4805 else if (WinRTTypeNameConverter::ResolveRedirectedType(pMT, &m_redirectedTypeIndex))
4807 m_vtElement = VTHACK_REDIRECTEDTYPE;
4809 switch (m_redirectedTypeIndex)
4811 case WinMDAdapter::RedirectedTypeIndex_System_DateTimeOffset:
4812 m_cbElementSize = ILDateTimeMarshaler::c_nativeSize;
4815 case WinMDAdapter::RedirectedTypeIndex_System_Type:
4816 m_cbElementSize = ILSystemTypeMarshaler::c_nativeSize;
4819 case WinMDAdapter::RedirectedTypeIndex_System_Exception:
4820 m_cbElementSize = ILHResultExceptionMarshaler::c_nativeSize;
4823 // WinRT delegates are IUnknown pointers
4824 case WinMDAdapter::RedirectedTypeIndex_System_EventHandlerGeneric:
4825 m_vtElement = VTHACK_INSPECTABLE;
4826 m_cbElementSize = sizeof(IUnknown*);
4829 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
4830 case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
4831 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
4832 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
4833 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
4835 m_cbElementSize = sizeof(IInspectable *);
4841 if (pMT->IsValueType())
4843 // other redirected structs are blittable and don't need special marshaling
4844 m_vtElement = VTHACK_BLITTABLERECORD;
4845 m_cbElementSize = pMT->GetNativeSize();
4849 // redirected interfaces should be treated as interface pointers
4850 _ASSERTE(pMT->IsInterface());
4851 m_vtElement = VTHACK_INSPECTABLE;
4852 m_cbElementSize = sizeof(IInspectable *);
4858 else if (pMT->IsBlittable() || pMT->IsTruePrimitive() || pMT->IsEnum())
4860 m_vtElement = VTHACK_BLITTABLERECORD;
4862 CorElementType elemType = pMT->GetInternalCorElementType();
4863 if (CorTypeInfo::IsPrimitiveType(elemType))
4865 // .NET and WinRT primitives have the same size
4866 m_cbElementSize = CorTypeInfo::Size(elemType);
4870 m_cbElementSize = pMT->GetNativeSize();
4873 else if (pMT->IsValueType())
4875 m_vtElement = VTHACK_NONBLITTABLERECORD;
4876 m_cbElementSize = pMT->GetNativeSize();
4880 m_vtElement = VTHACK_INSPECTABLE;
4881 m_cbElementSize = sizeof(IInspectable *);
4886 #endif // FEATURE_COMINTEROP
4888 void ArrayMarshalInfo::InitElementInfo(CorNativeType arrayNativeType, MarshalInfo::MarshalScenario ms, TypeHandle thElement, CorNativeType ntElement, BOOL isAnsi)
4893 PRECONDITION(!thElement.IsNull());
4894 POSTCONDITION(!IsValid() || !m_thElement.IsNull());
4898 CorElementType etElement = ELEMENT_TYPE_END;
4901 // IMPORTANT: The error resource IDs used in this function must not contain any placeholders!
4903 // Also please maintain the standard of using IDS_EE_BADMARSHAL_XXX when defining new error
4904 // message resource IDs.
4907 if (thElement.IsArray())
4908 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_NESTEDARRAY);
4910 m_thElement = thElement;
4912 if (m_thElement.IsPointer())
4914 m_flags = (ArrayMarshalInfoFlags)(m_flags | amiIsPtr);
4915 m_thElement = ((ParamTypeDesc*)m_thElement.AsTypeDesc())->GetModifiedType();
4918 etElement = m_thElement.GetSignatureCorElementType();
4920 if (IsAMIPtr(m_flags) && (etElement > ELEMENT_TYPE_R8))
4922 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_UNSUPPORTED_SIG);
4925 if (etElement == ELEMENT_TYPE_CHAR)
4929 case NATIVE_TYPE_I1: //fallthru
4930 case NATIVE_TYPE_U1:
4931 m_vtElement = VTHACK_ANSICHAR;
4934 case NATIVE_TYPE_I2: //fallthru
4935 case NATIVE_TYPE_U2:
4936 m_vtElement = VT_UI2;
4939 // Compat: If the native type doesn't make sense, we need to ignore it and not report an error.
4940 case NATIVE_TYPE_DEFAULT: //fallthru
4942 #ifdef FEATURE_COMINTEROP
4943 if (ms == MarshalInfo::MARSHAL_SCENARIO_COMINTEROP)
4944 m_vtElement = VT_UI2;
4946 #endif // FEATURE_COMINTEROP
4947 m_vtElement = isAnsi ? VTHACK_ANSICHAR : VT_UI2;
4950 else if (etElement == ELEMENT_TYPE_BOOLEAN)
4954 case NATIVE_TYPE_BOOLEAN:
4955 m_vtElement = VTHACK_WINBOOL;
4958 #ifdef FEATURE_COMINTEROP
4959 case NATIVE_TYPE_VARIANTBOOL:
4960 m_vtElement = VT_BOOL;
4962 #endif // FEATURE_COMINTEROP
4964 case NATIVE_TYPE_I1 :
4965 case NATIVE_TYPE_U1 :
4966 m_vtElement = VTHACK_CBOOL;
4969 // Compat: if the native type doesn't make sense, we need to ignore it and not report an error.
4970 case NATIVE_TYPE_DEFAULT: //fallthru
4972 #ifdef FEATURE_COMINTEROP
4973 if (ms == MarshalInfo::MARSHAL_SCENARIO_COMINTEROP ||
4974 arrayNativeType == NATIVE_TYPE_SAFEARRAY)
4976 m_vtElement = VT_BOOL;
4979 #endif // FEATURE_COMINTEROP
4981 m_vtElement = VTHACK_WINBOOL;
4986 else if (etElement == ELEMENT_TYPE_I)
4988 m_vtElement = static_cast<VARTYPE>((GetPointerSize() == 4) ? VT_I4 : VT_I8);
4990 else if (etElement == ELEMENT_TYPE_U)
4992 m_vtElement = static_cast<VARTYPE>((GetPointerSize() == 4) ? VT_UI4 : VT_UI8);
4994 else if (etElement <= ELEMENT_TYPE_R8)
4996 static const BYTE map [] =
4998 VT_NULL, // ELEMENT_TYPE_END
4999 VT_VOID, // ELEMENT_TYPE_VOID
5000 VT_NULL, // ELEMENT_TYPE_BOOLEAN
5001 VT_NULL, // ELEMENT_TYPE_CHAR
5002 VT_I1, // ELEMENT_TYPE_I1
5003 VT_UI1, // ELEMENT_TYPE_U1
5004 VT_I2, // ELEMENT_TYPE_I2
5005 VT_UI2, // ELEMENT_TYPE_U2
5006 VT_I4, // ELEMENT_TYPE_I4
5007 VT_UI4, // ELEMENT_TYPE_U4
5008 VT_I8, // ELEMENT_TYPE_I8
5009 VT_UI8, // ELEMENT_TYPE_U8
5010 VT_R4, // ELEMENT_TYPE_R4
5011 VT_R8 // ELEMENT_TYPE_R8
5015 _ASSERTE(map[etElement] != VT_NULL);
5016 m_vtElement = map[etElement];
5020 if (m_thElement == TypeHandle(g_pStringClass))
5024 case NATIVE_TYPE_DEFAULT:
5025 #ifdef FEATURE_COMINTEROP
5026 if (arrayNativeType == NATIVE_TYPE_SAFEARRAY || ms == MarshalInfo::MARSHAL_SCENARIO_COMINTEROP)
5028 m_vtElement = VT_BSTR;
5031 #endif // FEATURE_COMINTEROP
5033 m_vtElement = static_cast<VARTYPE>(isAnsi ? VT_LPSTR : VT_LPWSTR);
5036 case NATIVE_TYPE_BSTR:
5037 m_vtElement = VT_BSTR;
5039 case NATIVE_TYPE_LPSTR:
5040 m_vtElement = VT_LPSTR;
5042 case NATIVE_TYPE_LPWSTR:
5043 m_vtElement = VT_LPWSTR;
5045 case NATIVE_TYPE_LPTSTR:
5047 #ifdef FEATURE_COMINTEROP
5048 if (ms == MarshalInfo::MARSHAL_SCENARIO_COMINTEROP || IsAMIExport(m_flags))
5050 // We disallow NATIVE_TYPE_LPTSTR for COM or if we are exporting.
5051 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHALPARAM_NO_LPTSTR);
5054 #endif // FEATURE_COMINTEROP
5056 // We no longer support Win9x so LPTSTR always maps to a Unicode string.
5057 m_vtElement = VT_LPWSTR;
5063 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_STRINGARRAY);
5066 else if (m_thElement == TypeHandle(g_pObjectClass))
5068 #ifdef FEATURE_COMINTEROP
5071 case NATIVE_TYPE_DEFAULT:
5072 if (ms == MarshalInfo::MARSHAL_SCENARIO_FIELD)
5073 m_vtElement = VT_UNKNOWN;
5075 m_vtElement = VT_VARIANT;
5078 case NATIVE_TYPE_STRUCT:
5079 m_vtElement = VT_VARIANT;
5082 case NATIVE_TYPE_INTF:
5083 case NATIVE_TYPE_IUNKNOWN:
5084 m_vtElement = VT_UNKNOWN;
5087 case NATIVE_TYPE_IDISPATCH:
5088 m_vtElement = VT_DISPATCH;
5092 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_OBJECTARRAY);
5095 #else // FEATURE_COMINTEROP
5098 case NATIVE_TYPE_IUNKNOWN:
5099 m_vtElement = VT_UNKNOWN;
5103 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_UNSUPPORTED_SIG);
5105 #endif // FEATURE_COMINTEROP
5107 else if (m_thElement.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE))))
5109 // Array's of SAFEHANDLEs are not supported.
5110 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_SAFEHANDLEARRAY);
5112 else if (m_thElement.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__CRITICAL_HANDLE))))
5114 // Array's of CRITICALHANDLEs are not supported.
5115 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_CRITICALHANDLEARRAY);
5117 else if (etElement == ELEMENT_TYPE_VALUETYPE)
5119 if (m_thElement == TypeHandle(MscorlibBinder::GetClass(CLASS__DATE_TIME)))
5121 if (ntElement == NATIVE_TYPE_STRUCT || ntElement == NATIVE_TYPE_DEFAULT)
5122 m_vtElement = VT_DATE;
5124 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_DATETIMEARRAY);
5126 else if (m_thElement == TypeHandle(MscorlibBinder::GetClass(CLASS__DECIMAL)))
5128 if (ntElement == NATIVE_TYPE_STRUCT || ntElement == NATIVE_TYPE_DEFAULT)
5129 m_vtElement = VT_DECIMAL;
5130 #ifdef FEATURE_COMINTEROP
5131 else if (ntElement == NATIVE_TYPE_CURRENCY)
5132 m_vtElement = VT_CY;
5133 #endif // FEATURE_COMINTEROP
5135 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_DECIMALARRAY);
5139 // When exporting, we need to handle enums specially.
5140 if (IsAMIExport(m_flags) && m_thElement.IsEnum())
5142 // Get the element type of the underlying type.
5143 CorElementType et = m_thElement.GetInternalCorElementType();
5145 // If it is not a 32-bit type, convert as the underlying type.
5146 if ((et == ELEMENT_TYPE_I4) || (et == ELEMENT_TYPE_U4))
5147 m_vtElement = VT_RECORD;
5149 m_vtElement = OleVariant::GetVarTypeForTypeHandle(m_thElement);
5153 m_vtElement = OleVariant::GetVarTypeForTypeHandle(m_thElement);
5157 #ifdef FEATURE_COMINTEROP
5158 else if (m_thElement == TypeHandle(MscorlibBinder::GetClass(CLASS__ERROR_WRAPPER)))
5160 m_vtElement = VT_ERROR;
5165 #ifdef FEATURE_COMINTEROP
5167 // Compat: Even if the classes have layout, we still convert them to interface pointers.
5169 ItfMarshalInfo itfInfo;
5170 MarshalInfo::GetItfMarshalInfo(m_thElement, TypeHandle(), FALSE, FALSE, ms, &itfInfo);
5172 // Compat: We must always do VT_UNKNOWN marshaling for parameters, even if the interface is marked late-bound.
5173 if (ms == MarshalInfo::MARSHAL_SCENARIO_FIELD)
5174 m_vtElement = static_cast<VARTYPE>(!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF) ? VT_DISPATCH : VT_UNKNOWN);
5176 m_vtElement = VT_UNKNOWN;
5178 m_thElement = itfInfo.thItf.IsNull() ? TypeHandle(g_pObjectClass) : itfInfo.thItf;
5179 m_thInterfaceArrayElementClass = itfInfo.thClass;
5181 #else // FEATURE_COMINTEROP
5182 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_UNSUPPORTED_SIG);
5183 #endif // FEATURE_COMINTEROP
5187 // Avoid throwing exceptions for any managed structs that have layouts and have types of fields that gets default to those banned types by default
5188 // We don't know if they will be passed to native code anyway, and the right place to make the check is in the marshallers
5189 if (AppX::IsAppXProcess() && ms != MarshalInfo::MARSHAL_SCENARIO_FIELD)
5191 bool set_error = false;
5193 switch (m_vtElement)
5196 m_resID = IDS_EE_BADMARSHAL_TYPE_IDISPATCH ;
5201 COMPlusThrow(kPlatformNotSupportedException, m_resID);
5204 // If we are exporting, we need to substitute the VTHACK_* VARTYPE with the actual
5205 // types as expressed in the type library.
5206 if (IsAMIExport(m_flags))
5208 if (m_vtElement == VTHACK_ANSICHAR)
5209 m_vtElement = VT_UI1;
5210 else if (m_vtElement == VTHACK_WINBOOL)
5211 m_vtElement = VT_I4;
5212 else if (m_vtElement == VTHACK_CBOOL)
5213 m_vtElement = VT_UI1;
5221 bool IsUnsupportedTypedrefReturn(MetaSig& msig)
5223 WRAPPER_NO_CONTRACT;
5225 return msig.GetReturnTypeNormalized() == ELEMENT_TYPE_TYPEDBYREF;
5228 #ifndef CROSSGEN_COMPILE
5230 #include "stubhelpers.h"
5231 FCIMPL3(void*, StubHelpers::CreateCustomMarshalerHelper,
5234 TypeHandle hndManagedType)
5238 CustomMarshalerHelper* pCMHelper = NULL;
5240 HELPER_METHOD_FRAME_BEGIN_RET_0();
5242 Module* pModule = pMD->GetModule();
5243 Assembly* pAssembly = pModule->GetAssembly();
5246 #ifdef FEATURE_COMINTEROP
5247 if (!hndManagedType.IsTypeDesc() &&
5248 IsTypeRefOrDef(g_CollectionsEnumeratorClassName, hndManagedType.GetModule(), hndManagedType.GetCl()))
5250 pCMHelper = SetupCustomMarshalerHelper(ENUMERATOR_TO_ENUM_VARIANT_CM_NAME,
5251 ENUMERATOR_TO_ENUM_VARIANT_CM_NAME_LEN,
5252 ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE,
5253 ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE_LEN,
5254 pAssembly, hndManagedType);
5257 #endif // FEATURE_COMINTEROP
5260 // Retrieve the native type for the current parameter.
5264 NativeTypeParamInfo ParamInfo;
5265 result = ParseNativeTypeInfo(paramToken, pModule->GetMDImport(), &ParamInfo);
5268 // this should all have been done at stub creation time
5270 CONSISTENCY_CHECK(result != 0);
5271 CONSISTENCY_CHECK(ParamInfo.m_NativeType == NATIVE_TYPE_CUSTOMMARSHALER);
5273 // Set up the custom marshaler info.
5274 pCMHelper = SetupCustomMarshalerHelper(ParamInfo.m_strCMMarshalerTypeName,
5275 ParamInfo.m_cCMMarshalerTypeNameBytes,
5276 ParamInfo.m_strCMCookie,
5277 ParamInfo.m_cCMCookieStrBytes,
5282 HELPER_METHOD_FRAME_END();
5284 return (void*)pCMHelper;
5288 #endif // CROSSGEN_COMPILE