Results 1 to 11 of 11

Thread: How to convert this C style UNION in a UDT to VB ?

  1. #1

    Thread Starter
    Addicted Member
    Join Date
    Jun 2022
    Posts
    239

    How to convert this C style UNION in a UDT to VB ?

    https://docs.microsoft.com/en-us/win...-oaidl-vardesc

    Code:
    'typedef struct tagVARDESC {
    '  MEMBERID memid;
    '  LPOLESTR lpstrSchema;
    '  union {
    '    ULONG   oInst;
    '    VARIANT *lpvarValue;
    '  } DUMMYUNIONNAME;
    '  ELEMDESC elemdescVar;
    '  WORD     wVarFlags;
    '  VARKIND  varkind;
    '} VARDESC, *LPVARDESC;
    I have tried LSET to simulate the C union but it doesn't work with lpvarValue because it is of VARIANT type.

    Any ideas ? Thanks.

  2. #2
    PowerPoster Zvoni's Avatar
    Join Date
    Sep 2012
    Location
    To the moon and then left
    Posts
    4,418

    Re: How to convert this C style UNION in a UDT to VB ?

    Both Members are 4 Bytes long, oInst = unsigned Integer 32-Bit, *lpvarValue = Pointer to Something

    so
    UnionMember As Long
    Last edited by Zvoni; Tomorrow at 31:69 PM.
    ----------------------------------------------------------------------------------------

    One System to rule them all, One Code to find them,
    One IDE to bring them all, and to the Framework bind them,
    in the Land of Redmond, where the Windows lie
    ---------------------------------------------------------------------------------
    People call me crazy because i'm jumping out of perfectly fine airplanes.
    ---------------------------------------------------------------------------------
    Code is like a joke: If you have to explain it, it's bad

  3. #3
    Frenzied Member
    Join Date
    Jun 2015
    Posts
    1,055

    Re: How to convert this C style UNION in a UDT to VB ?

    yup, you will just have to interpret the data manually later

  4. #4
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,598

    Re: How to convert this C style UNION in a UDT to VB ?

    Unions are just a convenient way to perform casting or even aliasing. Whenever you encounter a union, just translate it to a single UDT field with the size of the largest member of the union.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

  5. #5

    Thread Starter
    Addicted Member
    Join Date
    Jun 2022
    Posts
    239

    Re: How to convert this C style UNION in a UDT to VB ?

    Code:
    Private Type MyType
        oInst As Long
        lpvarValue As LongLong
    End Type
    
    Private Type VARDESC
        memid As Long
        #If Win64 Then
            lpstrSchema As LongLong
        #Else
            lpstrSchema As Long
        #End If
        UnionMember As LongLong
        elemdescVar As Long
        wVarFlags As Long
        varkind As Long
    End Type
    Code:
        Dim X As MyType
        
       Call CopyMemory(X, ByVal tVARDESC.UnionMember, Len(X))
       Debug.Print X.lpvarValue & vbTab & rgBstrNames(0)
    The above returns correct values for positive Enums in the lpvarValue Member but returns incorrect values for negative Enums.
    Seems the UNSIGNED ULONG in oInst Member is causing the problem.

    Note : Code is running in x64bit hence the LongLong Type (8 bytes)
    Any ideas ?
    Last edited by AngelV; Jun 29th, 2022 at 07:36 AM.

  6. #6
    Frenzied Member
    Join Date
    Jun 2015
    Posts
    1,055

    Re: How to convert this C style UNION in a UDT to VB ?

    this is incorrect

    Code:
    '  union {
    '    ULONG   oInst;
    '    VARIANT *lpvarValue;
    '  } DUMMYUNIONNAME;
    
    Private Type MyType
        oInst As Long
        lpvarValue As LongLong
    End Type
    a union just means the data at this offset can be interpreted as either ULONG or VARIANT* so you can access the same data in different ways
    depending on what was returned in the structure. it is not two independent fields

  7. #7

    Thread Starter
    Addicted Member
    Join Date
    Jun 2022
    Posts
    239

    Re: How to convert this C style UNION in a UDT to VB ?

    Quote Originally Posted by dz32 View Post
    this is incorrect

    Code:
    '  union {
    '    ULONG   oInst;
    '    VARIANT *lpvarValue;
    '  } DUMMYUNIONNAME;
    
    Private Type MyType
        oInst As Long
        lpvarValue As LongLong
    End Type
    a union just means the data at this offset can be interpreted as either ULONG or VARIANT* so you can access the same data in different ways
    depending on what was returned in the structure. it is not two independent fields
    Sorry, I am not sure I understand. Are you saying I shouldn't use the separate MyType UDT ?
    If so, how would I go about it ?

    Thanks.

  8. #8
    Frenzied Member
    Join Date
    Jun 2015
    Posts
    1,055

    Re: How to convert this C style UNION in a UDT to VB ?

    from a quick google, ULONG is 32bit in both 32/64 process
    pointers like Variant* will be 4 bytes/8 bytes in 32/64 process

    if you are expecting oInst, you want the first? 4 bytes from the DUMMYUNIONNAME offset
    (in a 64bit process I am not sure if it will be the hi 32bits or the low 32bits you will have to test)

    if you want to read the data as Variant* then in a 32bit process you would read the same 4 bytes
    which is now interpreted as a memory address, then read the data at that memory address as the variant structure itself

    in a 64 bit process, the Variant* will be a 8 byte address to dereference.

    Copy the whole structure to a byte buffer and do a hexdump on it to the immediate window or text editor
    so you can visualize it. You could also create a C test DLL with your own expected data to make sure they interoperate
    as you expect. You could also use a native debugger like olly or x64dbg to view memory using varptr(myUdt) as the address to view
    Last edited by dz32; Jun 29th, 2022 at 08:08 AM.

  9. #9

    Thread Starter
    Addicted Member
    Join Date
    Jun 2022
    Posts
    239

    Re: How to convert this C style UNION in a UDT to VB ?

    Code:
    'typedef struct tagVARDESC {
    '  MEMBERID memid;
    '  LPOLESTR lpstrSchema;
    '  union {
    '    ULONG   oInst;
    '    VARIANT *lpvarValue;
    '  } DUMMYUNIONNAME;
    '  ELEMDESC elemdescVar;
    '  WORD     wVarFlags;
    '  VARKIND  varkind;
    '} VARDESC, *LPVARDESC;
    
    
    Private Type LARGE_INT
        LowPart As Long
        HighPart As Long
    End Type
        
    Private Type MyType
        oInst As Long
        #If Win64 Then
            lpvarValue As LongLong
        #Else
            lpvarValue As Long
        #End If
    End Type
    
    Private Type VARDESC
        memid As Long
        #If Win64 Then
            lpstrSchema As LongLong
            DUMMYUNIONNAME As LongLong
        #Else
            lpstrSchema As Long
            DUMMYUNIONNAME As Long
        #End If
        elemdescVar As Long
        wVarFlags As Long
        varkind As Long
    End Type
    Code:
    Const PTR_SIZE As Long = 8
    
    Dim tDUMMYUNIONNAME As MyType
    
    Call CopyMemory(tDUMMYUNIONNAME, ByVal tVARDESC.DUMMYUNIONNAME, Len(tDUMMYUNIONNAME))
    
    Dim udtLI As LARGE_INT
    
    Call CopyMemory(ByVal udtLI, tDUMMYUNIONNAME.lpvarValue, PTR_SIZE)
    
    Debug.Print (udtLI.LowPart) & vbTab & rgBstrNames(0)   'SUCCESS
    Finally, fetching the value in the low 32bit order worked correctly for positive as well as for negative Enums.

    Thanks everyone.

  10. #10
    Frenzied Member
    Join Date
    Jun 2015
    Posts
    1,055

    Re: How to convert this C style UNION in a UDT to VB ?

    glad you got it. this is one way you can watch it:

    Code:
    #include <stdio.h>
    #include <windows.h>
    #include <conio.h>
    #include <cstddef>
    
    int main()
    {
    
        printf("sizeof(VARDESC) = %d\n\n", sizeof(VARDESC));
        VARDESC v;
        v.memid = 0x11223344;
        v.lpstrSchema = (LPOLESTR)0x55667788;
        v.oInst = 0x99AABBCC;
    
        printf("offset of oInst = 0x%x   lpvarValue=0x%x \n", offsetof(VARDESC, oInst), offsetof(VARDESC, lpvarValue));
    
        unsigned char b[sizeof(VARDESC)];
        memcpy(&b, &v, sizeof(VARDESC));
    
        for (int i = 0; i < sizeof(VARDESC); i++) {
            printf("%x ", b[i]);
        }
    
        printf("\n\nAny key to exit...");
        _getch();
    
    
    }
    sample output
    Code:
    32bit: 
    sizeof(VARDESC) = 36
    offset of oInst = 0x8   lpvarValue=0x8
    44 33 22 11 88 77 66 55 cc bb aa 99 cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc
    
    64bit: 
    sizeof(VARDESC) = 64
    offset of oInst = 0x10   lpvarValue=0x10
    44 33 22 11 cc cc cc cc 88 77 66 55 0 0 0 0 cc bb aa 99 cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc
    Last edited by dz32; Jun 29th, 2022 at 08:36 AM.

  11. #11

    Thread Starter
    Addicted Member
    Join Date
    Jun 2022
    Posts
    239

    Re: How to convert this C style UNION in a UDT to VB ?

    Quote Originally Posted by dz32 View Post
    glad you got it. this is one way you can watch it:
    Thanks dz32 for taking the time to help.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width