aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/ecore/src/lib/ecore/ecore_exe_win32.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/ecore/src/lib/ecore/ecore_exe_win32.c')
-rw-r--r--libraries/ecore/src/lib/ecore/ecore_exe_win32.c1055
1 files changed, 1055 insertions, 0 deletions
diff --git a/libraries/ecore/src/lib/ecore/ecore_exe_win32.c b/libraries/ecore/src/lib/ecore/ecore_exe_win32.c
new file mode 100644
index 0000000..1f5cb4e
--- /dev/null
+++ b/libraries/ecore/src/lib/ecore/ecore_exe_win32.c
@@ -0,0 +1,1055 @@
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
27typedef 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
35struct _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
84static Ecore_Exe *exes = NULL;
85
86static int _ecore_exe_win32_pipes_set(Ecore_Exe *exe);
87static void _ecore_exe_win32_pipes_close(Ecore_Exe *exe);
88
89static BOOL CALLBACK _ecore_exe_enum_windows_procedure(HWND window,
90 LPARAM data);
91static void _ecore_exe_event_add_free(void *data,
92 void *ev);
93static void _ecore_exe_event_del_free(void *data,
94 void *ev);
95static void _ecore_exe_event_exe_data_free(void *data,
96 void *ev);
97static int _ecore_exe_win32_pipe_thread_generic_cb(void *data,
98 Ecore_Exe_Flags flags);
99static DWORD WINAPI _ecore_exe_win32_pipe_thread_read_cb(void *data);
100static DWORD WINAPI _ecore_exe_win32_pipe_thread_error_cb(void *data);
101static Eina_Bool _ecore_exe_close_cb(void *data,
102 Ecore_Win32_Handler *wh);
103static void _ecore_exe_pipe_read_cb(void *data,
104 void *buf,
105 unsigned int size);
106static int _ecore_exe_pipe_write_cb(void *data,
107 Ecore_Win32_Handler *wh);
108static void _ecore_exe_pipe_error_cb(void *data,
109 void *buf,
110 unsigned int size);
111
112EAPI int ECORE_EXE_EVENT_ADD = 0;
113EAPI int ECORE_EXE_EVENT_DEL = 0;
114EAPI int ECORE_EXE_EVENT_DATA = 0;
115EAPI int ECORE_EXE_EVENT_ERROR = 0;
116
117void
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
126void
127_ecore_exe_shutdown(void)
128{
129 while (exes)
130 ecore_exe_free(exes);
131}
132
133static int run_pri = NORMAL_PRIORITY_CLASS;
134
135EAPI void
136ecore_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
169EAPI int
170ecore_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
198EAPI Ecore_Exe *
199ecore_exe_run(const char *exe_cmd,
200 const void *data)
201{
202 return ecore_exe_pipe_run(exe_cmd, 0, data);
203}
204
205EAPI Ecore_Exe *
206ecore_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
299delete_h_close:
300 ecore_main_win32_handler_del(exe->h_close);
301close_process2:
302 CloseHandle(exe->process2);
303close_thread:
304 CloseHandle(exe->process_thread);
305 CloseHandle(exe->process);
306free_exe_cmd:
307 free(exe->cmd);
308close_pipes:
309 _ecore_exe_win32_pipes_close(exe);
310free_exe:
311 free(exe);
312 return NULL;
313}
314
315EAPI void
316ecore_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
328EAPI Eina_Bool
329ecore_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
368EAPI void
369ecore_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 */
380EAPI void
381ecore_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
389EAPI Ecore_Exe_Event_Data *
390ecore_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
431EAPI void
432ecore_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
440EAPI void *
441ecore_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
469EAPI pid_t
470ecore_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
480EAPI void
481ecore_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
494EAPI const char *
495ecore_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
505EAPI const char *
506ecore_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
516EAPI void *
517ecore_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
527EAPI Ecore_Exe_Flags
528ecore_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
538EAPI void
539ecore_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
554EAPI void
555ecore_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
570EAPI void
571ecore_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
585EAPI void
586ecore_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
600EAPI void
601ecore_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
615EAPI void
616ecore_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
630EAPI void
631ecore_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
643EAPI void
644ecore_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 */
656static 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
736static 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
742static 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
748static 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
801close_pipe:
802 CloseHandle(child_pipe);
803 CloseHandle(child_pipe_x);
804
805 return 0;
806}
807
808static 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
854static 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
862static 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
929static 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
939static 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
951static 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
961static 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
996static 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
1010static 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
1042static 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