7f4435a80c04888de72d865032a9944e6faa3c3b
[profile/ivi/ecore.git] / src / lib / ecore / ecore_exe_win32.c
1 /*
2  * TODO:
3  * - manage I/O pipes (several ones, and stdin)
4  * - manage SetConsoleCtrlHandler ?
5  * - the child process seems to still run after the DEL event
6  * - add log messages
7  */
8
9 #ifdef HAVE_CONFIG_H
10 # include <config.h>
11 #endif
12
13 #ifdef HAVE_EVIL
14 # include <Evil.h>
15 #endif
16
17 #include "Ecore.h"
18 #include "ecore_private.h"
19
20 #define WIN32_LEAN_AND_MEAN
21 #include <windows.h>
22 #undef WIN32_LEAN_AND_MEAN
23 #include <process.h>
24
25 #define ECORE_EXE_WIN32_TIMEOUT 3000
26
27 typedef enum
28 {
29   ECORE_EXE_WIN32_SIGINT,
30   ECORE_EXE_WIN32_SIGQUIT,
31   ECORE_EXE_WIN32_SIGTERM,
32   ECORE_EXE_WIN32_SIGKILL
33 } Ecore_Exe_Win32_Signal;
34
35 struct _Ecore_Exe
36 {
37    EINA_INLIST;
38    ECORE_MAGIC;
39
40    HANDLE process2;
41    HANDLE process; /* CloseHandle */
42    HANDLE process_thread;
43    DWORD  process_id;
44    DWORD  thread_id;
45    void  *data;
46    char  *tag;
47    char  *cmd;
48    Ecore_Exe_Flags flags;
49    Ecore_Exe_Win32_Signal sig;
50    Ecore_Win32_Handler *h_close;
51    struct
52    {
53       HANDLE child_pipe;
54       HANDLE child_pipe_x;
55       Ecore_Pipe *p;
56       HANDLE thread;
57       void  *data_buf;
58       int    data_size;
59    } pipe_read;
60    struct
61    {
62       HANDLE child_pipe;
63       HANDLE child_pipe_x;
64       HANDLE thread;
65       Ecore_Win32_Handler *h;
66       void  *data_buf;
67       int    data_size;
68    } pipe_write;
69    struct
70    {
71       HANDLE child_pipe;
72       HANDLE child_pipe_x;
73       Ecore_Pipe *p;
74       HANDLE thread;
75       void  *data_buf;
76       int    data_size;
77    } pipe_error;
78    Eina_Bool    close_stdin : 1;
79    Eina_Bool    is_suspended : 1;
80
81    Ecore_Exe_Cb pre_free_cb;
82 };
83
84 static Ecore_Exe *exes = NULL;
85
86 static int           _ecore_exe_win32_pipes_set(Ecore_Exe *exe);
87 static void          _ecore_exe_win32_pipes_close(Ecore_Exe *exe);
88
89 static BOOL CALLBACK _ecore_exe_enum_windows_procedure(HWND window, LPARAM data);
90 static void          _ecore_exe_event_add_free(void *data, void *ev);
91 static void          _ecore_exe_event_del_free(void *data, void *ev);
92 static void          _ecore_exe_event_exe_data_free(void *data,
93                                                     void *ev);
94 static int           _ecore_exe_win32_pipe_thread_generic_cb(void *data, Ecore_Exe_Flags flags);
95 static DWORD WINAPI  _ecore_exe_win32_pipe_thread_read_cb(void *data);
96 static DWORD WINAPI  _ecore_exe_win32_pipe_thread_error_cb(void *data);
97 static Eina_Bool     _ecore_exe_close_cb(void *data, Ecore_Win32_Handler *wh);
98 static void          _ecore_exe_pipe_read_cb(void *data, void *buf, unsigned int size);
99 static int           _ecore_exe_pipe_write_cb(void *data, Ecore_Win32_Handler *wh);
100 static void          _ecore_exe_pipe_error_cb(void *data, void *buf, unsigned int size);
101
102 EAPI int ECORE_EXE_EVENT_ADD = 0;
103 EAPI int ECORE_EXE_EVENT_DEL = 0;
104 EAPI int ECORE_EXE_EVENT_DATA = 0;
105 EAPI int ECORE_EXE_EVENT_ERROR = 0;
106
107 void
108 _ecore_exe_init(void)
109 {
110    ECORE_EXE_EVENT_ADD = ecore_event_type_new();
111    ECORE_EXE_EVENT_DEL = ecore_event_type_new();
112    ECORE_EXE_EVENT_DATA = ecore_event_type_new();
113    ECORE_EXE_EVENT_ERROR = ecore_event_type_new();
114 }
115
116 void
117 _ecore_exe_shutdown(void)
118 {
119    while (exes)
120       ecore_exe_free(exes);
121 }
122
123 static int run_pri = NORMAL_PRIORITY_CLASS;
124
125 EAPI void
126 ecore_exe_run_priority_set(int pri)
127 {
128    switch (pri)
129      {
130      case ECORE_EXE_WIN32_PRIORITY_IDLE:
131        run_pri = IDLE_PRIORITY_CLASS;
132        break;
133      case ECORE_EXE_WIN32_PRIORITY_BELOW_NORMAL:
134        run_pri = BELOW_NORMAL_PRIORITY_CLASS;
135        break;
136      case ECORE_EXE_WIN32_PRIORITY_NORMAL:
137        run_pri = NORMAL_PRIORITY_CLASS;
138        break;
139      case ECORE_EXE_WIN32_PRIORITY_ABOVE_NORMAL:
140        run_pri = ABOVE_NORMAL_PRIORITY_CLASS;
141        break;
142      case ECORE_EXE_WIN32_PRIORITY_HIGH:
143        run_pri = HIGH_PRIORITY_CLASS;
144        break;
145      case ECORE_EXE_WIN32_PRIORITY_REALTIME:
146        run_pri = REALTIME_PRIORITY_CLASS;
147        break;
148      default:
149        break;
150      }
151 }
152
153 EAPI int
154 ecore_exe_run_priority_get(void)
155 {
156    switch (run_pri)
157      {
158      case IDLE_PRIORITY_CLASS:
159        return ECORE_EXE_WIN32_PRIORITY_IDLE;
160      case BELOW_NORMAL_PRIORITY_CLASS:
161        return ECORE_EXE_WIN32_PRIORITY_BELOW_NORMAL;
162      case NORMAL_PRIORITY_CLASS:
163        return ECORE_EXE_WIN32_PRIORITY_NORMAL;
164      case ABOVE_NORMAL_PRIORITY_CLASS:
165        return ECORE_EXE_WIN32_PRIORITY_ABOVE_NORMAL;
166      case HIGH_PRIORITY_CLASS:
167        return ECORE_EXE_WIN32_PRIORITY_HIGH;
168      case REALTIME_PRIORITY_CLASS:
169        return ECORE_EXE_WIN32_PRIORITY_REALTIME;
170        /* default should not be reached */
171      default:
172        return ECORE_EXE_WIN32_PRIORITY_NORMAL;
173      }
174 }
175
176 EAPI Ecore_Exe *
177 ecore_exe_run(const char *exe_cmd, const void *data)
178 {
179    return ecore_exe_pipe_run(exe_cmd, 0, data);
180 }
181
182 EAPI Ecore_Exe *
183 ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
184 {
185    STARTUPINFO          si;
186    PROCESS_INFORMATION  pi;
187    Ecore_Exe_Event_Add *e;
188    Ecore_Exe           *exe;
189    char                *ret = NULL;
190
191    exe = calloc(1, sizeof(Ecore_Exe));
192    if (!exe)
193      return NULL;
194
195    if ((flags & ECORE_EXE_PIPE_AUTO) && (!(flags & ECORE_EXE_PIPE_ERROR))
196        && (!(flags & ECORE_EXE_PIPE_READ)))
197      /* We need something to auto pipe. */
198      flags |= ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR;
199
200    exe->flags = flags;
201    if (exe->flags & ECORE_EXE_PIPE_READ)
202      if (!_ecore_exe_win32_pipes_set(exe))
203        goto free_exe;
204   
205    if (exe->flags & ECORE_EXE_PIPE_WRITE)
206      if (!_ecore_exe_win32_pipes_set(exe))
207        goto close_pipes;
208
209    if (exe->flags & ECORE_EXE_PIPE_ERROR)
210      if (!_ecore_exe_win32_pipes_set(exe))
211        goto close_pipes;
212
213    if ((exe->flags & ECORE_EXE_USE_SH) ||
214        ((ret = strrstr(exe_cmd, ".bat")) && (ret[4] == '\0')))
215      {
216         char buf[PATH_MAX];
217         snprintf(buf, PATH_MAX, "cmd.exe /c %s", exe_cmd);
218         exe->cmd = strdup(buf);
219      }
220    else
221      exe->cmd = strdup(exe_cmd);
222
223    if (!exe->cmd)
224      goto close_pipes;
225
226    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
227
228    ZeroMemory(&si, sizeof(STARTUPINFO));
229    si.cb = sizeof(STARTUPINFO);
230    si.hStdOutput = exe->pipe_read.child_pipe_x;
231    si.hStdInput = exe->pipe_write.child_pipe;
232    si.hStdError = exe->pipe_error.child_pipe_x;
233    si.dwFlags |= STARTF_USESTDHANDLES;
234
235    /* FIXME: gerer la priorite */
236
237    if (!CreateProcess(NULL, exe->cmd, NULL, NULL, EINA_TRUE,
238                       run_pri | CREATE_SUSPENDED, NULL, NULL, &si, &pi))
239      goto free_exe_cmd;
240
241    /* be sure that the child process is running */
242    /* FIXME: This does not work if the child is an EFL-based app */
243    /* if (WaitForInputIdle(pi.hProcess, INFINITE) == WAIT_FAILED) */
244    /*   goto free_exe_cmd; */
245
246    ECORE_MAGIC_SET(exe, ECORE_MAGIC_EXE);
247    exe->process = pi.hProcess;
248    exe->process_thread = pi.hThread;
249    exe->process_id = pi.dwProcessId;
250    exe->thread_id = pi.dwThreadId;
251    exe->data = (void *)data;
252
253    if (!(exe->process2 = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_SUSPEND_RESUME | PROCESS_TERMINATE | SYNCHRONIZE,
254                                      EINA_FALSE, pi.dwProcessId)))
255      goto close_thread;
256
257    exe->h_close = ecore_main_win32_handler_add(exe->process2, _ecore_exe_close_cb, exe);
258    if (!exe->h_close) goto close_process2;
259
260    if (ResumeThread(exe->process_thread) == ((DWORD)-1))
261      goto close_process2;
262
263    exes = (Ecore_Exe *)eina_inlist_append(EINA_INLIST_GET(exes), EINA_INLIST_GET(exe));
264
265    e = (Ecore_Exe_Event_Add *)calloc(1, sizeof(Ecore_Exe_Event_Add));
266    if (!e) goto delete_h_close;
267
268    e->exe = exe;
269    ecore_event_add(ECORE_EXE_EVENT_ADD, e,
270                    _ecore_exe_event_add_free, NULL);
271
272    return exe;
273
274  delete_h_close:
275    ecore_main_win32_handler_del(exe->h_close);
276  close_process2:
277    CloseHandle(exe->process2);
278  close_thread:
279    CloseHandle(exe->process_thread);
280    CloseHandle(exe->process);
281  free_exe_cmd:
282    free(exe->cmd);
283  close_pipes:
284    _ecore_exe_win32_pipes_close(exe);
285  free_exe:
286    free(exe);
287    return NULL;
288 }
289
290 EAPI void
291 ecore_exe_callback_pre_free_set(Ecore_Exe *exe, Ecore_Exe_Cb func)
292 {
293    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
294      {
295         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE,
296                          "ecore_exe_callback_pre_free_set");
297         return;
298      }
299    exe->pre_free_cb = func;
300 }
301
302 EAPI Eina_Bool
303 ecore_exe_send(Ecore_Exe *exe, const void *data, int size)
304 {
305    void *buf;
306
307    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
308      {
309         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_send");
310         return 0;
311      }
312
313    if (exe->close_stdin)
314      {
315         ERR("Ecore_Exe %p stdin is closed! Cannot send %d bytes from %p",
316             exe, size, data);
317         return 0;
318      }
319
320    if (!exe->pipe_write.child_pipe)
321      {
322         ERR("Ecore_Exe %p created without ECORE_EXE_PIPE_WRITE! "
323             "Cannot send %d bytes from %p", exe, size, data);
324         return 0;
325      }
326
327    buf = realloc(exe->pipe_write.data_buf, exe->pipe_write.data_size + size);
328    if (!buf) return 0;
329
330    exe->pipe_write.data_buf = buf;
331    memcpy((char *)exe->pipe_write.data_buf + exe->pipe_write.data_size, data, size);
332    exe->pipe_write.data_size += size;
333
334    /* if (exe->pipe_write.) */
335    /*    ecore_main_fd_handler_active_set(exe->pipe_write.h, ECORE_FD_WRITE); */
336
337    return 1;
338 }
339
340 EAPI void
341 ecore_exe_close_stdin(Ecore_Exe *exe)
342 {
343    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
344      {
345         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_close_stdin");
346         return;
347      }
348    exe->close_stdin = 1;
349 }
350
351 /* Not used on Windows */
352 EAPI void
353 ecore_exe_auto_limits_set(Ecore_Exe *exe __UNUSED__, int start_bytes __UNUSED__, int end_bytes __UNUSED__, int start_lines __UNUSED__, int end_lines __UNUSED__)
354 {
355 }
356
357 EAPI Ecore_Exe_Event_Data *
358 ecore_exe_event_data_get(Ecore_Exe *exe, Ecore_Exe_Flags flags)
359 {
360    Ecore_Exe_Event_Data *e = NULL;
361    unsigned char        *inbuf;
362    int                   inbuf_num;
363
364    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
365      {
366         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_event_data_get");
367         return NULL;
368      }
369
370    /* Sort out what sort of event we are, */
371    /* And get the data. */
372    if (flags & ECORE_EXE_PIPE_READ)
373      {
374         inbuf = exe->pipe_read.data_buf;
375         inbuf_num = exe->pipe_read.data_size;
376         exe->pipe_read.data_buf = NULL;
377         exe->pipe_read.data_size = 0;
378      }
379    else
380      {
381         inbuf = exe->pipe_error.data_buf;
382         inbuf_num = exe->pipe_error.data_size;
383         exe->pipe_error.data_buf = NULL;
384         exe->pipe_error.data_size = 0;
385      }
386
387    e = calloc(1, sizeof(Ecore_Exe_Event_Data));
388    if (e)
389      {
390         e->exe = exe;
391         e->data = inbuf;
392         e->size = inbuf_num;
393      }
394
395    return e;
396 }
397
398 EAPI void
399 ecore_exe_event_data_free(Ecore_Exe_Event_Data *e)
400 {
401    if (!e) return;
402    IF_FREE(e->lines);
403    IF_FREE(e->data);
404    free(e);
405 }
406
407 EAPI void *
408 ecore_exe_free(Ecore_Exe *exe)
409 {
410    void *data;
411
412    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
413      {
414         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_free");
415         return NULL;
416      }
417
418    data = exe->data;
419
420    if (exe->pre_free_cb)
421      exe->pre_free_cb(data, exe);
422
423    CloseHandle(exe->process2);
424    CloseHandle(exe->process_thread);
425    CloseHandle(exe->process);
426    free(exe->cmd);
427    _ecore_exe_win32_pipes_close(exe);
428    exes = (Ecore_Exe *)eina_inlist_remove(EINA_INLIST_GET(exes), EINA_INLIST_GET(exe));
429    ECORE_MAGIC_SET(exe, ECORE_MAGIC_NONE);
430    if (exe->tag) free(exe->tag);
431    free(exe);
432
433    return data;
434 }
435
436 EAPI pid_t
437 ecore_exe_pid_get(const Ecore_Exe *exe)
438 {
439    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
440      {
441         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_pid_get");
442         return -1;
443      }
444    return exe->process_id;
445 }
446
447 EAPI void
448 ecore_exe_tag_set(Ecore_Exe *exe, const char *tag)
449 {
450    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
451      {
452         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_tag_set");
453         return;
454      }
455    IF_FREE(exe->tag);
456    if (tag)
457       exe->tag = strdup(tag);
458 }
459
460 EAPI const char *
461 ecore_exe_tag_get(const Ecore_Exe *exe)
462 {
463    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
464      {
465         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_tag_get");
466         return NULL;
467      }
468    return exe->tag;
469 }
470
471 EAPI const char *
472 ecore_exe_cmd_get(const Ecore_Exe *exe)
473 {
474    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
475      {
476         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_cmd_get");
477         return NULL;
478      }
479    return exe->cmd;
480 }
481
482 EAPI void *
483 ecore_exe_data_get(const Ecore_Exe *exe)
484 {
485    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
486      {
487         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_data_get");
488         return NULL;
489      }
490    return exe->data;
491 }
492
493 EAPI Ecore_Exe_Flags
494 ecore_exe_flags_get(const Ecore_Exe *exe)
495 {
496    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
497      {
498         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_data_get");
499         return 0;
500      }
501    return exe->flags;
502 }
503
504 EAPI void
505 ecore_exe_pause(Ecore_Exe *exe)
506 {
507    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
508      {
509         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_pause");
510         return;
511      }
512
513    if (exe->is_suspended)
514      return;
515
516    if (SuspendThread(exe->process_thread) != (DWORD)-1)
517      exe->is_suspended = 1;
518 }
519
520 EAPI void
521 ecore_exe_continue(Ecore_Exe *exe)
522 {
523    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
524      {
525         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_continue");
526         return;
527      }
528
529    if (!exe->is_suspended)
530      return;
531
532    if (ResumeThread(exe->process_thread) != (DWORD)-1)
533      exe->is_suspended = 0;
534 }
535
536 EAPI void
537 ecore_exe_interrupt(Ecore_Exe *exe)
538 {
539    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
540      {
541         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_interrupt");
542         return;
543      }
544
545    CloseHandle(exe->process_thread);
546    CloseHandle(exe->process);
547    exe->sig = ECORE_EXE_WIN32_SIGINT;
548    while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe));
549 }
550
551 EAPI void
552 ecore_exe_quit(Ecore_Exe *exe)
553 {
554    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
555      {
556         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_quit");
557         return;
558      }
559
560    CloseHandle(exe->process_thread);
561    CloseHandle(exe->process);
562    exe->sig = ECORE_EXE_WIN32_SIGQUIT;
563    while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe));
564 }
565
566 EAPI void
567 ecore_exe_terminate(Ecore_Exe *exe)
568 {
569    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
570      {
571         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_terminate");
572         return;
573      }
574
575 /*    CloseHandle(exe->thread); */
576    CloseHandle(exe->process);
577    exe->sig = ECORE_EXE_WIN32_SIGTERM;
578    while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe));
579 }
580
581 EAPI void
582 ecore_exe_kill(Ecore_Exe *exe)
583 {
584    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
585      {
586         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_kill");
587         return;
588      }
589
590    CloseHandle(exe->process_thread);
591    CloseHandle(exe->process);
592    exe->sig = ECORE_EXE_WIN32_SIGKILL;
593    while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe));
594 }
595
596 EAPI void
597 ecore_exe_signal(Ecore_Exe *exe, int num __UNUSED__)
598 {
599    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
600      {
601         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_signal");
602         return;
603      }
604
605    /* does nothing */
606 }
607
608 EAPI void
609 ecore_exe_hup(Ecore_Exe *exe)
610 {
611    if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
612      {
613         ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_hup");
614         return;
615      }
616
617    /* does nothing */
618 }
619
620 /* FIXME: manage error mode */
621 static int
622 _ecore_exe_win32_pipe_thread_generic_cb(void *data, Ecore_Exe_Flags flags)
623 {
624 #define BUFSIZE 2048
625    char        buf[BUFSIZE];
626    Ecore_Exe  *exe;
627    char       *current_buf = NULL;
628    HANDLE      child_pipe;
629    Ecore_Pipe *ecore_pipe;
630    Ecore_Exe_Event_Data *event;
631    DWORD       size;
632    DWORD       current_size = 0;
633    BOOL res;
634
635    exe = (Ecore_Exe *)data;
636
637    /* Sort out what sort of handler we are. */
638    /* And get any left over data from last time. */
639    if ((exe->flags & ECORE_EXE_PIPE_READ) && (flags == ECORE_EXE_PIPE_READ))
640      {
641         child_pipe = exe->pipe_read.child_pipe;
642         ecore_pipe = exe->pipe_read.p;
643         flags = ECORE_EXE_PIPE_READ;
644      }
645    else if ((exe->flags & ECORE_EXE_PIPE_ERROR) && (flags == ECORE_EXE_PIPE_ERROR))
646      {
647         child_pipe = exe->pipe_error.child_pipe;
648         ecore_pipe = exe->pipe_error.p;
649         flags = ECORE_EXE_PIPE_ERROR;
650      }
651    else
652      return 0;
653
654    while (1)
655      {
656        if (!PeekNamedPipe(child_pipe, buf, sizeof(buf), &size, &current_size, NULL))
657           continue;
658         if (size == 0)
659           continue;
660         current_buf = (char *)malloc(current_size);
661         if (!current_buf)
662           continue;
663         res = ReadFile(child_pipe, current_buf, current_size, &size, NULL);
664         if (!res || (size == 0))
665           {
666              free(current_buf);
667              current_buf = NULL;
668              continue;
669           }
670         if (current_size != size)
671           {
672              free(current_buf);
673              current_buf = NULL;
674              continue;
675           }
676         current_size = size;
677
678         if (flags == ECORE_EXE_PIPE_READ)
679           {
680              exe->pipe_read.data_buf = current_buf;
681              exe->pipe_read.data_size = current_size;
682           }
683         else
684           {
685              exe->pipe_error.data_buf = current_buf;
686              exe->pipe_error.data_size = current_size;
687           }
688              
689         event = ecore_exe_event_data_get(exe, flags);
690         if (event)
691           ecore_pipe_write(ecore_pipe, &event, sizeof(event));
692
693         current_buf = NULL;
694         current_size = 0;
695      }
696
697    return 1;
698 }
699
700 static DWORD WINAPI
701 _ecore_exe_win32_pipe_thread_read_cb(void *data)
702 {
703   return _ecore_exe_win32_pipe_thread_generic_cb(data, ECORE_EXE_PIPE_READ);
704 }
705
706 static DWORD WINAPI
707 _ecore_exe_win32_pipe_thread_error_cb(void *data)
708 {
709   return _ecore_exe_win32_pipe_thread_generic_cb(data, ECORE_EXE_PIPE_ERROR);
710 }
711
712 static int
713 _ecore_exe_win32_pipes_set(Ecore_Exe *exe)
714 {
715    SECURITY_ATTRIBUTES sa;
716    HANDLE child_pipe;
717    HANDLE child_pipe_x;
718
719    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
720    sa.bInheritHandle = EINA_TRUE;
721    sa.lpSecurityDescriptor = NULL;
722
723    if (!CreatePipe(&child_pipe, &child_pipe_x, &sa, 0))
724      return 0;
725    if (exe->flags & ECORE_EXE_PIPE_WRITE)
726      {
727         if (!SetHandleInformation(child_pipe_x, HANDLE_FLAG_INHERIT, 0))
728           goto close_pipe;
729      }
730    else
731      {
732         if (!SetHandleInformation(child_pipe, HANDLE_FLAG_INHERIT, 0))
733           goto close_pipe;
734      }
735
736    if (exe->flags & ECORE_EXE_PIPE_READ)
737      {
738         exe->pipe_read.child_pipe = child_pipe;
739         exe->pipe_read.child_pipe_x = child_pipe_x;
740         exe->pipe_read.p = ecore_pipe_add(_ecore_exe_pipe_read_cb, exe);
741         exe->pipe_read.thread = CreateThread(NULL, 0,
742                                              _ecore_exe_win32_pipe_thread_read_cb,
743                                              exe, 0, NULL);
744      }
745    else if (exe->flags & ECORE_EXE_PIPE_WRITE)
746      {
747         exe->pipe_write.child_pipe = child_pipe;
748         exe->pipe_write.child_pipe_x = child_pipe_x;
749 /*         exe->pipe_write.thread = CreateThread(NULL, 0, */
750 /*                                              _ecore_exe_win32_pipe_thread_cb, */
751 /*                                              exe, 0, NULL); */
752      }
753    else
754      {
755         exe->pipe_error.child_pipe = child_pipe;
756         exe->pipe_error.child_pipe_x = child_pipe_x;
757         exe->pipe_error.p = ecore_pipe_add(_ecore_exe_pipe_error_cb, exe);
758         exe->pipe_error.thread = CreateThread(NULL, 0,
759                                              _ecore_exe_win32_pipe_thread_error_cb,
760                                              exe, 0, NULL);
761      }
762
763    return 1;
764
765  close_pipe:
766    CloseHandle(child_pipe);
767    CloseHandle(child_pipe_x);
768
769    return 0;
770 }
771
772 static void
773 _ecore_exe_win32_pipes_close(Ecore_Exe *exe)
774 {
775    if (exe->flags & ECORE_EXE_PIPE_READ)
776      {
777        if (exe->pipe_read.child_pipe)
778          {
779             CloseHandle(exe->pipe_read.child_pipe);
780             exe->pipe_read.child_pipe = NULL;
781          }
782        if (exe->pipe_read.child_pipe_x)
783          {
784            CloseHandle(exe->pipe_read.child_pipe_x);
785            exe->pipe_read.child_pipe_x = NULL;
786          }
787      }
788
789    if (exe->flags & ECORE_EXE_PIPE_WRITE)
790      {
791        if (exe->pipe_write.child_pipe)
792          {
793             CloseHandle(exe->pipe_write.child_pipe);
794             exe->pipe_write.child_pipe = NULL;
795          }
796        if (exe->pipe_write.child_pipe_x)
797          {
798            CloseHandle(exe->pipe_write.child_pipe_x);
799            exe->pipe_write.child_pipe_x = NULL;
800          }
801      }
802
803    if (exe->flags & ECORE_EXE_PIPE_ERROR)
804      {
805        if (exe->pipe_error.child_pipe)
806          {
807             CloseHandle(exe->pipe_error.child_pipe);
808             exe->pipe_error.child_pipe = NULL;
809          }
810        if (exe->pipe_error.child_pipe_x)
811          {
812            CloseHandle(exe->pipe_error.child_pipe_x);
813            exe->pipe_error.child_pipe_x = NULL;
814          }
815      }
816 }
817
818 static DWORD WINAPI
819 _ecore_exe_thread_procedure(LPVOID data __UNUSED__)
820 {
821    GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
822    GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0);
823    return 1;
824 }
825
826 static BOOL CALLBACK
827 _ecore_exe_enum_windows_procedure(HWND window, LPARAM data)
828 {
829    Ecore_Exe *exe;
830    DWORD      thread_id;
831
832    exe = (Ecore_Exe *)data;
833    thread_id = GetWindowThreadProcessId(window, NULL);
834
835    if (thread_id == exe->thread_id)
836      {
837         /* Ctrl-C or Ctrl-Break */
838         if (CreateRemoteThread(exe->process, NULL, 0,
839                                (LPTHREAD_START_ROUTINE)_ecore_exe_thread_procedure, NULL,
840                                0, NULL))
841           {
842             printf ("remote thread\n");
843             return EINA_FALSE;
844           }
845
846         if ((exe->sig == ECORE_EXE_WIN32_SIGINT) ||
847             (exe->sig == ECORE_EXE_WIN32_SIGQUIT))
848           {
849             printf ("int or quit\n");
850             return EINA_FALSE;
851           }
852
853         /* WM_CLOSE message */
854         PostMessage(window, WM_CLOSE, 0, 0);
855         if (WaitForSingleObject(exe->process, ECORE_EXE_WIN32_TIMEOUT) == WAIT_OBJECT_0)
856           {
857             printf ("CLOSE\n");
858             return EINA_FALSE;
859           }
860
861         /* WM_QUIT message */
862         PostMessage(window, WM_QUIT, 0, 0);
863         if (WaitForSingleObject(exe->process, ECORE_EXE_WIN32_TIMEOUT) == WAIT_OBJECT_0)
864           {
865             printf ("QUIT\n");
866             return EINA_FALSE;
867           }
868
869         /* Exit process */
870         if (CreateRemoteThread(exe->process, NULL, 0,
871                                (LPTHREAD_START_ROUTINE)ExitProcess, NULL,
872                                0, NULL))
873           {
874             printf ("remote thread 2\n");
875             return EINA_FALSE;
876           }
877
878         if (exe->sig == ECORE_EXE_WIN32_SIGTERM)
879           {
880             printf ("term\n");
881             return EINA_FALSE;
882           }
883
884         TerminateProcess(exe->process, 0);
885
886         return EINA_FALSE;
887      }
888
889    return EINA_TRUE;
890 }
891
892 static void
893 _ecore_exe_event_add_free(void *data __UNUSED__, void *ev)
894 {
895    Ecore_Exe_Event_Add *e;
896
897    e = (Ecore_Exe_Event_Add *)ev;
898    free(e);
899 }
900
901 static void
902 _ecore_exe_event_del_free(void *data __UNUSED__, void *ev)
903 {
904    Ecore_Exe_Event_Del *e;
905
906    e = (Ecore_Exe_Event_Del *)ev;
907    if (e->exe)
908      ecore_exe_free(e->exe);
909    free(e);
910 }
911
912 static void
913 _ecore_exe_event_exe_data_free(void *data __UNUSED__, void *ev)
914 {
915    Ecore_Exe_Event_Data *e;
916
917    e = (Ecore_Exe_Event_Data *)ev;
918    ecore_exe_event_data_free(e);
919 }
920
921 static Eina_Bool
922 _ecore_exe_close_cb(void *data, Ecore_Win32_Handler *wh __UNUSED__)
923 {
924    Ecore_Exe_Event_Del *e;
925    Ecore_Exe           *exe;
926    DWORD                exit_code = 0;
927
928    e = calloc(1, sizeof(Ecore_Exe_Event_Del));
929    if (!e) return 0;
930
931    exe = (Ecore_Exe *)data;
932
933    if (GetExitCodeProcess(exe->process2, &exit_code))
934      {
935         e->exit_code = exit_code;
936         e->exited = 1;
937      }
938    else
939      {
940         char *msg;
941
942         msg = evil_last_error_get();
943         printf("%s\n", msg);
944         free(msg);
945      }
946      e->pid = exe->process_id;
947      e->exe = exe;
948
949      ecore_event_add(ECORE_EXE_EVENT_DEL, e,
950                      _ecore_exe_event_del_free, NULL);
951      
952    return 0;
953 }
954
955 static void
956 _ecore_exe_pipe_read_cb(void *data, void *buf, unsigned int size)
957 {
958    Ecore_Exe_Event_Data *e;
959
960    e = *((Ecore_Exe_Event_Data **)buf);
961    if (e)
962      ecore_event_add(ECORE_EXE_EVENT_DATA, e,
963                      _ecore_exe_event_exe_data_free,
964                      NULL);
965 }
966
967 static int
968 _ecore_exe_pipe_write_cb(void *data, Ecore_Win32_Handler *wh __UNUSED__)
969 {
970    char       buf[READBUFSIZ];
971    Ecore_Exe *exe;
972    DWORD      num_exe;
973    BOOL       res;
974
975    exe = (Ecore_Exe *)data;
976
977    res = WriteFile(exe->pipe_write.child_pipe_x, buf, READBUFSIZ, &num_exe, NULL);
978    if (!res || num_exe == 0)
979      {
980        /* FIXME: what to do here ?? */
981      }
982
983    if (exe->close_stdin == 1)
984      {
985         if (exe->pipe_write.h)
986           {
987              ecore_main_win32_handler_del(exe->pipe_write.h);
988              exe->pipe_write.h = NULL;
989           }
990         exe->pipe_write.h = NULL;
991         CloseHandle(exe->pipe_write.child_pipe);
992         exe->pipe_write.child_pipe = NULL;
993      }
994
995    return 1;
996 }
997
998 static void
999 _ecore_exe_pipe_error_cb(void *data, void *buf, unsigned int size)
1000 {
1001    Ecore_Exe_Event_Data *e;
1002
1003    e = *((Ecore_Exe_Event_Data **)buf);
1004    if (e)
1005      ecore_event_add(ECORE_EXE_EVENT_ERROR, e,
1006                      _ecore_exe_event_exe_data_free,
1007                      NULL);
1008 }