Library Low-Level Win32 Routines ver 0.0.1
Aurthor Jordah Ferguson
Contacts jorfergie03@yahoo.com
Date Thursday, July 25, 2002
Table of Contents
  1. Memory Routines
  2. Creating custom memory Heaps
  3. Structure Handling Routines
  4. Misc routines
  5. Function Reference
  6. Distribution Status
  7. Disclaimer
This library holds a set of routines i have found very useful in win32 programming. My routines 
are designed to be safe and will save you a lot of time during the course of your win32 programming. 
This is all you will be needing to start programming in API or even using low-level win32lib.
By default, incase an error is encountered a message box pops-up explaining the error. However you 
can suppress any error message by calling SetErrorWarning(0). To later allow errors to be displayed then you
call SetErrorWarning(1)
Memory Routines:
	Memory calls are made using kernel32 API calls. The reason i choose to do this is because
they are more OS friendly as they return freed memory back to the OS for the other programs to use.
When you allocate memory using Euphoria calls, the memory when freed is not actually returned to the
OS but is reserved for the next allocation. The only problem with this method is that if you have a computer
low on memory and free disk-space and you allocate large chunks of memory, the OS will either deny other
programs chance to run due to lack of memory or the OS will cause you program to be closed.
I have wrapped some kernel heap functions and made them global just incase you need to create your own
private memory heaps. see Creating your Custom Memory Heaps
A default heap is automatically created for you when you include llrtn.ew in your program. 
The default heap has an intial size of 16384 bytes of physical storage, if you application requests more than 
that, then the OS allocates extra virtual memory.
To allocate memory from the default heap you'll have to use Alloc,AllocString,Free,FreeAllMem. Using these 
functions is all you'll need but just incase you need to create your own custom heap for some reason then 
see Creating your Custom Memory Heaps
I would like to thank Matt Lewis and Derek for once explaining the heap functions to me and Mario Steele and 
Lucius Hilley for chatting with me about the Pros and Cons of the functions
Function Description
Alloc Allocates n bytes of contiguous bytes of memory. Using the Default Heap
AllocString Allocate space for string sequence s. Using the Default heap
Free Free previously allocated memory from the Default heap
FreeAllMem Frees all memory in the default heap and destroys the heap
lstrlen This function returns the length of a null-terminating string in memory
PeekString This function returns a null-terminating string from memory
SafePeek2s Return a signed word(2-byte) in the range -32768 to 32767 from a memory address
SafePeek2u Return a unsigned word(2-byte) in the range 0 to 65535 from a memory address
SafePeek4s Return a 4-byte (32-bit) signed value in the range -2147483648 to +2147483647 from a memory address
SafePeek4u Return a 4-byte (32-bit) unsigned value in the range 0 to 4294967295 from a memory address
SafePeeks Return a single signed byte value in the range -128 to 127 from a memory address
SafePeeku Return a single unsigned byte value in the range 0 to 255 from a memory address
SafePoke write a single byte value to a memory address
SafePoke2 write a 2-byte value(word) to amemory address
SafePoke4 write a 4-byte (32-bit) value to a memory address

Creating and Managing your Custom Heaps

All the above routines are just wrap-ups of the C functions below, they are very sufficient and you'll find almost no need to create custom made heaps but just incase you need to; here is how you do it.

Step1: Create the Actual heap you will have to supply the initial size of the heap
example:
atom myheap
myheap =
HeapCreate(4096) -- Creates a heap with 4096 bytes of intial hysical storage

Step2:After creating the heap you can now allocate and free memory using HeapAlloc and HeapFree. Remember the heap is growable so you can even allocate 20000 bytes from the above heap, it would only commit virtual memory pages to cover-up your needs
example:
atom memaddr,junk
memaddr = HeapAlloc(myheap,20)
-- Allocate 20 bytes of memory
junk = HeapFree(myheap,memaddr)
-- Free memaddr from the heap
example2:
Incase you wanted to allocate a string in memory you would do it like this
atom addr,len_,junk
sequence eu eu = "Euphoria 2.3"
len_ = length(eu)
addr = HeapAlloc(myheap,len_+1)
if addr then
SafePoke(addr,eu)
SafePoke(addr+len_,0)
end if
junk = HeapFree(myheap,addr)

