Sys.Signals module for a Variant type of signals (and a set_signal function that...
[ocaml.git] / stdlib / headernt.c
blobc8d23ee256fbb7132435b657ec0ba4cd4c82a75f
1 /***********************************************************************/
2 /* */
3 /* Objective Caml */
4 /* */
5 /* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
6 /* */
7 /* Copyright 1998 Institut National de Recherche en Informatique et */
8 /* en Automatique. All rights reserved. This file is distributed */
9 /* under the terms of the GNU Library General Public License, with */
10 /* the special exception on linking described in file ../LICENSE. */
11 /* */
12 /***********************************************************************/
14 /* $Id$ */
16 #define STRICT
17 #define WIN32_LEAN_AND_MEAN
19 #include <windows.h>
20 #include "mlvalues.h"
21 #include "exec.h"
23 #ifndef __MINGW32__
24 #pragma comment(linker , "/entry:headerentry")
25 #pragma comment(linker , "/subsystem:console")
26 #pragma comment(lib , "kernel32")
27 #endif
29 char * default_runtime_name = "ocamlrun";
31 static
32 #if _MSC_VER >= 1200
33 __forceinline
34 #else
35 __inline
36 #endif
37 unsigned long read_size(const char * const ptr)
39 const unsigned char * const p = (const unsigned char * const) ptr;
40 return ((unsigned long) p[0] << 24) | ((unsigned long) p[1] << 16) |
41 ((unsigned long) p[2] << 8) | p[3];
44 static __inline char * read_runtime_path(HANDLE h)
46 char buffer[TRAILER_SIZE];
47 static char runtime_path[MAX_PATH];
48 DWORD nread;
49 int num_sections, path_size, i;
50 long ofs;
52 if (SetFilePointer(h, -TRAILER_SIZE, NULL, FILE_END) == -1) return NULL;
53 if (! ReadFile(h, buffer, TRAILER_SIZE, &nread, NULL)) return NULL;
54 if (nread != TRAILER_SIZE) return NULL;
55 num_sections = read_size(buffer);
56 ofs = TRAILER_SIZE + num_sections * 8;
57 if (SetFilePointer(h, - ofs, NULL, FILE_END) == -1) return NULL;
58 path_size = 0;
59 for (i = 0; i < num_sections; i++) {
60 if (! ReadFile(h, buffer, 8, &nread, NULL) || nread != 8) return NULL;
61 if (buffer[0] == 'R' && buffer[1] == 'N' &&
62 buffer[2] == 'T' && buffer[3] == 'M') {
63 path_size = read_size(buffer + 4);
64 ofs += path_size;
65 } else if (path_size > 0)
66 ofs += read_size(buffer + 4);
68 if (path_size == 0) return default_runtime_name;
69 if (path_size >= MAX_PATH) return NULL;
70 if (SetFilePointer(h, -ofs, NULL, FILE_END) == -1) return NULL;
71 if (! ReadFile(h, runtime_path, path_size, &nread, NULL)) return NULL;
72 if (nread != path_size) return NULL;
73 runtime_path[path_size - 1] = 0;
74 return runtime_path;
77 static BOOL WINAPI ctrl_handler(DWORD event)
79 if (event == CTRL_C_EVENT || event == CTRL_BREAK_EVENT)
80 return TRUE; /* pretend we've handled them */
81 else
82 return FALSE;
85 #define msg_and_length(msg) msg , (sizeof(msg) - 1)
87 static __inline void __declspec(noreturn) run_runtime(char * runtime,
88 char * const cmdline)
90 char path[MAX_PATH];
91 STARTUPINFO stinfo;
92 PROCESS_INFORMATION procinfo;
93 DWORD retcode;
94 if (SearchPath(NULL, runtime, ".exe", MAX_PATH, path, &runtime) == 0) {
95 HANDLE errh;
96 DWORD numwritten;
97 errh = GetStdHandle(STD_ERROR_HANDLE);
98 WriteFile(errh, msg_and_length("Cannot exec "), &numwritten, NULL);
99 WriteFile(errh, runtime, strlen(runtime), &numwritten, NULL);
100 WriteFile(errh, msg_and_length("\r\n"), &numwritten, NULL);
101 ExitProcess(2);
102 #if _MSC_VER >= 1200
103 __assume(0); /* Not reached */
104 #endif
106 /* Need to ignore ctrl-C and ctrl-break, otherwise we'll die and take
107 the underlying OCaml program with us! */
108 SetConsoleCtrlHandler(ctrl_handler, TRUE);
110 stinfo.cb = sizeof(stinfo);
111 stinfo.lpReserved = NULL;
112 stinfo.lpDesktop = NULL;
113 stinfo.lpTitle = NULL;
114 stinfo.dwFlags = 0;
115 stinfo.cbReserved2 = 0;
116 stinfo.lpReserved2 = NULL;
117 if (!CreateProcess(path, cmdline, NULL, NULL, TRUE, 0, NULL, NULL,
118 &stinfo, &procinfo)) {
119 HANDLE errh;
120 DWORD numwritten;
121 errh = GetStdHandle(STD_ERROR_HANDLE);
122 WriteFile(errh, msg_and_length("Cannot exec "), &numwritten, NULL);
123 WriteFile(errh, runtime, strlen(runtime), &numwritten, NULL);
124 WriteFile(errh, msg_and_length("\r\n"), &numwritten, NULL);
125 ExitProcess(2);
126 #if _MSC_VER >= 1200
127 __assume(0); /* Not reached */
128 #endif
130 CloseHandle(procinfo.hThread);
131 WaitForSingleObject(procinfo.hProcess , INFINITE);
132 GetExitCodeProcess(procinfo.hProcess , &retcode);
133 CloseHandle(procinfo.hProcess);
134 ExitProcess(retcode);
135 #if _MSC_VER >= 1200
136 __assume(0); /* Not reached */
137 #endif
140 #ifdef __MINGW32__
141 int main()
142 #else
143 void __declspec(noreturn) __cdecl headerentry()
144 #endif
146 char truename[MAX_PATH];
147 char * cmdline = GetCommandLine();
148 char * runtime_path;
149 HANDLE h;
151 GetModuleFileName(NULL, truename, sizeof(truename));
152 h = CreateFile(truename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
153 NULL, OPEN_EXISTING, 0, NULL);
154 if (h == INVALID_HANDLE_VALUE ||
155 (runtime_path = read_runtime_path(h)) == NULL) {
156 HANDLE errh;
157 DWORD numwritten;
158 errh = GetStdHandle(STD_ERROR_HANDLE);
159 WriteFile(errh, truename, strlen(truename), &numwritten, NULL);
160 WriteFile(errh, msg_and_length(" not found or is not a bytecode executable file\r\n"),
161 &numwritten, NULL);
162 ExitProcess(2);
163 #if _MSC_VER >= 1200
164 __assume(0); /* Not reached */
165 #endif
167 CloseHandle(h);
168 run_runtime(runtime_path , cmdline);
169 #if _MSC_VER >= 1200
170 __assume(0); /* Not reached */
171 #endif
172 #ifdef __MINGW32__
173 return 0;
174 #endif