Page 1 of 2

Compiling a list of WinAPI types and their Purebasic equals

Posted: Mon Jun 26, 2006 7:11 pm
by Kale
I'm currently compiling a list of WinAPI types and their Purebasic counterparts. This list was started by Fr34k but i'm updating it to PBv4. Is there any i've missed or got wrong??? Please take a look:

Code: Select all

;==============================================================================
;-NONE
;==============================================================================

VOID

;==============================================================================
;-CONSTANT
;==============================================================================

CONST

;==============================================================================
;-BYTE
;==============================================================================

BOOL
BOOLEAN
BYTE

;==============================================================================
;-CHARACTER
;==============================================================================

CHAR
UCHAR
WCHAR
TBYTE
TCHAR

;==============================================================================
;-WORD
;==============================================================================

SHORT
WORD

;==============================================================================
;-LONG
;==============================================================================

COLORREF
DWORD
DWORD32
HACCEL
HANDLE
HBITMAP
HBRUSH
HCONV
HCONVLIST
HCURSOR
HDC
HDDEDATA
HDESK
HDROP
HDWP
HENHMETAFILE
HFILE
HFONT
HGDIOBJ
HGLOBAL
HHOOK
HICON
HIMAGELIST
HIMC
HINSTANCE
HKEY
HKL
HLOCAL
HMENU
HMETAFILE
HMODULE
HMONITOR
HPALETTE
HPEN
HRGN
HRSRC
HSZ
HWINSTA
HWND
INT
INT32
LANGID
LCID
LCTYPE
LONG
LONG32
LPARAM
LRESULT
SC_HANDLE
SC_LOCK
SERVICE_STATUS_HANDLE
USHORT
WPARAM

;==============================================================================
;-QUAD
;==============================================================================

UINT
UINT32
ULONG
ULONG32
DWORD64
INT64
LONG64
LONGLONG
UINT64
ULONG64
ULONGLONG

;==============================================================================
;-FLOAT
;==============================================================================

FLOAT

;==============================================================================
;-DOUBLE
;==============================================================================

DOUBLE
LONGDOUBLE

;==============================================================================
;-*POINTER
;==============================================================================

DWORD_PTR
INT_PTR
LONG_PTR
LPBOOL
LPBYTE
LPCOLORREF
LPCRITICAL_SECTION
LPCSTR
LPCTSTR
LPCVOID
LPCWSTR
LPDWORD
LPHANDLE
LPINT
LPLONG
LPSTR
LPTSTR
LPVOID
LPWORD
LPWSTR
PBOOL
PBOOLEAN
PBYTE
PCHAR
PCRITICAL_SECTION
PCSTR
PCTSTR
PCWCH
PCWSTR
PDWORD
PFLOAT
PHANDLE
PHKEY
PINT
PLCID
PLONG
PLUID
POINTER_32
POINTER_64
PSHORT
PSTR
PTBYTE
PTCHAR
PTSTR
PUCHAR
PUINT
PULONG
PUSHORT
PVOID
PWCHAR
PWORD
PWSTR
UINT_PTR
ULONG_PTR
Any Changes? :)

Posted: Mon Jun 26, 2006 8:37 pm
by Trond
BOOL is 4 bytes, you said it equals a BYTE which is 1 byte. (BOOLEAN is 1 byte)
USHORT is 2 bytes, you said it equals a LONG which is 4 bytes.
UINT is 4 bytes, you said it equals a QUAD which is 8 bytes.
UINT32 is 4 bytes, you said it equals a QUAD which is 8 bytes.
ULONG is 4 bytes, you said it equals a QUAD which is 8 bytes.
ULONG32 is 4 bytes, you said it equals a QUAD which is 8 bytes.
There is no such type as LONGDOUBLE in the Windows API.
I don't have a POINTER_64 type, but I'd guess this is a 64-bit pointer, in which case it should NOT be *POINTER but rather a QUAD.
LANGID is 2 bytes, you said it equals a LONG which is 4 bytes.
PSTR should be String pointer (*MyName.s).

In my humble opinion, all 32-bit pointers to fundamental types should be LONG unless commented on above, but that's a matter of preference.

