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