mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
@ - Add generic Win 32 API extension (jmoore)
This commit is contained in:
parent
f111b84e05
commit
70941fe41b
14 changed files with 1484 additions and 0 deletions
2
ext/w32api/CREDITS
Normal file
2
ext/w32api/CREDITS
Normal file
|
@ -0,0 +1,2 @@
|
|||
W32API
|
||||
James Moore <jmoore@php.net>
|
0
ext/w32api/EXPERIMENTAL
Normal file
0
ext/w32api/EXPERIMENTAL
Normal file
49
ext/w32api/README
Normal file
49
ext/w32api/README
Normal file
|
@ -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>
|
5
ext/w32api/TODO
Normal file
5
ext/w32api/TODO
Normal file
|
@ -0,0 +1,5 @@
|
|||
TODO
|
||||
====
|
||||
- ByVal and ByRef Passing.
|
||||
- Better type checking.
|
||||
- Fix Mem leaks.
|
64
ext/w32api/examples/uptime.php
Normal file
64
ext/w32api/examples/uptime.php
Normal file
|
@ -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);
|
||||
?>
|
137
ext/w32api/php_w32api.h
Normal file
137
ext/w32api/php_w32api.h
Normal file
|
@ -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 */
|
31
ext/w32api/test_dll/dll_test.h
Normal file
31
ext/w32api/test_dll/dll_test.h
Normal file
|
@ -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
|
10
ext/w32api/test_dll/test.php
Normal file
10
ext/w32api/test_dll/test.php
Normal file
|
@ -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);
|
||||
|
||||
?>
|
33
ext/w32api/test_dll/test_dll.c
Normal file
33
ext/w32api/test_dll/test_dll.c
Normal file
|
@ -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);
|
||||
}
|
2
ext/w32api/test_dll/test_dll.def
Normal file
2
ext/w32api/test_dll/test_dll.def
Normal file
|
@ -0,0 +1,2 @@
|
|||
EXPORTS
|
||||
print_name
|
110
ext/w32api/test_dll/test_dll.dsp
Normal file
110
ext/w32api/test_dll/test_dll.dsp
Normal file
|
@ -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
|
29
ext/w32api/test_dll/test_dll.dsw
Normal file
29
ext/w32api/test_dll/test_dll.dsw
Normal file
|
@ -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>
|
||||
{{{
|
||||
}}}
|
||||
|
||||
###############################################################################
|
||||
|
898
ext/w32api/w32api.c
Normal file
898
ext/w32api/w32api.c
Normal file
|
@ -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 */
|
114
ext/w32api/w32api.dsp
Normal file
114
ext/w32api/w32api.dsp
Normal file
|
@ -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
|
Loading…
Add table
Add a link
Reference in a new issue