And a few additions:
ATOM = WORD
NULL = LONG

Posted: Mon Jun 26, 2006 10:04 pm
by Kale
Trond wrote:BOOL is 4 bytes, you said it equals a BYTE which is 1 byte. (BOOLEAN is 1 byte)
USHORT is 2 bytes, you said it equals a LONG which is 4 bytes.
UINT is 4 bytes, you said it equals a QUAD which is 8 bytes.
UINT32 is 4 bytes, you said it equals a QUAD which is 8 bytes.
ULONG is 4 bytes, you said it equals a QUAD which is 8 bytes.
ULONG32 is 4 bytes, you said it equals a QUAD which is 8 bytes.
There is no such type as LONGDOUBLE in the Windows API.
I don't have a POINTER_64 type, but I'd guess this is a 64-bit pointer, in which case it should NOT be *POINTER but rather a QUAD.
LANGID is 2 bytes, you said it equals a LONG which is 4 bytes.
PSTR should be String pointer (*MyName.s).

In my humble opinion, all 32-bit pointers to fundamental types should be LONG unless commented on above, but that's a matter of preference.

And a few additions:
ATOM = WORD
NULL = LONG
Thanks for taking a look m8, but just one little point to how the above types have been choosen. The purebasic types are types that can be used as an alternative to the ones listed and might not necessarily be of the same size. For example, 'USHORT' like you said is indeed 2 bytes but is unsigned, so for a Purebasic type to handle all 'USHORT's potential values correctly a long should be used to avoid any numeric wrapping issue. See what i mean? :)

I shall however study your list and make any changes. thanks. :)

For reference this is where im getting most of this info from: http://freak.purearea.net/help/wintypes.txt im just attempting to update it.

Posted: Mon Jun 26, 2006 10:34 pm
by Trond
Personally I'd rather encounter a few wraps than a corrupted stack.

Edit:
Let me show you something. Have a look at this code:

Code: Select all

Procedure Kiwi()
  Noxer.s = "Noxer"
  Poxer.s = "Poxer"
  Long.l = 1234
  OpenLibrary(0, "dll.dll")
  CallFunction(0, "ApricotAPI", Long, Long)
  Debug Poxer
EndProcedure

Kiwi()
If ApricotAPI is function that takes two USHORTs, then the debug statement will print "Noxer" and you'll be left with an invalid memory access error on the EndProcedure line. Of course, some people prefer this to wrapping values.

Posted: Wed Jun 28, 2006 11:51 am
by Kale
Anyone else got any more input on this?

Posted: Wed Jun 28, 2006 1:30 pm
by Trond
Yes, freak says I'm wrong, and he's right. (That is, unless the difference is between a quad and a long.) The byte size of a variable is rounded up to the closest number divisible by four before it's pushed onto the stack.

Posted: Wed Jun 28, 2006 3:02 pm
by freak
First of all, here is a link that is helpful:
http://msdn.microsoft.com/library/defau ... _types.asp

Then i would say you should make a distiction with the character types, as PB now supports
unicode.
The PB character type changes size with unicode on, so care must be taken with the fixed
size character types of windows:

Code: Select all

CHAR  - always 1byte, so in unicode mode, a byte must be used
UCHAR - always 1byte (unsigned) This can be seen as a CHAR in general, as the char type in C is unsigned on just about any system anyway these days.
WCHAR - always 2byte, so in non-unicode mode, a word must be used
TBYTE - byte in non-unicode and word in unicode mode. I would not use the character type here, as TBYTE is a signed type
TCHAR - this is exactly the PB character type 
CONST:
this is just a modifier keyword telling the compiler that a value is not changed inside a function.
It allows for some optimisations in C compilers. So this is not a PB constant. When a
function parameter has this modifier, it should just be ignored.

BOOL is a long, as Trond said.

About the unsigned types:
Simply using a bigger type directly is not a good option. The example Trond provided
actually works without error, but only because of the alignment. It will be problematic
when using a quad instead of ULONG for sure. Also using a different size type
will be problematic inside structures as well.

