Paradox Community
Search:

 Welcome |  What is Paradox |  Paradox Folk |  Paradox Solutions |
 Interactive Paradox |  Paradox Programming |  Internet/Intranet Development |
 Support Options |  Classified Ads |  Wish List |  Submissions 


Paradox Programming Articles  |  Beyond Help Articles  |  Tips & Tricks Articles  


Using Win32 API Functions with Structures
Explanation and Example
© 2001 Pascal Hutton

Introduction

The purpose of this "article" is to show that it is possible to call functions from Win32 API even when they require a structure as a parameter.

How is it possible? Well, it's a bit complicated procedure but once you got it you can do (almost) everything you want (except callback functions).

The functions required to do this are all stored in the file kernel32.dll.


Step 1

You need to allocate a block of memory to store the components of the structure, the function GlobalAlloc will be used to do it. Once you have called the function, the return value is a pointer to the memory block.

Here’s how GlobalAlloc is used:
GlobalAlloc(GMEM_FIXED cLong, dwsize cLong) cLong [stdcall]
  • GMEM_FIXED: a constant fromhex("0x40") and allocates fixed memory so the return value of the function is a pointer to the memory block.
  • dwsize: specify the block size needed, in bytes (usually multiples of 4)

Step 2

Now you can move the data directly to the memory with the function RtlMoveMemory. You have to step through the block to write the data in the memory, so your starting "address" will be the pointer returned by GlobalAlloc and you'll have to add 4 each time you progress in the filling process. It's the complicated part but don’t worry it will be more clear with a sample.

The RtlMoveMemory function can be declared in two ways.
RtlMoveMemory(hpvdest cLong, hpvsource cptr, dwbytes cLong) cLong [stdcall]
This declaration is to use the function to write in the memory block
  • hpvdest: a longint value which is the pointer to the block or position in the block
  • hpvsource: a longint or smallint or string value that you want to transfer to the block
  • dwbytes: number of bytes to write
RtlMoveMemory(hpvdest cptr, hpvsource cLong, dwbytes cLong) cLong [stdcall]
This declaration is to use the function to read the memory block.
  • hpvdest: a longint or smallint or string value which is the buffer to receive data
  • hpvsource: a longint value which is the the pointer to the position of the memory block you want to read
  • dwbytes: number of bytes to read
The return value (in both declarations) is the address of the next block 4 bytes ahead if the function works, otherwise it's 0.


Step 3

You call the function and pass the pointer of the memory block to the function.


Step 4

Free the memory block with the function with GlobalFree.
GlobalFree(hMem cLong) cLong [stdcall]
  • hMem: the pointer to the memory block allocated with GlobalAlloc

Sample

Let’s suppose we have a function called "structfunc" which has 3 parameters : longint, structure, string.

The structure is organized as follows:
param1    longint
param2    longint
param3    longint
To use it we'll need to allocate a block of 12 bytes (4 bytes for each longint value).

The uses statement:
uses dll_name
  structfunc(long_value cLong, struct_pointer cLong, string_value cptr) cLong [stdcall]
enduses

uses "kernel32.dll"
  GlobalAlloc(wFlags cLong, dwBytes cLong) cLong [stdcall]
  RtlMoveMemory(hpvDest clong, hpvSource cptr, cbCopy cLong) cLong [stdcall]
  GlobalFree(hMem cLong) cLong [stdcall]
enduses
Now the var statement:
Var
  long_value longint
  param1, param2, param3 longint ;// these are used to act as the structure
  string_value string
  mem_block longint              ;// pointer to the memory block
  adr longint                    ;// variable used to go through the block
  res longint
endvar
Now the code.

We need 12 bytes of fixed memory to use it to store the structure:
mem_block = GlobalAlloc(fromhex("0x40"), 12)
Now we can fill the structure:
param1 = 400
param2 = 227
param3 = 600
adr is a temp variable to pass the values to the memory block and move ahead in it, so we start by giving the value of the pointer to adr:
adr = mem_block
We pass the first parameter, param1, to adr which is the pointer or beginning of the block and the values will be stored in 4 bytes:
res = RtlMoveMemory(adr, param1, 4)
We move 4 bytes ahead:
adr = adr + 4
And do the same for the second parameter:
res = RtlMoveMemory(adr, param2, 4)
and so on...
adr = adr + 4
res = RtlMoveMemory(adr, param3, 4)
Now the other parameters:
long_value = 123654
string_value = "this is a test"
Call the function:
res = structfunc(long_value, mem_block, string_value)
Free the memory block:
res = GlobalFree(mem_block)

A Real Sample


Discussion of this article


 Feedback |  Paradox Day |  Who Uses Paradox |  I Use Paradox |  Downloads 


 The information provided on this Web site is not in any way sponsored or endorsed by Corel Corporation.
 Paradox is a registered trademark of Corel Corporation.


 Modified: 15 May 2003
 Terms of Use / Legal Disclaimer


 Copyright © 2001- 2003 Paradox Community. All rights reserved. 
 Company and product names are trademarks or registered trademarks of their respective companies. 
 Authors hold the copyrights to their own works. Please contact the author of any article for details.