1 #include "rktio.h"
2 #include "rktio_private.h"
3 
4 #define rktio_SHOW_CONVERT(v) case RKTIO_ ## v: show_mode = v; break
5 
rktio_shell_execute(rktio_t * rktio,const char * verb,const char * target,const char * arg,const char * dir,int show_mode)6 rktio_ok_t rktio_shell_execute(rktio_t *rktio,
7 			       const char *verb,
8 			       const char *target,
9 			       const char *arg,
10 			       const char *dir,
11 			       int show_mode)
12 /* dir needs to have normalized path separators */
13 {
14 #ifdef RKTIO_SYSTEM_WINDOWS
15   SHELLEXECUTEINFOW se;
16   int ok, r;
17 
18   switch(show_mode) {
19     rktio_SHOW_CONVERT(SW_HIDE);
20     rktio_SHOW_CONVERT(SW_MAXIMIZE);
21     rktio_SHOW_CONVERT(SW_MINIMIZE);
22     rktio_SHOW_CONVERT(SW_RESTORE);
23     rktio_SHOW_CONVERT(SW_SHOW);
24     rktio_SHOW_CONVERT(SW_SHOWDEFAULT);
25     rktio_SHOW_CONVERT(SW_SHOWMAXIMIZED);
26     rktio_SHOW_CONVERT(SW_SHOWMINIMIZED);
27     rktio_SHOW_CONVERT(SW_SHOWMINNOACTIVE);
28     rktio_SHOW_CONVERT(SW_SHOWNA);
29     rktio_SHOW_CONVERT(SW_SHOWNOACTIVATE);
30     rktio_SHOW_CONVERT(SW_SHOWNORMAL);
31   }
32 
33   memset(&se, 0, sizeof(se));
34   se.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT;
35   se.cbSize = sizeof(se);
36   if (!verb)
37     se.lpVerb = NULL;
38   else
39     se.lpVerb = WIDE_PATH_copy(verb);
40   se.lpFile = WIDE_PATH_copy(target);
41   se.lpParameters = WIDE_PATH_copy(arg);
42   se.lpDirectory = WIDE_PATH_copy(dir);
43   se.nShow = show_mode;
44   se.hwnd = NULL;
45 
46   r = (int)(intptr_t)ShellExecuteW(se.hwnd, se.lpVerb, se.lpFile, se.lpParameters,
47 				   se.lpDirectory, se.nShow);
48 
49   ok = (r > 32);
50 
51   if (!ok) {
52     switch(r) {
53     case ERROR_FILE_NOT_FOUND:
54     case ERROR_PATH_NOT_FOUND:
55     case ERROR_BAD_FORMAT:
56       set_windows_error(r);
57       break;
58     default:
59       /* Other results are not Windows error codes,
60 	 so just collapse them to a Racket error */
61       set_racket_error(RKTIO_ERROR_SHELL_EXECUTE_FAILED);
62       break;
63     }
64   }
65 
66   if (se.lpVerb) free((char *)se.lpVerb);
67   free((char *)se.lpFile);
68   free((char *)se.lpParameters);
69   free((char *)se.lpDirectory);
70 
71   return ok;
72 #else
73   set_racket_error(RKTIO_ERROR_UNSUPPORTED);
74   return 0;
75 #endif
76 }
77