-
Jun 29th, 2022, 03:45 AM
#1
Thread Starter
Addicted Member
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.
-
Jun 29th, 2022, 03:55 AM
#2
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
-
Jun 29th, 2022, 04:12 AM
#3
Re: How to convert this C style UNION in a UDT to VB ?
yup, you will just have to interpret the data manually later
-
Jun 29th, 2022, 05:56 AM
#4
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.
-
Jun 29th, 2022, 07:27 AM
#5
Thread Starter
Addicted Member
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.
-
Jun 29th, 2022, 07:35 AM
#6
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
-
Jun 29th, 2022, 07:39 AM
#7
Thread Starter
Addicted Member
Re: How to convert this C style UNION in a UDT to VB ?
Originally Posted by dz32
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.
-
Jun 29th, 2022, 07:52 AM
#8
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.
-
Jun 29th, 2022, 08:28 AM
#9
Thread Starter
Addicted Member
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.
-
Jun 29th, 2022, 08:33 AM
#10
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.
-
Jun 29th, 2022, 09:02 AM
#11
Thread Starter
Addicted Member
Re: How to convert this C style UNION in a UDT to VB ?
Originally Posted by dz32
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|