mirror of
https://github.com/sqlmapproject/sqlmap.git
synced 2024-11-26 11:33:47 +03:00
Merged UDF Linux and Windows development environments
This commit is contained in:
parent
746cbdba96
commit
d4d26b59eb
|
@ -1,278 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<link rel="stylesheet" type="text/css" href="../mysqludf.css"/>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
||||||
<title>lib_mysqludf_sys - A library of MySQL UDFs for working with the environment in which MySQL runs</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div>
|
|
||||||
<a href="../index.html">Top</a>
|
|
||||||
| <a href="../mysql_udf_repository_libraries.html">Up</a>
|
|
||||||
</div>
|
|
||||||
<h1>lib_mysqludf_sys</h1>
|
|
||||||
<div>
|
|
||||||
<a href="lib_mysqludf_sys.html">Documentation</a>
|
|
||||||
| <a href="lib_mysqludf_sys.so">Binary</a>
|
|
||||||
| <a href="lib_mysqludf_sys.sql">Installation</a>
|
|
||||||
| <a href="lib_mysqludf_sys.c">Source</a>
|
|
||||||
| <a href="lib_mysqludf_sys_0.0.2.tar.gz">tar.gz</a>
|
|
||||||
</div>
|
|
||||||
<p>
|
|
||||||
This library <code>lib_mysqludf_sys</code> contains a number of functions that allows one to interact with the operating system.
|
|
||||||
</p>
|
|
||||||
<ol>
|
|
||||||
<li><a href="#sys_eval"><code>sys_eval</code></a> - executes an arbitrary command, and returns it's output.</li>
|
|
||||||
<li><a href="#sys_exec"><code>sys_exec</code></a> - executes an arbitrary command, and returns it's exit code.</li>
|
|
||||||
<li><a href="#sys_get"><code>sys_get</code></a> - gets the value of an environment variable.</li>
|
|
||||||
<li><a href="#sys_set"><code>sys_set</code></a> - create an environment variable, or update the value of an existing environment variable.</li>
|
|
||||||
</ol>
|
|
||||||
<p>
|
|
||||||
Use <a href="#lib_mysqludf_sys_info"><code>lib_mysqludf_sys_info()</code></a> to obtain information about the currently installed version of <code>lib_mysqludf_sys</code>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
<a name="sys_eval"></a><h2>sys_eval</h2>
|
|
||||||
<p>
|
|
||||||
<code>sys_eval</code> takes one command string argument and executes it, returning its output.
|
|
||||||
</p>
|
|
||||||
<h3>Syntax</h3>
|
|
||||||
<pre>sys_eval(<b>arg1</b>)</pre>
|
|
||||||
<h3>Parameters and Return Values</h3>
|
|
||||||
<dl>
|
|
||||||
<dt><code><b>arg1</b></code></dt>
|
|
||||||
<dd>
|
|
||||||
A command string valid for the current operating system or execution environment.
|
|
||||||
</dd>
|
|
||||||
<dt>returns</dt>
|
|
||||||
<dd>
|
|
||||||
Whatever output the command pushed to the standard output stream.
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<h3>Installation</h3>
|
|
||||||
<p>
|
|
||||||
Place the shared library binary in an appropriate location.
|
|
||||||
Log in to mysql as root or as another user with sufficient privileges, and select any database.
|
|
||||||
Then, create the function using the following DDL statement:
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
CREATE FUNCTION sys_eval RETURNS STRING SONAME 'lib_mysqludf_sys.so';
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
The function will be globally available in all databases.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The deinstall the function, run the following statement:
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
DROP FUNCTION sys_eval;
|
|
||||||
</pre>
|
|
||||||
<h3>Examples</h3>
|
|
||||||
<p>
|
|
||||||
None yet
|
|
||||||
</p>
|
|
||||||
<h3>A Note of Caution</h3>
|
|
||||||
<p>
|
|
||||||
Be very careful in deciding whether you need this function.
|
|
||||||
UDFs are available to all database users - you cannot grant EXECUTE privileges for them.
|
|
||||||
As the commandstring passed to <code>sys_exec</code> can do pretty much everything,
|
|
||||||
exposing the function poses a very real security hazard.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Even for a benign user, it is possible to accidentally do a lot of damage with it.
|
|
||||||
The call will be executed with the privileges of the os user that runs MySQL,
|
|
||||||
so it is entirely feasible to delete MySQL's data directory, or worse.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The function is intended for specialized MySQL applications where one needs extended
|
|
||||||
control over the operating system.
|
|
||||||
Currently, we do not have UDF's for ftp, email and http,
|
|
||||||
and this function can be used to implement such functionality in case it is really necessary
|
|
||||||
(datawarehouse staging areas could be a case in example).
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
You have been warned! If you don't see the hazard, please don't try to find it; just trust me on this.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
If you do decide to use this library in a production environment, make sure that only specific commands can be run and file access is limited by using <a href="http://www.novell.com/documentation/apparmor/index.html">AppArmor</a>.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<a name="sys_exec"></a><h2>sys_exec</h2>
|
|
||||||
<p>
|
|
||||||
<code>sys_exec</code> takes one command string argument and executes it.
|
|
||||||
</p>
|
|
||||||
<h3>Syntax</h3>
|
|
||||||
<pre>sys_exec(<b>arg1</b>)</pre>
|
|
||||||
<h3>Parameters and Return Values</h3>
|
|
||||||
<dl>
|
|
||||||
<dt><code><b>arg1</b></code></dt>
|
|
||||||
<dd>
|
|
||||||
A command string valid for the current operating system or execution environment.
|
|
||||||
</dd>
|
|
||||||
<dt>returns</dt>
|
|
||||||
<dd>
|
|
||||||
An (integer) exit code returned by the executed process.
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<h3>Installation</h3>
|
|
||||||
<p>
|
|
||||||
Place the shared library binary in an appropriate location.
|
|
||||||
Log in to mysql as root or as another user with sufficient privileges, and select any database.
|
|
||||||
Then, create the function using the following DDL statement:
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
CREATE FUNCTION sys_exec RETURNS INT SONAME 'lib_mysqludf_sys.so';
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
The function will be globally available in all databases.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The deinstall the function, run the following statement:
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
DROP FUNCTION sys_exec;
|
|
||||||
</pre>
|
|
||||||
<h3>Examples</h3>
|
|
||||||
<p>
|
|
||||||
None yet
|
|
||||||
</p>
|
|
||||||
<h3>A Note of Caution</h3>
|
|
||||||
<p>
|
|
||||||
Be very careful in deciding whether you need this function.
|
|
||||||
UDFs are available to all database users - you cannot grant EXECUTE privileges for them.
|
|
||||||
As the commandstring passed to <code>sys_exec</code> can do pretty much everything,
|
|
||||||
exposing the function poses a very real security hazard.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Even for a benign user, it is possible to accidentally do a lot of damage with it.
|
|
||||||
The call will be executed with the privileges of the os user that runs MySQL,
|
|
||||||
so it is entirely feasible to delete MySQL's data directory, or worse.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The function is intended for specialized MySQL applications where one needs extended
|
|
||||||
control over the operating system.
|
|
||||||
Currently, we do not have UDF's for ftp, email and http,
|
|
||||||
and this function can be used to implement such functionality in case it is really necessary
|
|
||||||
(datawarehouse staging areas could be a case in example).
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
You have been warned! If you don't see the hazard, please don't try to find it; just trust me on this.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
If you do decide to use this library in a production environment, make sure that only specific commands can be run and file access is limited by using <a href="http://www.novell.com/documentation/apparmor/index.html">AppArmor</a>.
|
|
||||||
</p>
|
|
||||||
<a name="sys_get"></a><h2>sys_get</h2>
|
|
||||||
<p>
|
|
||||||
<code>sys_get</code> takes the name of an environment variable and returns the value of the variable.
|
|
||||||
</p>
|
|
||||||
<h3>Syntax</h3>
|
|
||||||
<pre>sys_get([<b>arg1</b>)</pre>
|
|
||||||
<h3>Parameters and Return Values</h3>
|
|
||||||
<dl>
|
|
||||||
<dt><code><b>arg1</b></code></dt>
|
|
||||||
<dd>
|
|
||||||
A string that denotes the name of an environment value.
|
|
||||||
</dd>
|
|
||||||
<dt>returns</dt>
|
|
||||||
<dd>
|
|
||||||
If the variable exists, a string containing the value of the environment variable.
|
|
||||||
If the variable does not exist, the function return NULL.
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<h3>Installation</h3>
|
|
||||||
<p>
|
|
||||||
Place the shared library binary in an appropriate location.
|
|
||||||
Log in to mysql as root or as another user with sufficient privileges, and select any database.
|
|
||||||
Then, create the function using the following DDL statement:
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
CREATE FUNCTION sys_get RETURNS STRING SONAME 'lib_mysqludf_sys.so';
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
The function will be globally available in all databases.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The deinstall the function, run the following statement:
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
DROP FUNCTION sys_get;
|
|
||||||
</pre>
|
|
||||||
<h3>Examples</h3>
|
|
||||||
<p>
|
|
||||||
None yet
|
|
||||||
</p>
|
|
||||||
<h3>A Note of Caution</h3>
|
|
||||||
<p>
|
|
||||||
Be very careful in deciding whether you need this function.
|
|
||||||
UDFs are available to all database users - you cannot grant EXECUTE privileges for them.
|
|
||||||
The variables known in the environment where mysql runs are freely accessible using this function.
|
|
||||||
Any user can get access to potentially secret information, such as
|
|
||||||
the user that is running mysqld, the path of the user's home directory etc.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The function is intended for specialized MySQL applications where one needs extended
|
|
||||||
control over the operating system.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
You have been warned! If you don't see the hazard, please don't try to find it; just trust me on this.
|
|
||||||
</p>
|
|
||||||
<a name="sys_set"></a><h2>sys_set</h2>
|
|
||||||
<p>
|
|
||||||
<code>sys_get</code> takes the name of an environment variable and returns the value of the variable.
|
|
||||||
</p>
|
|
||||||
<h3>Syntax</h3>
|
|
||||||
<pre>sys_set([<b>arg1, arg2</b>)</pre>
|
|
||||||
<h3>Parameters and Return Values</h3>
|
|
||||||
<dl>
|
|
||||||
<dt><code><b>arg1</b></code></dt>
|
|
||||||
<dd>
|
|
||||||
A string that denotes the name of an environment value.
|
|
||||||
</dd>
|
|
||||||
<dt><code><b>arg2</b></code></dt>
|
|
||||||
<dd>
|
|
||||||
An expression that contains the value that is to be assigned to the environment variable.
|
|
||||||
</dd>
|
|
||||||
<dt>returns</dt>
|
|
||||||
<dd>
|
|
||||||
0 if the assignment or creation succeed.
|
|
||||||
non-zero otherwise.
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<h3>Installation</h3>
|
|
||||||
<p>
|
|
||||||
Place the shared library binary in an appropriate location.
|
|
||||||
Log in to mysql as root or as another user with sufficient privileges, and select any database.
|
|
||||||
Then, create the function using the following DDL statement:
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
CREATE FUNCTION sys_set RETURNS STRING SONAME 'lib_mysqludf_sys.so';
|
|
||||||
</pre>
|
|
||||||
<p>
|
|
||||||
The function will be globally available in all databases.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The deinstall the function, run the following statement:
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
DROP FUNCTION sys_set;
|
|
||||||
</pre>
|
|
||||||
<h3>Examples</h3>
|
|
||||||
<p>
|
|
||||||
None yet
|
|
||||||
</p>
|
|
||||||
<h3>A Note of Caution</h3>
|
|
||||||
<p>
|
|
||||||
Be very careful in deciding whether you need this function.
|
|
||||||
UDFs are available to all database users - you cannot grant EXECUTE privileges for them.
|
|
||||||
This function will overwrite existing environment variables.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The function is intended for specialized MySQL applications where one needs extended
|
|
||||||
control over the operating system.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
You have been warned! If you don't see the hazard, please don't try to find it; just trust me on this.
|
|
||||||
</p>
|
|
||||||
</body>
|
|
||||||
</html
|
|
19
extra/udfhack/windows/README.txt
Normal file
19
extra/udfhack/windows/README.txt
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
1. Before compiling, certain enviroment variables have to be set, depending on the project used. for project lib_mysqludf_sys variables PLATFORM_SDK_DIR and MYSQL_SERVER_DIR have to be set, while for lib_postgresqludf_sys PLATFORM_SDK_DIR and POSTGRESQL_SERVER_DIR.
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
Variable name Variable description
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
PLATFORM_SDK_DIR directory where the Platform SDK is installed
|
||||||
|
MYSQL_SERVER_DIR directory where the MySQL is installed
|
||||||
|
POSTGRESQL_SERVER_DIR directory where the PostgreSQL is installed
|
||||||
|
|
||||||
|
2. Procedure for setting environment variables:
|
||||||
|
My Computer -> Properties -> Advanced -> Environment Variables
|
||||||
|
User variables -> New
|
||||||
|
|
||||||
|
3. Sample values:
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
Variable name Variable value
|
||||||
|
--------------------------------------------------------------------------
|
||||||
|
PLATFORM_SDK_DIR C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2
|
||||||
|
MYSQL_SERVER_DIR C:\Program Files\MySQL\MySQL Server 5.1
|
||||||
|
POSTGRESQL_SERVER_DIR C:\Program Files\PostgreSQL\8.3
|
BIN
extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys.sln
Executable file
BIN
extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys.sln
Executable file
Binary file not shown.
551
extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.c
Executable file
551
extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.c
Executable file
|
@ -0,0 +1,551 @@
|
||||||
|
/*
|
||||||
|
lib_mysqludf_sys - a library with miscellaneous (operating) system level functions
|
||||||
|
Copyright (C) 2007 Roland Bouman
|
||||||
|
Copyright (C) 2008-2009 Roland Bouman and Bernardo Damele A. G.
|
||||||
|
web: http://www.mysqludf.org/
|
||||||
|
email: mysqludfs@gmail.com, bernardo.damele@gmail.com
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
#define DLLEXP __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define DLLEXP
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef STANDARD
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#ifdef __WIN__
|
||||||
|
typedef unsigned __int64 ulonglong;
|
||||||
|
typedef __int64 longlong;
|
||||||
|
#else
|
||||||
|
typedef unsigned long long ulonglong;
|
||||||
|
typedef long long longlong;
|
||||||
|
#endif /*__WIN__*/
|
||||||
|
#else
|
||||||
|
#include <my_global.h>
|
||||||
|
#include <my_sys.h>
|
||||||
|
#endif
|
||||||
|
#include <mysql.h>
|
||||||
|
#include <m_ctype.h>
|
||||||
|
#include <m_string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_DLOPEN
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LIBVERSION "lib_mysqludf_sys version 0.0.3"
|
||||||
|
|
||||||
|
#ifdef __WIN__
|
||||||
|
#define SETENV(name,value) SetEnvironmentVariable(name,value);
|
||||||
|
#else
|
||||||
|
#define SETENV(name,value) setenv(name,value,1);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DLLEXP
|
||||||
|
my_bool lib_mysqludf_sys_info_init(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char *message
|
||||||
|
);
|
||||||
|
|
||||||
|
DLLEXP
|
||||||
|
void lib_mysqludf_sys_info_deinit(
|
||||||
|
UDF_INIT *initid
|
||||||
|
);
|
||||||
|
|
||||||
|
DLLEXP
|
||||||
|
char* lib_mysqludf_sys_info(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char* result
|
||||||
|
, unsigned long* length
|
||||||
|
, char *is_null
|
||||||
|
, char *error
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sys_get
|
||||||
|
*
|
||||||
|
* Gets the value of the specified environment variable.
|
||||||
|
*/
|
||||||
|
DLLEXP
|
||||||
|
my_bool sys_get_init(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char *message
|
||||||
|
);
|
||||||
|
|
||||||
|
DLLEXP
|
||||||
|
void sys_get_deinit(
|
||||||
|
UDF_INIT *initid
|
||||||
|
);
|
||||||
|
|
||||||
|
DLLEXP
|
||||||
|
char* sys_get(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char* result
|
||||||
|
, unsigned long* length
|
||||||
|
, char *is_null
|
||||||
|
, char *error
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sys_set
|
||||||
|
*
|
||||||
|
* Sets the value of the environment variables.
|
||||||
|
* This function accepts a set of name/value pairs
|
||||||
|
* which are then set as environment variables.
|
||||||
|
* Use sys_get to retrieve the value of such a variable
|
||||||
|
*/
|
||||||
|
DLLEXP
|
||||||
|
my_bool sys_set_init(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char *message
|
||||||
|
);
|
||||||
|
|
||||||
|
DLLEXP
|
||||||
|
void sys_set_deinit(
|
||||||
|
UDF_INIT *initid
|
||||||
|
);
|
||||||
|
|
||||||
|
DLLEXP
|
||||||
|
long long sys_set(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char *is_null
|
||||||
|
, char *error
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sys_exec
|
||||||
|
*
|
||||||
|
* executes the argument commandstring and returns its exit status.
|
||||||
|
* Beware that this can be a security hazard.
|
||||||
|
*/
|
||||||
|
DLLEXP
|
||||||
|
my_bool sys_exec_init(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char *message
|
||||||
|
);
|
||||||
|
|
||||||
|
DLLEXP
|
||||||
|
void sys_exec_deinit(
|
||||||
|
UDF_INIT *initid
|
||||||
|
);
|
||||||
|
|
||||||
|
DLLEXP
|
||||||
|
my_ulonglong sys_exec(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char *is_null
|
||||||
|
, char *error
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sys_eval
|
||||||
|
*
|
||||||
|
* executes the argument commandstring and returns its standard output.
|
||||||
|
* Beware that this can be a security hazard.
|
||||||
|
*/
|
||||||
|
DLLEXP
|
||||||
|
my_bool sys_eval_init(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char *message
|
||||||
|
);
|
||||||
|
|
||||||
|
DLLEXP
|
||||||
|
void sys_eval_deinit(
|
||||||
|
UDF_INIT *initid
|
||||||
|
);
|
||||||
|
|
||||||
|
DLLEXP
|
||||||
|
char* sys_eval(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char* result
|
||||||
|
, unsigned long* length
|
||||||
|
, char *is_null
|
||||||
|
, char *error
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sys_bineval
|
||||||
|
*
|
||||||
|
* executes bynary opcodes.
|
||||||
|
* Beware that this can be a security hazard.
|
||||||
|
*/
|
||||||
|
DLLEXP
|
||||||
|
my_bool sys_bineval_init(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
);
|
||||||
|
|
||||||
|
DLLEXP
|
||||||
|
void sys_bineval_deinit(
|
||||||
|
UDF_INIT *initid
|
||||||
|
);
|
||||||
|
|
||||||
|
DLLEXP
|
||||||
|
int sys_bineval(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
);
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
DWORD WINAPI exec_payload(LPVOID lpParameter);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* lib_mysqludf_sys_info
|
||||||
|
*/
|
||||||
|
my_bool lib_mysqludf_sys_info_init(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char *message
|
||||||
|
){
|
||||||
|
my_bool status;
|
||||||
|
if(args->arg_count!=0){
|
||||||
|
strcpy(
|
||||||
|
message
|
||||||
|
, "No arguments allowed (udf: lib_mysqludf_sys_info)"
|
||||||
|
);
|
||||||
|
status = 1;
|
||||||
|
} else {
|
||||||
|
status = 0;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lib_mysqludf_sys_info_deinit(
|
||||||
|
UDF_INIT *initid
|
||||||
|
){
|
||||||
|
}
|
||||||
|
|
||||||
|
char* lib_mysqludf_sys_info(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char* result
|
||||||
|
, unsigned long* length
|
||||||
|
, char *is_null
|
||||||
|
, char *error
|
||||||
|
){
|
||||||
|
strcpy(result,LIBVERSION);
|
||||||
|
*length = strlen(LIBVERSION);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bool sys_get_init(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char *message
|
||||||
|
){
|
||||||
|
if(args->arg_count==1
|
||||||
|
&& args->arg_type[0]==STRING_RESULT){
|
||||||
|
initid->maybe_null = 1;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
strcpy(
|
||||||
|
message
|
||||||
|
, "Expected exactly one string type parameter"
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_get_deinit(
|
||||||
|
UDF_INIT *initid
|
||||||
|
){
|
||||||
|
}
|
||||||
|
|
||||||
|
char* sys_get(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char* result
|
||||||
|
, unsigned long* length
|
||||||
|
, char *is_null
|
||||||
|
, char *error
|
||||||
|
){
|
||||||
|
char* value = getenv(args->args[0]);
|
||||||
|
if(value == NULL){
|
||||||
|
*is_null = 1;
|
||||||
|
} else {
|
||||||
|
*length = strlen(value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bool sys_set_init(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char *message
|
||||||
|
){
|
||||||
|
if(args->arg_count!=2){
|
||||||
|
strcpy(
|
||||||
|
message
|
||||||
|
, "Expected exactly two arguments"
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(args->arg_type[0]!=STRING_RESULT){
|
||||||
|
strcpy(
|
||||||
|
message
|
||||||
|
, "Expected string type for name parameter"
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
args->arg_type[1]=STRING_RESULT;
|
||||||
|
if((initid->ptr=malloc(
|
||||||
|
args->lengths[0]
|
||||||
|
+ 1
|
||||||
|
+ args->lengths[1]
|
||||||
|
+ 1
|
||||||
|
))==NULL){
|
||||||
|
strcpy(
|
||||||
|
message
|
||||||
|
, "Could not allocate memory"
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_set_deinit(
|
||||||
|
UDF_INIT *initid
|
||||||
|
){
|
||||||
|
if (initid->ptr!=NULL){
|
||||||
|
free(initid->ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long long sys_set(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char *is_null
|
||||||
|
, char *error
|
||||||
|
){
|
||||||
|
char *name = initid->ptr;
|
||||||
|
char *value = name + args->lengths[0] + 1;
|
||||||
|
memcpy(
|
||||||
|
name
|
||||||
|
, args->args[0]
|
||||||
|
, args->lengths[0]
|
||||||
|
);
|
||||||
|
*(name + args->lengths[0]) = '\0';
|
||||||
|
memcpy(
|
||||||
|
value
|
||||||
|
, args->args[1]
|
||||||
|
, args->lengths[1]
|
||||||
|
);
|
||||||
|
*(value + args->lengths[1]) = '\0';
|
||||||
|
return SETENV(name,value);
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bool sys_exec_init(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char *message
|
||||||
|
){
|
||||||
|
unsigned int i=0;
|
||||||
|
if(args->arg_count == 1
|
||||||
|
&& args->arg_type[i]==STRING_RESULT){
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
strcpy(
|
||||||
|
message
|
||||||
|
, "Expected exactly one string type parameter"
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_exec_deinit(
|
||||||
|
UDF_INIT *initid
|
||||||
|
){
|
||||||
|
}
|
||||||
|
|
||||||
|
my_ulonglong sys_exec(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char *is_null
|
||||||
|
, char *error
|
||||||
|
){
|
||||||
|
return system(args->args[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bool sys_eval_init(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char *message
|
||||||
|
){
|
||||||
|
unsigned int i=0;
|
||||||
|
if(args->arg_count == 1
|
||||||
|
&& args->arg_type[i]==STRING_RESULT){
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
strcpy(
|
||||||
|
message
|
||||||
|
, "Expected exactly one string type parameter"
|
||||||
|
);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_eval_deinit(
|
||||||
|
UDF_INIT *initid
|
||||||
|
){
|
||||||
|
}
|
||||||
|
|
||||||
|
char* sys_eval(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
, char* result
|
||||||
|
, unsigned long* length
|
||||||
|
, char *is_null
|
||||||
|
, char *error
|
||||||
|
){
|
||||||
|
FILE *pipe;
|
||||||
|
char line[1024];
|
||||||
|
unsigned long outlen, linelen;
|
||||||
|
|
||||||
|
result = malloc(1);
|
||||||
|
outlen = 0;
|
||||||
|
|
||||||
|
pipe = popen(args->args[0], "r");
|
||||||
|
|
||||||
|
while (fgets(line, sizeof(line), pipe) != NULL) {
|
||||||
|
linelen = strlen(line);
|
||||||
|
result = realloc(result, outlen + linelen);
|
||||||
|
strncpy(result + outlen, line, linelen);
|
||||||
|
outlen = outlen + linelen;
|
||||||
|
}
|
||||||
|
|
||||||
|
pclose(pipe);
|
||||||
|
|
||||||
|
if (!(*result) || result == NULL) {
|
||||||
|
*is_null = 1;
|
||||||
|
} else {
|
||||||
|
result[outlen-1] = 0x00;
|
||||||
|
*length = strlen(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bool sys_bineval_init(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_bineval_deinit(
|
||||||
|
UDF_INIT *initid
|
||||||
|
){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int sys_bineval(
|
||||||
|
UDF_INIT *initid
|
||||||
|
, UDF_ARGS *args
|
||||||
|
){
|
||||||
|
int32 argv0_size;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
int pID;
|
||||||
|
char *code;
|
||||||
|
#else
|
||||||
|
int *addr;
|
||||||
|
size_t page_size;
|
||||||
|
pid_t pID;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
argv0_size = strlen(args->args[0]);
|
||||||
|
len = (size_t)argv0_size;
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
// allocate a +rwx memory page
|
||||||
|
code = (char *) VirtualAlloc(NULL, len+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||||
|
strncpy(code, args->args[0], len);
|
||||||
|
|
||||||
|
WaitForSingleObject(CreateThread(NULL, 0, exec_payload, code, 0, &pID), INFINITE);
|
||||||
|
#else
|
||||||
|
pID = fork();
|
||||||
|
if(pID<0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if(pID==0)
|
||||||
|
{
|
||||||
|
page_size = (size_t)sysconf(_SC_PAGESIZE)-1; // get page size
|
||||||
|
page_size = (len+page_size) & ~(page_size); // align to page boundary
|
||||||
|
|
||||||
|
// mmap an rwx memory page
|
||||||
|
addr = mmap(0, page_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, 0, 0);
|
||||||
|
|
||||||
|
if (addr == MAP_FAILED)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
strncpy((char *)addr, args->args[0], len);
|
||||||
|
|
||||||
|
((void (*)(void))addr)();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pID>0)
|
||||||
|
waitpid(pID, 0, WNOHANG);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
DWORD WINAPI exec_payload(LPVOID lpParameter)
|
||||||
|
{
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
mov eax, [lpParameter]
|
||||||
|
call eax
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HAVE_DLOPEN */
|
BIN
extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.vcproj
Executable file
BIN
extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.vcproj
Executable file
Binary file not shown.
BIN
extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys.sln
Executable file
BIN
extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys.sln
Executable file
Binary file not shown.
|
@ -0,0 +1,207 @@
|
||||||
|
/*
|
||||||
|
lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions
|
||||||
|
Copyright (C) 2009 Bernardo Damele A. G.
|
||||||
|
web: http://bernardodamele.blogspot.com/
|
||||||
|
email: bernardo.damele@gmail.com
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
#define _USE_32BIT_TIME_T
|
||||||
|
#define DLLEXP __declspec(dllexport)
|
||||||
|
#define BUILDING_DLL 1
|
||||||
|
#else
|
||||||
|
#define DLLEXP
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <postgres.h>
|
||||||
|
#include <fmgr.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
DWORD WINAPI exec_payload(LPVOID lpParameter);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PG_MODULE_MAGIC
|
||||||
|
PG_MODULE_MAGIC;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PG_FUNCTION_INFO_V1(sys_exec);
|
||||||
|
#ifdef PGDLLIMPORT
|
||||||
|
extern PGDLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) {
|
||||||
|
#else
|
||||||
|
extern DLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) {
|
||||||
|
#endif
|
||||||
|
text *argv0 = PG_GETARG_TEXT_P(0);
|
||||||
|
int32 argv0_size;
|
||||||
|
int32 result = 0;
|
||||||
|
char *command;
|
||||||
|
|
||||||
|
argv0_size = VARSIZE(argv0) - VARHDRSZ;
|
||||||
|
command = (char *)malloc(argv0_size + 1);
|
||||||
|
|
||||||
|
memcpy(command, VARDATA(argv0), argv0_size);
|
||||||
|
command[argv0_size] = '\0';
|
||||||
|
|
||||||
|
/*
|
||||||
|
Only if you want to log
|
||||||
|
elog(NOTICE, "Command execution: %s", command);
|
||||||
|
*/
|
||||||
|
|
||||||
|
result = system(command);
|
||||||
|
free(command);
|
||||||
|
|
||||||
|
PG_FREE_IF_COPY(argv0, 0);
|
||||||
|
PG_RETURN_INT32(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
PG_FUNCTION_INFO_V1(sys_eval);
|
||||||
|
#ifdef PGDLLIMPORT
|
||||||
|
extern PGDLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) {
|
||||||
|
#else
|
||||||
|
extern DLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) {
|
||||||
|
#endif
|
||||||
|
text *argv0 = PG_GETARG_TEXT_P(0);
|
||||||
|
text *result_text;
|
||||||
|
int32 argv0_size;
|
||||||
|
char *command;
|
||||||
|
char *result;
|
||||||
|
FILE *pipe;
|
||||||
|
char line[1024];
|
||||||
|
int32 outlen, linelen;
|
||||||
|
|
||||||
|
argv0_size = VARSIZE(argv0) - VARHDRSZ;
|
||||||
|
command = (char *)malloc(argv0_size + 1);
|
||||||
|
|
||||||
|
memcpy(command, VARDATA(argv0), argv0_size);
|
||||||
|
command[argv0_size] = '\0';
|
||||||
|
|
||||||
|
/*
|
||||||
|
Only if you want to log
|
||||||
|
elog(NOTICE, "Command evaluated: %s", command);
|
||||||
|
*/
|
||||||
|
|
||||||
|
result = (char *)malloc(1);
|
||||||
|
outlen = 0;
|
||||||
|
|
||||||
|
pipe = popen(command, "r");
|
||||||
|
|
||||||
|
while (fgets(line, sizeof(line), pipe) != NULL) {
|
||||||
|
linelen = strlen(line);
|
||||||
|
result = (char *)realloc(result, outlen + linelen);
|
||||||
|
strncpy(result + outlen, line, linelen);
|
||||||
|
outlen = outlen + linelen;
|
||||||
|
}
|
||||||
|
|
||||||
|
pclose(pipe);
|
||||||
|
|
||||||
|
if (*result) {
|
||||||
|
result[outlen-1] = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
result_text = (text *)malloc(VARHDRSZ + strlen(result));
|
||||||
|
#ifdef SET_VARSIZE
|
||||||
|
SET_VARSIZE(result_text, VARHDRSZ + strlen(result));
|
||||||
|
#else
|
||||||
|
VARATT_SIZEP(result_text) = strlen(result) + VARHDRSZ;
|
||||||
|
#endif
|
||||||
|
memcpy(VARDATA(result_text), result, strlen(result));
|
||||||
|
|
||||||
|
PG_RETURN_POINTER(result_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
PG_FUNCTION_INFO_V1(sys_bineval);
|
||||||
|
#ifdef PGDLLIMPORT
|
||||||
|
extern PGDLLIMPORT Datum sys_bineval(PG_FUNCTION_ARGS) {
|
||||||
|
#else
|
||||||
|
extern DLLIMPORT Datum sys_bineval(PG_FUNCTION_ARGS) {
|
||||||
|
#endif
|
||||||
|
text *argv0 = PG_GETARG_TEXT_P(0);
|
||||||
|
int32 argv0_size;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
int pID;
|
||||||
|
char *code;
|
||||||
|
#else
|
||||||
|
int *addr;
|
||||||
|
size_t page_size;
|
||||||
|
pid_t pID;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
argv0_size = VARSIZE(argv0) - VARHDRSZ;
|
||||||
|
len = (size_t)argv0_size;
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
// allocate a +rwx memory page
|
||||||
|
code = (char *) VirtualAlloc(NULL, len+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||||
|
strncpy(code, VARDATA(argv0), len);
|
||||||
|
|
||||||
|
WaitForSingleObject(CreateThread(NULL, 0, exec_payload, code, 0, &pID), INFINITE);
|
||||||
|
#else
|
||||||
|
pID = fork();
|
||||||
|
if(pID<0)
|
||||||
|
PG_RETURN_INT32(1);
|
||||||
|
|
||||||
|
if(pID==0)
|
||||||
|
{
|
||||||
|
page_size = (size_t)sysconf(_SC_PAGESIZE)-1; // get page size
|
||||||
|
page_size = (len+page_size) & ~(page_size); // align to page boundary
|
||||||
|
|
||||||
|
// mmap an rwx memory page
|
||||||
|
addr = mmap(0, page_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, 0, 0);
|
||||||
|
|
||||||
|
if (addr == MAP_FAILED)
|
||||||
|
PG_RETURN_INT32(1);
|
||||||
|
|
||||||
|
strncpy((char *)addr, VARDATA(argv0), len);
|
||||||
|
|
||||||
|
((void (*)(void))addr)();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pID>0)
|
||||||
|
waitpid(pID, 0, WNOHANG);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PG_RETURN_INT32(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
|
||||||
|
DWORD WINAPI exec_payload(LPVOID lpParameter)
|
||||||
|
{
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
mov eax, [lpParameter]
|
||||||
|
call eax
|
||||||
|
}
|
||||||
|
}
|
||||||
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user