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 = GetThread()->GetDomain()->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(BaseDomain *pDomain, LoaderHeap *pHeap, CrstBase *pCrst) :
1087 LockOwner lock = {pCrst, IsOwnerOfCrst};
1088 #ifndef CROSSGEN_COMPILE
1089 m_CMHelperHashtable.Init(INITIAL_NUM_CMHELPER_HASHTABLE_BUCKETS, &lock);
1090 m_SharedCMHelperToCMInfoMap.Init(INITIAL_NUM_CMINFO_HASHTABLE_BUCKETS, &lock);
1091 #endif // CROSSGEN_COMPILE
1095 EEMarshalingData::~EEMarshalingData()
1097 WRAPPER_NO_CONTRACT;
1099 CustomMarshalerInfo *pCMInfo;
1101 // <TODO>@TODO(DM): Remove the linked list of CMInfo's and instead hang the OBJECTHANDLE
1102 // contained inside the CMInfo off the AppDomain directly. The AppDomain can have
1103 // a list of tasks to do when it gets teared down and we could leverage that
1104 // to release the object handles.</TODO>
1106 // Walk through the linked list and delete all the custom marshaler info's.
1107 while ((pCMInfo = m_pCMInfoList.RemoveHead()) != NULL)
1110 #ifdef FEATURE_COMINTEROP
1111 if (m_pOleColorInfo)
1113 delete m_pOleColorInfo;
1114 m_pOleColorInfo = NULL;
1123 if (m_pEventArgsInfo)
1125 delete m_pEventArgsInfo;
1126 m_pEventArgsInfo = NULL;
1132 void *EEMarshalingData::operator new(size_t size, LoaderHeap *pHeap)
1139 INJECT_FAULT(COMPlusThrowOM());
1140 PRECONDITION(CheckPointer(pHeap));
1141 POSTCONDITION(CheckPointer(RETVAL));
1145 void* mem = pHeap->AllocMem(S_SIZE_T(sizeof(EEMarshalingData)));
1151 void EEMarshalingData::operator delete(void *pMem)
1153 LIMITED_METHOD_CONTRACT;
1154 // Instances of this class are always allocated on the loader heap so
1155 // the delete operator has nothing to do.
1158 #ifndef CROSSGEN_COMPILE
1160 CustomMarshalerHelper *EEMarshalingData::GetCustomMarshalerHelper(Assembly *pAssembly, TypeHandle hndManagedType, LPCUTF8 strMarshalerTypeName, DWORD cMarshalerTypeNameBytes, LPCUTF8 strCookie, DWORD cCookieStrBytes)
1162 CONTRACT (CustomMarshalerHelper*)
1167 INJECT_FAULT(COMPlusThrowOM());
1168 PRECONDITION(CheckPointer(pAssembly));
1169 POSTCONDITION(CheckPointer(RETVAL));
1173 CustomMarshalerHelper *pCMHelper = NULL;
1174 CustomMarshalerHelper* pNewCMHelper = NULL;
1175 NewHolder<CustomMarshalerInfo> pNewCMInfo(NULL);
1177 TypeHandle hndCustomMarshalerType;
1179 // Create the key that will be used to lookup in the hashtable.
1180 EECMHelperHashtableKey Key(cMarshalerTypeNameBytes, strMarshalerTypeName, cCookieStrBytes, strCookie, hndManagedType.GetInstantiation());
1182 // Lookup the custom marshaler helper in the hashtable.
1183 if (m_CMHelperHashtable.GetValue(&Key, (HashDatum*)&pCMHelper))
1189 // Validate the arguments.
1190 _ASSERTE(strMarshalerTypeName && strCookie && !hndManagedType.IsNull());
1192 // Append a NULL terminator to the marshaler type name.
1193 SString strCMMarshalerTypeName(SString::Utf8, strMarshalerTypeName, cMarshalerTypeNameBytes);
1195 // Load the custom marshaler class.
1196 BOOL fNameIsAsmQualified = FALSE;
1197 hndCustomMarshalerType = TypeName::GetTypeUsingCASearchRules(strCMMarshalerTypeName.GetUTF8NoConvert(), pAssembly, &fNameIsAsmQualified);
1199 if (hndCustomMarshalerType.IsGenericTypeDefinition())
1201 // Instantiate generic custom marshalers using the instantiation of the type being marshaled.
1202 hndCustomMarshalerType = hndCustomMarshalerType.Instantiate(hndManagedType.GetInstantiation());
1205 // Set the assembly to null to indicate that the custom marshaler name is assembly
1207 if (fNameIsAsmQualified)
1211 // Create the custom marshaler info in the specified heap.
1212 pNewCMInfo = new (m_pHeap) CustomMarshalerInfo(m_pDomain, hndCustomMarshalerType, hndManagedType, strCookie, cCookieStrBytes);
1214 // Create the custom marshaler helper in the specified heap.
1215 pNewCMHelper = new (m_pHeap) NonSharedCustomMarshalerHelper(pNewCMInfo);
1218 // Take the app domain lock before we insert the custom marshaler info into the hashtable.
1220 BaseDomain::LockHolder lh(m_pDomain);
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_pDomain,
1281 hndCustomMarshalerType,
1282 pSharedCMHelper->GetManagedType(),
1283 pSharedCMHelper->GetCookieString(),
1284 pSharedCMHelper->GetCookieStringByteCount());
1287 // Take the app domain lock before we insert the custom marshaler info into the hashtable.
1288 BaseDomain::LockHolder lh(m_pDomain);
1290 // Verify that the custom marshaler info has not already been added by another thread.
1291 if (m_SharedCMHelperToCMInfoMap.GetValue(pSharedCMHelper, (HashDatum*)&pCMInfo))
1296 // Add the custom marshaler helper to the hash table.
1297 m_SharedCMHelperToCMInfoMap.InsertValue(pSharedCMHelper, pNewCMInfo, FALSE);
1299 // Add the custom marshaler into the linked list.
1300 m_pCMInfoList.InsertHead(pNewCMInfo);
1302 // Release the lock and return the custom marshaler info.
1305 pNewCMInfo.SuppressRelease();
1308 #endif // CROSSGEN_COMPILE
1310 #ifdef FEATURE_COMINTEROP
1311 UriMarshalingInfo *EEMarshalingData::GetUriMarshalingInfo()
1313 CONTRACT (UriMarshalingInfo*)
1318 INJECT_FAULT(COMPlusThrowOM());
1319 POSTCONDITION(CheckPointer(RETVAL));
1323 if (m_pUriInfo == NULL)
1325 UriMarshalingInfo *pUriInfo = new (m_pHeap) UriMarshalingInfo();
1327 if (InterlockedCompareExchangeT(&m_pUriInfo, pUriInfo, NULL) != NULL)
1329 // Another thread beat us to it. Delete on UriMarshalingInfo is an empty operation
1330 // which is OK, since the possible leak is rare, small, and constant. This is the same
1331 // pattern as in code:GetCustomMarshalerInfo.
1339 EventArgsMarshalingInfo *EEMarshalingData::GetEventArgsMarshalingInfo()
1341 CONTRACT (EventArgsMarshalingInfo*)
1346 INJECT_FAULT(COMPlusThrowOM());
1347 POSTCONDITION(CheckPointer(RETVAL));
1351 if (m_pEventArgsInfo == NULL)
1353 EventArgsMarshalingInfo *pEventArgsInfo = new (m_pHeap) EventArgsMarshalingInfo();
1355 if (InterlockedCompareExchangeT(&m_pEventArgsInfo, pEventArgsInfo, NULL) != NULL)
1357 // Another thread beat us to it. Delete on EventArgsMarshalingInfo is an empty operation
1358 // which is OK, since the possible leak is rare, small, and constant. This is the same
1359 // pattern as in code:GetCustomMarshalerInfo.
1360 delete pEventArgsInfo;
1364 RETURN m_pEventArgsInfo;
1367 OleColorMarshalingInfo *EEMarshalingData::GetOleColorMarshalingInfo()
1369 CONTRACT (OleColorMarshalingInfo*)
1374 INJECT_FAULT(COMPlusThrowOM());
1375 POSTCONDITION(CheckPointer(RETVAL));
1379 if (m_pOleColorInfo == NULL)
1381 OleColorMarshalingInfo *pOleColorInfo = new (m_pHeap) OleColorMarshalingInfo();
1383 if (InterlockedCompareExchangeT(&m_pOleColorInfo, pOleColorInfo, NULL) != NULL)
1385 // Another thread beat us to it. Delete on OleColorMarshalingInfo is an empty operation
1386 // which is OK, since the possible leak is rare, small, and constant. This is the same
1387 // pattern as in code:GetCustomMarshalerInfo.
1388 delete pOleColorInfo;
1392 RETURN m_pOleColorInfo;
1394 #endif // FEATURE_COMINTEROP
1396 //==========================================================================
1397 // Constructs MarshalInfo.
1398 //==========================================================================
1400 #pragma warning(push)
1401 #pragma warning(disable:21000) // Suppress PREFast warning about overly large function
1403 MarshalInfo::MarshalInfo(Module* pModule,
1405 const SigTypeContext *pTypeContext,
1408 CorNativeLinkType nlType,
1409 CorNativeLinkFlags nlFlags,
1411 UINT paramidx, // parameter # for use in error messages (ignored if not parameter)
1412 UINT numArgs, // number of arguments
1414 BOOL ThrowOnUnmappableChar,
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 m_BestFit = BestFit;
1443 m_ThrowOnUnmappableChar = ThrowOnUnmappableChar;
1445 m_fAnsi = (ms == MARSHAL_SCENARIO_NDIRECT) && (nlType == nltAnsi);
1446 m_managedArgSize = 0;
1447 m_nativeArgSize = 0;
1450 m_args.m_pMarshalInfo = this;
1451 m_args.m_pMT = NULL;
1452 m_pModule = pModule;
1453 CorElementType mtype = ELEMENT_TYPE_END;
1454 CorElementType corElemType = ELEMENT_TYPE_END;
1458 #ifdef FEATURE_COMINTEROP
1461 m_fErrorNativeType = FALSE;
1462 m_hiddenLengthParamIndex = (UINT16)-1;
1463 m_dwHiddenLengthManagedHomeLocal= 0xFFFFFFFF;
1464 m_dwHiddenLengthNativeHomeLocal = 0xFFFFFFFF;
1466 m_pDefaultItfMT = NULL;
1467 #endif // FEATURE_COMINTEROP
1472 CHAR achDbgContext[DEBUG_CONTEXT_STR_LEN] = "";
1475 strncpy_s(achDbgContext, COUNTOF(achDbgContext), "<Unknown>", _TRUNCATE);
1479 strncat_s(achDbgContext, COUNTOF(achDbgContext), pDebugClassName, _TRUNCATE);
1480 strncat_s(achDbgContext, COUNTOF(achDbgContext), NAMESPACE_SEPARATOR_STR, _TRUNCATE);
1481 strncat_s(achDbgContext, COUNTOF(achDbgContext), pDebugName, _TRUNCATE);
1482 strncat_s(achDbgContext, COUNTOF(achDbgContext), " ", _TRUNCATE);
1486 strncat_s(achDbgContext, COUNTOF(achDbgContext), "field", _TRUNCATE);
1489 strncat_s(achDbgContext, COUNTOF(achDbgContext), "return value", _TRUNCATE);
1494 sprintf_s(buf, COUNTOF(buf), "param #%lu", (ULONG)argidx);
1495 strncat_s(achDbgContext, COUNTOF(achDbgContext), buf, _TRUNCATE);
1500 m_strDebugMethName = pDebugName;
1501 m_strDebugClassName = pDebugClassName;
1504 m_in = m_out = FALSE;
1510 // Retrieve the native type for the current parameter.
1511 if (!ParseNativeTypeInfo(token, pModule->GetMDImport(), &ParamInfo))
1513 IfFailGoto(E_FAIL, lFail);
1516 nativeType = ParamInfo.m_NativeType;
1517 corElemType = sig.PeekElemTypeNormalized(pModule, pTypeContext);
1518 mtype = corElemType;
1520 #ifdef FEATURE_COMINTEROP
1521 if (IsWinRTScenario() && nativeType != NATIVE_TYPE_DEFAULT)
1523 // Do not allow any MarshalAs in WinRT scenarios - marshaling is fully described by the parameter type.
1524 m_type = MARSHAL_TYPE_UNKNOWN;
1525 m_resID = IDS_EE_BADMARSHAL_WINRT_MARSHAL_AS;
1526 IfFailGoto(E_FAIL, lFail);
1528 #endif // FEATURE_COMINTEROP
1530 // Make sure SizeParamIndex < numArgs when marshalling native arrays
1531 if (nativeType == NATIVE_TYPE_ARRAY && ParamInfo.m_SizeIsSpecified)
1533 if (ParamInfo.m_Multiplier > 0 && ParamInfo.m_CountParamIdx >= numArgs)
1535 // Do not throw exception here.
1536 // We'll use EmitOrThrowInteropException to throw exception in non-COM interop
1537 // and emit exception throwing code directly in STUB in COM interop
1538 m_type = MARSHAL_TYPE_UNKNOWN;
1539 m_resID = IDS_EE_SIZECONTROLOUTOFRANGE;
1540 IfFailGoto(E_FAIL, lFail);
1544 // Parse ET_BYREF signature
1545 if (mtype == ELEMENT_TYPE_BYREF)
1548 SigPointer sigtmp = sig;
1549 IfFailGoto(sig.GetElemType(NULL), lFail);
1550 mtype = sig.PeekElemTypeNormalized(pModule, pTypeContext);
1558 // Check for valid ET_PTR signature
1559 if (mtype == ELEMENT_TYPE_PTR)
1561 #ifdef FEATURE_COMINTEROP
1562 // WinRT does not support ET_PTR
1563 if (IsWinRTScenario())
1565 m_type = MARSHAL_TYPE_UNKNOWN;
1566 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
1567 IfFailGoto(E_FAIL, lFail);
1569 #endif // FEATURE_COMINTEROP
1571 SigPointer sigtmp = sig;
1572 IfFailGoto(sigtmp.GetElemType(NULL), lFail);
1574 // Peek closed elem type here to prevent ELEMENT_TYPE_VALUETYPE turning into a primitive.
1575 CorElementType mtype2 = sigtmp.PeekElemTypeClosed(pModule, pTypeContext);
1577 if (mtype2 == ELEMENT_TYPE_VALUETYPE)
1580 TypeHandle th = sigtmp.GetTypeHandleThrowing(pModule, pTypeContext);
1581 _ASSERTE(!th.IsNull());
1583 // We want to leave out enums as they surely don't have copy constructors
1584 // plus they are not marked as blittable.
1587 // It should be blittable
1588 if (!th.IsBlittable())
1590 m_resID = IDS_EE_BADMARSHAL_PTRNONBLITTABLE;
1591 IfFailGoto(E_FAIL, lFail);
1598 if (!(mtype2 != ELEMENT_TYPE_CLASS &&
1599 mtype2 != ELEMENT_TYPE_STRING &&
1600 mtype2 != ELEMENT_TYPE_OBJECT &&
1601 mtype2 != ELEMENT_TYPE_SZARRAY))
1603 m_resID = IDS_EE_BADMARSHAL_PTRSUBTYPE;
1604 IfFailGoto(E_FAIL, lFail);
1610 // System primitive types (System.Int32, et.al.) will be marshaled as expected
1611 // because the mtype CorElementType is normalized (e.g. ELEMENT_TYPE_I4).
1613 // We however need to detect if such a normalization occurred for non-system
1614 // trivial value types, because we hold CorNativeType belonging to the original
1615 // "un-normalized" signature type. It has to be verified that all the value types
1616 // that have been normalized away have default marshaling or MarshalAs(Struct).
1617 // In addition, the nativeType must be updated with the type of the real primitive inside.
1619 VerifyAndAdjustNormalizedType(pModule, sig, pTypeContext, &mtype, &nativeType);
1620 #endif // _TARGET_X86_
1623 if (nativeType == NATIVE_TYPE_CUSTOMMARSHALER)
1627 case ELEMENT_TYPE_VAR:
1628 case ELEMENT_TYPE_CLASS:
1629 case ELEMENT_TYPE_OBJECT:
1630 m_CMVt = VT_UNKNOWN;
1633 case ELEMENT_TYPE_STRING:
1634 case ELEMENT_TYPE_SZARRAY:
1635 case ELEMENT_TYPE_ARRAY:
1640 m_resID = IDS_EE_BADMARSHAL_CUSTOMMARSHALER;
1641 IfFailGoto(E_FAIL, lFail);
1644 // Set m_type to MARSHAL_TYPE_UNKNOWN in case SetupCustomMarshalerHelper throws.
1645 m_type = MARSHAL_TYPE_UNKNOWN;
1647 if (fLoadCustomMarshal)
1649 // Set up the custom marshaler info.
1650 TypeHandle hndManagedType = sig.GetTypeHandleThrowing(pModule, pTypeContext);
1654 m_pCMHelper = SetupCustomMarshalerHelper(ParamInfo.m_strCMMarshalerTypeName,
1655 ParamInfo.m_cCMMarshalerTypeNameBytes,
1656 ParamInfo.m_strCMCookie,
1657 ParamInfo.m_cCMCookieStrBytes,
1664 MethodDesc* pMDforModule = pMD;
1665 if (pMD->IsILStub())
1667 pMDforModule = pMD->AsDynamicMethodDesc()->GetILStubResolver()->GetStubTargetMethodDesc();
1669 m_args.rcm.m_pMD = pMDforModule;
1670 m_args.rcm.m_paramToken = token;
1671 m_args.rcm.m_hndManagedType = hndManagedType.AsPtr();
1672 CONSISTENCY_CHECK(pModule == pMDforModule->GetModule());
1676 // Specify which custom marshaler to use.
1677 m_type = MARSHAL_TYPE_REFERENCECUSTOMMARSHALER;
1684 case ELEMENT_TYPE_BOOLEAN:
1687 case NATIVE_TYPE_BOOLEAN:
1688 m_type = MARSHAL_TYPE_WINBOOL;
1691 #ifdef FEATURE_COMINTEROP
1692 case NATIVE_TYPE_VARIANTBOOL:
1693 m_type = MARSHAL_TYPE_VTBOOL;
1695 #endif // FEATURE_COMINTEROP
1697 case NATIVE_TYPE_U1:
1698 case NATIVE_TYPE_I1:
1699 m_type = MARSHAL_TYPE_CBOOL;
1702 case NATIVE_TYPE_DEFAULT:
1703 #ifdef FEATURE_COMINTEROP
1704 if (m_ms == MARSHAL_SCENARIO_COMINTEROP)
1706 // 2-byte COM VARIANT_BOOL
1707 m_type = MARSHAL_TYPE_VTBOOL;
1709 else if (m_ms == MARSHAL_SCENARIO_WINRT)
1711 // 1-byte WinRT bool
1712 m_type = MARSHAL_TYPE_CBOOL;
1715 #endif // FEATURE_COMINTEROP
1717 // 4-byte Windows BOOL
1718 _ASSERTE(m_ms == MARSHAL_SCENARIO_NDIRECT);
1719 m_type = MARSHAL_TYPE_WINBOOL;
1724 m_resID = IDS_EE_BADMARSHAL_BOOLEAN;
1725 IfFailGoto(E_FAIL, lFail);
1729 case ELEMENT_TYPE_CHAR:
1732 case NATIVE_TYPE_I1: //fallthru
1733 case NATIVE_TYPE_U1:
1734 m_type = MARSHAL_TYPE_ANSICHAR;
1737 case NATIVE_TYPE_I2: //fallthru
1738 case NATIVE_TYPE_U2:
1739 m_type = MARSHAL_TYPE_GENERIC_U2;
1742 case NATIVE_TYPE_DEFAULT:
1743 m_type = ( (m_ms == MARSHAL_SCENARIO_NDIRECT && m_fAnsi) ? MARSHAL_TYPE_ANSICHAR : MARSHAL_TYPE_GENERIC_U2 );
1747 m_resID = IDS_EE_BADMARSHAL_CHAR;
1748 IfFailGoto(E_FAIL, lFail);
1753 case ELEMENT_TYPE_I1:
1754 if (!(nativeType == NATIVE_TYPE_I1 || nativeType == NATIVE_TYPE_U1 || nativeType == NATIVE_TYPE_DEFAULT))
1756 m_resID = IDS_EE_BADMARSHAL_I1;
1757 IfFailGoto(E_FAIL, lFail);
1759 m_type = MARSHAL_TYPE_GENERIC_1;
1762 case ELEMENT_TYPE_U1:
1763 if (!(nativeType == NATIVE_TYPE_U1 || nativeType == NATIVE_TYPE_I1 || nativeType == NATIVE_TYPE_DEFAULT))
1765 m_resID = IDS_EE_BADMARSHAL_I1;
1766 IfFailGoto(E_FAIL, lFail);
1768 m_type = MARSHAL_TYPE_GENERIC_U1;
1771 case ELEMENT_TYPE_I2:
1772 if (!(nativeType == NATIVE_TYPE_I2 || nativeType == NATIVE_TYPE_U2 || nativeType == NATIVE_TYPE_DEFAULT))
1774 m_resID = IDS_EE_BADMARSHAL_I2;
1775 IfFailGoto(E_FAIL, lFail);
1777 m_type = MARSHAL_TYPE_GENERIC_2;
1780 case ELEMENT_TYPE_U2:
1781 if (!(nativeType == NATIVE_TYPE_U2 || nativeType == NATIVE_TYPE_I2 || nativeType == NATIVE_TYPE_DEFAULT))
1783 m_resID = IDS_EE_BADMARSHAL_I2;
1784 IfFailGoto(E_FAIL, lFail);
1786 m_type = MARSHAL_TYPE_GENERIC_U2;
1789 case ELEMENT_TYPE_I4:
1792 case NATIVE_TYPE_I4:
1793 case NATIVE_TYPE_U4:
1794 case NATIVE_TYPE_DEFAULT:
1797 #ifdef FEATURE_COMINTEROP
1798 case NATIVE_TYPE_ERROR:
1799 m_fErrorNativeType = TRUE;
1801 #endif // FEATURE_COMINTEROP
1804 m_resID = IDS_EE_BADMARSHAL_I4;
1805 IfFailGoto(E_FAIL, lFail);
1807 m_type = MARSHAL_TYPE_GENERIC_4;
1810 case ELEMENT_TYPE_U4:
1813 case NATIVE_TYPE_I4:
1814 case NATIVE_TYPE_U4:
1815 case NATIVE_TYPE_DEFAULT:
1818 #ifdef FEATURE_COMINTEROP
1819 case NATIVE_TYPE_ERROR:
1820 m_fErrorNativeType = TRUE;
1822 #endif // FEATURE_COMINTEROP
1825 m_resID = IDS_EE_BADMARSHAL_I4;
1826 IfFailGoto(E_FAIL, lFail);
1828 m_type = MARSHAL_TYPE_GENERIC_4;
1831 case ELEMENT_TYPE_I8:
1832 if (!(nativeType == NATIVE_TYPE_I8 || nativeType == NATIVE_TYPE_U8 || nativeType == NATIVE_TYPE_DEFAULT))
1834 m_resID = IDS_EE_BADMARSHAL_I8;
1835 IfFailGoto(E_FAIL, lFail);
1837 m_type = MARSHAL_TYPE_GENERIC_8;
1840 case ELEMENT_TYPE_U8:
1841 if (!(nativeType == NATIVE_TYPE_U8 || nativeType == NATIVE_TYPE_I8 || nativeType == NATIVE_TYPE_DEFAULT))
1843 m_resID = IDS_EE_BADMARSHAL_I8;
1844 IfFailGoto(E_FAIL, lFail);
1846 m_type = MARSHAL_TYPE_GENERIC_8;
1849 case ELEMENT_TYPE_I:
1850 #ifdef FEATURE_COMINTEROP
1851 if (IsWinRTScenario())
1853 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
1854 IfFailGoto(E_FAIL, lFail);
1856 #endif // FEATURE_COMINTEROP
1858 if (!(nativeType == NATIVE_TYPE_INT || nativeType == NATIVE_TYPE_UINT || nativeType == NATIVE_TYPE_DEFAULT))
1860 m_resID = IDS_EE_BADMARSHAL_I;
1861 IfFailGoto(E_FAIL, lFail);
1863 m_type = (sizeof(LPVOID) == 4 ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8);
1866 case ELEMENT_TYPE_U:
1867 #ifdef FEATURE_COMINTEROP
1868 if (IsWinRTScenario())
1870 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
1871 IfFailGoto(E_FAIL, lFail);
1873 #endif // FEATURE_COMINTEROP
1875 if (!(nativeType == NATIVE_TYPE_UINT || nativeType == NATIVE_TYPE_INT || nativeType == NATIVE_TYPE_DEFAULT))
1877 m_resID = IDS_EE_BADMARSHAL_I;
1878 IfFailGoto(E_FAIL, lFail);
1880 m_type = (sizeof(LPVOID) == 4 ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8);
1884 case ELEMENT_TYPE_R4:
1885 if (!(nativeType == NATIVE_TYPE_R4 || nativeType == NATIVE_TYPE_DEFAULT))
1887 m_resID = IDS_EE_BADMARSHAL_R4;
1888 IfFailGoto(E_FAIL, lFail);
1890 m_type = MARSHAL_TYPE_FLOAT;
1893 case ELEMENT_TYPE_R8:
1894 if (!(nativeType == NATIVE_TYPE_R8 || nativeType == NATIVE_TYPE_DEFAULT))
1896 m_resID = IDS_EE_BADMARSHAL_R8;
1897 IfFailGoto(E_FAIL, lFail);
1899 m_type = MARSHAL_TYPE_DOUBLE;
1902 case ELEMENT_TYPE_PTR:
1903 #ifdef FEATURE_COMINTEROP
1904 _ASSERTE(!IsWinRTScenario()); // we checked for this earlier
1905 #endif // FEATURE_COMINTEROP
1907 if (nativeType != NATIVE_TYPE_DEFAULT)
1909 m_resID = IDS_EE_BADMARSHAL_PTR;
1910 IfFailGoto(E_FAIL, lFail);
1912 m_type = ( (sizeof(void*)==4) ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8 );
1915 case ELEMENT_TYPE_FNPTR:
1916 #ifdef FEATURE_COMINTEROP
1917 if (IsWinRTScenario())
1919 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
1920 IfFailGoto(E_FAIL, lFail);
1922 #endif // FEATURE_COMINTEROP
1924 if (!(nativeType == NATIVE_TYPE_FUNC || nativeType == NATIVE_TYPE_DEFAULT))
1926 m_resID = IDS_EE_BADMARSHAL_FNPTR;
1927 IfFailGoto(E_FAIL, lFail);
1929 m_type = ( (sizeof(void*)==4) ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8 );
1932 case ELEMENT_TYPE_OBJECT:
1933 case ELEMENT_TYPE_STRING:
1934 case ELEMENT_TYPE_CLASS:
1935 case ELEMENT_TYPE_VAR:
1937 TypeHandle sigTH = sig.GetTypeHandleThrowing(pModule, pTypeContext);
1939 // Disallow marshaling generic types except for WinRT interfaces.
1940 if (sigTH.HasInstantiation())
1942 #ifdef FEATURE_COMINTEROP
1943 if (!sigTH.SupportsGenericInterop(TypeHandle::Interop_NativeToManaged))
1944 #endif // FEATURE_COMINTEROP
1946 m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
1947 IfFailGoto(E_FAIL, lFail);
1951 m_pMT = sigTH.GetMethodTable();
1953 IfFailGoto(COR_E_TYPELOAD, lFail);
1955 #ifdef FEATURE_COMINTEROP
1956 MethodTable* pDefaultMT = NULL;
1958 // Look for marshaling of WinRT runtime classes
1959 if ((m_pMT->IsProjectedFromWinRT() || m_pMT->IsExportedToWinRT()) && !m_pMT->HasExplicitGuid())
1961 // The type loader guarantees that there are no WinRT interfaces without explicit GUID
1962 _ASSERTE(!m_pMT->IsInterface());
1964 // Make sure that this is really a legal runtime class and not a custom attribute or delegate
1965 if (!m_pMT->IsLegalNonArrayWinRTType() || m_pMT->IsDelegate())
1967 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
1968 IfFailGoto(E_FAIL, lFail);
1971 // This class must have a default interface that describes how it is marshaled
1972 pDefaultMT = m_pMT->GetDefaultWinRTInterface();
1973 if (pDefaultMT == NULL)
1975 m_resID = IDS_EE_BADMARSHAL_WINRT_MISSING_GUID;
1976 IfFailGoto(E_FAIL, lFail);
1980 if (nativeType == NATIVE_TYPE_INTF)
1983 if (sig.IsStringType(pModule, pTypeContext))
1985 m_resID = IDS_EE_BADMARSHALPARAM_STRING;
1986 IfFailGoto(E_FAIL, lFail);
1989 if (m_ms == MARSHAL_SCENARIO_WINRT && COMDelegate::IsDelegate(m_pMT))
1991 // In WinRT scenarios delegates must be WinRT delegates
1992 if (!m_pMT->IsProjectedFromWinRT() && !WinRTTypeNameConverter::IsRedirectedType(m_pMT))
1994 m_resID = IDS_EE_BADMARSHAL_WINRT_DELEGATE;
1995 IfFailGoto(E_FAIL, lFail);
1999 m_type = MARSHAL_TYPE_INTERFACE;
2001 else if (pDefaultMT != NULL && nativeType == NATIVE_TYPE_DEFAULT)
2003 // Pretend this is really marshaling as the default interface type
2005 // Validate it's a WinRT interface with GUID
2006 if (!pDefaultMT->IsInterface() ||
2007 (!pDefaultMT->IsProjectedFromWinRT() && !pDefaultMT->IsExportedToWinRT()) ||
2008 !pDefaultMT->HasExplicitGuid())
2010 // This might also be a redirected interface - which is also allowed
2011 if (!pDefaultMT->IsWinRTRedirectedInterface(TypeHandle::Interop_NativeToManaged))
2013 m_resID = IDS_EE_BADMARSHAL_DEFAULTIFACE_NOT_WINRT_IFACE;
2014 IfFailGoto(E_FAIL, lFail);
2018 // Validate that it's one of the component interfaces of the class in the signature
2019 if (!m_pMT->ImplementsEquivalentInterface(pDefaultMT))
2021 m_resID = IDS_EE_BADMARSHAL_DEFAULTIFACE_NOT_SUBTYPE;
2022 IfFailGoto(E_FAIL, lFail);
2025 // Make sure it's not an unexpected generic case (not clear we can actually get here in practice due
2026 // to the above Implements check)
2027 if (pDefaultMT->HasInstantiation() && !pDefaultMT->SupportsGenericInterop(TypeHandle::Interop_NativeToManaged))
2029 m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
2030 IfFailGoto(E_FAIL, lFail);
2033 // Store the marshal data just as if we were marshaling as this default interface type
2034 m_type = MARSHAL_TYPE_INTERFACE;
2035 m_pDefaultItfMT = pDefaultMT;
2038 #endif // FEATURE_COMINTEROP
2040 bool builder = false;
2041 if (sig.IsStringTypeThrowing(pModule, pTypeContext)
2042 || ((builder = true), 0)
2043 || sig.IsClassThrowing(pModule, g_StringBufferClassName, pTypeContext)
2046 switch ( nativeType )
2048 case NATIVE_TYPE_LPWSTR:
2049 m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_LPWSTR;
2052 case NATIVE_TYPE_LPSTR:
2053 m_type = builder ? MARSHAL_TYPE_LPSTR_BUFFER : MARSHAL_TYPE_LPSTR;
2056 case NATIVE_TYPE_LPUTF8STR:
2057 m_type = builder ? MARSHAL_TYPE_UTF8_BUFFER : MARSHAL_TYPE_LPUTF8STR;
2060 case NATIVE_TYPE_LPTSTR:
2062 #ifdef FEATURE_COMINTEROP
2063 if (m_ms != MARSHAL_SCENARIO_NDIRECT)
2065 _ASSERTE(m_ms == MARSHAL_SCENARIO_COMINTEROP);
2066 // We disallow NATIVE_TYPE_LPTSTR for COM.
2067 IfFailGoto(E_FAIL, lFail);
2069 #endif // FEATURE_COMINTEROP
2070 // We no longer support Win9x so LPTSTR always maps to a Unicode string.
2071 m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_LPWSTR;
2075 case NATIVE_TYPE_BSTR:
2078 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2079 IfFailGoto(E_FAIL, lFail);
2081 m_type = MARSHAL_TYPE_BSTR;
2084 case NATIVE_TYPE_ANSIBSTR:
2087 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2088 IfFailGoto(E_FAIL, lFail);
2090 m_type = MARSHAL_TYPE_ANSIBSTR;
2093 case NATIVE_TYPE_TBSTR:
2097 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2098 IfFailGoto(E_FAIL, lFail);
2101 // We no longer support Win9x so TBSTR always maps to a normal (unicode) BSTR.
2102 m_type = MARSHAL_TYPE_BSTR;
2106 #ifdef FEATURE_COMINTEROP
2107 case NATIVE_TYPE_BYVALSTR:
2111 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2112 IfFailGoto(E_FAIL, lFail);
2114 m_type = m_fAnsi ? MARSHAL_TYPE_VBBYVALSTR : MARSHAL_TYPE_VBBYVALSTRW;
2118 case NATIVE_TYPE_HSTRING:
2122 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2123 IfFailGoto(E_FAIL, lFail);
2126 m_type = MARSHAL_TYPE_HSTRING;
2129 #endif // FEATURE_COMINTEROP
2131 case NATIVE_TYPE_DEFAULT:
2133 #ifdef FEATURE_COMINTEROP
2134 if (m_ms == MARSHAL_SCENARIO_WINRT)
2138 m_resID = IDS_EE_BADMARSHALPARAM_STRINGBUILDER;
2139 IfFailGoto(E_FAIL, lFail);
2142 m_type = MARSHAL_TYPE_HSTRING;
2144 else if (m_ms != MARSHAL_SCENARIO_NDIRECT)
2146 _ASSERTE(m_ms == MARSHAL_SCENARIO_COMINTEROP);
2147 m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_BSTR;
2150 #endif // FEATURE_COMINTEROP
2153 m_type = builder ? MARSHAL_TYPE_LPSTR_BUFFER : MARSHAL_TYPE_LPSTR;
2157 m_type = builder ? MARSHAL_TYPE_LPWSTR_BUFFER : MARSHAL_TYPE_LPWSTR;
2163 m_resID = builder ? IDS_EE_BADMARSHALPARAM_STRINGBUILDER : IDS_EE_BADMARSHALPARAM_STRING;
2164 IfFailGoto(E_FAIL, lFail);
2168 #ifdef FEATURE_COMINTEROP
2169 else if (sig.IsClassThrowing(pModule, g_CollectionsEnumeratorClassName, pTypeContext) &&
2170 nativeType == NATIVE_TYPE_DEFAULT)
2172 m_CMVt = VT_UNKNOWN;
2173 m_type = MARSHAL_TYPE_REFERENCECUSTOMMARSHALER;
2175 if (fLoadCustomMarshal)
2179 m_pCMHelper = SetupCustomMarshalerHelper(ENUMERATOR_TO_ENUM_VARIANT_CM_NAME,
2180 ENUMERATOR_TO_ENUM_VARIANT_CM_NAME_LEN,
2181 ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE,
2182 ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE_LEN,
2188 MethodDesc* pMDforModule = pMD;
2189 if (pMD->IsILStub())
2191 pMDforModule = pMD->AsDynamicMethodDesc()->GetILStubResolver()->GetStubTargetMethodDesc();
2193 m_args.rcm.m_pMD = pMDforModule;
2194 m_args.rcm.m_paramToken = token;
2195 m_args.rcm.m_hndManagedType = sigTH.AsPtr();
2196 CONSISTENCY_CHECK(pModule == pMDforModule->GetModule());
2200 #endif // FEATURE_COMINTEROP
2201 else if (sigTH.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE))))
2203 if (nativeType != NATIVE_TYPE_DEFAULT)
2205 m_resID = IDS_EE_BADMARSHAL_SAFEHANDLE;
2206 IfFailGoto(E_FAIL, lFail);
2208 m_args.m_pMT = m_pMT;
2209 m_type = MARSHAL_TYPE_SAFEHANDLE;
2211 else if (sigTH.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__CRITICAL_HANDLE))))
2213 if (nativeType != NATIVE_TYPE_DEFAULT)
2215 m_resID = IDS_EE_BADMARSHAL_CRITICALHANDLE;
2216 IfFailGoto(E_FAIL, lFail);
2218 m_args.m_pMT = m_pMT;
2219 m_type = MARSHAL_TYPE_CRITICALHANDLE;
2221 else if (sig.IsClassThrowing(pModule, g_ReflectionMethodInterfaceName, pTypeContext))
2223 if (nativeType != NATIVE_TYPE_DEFAULT)
2225 IfFailGoto(E_FAIL, lFail);
2228 m_type = MARSHAL_TYPE_RUNTIMEMETHODINFO;
2230 #ifdef FEATURE_COMINTEROP
2231 else if (m_pMT->IsInterface())
2233 if (!(nativeType == NATIVE_TYPE_DEFAULT ||
2234 nativeType == NATIVE_TYPE_INTF))
2236 m_resID = IDS_EE_BADMARSHAL_INTERFACE;
2237 IfFailGoto(E_FAIL, lFail);
2239 m_type = MARSHAL_TYPE_INTERFACE;
2241 if (m_ms == MARSHAL_SCENARIO_WINRT)
2243 // all interfaces marshaled in WinRT scenarios are IInspectable-based
2247 // Check for Windows.Foundation.HResult <-> Exception
2248 else if (m_ms == MARSHAL_SCENARIO_WINRT && MscorlibBinder::IsClass(m_pMT, CLASS__EXCEPTION))
2250 m_args.m_pMT = m_pMT;
2251 m_type = MARSHAL_TYPE_EXCEPTION;
2253 #endif // FEATURE_COMINTEROP
2254 else if (COMDelegate::IsDelegate(m_pMT))
2256 m_args.m_pMT = m_pMT;
2257 #ifdef FEATURE_COMINTEROP
2258 if (m_ms == MARSHAL_SCENARIO_WINRT)
2260 // Delegates must be imported from WinRT and marshaled as Interface
2261 if (!m_pMT->IsProjectedFromWinRT() && !WinRTTypeNameConverter::IsRedirectedType(m_pMT))
2263 m_resID = IDS_EE_BADMARSHAL_WINRT_DELEGATE;
2264 IfFailGoto(E_FAIL, lFail);
2267 #endif // FEATURE_COMINTEROP
2271 case NATIVE_TYPE_FUNC:
2272 m_type = MARSHAL_TYPE_DELEGATE;
2275 case NATIVE_TYPE_DEFAULT:
2276 #ifdef FEATURE_COMINTEROP
2277 if (m_ms != MARSHAL_SCENARIO_NDIRECT)
2279 _ASSERTE(m_ms == MARSHAL_SCENARIO_COMINTEROP || m_ms == MARSHAL_SCENARIO_WINRT);
2280 m_type = MARSHAL_TYPE_INTERFACE;
2283 #endif // FEATURE_COMINTEROP
2284 m_type = MARSHAL_TYPE_DELEGATE;
2289 m_resID = IDS_EE_BADMARSHAL_DELEGATE;
2290 IfFailGoto(E_FAIL, lFail);
2294 else if (m_pMT->IsBlittable())
2296 if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_LPSTRUCT))
2298 m_resID = IDS_EE_BADMARSHAL_CLASS;
2299 IfFailGoto(E_FAIL, lFail);
2301 m_type = MARSHAL_TYPE_BLITTABLEPTR;
2302 m_args.m_pMT = m_pMT;
2304 else if (m_pMT->HasLayout())
2306 if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_LPSTRUCT))
2308 m_resID = IDS_EE_BADMARSHAL_CLASS;
2309 IfFailGoto(E_FAIL, lFail);
2311 m_type = MARSHAL_TYPE_LAYOUTCLASSPTR;
2312 m_args.m_pMT = m_pMT;
2314 else if (sig.IsClassThrowing(pModule, g_ReflectionModuleName, pTypeContext))
2316 if (nativeType != NATIVE_TYPE_DEFAULT)
2318 IfFailGoto(E_FAIL, lFail);
2321 m_type = MARSHAL_TYPE_RUNTIMEMODULE;
2323 else if (sig.IsClassThrowing(pModule, g_ReflectionAssemblyName, pTypeContext))
2325 if (nativeType != NATIVE_TYPE_DEFAULT)
2327 IfFailGoto(E_FAIL, lFail);
2330 m_type = MARSHAL_TYPE_RUNTIMEASSEMBLY;
2332 #ifdef FEATURE_COMINTEROP
2333 else if (m_ms == MARSHAL_SCENARIO_WINRT && sig.IsClassThrowing(pModule, g_SystemUriClassName, pTypeContext))
2335 m_type = MARSHAL_TYPE_URI;
2337 else if (m_ms == MARSHAL_SCENARIO_WINRT && sig.IsClassThrowing(pModule, g_NotifyCollectionChangedEventArgsName, pTypeContext))
2339 m_type = MARSHAL_TYPE_NCCEVENTARGS;
2341 else if (m_ms == MARSHAL_SCENARIO_WINRT && sig.IsClassThrowing(pModule, g_PropertyChangedEventArgsName, pTypeContext))
2343 m_type = MARSHAL_TYPE_PCEVENTARGS;
2345 #endif // FEATURE_COMINTEROP
2346 else if (m_pMT->IsObjectClass())
2350 #ifdef FEATURE_COMINTEROP
2351 case NATIVE_TYPE_DEFAULT:
2352 if (ms == MARSHAL_SCENARIO_WINRT)
2355 m_type = MARSHAL_TYPE_INTERFACE;
2359 case NATIVE_TYPE_STRUCT:
2360 m_type = MARSHAL_TYPE_OBJECT;
2363 case NATIVE_TYPE_INTF:
2364 case NATIVE_TYPE_IUNKNOWN:
2365 m_type = MARSHAL_TYPE_INTERFACE;
2368 case NATIVE_TYPE_IDISPATCH:
2370 m_type = MARSHAL_TYPE_INTERFACE;
2373 case NATIVE_TYPE_IINSPECTABLE:
2375 m_type = MARSHAL_TYPE_INTERFACE;
2378 case NATIVE_TYPE_DEFAULT:
2379 case NATIVE_TYPE_STRUCT:
2380 m_resID = IDS_EE_OBJECT_TO_VARIANT_NOT_SUPPORTED;
2381 IfFailGoto(E_FAIL, lFail);
2383 case NATIVE_TYPE_INTF:
2384 case NATIVE_TYPE_IUNKNOWN:
2385 case NATIVE_TYPE_IDISPATCH:
2386 m_resID = IDS_EE_OBJECT_TO_ITF_NOT_SUPPORTED;
2387 IfFailGoto(E_FAIL, lFail);
2388 #endif // FEATURE_COMINTEROP
2390 case NATIVE_TYPE_ASANY:
2391 m_type = m_fAnsi ? MARSHAL_TYPE_ASANYA : MARSHAL_TYPE_ASANYW;
2395 m_resID = IDS_EE_BADMARSHAL_OBJECT;
2396 IfFailGoto(E_FAIL, lFail);
2400 #ifdef FEATURE_COMINTEROP
2401 else if (sig.IsClassThrowing(pModule, g_ArrayClassName, pTypeContext))
2403 if (IsWinRTScenario())
2405 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2406 IfFailGoto(E_FAIL, lFail);
2411 case NATIVE_TYPE_DEFAULT:
2412 case NATIVE_TYPE_INTF:
2413 m_type = MARSHAL_TYPE_INTERFACE;
2416 case NATIVE_TYPE_SAFEARRAY:
2418 TypeHandle thElement = TypeHandle(g_pObjectClass);
2420 if (ParamInfo.m_SafeArrayElementVT != VT_EMPTY)
2422 if (ParamInfo.m_cSafeArrayUserDefTypeNameBytes > 0)
2424 // Load the type. Use an SString for the string since we need to NULL terminate the string
2425 // that comes from the metadata.
2426 StackScratchBuffer utf8Name;
2427 SString safeArrayUserDefTypeName(SString::Utf8, ParamInfo.m_strSafeArrayUserDefTypeName, ParamInfo.m_cSafeArrayUserDefTypeNameBytes);
2428 thElement = TypeName::GetTypeUsingCASearchRules(safeArrayUserDefTypeName.GetUTF8(utf8Name), pAssembly);
2433 // Compat: If no safe array VT was specified, default to VT_VARIANT.
2434 ParamInfo.m_SafeArrayElementVT = VT_VARIANT;
2437 IfFailGoto(HandleArrayElemType(&ParamInfo, 0, thElement, -1, FALSE, isParam, pAssembly), lFail);
2442 m_resID = IDS_EE_BADMARSHAL_SYSARRAY;
2443 IfFailGoto(E_FAIL, lFail);
2448 else if (m_pMT->IsArray())
2450 _ASSERTE(!"This invalid signature should never be hit!");
2451 IfFailGoto(E_FAIL, lFail);
2453 else if ((m_ms == MARSHAL_SCENARIO_WINRT) && sig.IsClassThrowing(pModule, g_TypeClassName, pTypeContext))
2455 m_type = MARSHAL_TYPE_SYSTEMTYPE;
2457 #endif // FEATURE_COMINTEROP
2458 else if (!m_pMT->IsValueType())
2460 #ifdef FEATURE_COMINTEROP
2461 if (IsWinRTScenario() && !m_pMT->IsLegalNonArrayWinRTType())
2463 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2464 IfFailGoto(E_FAIL, lFail);
2466 #endif // FEATURE_COMINTEROP
2468 if (!(nativeType == NATIVE_TYPE_INTF || nativeType == NATIVE_TYPE_DEFAULT))
2470 m_resID = IDS_EE_BADMARSHAL_NOLAYOUT;
2471 IfFailGoto(E_FAIL, lFail);
2473 #ifdef FEATURE_COMINTEROP
2474 // default marshalling is interface
2475 m_type = MARSHAL_TYPE_INTERFACE;
2476 #else // FEATURE_COMINTEROP
2477 m_resID = IDS_EE_OBJECT_TO_ITF_NOT_SUPPORTED;
2478 IfFailGoto(E_FAIL, lFail);
2479 #endif // FEATURE_COMINTEROP
2484 _ASSERTE(m_pMT->IsValueType());
2492 case ELEMENT_TYPE_VALUETYPE:
2495 if (sig.IsClassThrowing(pModule, g_DecimalClassName, pTypeContext))
2499 case NATIVE_TYPE_DEFAULT:
2500 case NATIVE_TYPE_STRUCT:
2501 m_type = MARSHAL_TYPE_DECIMAL;
2504 case NATIVE_TYPE_LPSTRUCT:
2505 m_type = MARSHAL_TYPE_DECIMAL_PTR;
2508 case NATIVE_TYPE_CURRENCY:
2509 m_type = MARSHAL_TYPE_CURRENCY;
2513 m_resID = IDS_EE_BADMARSHALPARAM_DECIMAL;
2514 IfFailGoto(E_FAIL, lFail);
2517 else if (sig.IsClassThrowing(pModule, g_GuidClassName, pTypeContext))
2521 case NATIVE_TYPE_DEFAULT:
2522 case NATIVE_TYPE_STRUCT:
2523 m_type = MARSHAL_TYPE_GUID;
2526 case NATIVE_TYPE_LPSTRUCT:
2527 m_type = MARSHAL_TYPE_GUID_PTR;
2531 m_resID = IDS_EE_BADMARSHAL_GUID;
2532 IfFailGoto(E_FAIL, lFail);
2535 #ifdef FEATURE_COMINTEROP
2536 else if (sig.IsClassThrowing(pModule, g_DateTimeOffsetClassName, pTypeContext))
2538 if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_STRUCT))
2540 m_resID = IDS_EE_BADMARSHAL_DATETIMEOFFSET;
2541 IfFailGoto(E_FAIL, lFail);
2543 m_type = MARSHAL_TYPE_DATETIME;
2544 m_pMT = MscorlibBinder::GetClass(CLASS__DATE_TIME_OFFSET);
2546 #endif // FEATURE_COMINTEROP
2547 else if (sig.IsClassThrowing(pModule, g_DateClassName, pTypeContext))
2549 if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_STRUCT))
2551 m_resID = IDS_EE_BADMARSHAL_DATETIME;
2552 IfFailGoto(E_FAIL, lFail);
2554 m_type = MARSHAL_TYPE_DATE;
2556 else if (sig.IsClassThrowing(pModule, "System.Runtime.InteropServices.ArrayWithOffset", pTypeContext))
2558 if (!(nativeType == NATIVE_TYPE_DEFAULT))
2560 IfFailGoto(E_FAIL, lFail);
2562 m_type = MARSHAL_TYPE_ARRAYWITHOFFSET;
2564 else if (sig.IsClassThrowing(pModule, "System.Runtime.InteropServices.HandleRef", pTypeContext))
2566 if (!(nativeType == NATIVE_TYPE_DEFAULT))
2568 IfFailGoto(E_FAIL, lFail);
2570 m_type = MARSHAL_TYPE_HANDLEREF;
2572 else if (sig.IsClassThrowing(pModule, "System.ArgIterator", pTypeContext))
2574 if (!(nativeType == NATIVE_TYPE_DEFAULT))
2576 IfFailGoto(E_FAIL, lFail);
2578 m_type = MARSHAL_TYPE_ARGITERATOR;
2580 #ifdef FEATURE_COMINTEROP
2581 else if (sig.IsClassThrowing(pModule, g_ColorClassName, pTypeContext))
2583 if (!(nativeType == NATIVE_TYPE_DEFAULT))
2585 IfFailGoto(E_FAIL, lFail);
2588 // This is only supported for COM interop.
2589 if (m_ms != MARSHAL_SCENARIO_COMINTEROP)
2591 IfFailGoto(E_FAIL, lFail);
2594 m_type = MARSHAL_TYPE_OLECOLOR;
2596 #endif // FEATURE_COMINTEROP
2597 else if (sig.IsClassThrowing(pModule, g_RuntimeTypeHandleClassName, pTypeContext))
2599 if (nativeType != NATIVE_TYPE_DEFAULT)
2601 IfFailGoto(E_FAIL, lFail);
2604 m_type = MARSHAL_TYPE_RUNTIMETYPEHANDLE;
2606 else if (sig.IsClassThrowing(pModule, g_RuntimeFieldHandleClassName, pTypeContext))
2608 if (nativeType != NATIVE_TYPE_DEFAULT)
2610 IfFailGoto(E_FAIL, lFail);
2613 m_type = MARSHAL_TYPE_RUNTIMEFIELDHANDLE;
2615 else if (sig.IsClassThrowing(pModule, g_RuntimeMethodHandleClassName, pTypeContext))
2617 if (nativeType != NATIVE_TYPE_DEFAULT)
2619 IfFailGoto(E_FAIL, lFail);
2622 m_type = MARSHAL_TYPE_RUNTIMEMETHODHANDLE;
2626 m_pMT = sig.GetTypeHandleThrowing(pModule, pTypeContext).GetMethodTable();
2630 #ifdef FEATURE_COMINTEROP
2631 // Handle Nullable<T> and KeyValuePair<K, V> for WinRT
2632 if (m_ms == MARSHAL_SCENARIO_WINRT)
2634 if (m_pMT->HasSameTypeDefAs(g_pNullableClass))
2636 m_type = MARSHAL_TYPE_NULLABLE;
2637 m_args.m_pMT = m_pMT;
2641 if (m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__KEYVALUEPAIRGENERIC)))
2643 m_type = MARSHAL_TYPE_KEYVALUEPAIR;
2644 m_args.m_pMT = m_pMT;
2648 if (!m_pMT->IsLegalNonArrayWinRTType())
2650 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2651 IfFailGoto(E_FAIL, lFail);
2654 #endif // FEATURE_COMINTEROP
2656 if (m_pMT->HasInstantiation())
2658 m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
2659 IfFailGoto(E_FAIL, lFail);
2662 UINT managedSize = m_pMT->GetAlignedNumInstanceFieldBytes();
2663 UINT nativeSize = m_pMT->GetNativeSize();
2665 if ( nativeSize > 0xfff0 ||
2666 managedSize > 0xfff0)
2668 m_resID = IDS_EE_STRUCTTOOCOMPLEX;
2669 IfFailGoto(E_FAIL, lFail);
2672 if (m_pMT->IsBlittable())
2674 if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_STRUCT))
2676 m_resID = IDS_EE_BADMARSHAL_VALUETYPE;
2677 IfFailGoto(E_FAIL, lFail);
2680 if (m_byref && !isParam)
2682 // Override the prohibition on byref returns so that IJW works
2684 m_type = ((sizeof(void*) == 4) ? MARSHAL_TYPE_GENERIC_4 : MARSHAL_TYPE_GENERIC_8);
2689 // JIT64 is not aware of normalized value types and this optimization
2690 // (returning small value types by value in registers) is already done in JIT64.
2691 if ( !m_byref // Permit register-sized structs as return values
2693 && CorIsPrimitiveType(m_pMT->GetInternalCorElementType())
2694 && !IsUnmanagedValueTypeReturnedByRef(nativeSize)
2695 && managedSize <= sizeof(void*)
2696 && nativeSize <= sizeof(void*))
2698 m_type = MARSHAL_TYPE_GENERIC_4;
2699 m_args.m_pMT = m_pMT;
2702 #endif // _TARGET_X86_
2704 m_args.m_pMT = m_pMT;
2705 m_type = MARSHAL_TYPE_BLITTABLEVALUECLASS;
2709 else if (m_pMT->HasLayout())
2711 if (!(nativeType == NATIVE_TYPE_DEFAULT || nativeType == NATIVE_TYPE_STRUCT))
2713 m_resID = IDS_EE_BADMARSHAL_VALUETYPE;
2714 IfFailGoto(E_FAIL, lFail);
2717 m_args.m_pMT = m_pMT;
2718 m_type = MARSHAL_TYPE_VALUECLASS;
2724 case ELEMENT_TYPE_SZARRAY:
2725 case ELEMENT_TYPE_ARRAY:
2727 // Get class info from array.
2728 TypeHandle arrayTypeHnd = sig.GetTypeHandleThrowing(pModule, pTypeContext);
2729 _ASSERTE(!arrayTypeHnd.IsNull());
2731 ArrayTypeDesc* asArray = arrayTypeHnd.AsArray();
2732 if (asArray == NULL)
2733 IfFailGoto(E_FAIL, lFail);
2735 TypeHandle thElement = asArray->GetTypeParam();
2737 #ifdef FEATURE_COMINTEROP
2738 if (m_ms != MARSHAL_SCENARIO_WINRT)
2739 #endif // FEATURE_COMINTEROP
2741 if (thElement.HasInstantiation())
2743 m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
2744 IfFailGoto(E_FAIL, lFail);
2749 if (arrayTypeHnd.GetMethodTable())
2751 ofs = ArrayBase::GetDataPtrOffset(arrayTypeHnd.GetMethodTable());
2754 ofs = 0; // can't represent it, so pass on magic value (which causes fallback to regular ML code)
2758 // Handle retrieving the information for the array type.
2759 IfFailGoto(HandleArrayElemType(&ParamInfo, (UINT16)ofs, thElement, asArray->GetRank(), mtype == ELEMENT_TYPE_SZARRAY, isParam, pAssembly), lFail);
2764 m_resID = IDS_EE_BADMARSHAL_BADMANAGED;
2768 #ifdef FEATURE_COMINTEROP
2769 //Field scenario is not blocked here because we don't want to block loading structs that
2770 //have the types which we are blocking, but never pass it to Interop.
2772 if (AppX::IsAppXProcess() && ms != MarshalInfo::MARSHAL_SCENARIO_FIELD)
2774 bool set_error = false;
2777 case MARSHAL_TYPE_ANSIBSTR:
2778 m_resID = IDS_EE_BADMARSHAL_TYPE_ANSIBSTR;
2781 case MARSHAL_TYPE_VBBYVALSTR:
2782 case MARSHAL_TYPE_VBBYVALSTRW:
2783 m_resID = IDS_EE_BADMARSHAL_TYPE_VBBYVALSTR;
2786 case MARSHAL_TYPE_REFERENCECUSTOMMARSHALER:
2787 m_resID = IDS_EE_BADMARSHAL_TYPE_REFERENCECUSTOMMARSHALER;
2790 case MARSHAL_TYPE_ASANYA:
2791 case MARSHAL_TYPE_ASANYW:
2792 m_resID = IDS_EE_BADMARSHAL_TYPE_ASANYA;
2795 case MARSHAL_TYPE_INTERFACE:
2798 m_resID = IDS_EE_BADMARSHAL_TYPE_IDISPATCH;
2805 COMPlusThrow(kPlatformNotSupportedException, m_resID);
2809 if (IsWinRTScenario() && !IsSupportedForWinRT(m_type))
2811 // the marshaler we came up with is not supported in WinRT scenarios
2812 m_type = MARSHAL_TYPE_UNKNOWN;
2813 m_resID = IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE;
2816 #endif // FEATURE_COMINTEROP
2818 if (m_byref && !isParam)
2820 // byref returns don't work: the thing pointed to lives on
2821 // a stack that disappears!
2822 m_type = MARSHAL_TYPE_UNKNOWN;
2826 //---------------------------------------------------------------------
2827 // Now, figure out the IN/OUT status.
2828 // Also set the m_fOleVarArgCandidate here to save perf of invoking Metadata API
2829 //---------------------------------------------------------------------
2830 m_fOleVarArgCandidate = FALSE;
2831 if (m_type != MARSHAL_TYPE_UNKNOWN && IsInOnly(m_type) && !m_byref)
2833 // If we got here, the parameter is something like an "int" where
2834 // [in] is the only semantically valid choice. Since there is no
2835 // possible way to interpret an [out] for such a type, we will ignore
2836 // the metadata and force the bits to "in". We could have defined
2837 // it as an error instead but this is less likely to cause problems
2838 // with metadata autogenerated from typelibs and poorly
2839 // defined C headers.
2847 // Capture and save away "In/Out" bits. If none is present, set both to FALSE (they will be properly defaulted downstream)
2848 if (token == mdParamDefNil)
2853 else if (TypeFromToken(token) != mdtParamDef)
2855 _ASSERTE(TypeFromToken(token) == mdtFieldDef);
2857 // Field setters are always In, the flags are ignored for return values of getters
2863 IMDInternalImport *pInternalImport = pModule->GetMDImport();
2866 LPCSTR szParamName_Ignore;
2868 if (FAILED(pInternalImport->GetParamDefProps(token, &usSequence, &dwAttr, &szParamName_Ignore)))
2875 m_in = IsPdIn(dwAttr) != 0;
2876 m_out = IsPdOut(dwAttr) != 0;
2877 #ifdef FEATURE_COMINTEROP
2878 // set m_fOleVarArgCandidate. The rule is same as the one defined in vm\tlbexp.cpp
2879 if(paramidx == numArgs && // arg is the last arg of the method
2880 !(dwAttr & PARAMFLAG_FOPT) && // arg is not a optional arg
2881 !IsNilToken(token) && // token is not a nil token
2882 (m_type == MARSHAL_TYPE_SAFEARRAY) && // arg is marshaled as SafeArray
2883 (m_arrayElementType == VT_VARIANT)) // the element of the safearray is VARIANT
2885 // check if it has default value
2886 MDDefaultValue defaultValue;
2887 if (SUCCEEDED(pInternalImport->GetDefaultValue(token, &defaultValue)) && defaultValue.m_bType == ELEMENT_TYPE_VOID)
2889 // check if it has params attribute
2890 if (pInternalImport->GetCustomAttributeByName(token, INTEROP_PARAMARRAY_TYPE, 0,0) == S_OK)
2891 m_fOleVarArgCandidate = TRUE;
2898 // If neither IN nor OUT are true, this signals the URT to use the default
2900 if (!m_in && !m_out)
2903 (mtype == ELEMENT_TYPE_CLASS
2904 && !(sig.IsStringType(pModule, pTypeContext))
2905 && sig.IsClass(pModule, g_StringBufferClassName, pTypeContext)))
2922 DumpMarshalInfo(pModule, sig, pTypeContext, token, ms, nlType, nlFlags);
2928 // We got here because of an illegal ELEMENT_TYPE/NATIVE_TYPE combo.
2929 m_type = MARSHAL_TYPE_UNKNOWN;
2930 //_ASSERTE(!"Invalid ELEMENT_TYPE/NATIVE_TYPE combination");
2934 #pragma warning(pop)
2937 VOID MarshalInfo::EmitOrThrowInteropParamException(NDirectStubLinker* psl, BOOL fMngToNative, UINT resID, UINT paramIdx)
2947 #ifdef FEATURE_COMINTEROP
2948 // If this is not forward COM interop, throw the exception right away. We rely on this
2949 // for example in code:ComPreStubWorker when we fire the InvalidMemberDeclaration MDA.
2950 if ((m_ms == MARSHAL_SCENARIO_COMINTEROP || m_ms == MARSHAL_SCENARIO_WINRT) && fMngToNative)
2952 psl->SetInteropParamExceptionInfo(resID, paramIdx);
2955 #endif // FEATURE_COMINTEROP
2957 ThrowInteropParamException(resID, paramIdx);
2961 HRESULT MarshalInfo::HandleArrayElemType(NativeTypeParamInfo *pParamInfo, UINT16 optbaseoffset, TypeHandle thElement, int iRank, BOOL fNoLowerBounds, BOOL isParam, Assembly *pAssembly)
2966 PRECONDITION(CheckPointer(pParamInfo));
2970 ArrayMarshalInfo arrayMarshalInfo(amiRuntime);
2974 // Store rank and bound information.
2977 m_iArrayRank = iRank;
2978 m_nolowerbounds = fNoLowerBounds;
2982 // Determine which type of marshaler to use.
2985 #ifdef FEATURE_COMINTEROP
2986 if (m_ms == MARSHAL_SCENARIO_WINRT)
2988 m_type = MARSHAL_TYPE_HIDDENLENGTHARRAY;
2990 else if (pParamInfo->m_NativeType == NATIVE_TYPE_SAFEARRAY)
2992 m_type = MARSHAL_TYPE_SAFEARRAY;
2995 #endif // FEATURE_COMINTEROP
2996 if (pParamInfo->m_NativeType == NATIVE_TYPE_ARRAY)
2998 m_type = MARSHAL_TYPE_NATIVEARRAY;
3000 else if (pParamInfo->m_NativeType == NATIVE_TYPE_DEFAULT)
3002 #ifdef FEATURE_COMINTEROP
3003 if (m_ms != MARSHAL_SCENARIO_NDIRECT)
3005 m_type = MARSHAL_TYPE_SAFEARRAY;
3008 #endif // FEATURE_COMINTEROP
3010 m_type = MARSHAL_TYPE_NATIVEARRAY;
3015 m_resID = IDS_EE_BADMARSHAL_ARRAY;
3019 #ifdef FEATURE_COMINTEROP
3020 if (m_type == MARSHAL_TYPE_SAFEARRAY)
3022 arrayMarshalInfo.InitForSafeArray(m_ms, thElement, pParamInfo->m_SafeArrayElementVT, m_fAnsi);
3024 else if (m_type == MARSHAL_TYPE_HIDDENLENGTHARRAY)
3026 arrayMarshalInfo.InitForHiddenLengthArray(thElement);
3029 #endif // FEATURE_COMINTEROP
3031 _ASSERTE(m_type == MARSHAL_TYPE_NATIVEARRAY);
3032 arrayMarshalInfo.InitForNativeArray(m_ms, thElement, pParamInfo->m_ArrayElementType, m_fAnsi);
3035 // Make sure the marshalling information is valid.
3036 if (!arrayMarshalInfo.IsValid())
3038 m_resID = arrayMarshalInfo.GetErrorResourceId();
3042 // Set the array type handle and VARTYPE to use for marshalling.
3043 m_hndArrayElemType = arrayMarshalInfo.GetElementTypeHandle();
3044 m_arrayElementType = arrayMarshalInfo.GetElementVT();
3046 if (m_type == MARSHAL_TYPE_NATIVEARRAY)
3048 // Retrieve the extra information associated with the native array marshaling.
3049 m_args.na.m_vt = m_arrayElementType;
3050 m_args.na.m_pMT = !m_hndArrayElemType.IsTypeDesc() ? m_hndArrayElemType.AsMethodTable() : NULL;
3051 m_args.na.m_optionalbaseoffset = optbaseoffset;
3052 m_countParamIdx = pParamInfo->m_CountParamIdx;
3053 m_multiplier = pParamInfo->m_Multiplier;
3054 m_additive = pParamInfo->m_Additive;
3056 #ifdef FEATURE_COMINTEROP
3057 else if (m_type == MARSHAL_TYPE_HIDDENLENGTHARRAY)
3059 m_args.na.m_optionalbaseoffset = optbaseoffset;
3061 m_args.na.m_vt = m_arrayElementType;
3062 m_args.na.m_pMT = m_hndArrayElemType.AsMethodTable();
3063 m_args.na.m_cbElementSize = arrayMarshalInfo.GetElementSize();
3064 m_args.na.m_redirectedTypeIndex = arrayMarshalInfo.GetRedirectedTypeIndex();
3066 #endif // FEATURE_COMINTEROP
3071 ILMarshaler* CreateILMarshaler(MarshalInfo::MarshalType mtype, NDirectStubLinker* psl)
3081 ILMarshaler* pMarshaler = NULL;
3085 #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) \
3086 case MarshalInfo::mt: \
3087 pMarshaler = new IL##mclass(); \
3090 #undef DEFINE_MARSHALER_TYPE
3093 UNREACHABLE_MSG("unexpected MarshalType passed to CreateILMarshaler");
3096 pMarshaler->SetNDirectStubLinker(psl);
3102 DWORD CalculateArgumentMarshalFlags(BOOL byref, BOOL in, BOOL out, BOOL fMngToNative)
3104 LIMITED_METHOD_CONTRACT;
3105 DWORD dwMarshalFlags = 0;
3109 dwMarshalFlags |= MARSHAL_FLAG_BYREF;
3114 dwMarshalFlags |= MARSHAL_FLAG_IN;
3119 dwMarshalFlags |= MARSHAL_FLAG_OUT;
3124 dwMarshalFlags |= MARSHAL_FLAG_CLR_TO_NATIVE;
3127 return dwMarshalFlags;
3130 DWORD CalculateReturnMarshalFlags(BOOL hrSwap, BOOL fMngToNative)
3132 LIMITED_METHOD_CONTRACT;
3133 DWORD dwMarshalFlags = MARSHAL_FLAG_RETVAL;
3137 dwMarshalFlags |= MARSHAL_FLAG_HRESULT_SWAP;
3142 dwMarshalFlags |= MARSHAL_FLAG_CLR_TO_NATIVE;
3145 return dwMarshalFlags;
3148 void MarshalInfo::GenerateArgumentIL(NDirectStubLinker* psl,
3149 int argOffset, // the argument's index is m_paramidx + argOffset
3150 UINT nativeStackOffset, // offset of the argument on the native stack
3156 PRECONDITION(CheckPointer(psl));
3160 if (m_type == MARSHAL_TYPE_UNKNOWN)
3162 EmitOrThrowInteropParamException(psl, fMngToNative, m_resID, m_paramidx + 1); // m_paramidx is 0-based, but the user wants to see a 1-based index
3166 // set up m_corArgSize and m_nativeArgSize
3167 SetupArgumentSizes();
3169 MarshalerOverrideStatus amostat;
3170 UINT resID = IDS_EE_BADMARSHAL_RESTRICTION;
3171 amostat = (GetArgumentOverrideProc(m_type)) (psl,
3178 m_paramidx + argOffset,
3182 if (amostat == OVERRIDDEN)
3187 if (amostat == DISALLOWED)
3189 EmitOrThrowInteropParamException(psl, fMngToNative, resID, m_paramidx + 1); // m_paramidx is 0-based, but the user wants to see a 1-based index
3193 CONSISTENCY_CHECK(amostat == HANDLEASNORMAL);
3195 NewHolder<ILMarshaler> pMarshaler = CreateILMarshaler(m_type, psl);
3196 DWORD dwMarshalFlags = CalculateArgumentMarshalFlags(m_byref, m_in, m_out, fMngToNative);
3198 if (!pMarshaler->SupportsArgumentMarshal(dwMarshalFlags, &resID))
3200 EmitOrThrowInteropParamException(psl, fMngToNative, resID, m_paramidx + 1); // m_paramidx is 0-based, but the user wants to see a 1-based index
3204 ILCodeStream* pcsMarshal = psl->GetMarshalCodeStream();
3205 ILCodeStream* pcsUnmarshal = psl->GetUnmarshalCodeStream();
3206 ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream();
3208 pcsMarshal->EmitNOP("// argument { ");
3209 pcsUnmarshal->EmitNOP("// argument { ");
3211 pMarshaler->EmitMarshalArgument(pcsMarshal, pcsUnmarshal, m_paramidx + argOffset, dwMarshalFlags, &m_args);
3214 // Increment a counter so that when the finally clause
3215 // is run, we only run the cleanup that is needed.
3217 if (pMarshaler->NeedsMarshalCleanupIndex())
3219 // we don't bother writing to the counter if marshaling does not need cleanup
3220 psl->EmitSetArgMarshalIndex(pcsMarshal, NDirectStubLinker::CLEANUP_INDEX_ARG0_MARSHAL + m_paramidx + argOffset);
3222 if (pMarshaler->NeedsUnmarshalCleanupIndex())
3224 // we don't bother writing to the counter if unmarshaling does not need exception cleanup
3225 psl->EmitSetArgMarshalIndex(pcsUnmarshal, NDirectStubLinker::CLEANUP_INDEX_ARG0_UNMARSHAL + m_paramidx + argOffset);
3228 pcsMarshal->EmitNOP("// } argument");
3229 pcsUnmarshal->EmitNOP("// } argument");
3231 pMarshaler->EmitSetupArgument(pcsDispatch);
3232 if (m_paramidx == 0)
3234 CorCallingConvention callConv = psl->GetStubTargetCallingConv();
3235 if ((callConv & IMAGE_CEE_CS_CALLCONV_MASK) == IMAGE_CEE_UNMANAGED_CALLCONV_THISCALL)
3237 // Make sure the 'this' argument to thiscall is of native int type; JIT asserts this.
3238 pcsDispatch->EmitCONV_I();
3243 void MarshalInfo::GenerateReturnIL(NDirectStubLinker* psl,
3252 PRECONDITION(CheckPointer(psl));
3256 MarshalerOverrideStatus amostat;
3257 UINT resID = IDS_EE_BADMARSHAL_RESTRICTION;
3259 if (m_type == MARSHAL_TYPE_UNKNOWN)
3261 amostat = HANDLEASNORMAL;
3265 amostat = (GetReturnOverrideProc(m_type)) (psl,
3272 if (amostat == DISALLOWED)
3274 EmitOrThrowInteropParamException(psl, fMngToNative, resID, 0);
3278 if (amostat == HANDLEASNORMAL)
3280 // Historically we have always allowed reading fields that are marshaled as C arrays.
3281 if (m_type == MARSHAL_TYPE_UNKNOWN || (!fieldGetter && m_type == MARSHAL_TYPE_NATIVEARRAY))
3283 EmitOrThrowInteropParamException(psl, fMngToNative, m_resID, 0);
3287 NewHolder<ILMarshaler> pMarshaler = CreateILMarshaler(m_type, psl);
3288 DWORD dwMarshalFlags = CalculateReturnMarshalFlags(retval, fMngToNative);
3290 if (!pMarshaler->SupportsReturnMarshal(dwMarshalFlags, &resID))
3292 EmitOrThrowInteropParamException(psl, fMngToNative, resID, 0);
3296 ILCodeStream* pcsMarshal = psl->GetMarshalCodeStream();
3297 ILCodeStream* pcsUnmarshal = psl->GetReturnUnmarshalCodeStream();
3298 ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream();
3300 pcsMarshal->EmitNOP("// return { ");
3301 pcsUnmarshal->EmitNOP("// return { ");
3303 UINT16 wNativeSize = GetNativeSize(m_type, m_ms);
3305 // The following statement behaviour has existed for a long time. By aligning the size of the return
3306 // value up to stack slot size, we prevent EmitMarshalReturnValue from distinguishing between, say, 3-byte
3307 // structure and 4-byte structure. The former is supposed to be returned by-ref using a secret argument
3308 // (at least in MSVC compiled code) while the latter is returned in EAX. We are keeping the behavior for
3309 // now for backward compatibility.
3310 X86_ONLY(wNativeSize = StackElemSize(wNativeSize));
3312 pMarshaler->EmitMarshalReturnValue(pcsMarshal, pcsUnmarshal, pcsDispatch, m_paramidx + argOffset, wNativeSize, dwMarshalFlags, &m_args);
3314 pcsMarshal->EmitNOP("// } return");
3315 pcsUnmarshal->EmitNOP("// } return");
3321 void MarshalInfo::SetupArgumentSizes()
3333 m_managedArgSize = StackElemSize(sizeof(void*));
3334 m_nativeArgSize = StackElemSize(sizeof(void*));
3338 m_managedArgSize = StackElemSize(GetManagedSize(m_type, m_ms));
3339 m_nativeArgSize = StackElemSize(GetNativeSize(m_type, m_ms));
3342 #ifdef ENREGISTERED_PARAMTYPE_MAXSIZE
3343 if (m_managedArgSize > ENREGISTERED_PARAMTYPE_MAXSIZE)
3344 m_managedArgSize = StackElemSize(sizeof(void*));
3346 if (m_nativeArgSize > ENREGISTERED_PARAMTYPE_MAXSIZE)
3347 m_nativeArgSize = StackElemSize(sizeof(void*));
3348 #endif // ENREGISTERED_PARAMTYPE_MAXSIZE
3351 UINT16 MarshalInfo::GetManagedSize(MarshalType mtype, MarshalScenario ms)
3361 static const BYTE managedSizes[]=
3363 #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::c_CLRSize,
3367 _ASSERTE((SIZE_T)mtype < COUNTOF(managedSizes));
3368 BYTE managedSize = managedSizes[mtype];
3370 if (managedSize == VARIABLESIZE)
3375 case MARSHAL_TYPE_BLITTABLEVALUECLASS:
3376 case MARSHAL_TYPE_VALUECLASS:
3377 #ifdef FEATURE_COMINTEROP
3378 case MARSHAL_TYPE_DATETIME:
3379 case MARSHAL_TYPE_NULLABLE:
3380 case MARSHAL_TYPE_KEYVALUEPAIR:
3381 #endif // FEATURE_COMINTEROP
3382 return (UINT16) m_pMT->GetAlignedNumInstanceFieldBytes();
3393 UINT16 MarshalInfo::GetNativeSize(MarshalType mtype, MarshalScenario ms)
3403 static const BYTE nativeSizes[]=
3405 #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::c_nativeSize,
3409 _ASSERTE((SIZE_T)mtype < COUNTOF(nativeSizes));
3410 BYTE nativeSize = nativeSizes[mtype];
3412 if (nativeSize == VARIABLESIZE)
3416 case MARSHAL_TYPE_BLITTABLEVALUECLASS:
3417 case MARSHAL_TYPE_VALUECLASS:
3418 return (UINT16) m_pMT->GetNativeSize();
3428 bool MarshalInfo::IsInOnly(MarshalType mtype)
3438 static const bool ILMarshalerIsInOnly[] =
3440 #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) \
3441 (IL##mclass::c_fInOnly ? true : false),
3446 return ILMarshalerIsInOnly[mtype];
3449 bool MarshalInfo::IsSupportedForWinRT(MarshalType mtype)
3459 static const bool MarshalerSupportsWinRT[] =
3461 #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) \
3467 return MarshalerSupportsWinRT[mtype];
3470 OVERRIDEPROC MarshalInfo::GetArgumentOverrideProc(MarshalType mtype)
3480 static const OVERRIDEPROC ILArgumentOverrideProcs[] =
3482 #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::ArgumentOverride,
3486 _ASSERTE((SIZE_T)mtype < COUNTOF(ILArgumentOverrideProcs));
3487 return ILArgumentOverrideProcs[mtype];
3490 RETURNOVERRIDEPROC MarshalInfo::GetReturnOverrideProc(MarshalType mtype)
3500 static const RETURNOVERRIDEPROC ILReturnOverrideProcs[] =
3502 #define DEFINE_MARSHALER_TYPE(mt, mclass, fWinRTSupported) IL##mclass::ReturnOverride,
3506 _ASSERTE((SIZE_T)mtype < COUNTOF(ILReturnOverrideProcs));
3507 return ILReturnOverrideProcs[mtype];
3510 void MarshalInfo::GetItfMarshalInfo(ItfMarshalInfo* pInfo)
3512 STANDARD_VM_CONTRACT;
3514 GetItfMarshalInfo(TypeHandle(m_pMT),
3515 #ifdef FEATURE_COMINTEROP
3516 TypeHandle(m_pDefaultItfMT),
3517 #else // FEATURE_COMINTEROP
3519 #endif // FEATURE_COMINTEROP
3526 void MarshalInfo::GetItfMarshalInfo(TypeHandle th, TypeHandle thItf, BOOL fDispItf, BOOL fInspItf, MarshalScenario ms, ItfMarshalInfo *pInfo)
3533 PRECONDITION(CheckPointer(pInfo));
3534 PRECONDITION(!th.IsNull());
3535 PRECONDITION(!th.IsTypeDesc());
3539 #ifdef FEATURE_COMINTEROP
3541 // Initialize the output parameter.
3543 pInfo->thItf = TypeHandle();
3544 pInfo->thClass = TypeHandle();
3546 if (!th.IsInterface())
3548 // If the parameter is not System.Object.
3549 if (!th.IsObjectType())
3551 // Set the class method table.
3552 pInfo->thClass = th;
3554 if (th.IsTypeDesc() || !th.AsMethodTable()->IsWinRTDelegate())
3556 // If this is not a WinRT delegate, retrieve the default interface method table.
3557 TypeHandle hndDefItfClass;
3558 DefaultInterfaceType DefItfType;
3560 if (!thItf.IsNull())
3562 hndDefItfClass = thItf;
3563 DefItfType = DefaultInterfaceType_Explicit;
3565 else if (th.IsProjectedFromWinRT() || th.IsExportedToWinRT())
3567 // WinRT classes use their WinRT default interface
3568 hndDefItfClass = th.GetMethodTable()->GetDefaultWinRTInterface();
3569 DefItfType = DefaultInterfaceType_Explicit;
3573 DefItfType = GetDefaultInterfaceForClassWrapper(th, &hndDefItfClass);
3577 case DefaultInterfaceType_Explicit:
3579 pInfo->thItf = hndDefItfClass;
3580 switch (hndDefItfClass.GetComInterfaceType())
3584 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3588 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3594 case DefaultInterfaceType_AutoDual:
3596 pInfo->thItf = hndDefItfClass;
3597 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3601 case DefaultInterfaceType_IUnknown:
3602 case DefaultInterfaceType_BaseComClass:
3607 case DefaultInterfaceType_AutoDispatch:
3609 pInfo->thItf = hndDefItfClass;
3610 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3616 _ASSERTE(!"Invalid default interface type!");
3624 // The type will be marshalled as an IUnknown, IInspectable, or IDispatch pointer depending
3625 // on the value of fDispItf and fInspItf
3628 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3632 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3635 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_USE_BASIC_ITF;
3640 // IInspectable-based interfaces are simple
3642 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3646 // Determine the interface this type will be marshalled as.
3647 if (th.IsComClassInterface())
3648 pInfo->thItf = th.GetDefItfForComClassItf();
3652 // Determine if we are dealing with an IDispatch, IInspectable, or IUnknown based interface.
3653 switch (pInfo->thItf.GetComInterfaceType())
3657 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3661 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3665 // Look to see if the interface has a coclass defined
3666 pInfo->thClass = th.GetCoClassForInterface();
3667 if (!pInfo->thClass.IsNull())
3669 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_CLASS_IS_HINT;
3673 // store the pre-redirection interface type as thNativeItf
3674 pInfo->thNativeItf = pInfo->thItf;
3676 if (ms == MARSHAL_SCENARIO_WINRT)
3678 // Use the "class is hint" flag so GetObjectRefFromComIP doesn't verify that the
3679 // WinRT object really supports IInspectable - note that we'll do the verification
3680 // in UnmarshalObjectFromInterface for this exact pInfo->thItf.
3681 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_CLASS_IS_HINT;
3683 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_WINRT_SCENARIO;
3685 // Perform interface redirection statically here. When the resulting ItfMarshalInfo
3686 // is used for CLR->WinRT marshaling, this is necessary so we know which COM vtable
3687 // to pass out (for instance IList could be marshaled out as IList or IBindableVector
3688 // depending on the marshal scenario). In the WinRT->CLR direction, it's just an
3689 // optimization which saves us from performing redirection at run-time.
3691 if (!pInfo->thItf.IsNull())
3693 MethodTable *pNewItfMT1;
3694 MethodTable *pNewItfMT2;
3695 switch (RCW::GetInterfacesForQI(pInfo->thItf.GetMethodTable(), &pNewItfMT1, &pNewItfMT2))
3697 case RCW::InterfaceRedirection_None:
3698 case RCW::InterfaceRedirection_UnresolvedIEnumerable:
3701 case RCW::InterfaceRedirection_IEnumerable_RetryOnFailure:
3702 case RCW::InterfaceRedirection_IEnumerable:
3703 case RCW::InterfaceRedirection_Other:
3704 pInfo->thNativeItf = pNewItfMT1;
3707 case RCW::InterfaceRedirection_Other_RetryOnFailure:
3708 pInfo->thNativeItf = pNewItfMT2;
3713 if (!pInfo->thNativeItf.IsNull())
3715 // The native interface is redirected WinRT interface - need to change the flags
3716 _ASSERTE(pInfo->thNativeItf.AsMethodTable()->IsProjectedFromWinRT());
3718 pInfo->dwFlags &= ~ItfMarshalInfo::ITF_MARSHAL_DISP_ITF;
3719 pInfo->dwFlags |= ItfMarshalInfo::ITF_MARSHAL_INSP_ITF;
3723 #else // FEATURE_COMINTEROP
3724 if (!th.IsInterface())
3725 pInfo->thClass = th;
3728 #endif // FEATURE_COMINTEROP
3731 HRESULT MarshalInfo::TryGetItfMarshalInfo(TypeHandle th, BOOL fDispItf, BOOL fInspItf, ItfMarshalInfo *pInfo)
3736 PRECONDITION(!th.IsNull());
3737 PRECONDITION(CheckPointer(pInfo));
3745 GetItfMarshalInfo(th, TypeHandle(), fDispItf, fInspItf,
3746 #ifdef FEATURE_COMINTEROP
3747 MARSHAL_SCENARIO_COMINTEROP,
3748 #else // FEATURE_COMINTEROP
3749 MARSHAL_SCENARIO_NDIRECT,
3750 #endif // FEATURE_COMINTEROP
3755 hr = GET_EXCEPTION()->GetHR();
3757 EX_END_CATCH(RethrowTerminalExceptions);
3763 VOID MarshalInfo::DumpMarshalInfo(Module* pModule, SigPointer sig, const SigTypeContext *pTypeContext, mdToken token,
3764 MarshalScenario ms, CorNativeLinkType nlType, CorNativeLinkFlags nlFlags)
3774 if (LoggingOn(LF_MARSHALER, LL_INFO10))
3777 StackScratchBuffer scratch;
3779 IMDInternalImport *pInternalImport = pModule->GetMDImport();
3781 logbuf.AppendASCII("------------------------------------------------------------\n");
3782 LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch)));
3785 logbuf.AppendASCII("Managed type: ");
3787 logbuf.AppendASCII("Byref ");
3789 TypeHandle th = sig.GetTypeHandleNT(pModule, pTypeContext);
3791 logbuf.AppendASCII("<error>");
3796 logbuf.AppendUTF8(sigfmt.GetCString());
3799 logbuf.AppendASCII("\n");
3800 LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch)));
3803 logbuf.AppendASCII("NativeType : ");
3804 PCCOR_SIGNATURE pvNativeType;
3806 if (token == mdParamDefNil
3807 || pInternalImport->GetFieldMarshal(token,
3809 &cbNativeType) != S_OK)
3811 logbuf.AppendASCII("<absent>");
3816 while (cbNativeType--)
3819 sprintf_s(num, COUNTOF(num), "0x%lx ", (ULONG)*pvNativeType);
3820 logbuf.AppendASCII(num);
3821 switch (*(pvNativeType++))
3823 #define XXXXX(nt) case nt: logbuf.AppendASCII("(" #nt ")"); break;
3825 XXXXX(NATIVE_TYPE_BOOLEAN)
3826 XXXXX(NATIVE_TYPE_I1)
3828 XXXXX(NATIVE_TYPE_U1)
3829 XXXXX(NATIVE_TYPE_I2)
3830 XXXXX(NATIVE_TYPE_U2)
3831 XXXXX(NATIVE_TYPE_I4)
3833 XXXXX(NATIVE_TYPE_U4)
3834 XXXXX(NATIVE_TYPE_I8)
3835 XXXXX(NATIVE_TYPE_U8)
3836 XXXXX(NATIVE_TYPE_R4)
3838 XXXXX(NATIVE_TYPE_R8)
3840 XXXXX(NATIVE_TYPE_LPSTR)
3841 XXXXX(NATIVE_TYPE_LPWSTR)
3842 XXXXX(NATIVE_TYPE_LPTSTR)
3843 XXXXX(NATIVE_TYPE_FIXEDSYSSTRING)
3845 XXXXX(NATIVE_TYPE_STRUCT)
3847 XXXXX(NATIVE_TYPE_INT)
3848 XXXXX(NATIVE_TYPE_FIXEDARRAY)
3850 XXXXX(NATIVE_TYPE_UINT)
3852 XXXXX(NATIVE_TYPE_FUNC)
3854 XXXXX(NATIVE_TYPE_ASANY)
3856 XXXXX(NATIVE_TYPE_ARRAY)
3857 XXXXX(NATIVE_TYPE_LPSTRUCT)
3859 XXXXX(NATIVE_TYPE_IUNKNOWN)
3861 XXXXX(NATIVE_TYPE_BSTR)
3862 #ifdef FEATURE_COMINTEROP
3863 XXXXX(NATIVE_TYPE_TBSTR)
3864 XXXXX(NATIVE_TYPE_ANSIBSTR)
3865 XXXXX(NATIVE_TYPE_HSTRING)
3866 XXXXX(NATIVE_TYPE_BYVALSTR)
3868 XXXXX(NATIVE_TYPE_VARIANTBOOL)
3869 XXXXX(NATIVE_TYPE_SAFEARRAY)
3871 XXXXX(NATIVE_TYPE_IDISPATCH)
3872 XXXXX(NATIVE_TYPE_INTF)
3873 #endif // FEATURE_COMINTEROP
3878 case NATIVE_TYPE_CUSTOMMARSHALER:
3881 logbuf.AppendASCII("(NATIVE_TYPE_CUSTOMMARSHALER)");
3883 // Skip the typelib guid.
3884 logbuf.AppendASCII(" ");
3886 strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType);
3889 BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen);
3890 memcpyNoGCRefs(p, pvNativeType, strLen);
3891 logbuf.CloseBuffer();
3892 logbuf.AppendASCII("\0");
3894 pvNativeType += strLen;
3895 cbNativeType -= strLen + 1;
3897 // Skip the name of the native type.
3898 logbuf.AppendASCII(" ");
3902 strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType);
3905 BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen);
3906 memcpyNoGCRefs(p, pvNativeType, strLen);
3907 logbuf.CloseBuffer();
3908 logbuf.AppendASCII("\0");
3910 pvNativeType += strLen;
3911 cbNativeType -= strLen + 1;
3913 // Extract the name of the custom marshaler.
3914 logbuf.AppendASCII(" ");
3918 strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType);
3921 BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen);
3922 memcpyNoGCRefs(p, pvNativeType, strLen);
3923 logbuf.CloseBuffer();
3924 logbuf.AppendASCII("\0");
3926 pvNativeType += strLen;
3927 cbNativeType -= strLen + 1;
3929 // Extract the cookie string.
3930 logbuf.AppendASCII(" ");
3933 strLen = CPackedLen::GetLength(pvNativeType, (void const **)&pvNativeType);
3936 BYTE* p = (BYTE*)logbuf.OpenANSIBuffer(strLen);
3937 memcpyNoGCRefs(p, pvNativeType, strLen);
3938 logbuf.CloseBuffer();
3939 logbuf.AppendASCII("\0");
3941 pvNativeType += strLen;
3942 cbNativeType -= strLen + 1;
3949 logbuf.AppendASCII("(?)");
3952 logbuf.AppendASCII(" ");
3955 logbuf.AppendASCII("\n");
3956 LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch)));
3959 logbuf.AppendASCII("MarshalType : ");
3962 sprintf_s(num, COUNTOF(num), "0x%lx ", (ULONG)m_type);
3963 logbuf.AppendASCII(num);
3967 #define DEFINE_MARSHALER_TYPE(mt, mc, fWinRTSupported) case mt: logbuf.AppendASCII( #mt " (IL" #mc ")"); break;
3970 case MARSHAL_TYPE_UNKNOWN:
3971 logbuf.AppendASCII("MARSHAL_TYPE_UNKNOWN (illegal combination)");
3975 logbuf.AppendASCII("MARSHAL_TYPE_???");
3979 logbuf.AppendASCII("\n");
3982 logbuf.AppendASCII("Metadata In/Out : ");
3983 if (TypeFromToken(token) != mdtParamDef || token == mdParamDefNil)
3984 logbuf.AppendASCII("<absent>");
3990 LPCSTR szParamName_Ignore;
3991 if (FAILED(pInternalImport->GetParamDefProps(token, &usSequence, &dwAttr, &szParamName_Ignore)))
3993 logbuf.AppendASCII("Invalid ParamDef record ");
3998 logbuf.AppendASCII("In ");
4000 if (IsPdOut(dwAttr))
4001 logbuf.AppendASCII("Out ");
4005 logbuf.AppendASCII("\n");
4007 logbuf.AppendASCII("Effective In/Out : ");
4009 logbuf.AppendASCII("In ");
4012 logbuf.AppendASCII("Out ");
4014 logbuf.AppendASCII("\n");
4016 LOG((LF_MARSHALER, LL_INFO10, logbuf.GetANSI(scratch)));
4019 } // MarshalInfo::DumpMarshalInfo
4022 #ifndef CROSSGEN_COMPILE
4023 #ifdef FEATURE_COMINTEROP
4024 DispParamMarshaler *MarshalInfo::GenerateDispParamMarshaler()
4026 CONTRACT (DispParamMarshaler*)
4031 INJECT_FAULT(COMPlusThrowOM());
4032 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
4036 NewHolder<DispParamMarshaler> pDispParamMarshaler = NULL;
4040 case MARSHAL_TYPE_OLECOLOR:
4041 pDispParamMarshaler = new DispParamOleColorMarshaler();
4044 case MARSHAL_TYPE_CURRENCY:
4045 pDispParamMarshaler = new DispParamCurrencyMarshaler();
4048 case MARSHAL_TYPE_GENERIC_4:
4049 if (m_fErrorNativeType)
4050 pDispParamMarshaler = new DispParamErrorMarshaler();
4053 case MARSHAL_TYPE_INTERFACE:
4055 ItfMarshalInfo itfInfo;
4056 GetItfMarshalInfo(TypeHandle(m_pMT), TypeHandle(m_pDefaultItfMT), m_fDispItf, m_fInspItf, m_ms, &itfInfo);
4057 pDispParamMarshaler = new DispParamInterfaceMarshaler(
4058 itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF,
4059 itfInfo.thItf.GetMethodTable(),
4060 itfInfo.thClass.GetMethodTable(),
4061 itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_CLASS_IS_HINT);
4065 case MARSHAL_TYPE_VALUECLASS:
4066 case MARSHAL_TYPE_BLITTABLEVALUECLASS:
4067 case MARSHAL_TYPE_BLITTABLEPTR:
4068 case MARSHAL_TYPE_LAYOUTCLASSPTR:
4069 pDispParamMarshaler = new DispParamRecordMarshaler(m_pMT);
4072 #ifdef FEATURE_CLASSIC_COMINTEROP
4073 case MARSHAL_TYPE_SAFEARRAY:
4074 pDispParamMarshaler = new DispParamArrayMarshaler(m_arrayElementType, m_hndArrayElemType.GetMethodTable());
4078 case MARSHAL_TYPE_DELEGATE:
4079 pDispParamMarshaler = new DispParamDelegateMarshaler(m_pMT);
4082 case MARSHAL_TYPE_REFERENCECUSTOMMARSHALER:
4083 pDispParamMarshaler = new DispParamCustomMarshaler(m_pCMHelper, m_CMVt);
4087 pDispParamMarshaler.SuppressRelease();
4088 RETURN pDispParamMarshaler;
4092 DispatchWrapperType MarshalInfo::GetDispWrapperType()
4094 STANDARD_VM_CONTRACT;
4096 DispatchWrapperType WrapperType = (DispatchWrapperType)0;
4100 case MARSHAL_TYPE_CURRENCY:
4101 WrapperType = DispatchWrapperType_Currency;
4104 case MARSHAL_TYPE_BSTR:
4105 WrapperType = DispatchWrapperType_BStr;
4108 case MARSHAL_TYPE_GENERIC_4:
4109 if (m_fErrorNativeType)
4110 WrapperType = DispatchWrapperType_Error;
4113 case MARSHAL_TYPE_INTERFACE:
4115 ItfMarshalInfo itfInfo;
4116 GetItfMarshalInfo(TypeHandle(m_pMT), TypeHandle(m_pDefaultItfMT), m_fDispItf, m_fInspItf, m_ms, &itfInfo);
4117 WrapperType = !!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF) ? DispatchWrapperType_Dispatch : DispatchWrapperType_Unknown;
4121 case MARSHAL_TYPE_SAFEARRAY:
4122 switch (m_arrayElementType)
4125 WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_Currency);
4128 WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_Unknown);
4131 WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_Dispatch);
4134 WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_Error);
4137 WrapperType = (DispatchWrapperType)(DispatchWrapperType_SafeArray | DispatchWrapperType_BStr);
4146 #endif // FEATURE_COMINTEROP
4149 VOID MarshalInfo::MarshalTypeToString(SString& strMarshalType, BOOL fSizeIsSpecified)
4161 if (m_type == MARSHAL_TYPE_NATIVEARRAY)
4164 VarTypeToString(m_arrayElementType, strVarType);
4166 if (!fSizeIsSpecified)
4168 strMarshalType.Printf(W("native array of %s (size not specified by a parameter)"),
4169 strVarType.GetUnicode());
4173 strMarshalType.Printf(W("native array of %s (size specified by parameter %i)"),
4174 strVarType.GetUnicode(), m_countParamIdx);
4179 #ifdef FEATURE_COMINTEROP
4180 // Some MarshalTypes have extra information and require special handling
4181 else if (m_type == MARSHAL_TYPE_INTERFACE)
4183 ItfMarshalInfo itfInfo;
4184 GetItfMarshalInfo(TypeHandle(m_pMT), TypeHandle(m_pDefaultItfMT), m_fDispItf, m_fInspItf, m_ms, &itfInfo);
4186 if (!itfInfo.thItf.IsNull())
4188 StackSString ssClassName;
4189 itfInfo.thItf.GetMethodTable()->_GetFullyQualifiedNameForClass(ssClassName);
4191 if (!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF))
4193 strMarshalType.SetLiteral(W("IDispatch "));
4195 else if (!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_INSP_ITF))
4197 strMarshalType.SetLiteral(W("IInspectable"));
4201 strMarshalType.SetLiteral(W("IUnknown "));
4204 if (itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_USE_BASIC_ITF)
4206 strMarshalType.Append(W("(basic) "));
4209 strMarshalType.Append(ssClassName);
4214 if (!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF))
4215 strRetVal = W("IDispatch");
4216 else if (!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_INSP_ITF))
4217 strRetVal = W("IInspectable");
4219 strRetVal = W("IUnknown");
4222 else if (m_type == MARSHAL_TYPE_SAFEARRAY)
4224 StackSString strVarType;
4225 VarTypeToString(m_arrayElementType, strVarType);
4227 strMarshalType = SL(W("SafeArray of "));
4228 strMarshalType.Append(strVarType);
4232 #endif // FEATURE_COMINTEROP
4233 else if (m_type == MARSHAL_TYPE_REFERENCECUSTOMMARSHALER)
4237 OBJECTHANDLE objHandle = m_pCMHelper->GetCustomMarshalerInfo()->GetCustomMarshaler();
4239 OBJECTREF pObjRef = ObjectFromHandle(objHandle);
4240 DefineFullyQualifiedNameForClassW();
4242 strMarshalType.Printf(W("custom marshaler (%s)"),
4243 GetFullyQualifiedNameForClassW(pObjRef->GetMethodTable()));
4250 // All other MarshalTypes with no special handling
4253 case MARSHAL_TYPE_GENERIC_1:
4254 strRetVal = W("BYTE");
4256 case MARSHAL_TYPE_GENERIC_U1:
4257 strRetVal = W("unsigned BYTE");
4259 case MARSHAL_TYPE_GENERIC_2:
4260 strRetVal = W("WORD");
4262 case MARSHAL_TYPE_GENERIC_U2:
4263 strRetVal = W("unsigned WORD");
4265 case MARSHAL_TYPE_GENERIC_4:
4266 strRetVal = W("DWORD");
4268 case MARSHAL_TYPE_GENERIC_8:
4269 strRetVal = W("QUADWORD");
4271 case MARSHAL_TYPE_WINBOOL:
4272 strRetVal = W("Windows Bool");
4274 #ifdef FEATURE_COMINTEROP
4275 case MARSHAL_TYPE_VTBOOL:
4276 strRetVal = W("VARIANT Bool");
4278 #endif // FEATURE_COMINTEROP
4279 case MARSHAL_TYPE_ANSICHAR:
4280 strRetVal = W("Ansi character");
4282 case MARSHAL_TYPE_CBOOL:
4283 strRetVal = W("CBool");
4285 case MARSHAL_TYPE_FLOAT:
4286 strRetVal = W("float");
4288 case MARSHAL_TYPE_DOUBLE:
4289 strRetVal = W("double");
4291 case MARSHAL_TYPE_CURRENCY:
4292 strRetVal = W("CURRENCY");
4294 case MARSHAL_TYPE_DECIMAL:
4295 strRetVal = W("DECIMAL");
4297 case MARSHAL_TYPE_DECIMAL_PTR:
4298 strRetVal = W("DECIMAL pointer");
4300 case MARSHAL_TYPE_GUID:
4301 strRetVal = W("GUID");
4303 case MARSHAL_TYPE_GUID_PTR:
4304 strRetVal = W("GUID pointer");
4306 case MARSHAL_TYPE_DATE:
4307 strRetVal = W("DATE");
4309 case MARSHAL_TYPE_BSTR:
4310 strRetVal = W("BSTR");
4312 case MARSHAL_TYPE_LPWSTR:
4313 strRetVal = W("LPWSTR");
4315 case MARSHAL_TYPE_LPSTR:
4316 strRetVal = W("LPSTR");
4318 case MARSHAL_TYPE_LPUTF8STR:
4319 strRetVal = W("LPUTF8STR");
4321 #ifdef FEATURE_COMINTEROP
4322 case MARSHAL_TYPE_ANSIBSTR:
4323 strRetVal = W("AnsiBStr");
4325 #endif // FEATURE_COMINTEROP
4326 case MARSHAL_TYPE_LPWSTR_BUFFER:
4327 strRetVal = W("LPWSTR buffer");
4329 case MARSHAL_TYPE_LPSTR_BUFFER:
4330 strRetVal = W("LPSTR buffer");
4332 case MARSHAL_TYPE_UTF8_BUFFER:
4333 strRetVal = W("UTF8 buffer");
4335 case MARSHAL_TYPE_ASANYA:
4336 strRetVal = W("AsAnyA");
4338 case MARSHAL_TYPE_ASANYW:
4339 strRetVal = W("AsAnyW");
4341 case MARSHAL_TYPE_DELEGATE:
4342 strRetVal = W("Delegate");
4344 case MARSHAL_TYPE_BLITTABLEPTR:
4345 strRetVal = W("blittable pointer");
4347 #ifdef FEATURE_COMINTEROP
4348 case MARSHAL_TYPE_VBBYVALSTR:
4349 strRetVal = W("VBByValStr");
4351 case MARSHAL_TYPE_VBBYVALSTRW:
4352 strRetVal = W("VBByRefStr");
4354 #endif // FEATURE_COMINTEROP
4355 case MARSHAL_TYPE_LAYOUTCLASSPTR:
4356 strRetVal = W("Layout class pointer");
4358 case MARSHAL_TYPE_ARRAYWITHOFFSET:
4359 strRetVal = W("ArrayWithOffset");
4361 case MARSHAL_TYPE_BLITTABLEVALUECLASS:
4362 strRetVal = W("blittable value class");
4364 case MARSHAL_TYPE_VALUECLASS:
4365 strRetVal = W("value class");
4367 case MARSHAL_TYPE_ARGITERATOR:
4368 strRetVal = W("ArgIterator");
4370 #ifdef FEATURE_COMINTEROP
4371 case MARSHAL_TYPE_OBJECT:
4372 strRetVal = W("VARIANT");
4374 #endif // FEATURE_COMINTEROP
4375 case MARSHAL_TYPE_HANDLEREF:
4376 strRetVal = W("HandleRef");
4378 #ifdef FEATURE_COMINTEROP
4379 case MARSHAL_TYPE_OLECOLOR:
4380 strRetVal = W("OLE_COLOR");
4382 #endif // FEATURE_COMINTEROP
4383 case MARSHAL_TYPE_RUNTIMETYPEHANDLE:
4384 strRetVal = W("RuntimeTypeHandle");
4386 case MARSHAL_TYPE_RUNTIMEFIELDHANDLE:
4387 strRetVal = W("RuntimeFieldHandle");
4389 case MARSHAL_TYPE_RUNTIMEMETHODHANDLE:
4390 strRetVal = W("RuntimeMethodHandle");
4392 case MARSHAL_TYPE_RUNTIMEMETHODINFO:
4393 strRetVal = W("RuntimeMethodInfo");
4395 case MARSHAL_TYPE_RUNTIMEMODULE:
4396 strRetVal = W("RuntimeModule");
4398 case MARSHAL_TYPE_RUNTIMEASSEMBLY:
4399 strRetVal = W("RuntimeAssembly");
4402 strRetVal = W("<UNKNOWN>");
4407 strMarshalType.Set(strRetVal);
4411 VOID MarshalInfo::VarTypeToString(VARTYPE vt, SString& strVarType)
4427 strRetVal = W("2-byte signed int");
4430 strRetVal = W("4-byte signed int");
4433 strRetVal = W("4-byte real");
4436 strRetVal = W("8-byte real");
4439 strRetVal = W("currency");
4442 strRetVal = W("date");
4445 strRetVal = W("binary string");
4448 strRetVal = W("IDispatch *");
4451 strRetVal = W("Scode");
4454 strRetVal = W("boolean");
4457 strRetVal = W("VARIANT *");
4460 strRetVal = W("IUnknown *");
4463 strRetVal = W("16-byte fixed point");
4466 strRetVal = W("user defined structure");
4469 strRetVal = W("signed char");
4472 strRetVal = W("unsigned char");
4475 strRetVal = W("unsigned short");
4478 strRetVal = W("unsigned short");
4481 strRetVal = W("signed int");
4484 strRetVal = W("unsigned int");
4487 strRetVal = W("LPSTR");
4490 strRetVal = W("LPWSTR");
4493 strRetVal = W("HResult");
4496 strRetVal = W("8-byte signed int");
4499 strRetVal = W("null");
4502 strRetVal = W("8-byte unsigned int");
4505 strRetVal = W("void");
4507 case VTHACK_WINBOOL:
4508 strRetVal = W("boolean");
4510 case VTHACK_ANSICHAR:
4511 strRetVal = W("char");
4514 strRetVal = W("1-byte C bool");
4517 strRetVal = W("unknown");
4521 strVarType.Set(strRetVal);
4525 #endif // CROSSGEN_COMPILE
4527 // Returns true if the marshaler represented by this instance requires COM to have been started.
4528 bool MarshalInfo::MarshalerRequiresCOM()
4530 LIMITED_METHOD_CONTRACT;
4532 #ifdef FEATURE_COMINTEROP
4535 case MARSHAL_TYPE_REFERENCECUSTOMMARSHALER:
4537 case MARSHAL_TYPE_BSTR:
4538 case MARSHAL_TYPE_ANSIBSTR:
4539 case MARSHAL_TYPE_OBJECT:
4540 case MARSHAL_TYPE_OLECOLOR:
4541 case MARSHAL_TYPE_SAFEARRAY:
4542 case MARSHAL_TYPE_INTERFACE:
4544 case MARSHAL_TYPE_URI:
4545 case MARSHAL_TYPE_KEYVALUEPAIR:
4546 case MARSHAL_TYPE_NULLABLE:
4547 case MARSHAL_TYPE_SYSTEMTYPE:
4548 case MARSHAL_TYPE_EXCEPTION:
4549 case MARSHAL_TYPE_HIDDENLENGTHARRAY:
4550 case MARSHAL_TYPE_HSTRING:
4551 case MARSHAL_TYPE_NCCEVENTARGS:
4552 case MARSHAL_TYPE_PCEVENTARGS:
4554 // some of these types do not strictly require COM for the actual marshaling
4555 // but they tend to be used in COM context so we keep the logic we had in
4556 // previous versions and return true here
4560 case MARSHAL_TYPE_LAYOUTCLASSPTR:
4561 case MARSHAL_TYPE_VALUECLASS:
4563 // pessimistic guess, but in line with previous versions
4567 case MARSHAL_TYPE_NATIVEARRAY:
4569 return (m_arrayElementType == VT_UNKNOWN ||
4570 m_arrayElementType == VT_DISPATCH ||
4571 m_arrayElementType == VT_VARIANT);
4574 #endif // FEATURE_COMINTEROP
4579 #ifdef FEATURE_COMINTEROP
4580 MarshalInfo::MarshalType MarshalInfo::GetHiddenLengthParamMarshalType()
4582 LIMITED_METHOD_CONTRACT;
4583 return MARSHAL_TYPE_GENERIC_U4;
4586 CorElementType MarshalInfo::GetHiddenLengthParamElementType()
4588 LIMITED_METHOD_CONTRACT;
4589 return ELEMENT_TYPE_U4;
4592 UINT16 MarshalInfo::GetHiddenLengthParamStackSize()
4594 LIMITED_METHOD_CONTRACT;
4595 return StackElemSize(GetNativeSize(GetHiddenLengthParamMarshalType(), m_ms));
4598 void MarshalInfo::MarshalHiddenLengthArgument(NDirectStubLinker *psl, BOOL managedToNative, BOOL isForReturnArray)
4603 PRECONDITION(CheckPointer(psl));
4604 PRECONDITION(m_type == MARSHAL_TYPE_HIDDENLENGTHARRAY);
4605 PRECONDITION(m_dwHiddenLengthManagedHomeLocal == 0xFFFFFFFF);
4606 PRECONDITION(m_dwHiddenLengthNativeHomeLocal == 0xFFFFFFFF);
4610 NewHolder<ILMarshaler> pHiddenLengthMarshaler = CreateILMarshaler(GetHiddenLengthParamMarshalType(), psl);
4613 ILCodeStream *pcsMarshal = psl->GetMarshalCodeStream();
4614 ILCodeStream *pcsUnmarshal = psl->GetUnmarshalCodeStream();
4616 pcsMarshal->EmitNOP("// hidden length argument { ");
4617 pcsUnmarshal->EmitNOP("// hidden length argument { ");
4619 DWORD dwMarshalFlags = MARSHAL_FLAG_HIDDENLENPARAM;
4620 if (isForReturnArray)
4622 // This is a hidden length argument for an [out, retval] argument, so setup flags to match that
4623 dwMarshalFlags |= CalculateArgumentMarshalFlags(TRUE, FALSE, TRUE, managedToNative);
4627 // The length parameter needs to be an [in] parameter if the array itself is an [in] parameter.
4628 // Additionally, in order to support the FillArray pattern:
4629 // FillArray([in] UInt32 length, [out, size_is(length)] ElementType* value)
4631 // We need to make sure that the length parameter is [in] if the array pointer is not byref, since
4632 // this means that the caller is allocating the array. This includes array buffers which are [out]
4633 // but not byref, since the [out] marshaling applies to the array contents but not the array pointer
4635 BOOL marshalHiddenLengthIn = m_in || !m_byref;
4636 dwMarshalFlags |= CalculateArgumentMarshalFlags(m_byref, marshalHiddenLengthIn, m_out, managedToNative);
4638 pHiddenLengthMarshaler->EmitMarshalHiddenLengthArgument(pcsMarshal,
4643 HiddenLengthParamIndex(),
4645 &m_dwHiddenLengthManagedHomeLocal,
4646 &m_dwHiddenLengthNativeHomeLocal);
4648 pcsMarshal->EmitNOP("// } hidden length argument");
4649 pcsUnmarshal->EmitNOP("// } hidden length argument");
4651 // Only emit into the dispatch stream for CLR -> Native cases - in the reverse, there is no argument
4652 // to pass to the managed method. Instead, the length is encoded in the marshaled array.
4653 if (managedToNative)
4655 ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream();
4656 pHiddenLengthMarshaler->EmitSetupArgument(pcsDispatch);
4660 #endif // FEATURE_COMINTEROP
4662 #define ReportInvalidArrayMarshalInfo(resId) \
4665 m_vtElement = VT_EMPTY; \
4666 m_errorResourceId = resId; \
4667 m_thElement = TypeHandle(); \
4672 void ArrayMarshalInfo::InitForNativeArray(MarshalInfo::MarshalScenario ms, TypeHandle thElement, CorNativeType ntElement, BOOL isAnsi)
4674 WRAPPER_NO_CONTRACT;
4675 InitElementInfo(NATIVE_TYPE_ARRAY, ms, thElement, ntElement, isAnsi);
4678 void ArrayMarshalInfo::InitForFixedArray(TypeHandle thElement, CorNativeType ntElement, BOOL isAnsi)
4680 WRAPPER_NO_CONTRACT;
4681 InitElementInfo(NATIVE_TYPE_FIXEDARRAY, MarshalInfo::MARSHAL_SCENARIO_FIELD, thElement, ntElement, isAnsi);
4684 #ifdef FEATURE_COMINTEROP
4685 void ArrayMarshalInfo::InitForSafeArray(MarshalInfo::MarshalScenario ms, TypeHandle thElement, VARTYPE vtElement, BOOL isAnsi)
4687 STANDARD_VM_CONTRACT;
4689 InitElementInfo(NATIVE_TYPE_SAFEARRAY, ms, thElement, NATIVE_TYPE_DEFAULT, isAnsi);
4691 if (IsValid() && vtElement != VT_EMPTY)
4693 if (vtElement == VT_USERDEFINED)
4695 // If the user explicitly sets the VARTYPE to VT_USERDEFINED, we simply ignore it
4696 // since the exporter will take care of transforming the vt to VT_USERDEFINED and the
4697 // marshallers needs the actual type.
4701 m_flags = (ArrayMarshalInfoFlags)(m_flags | amiSafeArraySubTypeExplicitlySpecified);
4702 m_vtElement = vtElement;
4707 void ArrayMarshalInfo::InitForHiddenLengthArray(TypeHandle thElement)
4709 STANDARD_VM_CONTRACT;
4711 MethodTable *pMT = NULL;
4713 // WinRT supports arrays of any WinRT-legal types
4714 if (thElement.IsArray())
4716 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_NESTEDARRAY);
4718 else if (thElement.IsTypeDesc() || !thElement.GetMethodTable()->IsLegalNonArrayWinRTType())
4720 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE);
4723 m_thElement = thElement;
4725 pMT = thElement.GetMethodTable();
4726 if (pMT->IsString())
4728 m_vtElement = VTHACK_HSTRING;
4729 m_cbElementSize = sizeof(HSTRING);
4731 else if (WinRTTypeNameConverter::ResolveRedirectedType(pMT, &m_redirectedTypeIndex))
4733 m_vtElement = VTHACK_REDIRECTEDTYPE;
4735 switch (m_redirectedTypeIndex)
4737 case WinMDAdapter::RedirectedTypeIndex_System_DateTimeOffset:
4738 m_cbElementSize = ILDateTimeMarshaler::c_nativeSize;
4741 case WinMDAdapter::RedirectedTypeIndex_System_Type:
4742 m_cbElementSize = ILSystemTypeMarshaler::c_nativeSize;
4745 case WinMDAdapter::RedirectedTypeIndex_System_Exception:
4746 m_cbElementSize = ILHResultExceptionMarshaler::c_nativeSize;
4749 // WinRT delegates are IUnknown pointers
4750 case WinMDAdapter::RedirectedTypeIndex_System_EventHandlerGeneric:
4751 m_vtElement = VTHACK_INSPECTABLE;
4752 m_cbElementSize = sizeof(IUnknown*);
4755 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Generic_KeyValuePair:
4756 case WinMDAdapter::RedirectedTypeIndex_System_Nullable:
4757 case WinMDAdapter::RedirectedTypeIndex_System_Uri:
4758 case WinMDAdapter::RedirectedTypeIndex_System_Collections_Specialized_NotifyCollectionChangedEventArgs:
4759 case WinMDAdapter::RedirectedTypeIndex_System_ComponentModel_PropertyChangedEventArgs:
4761 m_cbElementSize = sizeof(IInspectable *);
4767 if (pMT->IsValueType())
4769 // other redirected structs are blittable and don't need special marshaling
4770 m_vtElement = VTHACK_BLITTABLERECORD;
4771 m_cbElementSize = pMT->GetNativeSize();
4775 // redirected interfaces should be treated as interface pointers
4776 _ASSERTE(pMT->IsInterface());
4777 m_vtElement = VTHACK_INSPECTABLE;
4778 m_cbElementSize = sizeof(IInspectable *);
4784 else if (pMT->IsBlittable() || pMT->IsTruePrimitive() || pMT->IsEnum())
4786 m_vtElement = VTHACK_BLITTABLERECORD;
4788 CorElementType elemType = pMT->GetInternalCorElementType();
4789 if (CorTypeInfo::IsPrimitiveType(elemType))
4791 // .NET and WinRT primitives have the same size
4792 m_cbElementSize = CorTypeInfo::Size(elemType);
4796 m_cbElementSize = pMT->GetNativeSize();
4799 else if (pMT->IsValueType())
4801 m_vtElement = VTHACK_NONBLITTABLERECORD;
4802 m_cbElementSize = pMT->GetNativeSize();
4806 m_vtElement = VTHACK_INSPECTABLE;
4807 m_cbElementSize = sizeof(IInspectable *);
4812 #endif // FEATURE_COMINTEROP
4814 void ArrayMarshalInfo::InitElementInfo(CorNativeType arrayNativeType, MarshalInfo::MarshalScenario ms, TypeHandle thElement, CorNativeType ntElement, BOOL isAnsi)
4819 PRECONDITION(!thElement.IsNull());
4820 POSTCONDITION(!IsValid() || !m_thElement.IsNull());
4824 CorElementType etElement = ELEMENT_TYPE_END;
4827 // IMPORTANT: The error resource IDs used in this function must not contain any placeholders!
4829 // Also please maintain the standard of using IDS_EE_BADMARSHAL_XXX when defining new error
4830 // message resource IDs.
4833 if (thElement.IsArray())
4834 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_NESTEDARRAY);
4836 m_thElement = thElement;
4838 if (m_thElement.IsPointer())
4840 m_flags = (ArrayMarshalInfoFlags)(m_flags | amiIsPtr);
4841 m_thElement = ((ParamTypeDesc*)m_thElement.AsTypeDesc())->GetModifiedType();
4844 etElement = m_thElement.GetSignatureCorElementType();
4846 if (IsAMIPtr(m_flags) && (etElement > ELEMENT_TYPE_R8))
4848 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_UNSUPPORTED_SIG);
4851 if (etElement == ELEMENT_TYPE_CHAR)
4855 case NATIVE_TYPE_I1: //fallthru
4856 case NATIVE_TYPE_U1:
4857 m_vtElement = VTHACK_ANSICHAR;
4860 case NATIVE_TYPE_I2: //fallthru
4861 case NATIVE_TYPE_U2:
4862 m_vtElement = VT_UI2;
4865 // Compat: If the native type doesn't make sense, we need to ignore it and not report an error.
4866 case NATIVE_TYPE_DEFAULT: //fallthru
4868 #ifdef FEATURE_COMINTEROP
4869 if (ms == MarshalInfo::MARSHAL_SCENARIO_COMINTEROP)
4870 m_vtElement = VT_UI2;
4872 #endif // FEATURE_COMINTEROP
4873 m_vtElement = isAnsi ? VTHACK_ANSICHAR : VT_UI2;
4876 else if (etElement == ELEMENT_TYPE_BOOLEAN)
4880 case NATIVE_TYPE_BOOLEAN:
4881 m_vtElement = VTHACK_WINBOOL;
4884 #ifdef FEATURE_COMINTEROP
4885 case NATIVE_TYPE_VARIANTBOOL:
4886 m_vtElement = VT_BOOL;
4888 #endif // FEATURE_COMINTEROP
4890 case NATIVE_TYPE_I1 :
4891 case NATIVE_TYPE_U1 :
4892 m_vtElement = VTHACK_CBOOL;
4895 // Compat: if the native type doesn't make sense, we need to ignore it and not report an error.
4896 case NATIVE_TYPE_DEFAULT: //fallthru
4898 #ifdef FEATURE_COMINTEROP
4899 if (ms == MarshalInfo::MARSHAL_SCENARIO_COMINTEROP ||
4900 arrayNativeType == NATIVE_TYPE_SAFEARRAY)
4902 m_vtElement = VT_BOOL;
4905 #endif // FEATURE_COMINTEROP
4907 m_vtElement = VTHACK_WINBOOL;
4912 else if (etElement == ELEMENT_TYPE_I)
4914 m_vtElement = static_cast<VARTYPE>((GetPointerSize() == 4) ? VT_I4 : VT_I8);
4916 else if (etElement == ELEMENT_TYPE_U)
4918 m_vtElement = static_cast<VARTYPE>((GetPointerSize() == 4) ? VT_UI4 : VT_UI8);
4920 else if (etElement <= ELEMENT_TYPE_R8)
4922 static const BYTE map [] =
4924 VT_NULL, // ELEMENT_TYPE_END
4925 VT_VOID, // ELEMENT_TYPE_VOID
4926 VT_NULL, // ELEMENT_TYPE_BOOLEAN
4927 VT_NULL, // ELEMENT_TYPE_CHAR
4928 VT_I1, // ELEMENT_TYPE_I1
4929 VT_UI1, // ELEMENT_TYPE_U1
4930 VT_I2, // ELEMENT_TYPE_I2
4931 VT_UI2, // ELEMENT_TYPE_U2
4932 VT_I4, // ELEMENT_TYPE_I4
4933 VT_UI4, // ELEMENT_TYPE_U4
4934 VT_I8, // ELEMENT_TYPE_I8
4935 VT_UI8, // ELEMENT_TYPE_U8
4936 VT_R4, // ELEMENT_TYPE_R4
4937 VT_R8 // ELEMENT_TYPE_R8
4941 _ASSERTE(map[etElement] != VT_NULL);
4942 m_vtElement = map[etElement];
4946 if (m_thElement == TypeHandle(g_pStringClass))
4950 case NATIVE_TYPE_DEFAULT:
4951 #ifdef FEATURE_COMINTEROP
4952 if (arrayNativeType == NATIVE_TYPE_SAFEARRAY || ms == MarshalInfo::MARSHAL_SCENARIO_COMINTEROP)
4954 m_vtElement = VT_BSTR;
4957 #endif // FEATURE_COMINTEROP
4959 m_vtElement = static_cast<VARTYPE>(isAnsi ? VT_LPSTR : VT_LPWSTR);
4962 case NATIVE_TYPE_BSTR:
4963 m_vtElement = VT_BSTR;
4965 case NATIVE_TYPE_LPSTR:
4966 m_vtElement = VT_LPSTR;
4968 case NATIVE_TYPE_LPWSTR:
4969 m_vtElement = VT_LPWSTR;
4971 case NATIVE_TYPE_LPTSTR:
4973 #ifdef FEATURE_COMINTEROP
4974 if (ms == MarshalInfo::MARSHAL_SCENARIO_COMINTEROP || IsAMIExport(m_flags))
4976 // We disallow NATIVE_TYPE_LPTSTR for COM or if we are exporting.
4977 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHALPARAM_NO_LPTSTR);
4980 #endif // FEATURE_COMINTEROP
4982 // We no longer support Win9x so LPTSTR always maps to a Unicode string.
4983 m_vtElement = VT_LPWSTR;
4989 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_STRINGARRAY);
4992 else if (m_thElement == TypeHandle(g_pObjectClass))
4994 #ifdef FEATURE_COMINTEROP
4997 case NATIVE_TYPE_DEFAULT:
4998 if (ms == MarshalInfo::MARSHAL_SCENARIO_FIELD)
4999 m_vtElement = VT_UNKNOWN;
5001 m_vtElement = VT_VARIANT;
5004 case NATIVE_TYPE_STRUCT:
5005 m_vtElement = VT_VARIANT;
5008 case NATIVE_TYPE_INTF:
5009 case NATIVE_TYPE_IUNKNOWN:
5010 m_vtElement = VT_UNKNOWN;
5013 case NATIVE_TYPE_IDISPATCH:
5014 m_vtElement = VT_DISPATCH;
5018 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_OBJECTARRAY);
5021 #else // FEATURE_COMINTEROP
5024 case NATIVE_TYPE_IUNKNOWN:
5025 m_vtElement = VT_UNKNOWN;
5029 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_UNSUPPORTED_SIG);
5031 #endif // FEATURE_COMINTEROP
5033 else if (m_thElement.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__SAFE_HANDLE))))
5035 // Array's of SAFEHANDLEs are not supported.
5036 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_SAFEHANDLEARRAY);
5038 else if (m_thElement.CanCastTo(TypeHandle(MscorlibBinder::GetClass(CLASS__CRITICAL_HANDLE))))
5040 // Array's of CRITICALHANDLEs are not supported.
5041 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_CRITICALHANDLEARRAY);
5043 else if (etElement == ELEMENT_TYPE_VALUETYPE)
5045 if (m_thElement == TypeHandle(MscorlibBinder::GetClass(CLASS__DATE_TIME)))
5047 if (ntElement == NATIVE_TYPE_STRUCT || ntElement == NATIVE_TYPE_DEFAULT)
5048 m_vtElement = VT_DATE;
5050 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_DATETIMEARRAY);
5052 else if (m_thElement == TypeHandle(MscorlibBinder::GetClass(CLASS__DECIMAL)))
5054 if (ntElement == NATIVE_TYPE_STRUCT || ntElement == NATIVE_TYPE_DEFAULT)
5055 m_vtElement = VT_DECIMAL;
5056 #ifdef FEATURE_COMINTEROP
5057 else if (ntElement == NATIVE_TYPE_CURRENCY)
5058 m_vtElement = VT_CY;
5059 #endif // FEATURE_COMINTEROP
5061 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_DECIMALARRAY);
5065 // When exporting, we need to handle enums specially.
5066 if (IsAMIExport(m_flags) && m_thElement.IsEnum())
5068 // Get the element type of the underlying type.
5069 CorElementType et = m_thElement.GetInternalCorElementType();
5071 // If it is not a 32-bit type, convert as the underlying type.
5072 if ((et == ELEMENT_TYPE_I4) || (et == ELEMENT_TYPE_U4))
5073 m_vtElement = VT_RECORD;
5075 m_vtElement = OleVariant::GetVarTypeForTypeHandle(m_thElement);
5079 m_vtElement = OleVariant::GetVarTypeForTypeHandle(m_thElement);
5083 #ifdef FEATURE_COMINTEROP
5084 else if (m_thElement == TypeHandle(MscorlibBinder::GetClass(CLASS__ERROR_WRAPPER)))
5086 m_vtElement = VT_ERROR;
5091 #ifdef FEATURE_COMINTEROP
5093 // Compat: Even if the classes have layout, we still convert them to interface pointers.
5095 ItfMarshalInfo itfInfo;
5096 MarshalInfo::GetItfMarshalInfo(m_thElement, TypeHandle(), FALSE, FALSE, ms, &itfInfo);
5098 // Compat: We must always do VT_UNKNOWN marshaling for parameters, even if the interface is marked late-bound.
5099 if (ms == MarshalInfo::MARSHAL_SCENARIO_FIELD)
5100 m_vtElement = static_cast<VARTYPE>(!!(itfInfo.dwFlags & ItfMarshalInfo::ITF_MARSHAL_DISP_ITF) ? VT_DISPATCH : VT_UNKNOWN);
5102 m_vtElement = VT_UNKNOWN;
5104 m_thElement = itfInfo.thItf.IsNull() ? TypeHandle(g_pObjectClass) : itfInfo.thItf;
5105 m_thInterfaceArrayElementClass = itfInfo.thClass;
5107 #else // FEATURE_COMINTEROP
5108 ReportInvalidArrayMarshalInfo(IDS_EE_BADMARSHAL_UNSUPPORTED_SIG);
5109 #endif // FEATURE_COMINTEROP
5113 // Avoid throwing exceptions for any managed structs that have layouts and have types of fields that gets default to those banned types by default
5114 // 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
5115 if (AppX::IsAppXProcess() && ms != MarshalInfo::MARSHAL_SCENARIO_FIELD)
5117 bool set_error = false;
5119 switch (m_vtElement)
5122 m_resID = IDS_EE_BADMARSHAL_TYPE_IDISPATCH ;
5127 COMPlusThrow(kPlatformNotSupportedException, m_resID);
5130 // If we are exporting, we need to substitute the VTHACK_* VARTYPE with the actual
5131 // types as expressed in the type library.
5132 if (IsAMIExport(m_flags))
5134 if (m_vtElement == VTHACK_ANSICHAR)
5135 m_vtElement = VT_UI1;
5136 else if (m_vtElement == VTHACK_WINBOOL)
5137 m_vtElement = VT_I4;
5138 else if (m_vtElement == VTHACK_CBOOL)
5139 m_vtElement = VT_UI1;
5147 bool IsUnsupportedValueTypeReturn(MetaSig& msig)
5157 CorElementType type = msig.GetReturnTypeNormalized();
5159 if (type == ELEMENT_TYPE_VALUETYPE || type == ELEMENT_TYPE_TYPEDBYREF)
5162 // On x86, the internal CorElementType for value types is normalized by the type loader
5163 // (see calls to ComputeInternalCorElementTypeForValueType in MethodTableBuilder).
5164 // We don't need to redo the normalization here.
5167 TypeHandle th = msig.GetRetTypeHandleThrowing();
5169 return EEClass::ComputeInternalCorElementTypeForValueType(th.GetMethodTable()) == ELEMENT_TYPE_VALUETYPE;
5170 #endif // _TARGET_X86_
5176 #ifndef CROSSGEN_COMPILE
5178 #include "stubhelpers.h"
5179 FCIMPL3(void*, StubHelpers::CreateCustomMarshalerHelper,
5182 TypeHandle hndManagedType)
5186 CustomMarshalerHelper* pCMHelper = NULL;
5188 HELPER_METHOD_FRAME_BEGIN_RET_0();
5190 Module* pModule = pMD->GetModule();
5191 Assembly* pAssembly = pModule->GetAssembly();
5194 #ifdef FEATURE_COMINTEROP
5195 if (!hndManagedType.IsTypeDesc() &&
5196 IsTypeRefOrDef(g_CollectionsEnumeratorClassName, hndManagedType.GetModule(), hndManagedType.GetCl()))
5198 pCMHelper = SetupCustomMarshalerHelper(ENUMERATOR_TO_ENUM_VARIANT_CM_NAME,
5199 ENUMERATOR_TO_ENUM_VARIANT_CM_NAME_LEN,
5200 ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE,
5201 ENUMERATOR_TO_ENUM_VARIANT_CM_COOKIE_LEN,
5202 pAssembly, hndManagedType);
5205 #endif // FEATURE_COMINTEROP
5208 // Retrieve the native type for the current parameter.
5212 NativeTypeParamInfo ParamInfo;
5213 result = ParseNativeTypeInfo(paramToken, pModule->GetMDImport(), &ParamInfo);
5216 // this should all have been done at stub creation time
5218 CONSISTENCY_CHECK(result != 0);
5219 CONSISTENCY_CHECK(ParamInfo.m_NativeType == NATIVE_TYPE_CUSTOMMARSHALER);
5221 // Set up the custom marshaler info.
5222 pCMHelper = SetupCustomMarshalerHelper(ParamInfo.m_strCMMarshalerTypeName,
5223 ParamInfo.m_cCMMarshalerTypeNameBytes,
5224 ParamInfo.m_strCMCookie,
5225 ParamInfo.m_cCMCookieStrBytes,
5230 HELPER_METHOD_FRAME_END();
5232 return (void*)pCMHelper;
5236 #endif // CROSSGEN_COMPILE