@ - Add generic Win 32 API extension (jmoore)

This commit is contained in:
James Moore 2001-11-07 14:31:03 +00:00
parent f111b84e05
commit 70941fe41b
14 changed files with 1484 additions and 0 deletions

2
ext/w32api/CREDITS Normal file
View file

@ -0,0 +1,2 @@
W32API
James Moore <jmoore@php.net>

0
ext/w32api/EXPERIMENTAL Normal file
View file

49
ext/w32api/README Normal file
View 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
View file

@ -0,0 +1,5 @@
TODO
====
- ByVal and ByRef Passing.
- Better type checking.
- Fix Mem leaks.

View 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
View 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 */

View 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

View 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);
?>

View 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);
}

View file

@ -0,0 +1,2 @@
EXPORTS
print_name

View 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

View 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
View 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
View 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