]> gitweb.factorcode.org Git - factor.git/blob - vm/os-windows.cpp
ab55beacdbb26e59cab0cedef927458f64953fb0
[factor.git] / vm / os-windows.cpp
1 #include "master.hpp"
2
3 namespace factor
4 {
5
6 HMODULE hFactorDll;
7
8 void factor_vm::init_ffi()
9 {
10         hFactorDll = GetModuleHandle(FACTOR_DLL);
11         if(!hFactorDll)
12                 fatal_error("GetModuleHandle() failed", 0);
13 }
14
15 void factor_vm::ffi_dlopen(dll *dll)
16 {
17         dll->handle = LoadLibraryEx((WCHAR *)alien_offset(dll->path), NULL, 0);
18 }
19
20 void *factor_vm::ffi_dlsym(dll *dll, symbol_char *symbol)
21 {
22         return (void *)GetProcAddress(dll ? (HMODULE)dll->handle : hFactorDll, symbol);
23 }
24
25 void factor_vm::ffi_dlclose(dll *dll)
26 {
27         FreeLibrary((HMODULE)dll->handle);
28         dll->handle = NULL;
29 }
30
31 BOOL factor_vm::windows_stat(vm_char *path)
32 {
33         BY_HANDLE_FILE_INFORMATION bhfi;
34         HANDLE h = CreateFileW(path,
35                         GENERIC_READ,
36                         FILE_SHARE_READ,
37                         NULL,
38                         OPEN_EXISTING,
39                         FILE_FLAG_BACKUP_SEMANTICS,
40                         NULL);
41
42         if(h == INVALID_HANDLE_VALUE)
43         {
44                 // FindFirstFile is the only call that can stat c:\pagefile.sys
45                 WIN32_FIND_DATA st;
46                 HANDLE h;
47
48                 if(INVALID_HANDLE_VALUE == (h = FindFirstFile(path, &st)))
49                         return false;
50                 FindClose(h);
51                 return true;
52         }
53         BOOL ret = GetFileInformationByHandle(h, &bhfi);
54         CloseHandle(h);
55         return ret;
56 }
57
58 void factor_vm::windows_image_path(vm_char *full_path, vm_char *temp_path, unsigned int length)
59 {
60         SNWPRINTF(temp_path, length-1, L"%s.image", full_path); 
61         temp_path[length - 1] = 0;
62 }
63
64 /* You must free() this yourself. */
65 const vm_char *factor_vm::default_image_path()
66 {
67         vm_char full_path[MAX_UNICODE_PATH];
68         vm_char *ptr;
69         vm_char temp_path[MAX_UNICODE_PATH];
70
71         if(!GetModuleFileName(NULL, full_path, MAX_UNICODE_PATH))
72                 fatal_error("GetModuleFileName() failed", 0);
73
74         if((ptr = wcsrchr(full_path, '.')))
75                 *ptr = 0;
76
77         SNWPRINTF(temp_path, MAX_UNICODE_PATH-1, L"%s.image", full_path); 
78         temp_path[MAX_UNICODE_PATH - 1] = 0;
79
80         return safe_strdup(temp_path);
81 }
82
83 /* You must free() this yourself. */
84 const vm_char *factor_vm::vm_executable_path()
85 {
86         vm_char full_path[MAX_UNICODE_PATH];
87         if(!GetModuleFileName(NULL, full_path, MAX_UNICODE_PATH))
88                 fatal_error("GetModuleFileName() failed", 0);
89         return safe_strdup(full_path);
90 }
91
92 void factor_vm::primitive_existsp()
93 {
94         vm_char *path = untag_check<byte_array>(ctx->pop())->data<vm_char>();
95         ctx->push(tag_boolean(windows_stat(path)));
96 }
97
98 segment::segment(cell size_, bool executable_p)
99 {
100         size = size_;
101
102         char *mem;
103         DWORD ignore;
104
105         if((mem = (char *)VirtualAlloc(NULL, getpagesize() * 2 + size,
106                 MEM_COMMIT, executable_p ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE)) == 0)
107                 out_of_memory();
108
109         if (!VirtualProtect(mem, getpagesize(), PAGE_NOACCESS, &ignore))
110                 fatal_error("Cannot allocate low guard page", (cell)mem);
111
112         if (!VirtualProtect(mem + size + getpagesize(),
113                 getpagesize(), PAGE_NOACCESS, &ignore))
114                 fatal_error("Cannot allocate high guard page", (cell)mem);
115
116         start = (cell)mem + getpagesize();
117         end = start + size;
118 }
119
120 segment::~segment()
121 {
122         SYSTEM_INFO si;
123         GetSystemInfo(&si);
124         if(!VirtualFree((void*)(start - si.dwPageSize), 0, MEM_RELEASE))
125                 fatal_error("Segment deallocation failed",0);
126 }
127
128 long getpagesize()
129 {
130         static long g_pagesize = 0;
131         if (! g_pagesize)
132         {
133                 SYSTEM_INFO system_info;
134                 GetSystemInfo (&system_info);
135                 g_pagesize = system_info.dwPageSize;
136         }
137         return g_pagesize;
138 }
139
140 /* 
141         Windows argument parsing ported to work on
142         int main(int argc, wchar_t **argv).
143
144         Based on MinGW's public domain char** version.
145
146         Used by WinMain() implementation in main-windows-ce.cpp
147         and main-windows-nt.cpp.
148
149 */
150
151 VM_C_API int parse_tokens(wchar_t *string, wchar_t ***tokens, int length)
152 {
153         /* Extract whitespace- and quotes- delimited tokens from the given string
154            and put them into the tokens array. Returns number of tokens
155            extracted. Length specifies the current size of tokens[].
156            THIS METHOD MODIFIES string.  */
157
158         const wchar_t *whitespace = L" \t\r\n";
159         wchar_t *tokenEnd = 0;
160         const wchar_t *quoteCharacters = L"\"\'";
161         wchar_t *end = string + wcslen(string);
162
163         if (string == NULL)
164                 return length;
165
166         while (1)
167         {
168                 const wchar_t *q;
169                 /* Skip over initial whitespace.  */
170                 string += wcsspn(string, whitespace);
171                 if (*string == '\0')
172                         break;
173
174                 for (q = quoteCharacters; *q; ++q)
175                 {
176                         if (*string == *q)
177                                 break;
178                 }
179                 if (*q)
180                 {
181                         /* Token is quoted.  */
182                         wchar_t quote = *string++;
183                         tokenEnd = wcschr(string, quote);
184                         /* If there is no endquote, the token is the rest of the string.  */
185                         if (!tokenEnd)
186                                 tokenEnd = end;
187                 }
188                 else
189                 {
190                         tokenEnd = string + wcscspn(string, whitespace);
191                 }
192
193                 *tokenEnd = '\0';
194
195                 {
196                         wchar_t **new_tokens;
197                         int newlen = length + 1;
198                         new_tokens = (wchar_t **)realloc (*tokens, sizeof (wchar_t**) * newlen);
199                         if (!new_tokens)
200                         {
201                                 /* Out of memory.  */
202                                 return -1;
203                         }
204
205                         *tokens = new_tokens;
206                         (*tokens)[length] = string;
207                         length = newlen;
208                 }
209                 if (tokenEnd == end)
210                         break;
211                 string = tokenEnd + 1;
212         }
213         return length;
214 }
215
216 VM_C_API void parse_args(int *argc, wchar_t ***argv, wchar_t *cmdlinePtrW)
217 {
218         int cmdlineLen = 0;
219
220         if (!cmdlinePtrW)
221                 cmdlineLen = 0;
222         else
223                 cmdlineLen = wcslen(cmdlinePtrW);
224
225         /* gets realloc()'d later */
226         *argc = 0;
227         *argv = (wchar_t **)malloc (sizeof (wchar_t**));
228
229         if (!*argv)
230                 ExitProcess(1);
231
232 #ifdef WINCE
233         wchar_t cmdnameBufW[MAX_UNICODE_PATH];
234
235         /* argv[0] is the path of invoked program - get this from CE.  */
236         cmdnameBufW[0] = 0;
237         GetModuleFileNameW(NULL, cmdnameBufW, sizeof (cmdnameBufW)/sizeof (cmdnameBufW[0]));
238
239         (*argv)[0] = wcsdup(cmdnameBufW);
240         if(!(*argv[0]))
241                 ExitProcess(1);
242         /* Add one to account for argv[0] */
243         (*argc)++;
244 #endif
245
246         if (cmdlineLen > 0)
247         {
248                 wchar_t *argv1 = wcsdup(cmdlinePtrW);
249                 if(!argv1)
250                         ExitProcess(1);
251                 *argc = parse_tokens(argv1, argv, *argc);
252                 if (*argc < 0)
253                         ExitProcess(1);
254         }
255         (*argv)[*argc] = 0;
256         return;
257 }
258
259 }