1
- using System . Runtime . InteropServices . ComTypes ;
1
+ using System ;
2
+ using System . Runtime . InteropServices . ComTypes ;
2
3
3
- namespace Rubberduck . JunkDrawer . Hacks
4
+ namespace Rubberduck . VBEditor . ComManagement . TypeLibs . Utility
4
5
{
5
6
public static class VarDescExtensions
6
7
{
@@ -16,13 +17,22 @@ public static class VarDescExtensions
16
17
///
17
18
/// There is a small but non-zero chance that there might be a valid pointer that happens to be only in high half of the address...
18
19
/// in that case, it'll be wrong but since VBA is always writing <see cref="VARKIND.VAR_STATIC"/> to the <see cref="VARDESC.varkind"/>
19
- /// field, we're kind of stuck...
20
+ /// field. To accommodate this unlikely possibility, we take advantage of VBA's other failure to comply with MS-OAUT specifications:
21
+ /// None of its constants has a valid member ID. Normally they are assigned <c>MEMBER_NIL</c> which makes them useless for enumeration. To
22
+ /// accommodate this, the TypeInfoWrapper in Rubberduck.VBEditor project will generate unique member IDs for those constants. Thus, we can use
23
+ /// the same range to infer that it's a constant assigned by the TypeInfoWrapper.
20
24
/// </remarks>
21
25
/// <param name="varDesc">The <see cref="VARDESC"/> from a VBA <see cref="ITypeInfo"/></param>
22
26
/// <returns>True if this is most likely a constant. False when it's definitely not.</returns>
23
27
public static bool IsValidVBAConstant ( this VARDESC varDesc )
24
28
{
25
- return varDesc . varkind == VARKIND . VAR_STATIC && varDesc . desc . oInst != 0 ;
29
+ // TODO: Move the function to a better home and avoid duplication of constants (see TypeInfoWrapper)
30
+ const int _ourConstantsDispatchMemberIDRangeStart = unchecked ( ( int ) 0xFEDC0000 ) ;
31
+ const int _ourConstantsDispatchMemberIDRangeBitmaskCheck = unchecked ( ( int ) 0xFFFF0000 ) ;
32
+
33
+ return ( varDesc . memid & _ourConstantsDispatchMemberIDRangeBitmaskCheck ) >= _ourConstantsDispatchMemberIDRangeStart
34
+ && varDesc . varkind == VARKIND . VAR_STATIC
35
+ && varDesc . desc . lpvarValue != IntPtr . Zero ;
26
36
}
27
37
}
28
38
}
0 commit comments