All pastes #1798277 Raw Edit

Someone

public c v1 · immutable
#1798277 ·published 2010-02-16 12:04 UTC
rendered paste body
/* * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 *//* * TODO: * - manage priority * - manage I/O pipes * - add events for data and error * - manage SetConsoleCtrlHandler ? */#ifdef HAVE_CONFIG_H# include <config.h>#endif#ifdef HAVE_EVIL# include <Evil.h>#endif#include "Ecore.h"#include "ecore_private.h"#ifndef _WIN32_WCE#define WIN32_LEAN_AND_MEAN#include <windows.h>#undef WIN32_LEAN_AND_MEAN#include <process.h>#define ECORE_EXE_WIN32_TIMEOUT 3000#define BUFSIZE 256typedef 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 process2;   HANDLE process; /* CloseHandle */   HANDLE thread;   DWORD  process_id;   DWORD  thread_id;   void  *data;   char  *tag;   char  *cmd;   Ecore_Exe_Flags flags;   Ecore_Exe_Win32_Signal sig;   Ecore_Win32_Handler *h_close;   struct   {      char buf[BUFSIZE];      HANDLE event;      OVERLAPPED ol;      HANDLE child_pipe;      HANDLE child_pipe_x;      uintptr_t thread;      Ecore_Win32_Handler *h;      void  *data_buf;      int    data_size;      int pending;   } pipe_read;   struct   {      HANDLE child_pipe;      HANDLE child_pipe_x;      uintptr_t thread;      Ecore_Win32_Handler *h;   } pipe_write;   struct   {      char buf[BUFSIZE];      HANDLE event;      OVERLAPPED ol;      HANDLE child_pipe;      HANDLE child_pipe_x;      uintptr_t thread;      Ecore_Win32_Handler *h;      void  *data_buf;      int    data_size;      int pending;   } pipe_error;   int    close_stdin;   int    is_suspended : 1;   void (*pre_free_cb)(void *data, const Ecore_Exe *exe);};static Ecore_Exe *exes = NULL;static int           _ecore_exe_win32_pipes_set(Ecore_Exe *exe);static void          _ecore_exe_win32_pipes_close(Ecore_Exe *exe);static BOOL CALLBACK _ecore_exe_enum_windows_procedure(HWND window, LPARAM data);static void          _ecore_exe_event_add_free(void *data, void *ev);static void          _ecore_exe_event_del_free(void *data, void *ev);static void          _ecore_exe_event_exe_data_free(void *data,                                                    void *ev);static int           _ecore_exe_close_cb(void *data, Ecore_Win32_Handler *wh);static int           _ecore_exe_pipe_read_cb(void *data, Ecore_Win32_Handler *wh);static int           _ecore_exe_pipe_write_cb(void *data, Ecore_Win32_Handler *wh);static int           _ecore_exe_pipe_error_cb(void *data, Ecore_Win32_Handler *wh);EAPI int ECORE_EXE_EVENT_ADD = 0;EAPI int ECORE_EXE_EVENT_DEL = 0;EAPI int ECORE_EXE_EVENT_DATA = 0;EAPI int ECORE_EXE_EVENT_ERROR = 0;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 voidecore_exe_run_priority_set(int pri){}EAPI intecore_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_Event_Add *e;   Ecore_Exe           *exe;   char                *ret = NULL;   exe = calloc(1, sizeof(Ecore_Exe));   if (!exe)     return NULL;   if ((flags & ECORE_EXE_PIPE_AUTO) && (!(flags & ECORE_EXE_PIPE_ERROR))       && (!(flags & ECORE_EXE_PIPE_READ)))     /* We need something to auto pipe. */     flags |= ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR;   printf ("create pipes...\n");   exe->flags = flags;   if (exe->flags & ECORE_EXE_PIPE_READ)     if (!_ecore_exe_win32_pipes_set(exe))       return NULL;     if (exe->flags & ECORE_EXE_PIPE_WRITE)     if (!_ecore_exe_win32_pipes_set(exe))       goto close_pipes;   if (exe->flags & ECORE_EXE_PIPE_ERROR)     if (!_ecore_exe_win32_pipes_set(exe))       goto close_pipes;   printf ("create pipes finished\n");   if ((exe->flags & ECORE_EXE_USE_SH) ||       ((ret = strrstr(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 close_pipes;   ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));   ZeroMemory(&si, sizeof(STARTUPINFO));   si.cb = sizeof(STARTUPINFO);   si.hStdOutput = exe->pipe_read.child_pipe_x;   si.hStdInput = exe->pipe_write.child_pipe;   si.hStdError = exe->pipe_error.child_pipe_x;   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;   /* be sure that the child process is running */   /* FIXME: This does not work if the child is an EFL-based app *//*    if (WaitForInputIdle(pi.hProcess, INFINITE) != 0) *//*      goto free_exe_cmd; */   ECORE_MAGIC_SET(exe, ECORE_MAGIC_EXE);   exe->process = pi.hProcess;   exe->thread = pi.hThread;   exe->process_id = pi.dwProcessId;   exe->thread_id = pi.dwThreadId;   exe->data = (void *)data;   if (!(exe->process2 = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_SUSPEND_RESUME | PROCESS_TERMINATE | SYNCHRONIZE,                                     FALSE, pi.dwProcessId)))     goto close_thread;   printf (" * 10\n");   exe->h_close = ecore_main_win32_handler_add(exe->process2, _ecore_exe_close_cb, exe);   if (!exe->h_close) goto close_process2;   printf (" * 11\n");   exes = (Ecore_Exe *)eina_inlist_append(EINA_INLIST_GET(exes), EINA_INLIST_GET(exe));   e = (Ecore_Exe_Event_Add *)calloc(1, sizeof(Ecore_Exe_Event_Add));   if (!e) goto delete_h_close;   e->exe = exe;   ecore_event_add(ECORE_EXE_EVENT_ADD, e,                   _ecore_exe_event_add_free, NULL);   return exe; delete_h_close:   ecore_main_win32_handler_del(exe->h_close); close_process2:   CloseHandle(exe->process2); close_thread:   CloseHandle(exe->thread);   CloseHandle(exe->process); free_exe_cmd:   free(exe->cmd); close_pipes:   _ecore_exe_win32_pipes_close(exe); free_exe:   free(exe);   return NULL;}EAPI voidecore_exe_callback_pre_free_set(Ecore_Exe *exe, void (*func)(void *data, const Ecore_Exe *exe)){   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))     {	ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,			 "ecore_exe_callback_pre_free_set");	return;     }   exe->pre_free_cb = func;}EAPI Eina_Boolecore_exe_send(Ecore_Exe *exe, const void *data, int size){}EAPI voidecore_exe_close_stdin(Ecore_Exe *exe){   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))     {	ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_close_stdin");	return;     }   exe->close_stdin = 1;}EAPI voidecore_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){   Ecore_Exe_Event_Data *e = NULL;   unsigned char      *inbuf;   int                 inbuf_num;   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))     {	ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_event_data_get");	return NULL;     }   /* Sort out what sort of event we are, */   /* And get the data. */   if (flags & ECORE_EXE_PIPE_READ)     {	flags = ECORE_EXE_PIPE_READ;	inbuf = exe->pipe_read.data_buf;	inbuf_num = exe->pipe_read.data_size;	exe->pipe_read.data_buf = NULL;	exe->pipe_read.data_size = 0;     }   else     {	flags = ECORE_EXE_PIPE_ERROR;	inbuf = exe->pipe_error.data_buf;	inbuf_num = exe->pipe_error.data_size;	exe->pipe_error.data_buf = NULL;	exe->pipe_error.data_size = 0;     }   e = calloc(1, sizeof(Ecore_Exe_Event_Data));   if (e)     {	e->exe = exe;	e->data = inbuf;	e->size = inbuf_num;     }   return e;}EAPI voidecore_exe_event_data_free(Ecore_Exe_Event_Data *e){   if (!e) return;   IF_FREE(e->lines);   IF_FREE(e->data);   free(e);}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;   if (exe->pre_free_cb)     exe->pre_free_cb(data, exe);   ecore_main_win32_handler_del(exe->h_close);   CloseHandle(exe->process2);   CloseHandle(exe->thread);   CloseHandle(exe->process);   free(exe->cmd);   _ecore_exe_win32_pipes_close(exe);   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_tecore_exe_pid_get(const 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 voidecore_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 const char *ecore_exe_tag_get(const 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 const char *ecore_exe_cmd_get(const 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(const 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 Ecore_Exe_Flagsecore_exe_flags_get(const Ecore_Exe *exe){   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))     {	ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_data_get");	return 0;     }   return exe->flags;}EAPI voidecore_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 voidecore_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 voidecore_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->thread);   CloseHandle(exe->process);   exe->sig = ECORE_EXE_WIN32_SIGINT;   while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe));}EAPI voidecore_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->thread);   CloseHandle(exe->process);   exe->sig = ECORE_EXE_WIN32_SIGQUIT;   while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe));}EAPI voidecore_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->thread); */   CloseHandle(exe->process);   exe->sig = ECORE_EXE_WIN32_SIGTERM;   while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe));}EAPI voidecore_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->thread);   CloseHandle(exe->process);   exe->sig = ECORE_EXE_WIN32_SIGKILL;   while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe));}EAPI voidecore_exe_signal(Ecore_Exe *exe, int num __UNUSED__){   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))     {	ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_signal");	return;     }   /* does nothing */}EAPI voidecore_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 */}/* FIXME: manage error mode */static void _ecore_exe_win32_pipe_thread_cb(void *data){   Ecore_Exe *exe;   DWORD      size;   exe = (Ecore_Exe *)data;   while (1)     {        BOOL res;         res = ReadFile(exe->pipe_read.child_pipe, exe->pipe_read.buf, sizeof(exe->pipe_read.buf), NULL, &exe->pipe_read.ol);        if (res) break;        else          {             if (GetLastError() == ERROR_IO_PENDING)               {                  exe->pipe_read.pending = 1;                  break;               }          }     }   printf ("pending: %d\n", exe->pipe_read.pending);   if (!exe->pipe_read.pending)     {        Ecore_Exe_Event_Data *e;         e = ecore_exe_event_data_get(exe, ECORE_EXE_PIPE_READ);        if (e)          ecore_event_add(ECORE_EXE_EVENT_DATA, e,                          _ecore_exe_event_exe_data_free,                          NULL);     }   else     {        if (!exe->pipe_read.h)          exe->pipe_read.h = ecore_main_win32_handler_add(exe->pipe_read.child_pipe, _ecore_exe_pipe_read_cb, exe);     }}static int_ecore_exe_win32_pipes_set(Ecore_Exe *exe){   SECURITY_ATTRIBUTES sa;   HANDLE event;   OVERLAPPED ol;   HANDLE child_pipe;   HANDLE child_pipe_x;   sa.nLength = sizeof(SECURITY_ATTRIBUTES);   sa.bInheritHandle = TRUE;   sa.lpSecurityDescriptor = NULL;   event = CreateEvent(NULL, TRUE, FALSE, NULL);   if (!event)     return 0;   ol.hEvent = event;   if (!CreatePipe(&child_pipe, &child_pipe_x, &sa, 0))     goto close_event;   if (exe->flags & ECORE_EXE_PIPE_WRITE)     {        if (!SetHandleInformation(child_pipe_x, HANDLE_FLAG_INHERIT, 0))          goto close_pipe;     }   else     {        if (!SetHandleInformation(child_pipe, HANDLE_FLAG_INHERIT, 0))          goto close_pipe;     }   if (exe->flags & ECORE_EXE_PIPE_READ)     {        exe->pipe_read.event = event;        exe->pipe_read.ol = ol;        exe->pipe_read.child_pipe = child_pipe;        exe->pipe_read.child_pipe_x = child_pipe_x;        exe->pipe_read.thread = _beginthread(_ecore_exe_win32_pipe_thread_cb, 0, exe);     }   else if (exe->flags & ECORE_EXE_PIPE_WRITE)     {        exe->pipe_write.child_pipe = child_pipe;        exe->pipe_write.child_pipe_x = child_pipe_x;        exe->pipe_write.thread = _beginthread(_ecore_exe_win32_pipe_thread_cb, 0, exe);     }   else     {        exe->pipe_error.event = event;        exe->pipe_error.ol = ol;        exe->pipe_error.child_pipe = child_pipe;        exe->pipe_error.child_pipe_x = child_pipe_x;        exe->pipe_error.thread = _beginthread(_ecore_exe_win32_pipe_thread_cb, 0, exe);     }   return 1; close_pipe:   CloseHandle(child_pipe);   CloseHandle(child_pipe_x); close_event:   CloseHandle(event);   return 0;}static void_ecore_exe_win32_pipes_close(Ecore_Exe *exe){   if (exe->flags & ECORE_EXE_PIPE_READ)     {       if (exe->pipe_read.child_pipe)         {            CloseHandle(exe->pipe_read.child_pipe);            exe->pipe_read.child_pipe = NULL;         }       if (exe->pipe_read.child_pipe_x)         {           CloseHandle(exe->pipe_read.child_pipe_x);           exe->pipe_read.child_pipe_x = NULL;         }       if (exe->pipe_read.event)         {            CloseHandle(exe->pipe_read.event);            exe->pipe_read.event = NULL;         }     }   if (exe->flags & ECORE_EXE_PIPE_WRITE)     {       if (exe->pipe_write.child_pipe)         {            CloseHandle(exe->pipe_write.child_pipe);            exe->pipe_write.child_pipe = NULL;         }       if (exe->pipe_write.child_pipe_x)         {           CloseHandle(exe->pipe_write.child_pipe_x);           exe->pipe_write.child_pipe_x = NULL;         }     }   if (exe->flags & ECORE_EXE_PIPE_ERROR)     {       if (exe->pipe_error.child_pipe)         {            CloseHandle(exe->pipe_error.child_pipe);            exe->pipe_error.child_pipe = NULL;         }       if (exe->pipe_error.child_pipe_x)         {           CloseHandle(exe->pipe_error.child_pipe_x);           exe->pipe_error.child_pipe_x = NULL;         }       if (exe->pipe_error.event)         {            CloseHandle(exe->pipe_error.event);            exe->pipe_error.event = NULL;         }     }}static DWORD WINAPI_ecore_exe_thread_procedure(LPVOID data __UNUSED__){   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))          {            printf ("remote thread\n");            return FALSE;          }        if ((exe->sig == ECORE_EXE_WIN32_SIGINT) ||            (exe->sig == ECORE_EXE_WIN32_SIGQUIT))          {            printf ("int or quit\n");            return FALSE;          }        /* WM_CLOSE message */        PostMessage(window, WM_CLOSE, 0, 0);        if (WaitForSingleObject(exe->process, ECORE_EXE_WIN32_TIMEOUT) == WAIT_OBJECT_0)          {            printf ("CLOSE\n");            return FALSE;          }        /* WM_QUIT message */        PostMessage(window, WM_QUIT, 0, 0);        if (WaitForSingleObject(exe->process, ECORE_EXE_WIN32_TIMEOUT) == WAIT_OBJECT_0)          {            printf ("QUIT\n");            return FALSE;          }        /* Exit process */        if (CreateRemoteThread(exe->process, NULL, 0,                               (LPTHREAD_START_ROUTINE)ExitProcess, NULL,                               0, NULL))          {            printf ("remote thread 2\n");            return FALSE;          }        if (exe->sig == ECORE_EXE_WIN32_SIGTERM)          {            printf ("term\n");            return FALSE;          }        TerminateProcess(exe->process, 0);        return FALSE;     }   return TRUE;}static void_ecore_exe_event_add_free(void *data __UNUSED__, void *ev){   Ecore_Exe_Event_Add *e;   e = (Ecore_Exe_Event_Add *)ev;   free(e);}static void_ecore_exe_event_del_free(void *data __UNUSED__, void *ev){   Ecore_Exe_Event_Del *e;   e = (Ecore_Exe_Event_Del *)ev;   if (e->exe)     ecore_exe_free(e->exe);   free(e);}static void_ecore_exe_event_exe_data_free(void *data __UNUSED__, void *ev){   Ecore_Exe_Event_Data *e;   e = (Ecore_Exe_Event_Data *)ev;   ecore_exe_event_data_free(e);}static int_ecore_exe_close_cb(void *data, Ecore_Win32_Handler *wh __UNUSED__){   Ecore_Exe_Event_Del *e;   Ecore_Exe           *exe;   DWORD                exit_code = 0;   e = calloc(1, sizeof(Ecore_Exe_Event_Del));   if (!e) return 0;   exe = (Ecore_Exe *)data;   if (GetExitCodeProcess(exe->process2, &exit_code))     {        e->exit_code = exit_code;        e->exited = 1;     }   else     {        char *msg;        msg = evil_last_error_get();        printf("%s\n", msg);        free(msg);     }     e->pid = exe->process_id;     e->exe = exe;     _ecore_event_add(ECORE_EXE_EVENT_DEL, e,                      _ecore_exe_event_del_free, NULL);   return 1;}static int_ecore_exe_generic_cb(void *data, Ecore_Win32_Handler *wh){   char                  buf[READBUFSIZ];   Ecore_Exe            *exe;   Ecore_Exe_Event_Data *e;   HANDLE                child_pipe;   LPOVERLAPPED          ol;   int                   event_type;   int                   pending;   DWORD                 num_exe;   Ecore_Exe_Flags       flags;   printf ("%s\n", __FUNCTION__);   if (!wh)     return 1;   exe = (Ecore_Exe *)data;   /* Sort out what sort of handler we are. */   /* And get any left over data from last time. */   if (exe->flags & ECORE_EXE_PIPE_READ)     {	flags = ECORE_EXE_PIPE_READ;	event_type = ECORE_EXE_EVENT_DATA;	child_pipe = exe->pipe_read.child_pipe;        pending = exe->pipe_read.pending;        ol = &exe->pipe_read.ol;     }   else     {	flags = ECORE_EXE_PIPE_ERROR;	event_type = ECORE_EXE_EVENT_ERROR;	child_pipe =  exe->pipe_error.child_pipe;        pending = exe->pipe_error.pending;        ol = &exe->pipe_error.ol;     }   if (!pending)     {        if (!GetOverlappedResult(child_pipe, ol, &num_exe, TRUE))          return 0;        if (exe->flags & ECORE_EXE_PIPE_READ)          {             if (exe->pipe_read.data_buf) free(exe->pipe_read.data_buf);             exe->pipe_read.data_size = 0;             exe->pipe_read.data_buf = malloc(num_exe);             if (exe->pipe_read.data_buf)               {                  memcpy(exe->pipe_read.data_buf, exe->pipe_read.buf, num_exe);                  exe->pipe_read.data_size = num_exe;               }          }        else          {             if (exe->pipe_error.data_buf) free(exe->pipe_error.data_buf);             exe->pipe_error.data_size = 0;             exe->pipe_error.data_buf = malloc(num_exe);             if (exe->pipe_error.data_buf)               {                  memcpy(exe->pipe_error.data_buf, exe->pipe_error.buf, num_exe);                  exe->pipe_error.data_size = num_exe;               }          }       goto add_event;     }   printf ("PROBLEM!!!!");   for (;;)     {        BOOL res;        res = ReadFile(child_pipe, buf, READBUFSIZ, NULL, ol);        if (!res || num_exe == 0) continue;        if (flags & ECORE_EXE_PIPE_READ)          {             if (exe->pipe_read.data_buf) free(exe->pipe_read.data_buf);             exe->pipe_read.data_size = 0;             exe->pipe_read.data_buf = malloc(num_exe);             if (exe->pipe_read.data_buf)               {                  memcpy(exe->pipe_read.data_buf, buf, num_exe);                  exe->pipe_read.data_size = num_exe;               }          }        else          {             if (exe->pipe_error.data_buf) free(exe->pipe_error.data_buf);             exe->pipe_error.data_size = 0;             exe->pipe_error.data_buf = malloc(num_exe);             if (exe->pipe_error.data_buf)               {                  memcpy(exe->pipe_error.data_buf, buf, num_exe);                  exe->pipe_error.data_size = num_exe;               }          }        break;     } add_event:   e = ecore_exe_event_data_get(exe, flags);   if (e)     ecore_event_add(event_type, e,                     _ecore_exe_event_exe_data_free,                     NULL);   return 1;}static int_ecore_exe_pipe_read_cb(void *data, Ecore_Win32_Handler *wh){   return _ecore_exe_generic_cb(data, wh);}static int_ecore_exe_pipe_write_cb(void *data, Ecore_Win32_Handler *wh __UNUSED__){   char       buf[READBUFSIZ];   Ecore_Exe *exe;   DWORD      num_exe;   BOOL       res;   exe = (Ecore_Exe *)data;   res = WriteFile(exe->pipe_write.child_pipe_x, buf, READBUFSIZ, &num_exe, NULL);   if (!res || num_exe == 0)     {       /* FIXME: what to do here ?? */     }   if (exe->close_stdin == 1)     {        if (exe->pipe_write.h)          ecore_main_win32_handler_del(exe->pipe_write.h);        exe->pipe_write.h = NULL;        CloseHandle(exe->pipe_write.child_pipe);        exe->pipe_write.child_pipe = NULL;     }   return 1;}static int_ecore_exe_pipe_error_cb(void *data, Ecore_Win32_Handler *wh){   return _ecore_exe_generic_cb(data, wh);}#elsevoid_ecore_exe_init(void){}void_ecore_exe_shutdown(void){}#endif