factor/vm/os-windows.c

238 lines
4.5 KiB
C
Raw Normal View History

2006-08-03 14:40:13 -04:00
#include "factor.h"
F_STRING *get_error_message()
{
DWORD id = GetLastError();
2006-11-02 21:28:44 -05:00
char *msg = error_message(id);
F_STRING *string = from_char_string(msg);
LocalFree(msg);
return string;
2006-08-03 14:40:13 -04:00
}
2006-11-02 21:28:44 -05:00
/* You must LocalFree() the return value! */
2006-08-03 14:40:13 -04:00
char *error_message(DWORD id)
{
char *buffer;
int index;
2006-10-31 15:48:34 -05:00
2006-08-03 14:40:13 -04:00
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
id,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &buffer,
0, NULL);
/* strip whitespace from end */
index = strlen(buffer) - 1;
while(index >= 0 && isspace(buffer[index]))
buffer[index--] = 0;
2006-10-31 15:48:34 -05:00
2006-11-02 21:28:44 -05:00
return buffer;
2006-08-03 14:40:13 -04:00
}
s64 current_millis(void)
{
FILETIME t;
GetSystemTimeAsFileTime(&t);
2006-11-02 21:28:44 -05:00
return (((s64)t.dwLowDateTime | (s64)t.dwHighDateTime<<32)
- EPOCH_OFFSET) / 10000;
2006-08-03 14:40:13 -04:00
}
2006-11-04 11:52:57 -05:00
void ffi_dlopen (F_DLL *dll, bool error)
2006-08-03 14:40:13 -04:00
{
2006-11-02 18:29:11 -05:00
HMODULE module = LoadLibrary(alien_offset(dll->path));
2006-08-03 14:40:13 -04:00
if (!module)
{
dll->dll = NULL;
if(error)
2006-10-18 17:16:37 -04:00
general_error(ERROR_FFI, F, tag_object(get_error_message()),true);
2006-08-03 14:40:13 -04:00
else
return;
}
dll->dll = module;
}
2006-11-04 11:52:57 -05:00
void *ffi_dlsym (F_DLL *dll, char *symbol, bool error)
2006-08-03 14:40:13 -04:00
{
2006-11-02 18:29:11 -05:00
void *sym = GetProcAddress(
dll ? (HMODULE)dll->dll : GetModuleHandle(NULL),
symbol);
2006-08-03 14:40:13 -04:00
if (!sym)
{
if(error)
general_error(ERROR_FFI,
tag_object(from_char_string(symbol)),
2006-10-18 17:16:37 -04:00
tag_object(get_error_message()),true);
2006-08-03 14:40:13 -04:00
else
return NULL;
}
return sym;
}
2006-11-04 11:52:57 -05:00
void ffi_dlclose (F_DLL *dll)
2006-08-03 14:40:13 -04:00
{
FreeLibrary((HMODULE)dll->dll);
dll->dll = NULL;
}
void primitive_stat(void)
{
WIN32_FILE_ATTRIBUTE_DATA st;
2006-10-31 00:52:02 -05:00
if(!GetFileAttributesEx(
unbox_char_string(),
GetFileExInfoStandard,
2006-10-31 15:48:34 -05:00
&st))
2006-08-03 14:40:13 -04:00
{
dpush(F);
2006-10-31 00:52:02 -05:00
dpush(F);
dpush(F);
dpush(F);
2006-10-31 15:48:34 -05:00
}
else
2006-08-03 14:40:13 -04:00
{
2006-10-31 00:52:02 -05:00
box_boolean(st.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
box_signed_4(0);
box_unsigned_8(
2006-11-04 11:52:57 -05:00
(s64)st.nFileSizeLow | (s64)st.nFileSizeHigh << 32);
2006-10-31 00:52:02 -05:00
box_unsigned_8((int)
2006-08-03 14:40:13 -04:00
((*(s64*)&st.ftLastWriteTime - EPOCH_OFFSET) / 10000000));
}
}
void primitive_read_dir(void)
{
HANDLE dir;
WIN32_FIND_DATA find_data;
2006-10-19 21:18:41 -04:00
char path[MAX_PATH + 4];
2006-08-03 14:40:13 -04:00
2006-10-31 15:48:34 -05:00
sprintf(path, "%s\\*", unbox_char_string());
2006-08-03 14:40:13 -04:00
GROWABLE_ARRAY(result);
2006-08-03 14:40:13 -04:00
2006-10-31 15:48:34 -05:00
if(INVALID_HANDLE_VALUE != (dir = FindFirstFile(path, &find_data)))
2006-08-03 14:40:13 -04:00
{
do
{
2006-10-31 16:45:12 -05:00
REGISTER_ARRAY(result);
CELL name = tag_object(from_char_string(
find_data.cFileName));
UNREGISTER_ARRAY(result);
GROWABLE_ADD(result,name);
2006-10-31 15:48:34 -05:00
}
2006-08-03 14:40:13 -04:00
while (FindNextFile(dir, &find_data));
CloseHandle(dir);
}
GROWABLE_TRIM(result);
2006-08-03 14:40:13 -04:00
dpush(tag_object(result));
}
void primitive_cwd(void)
{
char buf[MAX_PATH];
if(!GetCurrentDirectory(MAX_PATH, buf))
io_error();
box_char_string(buf);
}
void primitive_cd(void)
{
SetCurrentDirectory(unbox_char_string());
}
2006-11-02 18:29:11 -05:00
F_SEGMENT *alloc_segment(CELL size)
2006-08-03 14:40:13 -04:00
{
SYSTEM_INFO si;
char *mem;
DWORD ignore;
2006-08-03 14:40:13 -04:00
GetSystemInfo(&si);
if((mem = (char *)VirtualAlloc(NULL, si.dwPageSize*2 + size, MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == 0)
2006-11-02 18:29:11 -05:00
fatal_error("VirtualAlloc() failed in alloc_segment()",0);
2006-08-03 14:40:13 -04:00
if (!VirtualProtect(mem, si.dwPageSize, PAGE_NOACCESS, &ignore))
fatal_error("Cannot allocate low guard page", (CELL)mem);
2006-08-03 14:40:13 -04:00
if (!VirtualProtect(mem+size+si.dwPageSize, si.dwPageSize, PAGE_NOACCESS, &ignore))
fatal_error("Cannot allocate high guard page", (CELL)mem);
2006-08-03 14:40:13 -04:00
2006-11-02 18:29:11 -05:00
F_SEGMENT *block = safe_malloc(sizeof(F_SEGMENT));
2006-08-03 14:40:13 -04:00
block->start = (int)mem + si.dwPageSize;
block->size = size;
2006-08-03 14:40:13 -04:00
return block;
2006-08-03 14:40:13 -04:00
}
2006-11-02 18:29:11 -05:00
void dealloc_segment(F_SEGMENT *block)
2006-08-03 14:40:13 -04:00
{
SYSTEM_INFO si;
GetSystemInfo(&si);
if(!VirtualFree((void*)(block->start - si.dwPageSize), 0, MEM_RELEASE))
fatal_error("VirtualFree() failed",0);
free(block);
2006-08-03 14:40:13 -04:00
}
long getpagesize(void)
2006-09-24 15:28:44 -04:00
{
static long g_pagesize = 0;
if (! g_pagesize)
{
SYSTEM_INFO system_info;
GetSystemInfo (&system_info);
g_pagesize = system_info.dwPageSize;
}
return g_pagesize;
}
const char *default_image_path(void)
{
return "factor.image";
}
2006-08-03 14:40:13 -04:00
/* SEH support. Proceed with caution. */
typedef long exception_handler_t(
2006-09-24 15:28:44 -04:00
PEXCEPTION_RECORD rec, void *frame, void *context, void *dispatch);
2006-08-03 14:40:13 -04:00
2006-09-24 15:28:44 -04:00
typedef struct exception_record
{
2006-08-03 14:40:13 -04:00
struct exception_record *next_handler;
void *handler_func;
} exception_record_t;
void seh_call(void (*func)(), exception_handler_t *handler)
{
exception_record_t record;
asm("mov %%fs:0, %0" : "=r" (record.next_handler));
asm("mov %0, %%fs:0" : : "r" (&record));
record.handler_func = handler;
func();
asm("mov %0, %%fs:0" : "=r" (record.next_handler));
}
2006-09-24 15:28:44 -04:00
static long exception_handler(PEXCEPTION_RECORD rec, void *frame, void *ctx, void *dispatch)
2006-08-03 14:40:13 -04:00
{
2006-10-31 00:52:02 -05:00
memory_protection_error(rec->ExceptionInformation[1], SIGSEGV);
2006-09-24 15:28:44 -04:00
return -1; /* unreachable */
2006-08-03 14:40:13 -04:00
}
2006-10-15 00:10:54 -04:00
void run(void)
2006-08-03 14:40:13 -04:00
{
2006-10-15 00:10:54 -04:00
interpreter();
}
void run_toplevel(void)
{
seh_call(run, exception_handler);
2006-08-03 14:40:13 -04:00
}