Step3:This is not compulsory, but is good practice. It is usually good to call HeapValidate() after HeapFree() or HeapAlloc()
example
atom junk,memaddr
memaddr = HeapAlloc(myheap,20)
-- Allocate 20 bytes of memory
junk = HeapValidate(myheap,memaddr)
if not HeapFree(myheap,addr) then
end if
junk = HeapValidate(myheap,0)

Step4:Once you are done with the heap then simply destroy it to free all the previous memory allocations and destroy the heap. After a heap is destroyed you can get an exception if you attempt to allocate or free memory from a destroyed heap
example:
junk =
HeapDestroy(myheap)

C Function Description
HeapCreate This function allocates a private heap object.
HeapAlloc The HeapAlloc function allocates a block of memory from a heap.
HeapFree The HeapFree function frees a memory block(pointer) allocated from a heap by the HeapAlloc
HeapDestroy The HeapDestroy function destroys the specified heap object.
HeapValidate The HeapValidate function attempts to validate a specified heap or memory pointer

Structure Handling Routines
Before i start the tutorial on my structure handling routines i would like to Credit Chris Bensler for the original idea and Bernie Ryan for all the knowledge of structures i picked up from winapi20.zip.  Thanx Chris Bensler bensler@mail.com also i would like to thank Jason Mirwald for listening to my suggestions and giving me a few suggestions.

Routine Description
defineStructure Declares a Structure and returns internal structure information needed for use with other structure routines
AllocateStructure Allocates memory of a structure based on its size and returns the structure modified to reflect change
FreeStructure Deallocates the memory of the structure and returns the structure modified to reflect change
AssociatePointer Associates a structure pointer given by windows with a structure
addressOf Returns the memory pointer of a structure or the memory pointer of a structure element
sizeOf Returns the number of bytes the structure covers. It returns an integer specifying the amount of RAM the structure needs
Store This function fills the structure elements with information
Fetch Returns the contents of a structure

Ok, now lets get on with the show. I'm going to explain how to declare and peek or Poke from the structure. Just like the way you have to declare a C function or Procedure, using my structure routines you have to declare your structure before you can put it into use, you do this by using the defineStructure() function. The return value is a sequence containing the structure defination needed when poking and peeking.

Declaring a Structure


s =
defineStructure({{name,C constant}})
The second parameter where C constant is placed can also be a structure defination in which case the Internal Data will be linked. It can also be in the form {C constant,repeat}
The Storing and fetching of structure information all depends on the C constant you specify for example C_WORD when storing uses SafePoke2 and when Fetching uses SafePeek2s while C_UWORD when storing uses SafePoke2 but when fetching uses SafePeek2u. If the C constant you specify is C_LPSZ then when storing you can simply supply the String, Conversion is Automatic, you can also specify an integer in which case it will allocate a buffer especially when Fetching data from a C routine.

example 1:

Below is the how i link the C structure RECT.
In C,

