Personal tools
From wiki.swiftlytilting.com
Jump to: navigation, search

WinBinder Manual/wb call function

Contents

Syntax

int wb_call_function (int address [, array args])
  • address is a pointer to a DLL function.
  • args is an optional array of parameters that must match those of the function being called.
NOTE: Function arguments are limited to a maximum of 20.

Returns

Returns an integer that may be a valid value or a pointer to one object, according to the library function called.

Extending WinBinder with foreign functions

You must perform the following steps to use a foreign function with WinBinder:

  1. Load a DLL that contains the function using wb_load_library().
  2. Get function address with wb_get_function_address().
  3. Declare constants for all structures, if any (detailed below).
  4. Create a PHP function that uses the foreign function using pack() and unpack() to pass and retrieve any structures.
  5. Call the newly declared PHP function as any other regular PHP function.

Passing and retrieving structures

The pack() function should be used to pass a structure to a foreign function. Similarly, the unpack() function can retrieve structure fields as an associative array. Some common Windows types and their corresponding format characters for pack() / unpack() are listed in the table below.

Windows ANSI C pack() bytes
BYTEunsigned charC1
DWORDunsigned longV4
HANDLE¹void *V4
LONGlongl4
LPARAMlongl4
LPTSTR, LPCTSTRunsigned short *V4
LRESULTlongl4
UINTunsigned intI4
WORDunsigned shortv2
WPARAMunsigned intI4
¹ Note: Most Windows and GDI handles, like HINSTANCE, HWND, HACCEL, HBITMAP, HICON etc. are 32-bit handles and should be packed identically.

Defining constants

Up to three constants are needed for each structure. The best way is to define them in advance to improve code readability. For example, the Windows API documentation defines a MEMORYSTATUS structure that is passed to the GlobalMemoryStatus() function to retrieve information about the system memory. The definition is as follows:

typedef struct _MEMORYSTATUS {
    DWORD dwLength;        // sizeof(MEMORYSTATUS)
    DWORD dwMemoryLoad;    // percent of memory in use
    DWORD dwTotalPhys;     // bytes of physical memory
    DWORD dwAvailPhys;     // free physical memory bytes
    DWORD dwTotalPageFile; // bytes of paging file
    DWORD dwAvailPageFile; // free bytes of paging file
    DWORD dwTotalVirtual;  // user bytes of address space
    DWORD dwAvailVirtual;  // free user bytes
} MEMORYSTATUS;

Because the structure consists of eight DWORDs, we can create a constant to format the structure like this:

define("MEMORYSTATUS_RAW",    "VVVVVVVV");

or

define("MEMORYSTATUS_RAW",    "V8");

This is enough to pass the structure to the function. To retrieve the structure, however, we need a different structure so that unpack() function can return an associative array with the field names:

define("MEMORYSTATUS",        "Vlen/Vmemload/Vphys/Vavailphys/Vpagefile/Vavailpagefile/Vvirtual/Vavailvirtual")

Finally, because we must also pass the size of the structure, we define another constant:

define("MEMORYSTATUS_SIZE",   8 * 4);

Examples

The mini-program below shows how to call a Windows function in a single PHP line.

<?
// Shows the current ANSI code-page identifier for the operating system.

include "../include/winbinder.php";

wb_message_box(0, "ANSI code-page identifier: " . wb_call_function(wb_get_function_address("GetACP", wb_load_library("KERNEL"))));

?>

The example below shows how to create a new PHP function that calls a Windows function.

<?
include "../include/winbinder.php";                         // Location of WinBinder library

// STEP 1: Load the DLL that contains the function

$KERNEL = wb_load_library("KERNEL");

// STEP 2: Get function address

$fgms = wb_get_function_address("GlobalMemoryStatus", $KERNEL);

// STEP 3: Declare constants for all structures

