]> gitweb.factorcode.org Git - factor.git/blob - vm/os-windows.c
Merge branch 'master' into experimental
[factor.git] / vm / os-windows.c
1 #include "master.h"
2
3 F_STRING *get_error_message(void)
4 {
5         DWORD id = GetLastError();
6         F_CHAR *msg = error_message(id);
7         F_STRING *string = from_u16_string(msg);
8         LocalFree(msg);
9         return string;
10 }
11
12 /* You must LocalFree() the return value! */
13 F_CHAR *error_message(DWORD id)
14 {
15         F_CHAR *buffer;
16         int index;
17
18         DWORD ret = FormatMessage(
19                 FORMAT_MESSAGE_ALLOCATE_BUFFER |
20                 FORMAT_MESSAGE_FROM_SYSTEM,
21                 NULL,
22                 id,
23                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
24                 (LPTSTR)(void *) &buffer,
25                 0, NULL);
26         if(ret == 0)
27                 return error_message(GetLastError());
28
29         /* strip whitespace from end */
30         index = wcslen(buffer) - 1;
31         while(index >= 0 && isspace(buffer[index]))
32                 buffer[index--] = 0;
33
34         return buffer;
35 }
36
37 HMODULE hFactorDll;
38
39 void init_ffi(void)
40 {
41         hFactorDll = GetModuleHandle(FACTOR_DLL);
42         if(!hFactorDll)
43                 fatal_error("GetModuleHandle(\"" FACTOR_DLL_NAME "\") failed", 0);
44 }
45
46 void ffi_dlopen(F_DLL *dll)
47 {
48         dll->dll = LoadLibraryEx(alien_offset(dll->path), NULL, 0);
49 }
50
51 void *ffi_dlsym(F_DLL *dll, F_SYMBOL *symbol)
52 {
53         return GetProcAddress(dll ? (HMODULE)dll->dll : hFactorDll, symbol);
54 }
55
56 void ffi_dlclose(F_DLL *dll)
57 {
58         FreeLibrary((HMODULE)dll->dll);
59         dll->dll = NULL;
60 }
61
62 bool windows_stat(F_CHAR *path)
63 {
64         BY_HANDLE_FILE_INFORMATION bhfi;
65         HANDLE h = CreateFileW(path,
66                         GENERIC_READ,
67                         FILE_SHARE_READ,
68                         NULL,
69                         OPEN_EXISTING,
70                         FILE_FLAG_BACKUP_SEMANTICS,
71                         NULL);
72
73         if(h == INVALID_HANDLE_VALUE)
74         {
75                 // FindFirstFile is the only call that can stat c:\pagefile.sys
76                 WIN32_FIND_DATA st;
77                 HANDLE h;
78
79                 if(INVALID_HANDLE_VALUE == (h = FindFirstFile(path, &st)))
80                         return false;
81                 FindClose(h);
82                 return true;
83         }
84         bool ret;
85         ret = GetFileInformationByHandle(h, &bhfi);
86         CloseHandle(h);
87         return ret;
88 }
89
90 void windows_image_path(F_CHAR *full_path, F_CHAR *temp_path, unsigned int length)
91 {
92         snwprintf(temp_path, length-1, L"%s.image", full_path); 
93         temp_path[sizeof(temp_path) - 1] = 0;
94 }
95
96 /* You must free() this yourself. */
97 const F_CHAR *default_image_path(void)
98 {
99         F_CHAR full_path[MAX_UNICODE_PATH];
100         F_CHAR *ptr;
101         F_CHAR temp_path[MAX_UNICODE_PATH];
102
103         if(!GetModuleFileName(NULL, full_path, MAX_UNICODE_PATH))
104                 fatal_error("GetModuleFileName() failed", 0);
105
106         if((ptr = wcsrchr(full_path, '.')))
107                 *ptr = 0;
108
109         snwprintf(temp_path, sizeof(temp_path)-1, L"%s.image", full_path); 
110         temp_path[sizeof(temp_path) - 1] = 0;
111
112         if(!windows_stat(temp_path)) {
113                 unsigned int len = wcslen(full_path);
114                 F_CHAR magic[] = L"-console";
115                 unsigned int magic_len = wcslen(magic);
116
117                 if(!wcsncmp(full_path + len - magic_len, magic, MIN(len, magic_len)))
118                         full_path[len - magic_len] = 0;
119                 snwprintf(temp_path, sizeof(temp_path)-1, L"%s.image", full_path); 
120                 temp_path[sizeof(temp_path) - 1] = 0;
121         }
122
123         return safe_strdup(temp_path);
124 }
125
126 /* You must free() this yourself. */
127 const F_CHAR *vm_executable_path(void)
128 {
129         F_CHAR full_path[MAX_UNICODE_PATH];
130         if(!GetModuleFileName(NULL, full_path, MAX_UNICODE_PATH))
131                 fatal_error("GetModuleFileName() failed", 0);
132         return safe_strdup(full_path);
133 }
134
135
136 void primitive_existsp(void)
137 {
138
139         F_CHAR *path = unbox_u16_string();
140         box_boolean(windows_stat(path));
141 }
142
143 F_SEGMENT *alloc_segment(CELL size)
144 {
145         char *mem;
146         DWORD ignore;
147
148         if((mem = (char *)VirtualAlloc(NULL, getpagesize() * 2 + size,
149                 MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == 0)
150                 out_of_memory();
151
152         if (!VirtualProtect(mem, getpagesize(), PAGE_NOACCESS, &ignore))
153                 fatal_error("Cannot allocate low guard page", (CELL)mem);
154
155         if (!VirtualProtect(mem + size + getpagesize(),
156                 getpagesize(), PAGE_NOACCESS, &ignore))
157                 fatal_error("Cannot allocate high guard page", (CELL)mem);
158
159         F_SEGMENT *block = safe_malloc(sizeof(F_SEGMENT));
160
161         block->start = (CELL)mem + getpagesize();
162         block->size = size;
163         block->end = block->start + size;
164
165         return block;
166 }
167
168 void dealloc_segment(F_SEGMENT *block)
169 {
170         SYSTEM_INFO si;
171         GetSystemInfo(&si);
172         if(!VirtualFree((void*)(block->start - si.dwPageSize), 0, MEM_RELEASE))
173                 fatal_error("dealloc_segment failed",0);
174         free(block);
175 }
176
177 long getpagesize(void)
178 {
179         static long g_pagesize = 0;
180         if (! g_pagesize)
181         {
182                 SYSTEM_INFO system_info;
183                 GetSystemInfo (&system_info);
184                 g_pagesize = system_info.dwPageSize;
185         }
186         return g_pagesize;
187 }
188
189 void sleep_micros(u64 usec)
190 {
191         Sleep((DWORD)(usec / 1000));
192 }