UGN Security

Converting C datatypes to VB's

Posted By: SilentRage

Converting C datatypes to VB's - 09/25/02 10:55 PM

NOTE: Some of the content of this tutorial assumes you know how pointers work in VB. This is covered by my tutorial "Tips & Tricks - Visual Basic and Pointers"

We're living in a C++ world with C++ documentation all over the place. Unfortunately, references for VB syntax for calling API's and their structures and constants are hard to find with the exception of - but even they have stopped updating.

So what do you do if you can't find the VB syntax for some API or structure? Well, you gotta use the only thing that's out there. C documenation.

But first, we need to know the VB datatypes really well. So here's the important ones.

Byte = 1 byte unsigned number (0 to 255)
Integer = 2 byte signed number (-32768 to 32767)
Boolean = 2 bytes. (-1 TRUE, 0 FALSE)
Long = 4 byte signed number (-2147483648 to 2147483647)
Single = 4 byte signed number
Double = 8 byte signed number

Now here's some common C datatypes

BYTE = 1 byte unsigned number
USHORT = 2 byte unsigned number
SHORT = 2 byte signed number
UINT = 4 byte unsigned number
INT = 4 byte signed number (on 32-bit systems)
BOOL = 4 byte signed number (on 32-bit systems)

now keep in mind that in a 32-bit system, you're going to have 32-bit handles and mostly 32-bit numbers in your API functions and structures. So the LONG datatype will be the most common. For instance, all the below types are 4 byte numbers. A VB long type works fine.


Alright, with the above in mind. Let's convert a function from C to VB syntax. Let's say we wanna create a window with CreateWindowEx. goto See the 'Search For' text box? Type 'CreateWindowEx' in there and press Enter. You'll get several results. The first 3 entries look good. Let's choose the top one.

Before we get into the conversion process, start the API functon line and we'll add to it as we go.

Declare Function CreateWindowEx Lib "" () As something

Scrolling down the the bottom of the page, we see that is says we need to import user32.lib. That's the clue we needed to know what dll the function is stored in. Add that in.

Declare Function CreateWindowEx Lib "user32.dll" () As something

The second thing is to be sure we have the correct name. You see, many functions in windows has a ANSI and UNICODE version. ANSI is where each character takes 1 byte. And in UNICODE each character takes 2 bytes. WIDE is another name for UNICODE. So we need to make sure the function isn't REALLY called CreateWindowExA (for ANSI) or CreateWindowExW (for WIDE).

There's 2 ways to be sure. 1, this MSDN page says there's a ANSI and WIDE version. 2, you can open user32.dll in wordpad and do a string search for CreateWindowEx. You'll see if it'll require a W or A. All function names can be looked at in a dll like this.

Well, now I want to use the ANSI version, so I format my declare line like this.

Declare Function CreateWindowEx Lib "user32.dll" Alias "CreateWindowExA" () As something

An alias is the TRUE name contained in the dll. CreateWindowEx is what we'll be using in our code.

HWND CreateWindowEx(
DWORD dwExStyle,
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam

woof, what a mess. Let's take this line by line. The first line says "HWND CreateWindowEx(". That means CreateWindowEx returns a HWND datatype. We know this to be a LONG 4 byte number. So instead of 'As something', you put 'as long'

Declare Function CreateWindowEx Lib "user32.dll" Alias "CreateWindowExA" () As Long

DWORD dwExStyle; = dwExStyle As Long
DWORD dwStyle, = dwStyle As Long

DWORD stands for Double Word. A Word is 2 bytes. So we need a 4 byte LONG number.

LPCTSTR lpClassName, = lpClassName As String
LPCTSTR lpWindowName, = lpWindowName As String

LP stands for Long Pointer. C is for constant. and a TSTR is compatible in C for either ANSI or UNICODE. All that complexity simply means it's a string in VB. However, it is important to know that the function expects a POINTER to the string. (see: Tips & Tricks - Visual Basic and Pointers)

int x, = X As Long
int y, = Y As Long
int nWidth, = nWidth As Long
int nHeight, = nHeight As Long

On a 32-bit system, an INT is a 32-bit value. That's yet another 4 byte type translated to visual basic's LONG.

HWND hWndParent, = hWndParent As Long
HMENU hMenu, = hMenu As Long
HINSTANCE hInstance, = hInstance As Long

We've got three more types all starting with H. That means they're handles. On a 32-bit system, handles are 32-bit values. So many types which all translate to a simple LONG in VB.

LPVOID lpParam = lpParam As Any

Now here's something you don't see everyday. Once again LP stands for Long Pointer. However, the VOID means it could be anything. It could be a pointer to a string, a number, or a structure. The specialized type 'Any' is only used in these API's. This is the only type which you don't want the 'ByVal' keyword before the argument. On all those other arguments, we want the VALUE of the variables we provide to the function. In this case, we want the POINTER to the variable. Below is the finished declaration statement.

Declare Function CreateWindowEx Lib "user32" Alias "CreateWindowExA" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, lpParam As Any) As Long

