summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Moore <jmoore@php.net>2001-11-07 14:31:03 +0000
committerJames Moore <jmoore@php.net>2001-11-07 14:31:03 +0000
commit70941fe41b93d6a7c6809780b17c6323127977cd (patch)
tree5cc34e96dbd309839bedea9de610387e6c3e0326
parentf111b84e0516594dc4b03bf9824e1c13a19c921c (diff)
downloadphp-git-70941fe41b93d6a7c6809780b17c6323127977cd.tar.gz
@ - Add generic Win 32 API extension (jmoore)
-rw-r--r--ext/w32api/CREDITS2
-rw-r--r--ext/w32api/EXPERIMENTAL0
-rw-r--r--ext/w32api/README49
-rw-r--r--ext/w32api/TODO5
-rw-r--r--ext/w32api/examples/uptime.php64
-rw-r--r--ext/w32api/php_w32api.h137
-rw-r--r--ext/w32api/test_dll/dll_test.h31
-rw-r--r--ext/w32api/test_dll/test.php10
-rw-r--r--ext/w32api/test_dll/test_dll.c33
-rw-r--r--ext/w32api/test_dll/test_dll.def2
-rw-r--r--ext/w32api/test_dll/test_dll.dsp110
-rw-r--r--ext/w32api/test_dll/test_dll.dsw29
-rw-r--r--ext/w32api/w32api.c898
-rw-r--r--ext/w32api/w32api.dsp114
14 files changed, 1484 insertions, 0 deletions
diff --git a/ext/w32api/CREDITS b/ext/w32api/CREDITS
new file mode 100644
index 0000000000..e046aad54c
--- /dev/null
+++ b/ext/w32api/CREDITS
@@ -0,0 +1,2 @@
+W32API
+James Moore <jmoore@php.net>
diff --git a/ext/w32api/EXPERIMENTAL b/ext/w32api/EXPERIMENTAL
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/ext/w32api/EXPERIMENTAL
diff --git a/ext/w32api/README b/ext/w32api/README
new file mode 100644
index 0000000000..0e77cfe750
--- /dev/null
+++ b/ext/w32api/README
@@ -0,0 +1,49 @@
+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>
diff --git a/ext/w32api/TODO b/ext/w32api/TODO
new file mode 100644
index 0000000000..76b2562d9b
--- /dev/null
+++ b/ext/w32api/TODO
@@ -0,0 +1,5 @@
+ TODO
+ ====
+ - ByVal and ByRef Passing.
+ - Better type checking.
+ - Fix Mem leaks.
diff --git a/ext/w32api/examples/uptime.php b/ext/w32api/examples/uptime.php
new file mode 100644
index 0000000000..24ef0e5422
--- /dev/null
+++ b/ext/w32api/examples/uptime.php
@@ -0,0 +1,64 @@
+<?php
+/*
+ +----------------------------------------------------------------------+
+ | PHP version 4.0 |
+ +----------------------------------------------------------------------+
+ | 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 |
+ | 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. |
+ +----------------------------------------------------------------------+
+ | Authors: 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);
+?>
diff --git a/ext/w32api/php_w32api.h b/ext/w32api/php_w32api.h
new file mode 100644
index 0000000000..3eb7de4177
--- /dev/null
+++ b/ext/w32api/php_w32api.h
@@ -0,0 +1,137 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP version 4.0 |
+ +----------------------------------------------------------------------+
+ | 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 |
+ | 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. |
+ +----------------------------------------------------------------------+
+ | Authors: James Moore <jmoore@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+ /* $Id$ */
+
+#if HAVE_W32API
+
+#ifndef PHP_W32API_H
+#define PHP_W32API_H
+
+extern zend_module_entry 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
+
+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_END_MODULE_GLOBALS(w32api)
+
+#ifdef ZTS
+#define W32_G(v) TSRMG(w32api_globals_id, zend_w32api_globals *, v)
+#else
+#define W32_G(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);
+PHP_MINIT_FUNCTION(w32api);
+PHP_MSHUTDOWN_FUNCTION(w32api);
+
+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);
+
+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 /* PHP_W32API_H */
+#endif /* 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
new file mode 100644
index 0000000000..e443c1784a
--- /dev/null
+++ b/ext/w32api/test_dll/dll_test.h
@@ -0,0 +1,31 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP version 4.0 |
+ +----------------------------------------------------------------------+
+ | 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 |
+ | 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. |
+ +----------------------------------------------------------------------+
+ | Authors: 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
new file mode 100644
index 0000000000..9f85acaf03
--- /dev/null
+++ b/ext/w32api/test_dll/test.php
@@ -0,0 +1,10 @@
+<?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
new file mode 100644
index 0000000000..39b29c416e
--- /dev/null
+++ b/ext/w32api/test_dll/test_dll.c
@@ -0,0 +1,33 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP version 4.0 |
+ +----------------------------------------------------------------------+
+ | 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 |
+ | 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. |
+ +----------------------------------------------------------------------+
+ | Authors: 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
new file mode 100644
index 0000000000..7ffba76950
--- /dev/null
+++ b/ext/w32api/test_dll/test_dll.def
@@ -0,0 +1,2 @@
+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
new file mode 100644
index 0000000000..945dc7efc1
--- /dev/null
+++ b/ext/w32api/test_dll/test_dll.dsp
@@ -0,0 +1,110 @@
+# Microsoft Developer Studio Project File - Name="test_dll" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=test_dll - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "test_dll.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "test_dll.mak" CFG="test_dll - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "test_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "test_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "test_dll - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_DLL_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_DLL_EXPORTS" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+
+!ELSEIF "$(CFG)" == "test_dll - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_DLL_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TEST_DLL_EXPORTS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "test_dll - Win32 Release"
+# Name "test_dll - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\test_dll.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\dll_test.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/ext/w32api/test_dll/test_dll.dsw b/ext/w32api/test_dll/test_dll.dsw
new file mode 100644
index 0000000000..e22c7b49ee
--- /dev/null
+++ b/ext/w32api/test_dll/test_dll.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "test_dll"=.\test_dll.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/ext/w32api/w32api.c b/ext/w32api/w32api.c
new file mode 100644
index 0000000000..068ae3193f
--- /dev/null
+++ b/ext/w32api/w32api.c
@@ -0,0 +1,898 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP version 4.0 |
+ +----------------------------------------------------------------------+
+ | 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 |
+ | 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. |
+ +----------------------------------------------------------------------+
+ | Authors: James Moore <jmoore@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if HAVE_W32API
+#include <stdio.h>
+#include <stdlib.h>
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "ext/standard/php_string.h"
+#include "php_w32api.h"
+
+/* {{{ w32api_functions[]
+ */
+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)
+ {NULL, NULL, NULL}
+};
+/* }}} */
+
+/* {{{ w32api_module_entry
+ */
+zend_module_entry w32api_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "w32api",
+ w32api_functions,
+ PHP_MINIT(w32api),
+ PHP_MSHUTDOWN(w32api),
+ NULL,
+ NULL,
+ PHP_MINFO(w32api),
+ "0.1", /* Replace with version number for your extension */
+ 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)
+{
+ 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))
+ {
+ FREE_HASHTABLE(W32_G(regfuncs));
+ }
+
+ if(W32_G(libraries))
+ {
+ php_w32api_unload_libraries();
+ FREE_HASHTABLE(W32_G(libraries));
+ }
+
+ if(W32_G(libraries))
+ {
+ FREE_HASHTABLE(W32_G(types));
+ }
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ DYNAPARM dtor */
+static void w32api_free_dynaparm(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ DYNAPARM *dparam;
+
+ dparam = (DYNAPARM *)rsrc->ptr;
+
+ if(dparam->pArg)
+ efree(dparam->pArg);
+
+ efree(dparam);
+}
+/* }}} */
+
+/* {{{ */
+static void php_w32api_unload_libraries()
+{
+ TSRMLS_FETCH();
+ zend_hash_destroy(W32_G(libraries));
+}
+/* }}} */
+
+/* {{{ */
+static void php_w32api_dtor_library(void *data)
+{
+ FreeLibrary((HINSTANCE)data);
+}
+/* }}} */
+
+/* {{{ */
+static void php_w32api_init_globals(zend_w32api_globals *w32api_globals)
+{
+ TSRMLS_FETCH();
+
+ w32api_globals->regfuncs = NULL;
+ w32api_globals->libraries = 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);
+
+ ALLOC_HASHTABLE(W32_G(libraries));
+ zend_hash_init(W32_G(libraries), 1, NULL, php_w32api_dtor_library, 1);
+
+ ALLOC_HASHTABLE(W32_G(types));
+ zend_hash_init(W32_G(types), 5, NULL, NULL, 1);
+
+}
+/* }}} */
+
+/* {{{ */
+static void register_constants(int module_number)
+{
+ TSRMLS_FETCH();
+
+ 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)
+
+}
+/* }}} */
+
+/* {{{ proto void w32api_set_call_method(int method)
+ Sets the calling method used */
+PHP_FUNCTION(w32api_set_call_method)
+{
+ zval **method;
+
+ if(zend_get_parameters_ex(1, &method) == FAILURE)
+ {
+ WRONG_PARAM_COUNT
+ }
+
+ switch((*method)->value.lval)
+ {
+ case DC_CALL_CDECL:
+ W32_G(call_type) = DC_CALL_CDECL;
+ break;
+ default:
+ W32_G(call_type) = DC_CALL_STD;
+ break;
+ }
+
+ RETURN_TRUE
+
+}
+/* }}} */
+
+/* {{{ proto bool w32api_register_function(string libary, string function_name)
+ Registers function function_name from library with PHP */
+PHP_FUNCTION(w32api_register_function)
+{
+ 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)
+ {
+ WRONG_PARAM_COUNT
+ }
+
+ convert_to_string_ex(libname);
+ convert_to_string_ex(funcname);
+ convert_to_string_ex(retval_type);
+
+ fe = (W32APIFE *)emalloc(sizeof(W32APIFE));
+ fe->retvaltype = 0;
+ //TODO: Check library isnt alreay loaded
+
+ hinstLib = LoadLibrary((*libname)->value.str.val);
+
+ if(hinstLib == NULL)
+ {
+ php_error(E_WARNING, "Could not load dynamic link library %s", (*libname)->value.str.val);
+ RETURN_FALSE
+ }
+
+ zend_hash_add(W32_G(libraries),
+ (*libname)->value.str.val,
+ strlen((*libname)->value.str.val),
+ &hinstLib,
+ sizeof(HINSTANCE),
+ NULL);
+
+ //TODO: Check function handle isnt already loaded
+
+ ProcAdd = (FARPROC) GetProcAddress(hinstLib, (*funcname)->value.str.val);
+
+ if(ProcAdd == NULL)
+ {
+ php_error(E_WARNING, "Could not get handle for function %s", (*funcname)->value.str.val);
+ RETURN_FALSE
+ }
+
+ fe->fp = ProcAdd;
+
+ 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"))
+ {
+ fe->rettype = malloc(4*sizeof(char));
+ fe->rettype = strdup("long\0");
+ }
+ else if (!strcmp((*retval_type)->value.str.val, "string"))
+ {
+ fe->rettype = malloc(7*sizeof(char));
+ fe->rettype = strdup("string\0");
+ }
+ else if (!strcmp((*retval_type)->value.str.val, "byte"))
+ {
+ fe->rettype = malloc(5*sizeof(char));
+ fe->rettype = strdup("byte\0");
+ }
+ else if (!strcmp((*retval_type)->value.str.val, "double"))
+ {
+ fe->rettype = malloc(7*sizeof(char));
+ fe->rettype = strdup("double\0");
+ }
+ else if (!strcmp((*retval_type)->value.str.val, "bool"))
+ {
+ fe->rettype = malloc(5*sizeof(char));
+ fe->rettype = strdup("bool\0");
+ }
+ else
+ {
+ /**
+ * 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;
+ }
+
+ 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
+ */
+ {
+ 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
+ }
+
+
+ }
+
+
+
+ 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)
+{
+ 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;
+
+ args = emalloc(argc * sizeof(zval **));
+ Param = (DYNAPARM *)emalloc((argc) * sizeof(DYNAPARM));
+
+ if(zend_get_parameters_array_ex(argc, args) == FAILURE)
+ {
+ WRONG_PARAM_COUNT
+ }
+
+ funcname = get_active_function_name(TSRMLS_C);
+
+ 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;
+ }
+
+ fe = (W32APIFE *)tmp;
+
+ // Build the DYNPARAM array.
+ for(i = 0; i < (argc); i++)
+ {
+ Param[i] = w32api_convert_zval_to_dynparam(args[(i)] TSRMLS_CC);
+ }
+
+
+ /**
+ * 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;
+ }
+
+ retval = php_w32api_dynamic_dll_call(W32_G(call_type), (ulong)(fe->fp), (argc), Param, pVParam, VParamsz);
+
+ if(!strcmp(fe->rettype, "long"))
+ {
+ RETURN_LONG(retval.Long);
+ }
+ else if (!strcmp(fe->rettype, "int"))
+ {
+ RETURN_LONG(retval.Int);
+ }
+ else if (!strcmp(fe->rettype, "string"))
+ {
+ RETURN_STRING(retval.Pointer, 1);
+ }
+ else if (!strcmp(fe->rettype, "byte"))
+ {
+ php_error(E_WARNING, "byte return values are not supported right now");
+ RETURN_FALSE;
+ }
+ else if (!strcmp(fe->rettype, "double"))
+ {
+ RETURN_DOUBLE(retval.Double);
+ }
+ else if (!strcmp(fe->rettype, "bool"))
+ {
+ if(retval.Int)
+ {
+ RETURN_TRUE;
+ }
+ else
+ {
+ RETURN_FALSE;
+ }
+ }
+ 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));
+ }
+
+}
+/* }}} */
+
+/* {{{ 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;
+}
+/* }}} */
+
+/* {{{ 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)
+ {
+ 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;
+ break;
+ case IS_LONG:
+ dparam.nWidth = sizeof(long);
+ dparam.dwArg = (*carg)->value.lval;
+ break;
+ case IS_DOUBLE:
+ dparam.nWidth = sizeof(float);
+ dparam.pArg = &(*carg)->value.dval;
+ dparam.dwFlags = DC_FLAG_ARGPTR;
+ break;
+ case IS_STRING:
+ dparam.nWidth = sizeof(char *);
+ dparam.pArg = (*carg)->value.str.val;
+ break;
+ case IS_BOOL:
+ dparam.nWidth = sizeof(BOOL);
+ dparam.dwArg = ((*carg)->value.lval == 0)?FALSE:TRUE;
+ break;
+ case IS_NULL:
+ dparam.nWidth = sizeof(void *);
+ dparam.pArg = NULL;
+ break;
+ default:
+ php_error(E_ERROR, "Cant convert variable to type dynparam");
+ }
+
+ 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
+ *
+ */
+
+/* {{{ 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)
+{
+ zval ***args;
+ int argc = ZEND_NUM_ARGS();
+ int i;
+ runtime_struct *rst, *orst;
+ void *tmp;
+ field *fields, *ptr;
+
+ args = (zval ***)emalloc(sizeof(zval **) * argc);
+ rst = malloc(sizeof(runtime_struct));
+
+ ptr = (field *)emalloc(sizeof(field) *((argc-1)/2));
+
+ fields = ptr;
+
+ if((zend_get_parameters_array_ex(argc, args) == FAILURE) || ((argc % 2) != 1))
+ {
+ WRONG_PARAM_COUNT
+ }
+
+ for(i=2; i<argc; i++)
+ {
+ convert_to_string_ex(args[i]);
+ }
+
+ convert_to_string_ex(args[0]);
+
+ rst->name = (*args[0])->value.str.val;
+ rst->size = 0;
+
+ /**
+ * We now take each parameter pair and fill out the field struct
+ * for each parameter pair.
+ */
+ 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);
+
+ 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;
+
+ 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 (!strcmp(ptr->type, "byte"))
+ {
+ ptr->fsize = 1;
+ }
+ else if (!strcmp(ptr->type, "double"))
+ {
+ ptr->fsize = sizeof(double);
+ }
+ else if (!strcmp(ptr->type, "bool"))
+ {
+ ptr->fsize = sizeof(BOOL);
+ }
+ else
+ {
+ /**
+ * 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;
+ }
+
+ rst->size += ptr->fsize;
+ ptr++;
+ }
+
+ rst->fields = fields;
+
+ if(zend_hash_add(W32_G(types), rst->name, strlen(rst->name), rst, sizeof(runtime_struct), NULL) == FAILURE)
+ {
+ php_error(E_WARNING, "Error registering type %s", rst->name);
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+
+}
+/* }}} */
+
+/* {{{ 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)
+{
+ DYNAPARM *dparam, *tparam;
+ void *rtstruct, *tmp;
+ runtime_struct *rst;
+ field *ptr;
+ char *m;
+ zval ***args;
+ zval **curarg;
+ int i, j,argc = ZEND_NUM_ARGS();
+
+ args = emalloc(sizeof(zval **) * argc);
+ dparam = emalloc(sizeof(DYNAPARM));
+
+ if(zend_get_parameters_array_ex(argc, args) != SUCCESS)
+ {
+ WRONG_PARAM_COUNT
+ }
+
+ 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)
+ {
+ php_error(E_WARNING, "Unknown type %s",(*args[0])->value.str.val);
+ RETURN_FALSE
+ }
+
+ rst = (runtime_struct *)tmp;
+
+ rtstruct = emalloc(rst->size);
+ rtstruct = memset(rtstruct, 0, rst->size);
+ tmp = rtstruct;
+ curarg = args[1];
+ ptr = rst->fields;
+
+ i = 0;
+ j = (argc-1);
+
+ 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;
+
+ curarg++;
+ ptr++;
+ i++;
+ }
+
+ dparam->dwFlags = 0;
+ dparam->nWidth = rst->size;
+ dparam->pArg = rtstruct;
+
+ ZEND_REGISTER_RESOURCE(return_value, dparam, W32_G(le_dynaparm));
+
+}
+/* }}} */
+
+
+#endif /* HAVE_W32API */ \ No newline at end of file
diff --git a/ext/w32api/w32api.dsp b/ext/w32api/w32api.dsp
new file mode 100644
index 0000000000..8910cfb929
--- /dev/null
+++ b/ext/w32api/w32api.dsp
@@ -0,0 +1,114 @@
+# Microsoft Developer Studio Project File - Name="w32api" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=w32api - Win32 Release_TS
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "w32api.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "w32api.mak" CFG="w32api - Win32 Release_TS"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "w32api - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "w32api - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "w32api - Win32 Release_TS"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release_TS"
+# PROP BASE Intermediate_Dir "Release_TS"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release_TS"
+# PROP Intermediate_Dir "Release_TS"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COMPILE_DL_W32API" /D ZTS=1 /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /ZI /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D ZEND_DEBUG=0 /D HAVE_W32API=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "W32API_EXPORTS" /D "COMPILE_DL_W32API" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x406 /d "NDEBUG"
+# ADD RSC /l 0x406 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /machine:I386 /out:"..\..\Release_TS/php_w32api.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\Release_TS_Inline"
+
+!ELSEIF "$(CFG)" == "w32api - Win32 Debug_TS"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Debug_TS"
+# PROP BASE Intermediate_Dir "Debug_TS"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Debug_TS"
+# PROP Intermediate_Dir "Debug_TS"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COMPILE_DL_W32API" /D ZTS=1 /YX /FD /c
+# ADD CPP /nologo /MTd /W3 /GX /I "..\.." /I "..\..\main" /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D "_DEBUG" /D "_LIB" /D "__WIN32__" /D "USE_TLS" /D "WIN32" /D "_MBCS" /D ZEND_DEBUG=1 /D "NDEBUG" /D "_WINDOWS" /D "_USRDLL" /D "W32API_EXPORTS" /D "COMPILE_DL_W32API" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_W32API=1 /FAcs /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# SUBTRACT MTL /Oicf
+# ADD BASE RSC /l 0x406 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php4ts_debug.lib /nologo /dll /machine:I386 /out:"..\..\Debug_TS/php_w32api.dll" /libpath:"..\..\Debug_TS"
+
+!ENDIF
+
+# Begin Target
+
+# Name "w32api - Win32 Release_TS"
+# Name "w32api - Win32 Debug_TS"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\w32api.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\php_w32api.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project