Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[VisualBasic] Fix TypeName for COM objects #40584

Merged
merged 12 commits into from
Aug 11, 2020
6 changes: 6 additions & 0 deletions src/libraries/Microsoft.VisualBasic.Core/src/ILLinkTrim.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<linker>
<assembly fullname="Microsoft.VisualBasic.Core">
<!-- Required for type querying via IDispatch -->
<type fullname="Microsoft.VisualBasic.CompilerServices.UnsafeNativeMethods/*"/>
ehasis marked this conversation as resolved.
Show resolved Hide resolved
</assembly>
</linker>
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,10 @@ GetSpecialValue:
End Function

Friend Shared Function VBFriendlyName(ByVal typ As System.Type, ByVal o As Object) As String
If typ.IsCOMObject AndAlso (typ.FullName = "System.__ComObject") Then
Return TypeNameOfCOMObject(o, False)
End If

Return VBFriendlyNameOfType(typ)
End Function

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,15 @@ Namespace Microsoft.VisualBasic.CompilerServices
End If

typ = Expression.GetType()
#If TARGET_WINDOWS Then
If (typ.IsCOMObject AndAlso (System.String.CompareOrdinal(typ.Name, COMObjectName) = 0)) Then
Result = TypeNameOfCOMObject(Expression, True)
Else
Result = VBFriendlyNameOfType(typ)
End If
#Else
Result = VBFriendlyNameOfType(typ)
#End If
Return Result
End Function

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,249 @@ Namespace Microsoft.VisualBasic.CompilerServices
Friend Shared Function GetLogicalDrives() As Integer
End Function

Public Const LCID_US_ENGLISH As Integer = &H409

<System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)>
Public Enum tagSYSKIND
SYS_WIN16 = 0
SYS_MAC = 2
End Enum

' REVIEW : - c# version was class, does it make a difference?
' [StructLayout(LayoutKind.Sequential)]
' Public class tagTLIBATTR {
<System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)>
Public Structure tagTLIBATTR
Public guid As Guid
Public lcid As Integer
Public syskind As tagSYSKIND
<MarshalAs(UnmanagedType.U2)> Public wMajorVerNum As Short
<MarshalAs(UnmanagedType.U2)> Public wMinorVerNum As Short
<MarshalAs(UnmanagedType.U2)> Public wLibFlags As Short
End Structure

<System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never),
ComImport(),
Guid("00020403-0000-0000-C000-000000000046"),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)>
Public Interface ITypeComp

<Obsolete("Bad signature. Fix and verify signature before use.", True)>
Sub RemoteBind(
<[In](), MarshalAs(UnmanagedType.LPWStr)> ByVal szName As String,
<[In](), MarshalAs(UnmanagedType.U4)> ByVal lHashVal As Integer,
<[In](), MarshalAs(UnmanagedType.U2)> ByVal wFlags As Short,
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal ppTInfo As ITypeInfo(),
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal pDescKind As ComTypes.DESCKIND(),
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal ppFuncDesc As ComTypes.FUNCDESC(),
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal ppVarDesc As ComTypes.VARDESC(),
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal ppTypeComp As ITypeComp(),
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal pDummy As Integer())

Sub RemoteBindType(
<[In](), MarshalAs(UnmanagedType.LPWStr)> ByVal szName As String,
<[In](), MarshalAs(UnmanagedType.U4)> ByVal lHashVal As Integer,
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal ppTInfo As ITypeInfo())
End Interface

<System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never),
ComImport(),
Guid("00020400-0000-0000-C000-000000000046"),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)>
Public Interface IDispatch

<Obsolete("Bad signature. Fix and verify signature before use.", True)>
<PreserveSig()>
Function GetTypeInfoCount() As Integer

<PreserveSig()>
Function GetTypeInfo(
<[In]()> ByVal index As Integer,
<[In]()> ByVal lcid As Integer,
<[Out](), MarshalAs(UnmanagedType.Interface)> ByRef pTypeInfo As ITypeInfo) As Integer

' WARNING : - This api NOT COMPLETELY DEFINED, DO NOT CALL!
<PreserveSig()>
Function GetIDsOfNames() As Integer

' WARNING : - This api NOT COMPLETELY DEFINED, DO NOT CALL!
<PreserveSig()>
Function Invoke() As Integer
End Interface

<System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never),
ComImport(),
Guid("00020401-0000-0000-C000-000000000046"),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)>
Public Interface ITypeInfo
<PreserveSig()>
Function GetTypeAttr(
<Out()> ByRef pTypeAttr As IntPtr) As Integer

<PreserveSig()>
Function GetTypeComp(
<Out()> ByRef pTComp As ITypeComp) As Integer


<PreserveSig()>
Function GetFuncDesc(
<[In](), MarshalAs(UnmanagedType.U4)> ByVal index As Integer,
<Out()> ByRef pFuncDesc As IntPtr) As Integer

