14 changed files with 1484 additions and 0 deletions
-
2ext/w32api/CREDITS
-
0ext/w32api/EXPERIMENTAL
-
49ext/w32api/README
-
5ext/w32api/TODO
-
64ext/w32api/examples/uptime.php
-
137ext/w32api/php_w32api.h
-
31ext/w32api/test_dll/dll_test.h
-
10ext/w32api/test_dll/test.php
-
33ext/w32api/test_dll/test_dll.c
-
2ext/w32api/test_dll/test_dll.def
-
110ext/w32api/test_dll/test_dll.dsp
-
29ext/w32api/test_dll/test_dll.dsw
-
898ext/w32api/w32api.c
-
114ext/w32api/w32api.dsp
@ -0,0 +1,2 @@ |
|||||
|
W32API |
||||
|
James Moore <jmoore@php.net> |
||||
@ -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> |
||||
@ -0,0 +1,5 @@ |
|||||
|
TODO |
||||
|
==== |
||||
|
- ByVal and ByRef Passing. |
||||
|
- Better type checking. |
||||
|
- Fix Mem leaks. |
||||
@ -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); |
||||
|
?>
|
||||
@ -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 */ |
||||
@ -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 |
||||
@ -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); |
||||
|
|
||||
|
?>
|
||||
@ -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); |
||||
|
} |
||||
@ -0,0 +1,2 @@ |
|||||
|
EXPORTS |
||||
|
print_name |
||||
@ -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 |
||||
@ -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> |
||||
|
{{{ |
||||
|
}}} |
||||
|
|
||||
|
############################################################################### |
||||
|
|
||||
@ -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 */ |
||||
@ -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 |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue