summaryrefslogtreecommitdiff
path: root/src/utilcode/tlbutils.cpp
diff options
context:
space:
mode:
authordotnet-bot <dotnet-bot@microsoft.com>2015-01-30 14:14:42 -0800
committerdotnet-bot <dotnet-bot@microsoft.com>2015-01-30 14:14:42 -0800
commitef1e2ab328087c61a6878c1e84f4fc5d710aebce (patch)
treedee1bbb89e9d722e16b0d1485e3cdd1b6c8e2cfa /src/utilcode/tlbutils.cpp
downloadcoreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.gz
coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.tar.bz2
coreclr-ef1e2ab328087c61a6878c1e84f4fc5d710aebce.zip
Initial commit to populate CoreCLR repo
[tfs-changeset: 1407945]
Diffstat (limited to 'src/utilcode/tlbutils.cpp')
-rw-r--r--src/utilcode/tlbutils.cpp222
1 files changed, 222 insertions, 0 deletions
diff --git a/src/utilcode/tlbutils.cpp b/src/utilcode/tlbutils.cpp
new file mode 100644
index 0000000000..88906bac64
--- /dev/null
+++ b/src/utilcode/tlbutils.cpp
@@ -0,0 +1,222 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+//
+
+//
+// Utilities used to help manipulating typelibs.
+
+#include "stdafx.h" // Precompiled header key.
+
+#include "tlbutils.h"
+#include "dispex.h"
+#include "posterror.h"
+#include "ndpversion.h"
+
+#define CUSTOM_MARSHALER_ASM ", CustomMarshalers, Version=" VER_ASSEMBLYVERSION_STR ", Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
+
+static const LPCWSTR DLL_EXTENSION = {W(".dll")};
+static const int DLL_EXTENSION_LEN = 4;
+static const LPCWSTR EXE_EXTENSION = {W(".exe")};
+static const int EXE_EXTENSION_LEN = 4;
+
+const StdConvertibleItfInfo aStdConvertibleInterfaces[] =
+{
+ { "System.Runtime.InteropServices.Expando.IExpando", (GUID*)&IID_IDispatchEx,
+ "System.Runtime.InteropServices.CustomMarshalers.ExpandoToDispatchExMarshaler" CUSTOM_MARSHALER_ASM, "IExpando" },
+
+ { "System.Reflection.IReflect", (GUID*)&IID_IDispatchEx,
+ "System.Runtime.InteropServices.CustomMarshalers.ExpandoToDispatchExMarshaler" CUSTOM_MARSHALER_ASM, "IReflect" },
+
+ { "System.Collections.IEnumerator", (GUID*)&IID_IEnumVARIANT,
+ "System.Runtime.InteropServices.CustomMarshalers.EnumeratorToEnumVariantMarshaler" CUSTOM_MARSHALER_ASM, "" },
+
+ { "System.Type", (GUID*)&IID_ITypeInfo,
+ "System.Runtime.InteropServices.CustomMarshalers.TypeToTypeInfoMarshaler" CUSTOM_MARSHALER_ASM, "" },
+};
+
+// This method returns the custom marshaler info to convert the native interface
+// to its managed equivalent. Or null if the interface is not a standard convertible interface.
+const StdConvertibleItfInfo *GetConvertionInfoFromNativeIID(REFGUID rGuidNativeItf)
+{
+ CONTRACT (const StdConvertibleItfInfo*)
+ {
+ NOTHROW;
+ POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
+ }
+ CONTRACT_END;
+
+ // Look in the table of interfaces that have standard convertions to see if the
+ // specified interface is there.
+ for (int i = 0; i < sizeof(aStdConvertibleInterfaces) / sizeof(StdConvertibleItfInfo); i++)
+ {
+ if (IsEqualGUID(rGuidNativeItf, *(aStdConvertibleInterfaces[i].m_pNativeTypeIID)))
+ RETURN &aStdConvertibleInterfaces[i];
+ }
+
+ // The interface is not in the table.
+ RETURN NULL;
+}
+
+//*****************************************************************************
+// Given a typelib, determine the managed namespace name.
+//*****************************************************************************
+HRESULT GetNamespaceNameForTypeLib( // S_OK or error.
+ ITypeLib *pITLB, // [IN] The TypeLib.
+ BSTR *pwzNamespace) // [OUT] Put the namespace name here.
+{
+ CONTRACTL
+ {
+ DISABLED(NOTHROW); // PostError goes down a throwing path right now. Revisit this when fixed.
+ PRECONDITION(CheckPointer(pITLB));
+ PRECONDITION(CheckPointer(pwzNamespace));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK; // A result.
+ ITypeLib2 *pITLB2=0; //For getting custom value.
+ TLIBATTR *pAttr=0; // Typelib attributes.
+ BSTR szPath=0; // Typelib path.
+
+ // If custom attribute for namespace exists, use it.
+ if (pITLB->QueryInterface(IID_ITypeLib2, (void **)&pITLB2) == S_OK)
+ {
+ VARIANT vt;
+ VariantInit(&vt);
+ if (pITLB2->GetCustData(GUID_ManagedName, &vt) == S_OK)
+ {
+ if (V_VT(&vt) == VT_BSTR)
+ {
+ // If the namespace ends with .dll then remove the extension.
+ LPWSTR pDest = wcsstr(vt.bstrVal, DLL_EXTENSION);
+ if (pDest && (pDest[DLL_EXTENSION_LEN] == 0 || pDest[DLL_EXTENSION_LEN] == ' '))
+ *pDest = 0;
+
+ if (!pDest)
+ {
+ // If the namespace ends with .exe then remove the extension.
+ pDest = wcsstr(vt.bstrVal, EXE_EXTENSION);
+ if (pDest && (pDest[EXE_EXTENSION_LEN] == 0 || pDest[EXE_EXTENSION_LEN] == ' '))
+ *pDest = 0;
+ }
+
+ if (pDest)
+ {
+ // We removed the extension so re-allocate a string of the new length.
+ *pwzNamespace = SysAllocString(vt.bstrVal);
+ SysFreeString(vt.bstrVal);
+ }
+ else
+ {
+ // There was no extension to remove so we can use the string returned
+ // by GetCustData().
+ *pwzNamespace = vt.bstrVal;
+ }
+
+ goto ErrExit;
+ }
+ else
+ {
+ VariantClear(&vt);
+ }
+ }
+ }
+
+ // No custom attribute, use library name.
+ IfFailGo(pITLB->GetDocumentation(MEMBERID_NIL, pwzNamespace, 0, 0, 0));
+
+ErrExit:
+ if (szPath)
+ ::SysFreeString(szPath);
+ if (pAttr)
+ pITLB->ReleaseTLibAttr(pAttr);
+ if (pITLB2)
+ pITLB2->Release();
+
+ return hr;
+} // HRESULT GetNamespaceNameForTypeLib()
+
+//*****************************************************************************
+// Given an ITypeInfo, determine the managed name. Optionally supply a default
+// namespace, otherwise derive namespace from containing typelib.
+//*****************************************************************************
+HRESULT GetManagedNameForTypeInfo( // S_OK or error.
+ ITypeInfo *pITI, // [IN] The TypeInfo.
+ LPCWSTR wzNamespace, // [IN, OPTIONAL] Default namespace name.
+ LPCWSTR wzAsmName, // [IN, OPTIONAL] Assembly name.
+ BSTR *pwzName) // [OUT] Put the name here.
+{
+ CONTRACTL
+ {
+ DISABLED(NOTHROW);
+ PRECONDITION(CheckPointer(pITI));
+ PRECONDITION(CheckPointer(wzNamespace, NULL_OK));
+ PRECONDITION(CheckPointer(wzAsmName, NULL_OK));
+ PRECONDITION(CheckPointer(pwzName));
+ }
+ CONTRACTL_END;
+
+ HRESULT hr = S_OK; // A result.
+ ITypeInfo2 *pITI2=0; // For getting custom value.
+ ITypeLib *pITLB=0; // Containing typelib.
+
+ BSTR bstrName=0; // Typeinfo's name.
+ BSTR bstrNamespace=0; // Typelib's namespace.
+ int cchFullyQualifiedName; // Size of namespace + name buffer.
+ int cchAsmName=0; // The size of the assembly name.
+ int cchAsmQualifiedName=0; // The size of the assembly qualified name buffer.
+ CQuickArray<WCHAR> qbFullyQualifiedName; // The fully qualified type name.
+
+ // Check for a custom value with name.
+ if (pITI->QueryInterface(IID_ITypeInfo2, (void **)&pITI2) == S_OK)
+ {
+ VARIANT vt; // For getting custom value.
+ ::VariantInit(&vt);
+ if (pITI2->GetCustData(GUID_ManagedName, &vt) == S_OK && vt.vt == VT_BSTR)
+ { // There is a custom value with the name. Just believe it.
+ *pwzName = vt.bstrVal;
+ vt.bstrVal = 0;
+ vt.vt = VT_EMPTY;
+ goto ErrExit;
+ }
+ }
+
+ // Still need name, get the namespace.
+ if (wzNamespace == 0)
+ {
+ IfFailGo(pITI->GetContainingTypeLib(&pITLB, 0));
+ IfFailGo(GetNamespaceNameForTypeLib(pITLB, &bstrNamespace));
+ wzNamespace = bstrNamespace;
+ }
+
+ // Get the name, and combine with namespace.
+ IfFailGo(pITI->GetDocumentation(MEMBERID_NIL, &bstrName, 0,0,0));
+ cchFullyQualifiedName = (int)(wcslen(bstrName) + wcslen(wzNamespace) + 1);
+ IfFailGo(qbFullyQualifiedName.ReSizeNoThrow(cchFullyQualifiedName + 1));
+ ns::MakePath(qbFullyQualifiedName.Ptr(), cchFullyQualifiedName + 1, wzNamespace, bstrName);
+
+ // If the assembly name is specified, then add it to the type name.
+ if (wzAsmName)
+ {
+ cchAsmName = (int)wcslen(wzAsmName);
+ cchAsmQualifiedName = cchFullyQualifiedName + cchAsmName + 3;
+ IfNullGo(*pwzName = ::SysAllocStringLen(0, cchAsmQualifiedName));
+ ns::MakeAssemblyQualifiedName(*pwzName, cchAsmQualifiedName, qbFullyQualifiedName.Ptr(), cchFullyQualifiedName, wzAsmName, cchAsmName);
+ }
+ else
+ {
+ IfNullGo(*pwzName = ::SysAllocStringLen(qbFullyQualifiedName.Ptr(), cchFullyQualifiedName));
+ }
+
+ErrExit:
+ if (bstrName)
+ ::SysFreeString(bstrName);
+ if (bstrNamespace)
+ ::SysFreeString(bstrNamespace);
+ if (pITLB)
+ pITLB->Release();
+ if (pITI2)
+ pITI2->Release();
+
+ return (hr);
+} // HRESULT GetManagedNameForTypeInfo()