<PreserveSig()>
Function GetVarDesc(
<[In](), MarshalAs(UnmanagedType.U4)> ByVal index As Integer,
<Out()> ByRef pVarDesc As IntPtr) As Integer

<PreserveSig()>
Function GetNames(
<[In]()> ByVal memid As Integer,
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal rgBstrNames As String(),
<[In](), MarshalAs(UnmanagedType.U4)> ByVal cMaxNames As Integer,
<Out(), MarshalAs(UnmanagedType.U4)> ByRef cNames As Integer) As Integer

<Obsolete("Bad signature, second param type should be Byref. Fix and verify signature before use.", True)>
<PreserveSig()>
Function GetRefTypeOfImplType(
<[In](), MarshalAs(UnmanagedType.U4)> ByVal index As Integer,
<Out()> ByRef pRefType As Integer) As Integer

<Obsolete("Bad signature, second param type should be Byref. Fix and verify signature before use.", True)>
<PreserveSig()>
Function GetImplTypeFlags(
<[In](), MarshalAs(UnmanagedType.U4)> ByVal index As Integer,
<Out()> ByVal pImplTypeFlags As Integer) As Integer

<PreserveSig()>
Function GetIDsOfNames(
<[In]()> ByVal rgszNames As IntPtr,
<[In](), MarshalAs(UnmanagedType.U4)> ByVal cNames As Integer,
<Out()> ByRef pMemId As IntPtr) As Integer

<Obsolete("Bad signature. Fix and verify signature before use.", True)>
<PreserveSig()>
Function Invoke() As Integer

<PreserveSig()>
Function GetDocumentation(
<[In]()> ByVal memid As Integer,
<Out(), MarshalAs(UnmanagedType.BStr)> ByRef pBstrName As String,
<Out(), MarshalAs(UnmanagedType.BStr)> ByRef pBstrDocString As String,
<Out(), MarshalAs(UnmanagedType.U4)> ByRef pdwHelpContext As Integer,
<Out(), MarshalAs(UnmanagedType.BStr)> ByRef pBstrHelpFile As String) As Integer

<Obsolete("Bad signature. Fix and verify signature before use.", True)>
<PreserveSig()>
Function GetDllEntry(
<[In]()> ByVal memid As Integer,
<[In]()> ByVal invkind As ComTypes.INVOKEKIND,
<Out(), MarshalAs(UnmanagedType.BStr)> ByVal pBstrDllName As String,
<Out(), MarshalAs(UnmanagedType.BStr)> ByVal pBstrName As String,
<Out(), MarshalAs(UnmanagedType.U2)> ByVal pwOrdinal As Short) As Integer

<PreserveSig()>
Function GetRefTypeInfo(
<[In]()> ByVal hreftype As IntPtr,
<Out()> ByRef pTypeInfo As ITypeInfo) As Integer

<Obsolete("Bad signature. Fix and verify signature before use.", True)>
<PreserveSig()>
Function AddressOfMember() As Integer

<Obsolete("Bad signature. Fix and verify signature before use.", True)>
<PreserveSig()>
Function CreateInstance(
<[In]()> ByRef pUnkOuter As IntPtr,
<[In]()> ByRef riid As Guid,
<Out(), MarshalAs(UnmanagedType.IUnknown)> ByVal ppvObj As Object) As Integer

<Obsolete("Bad signature. Fix and verify signature before use.", True)>
<PreserveSig()>
Function GetMops(
<[In]()> ByVal memid As Integer,
<Out(), MarshalAs(UnmanagedType.BStr)> ByVal pBstrMops As String) As Integer

<PreserveSig()>
Function GetContainingTypeLib(
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal ppTLib As ITypeLib(),
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal pIndex As Integer()) As Integer

<PreserveSig()>
Sub ReleaseTypeAttr(ByVal typeAttr As IntPtr)

<PreserveSig()>
Sub ReleaseFuncDesc(ByVal funcDesc As IntPtr)

<PreserveSig()>
Sub ReleaseVarDesc(ByVal varDesc As IntPtr)
End Interface

<System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never),
ComImport(),
Guid("B196B283-BAB4-101A-B69C-00AA00341D07"),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)>
Public Interface IProvideClassInfo
Function GetClassInfo() As <MarshalAs(UnmanagedType.Interface)> ITypeInfo
End Interface

<System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never),
ComImport(),
Guid("00020402-0000-0000-C000-000000000046"),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)>
Public Interface ITypeLib
<Obsolete("Bad signature. Fix and verify signature before use.", True)>
Sub RemoteGetTypeInfoCount(
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal pcTInfo As Integer())

Sub GetTypeInfo(
<[In](), MarshalAs(UnmanagedType.U4)> ByVal index As Integer,
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal ppTInfo As ITypeInfo())

Sub GetTypeInfoType(
<[In](), MarshalAs(UnmanagedType.U4)> ByVal index As Integer,
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal pTKind As ComTypes.TYPEKIND())

Sub GetTypeInfoOfGuid(
<[In]()> ByRef guid As Guid,
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal ppTInfo As ITypeInfo())