The MSDN is also great for looking up structures. Structures are the 'Type' statements you rarely need in Visual Basic unless you're working with the API. Here's a structure in both C and VB format.

struct WSAData {
WORD wVersion;
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYSSTATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;

Here we see a few more different types. Remember when I said a WORD is 2 bytes? That means you'll want Integers for those. A char is a string, but NOT a pointer to a string like we had before. This is a fixed length string. unsigned shorts (USHORT) are also 2 byte values or again - Visual Basic integers. char FAR * - I have no earthly idea. char makes it seem like it's a string, but it's not. lpVendorInfo clues us in that it's a Long pointer - hence a Visual Basic LONG. Just like handles, all pointers in a 32-bit system are 4 bytes.

Here's the Visual Basic version:

wVersion As Integer
wHighVersion As Integer
szDescription As String * WSA_DescriptionSize
szSystemStatus As String * WSA_SysStatusSize
iMaxSockets As Integer
iMaxUdpDg As Integer
lpVendorInfo As Long
End Type

Well, that's all I have to say about that. WSA_DescriptionSize and WSA_SysStatusSize are numerical constants. To get constant values you must download API-Viewer from - or do a text search through C HEADER files to get the values of the constants. MSDN doesn't give them to you.

Once again, if there's any questions, or you want me to convert a mysterious API or structure to VB syntax - feel free to reply.
Posted By: jrfalcon

Re: Converting C datatypes to VB's - 10/09/03 03:12 PM

Calling a C DLL from VB gives me the Runtime
Error: Bad DLL calling convention

The C declaration is:

int Z4W32FUNC z4opencfgSTD(Z4OPEN_PARM *, ...); /* open with custom parameters */

My VB declaration is:

Public Declare Function z4opencfg Lib "zip4_w32.dll" Alias "z4opencfgSTD" _

(ByVal rsvd1 As String, ByVal status As Integer, ByRef fname As Long, ByRef config As CONFIG_PARM, _

ByVal elotflag As Byte, ByVal dpvflag As Byte, ByVal iopenflag As Byte, ByVal rsvd2 As String) As Long

Please advice
Posted By: SilentRage

Re: Converting C datatypes to VB's - 10/09/03 07:46 PM

"Bad DLL calling convention" errors occur when you declare your API functions with incorrect datatypes or with too few or too many parameters.

You did not provide enough information so I looked it up. Apparently the z4opencfg function has optional parameters. I think you need to leave that alone. The VB declaration is this:

Public Declare Function z4opencfg Lib "zip4_w32.dll" Alias "z4opencfgSTD" (lpOpenParm As Z4OPEN_PARM)

And here's the structures to be filled and passed to that function:

C structures

typedef struct
char *address1;
char *addrindex;
char *cdrom;
char *citystate;
char *crossref;
char *system;
char *elot;
char *elotindex;
char *ewspath;

typedef struct
char rsvd1[50];
short status;
char *fname;
char elotflag;
char rsvd2[50];

VB structures

address1 As String
addrindex As String
cdrom As String
citystate As String
crossref As String
system As String
elot As String
elotindex As String
ewspath As String
End Type

Public Type Z4OPEN_PARM
rsvd1 As String * 50
status As Integer
fname As String
elotflag As Byte
rsvd2 As String * 50
End Type
Posted By: jrfalcon

Re: Converting C datatypes to VB's - 10/10/03 03:52 AM

My code for calling the DLL is the following:

Dim openparam As Z4OPEN_PARM
Dim lRet As Long
openparam.config.address1 = "D:\"
openparam.config.addrindex = "D:\"
openparam.config.cdrom = "D:\"
openparam.config.citystate = "D:\"
openparam.config.crossref = "D:\"
openparam.config.system = "D:\"
openparam.config.elot = "D:\"
openparam.config.elotindex = "D:\"
openparam.config.ewspath = "D:\"
openparam.config.dpvpath = "D:\"
lRet = z4opencfg(openparam)

I am still getting the bad calling convention error. Any ideas of what I am doing wrong?
Posted By: SilentRage

Re: Converting C datatypes to VB's - 10/10/03 06:48 AM

I forgot to put the "As Long" at the end of the function declaration. Does it still not work with As Long at the end?

Public Declare Function z4opencfg Lib "zip4_w32.dll" Alias "z4opencfgSTD" (lpOpenParm As Z4OPEN_PARM) As Long
Posted By: jrfalcon

Re: Converting C datatypes to VB's - 10/11/03 11:25 AM

I noticed the As Long missing and put it in - still no go.
Posted By: SilentRage

Re: Converting C datatypes to VB's - 10/13/03 04:58 AM

Is there a header file available for C programmers to use that library? Or is there working C code that uses that library? I'd like to take a look at one or the other to verify I got my declaration right.
Posted By: Michael827

Re: Converting C datatypes to VB's - 05/14/04 01:59 AM

I'm receving the same "Bad DLL calling convention" error. Does anyone have a VB solution for this?
© 2018 UGN Security Forum