Storage-wise, a unsigned type is exactly the same as a signed one. Thats why at a place
of an unsigned type, a PB type of the same size should be used. Only when it comes
to working with the value, it should be transfered into a larger type using the famous
masking with & $FF.

Basically it is like this: If a larger type is transfered into a smaller one, the higher bits
are simply cut, so signed/unsigned makes no difference here. Only when moving from
a small type to a big one, all the higher bits are filled with '1'. Here the masking
like above prevents that by masking out these '1's after the transfer.

I suggest you put the unsigned types to the PB types of the same size, and add a note
about this issue. Maybe also provide a set of macros like this:

Code: Select all

Macro ReadUBYTE(ubyte)
  ((ubyte) & $FF)
EndMacro

Macro ReadUSHORT(ushort)
  ((ushort) & $FFFF)
EndMacro

; and so forth for bigger types, just with more FFFF's
This way, after getting a ULONG from somewhere (put into a long), the real value
is read like this:

Code: Select all

realvalue.q = ReadULONG(ulong.l)
POINTER_32
POINTER_64
These are weird. As i understand it, these are truncated/sign extended values to have a fixed
size on both 32bit and 64bit windows. So they would be a long and quad respectively, not
a *pointer. I do not understand the reason for this, as it makes no sense to me, but i have
never seen them used in any piece of code or api call so far, so i guess it can be safely ignored :)

some info: http://msdn.microsoft.com/library/defau ... _types.asp

String pointers:
I think it is worth noting what exactly hides behind the different types of string pointers, as
usually you not just want to store the pointer, but also access the data behind it.

General: P... vs. LP...: The fact that there is a P... and LP... type for most things is originating
from the win16 to win32 transition and has no meaning anymore these days.
The P... and LP... pointers are the same now these days, and the LP... types are the
ones most commonly used. (this applies not only to string pointers of course)

Code: Select all

LPCSTR
8-bit character string. PokeS/PeekS with #PB_Ascii can be used both
in unicode/non-unicode mode to read this

LPCWSTR
PCWSTR
PWSTR
LPOLESTR
16-bit character string. PokeS/PeekS with #PB_Unicode can be used both
in unicode/non-unicode mode to read this

LPCTSTR
LPTSTR
LPSTR
PCTSTR 
PTSTR
8 or 16-bit depending on the unicode mode. So this is the same as the PB string type.

Posted: Thu Jun 29, 2006 2:48 pm
by Kale
Can you take a look at this updated list? Does this fit more inline with the WinAPI types?

Code: Select all

;==============================================================================
;-BYTE
;==============================================================================

BOOLEAN
BYTE
CHAR
UCHAR †

;==============================================================================
;-CHARACTER
;==============================================================================

TBYTE †
TCHAR

;==============================================================================
;-WORD
;==============================================================================

SHORT
USHORT †
WCHAR
WORD

;==============================================================================
;-LONG
;==============================================================================

BOOL
COLORREF
DWORD
DWORD32
HACCEL
HANDLE
HBITMAP
HBRUSH
HCONV
HCONVLIST
HCURSOR
HDC
HDDEDATA
HDESK
HDROP
HDWP
HENHMETAFILE
HFILE
HFONT
HGDIOBJ
HGLOBAL
HHOOK
HICON
HIMAGELIST
HIMC
HINSTANCE
HKEY
HKL
HLOCAL
HMENU
HMETAFILE
HMODULE
HMONITOR
HPALETTE
HPEN
HRGN
HRSRC
HSZ
HWINSTA
HWND
INT
INT32
LANGID
LCID
LCTYPE
LONG
LONG32
LPARAM
LPBOOL
LPBYTE
LPCOLORREF
LPCRITICAL_SECTION
LPCSTR
LPCTSTR
LPCVOID
LPCWSTR
LPDWORD
LPHANDLE
LPINT
LPLONG
LPSTR
LPTSTR
LPVOID
LPWORD
LPWSTR
LRESULT
PBOOL
PBOOLEAN
PBYTE
PCHAR
PCRITICAL_SECTION
PCSTR
PCTSTR
PCWCH
PCWSTR
PDWORD
PFLOAT
PHANDLE
PHKEY
PINT
PLCID
PLONG
PLUID
POINTER_32
PSHORT
PSTR
PTBYTE
PTCHAR
PTSTR
PUCHAR
PUINT
PULONG
PUSHORT
PVOID
PWCHAR
PWORD
PWSTR
SC_HANDLE
SC_LOCK
SERVICE_STATUS_HANDLE
UINT †
UINT32 †
ULONG †
ULONG32 †
WPARAM

