Binary data structures and
API OpenScript programming |
|
Problem |
|
While developing the RAS
book I encountered the problem of converting C/C++ data structures
into OpenScript. The conventional method of handling such data blocks
is pointer<type> OpenScript functions where you need to specify
the exact offset of the data item from the beginning of the block. If
you've ever used windows system dlls in your toolbook programs
you agree that there is always a risk of making error in addressing
data in such block. Offered here is the method of addressing data in
the structures based on the symbolic name of the items instead of their
real offsets. This method is realized in MemBlock functions. |
Structure declaration |
|
Data structure can be described by comma separated list
of data types used by OpenScript pointer<type> functions. Each
of the line in the structure declaration contains type specifications
in the following format:
..., <name>
<type> <n>, ...
where <name> is the symbolic name of the field, <type>
is the data type and <n> is the optional length of the field.
You can easily convert standard C/C++ structure declarations into
MemBlock declarations. For example |
|
"dwSize DWORD" - reserves DWORD (4 bytes) for "dwSize"
variable
"dwSize DWORD 4" - reserves 4 dwords
"szDeviceType STRING 17" - reserves 17 bytes for the NULL
terminated string "szDeviceType"
|
Examples |
|
Below C declaration of RASCONSTATUS structure taken from
Win32 API help is shown. |
|
const
RAS_MaxDeviceType=16;
RAS_MaxDeviceName=128;
typedef struct _RASCONNSTATUS {
DWORD dwSize;
RASCONNSTATE rasconnstate;
DWORD dwError;
TCHAR szDeviceType[RAS_MaxDeviceType + 1];
TCHAR szDeviceName[RAS_MaxDeviceName + 1];
} RASCONNSTATUS;
|
|
The corresponding MemBlock declaration string is here |
|
-- RAS connection status structure definition
RAS_CONNSTATUS_def=\
"dwSize DWORD,"&\
"rasconnstate WORD,"&\
"dwError DWORD,"&\
"szDeviceType STRING 17,"&\
"szDeviceName STRING 129"
|
|
This script returns the total number of bytes in the structure |
|
get getBlockBytes(RAS_CONNSTATUS_def)
-- returns 156
|
|
To allocate memory you can use getMemBlock()/FreeMemBlock()
functions from tbwin.dll, KERNEL GlobalAlloc() etc. or toolbook ASYM_getMemBlock()/ASYM_freeMemBlock()
functions. |
|
linkDLL "tbwin.dll"
POINTER getMemBlock(DWORD)
WORD freeMemBlock(POINTER)
end
|
|
The following script calculates the actual offset (in
bytes) of any data item addressed by its symbolic name in the MemBlock
structure |
|
myOffset=getBlockOffset(RAS_CONNSTATUS_def,\
"dwError")
-- in this case function returns 6
|
|
If you want to set a variable inside data structure you
do not need its actual offset, use the symbolic name and declaration
string instead to access memory via toolbook pointer. |
|
-- blockPointer - pointer to the memory block
-- RAS_CONNSTATUS_def - definition string
-- "dwError" - the name of variable
get setBlockVal(blockPointer,\
RAS_CONNSTATUS_def,\
"dwError",\
0xFFFFFFFF)
-- puts 0xFFFFFFFF value into the
-- "dwError" variable
|
|
In the same way you can extract a value from the item
in memory block. |
|
-- blockPointer - pointer to the memory block
-- RAS_CONNSTATUS_def - definition string
-- "dwError" - the name of variable
myValue=getBlockVal(blockPointer,\
RAS_CONNSTATUS_def,\
"dwError")
-- returns the DWORD value of
-- "dwError" variable
|
|
|
MemBlock()
functions scripts.. |
|
|
|