From: James Moore Date: Tue, 12 Nov 2002 14:29:42 +0000 (+0000) Subject: Rewrite of the W32api extension X-Git-Tag: php-4.3.0RC1~81 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=41114c05fe2b34f763d7da14b29c0b1c6aacb7fb;p=php Rewrite of the W32api extension @ New version of w32api extension. Old API deprecated (jmoore) --- diff --git a/ext/w32api/README b/ext/w32api/README index 0e77cfe750..66a65ee747 100644 --- a/ext/w32api/README +++ b/ext/w32api/README @@ -2,48 +2,4 @@ Win 32 API Extension ==================== /* $Revision$ */ -This extension is a generic extension api to dll's. This was originally written to allow access to the Win32 API from PHP. Although you can also access other functions exported via other DLL's. - -An example of getting the amount of time the system has been running and displaying it in a message box: - -========================== Example.php ===================================== - -============================================================================ - -Currently supported types are generic PHP types (strings, bools, doubles, longs and null's) others will be added as and when I can figure out the best way of converting between types. - -Thanks to Ton Plooy for the base code for the generic calling function. - -- James Moore +See notes in w32api.c \ No newline at end of file diff --git a/ext/w32api/TODO b/ext/w32api/TODO index 76b2562d9b..771ad3b384 100644 --- a/ext/w32api/TODO +++ b/ext/w32api/TODO @@ -1,5 +1,3 @@ TODO ==== - - ByVal and ByRef Passing. - - Better type checking. - - Fix Mem leaks. +.... LOTS .... \ No newline at end of file diff --git a/ext/w32api/examples/uptime.php b/ext/w32api/examples/uptime.php deleted file mode 100644 index 973a52d1a2..0000000000 --- a/ext/w32api/examples/uptime.php +++ /dev/null @@ -1,64 +0,0 @@ - | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -/** - * A little example that registers MessageBoxA and GetTickCount then using - * these two API functions tells you how long you computer has been - * running - */ - /** - * Define constants needed - * Taken from Visual Studio/Tools/Winapi/WIN32API.txt - */ - - define("MB_OK", 0); - - - dl("php_w32api.dll"); - - w32api_register_function("kernel32.dll", - "GetTickCount", - "long"); - - w32api_register_function("User32.dll", - "MessageBoxA", - "long"); - - $ticks = GetTickCount(); - - $secs = floor($ticks / 1000); - $mins = floor($secs / 60); - $hours = floor($mins / 60); - - $str = sprintf("You have been using your computer for:". - "\r\n %d Milliseconds, or \r\n %d Seconds". - "or \r\n %d mins or\r\n %d hours %d mins.", - $ticks, - $secs, - $mins, - $hours, - $mins - ($hours*60)); - - MessageBoxA(NULL, - $str, - "Uptime Information", - MB_OK); -?> diff --git a/ext/w32api/php_w32api.h b/ext/w32api/php_w32api.h index cbe52234ea..05a353265f 100644 --- a/ext/w32api/php_w32api.h +++ b/ext/w32api/php_w32api.h @@ -1,8 +1,8 @@ /* +----------------------------------------------------------------------+ - | PHP Version 4 | + | PHP version 4.0 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2002 The PHP Group | + | Copyright (c) 1997-2001 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.02 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -12,126 +12,334 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: James Moore | + | Authors: James Moore | +----------------------------------------------------------------------+ - */ +*/ - /* $Id$ */ +/* $Id$ */ -#if HAVE_W32API +#if HAVE_W32API #ifndef PHP_W32API_H #define PHP_W32API_H +/* ================================================================================================ + * Type Definitions + * ================================================================================================ + */ +typedef struct _w32api_lib_handle w32api_lib_handle; +typedef struct _w32api_func_handle w32api_func_handle; +typedef struct _w32api_type_handle w32api_type_handle; +typedef struct _w32api_type_instance w32api_type_instance; +typedef struct _arguments arguments; +typedef struct _argument argument; +typedef union _w32api_parser_function_definition_union w32api_parser_function_definition_union; +typedef struct _w32api_func_handle_ptr w32api_func_handle_ptr; +typedef struct _w32api_type_handle_ptr w32api_type_handle_ptr; +typedef union _w32api_parser_type_definition_union w32api_parser_type_definition_union; +typedef struct _member member; +typedef struct _members members; +typedef union _w32api_result w32api_result; +typedef struct _w32api_dynamic_param w32api_dynamic_param; + +struct _w32api_lib_handle +{ + HINSTANCE handle; /* Handle for our library */ + char *library_name; /* name of our library */ + int ref_count; /* reference counter */ +}; + +struct _w32api_func_handle_ptr /* Temporary structure */ +{ /* To work around problems */ + w32api_func_handle *hnd; /* at 3am.. Ill sort it out */ +}; /* When I can think straight */ + +struct _w32api_type_handle_ptr /* Ditto.. should really combine */ +{ /* These two into a union at least */ + w32api_type_handle *hnd; +}; + +struct _w32api_type_handle +{ + char *type_name; /* Name of our type */ + long size; /* Size of type */ + members *member_list; /* Pointer List of members */ + long member_count; /* Number of members */ +}; + +struct _w32api_type_instance +{ + w32api_type_handle *type; /* pointer to w32api_type_handle */ + zval **values; /* First element of an array of ptr's to zvals */ +}; + +struct _w32api_func_handle +{ + FARPROC handle; /* Handle for our function */ + w32api_lib_handle *lib; /* Pointer to the library handle */ + char *function_name; /* Name of our function (Alias is store if supplied) */ + long return_type_id; /* ID of return type */ + char *return_type_name; /* Name of return type (if W32API_COMPLEX) */ + long flags; /* Flags for function */ + arguments *argument_list; /* Pointer List of arguments */ +}; + +struct _arguments +{ + argument *arg; /* Current Argument */ + arguments *next_arg; /* Next Arugment */ + arguments *prev_arg; /* Previous Argument */ +}; + +struct _argument +{ + long type_id; /* ID of the return type */ + char *type_name; /* Name of type (if W32API_COMPLEX) */ + char *argument_name; /* Name of argument, currently not used */ + long flags; /* Currently used for byref/byval */ +}; + +struct _member +{ + char *member_name; + long member_type_id; + char *member_type_name; + long flags; + long offset; +}; + +struct _members +{ + member *member; + members *next_member; + members *prev_member; +}; + +union _w32api_result +{ + int ival; + unsigned long lval; + DWORD dwval; + void *ptr; + float fval; + double dval; + __int64 i64val; +}; + +struct _w32api_dynamic_param +{ + long flags; + int width; + union { + unsigned long argument; + void *argument_ptr; + }; +}; + + +union _w32api_parser_function_definition_union +{ + char *s; + arguments *arg; +}; + +union _w32api_parser_type_definition_union +{ + char *s; + members *type; +}; + +/* ================================================================================================ + * Constants + * ================================================================================================ + */ + +/* Recognised Base types */ +#define W32API_UNKNOWN -1 +#define W32API_NULL 1 +#define W32API_INT 2 +#define W32API_LONG 3 +#define W32API_DOUBLE 4 +#define W32API_FLOAT 5 +#define W32API_STRING 6 +#define W32API_BYTE 7 +#define W32API_BOOL 8 +#define W32API_COMPLEX 9 + +/* Function Flags */ +#define W32API_ARGPTR (1<<0) +#define W32API_BORLAND (1<<1) +#define W32API_CDECL (1<<2) +#define W32API_REAL4 (1<<3) +#define W32API_REAL8 (1<<4) + +/* ================================================================================================ + * Utility Macros + * ================================================================================================ + */ +#define PROP_SET_ARGS zend_property_reference *property_reference, pval *value +#define PROP_GET_ARGS zend_property_reference *property_reference + +#define W32API_PROP_SET_FUNCTION_N(class_name) w32api_set_property_handler_##class_name +#define W32API_PROP_GET_FUNCTION_N(class_name) w32api_get_property_handler_##class_name +#define W32API_CALL_FUNCTION_N(class_name) w32api_call_handler_##class_name + +#define W32API_PROP_SET_FUNCTION(class_name) PHP_W32API_API int W32API_PROP_SET_FUNCTION_N(class_name)(PROP_SET_ARGS) +#define W32API_PROP_GET_FUNCTION(class_name) PHP_W32API_API zval W32API_PROP_GET_FUNCTION_N(class_name)(PROP_GET_ARGS) +#define W32API_CALL_FUNCITON(class_name) PHP_W32API_API void W32API_CALL_FUNCTION_N(class_name)(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference) + +#define W32API_CLASS_FUNCTION(class_name, function_name) PHP_FUNCTION(##class_name##function_name) +#define W32API_CLASS_FN(class_name, function_name) PHP_FN(##class_name##function_name) +#define W32API_CLASS_FE(class_name, function_name, function_args) {#function_name, W32API_CLASS_FN(class_name, function_name), function_args}, + +/* ================================================================================================ + * Module exports, Global Variables and General Definitions + * ================================================================================================ + */ extern zend_module_entry w32api_module_entry; -#define phpext_w32api_ptr &w32api_module_entry +#define phpext_w32api_ptr &w32api_module_entry; -#ifdef PHP_WIN32 #define PHP_W32API_API __declspec(dllexport) -#else -#define PHP_W32API_API -#endif #ifdef ZTS #include "TSRM.h" -#endif +#endif /* ZTS */ ZEND_BEGIN_MODULE_GLOBALS(w32api) - HashTable *regfuncs; // HashTable of Registered function handles - HashTable *libraries; // HashTable holding pointers to the libariers - HashTable *types; // Handles for users' types - int le_dynaparm; // Resource handle - DWORD call_type; // Type of call we use when calling a DLL. + zend_class_entry *win32_ce; /* The class entry for our win32 class */ + zend_class_entry *type_ce; /* The class entry for our type class */ + HashTable *funcs; /* Functions we registered */ + HashTable *libraries; /* Libraries we load using LoadLibrary */ + HashTable *types; /* Types we have registed with us */ + HashTable *callbacks; /* Callbacks we have registered with us */ + long le_type_instance; /* Resource hanlde for runtime instances */ ZEND_END_MODULE_GLOBALS(w32api) +ZEND_DECLARE_MODULE_GLOBALS(w32api) + #ifdef ZTS -#define W32_G(v) TSRMG(w32api_globals_id, zend_w32api_globals *, v) +#define WG(v) TSRMG(w32api_globals_id, zend_w32api_globals *, v) #else -#define W32_G(v) (w32api_globals.v) +#define WG(v) (w32api_globals.v) #endif -#define W32_REG_CONST(cname) REGISTER_LONG_CONSTANT(#cname, cname, CONST_CS | CONST_PERSISTENT); - -#define DC_MICROSOFT 0x0000 // Default -#define DC_BORLAND 0x0001 // Borland compat -#define DC_CALL_CDECL 0x0010 // __cdecl -#define DC_CALL_STD 0x0020 // __stdcall -#define DC_RETVAL_MATH4 0x0100 // Return value in ST -#define DC_RETVAL_MATH8 0x0200 // Return value in ST - -#define DC_CALL_STD_BO (DC_CALL_STD | DC_BORLAND) -#define DC_CALL_STD_MS (DC_CALL_STD | DC_MICROSOFT) -#define DC_CALL_STD_M8 (DC_CALL_STD | DC_RETVAL_MATH8) - -#define DC_FLAG_ARGPTR 0x00000002 - -typedef struct W32APIFE { - FARPROC fp; // Pointer to the function - char *rettype; // return value type - int retvaltype; // if complex = 1 if simple = 0 -} W32APIFE; - -typedef struct _field { - char *fname; // Fields name - char *type; // Type of field - int fsize; // size of field -} field; - -typedef struct runtime_struct { - char *name; // structs name - long size; // structs size - void *fields; // pointer to an array of fields -} runtime_struct; - -#pragma pack(1) // Set struct packing to one byte - -typedef union RESULT { // Various result types - int Int; // Generic four-byte type - long Long; // Four-byte long - void *Pointer; // 32-bit pointer - float Float; // Four byte real - double Double; // 8-byte real - __int64 int64; // big int (64-bit) -} RESULT; - - -typedef struct DYNAPARM { - DWORD dwFlags; // Parameter flags - int nWidth; // Byte width - union { // - DWORD dwArg; // 4-byte argument - void *pArg; // Pointer to argument - }; -} DYNAPARM; - - -PHP_W32API_API RESULT php_w32api_dynamic_dll_call( - int Flags, - DWORD lpFunction, - int nArgs, - DYNAPARM Param[], - LPVOID pRet, - int nRetSize - ); -static void php_w32api_init_globals(zend_w32api_globals *w32api_globals); -static void php_w32api_dtor_libary(void *data); -static void php_w32api_unload_libraries(); - -PHP_MINFO_FUNCTION(w32api); +/* ================================================================================================ + * Startup, Shutdown and Info Functions + * ================================================================================================ + */ PHP_MINIT_FUNCTION(w32api); PHP_MSHUTDOWN_FUNCTION(w32api); +PHP_RINIT_FUNCTION(w32api); +PHP_RSHUTDOWN_FUNCTION(w32api); +PHP_MINFO_FUNCTION(w32api); +static void php_w32api_init_globals(zend_w32api_globals *w32api_globals); +static void php_w32api_hash_lib_dtor(void *data); +static void php_w32api_hash_func_dtor(void *data); +static void php_w32api_hash_callback_dtor(void *data); +static void php_w32api_hash_type_dtor(void *data); +static void w32api_type_instance_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC); + +/* ================================================================================================ + * Win32 Class Functions + * ================================================================================================ + */ +int win32_class_init(TSRMLS_D); +int win32_class_rshutdown(TSRMLS_D); +W32API_CLASS_FUNCTION(win32, registerfunction); +W32API_CLASS_FUNCTION(win32, unregisterfunction); +W32API_CLASS_FUNCTION(win32, registercallback); +W32API_CLASS_FUNCTION(win32, definetype); +W32API_CLASS_FUNCTION(win32, gettypesize); +W32API_CLASS_FUNCTION(win32, inittype); +W32API_CLASS_FUNCTION(win32, decref); +W32API_CLASS_FUNCTION(win32, invokefunction); + + +/* ================================================================================================ + * Type Class Functions + * ================================================================================================ + */ +int type_class_init(TSRMLS_DC); + +W32API_CLASS_FUNCTION(type, clone); +W32API_PROP_SET_FUNCTION(type); +W32API_PROP_GET_FUNCTION(type); + +/* ================================================================================================ + * Utility Functions + * ================================================================================================ + */ + +static int php_w32api_load_function (char *definition, int definition_len, int flags TSRMLS_DC); +static void php_w32api_unload_function (w32api_func_handle **fh TSRMLS_DC); + +static int php_w32api_load_library (char *library_name, w32api_lib_handle **lh TSRMLS_DC); +static void php_w32api_unload_library (w32api_lib_handle *lh, int flags TSRMLS_DC); + +static int php_w32api_register_callback(char *function_definition, int function_definition_len TSRMLS_DC); + +static void php_w32api_free_arguments(arguments *argument_list); +static void php_w32api_free_members(members *member_list); + +static int php_w32api_get_type_id_from_name(char *type); +static unsigned char *php_w32api_do_arg_types(arguments **arguments); + +void php_w32api_marshall_zval_to_c(argument *arg, w32api_dynamic_param *dp, zval *pzval TSRMLS_DC); + +static void php_w32api_init_type(w32api_type_handle *th, zval *obj TSRMLS_DC); +static int php_w32api_do_prop_get(zval *object, zval *return_value, zend_llist_element **element TSRMLS_DC); +static int php_w32api_do_prop_set(zval *object, zval *value, zend_llist_element **element TSRMLS_DC); +static void *php_w32api_complex_marshall_zval_to_c(zval *pzval, int *width, void *data TSRMLS_DC); + +/* ================================================================================================ + * Parser & Scanner Functions + * ================================================================================================ + */ +#define w32api_parser_load_alias_function w32api_parser_load_function_ex +#define w32api_parser_load_function(return_type, function_name, arguments, library_name) w32api_parser_load_function_ex (return_type, function_name, NULL, arguments, library_name) +#define w32api_parser_make_argument_byref(arg_type, arg_name) w32api_parser_make_argument(arg_type, arg_name, BYREF_FORCE) +#define w32api_parser_make_argument_byval(arg_type, arg_name) w32api_parser_make_argument(arg_type, arg_name, BYREF_NONE) + +#define w32api_parser_type_make_byref_value(member_name, member_type) w32api_parser_type_make_value(member_name, member_type, BYREF_FORCE) +#define w32api_parser_type_make_byval_value(member_name, member_type) w32api_parser_type_make_value(member_name, member_type, BYREF_NONE) + +w32api_func_handle *w32api_parser_load_function_ex(char *return_type, char *function_name, char *alias_name, arguments *argument_list, char *library_name); +arguments *w32api_parser_make_argument(char *arg_type, char *arg_name, int byref); +arguments *w32api_parser_join_arguments(arguments *lval, arguments *rval); +int w32api_function_definition_error(char *s); + +w32api_type_handle *w32api_parser_register_type(char *type_name, members *member_list); +members *w32api_parser_type_make_value(char *member_name, char *type_name, long flags); +members *w32api_parser_type_join_values(members *lval, members *rval); +int w32api_type_definition_error(char *s); + +struct yy_buffer_state *w32api_function_definition_scan_bytes(char *bytes, int len); /* Definied in w32api_function_definition_scanner.c */ +int w32api_function_definition_parse(void *fh); /* Definied in w32api_function_definition_parser.c */ + +struct yy_buffer_state *w32api_type_definition_scan_bytes(char *bytes, int len); /* Definied in w32api_type_definition_scanner.c */ +int w32api_type_definition_parse(void *th); /* Definied in w32api_type_definition_parser.c */ + + +/* ================================================================================================ + * Various Debugging Functions + * ================================================================================================ + */ +#ifndef NDEBUG +W32API_CLASS_FUNCTION(win32, dump_library_hash); +W32API_CLASS_FUNCTION(win32, dump_function_hash); +W32API_CLASS_FUNCTION(win32, dump_callback_hash); +W32API_CLASS_FUNCTION(win32, dump_type_hash); + +int php_w32api_dump_library_hash_cb(void *pData TSRMLS_DC); +int php_w32api_dump_function_hash_cb(void *pData TSRMLS_DC); +int php_w32api_dump_callback_hash_cb(void *pData TSRMLS_DC); +int php_w32api_dump_type_hash_cb(void *pData TSRMLS_DC); -PHP_FUNCTION(w32api_register_function); -PHP_FUNCTION(w32api_invoke_function); -PHP_FUNCTION(w32api_deftype); -PHP_FUNCTION(w32api_init_dtype); -PHP_FUNCTION(w32api_set_call_method); +void php_w32api_print_arguments(arguments *argument_list); +void php_w32api_print_members(members *member_list); -static void register_constants(int module_number); -static void w32api_free_dynaparm(zend_rsrc_list_entry *rsrc TSRMLS_DC); -void get_arg_pointer(zval **value, void ** argument); -DYNAPARM w32api_convert_zval_to_dynparam(zval ** carg TSRMLS_DC); +#endif /* ifndef NDEBUG */ -#endif /* PHP_W32API_H */ -#endif /* HAVE_W32API */ \ No newline at end of file +#endif /* ifndef PHP_W32API_H */ +#endif /* if HAVE_W32API */ \ No newline at end of file diff --git a/ext/w32api/test_dll/dll_test.h b/ext/w32api/test_dll/dll_test.h deleted file mode 100644 index a0d84c86c7..0000000000 --- a/ext/w32api/test_dll/dll_test.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 4 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2002 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 2.02 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available at through the world-wide-web at | - | http://www.php.net/license/2_02.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: James Moore | - +----------------------------------------------------------------------+ -*/ - -#ifndef _TEST_DLL_H -#define _TEST_DLL_H - -#define TEST_DLL_API __declspec(dllexport) - -typedef struct _name { - char *fname; - char *lname; -} name; - -TEST_DLL_API void print_names(name *n); - -#endif _TEST_DLL_H \ No newline at end of file diff --git a/ext/w32api/test_dll/test.php b/ext/w32api/test_dll/test.php deleted file mode 100644 index 9f85acaf03..0000000000 --- a/ext/w32api/test_dll/test.php +++ /dev/null @@ -1,10 +0,0 @@ - diff --git a/ext/w32api/test_dll/test_dll.c b/ext/w32api/test_dll/test_dll.c deleted file mode 100644 index c455cc30fd..0000000000 --- a/ext/w32api/test_dll/test_dll.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - +----------------------------------------------------------------------+ - | PHP Version 4 | - +----------------------------------------------------------------------+ - | Copyright (c) 1997-2002 The PHP Group | - +----------------------------------------------------------------------+ - | This source file is subject to version 2.02 of the PHP license, | - | that is bundled with this package in the file LICENSE, and is | - | available at through the world-wide-web at | - | http://www.php.net/license/2_02.txt. | - | If you did not receive a copy of the PHP license and are unable to | - | obtain it through the world-wide-web, please send a note to | - | license@php.net so we can mail you a copy immediately. | - +----------------------------------------------------------------------+ - | Author: James Moore | - +----------------------------------------------------------------------+ -*/ - -/* $Id$ */ - -#include -#include "dll_test.h" - -/** - * Test DLL for w32api functions. Functions below are used to test - * Various parts of the extension. - */ - -/* Test for complex type passing */ -TEST_DLL_API void print_names(name *n) -{ - printf("%s %s", n->fname, n->lname); -} \ No newline at end of file diff --git a/ext/w32api/test_dll/test_dll.def b/ext/w32api/test_dll/test_dll.def deleted file mode 100644 index 7ffba76950..0000000000 --- a/ext/w32api/test_dll/test_dll.def +++ /dev/null @@ -1,2 +0,0 @@ -EXPORTS - print_name \ No newline at end of file diff --git a/ext/w32api/test_dll/test_dll.dsp b/ext/w32api/test_dll/test_dll.dsp deleted file mode 100644 index 945dc7efc1..0000000000 --- a/ext/w32api/test_dll/test_dll.dsp +++ /dev/null @@ -1,110 +0,0 @@ -# Microsoft Developer Studio Project File - Name="test_dll" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=test_dll - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "test_dll.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "test_dll.mak" CFG="test_dll - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "test_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "test_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "test_dll - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_DLL_EXPORTS" /YX /FD /c -# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_DLL_EXPORTS" /YX /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x809 /d "NDEBUG" -# ADD RSC /l 0x809 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 - -!ELSEIF "$(CFG)" == "test_dll - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_DLL_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_DLL_EXPORTS" /YX /FD /GZ /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x809 /d "_DEBUG" -# ADD RSC /l 0x809 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept - -!ENDIF - -# Begin Target - -# Name "test_dll - Win32 Release" -# Name "test_dll - Win32 Debug" -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\test_dll.c -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\dll_test.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/ext/w32api/test_dll/test_dll.dsw b/ext/w32api/test_dll/test_dll.dsw deleted file mode 100644 index e22c7b49ee..0000000000 --- a/ext/w32api/test_dll/test_dll.dsw +++ /dev/null @@ -1,29 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "test_dll"=.\test_dll.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/ext/w32api/w32api.c b/ext/w32api/w32api.c index 89190d3175..7bbb226e2b 100644 --- a/ext/w32api/w32api.c +++ b/ext/w32api/w32api.c @@ -1,8 +1,8 @@ /* +----------------------------------------------------------------------+ - | PHP Version 4 | + | PHP version 4.0 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2002 The PHP Group | + | Copyright (c) 1997-2001 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.02 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -12,20 +12,204 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: James Moore | + | Authors: James Moore | +----------------------------------------------------------------------+ */ /* $Id$ */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +/* + * Win32 API Extension for PHP 4 + * ============================= + * + * This extension allows PHP Developers to access the underlying functions in the + * Win32 API Dll's in a generic way, it provides a mechanism for the user to load + * and register functions from dll's and then to call them, it also implements a + * generic callback handler which allows the user to pass a pointer to one of + * their PHP functions to act as a callback from the C function enabling the PHP + * programmer to handle callbacks in PHP seemlessly. Finally the extension marshalls + * from PHP types (Zvals) to C structures seemlessly once it has been told about them + * + * I would like to thank Ton Plooy for his article on a similar subject which gave me + * the initial idea for a generic dll caller and some good pointers on how to actaully + * implement it. + */ + +/* + * Interface the PHP Programmer Sees + * ================================== + * + * To keep namespaces tidy the module will introduce two classes, the first is + * the win32 class which has several functions to load and register functions from + * the underlying DLL's. The Win32 class also has functions for informing the + * module about the C types we will be using so it can marshall and demarshall to and from + * the C Interface. . Our second class is the Type class. The type class is our container + * for complex C types which are registered and initiated using our win32 class functions. + * + * Win32 Class Functions + * ===================== + * + * static int Win32::RegisterFunction( string Definition, long flags ) + * ------------------------------------------------------------------- + * + * This function is used for registering a dll function with the module. The Definition should take + * the form: + * Definition: [Alias ) From + * + * return_type :- Either a simple type or a type that has + * been registered with the module + * + * function_name :- The name of the function within the dll, if this is not found + * we append an A to the function name to check for a ASCII version, + * if this is not found we fail. + * + * alias_name :- If this is provided then we register the function under this name + * in the PHP Symbol table. + * + * argument_list :- A comma seperated list of arguments in the form + * [&]argument_name. + * + * argument_type :- Argument type is a type known to the module + * + * argument_name :- This is not currently used although if it is proceeded by an + * & (Ampersand) then a pointer is passed rather than the value. + * + * some_dll :- This is the name of the dll to find the function in. + * + * On success the function returns TRUE, on error FALSE, The function issues appropriate errors + * to allow the PHP Progammer to catch individual errors. + * + * static int Win32::UnregisterFunction(string FunctionName) + * --------------------------------------------------------- + * + * Allows the PHP programmer to force a funciton to be unregistered saving on memory resources. Can + * be useful in long running scripts. + * + * Returns TRUE on success, FALSE on error. + * + * + * static int Win32::DefineType( string Definition ) + * ------------------------------------------------- + * + * This function is used to register a C-Type which will be used when calling a function, it only + * supports the equivilent of C structures at this time so if you need to use a union you must use the + * largest member of that union as the type in the struct for this to work. + * + * The definition string takes the form: + * + * Definition: { } + * + * type_name :- A unique name for this type. + * + * type_list :- Takes for form [&] + * + * member_type :- The type of this member. + * + * member_name :- The name for this member, if an & (ampersand) preceeds + * the name it will be stripped and a pointer rather than + * the value will be used. + * + * Returns TRUE on success, FALSE on error. + * + * + * static int Win32::GetTypeSize(mixed TypeHandle) + * ----------------------------------------------- + * + * This function returns the size of a type registered with the module. The parameter should + * either be the name of the type or an instance of it. The Function returns FALSE on error + * ***USE === to distinguish between this and a size of 0*** or the size of the type on success. + * + * + * static mixed Win32::InitType(String TypeName) + * --------------------------------------------- + * + * Creates an instance of the type so that the PHP Programmer can assign values and then pass + * it to a C Function. Returns NULL on error. + * + * static int Win32::DecRef(mixed var) + * ----------------------------------- + * Decreases the reference count on a variable only if we incremented the refcount when passing + * the variable to a C function. + * + * TYPE Functions + * ============== + * + * mixed Type::Type(String TypeName) + * --------------------------------- + * See Win32::InitType, + * + * mixed Type::Clone() + * ------------------- + * + * Allows you to make an exact copy of the class, this should be used rather than the &= syntax + * Due to the nesting within classes. This function WILL become redundant in PHP 5. + */ + +/* + * Implementation Details + * ====================== + * + * This module will only work on the Intel platform. + * + * We basically want to set up this structure: + * + * +-----------+ + * | PHP | + * +-----------+ + * Call | /|\ + * \|/ | call_user_function_ex + * +------------------------+ + * | Win 32 API Extension | + * +------------------------+ + * | /|\ + * \|/ | Callback + * +-------------+ + * | C-Space | + * +-------------+ + * + * Win32 Needs to then Marshall between zvals and + * + * Marshalling from ZVAL's to C Types. + * ----------------------------------- + * For simple types this is very easy as we either just copy the value or a pointer + * to it onto the stack, if we copy a pointer then we must increase the refcount on + * the zval and must also make sure we get it passed to us by reference. + * + * The problem here is when to dereference the zval again as we may get into the following + * situation + * + * We call somefunction giving it an argument by reference (IE we pass a pointer to the value union of a zval) + * we must increase the ref count on the zval to avoid the possibility of a GPE (IE the zval is dtord and then + * the function uses the zval in some sort of callback we could end up with a GPE) + * But if we increase the zval's refcount without dtoring it anywhere it would cause a mem leak. + * + * Therefore we probably need to keep a local reference table so we can either allow the user to call + * Win32::DecRef($var) to decrement the reference count (We would want to keep a local table to avoid anyone + * breaking Zend's handling off it as well..)) + * + * Then at MSHUTDOWN we free this hashtable decrementing the refcount as needed.. + * + * Complex types are less clear cut on how to handle them. My prefered method is to always + * keep these in a C Format but to allow access to these via a wrapper object which calculates + * the offset of the data to allow access to it from PHP. This also allows us to do no conversion + * when dealing with C types coming to us allowing us to deal with pointers in a more clear way. + * + * + * Enabling C Code to call PHP Code in a generic fashion + * ----------------------------------------------------- + * What we do here is we use _declspec(naked) to tell the compiler we will handle all stack operations + * ourself, we also then create (At runtime) function prologues which we place on the heap which push + * extra arguments onto the stack which tell us which php_function is being called back and the callback type + * which has been registered with us. + * + */ + +#if HAVE_W32API -#if HAVE_W32API #include #include -#define WIN32_LEAN_AND_MEAN + +#define WINDOWS_LEAN_AND_MEAN #include #include "php.h" @@ -34,866 +218,2070 @@ #include "ext/standard/php_string.h" #include "php_w32api.h" -/* {{{ w32api_functions[] + +/* ===================================================================================================== + * PHP Module Startup, Shutdown & Info Code + * ===================================================================================================== */ -function_entry w32api_functions[] = { - PHP_FE(w32api_register_function, NULL) - PHP_FE(w32api_deftype, NULL) - PHP_FE(w32api_init_dtype, NULL) - PHP_FE(w32api_set_call_method, NULL) - PHP_FE(w32api_invoke_function, NULL) - {NULL, NULL, NULL} -}; -/* }}} */ + +#ifdef COMPILE_DL_W32API +ZEND_GET_MODULE(w32api) +#endif /* {{{ w32api_module_entry */ zend_module_entry w32api_module_entry = { STANDARD_MODULE_HEADER, - "w32api", - w32api_functions, + "Win32 API", + NULL, /* We define no global functions */ PHP_MINIT(w32api), PHP_MSHUTDOWN(w32api), - NULL, - NULL, + PHP_RINIT(w32api), + PHP_RSHUTDOWN(w32api), PHP_MINFO(w32api), - "0.1", /* Replace with version number for your extension */ + "0.2", STANDARD_MODULE_PROPERTIES }; /* }}} */ -ZEND_DECLARE_MODULE_GLOBALS(w32api) - -#ifdef COMPILE_DL_W32API -ZEND_GET_MODULE(w32api) -#endif - -/* {{{ PHP_MINFO_FUNCTION - */ -PHP_MINFO_FUNCTION(w32api) -{ - php_info_print_table_start(); - php_info_print_table_row(2, "Win32 API Support", "enabled" ); - php_info_print_table_end(); -} -/* }}} */ /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(w32api) { + /* Setup out module globals */ ZEND_INIT_MODULE_GLOBALS(w32api, php_w32api_init_globals, NULL); - register_constants(module_number); - W32_G(le_dynaparm) = zend_register_list_destructors_ex(w32api_free_dynaparm, NULL, "dynaparm", module_number); - - return SUCCESS; -} -/* }}} */ -/* {{{ PHP_MSHUTDOWN_FUNCTION - */ -PHP_MSHUTDOWN_FUNCTION(w32api) -{ - if(W32_G(regfuncs)) + if(win32_class_init(TSRMLS_C) != SUCCESS) { - FREE_HASHTABLE(W32_G(regfuncs)); + return FAILURE; } - if(W32_G(libraries)) + if(type_class_init(TSRMLS_C) != SUCCESS) { - php_w32api_unload_libraries(); - FREE_HASHTABLE(W32_G(libraries)); + return FAILURE; } - if(W32_G(libraries)) - { - FREE_HASHTABLE(W32_G(types)); - } + WG(le_type_instance) = zend_register_list_destructors_ex(w32api_type_instance_dtor, NULL, "Type Instance", module_number); + + /* Function Flags */ + 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 + */ +PHP_MSHUTDOWN_FUNCTION(w32api) +{ return SUCCESS; } /* }}} */ -/* {{{ DYNAPARM dtor */ -static void w32api_free_dynaparm(zend_rsrc_list_entry *rsrc TSRMLS_DC) +/* {{{ PHP_RINIT_FUNCTION + */ +PHP_RINIT_FUNCTION(w32api) { - DYNAPARM *dparam; + /* Allocate Request Specific HT's here + */ + ALLOC_HASHTABLE(WG(funcs)); + zend_hash_init(WG(funcs), 1, NULL, php_w32api_hash_func_dtor, 1); - dparam = (DYNAPARM *)rsrc->ptr; + ALLOC_HASHTABLE(WG(libraries)); + zend_hash_init(WG(libraries), 1, NULL, php_w32api_hash_lib_dtor, 1); - if(dparam->pArg) - efree(dparam->pArg); + ALLOC_HASHTABLE(WG(callbacks)); + zend_hash_init(WG(callbacks), 1, NULL, php_w32api_hash_callback_dtor, 1); - efree(dparam); -} + ALLOC_HASHTABLE(WG(types)); + zend_hash_init(WG(types), 1, NULL, php_w32api_hash_type_dtor, 1); + + + return SUCCESS; + +}; /* }}} */ -/* {{{ */ -static void php_w32api_unload_libraries() +/* {{{ PHP_RSHUTDOWN_FUNCTION + */ +PHP_RSHUTDOWN_FUNCTION(w32api) { - TSRMLS_FETCH(); - zend_hash_destroy(W32_G(libraries)); + + win32_class_rshutdown(TSRMLS_C); + + /* Must be dtor'd before libraries */ + zend_hash_destroy(WG(funcs)); + FREE_HASHTABLE(WG(funcs)); + + zend_hash_destroy(WG(libraries)); + FREE_HASHTABLE(WG(libraries)); /* we may only want to do this on MSHUTDOWN but for now it can be here */ + + zend_hash_destroy(WG(callbacks)); + FREE_HASHTABLE(WG(callbacks)); + + zend_hash_destroy(WG(types)); + FREE_HASHTABLE(WG(types)); + + + return SUCCESS; } /* }}} */ -/* {{{ */ -static void php_w32api_dtor_library(void *data) + +/* {{{ PHP_MINFO_FUNCTION + */ +PHP_MINFO_FUNCTION(w32api) { - FreeLibrary((HINSTANCE)data); + php_info_print_table_start(); + php_info_print_table_row(2, "Win32 API Support", "enabled" ); + php_info_print_table_end(); } /* }}} */ -/* {{{ */ +/* {{{ php_w32api_init_globals + */ static void php_w32api_init_globals(zend_w32api_globals *w32api_globals) { - TSRMLS_FETCH(); - - w32api_globals->regfuncs = NULL; + 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; - w32api_globals->call_type = DC_CALL_STD; +} +/* }}} */ - ALLOC_HASHTABLE(W32_G(regfuncs)); - zend_hash_init(W32_G(regfuncs), 1, NULL, NULL, 1); +/* {{{ php_w32api_hash_lib_dtor (void *data) + * Dtor function called when hash is destroied, unloads library + */ +static void php_w32api_hash_lib_dtor(void *data) +{ + w32api_lib_handle *lh; /* Library Handle */ + TSRMLS_FETCH(); /* Get thread safe stuff */ + lh = (w32api_lib_handle *)data; - ALLOC_HASHTABLE(W32_G(libraries)); - zend_hash_init(W32_G(libraries), 1, NULL, php_w32api_dtor_library, 1); + FreeLibrary(lh->handle); + efree(lh->library_name); +} +/* }}} */ - ALLOC_HASHTABLE(W32_G(types)); - zend_hash_init(W32_G(types), 5, NULL, NULL, 1); +/* {{{ php_w32api_hash_func_dtor (void *data) + * Dtor function called when hash is destroied, unloads function. + */ +static void php_w32api_hash_func_dtor(void *data) +{ + w32api_func_handle **fh; /* Function Handle */ + TSRMLS_FETCH(); /* Get thread safe stuff */ + fh = (w32api_func_handle **)data; + php_w32api_unload_function(fh TSRMLS_CC); } /* }}} */ -/* {{{ */ -static void register_constants(int module_number) +/* {{{ php_w32api_hash_callback_dtor + * DTOR function called when hash is destroied, removes callback. + */ +static void php_w32api_hash_callback_dtor(void *data) { - TSRMLS_FETCH(); + w32api_func_handle **fh; + + fh = (w32api_func_handle **)data; - W32_REG_CONST(DC_MICROSOFT) - W32_REG_CONST(DC_BORLAND) - W32_REG_CONST(DC_CALL_CDECL) - W32_REG_CONST(DC_CALL_STD) - W32_REG_CONST(DC_RETVAL_MATH4) - W32_REG_CONST(DC_RETVAL_MATH8) - W32_REG_CONST(DC_CALL_STD_BO) - W32_REG_CONST(DC_CALL_STD_MS) - W32_REG_CONST(DC_CALL_STD_M8) - W32_REG_CONST(DC_FLAG_ARGPTR) + php_w32api_free_arguments((*fh)->argument_list); + efree((*fh)->function_name); + + if((*fh)->return_type_name) + efree((*fh)->return_type_name); + efree(*fh); +} + +/* {{{ php_w32api_hash_type_dtor + * DTOR function called when hash is destroied, removes callback. + */ +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); } -/* }}} */ -/* {{{ proto void w32api_set_call_method(int method) - Sets the calling method used */ -PHP_FUNCTION(w32api_set_call_method) +static void w32api_type_instance_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) { - zval **method; + w32api_type_instance *ti; + int i = 0; - if(zend_get_parameters_ex(1, &method) == FAILURE) - { - WRONG_PARAM_COUNT - } + if(!rsrc || !rsrc->ptr) + return; - switch((*method)->value.lval) + ti = (w32api_type_instance *)rsrc->ptr; + + for(i = 0; i < ti->type->member_count; i++) { - case DC_CALL_CDECL: - W32_G(call_type) = DC_CALL_CDECL; - break; - default: - W32_G(call_type) = DC_CALL_STD; - break; + if(ti->values[i]) + zval_ptr_dtor(&ti->values[i]); } - RETURN_TRUE - + efree(ti); + + return; } -/* }}} */ +/* ===================================================================================================== + * Utility Functions + * ===================================================================================================== + */ -/* {{{ proto bool w32api_register_function(string libary, string function_name) - Registers function function_name from library with PHP */ -PHP_FUNCTION(w32api_register_function) +/* {{{ php_w32api_unload_library + * Expects two arguments, the first is the pointer to a w32api_lib_handle + * and the second is a flag, if the flag is 0 then the reference counter is + * use if it is one then the library is unloaded irrespective of the reference + * counter + */ +static void php_w32api_unload_library (w32api_lib_handle *lh, int flags TSRMLS_DC) { - HINSTANCE hinstLib; - FARPROC ProcAdd; - W32APIFE *fe; - BOOL fRunTimeLinkSuccess = FALSE; - zval **libname, **funcname, **retval_type; - void *tmp; - runtime_struct *rst; - if(zend_get_parameters_ex(3, &libname, &funcname, &retval_type) == FAILURE) + if(flags == 0) { - WRONG_PARAM_COUNT + lh->ref_count--; } - convert_to_string_ex(libname); - convert_to_string_ex(funcname); - convert_to_string_ex(retval_type); + if((flags == 1) || (lh->ref_count == 0)) + { + /* remove outselves from the hashtable */ + zend_hash_del(WG(libraries), lh->library_name, strlen(lh->library_name) + 1); + } +} +/* }}} */ - fe = (W32APIFE *)emalloc(sizeof(W32APIFE)); - fe->retvaltype = 0; - //TODO: Check library isnt alreay loaded +/* {{{ php_w32api_unload_function + * Expects one argument, a pointer to a w32api_func_handle, unloads this + * function from both the function table internally and the PHP function + * table then it decrements the reference counter on the library. + */ +static void php_w32api_unload_function (w32api_func_handle **fh TSRMLS_DC) +{ + zend_function *function = NULL; - hinstLib = LoadLibrary((*libname)->value.str.val); + efree((*fh)->return_type_name); + php_w32api_free_arguments((*fh)->argument_list); - if(hinstLib == NULL) + /* If needs be we need to retrieve function ptr from hash table + * and free anything we allocate when creating them at runtime (most notably + * arg_types + */ + if(zend_hash_find( &WG(win32_ce)->function_table, + (*fh)->function_name, + strlen((*fh)->function_name) + 1, + (void **)&function) == SUCCESS) { - php_error(E_WARNING, "Could not load dynamic link library %s", (*libname)->value.str.val); - RETURN_FALSE + zend_internal_function *internal_function = (zend_internal_function *)function; + if(internal_function->arg_types) + efree(internal_function->arg_types); } - zend_hash_add(W32_G(libraries), - (*libname)->value.str.val, - strlen((*libname)->value.str.val), - &hinstLib, - sizeof(HINSTANCE), - NULL); + /* Remove from Function Table */ + 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); + +} +/* }}} */ - //TODO: Check function handle isnt already loaded +/* {{{ php_w32api_load_function + * Expects three arguments, The definition of the function in string format, the definitions length + * and a pointer to a pointer to a function handle. returns SUCCESS or FAILURE. + */ +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; - ProcAdd = (FARPROC) GetProcAddress(hinstLib, (*funcname)->value.str.val); + fh = emalloc(sizeof(w32api_func_handle *)); + *fh = NULL; - if(ProcAdd == NULL) + /* Parse function */ + w32api_function_definition_scan_bytes(definition, definition_len); + if((w32api_function_definition_parse((void *)&hnd) != 0)) { - php_error(E_WARNING, "Could not get handle for function %s", (*funcname)->value.str.val); - RETURN_FALSE + *fh = hnd.hnd; + if(*fh != NULL) + efree(*fh); + + efree(fh); + return FAILURE; } + *fh = hnd.hnd; - fe->fp = ProcAdd; + if(!*fh) + return FAILURE; - if(!strcmp((*retval_type)->value.str.val, "long")) - { - fe->rettype = malloc(5*sizeof(char)); - fe->rettype = strdup("long\0"); - } - else if (!strcmp((*retval_type)->value.str.val, "int")) + + if(zend_hash_exists(&WG(win32_ce)->function_table, (*fh)->function_name, strlen((*fh)->function_name) + 1)) { - fe->rettype = malloc(4*sizeof(char)); - fe->rettype = strdup("long\0"); + php_error( E_WARNING, + "A function by the name %s already has been registered, cannot redefine function", + (*fh)->function_name); + + /* We dont want to unload function as it already exists so lets just free it ourselves */ + 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; } - else if (!strcmp((*retval_type)->value.str.val, "string")) + + /* Insert it into our hash table */ + if(zend_hash_add( WG(funcs), + (*fh)->function_name, + strlen((*fh)->function_name) + 1, + fh, + sizeof(w32api_func_handle), + NULL) != SUCCESS) { - fe->rettype = malloc(7*sizeof(char)); - fe->rettype = strdup("string\0"); + + php_error( E_WARNING, + "Loading of function %s failed: Could not insert function handle into hash", + (*fh)->function_name); + + /* Tidy up */ + zend_hash_del(WG(funcs), (*fh)->function_name, strlen((*fh)->function_name) +1); + return FAILURE; } - else if (!strcmp((*retval_type)->value.str.val, "byte")) + + /* Insert function into win32_ce's function_table */ + 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) { - fe->rettype = malloc(5*sizeof(char)); - fe->rettype = strdup("byte\0"); + php_error(E_ERROR, "Could not register funciton %s into function table", (*fh)->function_name); + zend_hash_del(WG(funcs), (*fh)->function_name, strlen((*fh)->function_name) +1); + + return FAILURE;; } - else if (!strcmp((*retval_type)->value.str.val, "double")) + + if(flags) { - fe->rettype = malloc(7*sizeof(char)); - fe->rettype = strdup("double\0"); + (*fh)->flags = (*fh)->flags | flags; } - else if (!strcmp((*retval_type)->value.str.val, "bool")) + + + return SUCCESS; +} +/* }}} */ + +/* {{{ php_w32api_unload_type + * Expects one argument, a pointer to a w32api_type_handle, unloads this + * type. + */ +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); + +} +/* }}} */ + +/* {{{ php_w32api_register_type + */ +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) { - fe->rettype = malloc(5*sizeof(char)); - fe->rettype = strdup("bool\0"); + *th = hnd.hnd; + + /* Leaks */ + if(*th != NULL) + efree(*th); + + efree(th); + return FAILURE; } - else + + *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))) { - /** - * this could be a userdef'd type so lets - * search the ht for that. - */ - if(zend_hash_find(W32_G(types), (*retval_type)->value.str.val, (*retval_type)->value.str.len, (void **) &tmp) == FAILURE) - { - php_error(E_WARNING, "Unknown type %s", (*retval_type)->value.str.val); - RETURN_FALSE; - } - rst = tmp; - fe->rettype = malloc(sizeof(char) * strlen(rst->name) + 1); - memcpy(fe->rettype, rst->name, strlen(rst->name) + 1); - fe->retvaltype = 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); + + /* We dont want to unload function as it already exists so lets just free it ourselves */ + php_w32api_free_members((*th)->member_list); + efree((*th)->type_name); + efree(*th); + efree(th); + + return FAILURE; } - - if(zend_hash_add(W32_G(regfuncs), php_strtolower((*funcname)->value.str.val, (*funcname)->value.str.len), (*funcname)->value.str.len, fe, sizeof(W32APIFE), NULL) == FAILURE) - { - php_error(E_WARNING, "Could not register function %s into hash"); - RETURN_FALSE; - } - /** - * We now need to add the function into the global namespace, the best way to do this is - * to register it as a new module then it will definatly be removed on shutdown - */ + /* Insert it into our hash table */ + if(zend_hash_add( WG(types), + (*th)->type_name, + strlen((*th)->type_name) + 1, + th, + sizeof(w32api_type_handle *), + NULL) != SUCCESS) { - zend_module_entry *temp_module_entry; - char *fname; - function_entry *tmp_functions; - - tmp_functions = malloc(sizeof(function_entry) * 2); - fname = malloc((*funcname)->value.str.len + 1); - memcpy(fname, (*funcname)->value.str.val, (*funcname)->value.str.len + 1); - - tmp_functions[0].fname = php_strtolower(fname, (*funcname)->value.str.len); - tmp_functions[0].handler = zif_w32api_invoke_function; - tmp_functions[0].func_arg_types = NULL; - tmp_functions[1].fname = NULL; - tmp_functions[1].handler = NULL; - tmp_functions[1].func_arg_types = NULL; - - - temp_module_entry = malloc(sizeof(zend_module_entry)); - temp_module_entry->size = sizeof(zend_module_entry); - temp_module_entry->zend_api = ZEND_MODULE_API_NO; - temp_module_entry->zend_debug = ZEND_DEBUG; - temp_module_entry->zts = USING_ZTS; - temp_module_entry->name = fname; - temp_module_entry->functions = tmp_functions; - temp_module_entry->module_startup_func = temp_module_entry->module_shutdown_func = - temp_module_entry->request_startup_func = temp_module_entry->request_shutdown_func = NULL; - temp_module_entry->info_func = NULL; - temp_module_entry->version = NULL; - temp_module_entry->global_startup_func = temp_module_entry->global_shutdown_func = NULL; - temp_module_entry->globals_id = 0; - temp_module_entry->module_started = 0; - temp_module_entry->type = 0; - temp_module_entry->handle = NULL; - temp_module_entry->module_number = 0; - - if(zend_register_module(temp_module_entry) != SUCCESS) - { - php_error(E_WARNING, "could not register function %s into the function table", (*funcname)->value.str.val); - RETURN_FALSE - } + php_error( E_WARNING, + "Loading of type %s failed: Could not insert type handle into hash", + (*th)->type_name); + /* Tidy up */ + zend_hash_del(WG(types), (*th)->type_name, strlen((*th)->type_name) + 1); + return FAILURE; } + return SUCCESS; - - RETURN_TRUE -}; +} /* }}} */ -/* {{{ proto mixed w32api_invoke_function(string funcname, ....) - Invokes function funcname with the arguments passed after the function name */ -PHP_FUNCTION(w32api_invoke_function) + +/* {{{ php_w32api_register_callback + */ +static int php_w32api_register_callback(char *function_definition, int function_definition_len TSRMLS_DC) { - zval ***args = (zval ***)NULL; - void *tmp; - W32APIFE *fe; - char *funcname; - int argc = ZEND_NUM_ARGS(); - runtime_struct *rst; - RESULT retval; - DYNAPARM *Param, *drval; - LPVOID pVParam; - int VParamsz; - int i; + w32api_func_handle **fh; + w32api_func_handle_ptr hnd; - args = emalloc(argc * sizeof(zval **)); - Param = (DYNAPARM *)emalloc((argc) * sizeof(DYNAPARM)); + char *new_definition = NULL; - if(zend_get_parameters_array_ex(argc, args) == FAILURE) - { - WRONG_PARAM_COUNT - } + fh = emalloc(sizeof(w32api_func_handle *)); + *fh = NULL; - funcname = get_active_function_name(TSRMLS_C); + new_definition = emalloc(function_definition_len + sizeof(" from cb.cb")); - if(zend_hash_find(W32_G(regfuncs), funcname, strlen(funcname), (void **) &tmp) == FAILURE) - { - php_error(E_WARNING, "Could not find function handle for function %s", funcname); - RETURN_FALSE; - } + snprintf(new_definition, function_definition_len + sizeof(" from cb.cb"), "%s from cb.cb", function_definition); - fe = (W32APIFE *)tmp; - // Build the DYNPARAM array. - for(i = 0; i < (argc); i++) + /* Parse function */ + w32api_function_definition_scan_bytes(new_definition, function_definition_len + sizeof(" from cb.cb")); + if(w32api_function_definition_parse((void *)&hnd) != 0) { - Param[i] = w32api_convert_zval_to_dynparam(args[(i)] TSRMLS_CC); - } + *fh = hnd.hnd; + /* Leaks */ + if(*fh != NULL) + efree(*fh); - /** - * We need to check the return type, if its a complex return type then we need to sort out pVParam and - * VParamsz and pass them as the last two parameters of the call to the invoke of the function. - */ - if(fe->retvaltype) // Complex return type - { - tmp = NULL; - if(zend_hash_find(W32_G(types), fe->rettype, strlen(fe->rettype), (void **) &tmp) == FAILURE) - { - php_error(E_WARNING, "Unknown type %s", fe->rettype); - RETURN_FALSE; - } - rst = tmp; - VParamsz = rst->size; - pVParam = malloc(rst->size); - } - else - { - pVParam = NULL; - VParamsz = 0; + efree(fh); + return FAILURE; } + *fh = hnd.hnd; - retval = php_w32api_dynamic_dll_call(W32_G(call_type), (ulong)(fe->fp), (argc), Param, pVParam, VParamsz); + if(!*fh) + return FAILURE; - if(!strcmp(fe->rettype, "long")) + + if(zend_hash_exists(WG(callbacks), (*fh)->function_name, strlen((*fh)->function_name) + 1)) { - RETURN_LONG(retval.Long); + php_error( E_WARNING, + "A callback by the name %s already has been registered, cannot redefine type", + (*fh)->function_name); + + /* We dont want to unload function as it already exists so lets just free it ourselves */ + php_w32api_free_arguments((*fh)->argument_list); + efree((*fh)->return_type_name); + efree((*fh)->function_name); + efree(*fh); + efree(fh); + + return FAILURE; } - else if (!strcmp(fe->rettype, "int")) + + /* Insert it into our hash table */ + if(zend_hash_add( WG(callbacks), + (*fh)->function_name, + strlen((*fh)->function_name) + 1, + fh, + sizeof(w32api_func_handle *), + NULL) != SUCCESS) { - RETURN_LONG(retval.Int); + + php_error( E_WARNING, + "Loading of function %s failed: Could not insert function handle into hash", + (*fh)->function_name); + + /* Tidy up */ + zend_hash_del(WG(callbacks), (*fh)->function_name, strlen((*fh)->function_name) + 1); + return FAILURE; } - else if (!strcmp(fe->rettype, "string")) + + return SUCCESS; + + + +} +/* }}} */ + + +/* {{{ php_w32api_free_arguments + * Expects one argument, the head of a list of arguments to free + */ +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) { - RETURN_STRING(retval.Pointer, 1); + php_w32api_free_arguments(argument_list->next_arg); } - else if (!strcmp(fe->rettype, "byte")) - { - php_error(E_WARNING, "byte return values are not supported right now"); + + efree(argument_list); + + return; +} +/* }}} */ + +/* {{{ php_w32api_free_members + * Expects one argument, the head of a list of members to free + */ +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; +} +/* }}} */ + +/* {{{ php_w32api_load_library + * Expects two parameters, first is libraries name the second is a pointer + * to a pointer to w32api_lib_handle which will recieve the resultant handle. + * returns SUCCESS on success and FAILURE on failure. + */ +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) /* Could not load library */ + { + LPVOID message_buffer; + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + (LPTSTR)&message_buffer, + 0, + NULL); + + /* Tidy up */ + efree((*lh)->library_name); + efree(*lh); + efree(lh); + + php_error(E_WARNING, "Loading of library failed: %s", message_buffer); + LocalFree(message_buffer); + + return FAILURE; + } + + /* Add to hash */ + 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); + + /* Tidy up */ + efree((*lh)->library_name); + efree(*lh); + efree(lh); + + return FAILURE; + } + + + return SUCCESS; + +} +/* }}} */ + + +/* {{{ php_w32api_do_arg_types + */ +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; + + /* See how much room we need to emalloc */ + while(curr_arg) + { + i++; + + if(curr_arg->arg->flags & BYREF_FORCE) + { + j = i; + } + + curr_arg = curr_arg->next_arg; + } + + /* Check to see if any args are by ref */ + 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 *); /* Pointers are always the same size */ + } + + 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) +{ + + /** + * Theory Behind Implementation + * ============================ + * We have four main jobs: + * 1) Push arguments onto stach aligned at 4 bytes. + * 2) Call Function + * 3) Get Return Values + * 4) Perform any cleanup needed. + * + * Pushing arguments onto the stack is fairly simple, just push from right to left + * so for a function with the prototype int sum(int a, int b) we would push b and + * then a in that order. + * + * Calling the function is fine as we already have the pointer to the function which + * we can use with call [function_pointer] to make the actual call. + * + * Return values are where we begin to get complicated. Now for simple return values up + * to 8 bytes they are returned via the EAX/EDX register pair. This means we can just + * copy the EAX/EDX pair to the win32_result sturcture and be sure we get any simple + * return type. If the return type is more than 8 bytes then things get complicated. + * When calling we must pass a hidden argument on the stach which points to a tempory + * buffer with enough memory to hold the return value, this return value is then copied + * to the correct varaible by us. Microsoft being the nice bunnies they are, decided to + * copy an optimization Borland introduced under win16 which is to pass structs of under + * 8 bytes directly via EAX/EDX pair. One final notable exception is dealing with floating + * point return types where we need to retrive the floating point number of the systems + * math coprocessor stack using the fstp call. + * + * Finally if its a __cdecl call we have to clean up the stack, otherwise the callee does this. + * + */ + + 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 // Store stack pointer (esp) in stack_pointer + _asm sub esp, 0x100 // Give ourselves 256 bytes on the stack + + + 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; + + /* We should have been passed a write reference when + * BYREF_FORCE is Set so we just add a reference + * when we pass it to the function, + * TODO: register the reference internally for safe unreferencing + */ + + 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)) + { + /* Need to free this when we demarshall */ + 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: + /* Thanks sterling */ + 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) + { + /* First call */ +/* return_value = emalloc(th->type->size); + + 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 NULL; + + + for(i = 0; i < th->type->member_count; i++) + { + + + } +*/ } + + +} + + +/* ===================================================================================================== + * Win32 Class Code + * ===================================================================================================== + */ + +/* {{{ win32_class_functions[] + */ +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} +}; +/* }}} */ + +/* {{{ win32_class_init(TSRMLS_D) + */ +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; +} +/* }}} */ + +/* {{{ win32_class_rshutdown(TSRMLS_D) + * Cleans up at the end of the shutdown removing and freeing anything we added to the function + * table. + */ +int win32_class_rshutdown(TSRMLS_D) +{ + + return SUCCESS; +} +/* }}} */ + +/* {{{ proto: int Win32::RegisterFunction(string definition [, int flags]) + * Registers and Loads a function from an underlying Dll + */ +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; + + +} +/* }}} */ + +/* {{{ proto: int Win32::UnregisterFunction(string function_name) + * Unregisters a previously loaded function + */ +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|l", + &function_name, + &function_name_len) == FAILURE) + { + return; + } + + /* Our deleteor handler removes us from the WG(win32_ce)->function_table + * so no need to delete specifically from there + */ + zend_hash_del(WG(funcs), function_name, strlen(function_name) + 1); + + RETURN_TRUE; + +} +/* }}} */ + +/* {{{ proto: int Win32::RegisterCallback(string definition) + * Registers a callback type + */ +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|l", + &function_definition, + &function_definition_len) == FAILURE) + { + return; + } + + if(php_w32api_register_callback(function_definition, function_definition_len TSRMLS_CC) != SUCCESS) + { + RETURN_FALSE; + } + + RETURN_TRUE; + +} +/* }}} */ + + +/* {{{ proto: int Win32::DefineType(string definition) + * Defines a C Like Type for use. + */ +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; + +} +/* }}} */ + +/* {{{ proto: int Win32::GetTypeSize(string type_name) + * Returns the size of a registered type + */ +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)); + + +} +/* }}} */ + +/* {{{ proto: int Win32::InitType(string TypeName) + * Creates an instance of type TypeName + */ +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; } - else if (!strcmp(fe->rettype, "double")) + + php_w32api_init_type(*th, return_value TSRMLS_CC); + +} +/* }}} */ + +/* {{{ proto: int Win32::DecRef(mixed Variable) + * Decreases the reference count on a variable + */ +W32API_CLASS_FUNCTION(win32, decref) +{ + +} +/* }}} */ + +/* {{{ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + * THIS FUNCTION IS NOT PUBLICALLY ACCESSABLE + * IT IS USED AS A GENERIC HANDLER FOR W32API + * CALLS. + */ +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) { - RETURN_DOUBLE(retval.Double); + php_error(E_ERROR, "Could not retrieve function handle from hash table"); + RETURN_FALSE; } - else if (!strcmp(fe->rettype, "bool")) + + if(argc) { - if(retval.Int) + if(zend_get_parameters_array_ex(argc, &func_arguments) == FAILURE) { - RETURN_TRUE; + WRONG_PARAM_COUNT } - else + + 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++) { - RETURN_FALSE; + 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 { - /** - * This is returned in pRet, we need to get type and build a DYNAPARM for - * the return value and return the RESOURCE. - */ - - drval = malloc(sizeof(DYNAPARM)); - drval->pArg = pVParam; - drval->nWidth = VParamsz; - drval->dwFlags = 0; - ZEND_REGISTER_RESOURCE(return_value, drval, W32_G(le_dynaparm)); + 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); -/* {{{ Dynamic calling of dll functions by pushing onto the stack manually. */ -PHP_W32API_API RESULT php_w32api_dynamic_dll_call( int Flags, DWORD lpFunction, - int nArgs, DYNAPARM Param[], - LPVOID pRet, int nRetSize) -{ - /** - * Here we dont know the function we are calling or the arguments - * it expects so we must do quite a lot of work, normally done by - * the compiler ourselves, this is far easier to do it Assembly than - * in C.. here goes (jmoore - 05/11/2001). - * - * Based on the code by Ton Plooy - * See Also MSFT KB Article ID: Q171729 for more background. - * - * We will support two calling mechanisms, __stdcall and __cdecl(WINAPIV). - */ - RESULT Res = { 0 }; - int i, nInd, nSize; - DWORD dwEAX, dwEDX, dwVal, *pStack, dwStSize = 0; - BYTE *pArg; - - _asm { - mov pStack, esp - sub esp, 0x100 - } - - for (i = nArgs; i > 0; i--) { - nInd = i - 1; - nSize = (Param[nInd].nWidth + 3) / 4 * 4; - pArg = (BYTE *)Param[nInd].pArg + nSize - 4; - dwStSize += (DWORD)nSize; - while (nSize > 0) { - if (Param[nInd].dwFlags & DC_FLAG_ARGPTR) { - dwVal = *(DWORD *)pArg; - pArg -= 4; - } - else { - - dwVal = Param[nInd].dwArg; - } - - pStack--; - *pStack = dwVal; - nSize -= 4; - } - } - - if((pRet != NULL) && ((Flags & DC_BORLAND) || (nRetSize > 8))) - { - dwStSize += 4; - pStack--; - *pStack = (DWORD)pRet; - } - - _asm { - add esp, 0x100 - sub esp, dwStSize - call [lpFunction] - mov dwEAX, eax - mov dwEDX, edx - } - - if (Flags & DC_CALL_CDECL) { - _asm add esp, dwStSize - } - - if (Flags & DC_RETVAL_MATH4) { - _asm fstp dword ptr [Res] - } - else if (Flags & DC_RETVAL_MATH8) { - _asm fstp qword ptr [Res] - } - else if (pRet == NULL) { - _asm{ - mov eax, [dwEAX] - mov DWORD PTR [Res], eax - mov edx, [dwEDX] - mov DWORD PTR [Res + 4], edx - } - } - else if (((Flags & DC_BORLAND) == 0) && (nRetSize <= 8)) { - // Microsoft optimized less than 8-bytes structure passing - _asm { - mov ecx, DWORD PTR [pRet] - mov eax, [dwEAX] - mov DWORD PTR [ecx], eax - mov edx, [dwEDX] - mov DWORD PTR [ecx + 4], edx - } - } - return Res; -} -/* }}} */ + w32api_return_buffer = emalloc(th->size); + w32api_return_buffer_size = th->size; + } -/* {{{ Conversion function for zvals to dynparams */ -DYNAPARM w32api_convert_zval_to_dynparam(zval ** carg TSRMLS_DC) -{ - DYNAPARM dparam, *tparam; - dparam.dwFlags = 0; - switch((*carg)->type) + + res = php_w32api_do_dynamic_dll_call(*fh, argc, params, w32api_return_buffer, w32api_return_buffer_size); + + if(argc) + /* We should demarshall here not just efree */ + efree(params); + + switch((*fh)->return_type_id) { - case IS_RESOURCE: - tparam = (DYNAPARM *) zend_fetch_resource(carg TSRMLS_CC, -1, "dynaparm", NULL, 1, W32_G(le_dynaparm)); - if(!tparam) - { - php_error(E_ERROR, "Error when fetching argument"); - } - dparam = *tparam; + case W32API_LONG: + RETURN_LONG(res.lval); break; - case IS_LONG: - dparam.nWidth = sizeof(long); - dparam.dwArg = (*carg)->value.lval; + case W32API_INT: + RETURN_LONG(res.ival); break; - case IS_DOUBLE: - dparam.nWidth = sizeof(float); - dparam.pArg = &(*carg)->value.dval; - dparam.dwFlags = DC_FLAG_ARGPTR; + case W32API_STRING: + case W32API_BYTE: + RETURN_STRING(res.ptr, 1); break; - case IS_STRING: - dparam.nWidth = sizeof(char *); - dparam.pArg = (*carg)->value.str.val; + case W32API_DOUBLE: + RETURN_DOUBLE(res.dval); break; - case IS_BOOL: - dparam.nWidth = sizeof(BOOL); - dparam.dwArg = ((*carg)->value.lval == 0)?FALSE:TRUE; + case W32API_FLOAT: + RETURN_DOUBLE(res.fval); + break; + case W32API_BOOL: + if(res.ival) + { + RETURN_TRUE; + } + else + { + RETURN_FALSE; + } break; - case IS_NULL: - dparam.nWidth = sizeof(void *); - dparam.pArg = NULL; + case W32API_COMPLEX: break; default: - php_error(E_ERROR, "Cant convert variable to type dynparam"); + php_error(E_WARNING, "Unknown return type %s", (*fh)->return_type_name); } - return dparam; } /* }}} */ -/** - * Typedef functions, We need to be flexible about what types we are going - * to pass and retrive from functions in the win32 api. this means we need - * to be able to create structs of any different type at runtime. We can do - * this in asm. For example: - * - * typedef struct james { - * char firstname[81]; - * char lastname[81]; - * } - * - * An instance of the above struct (lets call this instance iJames. iJames - * is a pointer to the first letter of firstname (the base address), firstname - * then fills the following 81 bytes (some of these may be empty), lastname is - * at the offset iJames+81, - * - * |- 81 Bytes -|- 81 Bytes -| - * +------//------+------//------+ - * | James\0 | Moore\0 | - * +------//------+------//------+ - * ^ ^ - * iJames iJames[81] - * - * We could store a value in ax in this field by - * the assembly command: - * - * move ac iJames[81] - * - * Unions are easy in asm as the length of memory they use is equal to the size - * of their largest member. For example: - * - * typedef union foo { - * int i; - * char j; - * } - * - * The length of an int might be 4 bytes, the length of a char might be 1 byte. - * So if we create an instance of foo called bar then it would have the following - * layout in memory: - * - * +---+------------+ - * | ¦ | - * +---+------------+ - * ^^^^^ - * Memory area for char - * ^^^^^^^^^^^^^^^^^^ - * Memory area for int - * - * Therefore even if there was only a char held in this section and the union was within - * a struct the next offset would still be base address + 4 not +1 so we need to deal - * with this too. - * - * When defining types the user can call the w32api_deftype() function, this takes 2n+1 args where - * n is the number of members the type has. The first argument is the name of the struct struct - * after that is the type of the member followed by the members name (in pairs). - * - * - * James Moore 6/11/2001 - * - */ +#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); +} -/* {{{ proto int w32api_deftype(string typename, string member1_type, string member1_name, ...) - Defines a type for use with other w32api_functions. */ -PHP_FUNCTION(w32api_deftype) +W32API_CLASS_FUNCTION(win32, dump_function_hash) { - zval ***args; - int argc = ZEND_NUM_ARGS(); - int i; - runtime_struct *rst, *orst; - void *tmp; - field *fields, *ptr; + zend_hash_apply(WG(funcs), (apply_func_t)php_w32api_dump_function_hash_cb TSRMLS_CC); +} - args = (zval ***)emalloc(sizeof(zval **) * argc); - rst = malloc(sizeof(runtime_struct)); +W32API_CLASS_FUNCTION(win32, dump_callback_hash) +{ - ptr = (field *)emalloc(sizeof(field) *((argc-1)/2)); + zend_hash_apply(WG(callbacks), (apply_func_t)php_w32api_dump_callback_hash_cb TSRMLS_CC); +} - fields = ptr; - if((zend_get_parameters_array_ex(argc, args) == FAILURE) || ((argc % 2) != 1)) - { - WRONG_PARAM_COUNT - } +W32API_CLASS_FUNCTION(win32, dump_type_hash) +{ - for(i=2; ilibrary_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); - rst->name = (*args[0])->value.str.val; - rst->size = 0; + printf("=====================================================================\n"); - /** - * We now take each parameter pair and fill out the field struct - * for each parameter pair. + 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 +/* ===================================================================================================== + * Type Class Code + * ===================================================================================================== + */ + +/* {{{ type_class_functions[] + */ +function_entry type_class_functions[] = { + W32API_CLASS_FE(type, clone, NULL) + {NULL, NULL, NULL} +}; +/* }}} */ + + +/* {{{ type_class_init(TSRMLS_DC) + */ +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) + */ +/* Most of this code is borrowed from php-gtk. Thanks to Andrei and Zeev for their + * help with the prop-get/set functions + */ +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(); + + + /* If we have $foo->bar->baz->boo->bin we have to do sucessive propgets + * Until we can do our prop set (thanks Zeev, Andrei) */ - for(i=1; itype = malloc((*args[i])->value.str.len + 1); - memcpy(ptr->type, (*args[i])->value.str.val, (*args[i])->value.str.len + 1); + 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); + } - ptr->fname = malloc((*args[i+1])->value.str.len + 1); - memcpy(ptr->fname, (*args[i+1])->value.str.val, (*args[i+1])->value.str.len + 1); - ptr->fsize = 0; + /* Trying to access a property on a non-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); + } + } - if(!strcmp(ptr->type, "long")) - { - ptr->fsize = sizeof(long); - } - else if (!strcmp(ptr->type, "int")) - { - ptr->fsize = sizeof(int); - } - else if (!strcmp(ptr->type, "string")) - { - ptr->fsize = sizeof(char *); + } 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); + } + + /* Trying to access index on a non-array. */ + 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); + } + } } - else if (!strcmp(ptr->type, "byte")) - { - ptr->fsize = 1; + + zval_dtor(&overloaded_property->element); + } + + /* object is now the object we want to set our property on */ + 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) + */ +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) { + /* Trying to access a property on a non-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) { + /* Trying to access index on a non-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; } - else if (!strcmp(ptr->type, "double")) - { - ptr->fsize = sizeof(double); + + zval_dtor(&overloaded_property->element); + + object = result; + + if (getter_retval == FAILURE) { + return result; } - else if (!strcmp(ptr->type, "bool")) + } + + zval_add_ref(&result_ptr); + SEPARATE_ZVAL(&result_ptr); + return *result_ptr; +} +/* }}} */ + +/* {{{ proto: Type Type::Clone() + * Creates an exact clone of the object. + */ +W32API_CLASS_FUNCTION(type, clone) +{ + +} +/* }}} */ + +/* ===================================================================================================== + * Scanner & Parser Functions + * ===================================================================================================== + */ + +/* ----------------------------- + * Function Definition Functions + * ----------------------------- + */ + +/* {{{ w32api_parser_load_function_ex + * Callback for the parser, if the library name is cb.cb we are registering a + * callback so the LoadLibary and GetProcAddress code is skipped + */ +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; /* This is estrdup'd in the Scanner already!! */ + return_value->return_type_name = return_type; /* This is estrdup'd in the Scanner already!! */ + return_value->return_type_id = php_w32api_get_type_id_from_name(return_type); + + if(strcmp("cb.cb", library_name)) /* Bit of a hack but we are registering a callback */ + { + php_w32api_load_library(library_name, &return_value->lib TSRMLS_CC); + + if(!return_value->lib) { - ptr->fsize = sizeof(BOOL); + /* php_w32api_load_library has already given error */ + efree(return_value); + return NULL; } - else + + return_value->handle = GetProcAddress(return_value->lib->handle, function_name); + + if(!return_value->handle) { - /** - * this could be a userdef'd type so lets - * search the ht for that. - */ - if(zend_hash_find(W32_G(types), ptr->type, strlen(ptr->type), (void **) &tmp) == FAILURE) - { - php_error(E_WARNING, "Unknown type %s", ptr->type); - RETURN_FALSE; - } - orst = tmp; - ptr->fsize = orst->size; + /* Check for variation ending with A */ + 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) + { + /* TODO: php_error_docref and GetLastError etc */ + php_error(E_WARNING, "Could not load function %s", function_name); + efree(return_value); + return NULL; + } } - - rst->size += ptr->fsize; - ptr++; } - rst->fields = fields; + /* We want function_name in lowercase now */ + php_strtolower(return_value->function_name, strlen(return_value->function_name)); + + /* Free it if we have a alias */ + if(alias_name) + efree(function_name); + + return return_value; +} +/* }}} */ + +/* {{{ w32api_parser_make_argument + * Helper function for the parser + */ +arguments *w32api_parser_make_argument(char *arg_type, char *arg_name, int byref) +{ + arguments *return_value = NULL; /* Pointer to our return value */ + argument *argument_value = NULL; /* Our actual argument */ + + 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(zend_hash_add(W32_G(types), rst->name, strlen(rst->name), rst, sizeof(runtime_struct), NULL) == FAILURE) + if(argument_value->type_id == W32API_UNKNOWN) { - php_error(E_WARNING, "Error registering type %s", rst->name); - RETURN_FALSE; + php_error(E_NOTICE, "Unknown type %s used as arugment type", arg_type); } - RETURN_TRUE; + return return_value; +} +/* }}} */ + +/* {{{ w32api_parser_join_arguments + * Helper function for the parser + */ +arguments *w32api_parser_join_arguments(arguments *lval, arguments *rval) +{ + lval->next_arg = rval; + rval->prev_arg = lval; + return lval; } -/* }}} */ +/* }}} */ + +/* {{{ w32api_function_definition_error + * Error function for the parser + */ +int w32api_function_definition_error(char *s) +{ + php_error(E_ERROR, "Function Definition Parse Error: %s", s); + return 0; +} +/* }}} */ -/* {{{ proto resource w32api_init_dtype(string typename, mixed val1, mixed val2); - Creates an instance to the data type typename and fills it with the values val1, val2, the function - then returns a DYNAPARM which can be passed when invoking a function as a parameter.*/ -PHP_FUNCTION(w32api_init_dtype) +/* ------------------------- + * Type Definition Functions + * ------------------------- + */ +w32api_type_handle *w32api_parser_register_type(char *type_name, members *member_list) { - DYNAPARM *dparam, *tparam; - void *rtstruct, *tmp; - runtime_struct *rst; - field *ptr; - char *m; - zval ***args; - zval **curarg; - int i, j,argc = ZEND_NUM_ARGS(); + w32api_type_handle *return_value = NULL; + members *current_member; + int offset = 0; + int member_count = 0; - args = emalloc(sizeof(zval **) * argc); - dparam = emalloc(sizeof(DYNAPARM)); + return_value = emalloc(sizeof(w32api_type_handle)); - if(zend_get_parameters_array_ex(argc, args) != SUCCESS) - { - WRONG_PARAM_COUNT - } + return_value->member_list = member_list; + return_value->type_name = type_name; /* estrdup'd in parser */ + return_value->member_count = 0; + + current_member = return_value->member_list; - convert_to_string_ex(args[0]); - if(zend_hash_find(W32_G(types), (*args[0])->value.str.val, (*args[0])->value.str.len, (void **)&tmp) == FAILURE) + while(current_member != NULL) { - php_error(E_WARNING, "Unknown type %s",(*args[0])->value.str.val); - RETURN_FALSE + 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; } - rst = (runtime_struct *)tmp; - rtstruct = emalloc(rst->size); - rtstruct = memset(rtstruct, 0, rst->size); - tmp = rtstruct; - curarg = args[1]; - ptr = rst->fields; + return_value->size = offset; - i = 0; - j = (argc-1); + return return_value; - while(itype, "long")) - { - convert_to_long_ex(curarg); - memcpy(tmp, &(*curarg)->value.lval, ptr->fsize); - } - else if (!strcmp(ptr->type, "int")) - { - convert_to_long_ex(curarg); - memcpy(tmp, &(*curarg)->value.lval, ptr->fsize); - } - else if (!strcmp(ptr->type, "string")) - { - convert_to_string_ex(curarg); - m = emalloc(sizeof(char) * (*curarg)->value.str.len + 1); - memcpy(m, (*curarg)->value.str.val, (*curarg)->value.str.len + 1); - memcpy(tmp, &m, ptr->fsize); - } - else if (!strcmp(ptr->type, "byte")) - { - /* use Lower order bytes */ - convert_to_long_ex(curarg); - memcpy(tmp, &(*curarg)->value.lval, ptr->fsize); - } - else if (!strcmp(ptr->type, "double")) - { - convert_to_double_ex(curarg); - memcpy(tmp, &(*curarg)->value.dval, ptr->fsize); - } - else if (!strcmp(ptr->type, "bool")) - { - convert_to_boolean_ex(curarg); - memcpy(tmp, &(*curarg)->value.lval, ptr->fsize); - } - else - { - /** - * OK we have a user type here, we need to treat the param - * as a resource and fetch the DYNAPARM its contained in - * then copy the contents of its LPVOID pointer into our - * memory space. - */ - ZEND_FETCH_RESOURCE(tparam, DYNAPARM *, curarg, -1, "dynaparm", W32_G(le_dynaparm)); - memcpy(tmp, tparam->pArg, ptr->fsize); - } - /** - * We need somthing that is 1 byte - */ - (char)tmp += ptr->fsize; - (void *)tmp; +} + +members *w32api_parser_type_make_value(char *type_name, char *member_name, long flags) +{ + members *return_value = NULL; /* Pointer to our return value */ + member *member_value = NULL; /* Our actual member */ - curarg++; - ptr++; - i++; - } + member_value = emalloc(sizeof(member)); + return_value = emalloc(sizeof(members)); - dparam->dwFlags = 0; - dparam->nWidth = rst->size; - dparam->pArg = rtstruct; - - ZEND_REGISTER_RESOURCE(return_value, dparam, W32_G(le_dynaparm)); + return_value->member = member_value; + return_value->next_member = return_value->prev_member = NULL; + + member_value->member_name = member_name; /* estrdup'd in parser */ + member_value->member_type_name = type_name; /* estrdup'd in parser */ + member_value->member_type_id = php_w32api_get_type_id_from_name(type_name); + member_value->flags = flags; + return return_value; } -/* }}} */ -#endif /* HAVE_W32API */ +members *w32api_parser_type_join_values(members *lval, members *rval) +{ + lval->next_member = rval; + rval->prev_member = lval; + + return lval; +} + +/* {{{ w32api_function_definition_error + * Error function for the parser + */ +int w32api_type_definition_error(char *s) +{ + php_error(E_ERROR, "Type Definition Parse Error: %s", s); + return 0; +} +/* }}} */ + + +#endif /* HAVE_W32API */ \ No newline at end of file diff --git a/ext/w32api/w32api.dsp b/ext/w32api/w32api.dsp index 8910cfb929..71eaaf57e5 100644 --- a/ext/w32api/w32api.dsp +++ b/ext/w32api/w32api.dsp @@ -4,7 +4,7 @@ # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 -CFG=w32api - Win32 Release_TS +CFG=w32api - Win32 Debug_TS !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE @@ -13,12 +13,12 @@ CFG=w32api - Win32 Release_TS !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE -!MESSAGE NMAKE /f "w32api.mak" CFG="w32api - Win32 Release_TS" +!MESSAGE NMAKE /f "w32api.mak" CFG="w32api - Win32 Debug_TS" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE -!MESSAGE "w32api - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE "w32api - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "w32api - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library") !MESSAGE # Begin Project @@ -29,67 +29,66 @@ CPP=cl.exe MTL=midl.exe RSC=rc.exe -!IF "$(CFG)" == "w32api - Win32 Release_TS" +!IF "$(CFG)" == "w32api - Win32 Debug_TS" # PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release_TS" -# PROP BASE Intermediate_Dir "Release_TS" -# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "w32api___Win32_Debug_TS" +# PROP BASE Intermediate_Dir "w32api___Win32_Debug_TS" # PROP BASE Target_Dir "" # PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release_TS" -# PROP Intermediate_Dir "Release_TS" +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "../../Debug_TS" +# PROP Intermediate_Dir "Debug_TS" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COMPILE_DL_W32API" /D ZTS=1 /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /ZI /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D ZEND_DEBUG=0 /D HAVE_W32API=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "W32API_EXPORTS" /D "COMPILE_DL_W32API" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /FR /YX /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x406 /d "NDEBUG" -# ADD RSC /l 0x406 /d "NDEBUG" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "W32API_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "W32API_EXPORTS" /D HAVE_W32API=1 /D "COMPILE_DL_W32API" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D ZEND_DEBUG=1 /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x809 /d "_DEBUG" +# ADD RSC /l 0x809 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS/php_w32api.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\Release_TS_Inline" +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 php4ts_debug.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"../../Debug_TS/php_w32api.dll" /pdbtype:sept /libpath:"..\..\Debug_TS" -!ELSEIF "$(CFG)" == "w32api - Win32 Debug_TS" +!ELSEIF "$(CFG)" == "w32api - Win32 Release_TS" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Debug_TS" -# PROP BASE Intermediate_Dir "Debug_TS" -# PROP BASE Ignore_Export_Lib 0 +# PROP BASE Output_Dir "w32api___Win32_Release_TS" +# PROP BASE Intermediate_Dir "w32api___Win32_Release_TS" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Debug_TS" -# PROP Intermediate_Dir "Debug_TS" +# PROP Output_Dir "../../Release_TS" +# PROP Intermediate_Dir "Release_TS" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COMPILE_DL_W32API" /D ZTS=1 /YX /FD /c -# ADD CPP /nologo /MTd /W3 /GX /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D "_DEBUG" /D "_LIB" /D "__WIN32__" /D "USE_TLS" /D "WIN32" /D "_MBCS" /D ZEND_DEBUG=1 /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "W32API_EXPORTS" /D "COMPILE_DL_W32API" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_W32API=1 /FAcs /FR /YX /FD /c +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "W32API_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "W32API_EXPORTS" /D "HAVE_W32API" /D "COMPILE_DL_W32API" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D ZEND_DEBUG=0 /YX /FD /c +# SUBTRACT CPP /WX /Fr # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# SUBTRACT MTL /Oicf -# ADD BASE RSC /l 0x406 /d "NDEBUG" +# ADD BASE RSC /l 0x809 /d "NDEBUG" # ADD RSC /l 0x809 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /machine:I386 -# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts_debug.lib /nologo /dll /machine:I386 /out:"..\..\Debug_TS/php_w32api.dll" /libpath:"..\..\Debug_TS" +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 php4ts.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /debugtype:both /machine:I386 /out:"../../Release_TS/php_w32api.dll" /libpath:"..\..\Release_TS" +# SUBTRACT LINK32 /incremental:yes !ENDIF # Begin Target -# Name "w32api - Win32 Release_TS" # Name "w32api - Win32 Debug_TS" +# Name "w32api - Win32 Release_TS" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" @@ -97,6 +96,22 @@ LINK32=link.exe SOURCE=.\w32api.c # End Source File +# Begin Source File + +SOURCE=.\w32api_function_definition_parser.c +# End Source File +# Begin Source File + +SOURCE=.\w32api_function_definition_scanner.c +# End Source File +# Begin Source File + +SOURCE=.\w32api_type_definition_parser.c +# End Source File +# Begin Source File + +SOURCE=.\w32api_type_definition_scanner.c +# End Source File # End Group # Begin Group "Header Files" @@ -105,10 +120,162 @@ SOURCE=.\w32api.c SOURCE=.\php_w32api.h # End Source File +# Begin Source File + +SOURCE=.\w32api_function_definition_parser.h +# End Source File +# Begin Source File + +SOURCE=.\w32api_type_definition_parser.h +# End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group +# Begin Group "Parsers" + +# PROP Default_Filter ".y" +# Begin Source File + +SOURCE=.\w32api_function_definition_parser.y + +!IF "$(CFG)" == "w32api - Win32 Debug_TS" + +# Begin Custom Build +InputDir=. +InputPath=.\w32api_function_definition_parser.y + +BuildCmds= \ + bison --output=w32api_function_definition_parser.c -v -d -p w32api_function_definition_ w32api_function_definition_parser.y + +"$(InputDir)/w32api_function_definition_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)/w32api_function_definition_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "w32api - Win32 Release_TS" + +# Begin Custom Build +InputDir=. +InputPath=.\w32api_function_definition_parser.y + +BuildCmds= \ + bison --output=w32api_function_definition_parser.c -v -d -p w32api_function_definition_ w32api_function_definition_parser.y + +"$(InputDir)/w32api_function_definition_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)/w32api_function_definition_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\w32api_type_definition_parser.y + +!IF "$(CFG)" == "w32api - Win32 Debug_TS" + +# Begin Custom Build +InputDir=. +InputPath=.\w32api_type_definition_parser.y + +BuildCmds= \ + bison --output=w32api_type_definition_parser.c -v -d -p w32api_type_definition_ w32api_type_definition_parser.y + +"$(InputDir)/w32api_type_definition_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)/w32api_type_definition_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "w32api - Win32 Release_TS" + +# Begin Custom Build +InputDir=. +InputPath=.\w32api_type_definition_parser.y + +BuildCmds= \ + bison --output=w32api_type_definition_parser.c -v -d -p w32api_type_definition_ w32api_type_definition_parser.y + +"$(InputDir)/w32api_type_definition_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)/w32api_type_definition_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# End Group +# Begin Group "Scanners" + +# PROP Default_Filter ".l" +# Begin Source File + +SOURCE=.\w32api_function_definition_scanner.l + +!IF "$(CFG)" == "w32api - Win32 Debug_TS" + +# Begin Custom Build +InputDir=. +InputPath=.\w32api_function_definition_scanner.l + +"$(InputDir)\w32api_function_definition_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + flex -B -i -Pw32api_function_definition -ow32api_function_definition_scanner.c w32api_function_definition_scanner.l + +# End Custom Build + +!ELSEIF "$(CFG)" == "w32api - Win32 Release_TS" + +# Begin Custom Build +InputDir=. +InputPath=.\w32api_function_definition_scanner.l + +"$(InputDir)\w32api_function_definition_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + flex -B -i -Pw32api_function_definition -ow32api_function_definition_scanner.c w32api_function_definition_scanner.l + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\w32api_type_definition_scanner.l + +!IF "$(CFG)" == "w32api - Win32 Debug_TS" + +# Begin Custom Build +InputDir=. +InputPath=.\w32api_type_definition_scanner.l + +"$(InputDir)/w32api_type_definition_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + flex -B -i -Pw32api_type_definition -ow32api_type_definition_scanner.c w32api_type_definition_scanner.l + +# End Custom Build + +!ELSEIF "$(CFG)" == "w32api - Win32 Release_TS" + +# Begin Custom Build +InputDir=. +InputPath=.\w32api_type_definition_scanner.l + +"$(InputDir)/w32api_type_definition_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + flex -B -i -Pw32api_type_definition -ow32api_type_definition_scanner.c w32api_type_definition_scanner.l + +# End Custom Build + +!ENDIF + +# End Source File +# End Group # End Target # End Project