diff --git a/legacy/ecore/src/lib/ecore/Ecore.h b/legacy/ecore/src/lib/ecore/Ecore.h index b654fd7166..b1e21453d5 100644 --- a/legacy/ecore/src/lib/ecore/Ecore.h +++ b/legacy/ecore/src/lib/ecore/Ecore.h @@ -120,9 +120,7 @@ extern "C" { }; typedef enum _Ecore_Poller_Type Ecore_Poller_Type; -#ifndef _WIN32 typedef void Ecore_Exe; /**< A handle for spawned processes */ -#endif typedef void Ecore_Timer; /**< A handle for timers */ typedef void Ecore_Idler; /**< A handle for idlers */ typedef void Ecore_Idle_Enterer; /**< A handle for idle enterers */ @@ -246,7 +244,6 @@ extern "C" { EAPI void *ecore_event_current_event_get(void); -#ifndef _WIN32 EAPI void ecore_exe_run_priority_set(int pri); EAPI int ecore_exe_run_priority_get(void); EAPI Ecore_Exe *ecore_exe_run(const char *exe_cmd, const void *data); @@ -270,7 +267,6 @@ extern "C" { EAPI void ecore_exe_kill(Ecore_Exe *exe); EAPI void ecore_exe_signal(Ecore_Exe *exe, int num); EAPI void ecore_exe_hup(Ecore_Exe *exe); -#endif EAPI Ecore_Idler *ecore_idler_add(int (*func) (void *data), const void *data); EAPI void *ecore_idler_del(Ecore_Idler *idler); diff --git a/legacy/ecore/src/lib/ecore/Makefile.am b/legacy/ecore/src/lib/ecore/Makefile.am index 46369f8cd6..bf8d8399a8 100644 --- a/legacy/ecore/src/lib/ecore/Makefile.am +++ b/legacy/ecore/src/lib/ecore/Makefile.am @@ -16,6 +16,7 @@ ecore_anim.c \ ecore_app.c \ ecore_events.c \ ecore_exe.c \ +ecore_exe_win32.c \ ecore_getopt.c \ ecore_hash.c \ ecore_idle_enterer.c \ diff --git a/legacy/ecore/src/lib/ecore/ecore_exe_win32.c b/legacy/ecore/src/lib/ecore/ecore_exe_win32.c new file mode 100644 index 0000000000..d77ae328c3 --- /dev/null +++ b/legacy/ecore/src/lib/ecore/ecore_exe_win32.c @@ -0,0 +1,392 @@ +/* + * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN + +#include "ecore_private.h" +#include "Ecore.h" + +#ifdef _WIN32 + +#define ECORE_EXE_WIN32_TIMEOUT 3000 + +typedef enum +{ + ECORE_EXE_WIN32_SIGINT, + ECORE_EXE_WIN32_SIGQUIT, + ECORE_EXE_WIN32_SIGTERM, + ECORE_EXE_WIN32_SIGKILL +} Ecore_Exe_Win32_Signal; + +struct _Ecore_Exe +{ + EINA_INLIST; + ECORE_MAGIC; + + HANDLE process; /* CloseHandle */ + HANDLE thread; + DWORD process_id; + DWORD thread_id; + void *data; + char *tag; + char *cmd; + Ecore_Exe_Win32_Signal sig; + int is_suspended : 1; +}; + +static Ecore_Exe *exes = NULL; + +static BOOL CALLBACK _ecore_exe_enum_windows_procedure(HWND window, LPARAM data); + +void +_ecore_exe_init(void) +{ +/* ECORE_EXE_EVENT_ADD = ecore_event_type_new(); */ +/* ECORE_EXE_EVENT_DEL = ecore_event_type_new(); */ +/* ECORE_EXE_EVENT_DATA = ecore_event_type_new(); */ +/* ECORE_EXE_EVENT_ERROR = ecore_event_type_new(); */ +} + +void +_ecore_exe_shutdown(void) +{ + while (exes) + ecore_exe_free(exes); +} + +EAPI void ecore_exe_run_priority_set(int pri) +{ +} + +EAPI int ecore_exe_run_priority_get(void) +{ +} + +EAPI Ecore_Exe *ecore_exe_run(const char *exe_cmd, const void *data) +{ + return ecore_exe_pipe_run(exe_cmd, 0, data); +} + +EAPI Ecore_Exe *ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data) +{ + STARTUPINFO si; + PROCESS_INFORMATION pi; + Ecore_Exe *exe; + char *ret = NULL; + + exe = calloc(1, sizeof(Ecore_Exe)); + if (!exe) + return NULL; + + if ((flags & ECORE_EXE_USE_SH) || + ((ret = strrchr(exe_cmd, ".bat")) && (ret[4] == '\0'))) + { + char buf[PATH_MAX]; + snprintf(buf, PATH_MAX, "cmd.exe /c %s", exe_cmd); + exe->cmd = strdup(buf); + } + else + exe->cmd = strdup(exe_cmd); + + if (!exe->cmd) + goto free_exe; + + ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); + + ZeroMemory(&si, sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); +/* si.hStdError = g_hChildStd_OUT_Wr; */ +/* si.hStdOutput = g_hChildStd_OUT_Wr; */ +/* si.hStdInput = g_hChildStd_IN_Rd; */ +/* si.dwFlags |= STARTF_USESTDHANDLES; */ + + /* FIXME: gerer la priorite */ + + if (!CreateProcess(NULL, exe->cmd, NULL, NULL, TRUE, + 0, NULL, NULL, &si, &pi)) + goto free_exe_cmd; + + exe->thread = pi.hThread; + exe->process_id = pi.dwProcessId; + exe->thread_id = pi.dwThreadId; + exe->data = (void *)data; + CloseHandle(pi.hProcess); + + if (!(exe->process = OpenProcess(PROCESS_SUSPEND_RESUME | PROCESS_TERMINATE | SYNCHRONIZE, + FALSE, pi.dwProcessId))) + goto close_thread; + + exes = (Ecore_Exe *)eina_inlist_append(EINA_INLIST_GET(exes), EINA_INLIST_GET(exe)); + return exe; + + close_thread: + CloseHandle(pi.hThread); + free_exe_cmd: + free(exe->cmd); + free_exe: + free(exe); + return NULL; +} + +EAPI int ecore_exe_send(Ecore_Exe *exe, void *data, int size) +{ +} + +EAPI void ecore_exe_close_stdin(Ecore_Exe *exe) +{ +} + +EAPI void ecore_exe_auto_limits_set(Ecore_Exe *exe, int start_bytes, int end_bytes, int start_lines, int end_lines) +{ +} + +EAPI Ecore_Exe_Event_Data *ecore_exe_event_data_get(Ecore_Exe *exe, Ecore_Exe_Flags flags) +{ +} + +EAPI void ecore_exe_event_data_free(Ecore_Exe_Event_Data *data) +{ +} + +EAPI void *ecore_exe_free(Ecore_Exe *exe) +{ + void *data; + + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_free"); + return NULL; + } + + data = exe->data; + + CloseHandle(exe->process); + CloseHandle(exe->thread); + free(exe->cmd); + exes = (Ecore_Exe *) eina_inlist_remove(EINA_INLIST_GET(exes), EINA_INLIST_GET(exe)); + ECORE_MAGIC_SET(exe, ECORE_MAGIC_NONE); + if (exe->tag) free(exe->tag); + free(exe); + + return data; +} + +EAPI pid_t ecore_exe_pid_get(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_pid_get"); + return -1; + } + return exe->process_id; +} + +EAPI void ecore_exe_tag_set(Ecore_Exe *exe, const char *tag) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_tag_set"); + return; + } + IF_FREE(exe->tag); + if (tag) + exe->tag = strdup(tag); +} + +EAPI char *ecore_exe_tag_get(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_tag_get"); + return NULL; + } + return exe->tag; +} + +EAPI char *ecore_exe_cmd_get(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_cmd_get"); + return NULL; + } + return exe->cmd; +} + +EAPI void *ecore_exe_data_get(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_data_get"); + return NULL; + } + return exe->data; +} + +EAPI void ecore_exe_pause(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_pause"); + return; + } + + if (exe->is_suspended) + return; + + if (SuspendThread(exe->thread) != (DWORD)-1) + exe->is_suspended = 1; +} + +EAPI void ecore_exe_continue(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_continue"); + return; + } + + if (!exe->is_suspended) + return; + + if (ResumeThread(exe->thread) != (DWORD)-1) + exe->is_suspended = 0; +} + +EAPI void ecore_exe_interrupt(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_interrupt"); + return; + } + + CloseHandle(exe->process); + exe->sig = ECORE_EXE_WIN32_SIGINT; + while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe)); +} + +EAPI void ecore_exe_quit(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_quit"); + return; + } + + CloseHandle(exe->process); + exe->sig = ECORE_EXE_WIN32_SIGQUIT; + while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe)); +} + +EAPI void ecore_exe_terminate(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_terminate"); + return; + } + + CloseHandle(exe->process); + exe->sig = ECORE_EXE_WIN32_SIGTERM; + while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe)); +} + +EAPI void ecore_exe_kill(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_kill"); + return; + } + + CloseHandle(exe->process); + exe->sig = ECORE_EXE_WIN32_SIGKILL; + while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe)); +} + +EAPI void ecore_exe_signal(Ecore_Exe *exe, int num) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_signal"); + return; + } + + /* does nothing */ +} + +EAPI void ecore_exe_hup(Ecore_Exe *exe) +{ + if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) + { + ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_hup"); + return; + } + + /* does nothing */ +} + +static DWORD WINAPI +_ecore_exe_thread_procedure(LPVOID data) +{ + GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); + GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0); + return 1; +} + +static BOOL CALLBACK +_ecore_exe_enum_windows_procedure(HWND window, LPARAM data) +{ + Ecore_Exe *exe; + DWORD thread_id; + + exe = (Ecore_Exe *)data; + thread_id = GetWindowThreadProcessId(window, NULL); + + if (thread_id == exe->thread_id) + { + /* Ctrl-C or Ctrl-Break */ + if (CreateRemoteThread(exe->process, NULL, 0, + (LPTHREAD_START_ROUTINE)_ecore_exe_thread_procedure, NULL, + 0, NULL)) + return FALSE; + + if ((exe->sig == ECORE_EXE_WIN32_SIGINT) || + (exe->sig == ECORE_EXE_WIN32_SIGQUIT)) + return FALSE; + + /* WM_CLOSE message */ + PostMessage(window, WM_CLOSE, 0, 0); + if (WaitForSingleObject(exe->process, ECORE_EXE_WIN32_TIMEOUT) == WAIT_OBJECT_0) + return FALSE; + + /* WM_QUIT message */ + PostMessage(window, WM_QUIT, 0, 0); + if (WaitForSingleObject(exe->process, ECORE_EXE_WIN32_TIMEOUT) == WAIT_OBJECT_0) + return FALSE; + + /* Exit process */ + if (CreateRemoteThread(exe->process, NULL, 0, + (LPTHREAD_START_ROUTINE)ExitProcess, NULL, + 0, NULL)) + return FALSE; + if (exe->sig == ECORE_EXE_WIN32_SIGTERM) + return FALSE; + + TerminateProcess(exe->process, 0); + + return FALSE; + } + + return TRUE; +} + +#endif diff --git a/legacy/ecore/src/lib/ecore/ecore_private.h b/legacy/ecore/src/lib/ecore/ecore_private.h index 6ab38e5986..e3ec537ec7 100644 --- a/legacy/ecore/src/lib/ecore/ecore_private.h +++ b/legacy/ecore/src/lib/ecore/ecore_private.h @@ -207,9 +207,7 @@ enum _Ecore_Poller_Type }; typedef enum _Ecore_Poller_Type Ecore_Poller_Type; -#ifndef _WIN32 typedef struct _Ecore_Exe Ecore_Exe; -#endif typedef struct _Ecore_Timer Ecore_Timer; typedef struct _Ecore_Idler Ecore_Idler; typedef struct _Ecore_Idle_Enterer Ecore_Idle_Enterer; @@ -418,12 +416,9 @@ int _ecore_signal_count_get(void); void _ecore_signal_call(void); #endif -#ifdef _WIN32 -static inline void _ecore_exe_init(void) { } -static inline void _ecore_exe_shutdown(void) { } -#else void _ecore_exe_init(void); void _ecore_exe_shutdown(void); +#ifndef _WIN32 Ecore_Exe *_ecore_exe_find(pid_t pid); void *_ecore_exe_event_del_new(void); void _ecore_exe_event_del_free(void *data, void *ev);