typedef struct _RECT { // rc
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECT;

Using defineStructure;

-------------------[ RECT STRUCTURE ]-------------------
global
sequence RECT
RECT
= defineStructure({
{"left" ,C_LONG},
{"top" ,C_LONG},
{"right" ,C_LONG},
{"bottom",C_LONG}
})

example 2
In C, here is how the drawitemstruct looks like

typedef struct tagDRAWITEMSTRUCT { // dis
UINT CtlType;
UINT CtlID;
UINT itemID;
UINT itemAction;
UINT itemState;
HWND hwndItem;
HDC hDC;
RECT rcItem; -----------------> This points to a RECT structure
DWORD itemData;
} DRAWITEMSTRUCT;

Using defineStructure here is how u would link it. It also requires you had declared the rect structure like in example 1

-------------------[ DRAWITEMSTRUCT ]-------------------
global sequence DRAWITEMSTRUCT
DRAWITEMSTRUCT
= defineStructure({
{"CtlType" ,C_UINT},
{"CtlID" ,C_UINT},
{"itemID" ,C_UINT},
{"itemAction",C_UINT},
{"itemState" ,C_UINT},
{"hwndItem" ,C_LONG},
{"hDC" ,C_LONG},
{"rcItem" ,RECT },--> Links/embends the RECT structure defination intoDRAWITEMSTRUCT
{"itemData" ,C_DWORD}
})

Example3
In C, here is an example of the PAINTSTRUCT

typedef struct tagPAINTSTRUCT { // ps

HDC hdc;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[32]; --> reserve 32 bytes
} PAINTSTRUCT;

using defineStructure.

-------------------[ PAINTSTRUCT ]-------------------
global sequence PAINTSTRUCT
PAINTSTRUCT
= defineStructure({
{"hdc" ,C_LONG },
{"fErase" ,C_BOOL },
{"RECT" ,RECT },
{"fRestore" ,C_BOOL },
{"fIncUpdate" ,C_BOOL },
{"rgbReserved",{C_BYTE,32}}
})


Example4
In C here is the TC_ITEM structure
typedef struct _TC_ITEM {
UINT mask;
UINT lpReserved1;
UINT lpReserved2;
LPSTR pszText;
int cchTextMax;
int iImage;
LPARAM lParam;
} TC_ITEM;

using defineStructure

-------------------[ TC_ITEM Structure ]-------------------
global sequence TC_ITEM
TC_ITEM
= defineStructure({
{"mask", C_UINT},
{"reserved1", C_UINT},
{"reserved2", C_UINT},
{"pszText", C_LPSZ},
{"cchTextMax", C_INT },
{"iImage", C_INT },
{"lParam", C_LONG}
})

Structures and Memory Management
When you declare a structure no memory is allocated for it, this is because you will find out that in windows programming you can either pass a structure pointer to a C function or receive a structure pointer. when you receive a structure pointer from windows for example the lParam from within a WM_NOTIFY message always points to the NMHDR structure. Trying to free that structure pointer can cause an exception, that is why i have devised two ways of linking structure pointers to a structure.

1) Passing a Strutucture to a C function.
If you routines are required to pass C structure pointers to C functions then you allocate a stucture using AllocateStructure(). AllocateStructure always checks the structure you are passing to it and if it has any previous allocated memory it is freed before the new memory is allocated.
You can deallocate memory from a structure using FreeStrucuture function. FreeStructure should be used when the memory was allocated using AllocateStructure. Example
-------------------[ RECT STRUCTURE ]-------------------
global
sequence RECT
RECT
= defineStructure({
{"left" ,C_LONG},
{"top" ,C_LONG},
{"right" ,C_LONG},
{"bottom",C_LONG}
})

RECT = AllocateStructure(RECT)
-- This allocates memory for RECT structure and returns the RECT structure with the internal data -- modified to reflect new Changes.
RECT = FreeStructure(RECT)
-- This deallocates memory of the RECT structure and returns the RECT structure with the
--Internal data modified to reflect changes

2) Receiving a structure pointer from a Windows Message
During the course of your win32 programming you will notice there are times windows returns to you a structure pointer from which you can extract your desired data. the best example i can think of at the moment is when you process the WM_NOTIFY message. the lParam always points to the NMHDR structure. for such occasions you need not allocate your declared structure but instead Associate the memory pointer(lparam) with it. Below is an example of how i declare the NMDHR structure and how i process the WM_NOTIFY message

-------------------------------------------------------

global sequence NMHDR
NMHDR
= defineStructure({
{"hwndFrom",C_ULONG},
{"idFrom" ,C_UINT },
{"code" ,C_LONG }
})

---<snip> Here is how i process the WM_NOTIFY message in my WndProc
elsif iMsg = WM_NOTIFY then
NMHDR
= AssociatePointer(NMHDR,lParam)
id
= Fetch(NMHDR,"hwndFrom")
iMsg
= Fetch(NMHDR,"code")
---<snip>

