]> granicus.if.org Git - php/commitdiff
Rewrite of the W32api extension
authorJames Moore <jmoore@php.net>
Tue, 12 Nov 2002 14:29:42 +0000 (14:29 +0000)
committerJames Moore <jmoore@php.net>
Tue, 12 Nov 2002 14:29:42 +0000 (14:29 +0000)
@ New version of w32api extension. Old API deprecated (jmoore)

12 files changed:
ext/w32api/README
ext/w32api/TODO
ext/w32api/examples/uptime.php [deleted file]
ext/w32api/php_w32api.h
ext/w32api/test_dll/dll_test.h [deleted file]
ext/w32api/test_dll/test.php [deleted file]
ext/w32api/test_dll/test_dll.c [deleted file]
ext/w32api/test_dll/test_dll.def [deleted file]
ext/w32api/test_dll/test_dll.dsp [deleted file]
ext/w32api/test_dll/test_dll.dsw [deleted file]
ext/w32api/w32api.c
ext/w32api/w32api.dsp

index 0e77cfe750a4249f1e890be06dcb5d02ea3ca728..66a65ee747c6e09cb91d0de9d7d11720b01a5421 100644 (file)
@@ -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 =====================================
-<?php
-
-        dl("php_w32api.dll");
-        
-        w32api_register_function("kernel32.dll", 
-                                 "GetTickCount",
-                                 W32_LONG);
-                                 
-        w32api_register_function("User32.dll",
-                                 "MessageBoxA",
-                                 W32_LONG);
-
-        $ticks = w32api_invoke_function("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));
-
-        w32api_invoke_function("MessageBoxA", 
-                                NULL, 
-                                $str, 
-                                "Uptime Information", 
-                                MB_OK);
-?>
-============================================================================
-
-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 <jmoore@php.net>
+See notes in w32api.c
\ No newline at end of file
index 76b2562d9b57e4bd2afaf84755d245672112591c..771ad3b3842b4eb7b1d052bdbbe529b7accbbbf8 100644 (file)
@@ -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 (file)
index 973a52d..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-<?php
-/*
-   +----------------------------------------------------------------------+
-   | 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 <jmoore@php.net>                                 |
-   +----------------------------------------------------------------------+
-*/
-
-/* $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);
-?>
index cbe52234ea451d7aefc448aa9204315ccb7cc355..05a353265fc540c7dc16b032758a5fa852c620be 100644 (file)
@@ -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        |
    | 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 <jmoore@php.net>                                 |
+   | Authors: James Moore <jmoore@php.net>                                |
    +----------------------------------------------------------------------+
- */
+*/
 
- /* $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 (file)
index a0d84c8..0000000
+++ /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 <jmoore@php.net>                                 |
-   +----------------------------------------------------------------------+
-*/
-
-#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 (file)
index 9f85aca..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<?php
-
-        dl("php_w32api.dll");
-        
-        w32api_register_function("test_dll.dll", "print_names", "long");
-        w32api_deftype("name", "string", "fname", "string", "lname");
-        $rsrc = w32api_init_dtype("name", "James", "Moore");
-        print_names($rsrc);
-
-?>
diff --git a/ext/w32api/test_dll/test_dll.c b/ext/w32api/test_dll/test_dll.c
deleted file mode 100644 (file)
index c455cc3..0000000
+++ /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 <jmoore@php.net>                                 |
-   +----------------------------------------------------------------------+
-*/
-
-/* $Id$ */
-
-#include <stdio.h>
-#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 (file)
index 7ffba76..0000000
+++ /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 (file)
index 945dc7e..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-# Microsoft Developer Studio Project File - Name="test_dll" - Package Owner=<4>\r
-# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
-# ** DO NOT EDIT **\r
-\r
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
-\r
-CFG=test_dll - Win32 Debug\r
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
-!MESSAGE use the Export Makefile command and run\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "test_dll.mak".\r
-!MESSAGE \r
-!MESSAGE You can specify a configuration when running NMAKE\r
-!MESSAGE by defining the macro CFG on the command line. For example:\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "test_dll.mak" CFG="test_dll - Win32 Debug"\r
-!MESSAGE \r
-!MESSAGE Possible choices for configuration are:\r
-!MESSAGE \r
-!MESSAGE "test_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE "test_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE \r
-\r
-# Begin Project\r
-# PROP AllowPerConfigDependencies 0\r
-# PROP Scc_ProjName ""\r
-# PROP Scc_LocalPath ""\r
-CPP=cl.exe\r
-MTL=midl.exe\r
-RSC=rc.exe\r
-\r
-!IF  "$(CFG)" == "test_dll - Win32 Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "Release"\r
-# PROP BASE Intermediate_Dir "Release"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Release"\r
-# PROP Intermediate_Dir "Release"\r
-# PROP Target_Dir ""\r
-# 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\r
-# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_DLL_EXPORTS" /YX /FD /c\r
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x809 /d "NDEBUG"\r
-# ADD RSC /l 0x809 /d "NDEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# 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\r
-# 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\r
-\r
-!ELSEIF  "$(CFG)" == "test_dll - Win32 Debug"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "Debug"\r
-# PROP BASE Intermediate_Dir "Debug"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Debug"\r
-# PROP Intermediate_Dir "Debug"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# 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\r
-# 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\r
-# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x809 /d "_DEBUG"\r
-# ADD RSC /l 0x809 /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# 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\r
-# 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\r
-\r
-!ENDIF \r
-\r
-# Begin Target\r
-\r
-# Name "test_dll - Win32 Release"\r
-# Name "test_dll - Win32 Debug"\r
-# Begin Group "Source Files"\r
-\r
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
-# Begin Source File\r
-\r
-SOURCE=.\test_dll.c\r
-# End Source File\r
-# End Group\r
-# Begin Group "Header Files"\r
-\r
-# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
-# Begin Source File\r
-\r
-SOURCE=.\dll_test.h\r
-# End Source File\r
-# End Group\r
-# Begin Group "Resource Files"\r
-\r
-# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
-# End Group\r
-# End Target\r
-# End Project\r
diff --git a/ext/w32api/test_dll/test_dll.dsw b/ext/w32api/test_dll/test_dll.dsw
deleted file mode 100644 (file)
index e22c7b4..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-Microsoft Developer Studio Workspace File, Format Version 6.00\r
-# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\r
-\r
-###############################################################################\r
-\r
-Project: "test_dll"=.\test_dll.dsp - Package Owner=<4>\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<4>\r
-{{{\r
-}}}\r
-\r
-###############################################################################\r
-\r
-Global:\r
-\r
-Package=<5>\r
-{{{\r
-}}}\r
-\r
-Package=<3>\r
-{{{\r
-}}}\r
-\r
-###############################################################################\r
-\r
index 89190d317530ed5c32858e1cab5980f13ecb531c..7bbb226e2b5b6e4a8764a941b8ecdd385abe0816 100644 (file)
@@ -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        |
    | 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 <jmoore@php.net>                                 |
+   | Authors: James Moore <jmoore@php.net>                                |
    +----------------------------------------------------------------------+
  */
 
 /* $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: <return_type> <function_name> [Alias <alias_name] (<argument_list>) From <some_dll>
+ *
+ *      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_type>
+ *                              [&]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> { <type_list> }
+ *
+ *      type_name :-            A unique name for this type.
+ *
+ *      type_list :-            Takes for form <member_type> [&]<member_name>
+ *
+ *          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 <stdio.h>
 #include <stdlib.h>
-#define  WIN32_LEAN_AND_MEAN
+
+#define WINDOWS_LEAN_AND_MEAN
 #include <windows.h>
 
 #include "php.h"
 #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 <tonp@xs4all.nl>
-        * 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 <jmoore@php.net> 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; i<argc; i++)
-       {
-               convert_to_string_ex(args[i]);
-       }
+       zend_hash_apply(WG(types), (apply_func_t)php_w32api_dump_type_hash_cb TSRMLS_CC);
+}
+
+int php_w32api_dump_library_hash_cb(void *pData TSRMLS_DC)
+{
+       w32api_lib_handle *lh = pData;
 
-       convert_to_string_ex(args[0]);
+       printf("=====================================================================\n");
+       printf("Library Name:    \t\t%s\n", lh->library_name);
+       printf("Reference Count: \t\t%d\n", lh->ref_count);
+       printf("Library Handle:  \t\t%p\n", lh->handle);
+       printf("Lib ptr loc      \t\t%p\n", lh);
+       printf("ll n loc         \t\t%p\n", &lh->ref_count);
 
-       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; i<argc; i += 2)
-       {
-               ptr->type = 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(i<j)
-       {
-               if(!strcmp(ptr->type, "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
index 8910cfb929665e45204802d4f1545c98ce567ed0..71eaaf57e521895a3f6aeae92f303ba517c2a353 100644 (file)
@@ -4,7 +4,7 @@
 \r
 # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
 \r
-CFG=w32api - Win32 Release_TS\r
+CFG=w32api - Win32 Debug_TS\r
 !MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
 !MESSAGE use the Export Makefile command and run\r
 !MESSAGE \r
@@ -13,12 +13,12 @@ CFG=w32api - Win32 Release_TS
 !MESSAGE You can specify a configuration when running NMAKE\r
 !MESSAGE by defining the macro CFG on the command line. For example:\r
 !MESSAGE \r
-!MESSAGE NMAKE /f "w32api.mak" CFG="w32api - Win32 Release_TS"\r
+!MESSAGE NMAKE /f "w32api.mak" CFG="w32api - Win32 Debug_TS"\r
 !MESSAGE \r
 !MESSAGE Possible choices for configuration are:\r
 !MESSAGE \r
-!MESSAGE "w32api - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")\r
 !MESSAGE "w32api - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")\r
+!MESSAGE "w32api - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")\r
 !MESSAGE \r
 \r
 # Begin Project\r
@@ -29,67 +29,66 @@ CPP=cl.exe
 MTL=midl.exe\r
 RSC=rc.exe\r
 \r
-!IF  "$(CFG)" == "w32api - Win32 Release_TS"\r
+!IF  "$(CFG)" == "w32api - Win32 Debug_TS"\r
 \r
 # PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "Release_TS"\r
-# PROP BASE Intermediate_Dir "Release_TS"\r
-# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Use_Debug_Libraries 1\r
+# PROP BASE Output_Dir "w32api___Win32_Debug_TS"\r
+# PROP BASE Intermediate_Dir "w32api___Win32_Debug_TS"\r
 # PROP BASE Target_Dir ""\r
 # PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Release_TS"\r
-# PROP Intermediate_Dir "Release_TS"\r
+# PROP Use_Debug_Libraries 1\r
+# PROP Output_Dir "../../Debug_TS"\r
+# PROP Intermediate_Dir "Debug_TS"\r
 # PROP Ignore_Export_Lib 0\r
 # PROP Target_Dir ""\r
-# 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\r
-# 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\r
-# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x406 /d "NDEBUG"\r
-# ADD RSC /l 0x406 /d "NDEBUG"\r
+# 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\r
+# 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\r
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
+# ADD BASE RSC /l 0x809 /d "_DEBUG"\r
+# ADD RSC /l 0x809 /d "_DEBUG"\r
 BSC32=bscmake.exe\r
 # ADD BASE BSC32 /nologo\r
 # ADD BSC32 /nologo\r
 LINK32=link.exe\r
-# 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\r
-# 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"\r
+# 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\r
+# 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"\r
 \r
-!ELSEIF  "$(CFG)" == "w32api - Win32 Debug_TS"\r
+!ELSEIF  "$(CFG)" == "w32api - Win32 Release_TS"\r
 \r
 # PROP BASE Use_MFC 0\r
 # PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "Debug_TS"\r
-# PROP BASE Intermediate_Dir "Debug_TS"\r
-# PROP BASE Ignore_Export_Lib 0\r
+# PROP BASE Output_Dir "w32api___Win32_Release_TS"\r
+# PROP BASE Intermediate_Dir "w32api___Win32_Release_TS"\r
 # PROP BASE Target_Dir ""\r
 # PROP Use_MFC 0\r
 # PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Debug_TS"\r
-# PROP Intermediate_Dir "Debug_TS"\r
+# PROP Output_Dir "../../Release_TS"\r
+# PROP Intermediate_Dir "Release_TS"\r
 # PROP Ignore_Export_Lib 0\r
 # PROP Target_Dir ""\r
-# 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\r
-# 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\r
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "W32API_EXPORTS" /YX /FD /c\r
+# 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\r
+# SUBTRACT CPP /WX /Fr\r
 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# SUBTRACT MTL /Oicf\r
-# ADD BASE RSC /l 0x406 /d "NDEBUG"\r
+# ADD BASE RSC /l 0x809 /d "NDEBUG"\r
 # ADD RSC /l 0x809 /d "NDEBUG"\r
 BSC32=bscmake.exe\r
 # ADD BASE BSC32 /nologo\r
 # ADD BSC32 /nologo\r
 LINK32=link.exe\r
-# 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\r
-# 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"\r
+# 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\r
+# 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"\r
+# SUBTRACT LINK32 /incremental:yes\r
 \r
 !ENDIF \r
 \r
 # Begin Target\r
 \r
-# Name "w32api - Win32 Release_TS"\r
 # Name "w32api - Win32 Debug_TS"\r
+# Name "w32api - Win32 Release_TS"\r
 # Begin Group "Source Files"\r
 \r
 # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
@@ -97,6 +96,22 @@ LINK32=link.exe
 \r
 SOURCE=.\w32api.c\r
 # End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\w32api_function_definition_parser.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\w32api_function_definition_scanner.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\w32api_type_definition_parser.c\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\w32api_type_definition_scanner.c\r
+# End Source File\r
 # End Group\r
 # Begin Group "Header Files"\r
 \r
@@ -105,10 +120,162 @@ SOURCE=.\w32api.c
 \r
 SOURCE=.\php_w32api.h\r
 # End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\w32api_function_definition_parser.h\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\w32api_type_definition_parser.h\r
+# End Source File\r
 # End Group\r
 # Begin Group "Resource Files"\r
 \r
 # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"\r
 # End Group\r
+# Begin Group "Parsers"\r
+\r
+# PROP Default_Filter ".y"\r
+# Begin Source File\r
+\r
+SOURCE=.\w32api_function_definition_parser.y\r
+\r
+!IF  "$(CFG)" == "w32api - Win32 Debug_TS"\r
+\r
+# Begin Custom Build\r
+InputDir=.\r
+InputPath=.\w32api_function_definition_parser.y\r
+\r
+BuildCmds= \\r
+       bison --output=w32api_function_definition_parser.c -v -d -p w32api_function_definition_ w32api_function_definition_parser.y\r
+\r
+"$(InputDir)/w32api_function_definition_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+   $(BuildCmds)\r
+\r
+"$(InputDir)/w32api_function_definition_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+   $(BuildCmds)\r
+# End Custom Build\r
+\r
+!ELSEIF  "$(CFG)" == "w32api - Win32 Release_TS"\r
+\r
+# Begin Custom Build\r
+InputDir=.\r
+InputPath=.\w32api_function_definition_parser.y\r
+\r
+BuildCmds= \\r
+       bison --output=w32api_function_definition_parser.c -v -d -p w32api_function_definition_ w32api_function_definition_parser.y\r
+\r
+"$(InputDir)/w32api_function_definition_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+   $(BuildCmds)\r
+\r
+"$(InputDir)/w32api_function_definition_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+   $(BuildCmds)\r
+# End Custom Build\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\w32api_type_definition_parser.y\r
+\r
+!IF  "$(CFG)" == "w32api - Win32 Debug_TS"\r
+\r
+# Begin Custom Build\r
+InputDir=.\r
+InputPath=.\w32api_type_definition_parser.y\r
+\r
+BuildCmds= \\r
+       bison --output=w32api_type_definition_parser.c -v -d -p w32api_type_definition_ w32api_type_definition_parser.y\r
+\r
+"$(InputDir)/w32api_type_definition_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+   $(BuildCmds)\r
+\r
+"$(InputDir)/w32api_type_definition_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+   $(BuildCmds)\r
+# End Custom Build\r
+\r
+!ELSEIF  "$(CFG)" == "w32api - Win32 Release_TS"\r
+\r
+# Begin Custom Build\r
+InputDir=.\r
+InputPath=.\w32api_type_definition_parser.y\r
+\r
+BuildCmds= \\r
+       bison --output=w32api_type_definition_parser.c -v -d -p w32api_type_definition_ w32api_type_definition_parser.y\r
+\r
+"$(InputDir)/w32api_type_definition_parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+   $(BuildCmds)\r
+\r
+"$(InputDir)/w32api_type_definition_parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+   $(BuildCmds)\r
+# End Custom Build\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# End Group\r
+# Begin Group "Scanners"\r
+\r
+# PROP Default_Filter ".l"\r
+# Begin Source File\r
+\r
+SOURCE=.\w32api_function_definition_scanner.l\r
+\r
+!IF  "$(CFG)" == "w32api - Win32 Debug_TS"\r
+\r
+# Begin Custom Build\r
+InputDir=.\r
+InputPath=.\w32api_function_definition_scanner.l\r
+\r
+"$(InputDir)\w32api_function_definition_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+       flex -B -i -Pw32api_function_definition -ow32api_function_definition_scanner.c w32api_function_definition_scanner.l\r
+\r
+# End Custom Build\r
+\r
+!ELSEIF  "$(CFG)" == "w32api - Win32 Release_TS"\r
+\r
+# Begin Custom Build\r
+InputDir=.\r
+InputPath=.\w32api_function_definition_scanner.l\r
+\r
+"$(InputDir)\w32api_function_definition_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+       flex -B -i -Pw32api_function_definition -ow32api_function_definition_scanner.c w32api_function_definition_scanner.l\r
+\r
+# End Custom Build\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# Begin Source File\r
+\r
+SOURCE=.\w32api_type_definition_scanner.l\r
+\r
+!IF  "$(CFG)" == "w32api - Win32 Debug_TS"\r
+\r
+# Begin Custom Build\r
+InputDir=.\r
+InputPath=.\w32api_type_definition_scanner.l\r
+\r
+"$(InputDir)/w32api_type_definition_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+       flex -B -i -Pw32api_type_definition -ow32api_type_definition_scanner.c w32api_type_definition_scanner.l\r
+\r
+# End Custom Build\r
+\r
+!ELSEIF  "$(CFG)" == "w32api - Win32 Release_TS"\r
+\r
+# Begin Custom Build\r
+InputDir=.\r
+InputPath=.\w32api_type_definition_scanner.l\r
+\r
+"$(InputDir)/w32api_type_definition_scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"\r
+       flex -B -i -Pw32api_type_definition -ow32api_type_definition_scanner.c w32api_type_definition_scanner.l\r
+\r
+# End Custom Build\r
+\r
+!ENDIF \r
+\r
+# End Source File\r
+# End Group\r
 # End Target\r
 # End Project\r