forked from enlightenment/efl
evil: add fork, adjust elua to use that
This commit is contained in:
parent
9c42595225
commit
02ef160621
|
@ -12,7 +12,11 @@ bin_elua_elua_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
|
||||||
-DELUA_MODULES_DIR="\"$(datadir)/elua/modules\"" @ELUA_CFLAGS@ \
|
-DELUA_MODULES_DIR="\"$(datadir)/elua/modules\"" @ELUA_CFLAGS@ \
|
||||||
-DLOCALE_DIR=\"@LOCALE_DIR@\" \
|
-DLOCALE_DIR=\"@LOCALE_DIR@\" \
|
||||||
-DPACKAGE_BUILD_DIR=\"`pwd`/$(top_builddir)\"
|
-DPACKAGE_BUILD_DIR=\"`pwd`/$(top_builddir)\"
|
||||||
|
if HAVE_WIN32
|
||||||
|
bin_elua_elua_LDADD = -L$(top_builddir)/src/lib/evil @ELUA_LIBS@
|
||||||
|
else
|
||||||
bin_elua_elua_LDADD = @ELUA_LIBS@
|
bin_elua_elua_LDADD = @ELUA_LIBS@
|
||||||
|
endif
|
||||||
bin_elua_elua_DEPENDENCIES = @ELUA_INTERNAL_LIBS@
|
bin_elua_elua_DEPENDENCIES = @ELUA_INTERNAL_LIBS@
|
||||||
|
|
||||||
eluamodulesdir = $(datadir)/elua/modules
|
eluamodulesdir = $(datadir)/elua/modules
|
||||||
|
|
|
@ -1,161 +0,0 @@
|
||||||
/* an implementation of fork for Windows */
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <setjmp.h>
|
|
||||||
|
|
||||||
typedef struct _OBJECT_ATTRIBUTES {
|
|
||||||
ULONG Length;
|
|
||||||
HANDLE RootDirectory;
|
|
||||||
PVOID ObjectName;
|
|
||||||
ULONG Attributes;
|
|
||||||
PVOID SecurityDescriptor;
|
|
||||||
PVOID SecurityQualityOfService;
|
|
||||||
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
|
|
||||||
|
|
||||||
typedef enum _MEMORY_INFORMATION_ {
|
|
||||||
MemoryBasicInformation,
|
|
||||||
MemoryWorkingSetList,
|
|
||||||
MemorySectionName,
|
|
||||||
MemoryBasicVlmInformation
|
|
||||||
} MEMORY_INFORMATION_CLASS;
|
|
||||||
|
|
||||||
typedef struct _CLIENT_ID {
|
|
||||||
HANDLE UniqueProcess;
|
|
||||||
HANDLE UniqueThread;
|
|
||||||
} CLIENT_ID, *PCLIENT_ID;
|
|
||||||
|
|
||||||
typedef struct _USER_STACK {
|
|
||||||
PVOID FixedStackBase;
|
|
||||||
PVOID FixedStackLimit;
|
|
||||||
PVOID ExpandableStackBase;
|
|
||||||
PVOID ExpandableStackLimit;
|
|
||||||
PVOID ExpandableStackBottom;
|
|
||||||
} USER_STACK, *PUSER_STACK;
|
|
||||||
|
|
||||||
typedef LONG KPRIORITY;
|
|
||||||
typedef ULONG_PTR KAFFINITY;
|
|
||||||
|
|
||||||
typedef struct _THREAD_BASIC_INFORMATION {
|
|
||||||
LONG ExitStatus;
|
|
||||||
PVOID TebBaseAddress;
|
|
||||||
CLIENT_ID ClientId;
|
|
||||||
KAFFINITY AffinityMask;
|
|
||||||
KPRIORITY Priority;
|
|
||||||
KPRIORITY BasePriority;
|
|
||||||
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
|
|
||||||
|
|
||||||
typedef enum _SYSTEM_INFORMATION_CLASS {
|
|
||||||
SystemHandleInformation = 0x10
|
|
||||||
} SYSTEM_INFORMATION_CLASS;
|
|
||||||
|
|
||||||
typedef LONG (NTAPI *ZwWriteVirtualMemory_t)(IN HANDLE,
|
|
||||||
IN PVOID, IN PVOID, IN ULONG, OUT PULONG OPTIONAL);
|
|
||||||
|
|
||||||
typedef LONG (NTAPI *ZwCreateProcess_t)(OUT PHANDLE,
|
|
||||||
IN ACCESS_MASK, IN POBJECT_ATTRIBUTES, IN HANDLE, IN BOOLEAN,
|
|
||||||
IN HANDLE OPTIONAL, IN HANDLE OPTIONAL, IN HANDLE OPTIONAL);
|
|
||||||
|
|
||||||
typedef LONG (WINAPI *ZwQuerySystemInformation_t)(SYSTEM_INFORMATION_CLASS,
|
|
||||||
PVOID, ULONG, PULONG);
|
|
||||||
|
|
||||||
typedef LONG (NTAPI *ZwQueryVirtualMemory_t)(IN HANDLE,
|
|
||||||
IN PVOID, IN MEMORY_INFORMATION_CLASS, OUT PVOID, IN ULONG,
|
|
||||||
OUT PULONG OPTIONAL);
|
|
||||||
|
|
||||||
typedef LONG (NTAPI *ZwGetContextThread_t)(IN HANDLE,
|
|
||||||
OUT PCONTEXT);
|
|
||||||
|
|
||||||
typedef LONG (NTAPI *ZwCreateThread_t)(OUT PHANDLE,
|
|
||||||
IN ACCESS_MASK, IN POBJECT_ATTRIBUTES, IN HANDLE, OUT PCLIENT_ID,
|
|
||||||
IN PCONTEXT, IN PUSER_STACK, IN BOOLEAN);
|
|
||||||
|
|
||||||
typedef LONG (NTAPI *ZwResumeThread_t)(IN HANDLE, OUT PULONG OPTIONAL);
|
|
||||||
typedef LONG (NTAPI *ZwClose_t)(IN HANDLE);
|
|
||||||
typedef LONG (NTAPI *ZwQueryInformationThread_t)(IN HANDLE,
|
|
||||||
IN THREAD_INFORMATION_CLASS, OUT PVOID, IN ULONG, OUT PULONG OPTIONAL);
|
|
||||||
|
|
||||||
static ZwCreateProcess_t ZwCreateProcess;
|
|
||||||
static ZwQuerySystemInformation_t ZwQuerySystemInformation;
|
|
||||||
static ZwQueryVirtualMemory_t ZwQueryVirtualMemory;
|
|
||||||
static ZwCreateThread_t ZwCreateThread;
|
|
||||||
static ZwGetContextThread_t ZwGetContextThread;
|
|
||||||
static ZwResumeThread_t ZwResumeThread;
|
|
||||||
static ZwClose_t ZwClose;
|
|
||||||
static ZwQueryInformationThread_t ZwQueryInformationThread;
|
|
||||||
static ZwWriteVirtualMemory_t ZwWriteVirtualMemory;
|
|
||||||
|
|
||||||
static jmp_buf jenv;
|
|
||||||
static int child_entry(void) {
|
|
||||||
longjmp(jenv, 1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int init_ntdll(void) {
|
|
||||||
HMODULE ntdll = GetModuleHandle("ntdll");
|
|
||||||
if (!ntdll) return 0;
|
|
||||||
|
|
||||||
#define FORK_WIN_GETPROC(name) name = (name##_t)GetProcAddress(ntdll, #name)
|
|
||||||
|
|
||||||
FORK_WIN_GETPROC(ZwCreateProcess);
|
|
||||||
FORK_WIN_GETPROC(ZwQuerySystemInformation);
|
|
||||||
FORK_WIN_GETPROC(ZwQueryVirtualMemory);
|
|
||||||
FORK_WIN_GETPROC(ZwCreateThread);
|
|
||||||
FORK_WIN_GETPROC(ZwGetContextThread);
|
|
||||||
FORK_WIN_GETPROC(ZwResumeThread);
|
|
||||||
FORK_WIN_GETPROC(ZwQueryInformationThread);
|
|
||||||
FORK_WIN_GETPROC(ZwWriteVirtualMemory);
|
|
||||||
FORK_WIN_GETPROC(ZwClose);
|
|
||||||
|
|
||||||
#undef FORK_WIN_GETPROC
|
|
||||||
|
|
||||||
return !!ZwCreateProcess;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int fork_win(void) {
|
|
||||||
if (setjmp(jenv)) return 0;
|
|
||||||
if (!ZwCreateProcess && !init_ntdll()) return -1;
|
|
||||||
|
|
||||||
HANDLE hproc = 0, hthread = 0;
|
|
||||||
OBJECT_ATTRIBUTES oa = { sizeof(oa) };
|
|
||||||
ZwCreateProcess(&hproc, PROCESS_ALL_ACCESS, &oa, (HANDLE)-1, TRUE, 0, 0, 0);
|
|
||||||
|
|
||||||
CONTEXT context = { CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS
|
|
||||||
| CONTEXT_FLOATING_POINT };
|
|
||||||
|
|
||||||
ZwGetContextThread((HANDLE)-2, &context);
|
|
||||||
|
|
||||||
MEMORY_BASIC_INFORMATION mbi;
|
|
||||||
|
|
||||||
#if _WIN64
|
|
||||||
context.Rip = (ULONG)child_entry;
|
|
||||||
ZwQueryVirtualMemory((HANDLE)-1, (PVOID)context.Rsp, MemoryBasicInformation,
|
|
||||||
&mbi, sizeof(mbi), 0);
|
|
||||||
#else
|
|
||||||
context.Eip = (ULONG)child_entry;
|
|
||||||
ZwQueryVirtualMemory((HANDLE)-1, (PVOID)context.Esp, MemoryBasicInformation,
|
|
||||||
&mbi, sizeof(mbi), 0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
USER_STACK stack = { 0, 0, (PCHAR)mbi.BaseAddress + mbi.RegionSize,
|
|
||||||
mbi.BaseAddress, mbi.AllocationBase };
|
|
||||||
CLIENT_ID cid;
|
|
||||||
|
|
||||||
ZwCreateThread(&hthread, THREAD_ALL_ACCESS, &oa, hproc, &cid, &context,
|
|
||||||
&stack, TRUE);
|
|
||||||
|
|
||||||
THREAD_BASIC_INFORMATION tbi;
|
|
||||||
ZwQueryInformationThread((HANDLE)-2, ThreadMemoryPriority, &tbi,
|
|
||||||
sizeof(tbi), 0);
|
|
||||||
PNT_TIB tib = (PNT_TIB)tbi.TebBaseAddress;
|
|
||||||
ZwQueryInformationThread(hthread, ThreadMemoryPriority, &tbi,
|
|
||||||
sizeof(tbi), 0);
|
|
||||||
ZwWriteVirtualMemory(hproc, tbi.TebBaseAddress, &tib->ExceptionList,
|
|
||||||
sizeof(tib->ExceptionList), 0);
|
|
||||||
|
|
||||||
ZwResumeThread(hthread, 0);
|
|
||||||
|
|
||||||
ZwClose(hthread);
|
|
||||||
ZwClose(hproc);
|
|
||||||
|
|
||||||
return (int)cid.UniqueProcess;
|
|
||||||
}
|
|
|
@ -7,9 +7,6 @@
|
||||||
#define pipe(x, mode) pipe(x)
|
#define pipe(x, mode) pipe(x)
|
||||||
#else
|
#else
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include "fork_win.c"
|
|
||||||
int fork_win(void);
|
|
||||||
#define fork fork_win
|
|
||||||
#define fdopen _fdopen
|
#define fdopen _fdopen
|
||||||
#define execv _execv
|
#define execv _execv
|
||||||
#define close _close
|
#define close _close
|
||||||
|
|
|
@ -30,6 +30,10 @@
|
||||||
#include <Eina.h>
|
#include <Eina.h>
|
||||||
#include <Ecore.h>
|
#include <Ecore.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_EVIL
|
||||||
|
#include <Evil.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <lua.h>
|
#include <lua.h>
|
||||||
#include <lualib.h>
|
#include <lualib.h>
|
||||||
#include <lauxlib.h>
|
#include <lauxlib.h>
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
# include <direct.h> /* for _getcwd */
|
# include <direct.h> /* for _getcwd */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
#include "Evil.h"
|
#include "Evil.h"
|
||||||
#include "evil_private.h"
|
#include "evil_private.h"
|
||||||
|
|
||||||
|
@ -421,3 +423,168 @@ int execvp (const char *file EVIL_UNUSED, char *const argv[] EVIL_UNUSED)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _WIN32_WCE */
|
#endif /* _WIN32_WCE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process related functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _WIN32_WCE
|
||||||
|
|
||||||
|
typedef struct _OBJECT_ATTRIBUTES
|
||||||
|
{
|
||||||
|
ULONG Length;
|
||||||
|
HANDLE RootDirectory;
|
||||||
|
PVOID ObjectName;
|
||||||
|
ULONG Attributes;
|
||||||
|
PVOID SecurityDescriptor;
|
||||||
|
PVOID SecurityQualityOfService;
|
||||||
|
} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
|
||||||
|
|
||||||
|
typedef enum _MEMORY_INFORMATION_
|
||||||
|
{
|
||||||
|
MemoryBasicInformation,
|
||||||
|
MemoryWorkingSetList,
|
||||||
|
MemorySectionName,
|
||||||
|
MemoryBasicVlmInformation
|
||||||
|
} MEMORY_INFORMATION_CLASS;
|
||||||
|
|
||||||
|
typedef struct _CLIENT_ID
|
||||||
|
{
|
||||||
|
HANDLE UniqueProcess;
|
||||||
|
HANDLE UniqueThread;
|
||||||
|
} CLIENT_ID, *PCLIENT_ID;
|
||||||
|
|
||||||
|
typedef struct _USER_STACK
|
||||||
|
{
|
||||||
|
PVOID FixedStackBase;
|
||||||
|
PVOID FixedStackLimit;
|
||||||
|
PVOID ExpandableStackBase;
|
||||||
|
PVOID ExpandableStackLimit;
|
||||||
|
PVOID ExpandableStackBottom;
|
||||||
|
} USER_STACK, *PUSER_STACK;
|
||||||
|
|
||||||
|
typedef LONG KPRIORITY;
|
||||||
|
typedef ULONG_PTR KAFFINITY;
|
||||||
|
|
||||||
|
typedef struct _THREAD_BASIC_INFORMATION
|
||||||
|
{
|
||||||
|
LONG ExitStatus;
|
||||||
|
PVOID TebBaseAddress;
|
||||||
|
CLIENT_ID ClientId;
|
||||||
|
KAFFINITY AffinityMask;
|
||||||
|
KPRIORITY Priority;
|
||||||
|
KPRIORITY BasePriority;
|
||||||
|
} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;
|
||||||
|
|
||||||
|
typedef enum _SYSTEM_INFORMATION_CLASS
|
||||||
|
{
|
||||||
|
SystemHandleInformation = 0x10
|
||||||
|
} SYSTEM_INFORMATION_CLASS;
|
||||||
|
|
||||||
|
typedef LONG (NTAPI *ZwWriteVirtualMemory_t )(IN HANDLE, IN PVOID, IN PVOID, IN ULONG, OUT PULONG OPTIONAL);
|
||||||
|
typedef LONG (NTAPI *ZwCreateProcess_t )(OUT PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES, IN HANDLE, IN BOOLEAN, IN HANDLE OPTIONAL, IN HANDLE OPTIONAL, IN HANDLE OPTIONAL);
|
||||||
|
typedef LONG (WINAPI *ZwQuerySystemInformation_t)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
|
||||||
|
typedef LONG (NTAPI *ZwQueryVirtualMemory_t )(IN HANDLE, IN PVOID, IN MEMORY_INFORMATION_CLASS, OUT PVOID, IN ULONG, OUT PULONG OPTIONAL);
|
||||||
|
typedef LONG (NTAPI *ZwGetContextThread_t )(IN HANDLE, OUT PCONTEXT);
|
||||||
|
typedef LONG (NTAPI *ZwCreateThread_t )(OUT PHANDLE, IN ACCESS_MASK, IN POBJECT_ATTRIBUTES, IN HANDLE, OUT PCLIENT_ID, IN PCONTEXT, IN PUSER_STACK, IN BOOLEAN);
|
||||||
|
typedef LONG (NTAPI *ZwResumeThread_t )(IN HANDLE, OUT PULONG OPTIONAL);
|
||||||
|
typedef LONG (NTAPI *ZwClose_t )(IN HANDLE);
|
||||||
|
typedef LONG (NTAPI *ZwQueryInformationThread_t)(IN HANDLE, IN THREAD_INFORMATION_CLASS, OUT PVOID, IN ULONG, OUT PULONG OPTIONAL);
|
||||||
|
|
||||||
|
static ZwCreateProcess_t ZwCreateProcess;
|
||||||
|
static ZwQuerySystemInformation_t ZwQuerySystemInformation;
|
||||||
|
static ZwQueryVirtualMemory_t ZwQueryVirtualMemory;
|
||||||
|
static ZwCreateThread_t ZwCreateThread;
|
||||||
|
static ZwGetContextThread_t ZwGetContextThread;
|
||||||
|
static ZwResumeThread_t ZwResumeThread;
|
||||||
|
static ZwClose_t ZwClose;
|
||||||
|
static ZwQueryInformationThread_t ZwQueryInformationThread;
|
||||||
|
static ZwWriteVirtualMemory_t ZwWriteVirtualMemory;
|
||||||
|
|
||||||
|
static jmp_buf jenv;
|
||||||
|
static int
|
||||||
|
child_entry(void)
|
||||||
|
{
|
||||||
|
longjmp(jenv, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
init_ntdll(void)
|
||||||
|
{
|
||||||
|
HMODULE ntdll = GetModuleHandle("ntdll");
|
||||||
|
if (!ntdll) return 0;
|
||||||
|
|
||||||
|
#define FORK_WIN_GETPROC(name) name = (name##_t)GetProcAddress(ntdll, #name)
|
||||||
|
|
||||||
|
FORK_WIN_GETPROC(ZwCreateProcess);
|
||||||
|
FORK_WIN_GETPROC(ZwQuerySystemInformation);
|
||||||
|
FORK_WIN_GETPROC(ZwQueryVirtualMemory);
|
||||||
|
FORK_WIN_GETPROC(ZwCreateThread);
|
||||||
|
FORK_WIN_GETPROC(ZwGetContextThread);
|
||||||
|
FORK_WIN_GETPROC(ZwResumeThread);
|
||||||
|
FORK_WIN_GETPROC(ZwQueryInformationThread);
|
||||||
|
FORK_WIN_GETPROC(ZwWriteVirtualMemory);
|
||||||
|
FORK_WIN_GETPROC(ZwClose);
|
||||||
|
|
||||||
|
#undef FORK_WIN_GETPROC
|
||||||
|
|
||||||
|
return !!ZwCreateProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
evil_fork(void)
|
||||||
|
{
|
||||||
|
if (setjmp(jenv))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!ZwCreateProcess && !init_ntdll())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
HANDLE hproc = 0, hthread = 0;
|
||||||
|
OBJECT_ATTRIBUTES oa = { sizeof(oa) };
|
||||||
|
ZwCreateProcess(&hproc, PROCESS_ALL_ACCESS, &oa, (HANDLE)-1, TRUE, 0, 0, 0);
|
||||||
|
|
||||||
|
CONTEXT context = { CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS
|
||||||
|
| CONTEXT_FLOATING_POINT };
|
||||||
|
|
||||||
|
ZwGetContextThread((HANDLE)-2, &context);
|
||||||
|
|
||||||
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
|
||||||
|
#if _WIN64
|
||||||
|
context.Rip = (ULONG)child_entry;
|
||||||
|
ZwQueryVirtualMemory((HANDLE)-1, (PVOID)context.Rsp, MemoryBasicInformation,
|
||||||
|
&mbi, sizeof(mbi), 0);
|
||||||
|
#else
|
||||||
|
context.Eip = (ULONG)child_entry;
|
||||||
|
ZwQueryVirtualMemory((HANDLE)-1, (PVOID)context.Esp, MemoryBasicInformation,
|
||||||
|
&mbi, sizeof(mbi), 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
USER_STACK stack = { 0, 0, (PCHAR)mbi.BaseAddress + mbi.RegionSize,
|
||||||
|
mbi.BaseAddress, mbi.AllocationBase };
|
||||||
|
CLIENT_ID cid;
|
||||||
|
|
||||||
|
ZwCreateThread(&hthread, THREAD_ALL_ACCESS, &oa, hproc, &cid, &context,
|
||||||
|
&stack, TRUE);
|
||||||
|
|
||||||
|
THREAD_BASIC_INFORMATION tbi;
|
||||||
|
ZwQueryInformationThread((HANDLE)-2, ThreadMemoryPriority, &tbi,
|
||||||
|
sizeof(tbi), 0);
|
||||||
|
PNT_TIB tib = (PNT_TIB)tbi.TebBaseAddress;
|
||||||
|
ZwQueryInformationThread(hthread, ThreadMemoryPriority, &tbi,
|
||||||
|
sizeof(tbi), 0);
|
||||||
|
ZwWriteVirtualMemory(hproc, tbi.TebBaseAddress, &tib->ExceptionList,
|
||||||
|
sizeof(tib->ExceptionList), 0);
|
||||||
|
|
||||||
|
ZwResumeThread(hthread, 0);
|
||||||
|
|
||||||
|
ZwClose(hthread);
|
||||||
|
ZwClose(hproc);
|
||||||
|
|
||||||
|
return (int)cid.UniqueProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _WIN32_WCE */
|
||||||
|
|
|
@ -318,6 +318,37 @@ EAPI int execvp( const char *file, char *const argv[]);
|
||||||
|
|
||||||
#endif /* _WIN32_WCE */
|
#endif /* _WIN32_WCE */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process related functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _WIN32_WCE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Duplicate the calling process.
|
||||||
|
*
|
||||||
|
* @return 0 on child, the child's PID on parent.
|
||||||
|
*
|
||||||
|
* Duplicate the existing process from which it is called. You then decide
|
||||||
|
* which process you're in by checking the return value - it'll always be 0
|
||||||
|
* for the child process and the child process' PID for the parent.
|
||||||
|
*
|
||||||
|
* Conformity: None.
|
||||||
|
*
|
||||||
|
* Supported OS: NT based Windows.
|
||||||
|
*/
|
||||||
|
EAPI int evil_fork(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @def fork()
|
||||||
|
*
|
||||||
|
* Wrapper around evil_fork().
|
||||||
|
*/
|
||||||
|
#define fork() evil_fork()
|
||||||
|
|
||||||
|
#endif /* _WIN32_WCE */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
|
|
Loading…
Reference in New Issue