AddressOf and sizeOf

When Passing a structure to a C-routine, you have to know use the memory pointer. using llrtns.ew you use addressOf() function to find out the address of structure or the pointer to an element of a structure. example:

global atom aRECT
-------------------[ RECT STRUCTURE ]-------------------
global sequence RECT
RECT
= defineStructure({
{"left" ,C_LONG},
{"top" ,C_LONG},
{"right" ,C_LONG},
{"bottom",C_LONG}
})
RECT
= AllocateStructure(RECT)
aRECT
= addressOf(RECT)
-------------------[ General Function ]-------------------
global function getClientRect(atom id)
sequence rect
atom hdc
rect
= repeat(0,4)
if id = Screen then
hdc
= getDC(id)
rect
[3] = c_func(zGetDeviceCaps,{hdc,HORZRES})
rect
[4] = c_func(zGetDeviceCaps,{hdc,VERTRES})
releaseDC(id,hdc)
else
if not c_func(zGetClientRect,{id,aRECT}) then
puts(1,"getClientRect() failed")
end if
rect
= Fetch(RECT,{})
end if
return rect
end function

-- also incase i wanted to manually obtain the addressOf the "top" element of the structure
-- i would do it like this
atom topAddr
topAddr = addressOf({RECT,"top"})

SizeOf()

During the course of your win32 programming you'll also find out some C functions require that you specify the size of the structure. The size of a structure is the number of bytes of RAM it uses. Microsoft came up with this method for compatibility reasons varing from platform to platform of windows. For example in win95, the structure MENUITEMINFO is one element smaller than that in windows 98. if you don't specify the size, the OS won't know what exactly you want to do and whatever function needs the structure address as a parameter fails. Below is an example that shows how to obtain the size of a bitmap object

-------------------[ BITMAP Structure ]-------------------
global sequence BITMAP
BITMAP
= defineStructure({
{"bmType", C_LONG},
{"bmWidth", C_LONG},
{"bmHeight", C_LONG},
{"bmWidthBytes" ,C_LONG},
{"bmPlanes", C_WORD},
{"bmBitsPixel", C_WORD},
{"bmBits", C_LONG}})
BITMAP
= AllocateStructure(BITMAP)
-------------------[ Size of a bitmap ]-------------------
global function GetBitmapSize(atom bitmap)
integer void
void
= c_func(zGetObject,{bitmap,sizeOf(BITMAP),addressOf(BITMAP)})
return Fetch(BITMAP,{"bmWidth","bmHeight"})--returns width and height of the bitmap handle
end function

Storing Data in a Structure

