#if HAVE_W32API
#include <stdio.h>
#include <stdlib.h>
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
#include "ext/standard/php_string.h"
#include "php_w32api.h"
#ifdef COMPILE_DL_W32API
ZEND_GET_MODULE(w32api)
#endif
zend_module_entry w32api_module_entry = {
STANDARD_MODULE_HEADER,
"Win32 API",
NULL,
PHP_MINIT(w32api),
PHP_MSHUTDOWN(w32api),
PHP_RINIT(w32api),
PHP_RSHUTDOWN(w32api),
PHP_MINFO(w32api),
"0.2",
STANDARD_MODULE_PROPERTIES
};
PHP_MINIT_FUNCTION(w32api)
{
ZEND_INIT_MODULE_GLOBALS(w32api, php_w32api_init_globals, NULL);
if(win32_class_init(TSRMLS_C) != SUCCESS)
{
return FAILURE;
}
if(type_class_init(TSRMLS_C) != SUCCESS)
{
return FAILURE;
}
WG(le_type_instance) = zend_register_list_destructors_ex(w32api_type_instance_dtor, NULL, "Type Instance", module_number);
REGISTER_LONG_CONSTANT( "W32API_ARGPTR", W32API_ARGPTR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT( "W32API_BORLAND", W32API_BORLAND, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT( "W32API_CDECL", W32API_CDECL, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT( "W32API_REAL4", W32API_REAL4, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT( "W32API_REAL8", W32API_REAL8, CONST_CS | CONST_PERSISTENT);
return SUCCESS;
};
PHP_MSHUTDOWN_FUNCTION(w32api)
{
return SUCCESS;
}
PHP_RINIT_FUNCTION(w32api)
{
HashTable *tmp;
WG(funcs) = WG(libraries) = WG(callbacks) = WG(types) = NULL;
ALLOC_HASHTABLE(tmp);
zend_hash_init(tmp, 1, NULL, php_w32api_hash_func_dtor, 1);
WG(funcs) = tmp;
ALLOC_HASHTABLE(tmp);
zend_hash_init(tmp, 1, NULL, php_w32api_hash_lib_dtor, 1);
WG(libraries) = tmp;
ALLOC_HASHTABLE(tmp);
zend_hash_init(tmp, 1, NULL, php_w32api_hash_callback_dtor, 1);
WG(callbacks) = tmp;
ALLOC_HASHTABLE(tmp);
zend_hash_init(tmp, 1, NULL, php_w32api_hash_type_dtor, 1);
WG(types) = tmp;
return SUCCESS;
};
PHP_RSHUTDOWN_FUNCTION(w32api)
{
win32_class_rshutdown(TSRMLS_C);
zend_hash_destroy(WG(funcs));
FREE_HASHTABLE(WG(funcs));
zend_hash_destroy(WG(libraries));
FREE_HASHTABLE(WG(libraries));
zend_hash_destroy(WG(callbacks));
FREE_HASHTABLE(WG(callbacks));
zend_hash_destroy(WG(types));
FREE_HASHTABLE(WG(types));
WG(funcs) = WG(libraries) = WG(callbacks) = WG(types) = NULL;
return SUCCESS;
}
PHP_MINFO_FUNCTION(w32api)
{
php_info_print_table_start();
php_info_print_table_row(2, "Win32 API Support", "enabled" );
php_info_print_table_end();
}
static void php_w32api_init_globals(zend_w32api_globals *w32api_globals)
{
w32api_globals->win32_ce = NULL;
w32api_globals->type_ce = NULL;
w32api_globals->funcs = NULL;
w32api_globals->libraries = NULL;
w32api_globals->callbacks = NULL;
w32api_globals->types = NULL;
}
static void php_w32api_hash_lib_dtor(void *data)
{
w32api_lib_handle *lh;
TSRMLS_FETCH();
lh = (w32api_lib_handle *)data;
FreeLibrary(lh->handle);
efree(lh->library_name);
}
static void php_w32api_hash_func_dtor(void *data)
{
w32api_func_handle **fh;
TSRMLS_FETCH();
fh = (w32api_func_handle **)data;
php_w32api_unload_function(fh TSRMLS_CC);
}
static void php_w32api_hash_callback_dtor(void *data)
{
w32api_func_handle **fh;
fh = (w32api_func_handle **)data;
php_w32api_free_arguments((*fh)->argument_list);
efree((*fh)->function_name);
if((*fh)->return_type_name)
efree((*fh)->return_type_name);
efree(*fh);
}
static void php_w32api_hash_type_dtor(void *data)
{
w32api_type_handle **th;
th = (w32api_type_handle **)data;
php_w32api_free_members((*th)->member_list);
efree((*th)->type_name);
efree(*th);
}
static void w32api_type_instance_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
w32api_type_instance *ti;
int i = 0;
if(!rsrc || !rsrc->ptr)
return;
ti = (w32api_type_instance *)rsrc->ptr;
for(i = 0; i < ti->type->member_count; i++)
{
if(ti->values[i])
zval_ptr_dtor(&ti->values[i]);
}
efree(ti);
return;
}
static void php_w32api_unload_library (w32api_lib_handle *lh, int flags TSRMLS_DC)
{
if(flags == 0)
{
lh->ref_count--;
}
if((flags == 1) || (lh->ref_count == 0))
{
zend_hash_del(WG(libraries), lh->library_name, strlen(lh->library_name) + 1);
}
}
static void php_w32api_unload_function (w32api_func_handle **fh TSRMLS_DC)
{
zend_function *function = NULL;
efree((*fh)->return_type_name);
php_w32api_free_arguments((*fh)->argument_list);
if(zend_hash_find( &WG(win32_ce)->function_table,
(*fh)->function_name,
strlen((*fh)->function_name) + 1,
(void **)&function) == SUCCESS)
{
zend_internal_function *internal_function = (zend_internal_function *)function;
if(internal_function->arg_types)
efree(internal_function->arg_types);
}
zend_hash_del(&WG(win32_ce)->function_table, (*fh)->function_name, strlen((*fh)->function_name) + 1);
php_w32api_unload_library((*fh)->lib, 0 TSRMLS_CC);
efree((*fh)->function_name);
efree(*fh);
}
static int php_w32api_load_function (char *definition, int definition_len, int flags TSRMLS_DC)
{
zend_function function;
zend_internal_function *internal_function = (zend_internal_function *)&function;
w32api_func_handle **fh;
w32api_func_handle_ptr hnd;
fh = emalloc(sizeof(w32api_func_handle *));
*fh = NULL;
w32api_function_definition_scan_bytes(definition, definition_len);
if((w32api_function_definition_parse((void *)&hnd) != 0))
{
*fh = hnd.hnd;
if(*fh != NULL)
efree(*fh);
efree(fh);
return FAILURE;
}
*fh = hnd.hnd;
if(!*fh)
return FAILURE;
if(zend_hash_exists(&WG(win32_ce)->function_table, (*fh)->function_name, strlen((*fh)->function_name) + 1))
{
php_error( E_WARNING,
"A function by the name %s already has been registered, cannot redefine function",
(*fh)->function_name);
php_w32api_unload_library((*fh)->lib, 0 TSRMLS_CC);
php_w32api_free_arguments((*fh)->argument_list);
efree((*fh)->return_type_name);
efree((*fh)->function_name);
efree(*fh);
efree(fh);
return FAILURE;
}
if(zend_hash_add( WG(funcs),
(*fh)->function_name,
strlen((*fh)->function_name) + 1,
fh,
sizeof(w32api_func_handle),
NULL) != SUCCESS)
{
php_error( E_WARNING,
"Loading of function %s failed: Could not insert function handle into hash",
(*fh)->function_name);
zend_hash_del(WG(funcs), (*fh)->function_name, strlen((*fh)->function_name) +1);
return FAILURE;
}
internal_function->type = ZEND_INTERNAL_FUNCTION;
internal_function->handler = W32API_CLASS_FN(win32, invokefunction);
internal_function->function_name = (*fh)->function_name;
internal_function->arg_types = php_w32api_do_arg_types(&(*fh)->argument_list);
if(zend_hash_add(&WG(win32_ce)->function_table, (*fh)->function_name,
strlen((*fh)->function_name) + 1, &function, sizeof(zend_function), NULL) == FAILURE)
{
php_error(E_ERROR, "Could not register function %s into function table", (*fh)->function_name);
zend_hash_del(WG(funcs), (*fh)->function_name, strlen((*fh)->function_name) +1);
return FAILURE;;
}
if(flags)
{
(*fh)->flags = (*fh)->flags | flags;
}
return SUCCESS;
}
static void php_w32api_unload_type (w32api_type_handle **th TSRMLS_DC)
{
php_w32api_free_members((*th)->member_list);
zend_hash_del(WG(types), (*th)->type_name, strlen((*th)->type_name) + 1);
}
static int php_w32api_register_type(char *type_definition, int type_definition_len TSRMLS_DC)
{
w32api_type_handle **th;
w32api_type_handle_ptr hnd;
th = emalloc(sizeof(w32api_type_handle *));
*th = NULL;
w32api_type_definition_scan_bytes(type_definition, type_definition_len);
if(w32api_type_definition_parse((void *)&hnd) != 0)
{
*th = hnd.hnd;
if(*th != NULL)
efree(*th);
efree(th);
return FAILURE;
}
*th = hnd.hnd;
if(!*th)
return FAILURE;
if((zend_hash_exists(WG(callbacks), (*th)->type_name, strlen((*th)->type_name) +1)) ||
(zend_hash_exists(WG(types), (*th)->type_name, strlen((*th)->type_name) + 1)))
{
php_error( E_WARNING,
"A type or callback by the name %s already has been registered, cannot redefine type or callback",
(*th)->type_name);
php_w32api_free_members((*th)->member_list);
efree((*th)->type_name);
efree(*th);
efree(th);
return FAILURE;
}
if(zend_hash_add( WG(types),
(*th)->type_name,
strlen((*th)->type_name) + 1,
th,
sizeof(w32api_type_handle *),
NULL) != SUCCESS)
{
php_error( E_WARNING,
"Loading of type %s failed: Could not insert type handle into hash",
(*th)->type_name);
zend_hash_del(WG(types), (*th)->type_name, strlen((*th)->type_name) + 1);
return FAILURE;
}
return SUCCESS;
}
static int php_w32api_register_callback(char *function_definition, int function_definition_len TSRMLS_DC)
{
w32api_func_handle **fh;
w32api_func_handle_ptr hnd;
char *new_definition = NULL;
fh = emalloc(sizeof(w32api_func_handle *));
*fh = NULL;
new_definition = emalloc(function_definition_len + sizeof(" from cb.cb"));
snprintf(new_definition, function_definition_len + sizeof(" from cb.cb"), "%s from cb.cb", function_definition);
w32api_function_definition_scan_bytes(new_definition, function_definition_len + sizeof(" from cb.cb"));
if(w32api_function_definition_parse((void *)&hnd) != 0)
{
*fh = hnd.hnd;
if(*fh != NULL)
efree(*fh);
efree(fh);
return FAILURE;
}
*fh = hnd.hnd;
if(!*fh)
return FAILURE;
if(zend_hash_exists(WG(callbacks), (*fh)->function_name, strlen((*fh)->function_name) + 1))
{
php_error( E_WARNING,
"A callback by the name %s already has been registered, cannot redefine type",
(*fh)->function_name);
php_w32api_free_arguments((*fh)->argument_list);
efree((*fh)->return_type_name);
efree((*fh)->function_name);
efree(*fh);
efree(fh);
return FAILURE;
}
if(zend_hash_add( WG(callbacks),
(*fh)->function_name,
strlen((*fh)->function_name) + 1,
fh,
sizeof(w32api_func_handle *),
NULL) != SUCCESS)
{
php_error( E_WARNING,
"Loading of function %s failed: Could not insert function handle into hash",
(*fh)->function_name);
zend_hash_del(WG(callbacks), (*fh)->function_name, strlen((*fh)->function_name) + 1);
return FAILURE;
}
return SUCCESS;
}
static void php_w32api_free_arguments(arguments *argument_list)
{
if(argument_list == NULL)
return;
efree(argument_list->arg->argument_name);
efree(argument_list->arg->type_name);
efree(argument_list->arg);
if(argument_list->next_arg != NULL)
{
php_w32api_free_arguments(argument_list->next_arg);
}
efree(argument_list);
return;
}
static void php_w32api_free_members(members *member_list)
{
if(member_list == NULL)
return;
efree(member_list->member->member_name);
if(member_list->member->member_type_name != NULL)
efree(member_list->member->member_type_name);
efree(member_list->member);
php_w32api_free_members(member_list->next_member);
efree(member_list);
return;
}
static int php_w32api_load_library (char *library_name, w32api_lib_handle **lh TSRMLS_DC)
{
if(zend_hash_find(WG(libraries), library_name, strlen(library_name) + 1, (void **)lh) == SUCCESS)
{
(*lh)->ref_count++;
return SUCCESS;
}
*lh = (w32api_lib_handle *) emalloc( sizeof(w32api_lib_handle) );
(*lh)->ref_count = 1;
(*lh)->library_name = estrdup(library_name);
(*lh)->handle = LoadLibrary((*lh)->library_name);
if(!(*lh)->handle)
{
LPVOID message_buffer;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&message_buffer,
0,
NULL);
efree((*lh)->library_name);
efree(*lh);
efree(lh);
php_error(E_WARNING, "Loading of library failed: %s", message_buffer);
LocalFree(message_buffer);
return FAILURE;
}
if(zend_hash_add( WG(libraries),
(*lh)->library_name,
strlen((*lh)->library_name) + 1,
*lh,
sizeof(w32api_lib_handle),
NULL) != SUCCESS)
{
php_error( E_WARNING,
"Loading of library %s failed: Could not insert library handle into hash",
(*lh)->library_name);
efree((*lh)->library_name);
efree(*lh);
efree(lh);
return FAILURE;
}
return SUCCESS;
}
static unsigned char *php_w32api_do_arg_types(arguments **argument_list)
{
int i = 0;
int j = 0;
arguments *curr_arg = NULL;
unsigned char *retval = NULL;
if(!(argument_list) || !(*argument_list))
return NULL;
curr_arg = *argument_list;
while(curr_arg)
{
i++;
if(curr_arg->arg->flags & BYREF_FORCE)
{
j = i;
}
curr_arg = curr_arg->next_arg;
}
if( j == 0 )
return NULL;
retval = (unsigned char *)emalloc(sizeof(unsigned char) * j + 1);
retval[0] = (unsigned char)j;
curr_arg = *argument_list;
for(i=1; i <= j; i++)
{
retval[i] = (unsigned char)curr_arg->arg->flags;
curr_arg = curr_arg->next_arg;
}
return retval;
}
static int php_w32api_get_type_size(int type_id, char *type_name, int flags)
{
TSRMLS_FETCH();
if(flags & BYREF_FORCE)
{
return sizeof(void *);
}
switch(type_id)
{
case W32API_NULL:
return sizeof(void *);
case W32API_INT:
return sizeof(int);
case W32API_LONG:
return sizeof(long);
case W32API_DOUBLE:
return sizeof(double);
case W32API_FLOAT:
return sizeof(float);
case W32API_STRING:
return sizeof(char *);
case W32API_BYTE:
return sizeof(char);
case W32API_BOOL:
return sizeof(int);
case W32API_COMPLEX:
{
w32api_type_handle **th;
if(zend_hash_find(WG(types), type_name, strlen(type_name) +1, (void **)&th) != SUCCESS)
{
php_error(E_ERROR, "Unknown type %s", type_name);
return -1;
}
return (*th)->size;
}
break;
case W32API_UNKNOWN:
default:
php_error(E_ERROR, "Unknown type %s", type_name);
return -1;
}
}
static int php_w32api_get_type_id_from_name(char *type)
{
TSRMLS_FETCH();
if(!strcmp(type, "long"))
{
return W32API_LONG;
}
else if(!strcmp(type, "int"))
{
return W32API_INT;
}
else if (!strcmp(type, "string"))
{
return W32API_STRING;
}
else if (!strcmp(type, "byte"))
{
return W32API_BYTE;
}
else if (!strcmp(type, "bool"))
{
return W32API_BOOL;
}
else if (!strcmp(type, "double"))
{
return W32API_DOUBLE;
}
else if (!strcmp(type, "float"))
{
return W32API_FLOAT;
}
else if (!strcmp(type, "void"))
{
return W32API_NULL;
}
else
{
if(zend_hash_exists(WG(types), type, strlen(type) +1))
{
return W32API_COMPLEX;
}
else
{
return W32API_UNKNOWN;
}
}
}
static void php_w32api_init_type(w32api_type_handle *th, zval *obj TSRMLS_DC)
{
w32api_type_instance *ti;
zval *rsrc_handle = NULL;
ti = emalloc(sizeof(w32api_type_instance));
if(!obj)
MAKE_STD_ZVAL(obj);
object_init_ex(obj, WG(type_ce));
ti->type = th;
ti->values = emalloc(sizeof(zval *) * th->member_count);
memset(ti->values, '\0', sizeof(zval *) * th->member_count);
MAKE_STD_ZVAL(rsrc_handle);
ZEND_REGISTER_RESOURCE(rsrc_handle, ti, WG(le_type_instance));
zend_hash_index_update(Z_OBJPROP_P(obj), 0, &rsrc_handle, sizeof(zval *), NULL);
}
static int php_w32api_do_prop_get(zval *object, zval *return_value, zend_llist_element **element TSRMLS_DC)
{
w32api_type_instance *th;
zval **type_instance_handle;
members *current_member;
char *property_name;
int i = 0;
zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &type_instance_handle);
th = (w32api_type_instance *)zend_fetch_resource(type_instance_handle TSRMLS_CC,
-1, "Complex Type Instance", NULL,
1, WG(le_type_instance));
if(!th)
return FAILURE;
property_name = Z_STRVAL(((zend_overloaded_element *)(*element)->data)->element);
current_member = th->type->member_list;
while(strcmp(current_member->member->member_name, property_name) != 0)
{
i++;
if(current_member->next_member != NULL)
current_member = current_member->next_member;
else
return FAILURE;
}
*return_value = *(th->values[i]);
zval_copy_ctor(return_value);
return SUCCESS;
}
static int php_w32api_do_prop_set(zval *object, zval *value, zend_llist_element **element TSRMLS_DC)
{
w32api_type_instance *th;
zval **type_instance_handle;
zval *new_var;
members *current_member;
char *property_name;
int i = 0;
zend_hash_index_find(Z_OBJPROP_P(object), 0, (void **) &type_instance_handle);
th = (w32api_type_instance *)zend_fetch_resource(type_instance_handle TSRMLS_CC,
-1, "Complex Type Instance", NULL,
1, WG(le_type_instance));
if(!th)
return FAILURE;
property_name = Z_STRVAL(((zend_overloaded_element *)(*element)->data)->element);
current_member = th->type->member_list;
while(strcmp(current_member->member->member_name, property_name) != 0)
{
i++;
if(current_member->next_member != NULL)
current_member = current_member->next_member;
else
return FAILURE;
}
if(current_member->member->flags & BYREF_FORCE)
{
if(th->values[i])
zval_ptr_dtor(&th->values[i]);
MAKE_STD_ZVAL(new_var);
*new_var = *value;
zval_copy_ctor(new_var);
th->values[i] = new_var;
}
else
{
th->values[i] = value;
zval_add_ref(&value);
}
return SUCCESS;
}
w32api_result php_w32api_do_dynamic_dll_call(w32api_func_handle *fh, int argc, w32api_dynamic_param *params, void *return_buffer, int return_buffer_size)
{
w32api_result result = { 0 };
DWORD *stack_pointer, stack_size = 0, eaxv, edxv;
BYTE *arg_ptr = NULL;
int size = 0, i = 0;
FARPROC fp = fh->handle;
_asm mov stack_pointer, esp _asm sub esp, 0x100
for(i = (argc - 1); i >= 0; i--)
{
size = (params[i].width + 3)/4 * 4;
arg_ptr = (unsigned char *)params[i].argument_ptr + size - 4;
stack_size += (unsigned long)size;
while(size > 0)
{
stack_pointer--;
if(params[i].flags == W32API_ARGPTR)
{
*stack_pointer = *(unsigned long *)arg_ptr;
arg_ptr -= 4;
}
else
{
*stack_pointer = params[i].argument;
}
size -= 4;
}
}
if((return_buffer) && ((fh->flags & W32API_BORLAND) || (return_buffer_size > 8)))
{
stack_size += 4;
stack_pointer--;
*stack_pointer = (unsigned long)return_buffer;
}
_asm add esp, 0x100
_asm sub esp, stack_size
_asm call [fp]
_asm mov eaxv, eax
_asm mov edxv, edx
if(fh->flags & W32API_CDECL)
{
_asm add esp, stack_size
}
if(fh->flags & W32API_REAL4)
_asm fstp dword ptr [result]
else if (fh->flags & W32API_REAL8)
_asm fstp qword ptr [result]
else if (!return_buffer)
{
_asm mov eax, [eaxv]
_asm mov edx, [edxv]
_asm mov DWORD PTR [result], eax
_asm mov DWORD PTR [result + 4], edx
}
else if (!(fh->flags & W32API_BORLAND) && (return_buffer_size <= 8))
{
_asm mov ecx, DWORD PTR [return_buffer]
_asm mov eax, [eaxv]
_asm mov DWORD PTR [ecx], eax
_asm mov edx, [edxv]
_asm mov DWORD PTR [ecx + 4], edx
}
return result;
}
void php_w32api_marshall_zval_to_c(argument *arg, w32api_dynamic_param *dp, zval *pzval TSRMLS_DC)
{
dp->flags = 0;
switch(arg->type_id)
{
case W32API_INT:
convert_to_long_ex(&pzval);
if(arg->flags & BYREF_FORCE)
{
dp->argument = (unsigned long)&pzval->value.lval;
dp->width = sizeof(int *);
}
else
{
dp->argument = (int)pzval->value.lval;
dp->width = sizeof(int);
}
break;
case W32API_LONG:
convert_to_long_ex(&pzval);
if(arg->flags & BYREF_FORCE)
{
dp->argument = (unsigned long)&pzval->value.lval;
dp->width = sizeof(int *);
zval_add_ref(&pzval);
}
else
{
dp->argument = pzval->value.lval;
dp->width = sizeof(int);
}
break;
case W32API_STRING:
convert_to_string_ex(&pzval);
if(!(arg->flags & BYREF_FORCE))
{
dp->argument = (unsigned long)estrndup(Z_STRVAL_P(pzval), Z_STRLEN_P(pzval));
}
else
{
dp->argument = (unsigned long)Z_STRVAL_P(pzval);
zval_add_ref(&pzval);
}
dp->width = sizeof(char *);
break;
case W32API_DOUBLE:
convert_to_double_ex(&pzval);
if(arg->flags & BYREF_FORCE)
{
dp->argument = (unsigned long)&pzval->value.dval;
dp->width = sizeof(double *);
zval_add_ref(&pzval);
}
else
{
dp->argument_ptr = &pzval->value.dval;
dp->width = sizeof(double);
dp->flags = W32API_ARGPTR;
}
break;
case W32API_FLOAT:
convert_to_double_ex(&pzval);
if(arg->flags & BYREF_FORCE)
{
dp->argument = (unsigned long)&pzval->value.dval;
dp->width = sizeof(double *);
zval_add_ref(&pzval);
}
else
{
dp->argument_ptr = &pzval->value.dval;
dp->width = sizeof(float);
dp->flags = W32API_ARGPTR;
}
break;
case W32API_BYTE:
convert_to_string_ex(&pzval);
if(arg->flags & BYREF_FORCE)
{
dp->argument = (unsigned long)&Z_STRVAL_P(pzval);
dp->width = sizeof(char *);
zval_add_ref(&pzval);
}
else
{
dp->argument = (char)Z_STRVAL_P(pzval)[0];
dp->width = sizeof(char);
}
break;
case W32API_BOOL:
convert_to_boolean_ex(&pzval);
if(arg->flags & BYREF_FORCE)
{
dp->argument = (unsigned long)&pzval->value.lval;
dp->width = sizeof(int *);
zval_add_ref(&pzval);
}
else
{
dp->argument = (int)pzval->value.lval;
dp->width = sizeof(int);
}
break;
case W32API_COMPLEX:
if(Z_TYPE_P(pzval) != IS_OBJECT)
{
php_error(E_ERROR, "Variable passed as complex value is not an object");
break;
}
if(arg->flags & BYREF_FORCE)
{
int width= 0;
void **ptr = NULL;
ptr = emalloc(sizeof(void *));
*ptr = php_w32api_complex_marshall_zval_to_c(pzval, &width, NULL TSRMLS_CC);
dp->argument = (unsigned long)ptr;
dp->width = width;
}
else
{
int width= 0;
dp->argument_ptr = php_w32api_complex_marshall_zval_to_c(pzval, &width, NULL TSRMLS_CC);
dp->width = width;
}
break;
case W32API_UNKNOWN:
php_error(E_ERROR, "Unknown type when calling function, marshalling failed");
break;
}
}
static void *php_w32api_complex_marshall_zval_to_c(zval *pzval, int *width, void *return_value TSRMLS_DC)
{
w32api_type_instance *th;
zval **type_instance_handle;
members *current_member;
char *offset = return_value;
int i = 0;
if(return_value == NULL)
{
}
}
function_entry win32_class_functions[] = {
W32API_CLASS_FE(win32, registerfunction, NULL)
W32API_CLASS_FE(win32, unregisterfunction, NULL)
W32API_CLASS_FE(win32, registercallback, NULL)
W32API_CLASS_FE(win32, definetype, NULL)
W32API_CLASS_FE(win32, gettypesize, NULL)
W32API_CLASS_FE(win32, inittype, NULL)
W32API_CLASS_FE(win32, decref, NULL)
#ifndef NDEBUG
W32API_CLASS_FE(win32, dump_function_hash, NULL)
W32API_CLASS_FE(win32, dump_library_hash, NULL)
W32API_CLASS_FE(win32, dump_callback_hash, NULL)
W32API_CLASS_FE(win32, dump_type_hash, NULL)
#endif
{NULL, NULL, NULL}
};
int win32_class_init(TSRMLS_D)
{
zend_class_entry ce;
INIT_CLASS_ENTRY(ce,
"win32",
win32_class_functions);
WG(win32_ce) = zend_register_internal_class(&ce TSRMLS_CC);
return SUCCESS;
}
int win32_class_rshutdown(TSRMLS_D)
{
return SUCCESS;
}
W32API_CLASS_FUNCTION(win32, registerfunction)
{
char *function_definition = NULL;
int function_definition_len;
long flags = 0;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l",
&function_definition,
&function_definition_len,
&flags) == FAILURE)
{
return;
}
if(php_w32api_load_function(function_definition, function_definition_len, flags TSRMLS_CC) != SUCCESS)
{
php_error(E_ERROR, "Registering Function %s failed", function_definition);
RETURN_FALSE;
}
RETURN_TRUE;
}
W32API_CLASS_FUNCTION(win32, unregisterfunction)
{
char *function_name = NULL;
int function_name_len;
w32api_func_handle **fh = NULL;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
&function_name,
&function_name_len) == FAILURE)
{
return;
}
zend_hash_del(WG(funcs), function_name, strlen(function_name) + 1);
RETURN_TRUE;
}
W32API_CLASS_FUNCTION(win32, registercallback)
{
char *function_definition = NULL;
int function_definition_len;
w32api_func_handle **fh = NULL;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
&function_definition,
&function_definition_len) == FAILURE)
{
return;
}
if(php_w32api_register_callback(function_definition, function_definition_len TSRMLS_CC) != SUCCESS)
{
RETURN_FALSE;
}
RETURN_TRUE;
}
W32API_CLASS_FUNCTION(win32, definetype)
{
char *type_definition = NULL;
int type_definition_len;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
&type_definition,
&type_definition_len) == FAILURE)
{
return;
}
if(php_w32api_register_type(type_definition, type_definition_len TSRMLS_CC) != SUCCESS)
{
php_error(E_ERROR, "Registering Type %s failed", type_definition);
RETURN_FALSE;
}
RETURN_TRUE;
}
W32API_CLASS_FUNCTION(win32, gettypesize)
{
char *type = NULL;
int type_len;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
&type,
&type_len) == FAILURE)
{
return;
}
RETURN_LONG(php_w32api_get_type_size(php_w32api_get_type_id_from_name(type), type, BYREF_NONE));
}
W32API_CLASS_FUNCTION(win32, inittype)
{
char *type_name = NULL;
int type_name_len = 0;
w32api_type_handle **th = NULL;
if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
&type_name, &type_name_len) == FAILURE)
{
return;
}
if(zend_hash_find(WG(types), type_name, type_name_len +1, (void **)&th) == FAILURE)
{
php_error(E_ERROR, "Could not retrieve type handle for type %s from hash table", type_name);
RETURN_FALSE;
}
php_w32api_init_type(*th, return_value TSRMLS_CC);
}
W32API_CLASS_FUNCTION(win32, decref)
{
}
W32API_CLASS_FUNCTION(win32, invokefunction)
{
char *function_name = get_active_function_name(TSRMLS_C);
int argc = ZEND_NUM_ARGS();
int i = 0;
w32api_dynamic_param *params = NULL;
w32api_dynamic_param *current_dynamic_param = NULL;
w32api_func_handle **fh = NULL;
w32api_result res = {0};
void *w32api_return_buffer = NULL;
int w32api_return_buffer_size = 0;
zval **func_arguments = NULL;
zval *current_zval = NULL;
arguments *curr_arg = NULL;
w32api_type_handle *th = NULL;
if(zend_hash_find(WG(funcs), function_name, strlen(function_name) +1, (void **)&fh) == FAILURE)
{
php_error(E_ERROR, "Could not retrieve function handle from hash table");
RETURN_FALSE;
}
if(argc)
{
if(zend_get_parameters_array_ex(argc, &func_arguments) == FAILURE)
{
WRONG_PARAM_COUNT
}
params = (w32api_dynamic_param *)emalloc(sizeof(w32api_dynamic_param) * argc);
curr_arg = (*fh)->argument_list;
current_dynamic_param = params;
for(i = 0; i < argc; i++)
{
current_zval = func_arguments[i];
php_w32api_marshall_zval_to_c(curr_arg->arg, current_dynamic_param, current_zval TSRMLS_CC);
current_dynamic_param++;
curr_arg = curr_arg->next_arg;
}
}
else
{
params = NULL;
}
if((*fh)->return_type_id == W32API_COMPLEX)
{
if(zend_hash_find(WG(types), (*fh)->return_type_name, strlen((*fh)->return_type_name) +1, (void **)&th) != SUCCESS)
php_error(E_ERROR, "Could not find type handle for type %s", (*fh)->return_type_name);
w32api_return_buffer = emalloc(th->size);
w32api_return_buffer_size = th->size;
}
res = php_w32api_do_dynamic_dll_call(*fh, argc, params, w32api_return_buffer, w32api_return_buffer_size);
if(argc)
efree(params);
switch((*fh)->return_type_id)
{
case W32API_LONG:
RETURN_LONG(res.lval);
break;
case W32API_INT:
RETURN_LONG(res.ival);
break;
case W32API_STRING:
case W32API_BYTE:
RETURN_STRING(res.ptr, 1);
break;
case W32API_DOUBLE:
RETURN_DOUBLE(res.dval);
break;
case W32API_FLOAT:
RETURN_DOUBLE(res.fval);
break;
case W32API_BOOL:
if(res.ival)
{
RETURN_TRUE;
}
else
{
RETURN_FALSE;
}
break;
case W32API_COMPLEX:
break;
default:
php_error(E_WARNING, "Unknown return type %s", (*fh)->return_type_name);
}
}
#ifndef NDEBUG
W32API_CLASS_FUNCTION(win32, dump_library_hash)
{
zend_hash_apply(WG(libraries), (apply_func_t)php_w32api_dump_library_hash_cb TSRMLS_CC);
}
W32API_CLASS_FUNCTION(win32, dump_function_hash)
{
zend_hash_apply(WG(funcs), (apply_func_t)php_w32api_dump_function_hash_cb TSRMLS_CC);
}
W32API_CLASS_FUNCTION(win32, dump_callback_hash)
{
zend_hash_apply(WG(callbacks), (apply_func_t)php_w32api_dump_callback_hash_cb TSRMLS_CC);
}
W32API_CLASS_FUNCTION(win32, dump_type_hash)
{
zend_hash_apply(WG(types), (apply_func_t)php_w32api_dump_type_hash_cb TSRMLS_CC);
}
int php_w32api_dump_library_hash_cb(void *pData TSRMLS_DC)
{
w32api_lib_handle *lh = pData;
printf("=====================================================================\n");
printf("Library Name: \t\t%s\n", lh->library_name);
printf("Reference Count: \t\t%d\n", lh->ref_count);
printf("Library Handle: \t\t%p\n", lh->handle);
printf("Lib ptr loc \t\t%p\n", lh);
printf("ll n loc \t\t%p\n", &lh->ref_count);
printf("=====================================================================\n");
return 0;
}
int php_w32api_dump_function_hash_cb(void *pData TSRMLS_DC)
{
w32api_func_handle **fh = pData;
printf("=====================================================================\n");
printf("Function Name: \t\t%s\n", (*fh)->function_name);
printf("Return Type Name: \t\t%s\n", (*fh)->return_type_name);
printf("Library Name: \t\t%s\n", (*fh)->lib->library_name );
printf("Function Flags: \t\t%d\n", (*fh)->flags);
printf("Function Handle: \t\t%p\n", (*fh)->handle);
printf("Return Type ID: \t\t%d\n", (*fh)->return_type_id);
printf("Return Type Name: \t\t%s\n", (*fh)->return_type_name);
printf("## Arguments ##\n");
printf("---------------------------------------------------------------------\n");
php_w32api_print_arguments((*fh)->argument_list);
printf("=====================================================================\n\n");
return 0;
}
int php_w32api_dump_callback_hash_cb(void *pData TSRMLS_DC)
{
w32api_func_handle **fh = pData;
printf("=====================================================================\n");
printf("Callback Name: \t\t%s\n", (*fh)->function_name);
printf("Return Type Name: \t\t%s\n", (*fh)->return_type_name);
printf("Callback Flags: \t\t%d\n", (*fh)->flags);
printf("Return Type ID: \t\t%d\n", (*fh)->return_type_id);
printf("Return Type Name: \t\t%s\n", (*fh)->return_type_name);
printf("## Arguments ##\n");
printf("---------------------------------------------------------------------\n");
php_w32api_print_arguments((*fh)->argument_list);
printf("=====================================================================\n\n");
return 0;
}
int php_w32api_dump_type_hash_cb(void *pData TSRMLS_DC)
{
w32api_type_handle **th = pData;
printf("=====================================================================\n");
printf("Type Name: \t\t%s\n", (*th)->type_name);
printf("Type Size: \t\t%d\n", (*th)->size);
printf("Member Count: \t\t%d\n", (*th)->member_count);
printf("## Members ##\n");
printf("---------------------------------------------------------------------\n");
php_w32api_print_members((*th)->member_list);
printf("=====================================================================\n\n");
return 0;
}
void php_w32api_print_members(members *member_list)
{
if(member_list == NULL)
return;
printf("\tMember Name: \t%s\n", member_list->member->member_name);
printf("\tMember Flags: \t%d\n", member_list->member->flags);
printf("\tMember Type ID: \t%d\n", member_list->member->member_type_id);
printf("\tMember Type Name:\t%s\n", member_list->member->member_type_name);
printf("\tMember Offset: \t%d\n", member_list->member->offset);
printf("---------------------------------------------------------------------\n");
php_w32api_print_members(member_list->next_member);
}
void php_w32api_print_arguments(arguments *argument_list)
{
if(argument_list == NULL)
return;
printf("\tArgument Name: \t%s\n", argument_list->arg->argument_name);
printf("\tArgument Flags: \t%d\n", argument_list->arg->flags);
printf("\tArgument Type ID:\t%d\n", argument_list->arg->type_id);
printf("\tArg Type Name: \t%s\n", argument_list->arg->type_name);
printf("---------------------------------------------------------------------\n");
php_w32api_print_arguments(argument_list->next_arg);
}
#endif
function_entry type_class_functions[] = {
W32API_CLASS_FE(type, clone, NULL)
{NULL, NULL, NULL}
};
int type_class_init(TSRMLS_D)
{
zend_class_entry ce;
INIT_OVERLOADED_CLASS_ENTRY(ce,
"type",
type_class_functions,
NULL,
W32API_PROP_GET_FUNCTION_N(type),
W32API_PROP_SET_FUNCTION_N(type));
WG(type_ce) = zend_register_internal_class(&ce TSRMLS_CC);
return SUCCESS;
}
W32API_PROP_SET_FUNCTION(type)
{
zval result, temp;
zval *temp_ptr = &temp;
zval *new_val;
zend_overloaded_element *overloaded_property;
zend_llist_element *element;
zval **object = &property_reference->object;
int setter_retval, getter_retval;
TSRMLS_FETCH();
for (element=property_reference->elements_list->head; element != property_reference->elements_list->tail; element=element->next) {
overloaded_property = (zend_overloaded_element *)element->data;
getter_retval = FAILURE;
if (Z_TYPE_P(overloaded_property) == OE_IS_OBJECT) {
if (Z_TYPE_PP(object) == IS_NULL ||
(Z_TYPE_PP(object) == IS_BOOL && Z_LVAL_PP(object) == 0) ||
(Z_TYPE_PP(object) == IS_STRING && Z_STRLEN_PP(object) == 0)) {
object_init(*object);
}
if (Z_TYPE_PP(object) != IS_OBJECT) {
return FAILURE;
}
getter_retval = php_w32api_do_prop_get(*object, &result, &element TSRMLS_CC);
if (getter_retval == SUCCESS) {
temp = result;
object = &temp_ptr;
} else {
if ((getter_retval = zend_hash_find(Z_OBJPROP_PP(object),
Z_STRVAL(overloaded_property->element),
Z_STRLEN(overloaded_property->element)+1,
(void **)&object)) == FAILURE) {
MAKE_STD_ZVAL(new_val);
ZVAL_NULL(new_val);
zend_hash_update(Z_OBJPROP_PP(object),
Z_STRVAL(overloaded_property->element),
Z_STRLEN(overloaded_property->element)+1,
&new_val, sizeof(void *), (void **)&object);
}
}
} else if (Z_TYPE_P(overloaded_property) == OE_IS_ARRAY) {
if (Z_TYPE_PP(object) == IS_NULL ||
(Z_TYPE_PP(object) == IS_BOOL && Z_LVAL_PP(object) == 0) ||
(Z_TYPE_PP(object) == IS_STRING && Z_STRLEN_PP(object) == 0)) {
array_init(*object);
}
if (Z_TYPE_PP(object) != IS_ARRAY) {
return FAILURE;
}
if (Z_TYPE(overloaded_property->element) == IS_STRING) {
getter_retval = zend_hash_find(Z_ARRVAL_PP(object),
Z_STRVAL(overloaded_property->element),
Z_STRLEN(overloaded_property->element)+1,
(void **)&object);
} else if (Z_TYPE(overloaded_property->element) == IS_LONG) {
getter_retval = zend_hash_index_find(Z_ARRVAL_PP(object),
Z_LVAL(overloaded_property->element),
(void **)&object);
}
if (getter_retval == FAILURE) {
MAKE_STD_ZVAL(new_val);
ZVAL_NULL(new_val);
if (Z_TYPE(overloaded_property->element) == IS_STRING) {
zend_hash_update(Z_ARRVAL_PP(object),
Z_STRVAL(overloaded_property->element),
Z_STRLEN(overloaded_property->element)+1,
&new_val, sizeof(void *), (void **)&object);
} else if (Z_TYPE(overloaded_property->element) == IS_LONG) {
zend_hash_index_update(Z_ARRVAL_PP(object),
Z_LVAL(overloaded_property->element),
&new_val, sizeof(void *), (void **)&object);
}
}
}
zval_dtor(&overloaded_property->element);
}
overloaded_property = (zend_overloaded_element *) element->data;
setter_retval = php_w32api_do_prop_set(*object, value, &element TSRMLS_CC);
zval_dtor(&overloaded_property->element);
return setter_retval;
}
W32API_PROP_GET_FUNCTION(type)
{
zval result;
zval *result_ptr = &result;
zval **prop_result;
zend_overloaded_element *overloaded_property;
zend_llist_element *element;
zval object = *property_reference->object;
int getter_retval;
TSRMLS_FETCH();
for (element=property_reference->elements_list->head; element; element=element->next) {
overloaded_property = (zend_overloaded_element *) element->data;
getter_retval = FAILURE;
ZVAL_NULL(&result);
if (Z_TYPE_P(overloaded_property) == OE_IS_OBJECT) {
if (Z_TYPE(object) != IS_OBJECT ||
Z_TYPE(overloaded_property->element) != IS_STRING) {
return result;
}
if ((getter_retval = php_w32api_do_prop_get(&object, &result, &element TSRMLS_CC) == FAILURE)) {
if ((getter_retval = zend_hash_find(Z_OBJPROP(object),
Z_STRVAL(overloaded_property->element),
Z_STRLEN(overloaded_property->element)+1,
(void **)&prop_result)) == SUCCESS) {
result = **prop_result;
}
}
} else if (Z_TYPE_P(overloaded_property) == OE_IS_ARRAY) {
if (Z_TYPE(object) != IS_ARRAY) {
return result;
}
if (Z_TYPE(overloaded_property->element) == IS_STRING) {
getter_retval = zend_hash_find(Z_ARRVAL(object),
Z_STRVAL(overloaded_property->element),
Z_STRLEN(overloaded_property->element)+1,
(void **)&prop_result);
} else if (Z_TYPE(overloaded_property->element) == IS_LONG) {
getter_retval = zend_hash_index_find(Z_ARRVAL(object),
Z_LVAL(overloaded_property->element),
(void **)&prop_result);
}
if (getter_retval == SUCCESS)
result = **prop_result;
}
zval_dtor(&overloaded_property->element);
object = result;
if (getter_retval == FAILURE) {
return result;
}
}
zval_add_ref(&result_ptr);
SEPARATE_ZVAL(&result_ptr);
return *result_ptr;
}
W32API_CLASS_FUNCTION(type, clone)
{
}
w32api_func_handle *w32api_parser_load_function_ex(char *return_type, char *function_name, char *alias_name, arguments *argument_list, char *library_name)
{
w32api_func_handle *return_value;
TSRMLS_FETCH();
return_value = (w32api_func_handle *)emalloc(sizeof(w32api_func_handle));
memset(return_value, '\0', sizeof(w32api_func_handle));
return_value->argument_list = argument_list;
return_value->flags = 0;
return_value->function_name = (alias_name)?alias_name:function_name;
return_value->return_type_name = return_type;
return_value->return_type_id = php_w32api_get_type_id_from_name(return_type);
if(strcmp("cb.cb", library_name))
{
php_w32api_load_library(library_name, &return_value->lib TSRMLS_CC);
if(!return_value->lib)
{
efree(return_value);
return NULL;
}
return_value->handle = GetProcAddress(return_value->lib->handle, function_name);
if(!return_value->handle)
{
char *ascii_name = NULL;
ascii_name = emalloc(strlen(function_name) + 2);
strcpy(ascii_name, function_name);
ascii_name[strlen(function_name)] = 'A';
ascii_name[strlen(function_name) + 1] = '\0';
return_value->handle = GetProcAddress(return_value->lib->handle, ascii_name);
efree(ascii_name);
if(!return_value->handle)
{
php_error(E_WARNING, "Could not load function %s", function_name);
efree(return_value);
return NULL;
}
}
}
php_strtolower(return_value->function_name, strlen(return_value->function_name));
if(alias_name)
efree(function_name);
return return_value;
}
arguments *w32api_parser_make_argument(char *arg_type, char *arg_name, int byref)
{
arguments *return_value = NULL;
argument *argument_value = NULL;
argument_value = emalloc(sizeof(argument));
return_value = emalloc(sizeof(arguments));
return_value->arg = argument_value;
return_value->next_arg = return_value->prev_arg = NULL;
argument_value->flags = byref;
argument_value->argument_name = arg_name;
argument_value->type_name = arg_type;
argument_value->type_id = php_w32api_get_type_id_from_name(arg_type);
if(argument_value->type_id == W32API_UNKNOWN)
{
php_error(E_NOTICE, "Unknown type %s used as arugment type", arg_type);
}
return return_value;
}
arguments *w32api_parser_join_arguments(arguments *lval, arguments *rval)
{
lval->next_arg = rval;
rval->prev_arg = lval;
return lval;
}
int w32api_function_definition_error(char *s)
{
php_error(E_ERROR, "Function Definition Parse Error: %s", s);
return 0;
}
w32api_type_handle *w32api_parser_register_type(char *type_name, members *member_list)
{
w32api_type_handle *return_value = NULL;
members *current_member;
int offset = 0;
int member_count = 0;
return_value = emalloc(sizeof(w32api_type_handle));
return_value->member_list = member_list;
return_value->type_name = type_name;
return_value->member_count = 0;
current_member = return_value->member_list;
while(current_member != NULL)
{
return_value->member_count++;
current_member->member->offset = offset;
offset += php_w32api_get_type_size(current_member->member->member_type_id, current_member->member->member_type_name, current_member->member->flags);
current_member = current_member->next_member;
}
return_value->size = offset;
return return_value;
}
members *w32api_parser_type_make_value(char *type_name, char *member_name, long flags)
{
members *return_value = NULL;
member *member_value = NULL;
member_value = emalloc(sizeof(member));
return_value = emalloc(sizeof(members));
return_value->member = member_value;
return_value->next_member = return_value->prev_member = NULL;
member_value->member_name = member_name;
member_value->member_type_name = type_name;
member_value->member_type_id = php_w32api_get_type_id_from_name(type_name);
member_value->flags = flags;
return return_value;
}
members *w32api_parser_type_join_values(members *lval, members *rval)
{
lval->next_member = rval;
rval->prev_member = lval;
return lval;
}
int w32api_type_definition_error(char *s)
{
php_error(E_ERROR, "Type Definition Parse Error: %s", s);
return 0;
}
#endif