define("MEMORYSTATUS",        "Vlen/Vmemload/Vphys/Vavailphys/Vpagefile/Vavailpagefile/Vvirtual/Vavailvirtual");
define("MEMORYSTATUS_RAW",    "V8");
define("MEMORYSTATUS_SIZE",   8 * 4);

// STEP 4: Create function that uses foreign function

function GlobalMemoryStatus()
{
    global $KERNEL, $fgms;
 
    $val = pack(MEMORYSTATUS_RAW, MEMORYSTATUS_SIZE,0,0,0,0,0,0,0);
    wb_call_function($fgms, array($val));
    return unpack(MEMORYSTATUS, $val);
}
 
// STEP 5: Use the newly declared PHP function as any other regular PHP function.
 
$mem = GlobalMemoryStatus();
$report =  "Total RAM is " . sprintf("%.2f", ($mem["phys"] / (1024 * 1024))) . " MB, " . $mem["memload"] . "% used";
wb_message_box(null, $report);

?>

Examples from dll_functions.phpw

One-parameter function

Parameters are passed in a array. In the following example we pass only one parameter. Our function simply returns the result from wb_call_function().

function GetSystemMetrics($what)
{
	global $USER, $KERNEL, $GDI;
	static $pfn = null;

	if($pfn === null)
	$pfn = wb_get_function_address("GetSystemMetrics", $USER);

	return wb_call_function($pfn, array($what));
}

How to return a string pointer

If our function returns a string pointer we need to wrap a wb_peek() around the wb_call_function() in order to read the returning memory address. That address contains the real value.

function GetCommandLine()
{
	global $USER, $KERNEL, $GDI;
	static $pfn = null;

	if($pfn === null)
	$pfn = wb_get_function_address("GetCommandLine", $KERNEL);

	return wb_peek(wb_call_function($pfn));
}

How to return a structure

If we going to get a structure in return we have to define it first.

define("SYSTEMTIME",			"vyear/vmonth/vdayofweek/vday/vhour/vminute/vsecond/vms");
define("SYSTEMTIME_RAW",		"v8");
define("SYSTEMTIME_SIZE",		8 * 2);

In this case we need to pass a large enough variable to the function (GetSystemTime) to hold the returning data. This can be done with str_repeat and the so called null-character (a backslash and a zero). From our definition we know the maximum size of the structure (see table above). We can now pass this variable as parameter as usual. The difference here is that we unpack the variable $val after wb_call_function() based on our definied structure 'SYSTEMTIME'.

function GetSystemTime()
{
	global $USER, $KERNEL, $GDI;
	static $pfn = null;

	if($pfn === null)
	$pfn = wb_get_function_address("GetSystemTime", $KERNEL);

	$val = str_repeat("\0", SYSTEMTIME_SIZE); // create a large enough variable

	wb_call_function($pfn, array($val));

	return unpack(SYSTEMTIME, $val); // unpack it
}

How to pass values to a structure and return the structure

The structure of MEMORYSTATUS consists of 8 values. The first value is the size of the structure according to the struct decleration. The other 7 values are zeros because they are supposed to be changed by the function. The variable $var now contains the struct we want to pass to the function. After we have called the function $val has most likely been changed and we then return it by using the unpack function as described above to get an array of all values the structure offers.

function GlobalMemoryStatus()
{
	global $USER, $KERNEL, $GDI;
	static $pfn = null;

	if($pfn === null)
	$pfn = wb_get_function_address("GlobalMemoryStatus", $KERNEL);

	$val = pack(MEMORYSTATUS_RAW, MEMORYSTATUS_SIZE, 0, 0, 0, 0, 0, 0, 0);
	wb_call_function($pfn, array($val));

	return unpack(MEMORYSTATUS, $val);
}

Note: In this example only zeros are packed. This is requested by the function; Of course you could pack other values and variables if necessary. Sometimes values within a struct also act as parameters.

Example: $val = pack(CUSTOMSTRUCT, $size, 5, 1, 20, $somevar, "example", $another_pointer, $another_struct);

See also

Winbinder Projects