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