In order to store data to a structure you use, Store(STRUCTURE,{{element,value}}). you can also use Store(Structure,{}) to erase all the contents of a structure(it does mem_set(addressOfStructure,0,sizeOf(Structure)). If you want to only store a value to one element you can use this notation for convinance. Store(RECT,{"top",200}). Below are a few examles that show you how store data.

-------------------[ TC_ITEM Structure ]-------------------
global sequence TC_ITEM
TC_ITEM
= defineStructure({
{"mask", C_UINT},
{"reserved1", C_UINT},
{"reserved2", C_UINT},
{"pszText", C_LPSZ},
{"cchTextMax", C_INT },
{"iImage", C_INT },
{"lParam", C_LONG}
})
TC_ITEM
= AllocateStructure(TC_ITEM)

---------------------------------------------------------
--Function:GetTabText(atom tabctl,integer tabitem)
--Use :It retrieves Text from a TabItem label
--Return :{} or TabText
---------------------------------------------------------

global function GetTabText(atom tabctl,integer tabitem)
integer junk
sequence InternalString
Store(TC_ITEM,
{{"mask",TCIF_TEXT },
{"pszText" ,128 },-- This creates a buffer to hold the string. Read more on C_LPSZ
{"cchTextMax",128 }})
junk
= sendMessage(tabctl,TCM_GETITEM,tabitem,addressOf(TC_ITEM))
InternalString
= Fetch(TC_ITEM,"pszText")
return InternalString
end function

example2: Shows the WinMain() of window.exw that comes with Eu2.3

-------------------[ WNDCLASSEX STRUCTRURE ]------------
sequence WNDCLASSEX
WNDCLASSEX
= defineStructure({
{"cbSize" ,C_UINT },
{"style" ,C_UINT },
{"lpfnWndProc" ,C_POINTER},
{"cbClsExtra" ,C_INT },
{"cbWndExtra" ,C_INT },
{"hInstance" ,C_LONG },
{"hIcon" ,C_LONG },
{"hCursor" ,C_LONG },
{"hbrBackground",C_LONG },
{"lpszMenuName" ,C_POINTER},
{"lpszClassName",C_PTR },
{"hIconSm" ,C_LONG }
})
WNDCLASSEX
= AllocateStructure(WNDCLASSEX)

atom my_title,aWNDCLASS
my_title
= AllocString("Euphoria for WIN32")
aWNDCLASS
= addressOf(WNDCLASSEX)

procedure WinMain()
-- main routine
atom szAppName
atom hwnd
atom WndProcAddress
atom class
integer id
atom icon_handle,Cursor,Bk
szAppName
= AllocString("HelloWin")
id
= routine_id("WndProc")
if id = -1 then
puts(1, "routine_id failed!\n")
abort(1)
end if
WndProcAddress
= call_back(id) -- get 32-bit address for callback
icon_handle = c_func(LoadIcon, {instance(), allocate_string("exw")})
Cursor = c_func(LoadCursor, {NULL, IDC_ARROW})
Bk
= c_func(GetStockObject, {WHITE_BRUSH})

Store(WNDCLASSEX,{}) -- Similar to mem_set() and filling with zeros

Store(WNDCLASSEX,{
{"cbSize" ,sizeOf(WNDCLASS)},
{"style" ,or_bits(CS_HREDRAW, CS_VREDRAW)},
{"lpfnWndProc",WndProcAddress},
{"cbClsExtra" ,NULL },
{"cbWndExtra" ,NULL },
{"hInstance" ,instance() },
{"hIcon" ,icon_handle},
{"hCursor" ,Cursor },
{"hbrBackground",Bk },
{"lpszMenuName",NULL },
{"lpszClassName",szAppName},
{"hIconSm" ,icon_handle}
})
class
= c_func(RegisterClassEx, {aWNDCLASS})
if class = 0 then
puts(1, "Couldn't register class\n")
abort(1)
end if
hwnd
= c_func(CreateWindow, {
0, -- extended style
szAppName, -- window class name
my_title, -- window caption
WS_OVERLAPPEDWINDOW, -- window style
CW_USEDEFAULT, -- initial x position
CW_USEDEFAULT, -- initial y position
CW_USEDEFAULT, -- initial x size
CW_USEDEFAULT, -- initial y size
NULL, -- parent window handle
NULL, -- window menu handle
0 , --hInstance // program instance handle
NULL}) -- creation parameters
if hwnd = 0 then
puts(1, "Couldn't CreateWindow\n")
abort(1)
end if
c_proc(ShowWindow, {hwnd, SW_SHOWNORMAL})
c_proc(UpdateWindow, {hwnd})
WNDCLASSEX =
FreeStructure(WNDCLASSEX)
Free(szAppName)
Free(my_title)
while c_func(GetMessage, {aMSG, NULL, 0, 0}) do-- aMSG is addressOF MSG structure
c_proc(TranslateMessage, {aMSG})
c_proc(DispatchMessage, {aMSG})
end while
end procedure

WinMain
()

Fetching

You can fetch data from a Structure using the Fetch() function. Fetch(Structure,{{element1,...}})
incase you need to Fetch more all the data from the structure you can use Fetch(Structure,{}). It returns a sequence containing all the peeked data in the same order you declared the structure. For examples

1) Look at GetTabText(atom tabctl,integer tabitem) example above
2)Look at the GetBitmapSize
(atom bitmap) example above
3)Look at the
getClientRect(atom id) example above