<Obsolete("Bad signature. Fix and verify signature before use.", True)>
Sub RemoteGetLibAttr(
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal ppTLibAttr As tagTLIBATTR(),
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal pDummy As Integer())

Sub GetTypeComp(
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal ppTComp As ITypeComp())

<Obsolete("Bad signature. Fix and verify signature before use.", True)>
Sub RemoteGetDocumentation(
ByVal index As Integer,
<[In](), MarshalAs(UnmanagedType.U4)> ByVal refPtrFlags As Integer,
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal pBstrName As String(),
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal pBstrDocString As String(),
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal pdwHelpContext As Integer(),
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal pBstrHelpFile As String())

<Obsolete("Bad signature. Fix and verify signature before use.", True)>
Sub RemoteIsName(
<[In](), MarshalAs(UnmanagedType.LPWStr)> ByVal szNameBuf As String,
<[In](), MarshalAs(UnmanagedType.U4)> ByVal lHashVal As Integer,
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal pfName As IntPtr(),
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal pBstrLibName As String())

<Obsolete("Bad signature. Fix and verify signature before use.", True)>
Sub RemoteFindName(
<[In](), MarshalAs(UnmanagedType.LPWStr)> ByVal szNameBuf As String,
<[In](), MarshalAs(UnmanagedType.U4)> ByVal lHashVal As Integer,
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal ppTInfo As ITypeInfo(),
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal rgMemId As Integer(),
<[In](), Out(), MarshalAs(UnmanagedType.LPArray)> ByVal pcFound As Short(),
<Out(), MarshalAs(UnmanagedType.LPArray)> ByVal pBstrLibName As String())

<Obsolete("Bad signature. Fix and verify signature before use.", True)>
Sub LocalReleaseTLibAttr()
End Interface

''' <summary>
''' Frees memory allocated from the local heap. i.e. frees memory allocated
''' by LocalAlloc or LocalReAlloc.n
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,64 @@ Namespace Microsoft.VisualBasic

End Function

Friend Function TypeNameOfCOMObject(ByVal VarName As Object, ByVal bThrowException As Boolean) As String

Dim Result As String = COMObjectName

#If TARGET_WINDOWS Then
Dim pTypeInfo As UnsafeNativeMethods.ITypeInfo = Nothing
Dim hr As Integer
Dim ClassName As String = Nothing
Dim DocString As String = Nothing
Dim HelpContext As Integer
Dim HelpFile As String = Nothing


Do
Dim pProvideClassInfo As UnsafeNativeMethods.IProvideClassInfo = TryCast(VarName, UnsafeNativeMethods.IProvideClassInfo)

If pProvideClassInfo IsNot Nothing Then
Try
pTypeInfo = pProvideClassInfo.GetClassInfo()
hr = pTypeInfo.GetDocumentation(-1, ClassName, DocString, HelpContext, HelpFile)
If hr >= 0 Then
Result = ClassName
Exit Do
End If
pTypeInfo = Nothing
Catch ex As StackOverflowException
Throw ex
Catch ex As OutOfMemoryException
Throw ex
Catch
'Ignore the error
End Try
End If

Dim pDispatch As UnsafeNativeMethods.IDispatch = TryCast(VarName, UnsafeNativeMethods.IDispatch)

If pDispatch IsNot Nothing Then
' Try using IDispatch
hr = pDispatch.GetTypeInfo(0, UnsafeNativeMethods.LCID_US_ENGLISH, pTypeInfo)
If hr >= 0 Then
hr = pTypeInfo.GetDocumentation(-1, ClassName, DocString, HelpContext, HelpFile)
If hr >= 0 Then
Result = ClassName
Exit Do
End If
End If
End If

Loop While (False)
#End If


If Result.Chars(0) = "_"c Then
Result = Result.Substring(1)
End If

Return Result
End Function

Public Function QBColor(ByVal Color As Integer) As Integer
If (Color And &HFFF0I) <> 0 Then
Expand Down Expand Up @@ -498,6 +556,27 @@ UnmangleName:

Dim Result As String = COMObjectName

#If TARGET_WINDOWS Then
Dim pTypeInfo As UnsafeNativeMethods.ITypeInfo = Nothing
Dim hr As Integer
Dim ClassName As String = Nothing
Dim DocString As String = Nothing
Dim HelpContext As Integer
Dim HelpFile As String = Nothing

Dim pDispatch As UnsafeNativeMethods.IDispatch = TryCast(VarName, UnsafeNativeMethods.IDispatch)

If pDispatch IsNot Nothing Then
hr = pDispatch.GetTypeInfo(0, UnsafeNativeMethods.LCID_US_ENGLISH, pTypeInfo)
If hr >= 0 Then
hr = pTypeInfo.GetDocumentation(-1, ClassName, DocString, HelpContext, HelpFile)
If hr >= 0 Then
Result = ClassName
End If
End If
End If
#End If

If Result.Chars(0) = "_"c Then
Result = Result.Substring(1)
End If
Expand Down
Loading