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