;==============================================================================
;-QUAD
;==============================================================================

DWORD64
INT64
LONG64
LONGLONG
POINTER_64
UINT64 †
ULONG64 †
ULONGLONG †

;==============================================================================
;-FLOAT
;==============================================================================

FLOAT

;==============================================================================
;-DOUBLE
;==============================================================================

DOUBLE

;==============================================================================
;-*POINTER
;==============================================================================

DWORD_PTR
INT_PTR
LONG_PTR
UINT_PTR
ULONG_PTR


Types marked with '†' need to be read correctly after a command call. This is because these
types may be unsigned or signed opposite to the Purebasic type they are using.

Posted: Thu Jun 29, 2006 3:57 pm
by freak
looks good to me.

Posted: Thu Jun 29, 2006 4:00 pm
by Kale
freak wrote:looks good to me.
Cool! ta m8. :)

Posted: Thu Jun 29, 2006 8:13 pm
by Kale
I've just coded these procedures to handle returning the correct value from different Win32 API types according to the above table but how do you return the correct result from an 64bit unsigned type? :shock:

Code: Select all

;Returns the correct unsigned value from a UCHAR.
Procedure.w UCHAR(UCHAR.b)
	ProcedureReturn UCHAR & $FF
EndProcedure

;Returns the correct signed value from a TBYTE.
CompilerIf #PB_Compiler_Unicode
	Procedure.w TBYTE(TBYTE.c)
CompilerElse
	Procedure.b TBYTE(TBYTE.c)
CompilerEndIf
	ProcedureReturn TBYTE
EndProcedure

;Returns the correct unsigned value from a USHORT.
Procedure.l USHORT(USHORT.w)
	ProcedureReturn USHORT & $FFFF
EndProcedure

;Returns the correct unsigned value from a UINT.
Procedure.q UINT(UINT.l)
	ProcedureReturn UINT & $FFFFFFFF
EndProcedure

;Returns the correct unsigned value from a UINT32.
Procedure.q UINT32(UINT32.l)
	ProcedureReturn UINT32 & $FFFFFFFF
EndProcedure

;Returns the correct unsigned value from a ULONG.
Procedure.q ULONG(ULONG.l)
	ProcedureReturn ULONG & $FFFFFFFF
EndProcedure

;Returns the correct unsigned value from a ULONG32.
Procedure.q ULONG32(ULONG32.l)
	ProcedureReturn ULONG32 & $FFFFFFFF
EndProcedure

Posted: Thu Jun 29, 2006 9:13 pm
by Bonne_den_kule
Is this right?

Code: Select all

Var & $FFFFFFFFFFFFFFFF 

Posted: Thu Jun 29, 2006 10:37 pm
by Kale
Bonne_den_kule wrote:Is this right?

Code: Select all

Var & $FFFFFFFFFFFFFFFF 
It doesn't make any difference because the biggest possible type has 64bits and this is interpretted as signed. :(

Code: Select all

Var.q = %1000000000000000000000000000000000000000000000000000000000000000
Debug Var
Debug Var & $FFFFFFFFFFFFFFFF

Posted: Fri Jun 30, 2006 2:44 am
by netmaestro
StrU() supports quads now, would that be of help?

Posted: Fri Jun 30, 2006 3:03 am
by Dare
I think this is the same issue as we had with longs before quads arrived. Every smaller integer type can be "&"-ed to a positive, but the biggest integer type cannot (if high bit set, its negative, period).

Still, with quads we get to emulate unsigned longs which is quite a big jump forward.

Unsigned types would be nice. Maybe for 4.1? :)