With the above structure functions you will find out programming in API or low-level win32lib is just iece of cake.

MISC Routines

Routines Description
LOWORD The LOWORD macro retrieves the low-order word from the given 32-bit value.
HIWORD The HIWORD macro retrieves the high-order word from the given 32-bit value.
MAKELONG The MAKELONG macro creates an unsigned 32-bit value by concatenating two given 16-bit values.
MAKEWORD The MAKEWORD macro creates an unsigned 16-bit integer by concatenating two given unsigned character values.
or_all() applies or_bits on bits in a given sequence

FUNCTION REFERENCE:


Syntax:      include llrtns.ew
             a = Alloc(i)

Description:
Allocate i contiguous bytes of memory. Return the address of the
block of memory, or return 0 if the memory can't be allocated.
The address returned will be at least 4-byte aligned.

Extra:
The memory returned is automatically intialized to zero for you
In Eu you would have to use mem_set() to initialize you memory to zero

example:
atom mem
mem = Alloc(24)-- allocates 24 bytes of memory
See also AllocString,Free,FreeAllMem

Syntax:      include llrtns.ew
             a = AllocString(s)

Description:
Allocate space for string sequence s. Copy s into this space
along with a 0 terminating character. This is the format expected
for C strings. The memory address of the string will be returned.
If there is not enough memory available, 0 will be returned.

The allocated memory is also initialized to Zero. This is Particularly
helpful especially during time of peeking the string from memory.
example:
     atom pstr
     pstr = AllocString("Eu is the Bomb")-- returns a pointer to the string
See also Alloc,Free,FreeAllMem,PeekString,lstrlen

 Syntax:  include llrtns.ew
          Free(a)
 Description:
Free up a previously allocated block of memory by specifying the
address of the start of the block, i.e. the address that was
returned by Alloc() or AllocString().
Freed memory is returned to the OS. so other programs can also use 
the freed memory. if you forget to free your memory or you forget
to call FreeAllMem() at the end of your program then there is no
need to worry as the heap is automatically destroyed by the OS when
the process terminates.
example:
atom pstr
pstr = AllocString("Eu is the Bomb")-- returns a pointer to the string     
Free(pstr)
See also  AllocString,Alloc,FreeAllMem

Syntax:  include llrtns.ew
         FreeAllMem()
Description: 
Calling this function Frees all the Allocated memory in the Heap and 
Destroys the Heap. Calling Alloc,Free,AllocString after this call
will cause an exception.
Note
The best place for this function in your program is after a call to 
WinMain()
Example: 
WinMain(MyWin,Normal)
FreeAllMem() 
See also AllocString,Free,Alloc    

Syntax:      include llrtns.ew
             a = HeapAlloc(atom heap,atom size)
             
Description: 
The HeapAlloc function allocates a block of memory from a heap. 
The allocated memory is not movable.                           
If HeapAlloc succeeds, it allocates at least the amount of memory 
requested. If the actual amount allocated is greater than the amount 
 requested, the process can use the entire amount. To determine the 
actual size of the allocated block, use the HeapSize function.              
To free a block of memory allocated by HeapAlloc, use the HeapFree 
function. The allocated memory  is initialized to zero.             
Returns 0 on failure or pointer to allocated memory 
See Also HeapFree,HeapCreate,HeapDestroy,HeapValidate,Creating your Custom Memory Heaps

Syntax:      include llrtns.ew
             a = HeapCreate(size)
Description: 
This function allocates a private heap object.The function reserves 
a contiguous block in the virtual address space of the process and 
allocates an initial physical storage block of size bytes.
Notes: 
The HeapCreate function creates a private heap object from which the 
calling process can allocate memory blocks by using the HeapAlloc 
function. The memory of a private heap object is accessible only to 
the process that created it. if you allocate more than size bytes
the heap grows to suit your needs but uses virtual memory.             
All heap functions need that you specify a handle to the heap object.
See also HeapAlloc,HeapFree,HeapValidate,HeapDestroy,Creating your Custom Memory Heaps

Syntax: include llrtns.ew
i =
HeapDestroy(heap)

Description:
The HeapDestroy function destroys the specified heap object. HeapDestroy decommits and
releases all the pages of a private heap object, and it invalidates the handle of the heap.

it returns 1 if successfull or 0 if failed

See also HeapAlloc,HeapCreate,HeapFree,HeapValidate,Creating your Custom Memory Heaps


Syntax:      include llrtns.ew
             i = HeapFree(atom heap, atom pointer)             
Description: 
 The HeapFree function frees a memory block(pointer) allocated from a heap by the HeapAlloc  
it returns 1 if successfull or 0 if it failed     
See also HeapAlloc,HeapCreate,HeapDestroy,HeapValidate,Creating your Custom Memory Heaps          

Syntax: include llrtns.ew
i =
HeapValidate()

Description:
The HeapValidate function attempts to validate a specified heap. The function scans all the memory blocks in the heap, and verifies that the heap control structures maintained by the operating system's heap manager are in a consistent state. You can also use the HeapValidate function to validate a single memory block within a specified heap, without checking the validity of the entire heap.

See Also HeapFree,HeapCreate,HeapDestroy,HeapAlloc,Creating your Custom Memory Heaps


Syntax: include llrtns.ew
        i = lstrlen(a)
Description:
  This function returns the length of a null-terminating string in 
memory a. It is mainly needed when peeking a string from memory.
It is faster to use this then peek to get a string from memory.
example:                   1) atom mem,len
		   mem = AllocString("Euphoria")
		   len = lstrlen(mem) -- len is 8
                   	    sequence answer
		   answer = peek({mem,len})-- answer is "Euphoria"
		2) Here is an example function where i use it, however you should 	
		   simply use PeekString()
		global function GetWindowText(atom id)
  			integer len_,mem_len_,ret_len
  			sequence buffer
  			  len_ = c_func(zGetWindowTextLength,{id})
   			  len_+=1
   			  mem_len_ = Alloc(len_)
 			   ret_len  = c_func(zGetWindowText,{id,mem_len_,len_})
			  if ret_len+1!=len_ then
 			   puts(1,"GetWindowText Failed to return text")
			  end if
			  buffer = peek({mem_len_,lstrlen(mem_len_)})
			  Free(mem_len_)
		  return buffer
		end function 
see also   AllocString,PeekString

Syntax:      include llrtns.ew
             s = PeekString(a)
Description: 
This function returns a null-terminating string from memory a.
It uses SafePeeku() and lstrlen(). So the above examples can be            
example:                 1) atom mem,len
		   mem = AllocString("Euphoria")
   		   sequence answer
		   answer = PeekString(mem)-- answer is "Euphoria"
		   
		2) Here is an example function where i use it, however you should 	
		   simply use PeekString()
		global function GetWindowText(atom id)
  			integer len_,mem_len_,ret_len
  			sequence buffer
  			  len_ = c_func(zGetWindowTextLength,{id})
   			  len_+=1
   			  mem_len_ = Alloc(len_)
 			   ret_len  = c_func(zGetWindowText,{id,mem_len_,len_})
			  if ret_len+1!=len_ then
 			   puts(1,"GetWindowText Failed to return text")
			  end if
			  buffer = PeekString(mem_len_)
			  Free(mem_len_)
		  return buffer
		end function   

See also   lstrlen,AllocString		

Syntax:      include llrtns.ew
             i = SafePeek2s(a1)
             or 
             s = SafePeek2s({a1,i})
Description: 
Return a signed word(2-byte) in the range -32768  to
32767 from machine address a1, or return a sequence
containing i consecutive 2-byte signed values starting at address
a1 in memory.
Note: 
This is also a missing function in Standard Euphoria that is needed
a lot in Win32 API. It tests for Read-Access before actaully peeking the
signed word
See also   SafePoke2,SafePeek2u

Syntax:      include llrtns.ew
             i = SafePeek2u(a1)
             or 
             s = SafePeek2u({a1,i})
Description: 
Return a unsigned word(2-byte) in the range 0 to
65535 from machine address a1, or return a sequence
containing i consecutive 2-byte unsigned values starting at address
a1 in memory.
Note: 
This is also a missing function in Standard Euphoria that is needed
a lot in Win32 API. It tests for Read-Access before actaully peeking the
unsigned word
See also SafePeek2s,SafePoke2

 Syntax:      a2 = SafePeek4s(a1)
              or ...
              s = SafePeek4s({a1, i})
 Description: 
Return a 4-byte (32-bit) signed value in the range -2147483648 to
+2147483647 from machine address a1, or return a sequence
containing i consecutive 4-byte signed values starting at address
a1 in memory.
Note:
This function is identical to that one found in Std Eu only that
This one checks for read-access. For more information read about
peek4s
See also SafePeek4u,SafePoke4

Syntax:      a2 = SafePeek4u(a1)
              or ...
              s = SafePeek4u({a1, i})
 Description: 
Return a 4-byte (32-bit) unsigned value in the range 0 to
4294967295 from machine address a1, or return a sequence
containing i consecutive 4-byte unsigned values starting at
address a1 in memory.
Note: 
This function is identical to that one found in Std Eu only that
This one checks for read-access. For more information read about
peek4u

See also SafePeek4s,SafePoke4   

Syntax:      include llrtns.ew
             a = SafePeeks(a)
             or 
             s = SafePeeks({a,i})
 Description:
 Return a single signed byte value in the range  -128 to 127  from machine
 address a, or return a sequence containing i consecutive byte
values starting at address a in memory.
Note: 
This function is missing with standard Euphoria. It also uses safe 
peeking by testing memory for Read Access before actually reading
the signed byte from memory.  
See also SafePeeku,SafePoke	        

Syntax:      include llrtns.ew
             i = SafePeeku(a)
             or 
             s = SafePeeku({a,i})
 Description: 
Return a single unsigned byte value in the range 0 to 255 from machine
address a, or return a sequence containing i consecutive byte
values starting at address a in memory.
Note: 
This is a safer version of Euphoria peek(). It works the same as peek
but is safer as in it tests if read access is allowed for the byte
it is going to read. For more information check out Euphorias peek()              
See also SafePeeks,SafePoke

 Syntax:      include llrtns.ew
		SafePoke(a, x)
 Description:
 If x is an atom, write a single byte value to memory address a.
If x is a sequence, write a sequence of byte values to
consecutive memory locations starting at location a.For more
read about Euphorias poke()
Note: 
Similar to Euphorias poke but tests if write - access to the memory
is permitted before poking.
See also SafePeeku,SafePeeks

 Syntax:      SafePoke2(a, x)
 Description: 
If x is an atom, write a 2-byte value(word) to memory address a.
If x is a sequence, write a sequence of 2-byte values to
consecutive memory locations starting at location a. 
It checks if write-access is permitted to a, before poking
See also SafePeek2s,SafePeek2u              

 Syntax:      SafePoke4(a, x)
 Description: 
If x is an atom, write a 4-byte (32-bit) value to memory address
a.
 If x is a sequence, write a sequence of 4-byte values to
consecutive memory locations starting at location a.

 Notes  
It checks if write-access is permitted to a, before poking.
For more information check out poke4 that comes with Std Eu

See also SafePeek4s,SafePeek4u
-- Distribution Status
-- -------------------
-- This software is being contributed to the Public Domain.
-- Feel free to use it, abuse it, and/or modify it for any purpose.
-- Send bug reports or feature requests to:
--      jorfergie03@yahoo.com 
--
--
-- Disclaimer
-- ----------
-- I am in no way responsible for any damage, data loss, or any other
-- adverse effects resulting from the use/abuse/etc. of this library.