diff options
Diffstat (limited to 'debian/transcode/transcode-1.1.7/import/w32dll-emu.c')
| -rw-r--r-- | debian/transcode/transcode-1.1.7/import/w32dll-emu.c | 1326 |
1 files changed, 1326 insertions, 0 deletions
diff --git a/debian/transcode/transcode-1.1.7/import/w32dll-emu.c b/debian/transcode/transcode-1.1.7/import/w32dll-emu.c new file mode 100644 index 00000000..7c1dbc36 --- /dev/null +++ b/debian/transcode/transcode-1.1.7/import/w32dll-emu.c @@ -0,0 +1,1326 @@ +/* + * w32dll-emu.c -- Win32 emulation routines to support DLLs + * Written by Andrew Church <achurch@achurch.org> + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <sys/mman.h> +#include <sys/time.h> +#include <wchar.h> + +#if !defined(HAVE_MMAP) +# error Sorry, mmap() support is required. +#endif + +#if defined(HAVE_ENDIAN_H) +# include <endian.h> +# if __BYTE_ORDER != __LITTLE_ENDIAN +# error Sorry, only little-endian architectures are supported. +# endif +#endif + +#if defined(HAVE_SYSCONF_WITH_SC_PAGESIZE) +# define GETPAGESIZE() (sysconf(_SC_PAGESIZE)) +#elif defined(HAVE_GETPAGESIZE) +# define GETPAGESIZE() (getpagesize()) +#elif defined(PAGESIZE) +# define GETPAGESIZE() (PAGESIZE) +#elif defined(PAGE_SIZE) +# define GETPAGESIZE() (PAGE_SIZE) +#else +# error System page size is not available! +#endif + +#include "w32dll.h" +#include "w32dll-local.h" +#include "w32dll-emu.h" + +/*************************************************************************/ + +/* Define this to enable creation of stubs for unemulated functions that + * print a warning to stderr and return -1 when the function is called. + * Note that this leaks one page of mmap() memory plus string memory per + * stub created. (Note, however, that for WINAPI functions the debug stub + * cannot know how many arguments to pop, so the program will probably + * crash on return.) + * Defining this also enables some debugging messages to stderr. + */ + +//#define W32DLL_EMU_DEBUG + +/*************************************************************************/ + +/* Array of known modules and associated handles (see w32dll-emu.h), + * terminated with name==NULL. */ + +#define MOD(modname) {.name = #modname ".dll", .handle = HANDLE_##modname} + +static const struct { + const char *name; + uint32_t handle; +} emumods[] = { + MOD(KERNEL32), + MOD(USER32), + { .name = NULL } +}; + +#undef MOD + + +/* Array of emulated functions, terminated with module==0. */ + +#define FUNC(mod,func) \ + {.module = HANDLE_##mod, .ordinal = 0, .name = #func, .funcptr = func} + +static const struct { + uint32_t module; /* handle */ + uint32_t ordinal; + const char *name; + void *funcptr; +} emufuncs[] = { + FUNC(KERNEL32, CloseHandle), + FUNC(KERNEL32, CreateSemaphoreA), + FUNC(KERNEL32, CreateSemaphoreW), + FUNC(KERNEL32, DeleteCriticalSection), + FUNC(KERNEL32, EnterCriticalSection), + FUNC(KERNEL32, ExitProcess), + FUNC(KERNEL32, FreeEnvironmentStringsA), + FUNC(KERNEL32, FreeEnvironmentStringsW), + FUNC(KERNEL32, GetACP), + FUNC(KERNEL32, GetCPInfo), + FUNC(KERNEL32, GetCommandLineA), + FUNC(KERNEL32, GetConsoleMode), + FUNC(KERNEL32, GetCurrentProcessId), + FUNC(KERNEL32, GetCurrentThreadId), + FUNC(KERNEL32, GetEnvironmentStringsA), + FUNC(KERNEL32, GetEnvironmentStringsW), + FUNC(KERNEL32, GetFileType), + FUNC(KERNEL32, GetLastError), + FUNC(KERNEL32, GetModuleFileNameA), + FUNC(KERNEL32, GetModuleHandleA), + FUNC(KERNEL32, GetProcAddress), + FUNC(KERNEL32, GetProcessHeap), + FUNC(KERNEL32, GetStartupInfoA), + FUNC(KERNEL32, GetStdHandle), + FUNC(KERNEL32, GetStringTypeW), + FUNC(KERNEL32, GetSystemTimeAsFileTime), + FUNC(KERNEL32, GetTickCount), + FUNC(KERNEL32, GetVersionExA), + FUNC(KERNEL32, HeapAlloc), + FUNC(KERNEL32, HeapCreate), + FUNC(KERNEL32, HeapDestroy), + FUNC(KERNEL32, HeapFree), + FUNC(KERNEL32, HeapReAlloc), + FUNC(KERNEL32, HeapSize), + FUNC(KERNEL32, InitializeCriticalSection), + FUNC(KERNEL32, InterlockedCompareExchange), + FUNC(KERNEL32, InterlockedCompareExchangePointer), + FUNC(KERNEL32, InterlockedDecrement), + FUNC(KERNEL32, InterlockedExchange), + FUNC(KERNEL32, InterlockedExchangeAdd), + FUNC(KERNEL32, InterlockedExchangePointer), + FUNC(KERNEL32, InterlockedIncrement), + FUNC(KERNEL32, InterlockedTestExchange), + FUNC(KERNEL32, LCMapStringA), + FUNC(KERNEL32, LCMapStringW), + FUNC(KERNEL32, LeaveCriticalSection), + FUNC(KERNEL32, LoadLibraryA), + FUNC(KERNEL32, MultiByteToWideChar), + FUNC(KERNEL32, QueryPerformanceCounter), + FUNC(KERNEL32, ReleaseSemaphore), + FUNC(KERNEL32, SetHandleCount), + FUNC(KERNEL32, SetLastError), + FUNC(KERNEL32, TlsAlloc), + FUNC(KERNEL32, TlsFree), + FUNC(KERNEL32, TlsGetValue), + FUNC(KERNEL32, TlsSetValue), + FUNC(KERNEL32, WaitForSingleObject), + FUNC(KERNEL32, WideCharToMultiByte), + FUNC(KERNEL32, WriteFile), + + FUNC(USER32, GetActiveWindow), + FUNC(USER32, MessageBoxA), + FUNC(USER32, MessageBoxW), + + { .module = 0 } +}; + +#undef FUNC + + +/* Debugging functions. */ + +#if defined(W32DLL_EMU_DEBUG) +# if !defined(MAP_ANONYMOUS) +# warn MAP_ANONYMOUS not defined, disabling W32DLL_EMU_DEBUG +# undef W32DLL_EMU_DEBUG +# else +static int32_t debug_stub(const char *module, const char *name, + uint32_t ordinal); +static void *create_debug_stub(const char *module, const char *name, + uint32_t ordinal); +# endif +#endif + +#if defined(W32DLL_EMU_DEBUG) +# define D(x) x +#else +# define D(x) /*nothing*/ +#endif + +/*************************************************************************/ +/*************************************************************************/ + +/* External interface. */ + +/*************************************************************************/ + +/** + * w32dll_emu_import_by_name, w32dll_emu_import_by_ordinal: Return the + * address of the emulated function corresponding to the given import, + * selected by either name or ordinal. + * + * Parameters: + * module: Name of the module from which to import. + * name: Import name descriptor (w32dll_emu_import_by_name() only). + * ordinal: Import ordinal (w32dll_emu_import_by_ordinal() only). + * Return value: + * The address corresponding to the import, or NULL if no emulation + * is available for the import. + */ + +void *w32dll_emu_import_by_name(const char *module, + const struct import_name_entry *name) +{ + int i; + uint32_t handle = 0; + + for (i = 0; emumods[i].name != NULL; i++) { + if (strcasecmp(emumods[i].name, module) == 0) { + handle = emumods[i].handle; + break; + } + } + if (handle) { + for (i = 0; emufuncs[i].module != 0; i++) { + if (emufuncs[i].module == handle + && strcasecmp(emufuncs[i].name, name->name) == 0) + return emufuncs[i].funcptr; + } + } +#if defined(W32DLL_EMU_DEBUG) + return create_debug_stub(module, name->name, 0); +#else + return NULL; +#endif +} + +/************************************/ + +void *w32dll_emu_import_by_ordinal(const char *module, uint32_t ordinal) +{ + /* Not supported yet. */ +#if defined(W32DLL_EMU_DEBUG) + return create_debug_stub(module, NULL, ordinal); +#else + return NULL; +#endif +} + +/*************************************************************************/ +/*************************************************************************/ + +/* The remainder of the file consists of emulation functions. */ + +/*************************************************************************/ +/*************************************************************************/ + +/* Emulation debugging functions. */ + +#if defined(W32DLL_EMU_DEBUG) + +/*************************************************************************/ + +/** + * debug_stub: Stub function which prints an error message. Called by + * machine code generated by create_debug_stub(). + * + * Parameters: + * module: Module name for which the stub is being called. + * name: Function name for which the stub is being called, or NULL + * if not applicable. + * ordinal: Function ordinal for which the stub is being called, if + * applicable. + * Return value: + * Always returns -1. + */ + +static int32_t debug_stub(const char *module, const char *name, + uint32_t ordinal) +{ + char numbuf[16]; + snprintf(numbuf, sizeof(numbuf), "0x%08X", ordinal); + fprintf(stderr, "[w32dll-emu] Unsupported function: %s/%s\n", + module, name ? name : numbuf); + return -1; +} + +/*************************************************************************/ + +/** + * create_debug_stub: Create a function which calls debug_stub(). + * + * Parameters: + * module: Module name for which the stub is being created. + * name: Function name for which the stub is being created, or NULL + * if not applicable. + * ordinal: Function ordinal for which the stub is being created, if + * applicable. + * Return value: + * A pointer to the newly-created debug stub, or NULL on error. + */ + +static void *create_debug_stub(const char *module, const char *name, + uint32_t ordinal) +{ + char *funcpage, *s; + int32_t offset; + + funcpage = mmap(NULL, GETPAGESIZE(), PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (funcpage == MAP_FAILED) + return NULL; + + if (module) + module = strdup(module); + if (!module) + module = "(null)"; + if (name) { + name = strdup(name); + if (!name) + name = "(null)"; + } + + /* Create the function. The code below is the equivalent of the + * following assembly: + * pop %eax + * pushl ordinal + * pushl name + * pushl module + * push %eax + * jmp debug_stub + */ + strcpy(funcpage, "\x58" + "\x68\x11\x11\x11\x11" + "\x68\x22\x22\x22\x22" + "\x68\x33\x33\x33\x33" + "\x50" + "\xE9\x44\x44\x44\x44"); + /* Fill in the various values. Do them in reverse order to avoid + * strstr() getting confused by intermediate nulls! */ + s = strstr(funcpage,"\x44\x44\x44\x44"); + offset = (int32_t)debug_stub - (int32_t)(s+4); + memcpy(s, &offset, 4); + memcpy(strstr(funcpage,"\x33\x33\x33\x33"), &module, 4); + memcpy(strstr(funcpage,"\x22\x22\x22\x22"), &name, 4); + memcpy(strstr(funcpage,"\x11\x11\x11\x11"), &ordinal, 4); + + /* Return the new page. */ + return funcpage; +} + +#endif /* W32DLL_EMU_DEBUG */ + +/*************************************************************************/ +/*************************************************************************/ + +/* Emulated functions in alphabetical order. See the Windows documentation + * for details about each function. */ + +/*************************************************************************/ + +/* Various data. */ + +static uint32_t w32_errno = 0; /* for GetLastError() */ +static int tls_alloced[TLS_MINIMUM_AVAILABLE]; +static void *tls_data[TLS_MINIMUM_AVAILABLE]; + +/*************************************************************************/ +/*************************************************************************/ + +/* KERNEL32 functions */ + +/*************************************************************************/ + +static WINAPI int CloseHandle(uint32_t handle) +{ + return 1; +} + +/*************************************************************************/ + +static WINAPI uint32_t CreateSemaphoreA(void *attr, uint32_t initial, + uint32_t max, const char *name) +{ + return HANDLE_SEMAPHORE; +} + +/*************************************************************************/ + +static WINAPI uint32_t CreateSemaphoreW(void *attr, uint32_t initial, + uint32_t max, const uint16_t *name) +{ + return HANDLE_SEMAPHORE; +} + +/*************************************************************************/ + +static WINAPI void DeleteCriticalSection(void *lock) +{ + /* Win32 "critical sections" are basically locks shared between threads. + * We only deal with one thread at the moment, so we ignore all these. */ +} + +/*************************************************************************/ + +static WINAPI void EnterCriticalSection(void *lock) +{ +} + +/*************************************************************************/ + +static WINAPI void ExitProcess(unsigned int exitcode) +{ + D((fprintf(stderr, "ExitProcess(%u) called, exiting...\n", exitcode))); + exit(exitcode); +} + +/*************************************************************************/ + +static WINAPI int FreeEnvironmentStringsA(void *env) +{ + return 1; +} + +/*************************************************************************/ + +static WINAPI int FreeEnvironmentStringsW(void *env) +{ + return 1; +} + +/*************************************************************************/ + +static WINAPI unsigned int GetACP(void) +{ + return 0; +} + +/*************************************************************************/ + +static WINAPI int GetCPInfo(unsigned int codepage, CPINFO *result) +{ + if (!result) { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + result->maxbytes = 1; + result->defchar[0] = '?'; + result->defchar[1] = 0; + memset(result->leadbytes, 0, sizeof(result->leadbytes)); + return 1; +} + +/*************************************************************************/ + +static WINAPI char *GetCommandLineA(void) +{ + static char dummy_cmdline[] = "dummy.exe"; + return dummy_cmdline; +} + +/*************************************************************************/ + +static WINAPI int GetConsoleMode(uint32_t file, uint16_t *result) +{ + if (file == HANDLE_STDIN) { + *result = 0x0007; /* PROCESSED_INPUT | LINE_INPUT | ECHO_INPUT */ + } else if (file == HANDLE_STDOUT) { + *result = 0x0001; /* PROCESSED_OUTPUT -- but not really! oh well */ + } else if (file == HANDLE_STDERR) { + *result = 0x0000; + } else { + SetLastError(ERROR_INVALID_HANDLE); + return 0; + } + return 1; +} + +/*************************************************************************/ + +static WINAPI uint32_t GetCurrentProcessId(void) +{ + return getpid(); +} + +/*************************************************************************/ + +static WINAPI uint32_t GetCurrentThreadId(void) +{ + return getpid(); +} + +/*************************************************************************/ + +static WINAPI void *GetEnvironmentStringsA(void) +{ + static char dummy_environ[2] = "\0\0"; + return dummy_environ; +} + +/*************************************************************************/ + +static WINAPI void *GetEnvironmentStringsW(void) +{ + static uint16_t dummy_environ[2] = {0,0}; + return dummy_environ; +} + +/*************************************************************************/ + +static WINAPI uint32_t GetFileType(uint32_t file) +{ + SetLastError(NO_ERROR); + if (file==HANDLE_STDIN || file==HANDLE_STDOUT || file==HANDLE_STDERR) + return 2; /* FILE_TYPE_CHAR */ + SetLastError(ERROR_INVALID_HANDLE); + return 0; /* FILE_TYPE_UNKNOWN */ +} + +/*************************************************************************/ + +static WINAPI uint32_t GetLastError(void) +{ + return w32_errno; +} + +/*************************************************************************/ + +static WINAPI uint32_t GetModuleFileNameA(uint32_t module, char *buf, + uint32_t size) +{ + int n = -1; + + if (module == 0 && module == HANDLE_DEFAULT) { + n = snprintf(buf, size, "%s", "dummy.exe"); + } else { + int i; + for (i = 0; emumods[i].name != NULL; i++) { + if (emumods[i].handle == module) { + n = snprintf(buf, size, "%s", emumods[i].name); + break; + } + } + if (!emumods[i].name) { + SetLastError(ERROR_INVALID_HANDLE); + return 0; + } + } + if (n < 0 || n >= size) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + return n; +} + +/*************************************************************************/ + +static WINAPI uint32_t GetModuleHandleA(const char *name) +{ + int i; + + if (!name) + return HANDLE_DEFAULT; + for (i = 0; emumods[i].name != NULL; i++) { + if (strcasecmp(emumods[i].name, name) == 0) + return emumods[i].handle; + } + D((fprintf(stderr, "GetModuleHandleA(%s) -> 0\n", name))); + SetLastError(ERROR_FILE_NOT_FOUND); + return 0; +} + +/*************************************************************************/ + +static WINAPI FARPROC GetProcAddress(uint32_t module, const char *name) +{ + int i; + + if (!name) { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + if (module == 0 && module == HANDLE_DEFAULT) { + D((fprintf(stderr, "GetProcAddress(DEFAULT, %s) -> NULL\n", name))); + SetLastError(ERROR_INVALID_FUNCTION); + return NULL; + } + for (i = 0; emufuncs[i].module != 0; i++) { + if (emufuncs[i].module==module && strcasecmp(emufuncs[i].name,name)==0) + return emufuncs[i].funcptr; + } + D((fprintf(stderr, "GetProcAddress(%d, %s) -> NULL\n", module, name))); + SetLastError(ERROR_INVALID_HANDLE); + return NULL; +} + +/*************************************************************************/ + +static WINAPI uint32_t GetProcessHeap(void) +{ + return HANDLE_HEAP; +} + +/*************************************************************************/ + +static WINAPI void GetStartupInfoA(STARTUPINFO *result) +{ + result->size = sizeof(*result); + result->reserved = NULL; + result->desktop = NULL; + result->title = "dummy"; + result->x = 0; + result->y = 0; + result->w = 640; + result->h = 480; + result->wchars = 80; + result->hchars = 30; + result->fill = 0; + result->flags = 0; + result->show = 1; + result->reserved2 = 0; + result->reserved3 = NULL; + result->h_stdin = HANDLE_STDIN; + result->h_stdout = HANDLE_STDOUT; + result->h_stderr = HANDLE_STDERR; +} + +/*************************************************************************/ + +static WINAPI uint32_t GetStdHandle(uint32_t index) +{ + if (index == (uint32_t)-10) + return HANDLE_STDIN; + if (index == (uint32_t)-11) + return HANDLE_STDOUT; + if (index == (uint32_t)-12) + return HANDLE_STDERR; + SetLastError(ERROR_INVALID_PARAMETER); + return INVALID_HANDLE_VALUE; +} + +/*************************************************************************/ + +static WINAPI int GetStringTypeW(uint32_t type, const uint16_t *str, + int len, uint16_t *typebuf) +{ + int i; + + if (!str || len <= 0 || !typebuf) { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + for (i = 0; i < len; i++) { + switch (type) { + case 1: + typebuf[i] = 0; + if (str[i] <= 0x7F) { + if (isupper((char)str[i])) + typebuf[i] |= 0x0001; + if (islower((char)str[i])) + typebuf[i] |= 0x0002; + if (isdigit((char)str[i])) + typebuf[i] |= 0x0004; + if (isspace((char)str[i])) + typebuf[i] |= 0x0008; + if (ispunct((char)str[i])) + typebuf[i] |= 0x0010; + if (iscntrl((char)str[i])) + typebuf[i] |= 0x0020; + if (isxdigit((char)str[i])) + typebuf[i] |= 0x0080; + if (isalpha((char)str[i])) + typebuf[i] |= 0x0100; + } // if (str[i] <= 0x7F) + break; + case 2: + if (str[i] >= 0x20 && str[i] <= 0x7E) { + typebuf[i] = 1; + } else { + typebuf[i] = 0; + } + break; + case 3: + if (isalpha((char)str[i])) { + typebuf[i] = 0x8040; /* ALPHA | HALFWIDTH */ + } + break; + } + } + return 1; +} + +/*************************************************************************/ + +static WINAPI void GetSystemTimeAsFileTime(uint64_t *result) +{ + /* Time is in 100-nanosecond units since 1601/1/1 0:00 UTC */ + /* Difference from 1601/1/1 to 1970/1/1 = 369 years, incl. 89 leap years */ + *result = ((uint64_t)time(NULL) + (uint64_t)(369*365+89)*86400) * 10000000; +} + +/*************************************************************************/ + +static WINAPI uint32_t GetTickCount(void) +{ + struct timeval tv; +#if defined(HAVE_GETTIMEOFDAY) + gettimeofday(&tv, NULL); +#else + tv.tv_sec = time(NULL); + tv.tv_usec = 0; +#endif + return tv.tv_sec*1000 + tv.tv_usec/1000; // as good as anything else +} + +/*************************************************************************/ + +static WINAPI int GetVersionExA(OSVERSIONINFOEX *result) +{ + if (!result || result->size < 148) { // 148: sizeof(OSVERSIONINFO) + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + /* Emulate Windows 2000 */ + result->major = 5; + result->minor = 0; + result->build = 31337; + result->platform = 2; + memset(result->extra, 0, sizeof(result->extra)); + if (result->size >= sizeof(*result)) { + result->sp_major = 4; + result->sp_minor = 0; + result->suite = 0x0000; + result->type = 0x01; + result->reserved = 0; + } + return 1; +} + +/*************************************************************************/ + +#define HEAPALLOC_MAGIC 0x9D1A9DA1 +#define HEAPFREE_MAGIC (~HEAPALLOC_MAGIC) + +static WINAPI void *HeapAlloc(uint32_t heap, uint32_t flags, size_t size) +{ + void *ptr = malloc(size+8); + D((fprintf(stderr, "HeapAlloc(%u) -> %p%s", size, ptr, ptr ? "" : "\n"))); + if (!ptr) { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + ptr = (uint32_t *)ptr+2; + ((uint32_t *)ptr)[-2] = HEAPALLOC_MAGIC; + ((uint32_t *)ptr)[-1] = size; + D((fprintf(stderr, " -> %p\n", ptr))); + if (flags & 0x00000008) /* HEAP_ZERO_MEMORY */ + memset(ptr, 0, size); + return ptr; +} + +/*************************************************************************/ + +static WINAPI uint32_t HeapCreate(uint32_t flags, size_t initial, size_t max) +{ + /* Just share the same "heap" */ + return HANDLE_HEAP; +} + +/*************************************************************************/ + +static WINAPI int HeapDestroy(uint32_t heap) +{ + return 1; /* Ignore */ +} + +/*************************************************************************/ + +static WINAPI int HeapFree(uint32_t heap, uint32_t flags, void *ptr) +{ + D((fprintf(stderr, "HeapFree(%p) [%08X %u]\n", ptr, + ptr ? ((uint32_t *)ptr)[-2] : 0, + ptr ? ((uint32_t *)ptr)[-1] : 0))); + if (ptr) { + if (((uint32_t *)ptr)[-2] != HEAPALLOC_MAGIC) { + D((fprintf(stderr, "HeapFree() on %s pointer %p!\n", + ((uint32_t *)ptr)[-2]==HEAPFREE_MAGIC ? "freed" : "bad", + ptr))); + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + ((uint32_t *)ptr)[-1] = HEAPFREE_MAGIC; + free((uint32_t *)ptr-2); + } + return 1; +} + +/*************************************************************************/ + +static WINAPI void *HeapReAlloc(uint32_t heap, uint32_t flags, void *ptr, + size_t size) +{ + size_t oldsize; + + D((fprintf(stderr, "HeapReAlloc(%p,%u) -> ", ptr, size))); + if (!ptr) + return HeapAlloc(heap, flags, size); + if (((uint32_t *)ptr)[-2] != HEAPALLOC_MAGIC) { + D((fprintf(stderr, "HeapReAlloc() on %s pointer %p!\n", + ((uint32_t *)ptr)[-2]==HEAPFREE_MAGIC ? "freed" : "bad", + ptr))); + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + oldsize = ((uint32_t *)ptr)[-1]; + ptr = realloc((uint32_t *)ptr-2, size+8); + D((fprintf(stderr, "oldsize %u -> %p%s", oldsize, ptr, ptr ? "" : "\n"))); + if (!ptr) { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return NULL; + } + ptr = (uint32_t *)ptr+2; + ((uint32_t *)ptr)[-2] = HEAPALLOC_MAGIC; + ((uint32_t *)ptr)[-1] = size; + D((fprintf(stderr, " -> %p\n", ptr))); + if (size > oldsize && (flags & 0x00000008)) /* HEAP_ZERO_MEMORY */ + memset((uint8_t *)ptr + oldsize, 0, size - oldsize); + return ptr; +} + +/*************************************************************************/ + +static WINAPI uint32_t HeapSize(uint32_t heap, uint32_t flags, const void *ptr) +{ + D((fprintf(stderr, "HeapSize(%p) -> %u\n", ptr, + (uint32_t) (((const uint64_t *)ptr)[-1])))); + return (uint32_t) (((const uint64_t *)ptr)[-1]); +} + +/*************************************************************************/ + +static WINAPI void InitializeCriticalSection(void *lock) +{ +} + +/*************************************************************************/ + +static WINAPI int32_t InterlockedCompareExchange + (int32_t *var, int32_t testval, int32_t newval) +{ + int32_t oldval = *var; + if (oldval == testval) + *var = newval; + return oldval; +} + +/*************************************************************************/ + +static WINAPI void *InterlockedCompareExchangePointer + (void ***var, void *testval, void *newval) +{ + void *oldval = *var; + if (oldval == testval) + *var = newval; + return oldval; +} + +/*************************************************************************/ + +static WINAPI int32_t InterlockedDecrement(int32_t *var) +{ + return --*var; +} + +/*************************************************************************/ + +static WINAPI int32_t InterlockedExchange(int32_t *var, int32_t newval) +{ + int32_t oldval = *var; + *var = newval; + return oldval; +} + +/*************************************************************************/ + +static WINAPI int32_t InterlockedExchangeAdd(int32_t *var, int32_t addval) +{ + int32_t oldval = *var; + *var += addval; + return oldval; +} + +/*************************************************************************/ + +static WINAPI void *InterlockedExchangePointer(void **var, void *newval) +{ + void *oldval = *var; + *var = newval; + return oldval; +} + +/*************************************************************************/ + +static WINAPI int32_t InterlockedIncrement(int32_t *var) +{ + return ++*var; +} + +/*************************************************************************/ + +static WINAPI int32_t InterlockedTestExchange(int32_t *var, int32_t testval, + int32_t newval) +{ + int32_t oldval = *var; + if (oldval == testval) + *var = newval; + return oldval; +} + +/*************************************************************************/ + +static WINAPI int LCMapStringA + (uint32_t locale, uint32_t flags, const char *in, int inlen, + char *out, int outsize) +{ + if (!in || !inlen || outsize < 0 || (outsize > 0 && !out)) { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + if (inlen < 0) + inlen = strlen(in) + 1; // include terminating null + if (outsize == 0) + return inlen; + if (outsize < inlen) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + memcpy(out, in, inlen); + return inlen; +} + +/*************************************************************************/ + +static WINAPI int LCMapStringW + (uint32_t locale, uint32_t flags, const uint16_t *in, int inlen, + uint16_t *out, int outsize) +{ + if (!in || !inlen || outsize < 0 || (outsize > 0 && !out)) { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + if (inlen < 0) { + inlen = 0; + while (in[inlen]) + inlen++; + inlen++; // include null terminator + } + if (outsize == 0) + return inlen; + if (outsize < inlen) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + memcpy(out, in, inlen*2); + return inlen; +} + +/*************************************************************************/ + +static WINAPI void LeaveCriticalSection(void *lock) +{ +} + +/*************************************************************************/ + +static WINAPI uint32_t LoadLibraryA(char *filename) +{ + return GetModuleHandleA(filename); +} + +/*************************************************************************/ + +static WINAPI int MultiByteToWideChar + (unsigned int codepage, uint32_t flags, const unsigned char *in, + int inlen, uint16_t *out, int outsize) +{ + int i, outlen; + + if (!in || !inlen || outsize < 0 || (outsize > 0 && !out)) { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + if (inlen < 0) { + inlen = 0; + while (in[inlen]) + inlen++; + inlen++; // include null terminator + } + outlen = 0; + + for (i = 0; i < inlen; i++) { + if (out) { + if (outlen >= outsize) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + *out++ = in[i]; + } + outlen++; + } + + return outlen; +} + +/*************************************************************************/ + +static WINAPI uint32_t QueryPerformanceCounter(int64_t *result) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + if (!result) { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + *result = (int64_t)tv.tv_sec*1000000 + tv.tv_usec; // sure, why not? + return 1; +} + +/*************************************************************************/ + +static WINAPI int ReleaseSemaphore(uint32_t sem, int32_t release_count, + int32_t *previous) +{ + if (sem != HANDLE_SEMAPHORE) { + SetLastError(ERROR_INVALID_HANDLE); + return 0; + } + if (previous) + *previous = 0; + return 1; +} + +/*************************************************************************/ + +static WINAPI void SetHandleCount(uint32_t count) +{ + /* obsolete Win16 function, does nothing */ +} + +/*************************************************************************/ + +static WINAPI void SetLastError(uint32_t error) +{ + w32_errno = error; +} + +/*************************************************************************/ + +static WINAPI uint32_t TlsAlloc(void) +{ + int i; + for (i = 0; i < TLS_MINIMUM_AVAILABLE; i++) { + if (!tls_alloced[i]) { + tls_alloced[i] = 1; + D((fprintf(stderr, "TlsAlloc() succeeded with %d\n", i))); + return i; + } + } + D((fprintf(stderr, "TlsAlloc() failed\n"))); + return ~0; +} + +/*************************************************************************/ + +static WINAPI int TlsFree(uint32_t index) +{ + if (index >= TLS_MINIMUM_AVAILABLE) { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + tls_alloced[index] = 0; + return 1; +} + +/*************************************************************************/ + +static WINAPI void *TlsGetValue(uint32_t index) +{ + if (index >= TLS_MINIMUM_AVAILABLE) { + SetLastError(ERROR_INVALID_PARAMETER); + return NULL; + } + SetLastError(NO_ERROR); + return tls_data[index]; +} + +/*************************************************************************/ + +static WINAPI int TlsSetValue(uint32_t index, void *value) +{ + if (index >= TLS_MINIMUM_AVAILABLE) { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + tls_data[index] = value; + return 1; +} + +/*************************************************************************/ + +static WINAPI uint32_t WaitForSingleObject(uint32_t handle, uint32_t msec) +{ + return 0; /* or WAIT_TIMEOUT == 0x102 */ +} + +/*************************************************************************/ + +static WINAPI int WideCharToMultiByte + (unsigned int codepage, uint32_t flags, const uint16_t *in, int inlen, + char *out, int outsize, const char *defchar, int *defchar_used) +{ + int i, outlen; + + if (!in || !inlen || outsize < 0 || (outsize > 0 && !out)) { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + if (inlen < 0) { + inlen = 0; + while (in[inlen]) + inlen++; + inlen++; // include null terminator + } + if (!defchar) + defchar = "?"; + outlen = 0; + + /* Simple implementation (FIXME look into glibc's conversion functions?) */ + for (i = 0; i < inlen; i++) { + if (in[i] <= 0x7F) { + if (out) { + if (outlen >= outsize) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + *out++ = (char)in[i]; + } + outlen++; + } else { + if (out) { + const char *s; + if (outlen + strlen(defchar) > outsize) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + s = defchar; + while (*s) + *out++ = *s++; + } + outlen += strlen(defchar); + if (defchar_used) + *defchar_used = 1; + } + } + + return outlen; +} + +/*************************************************************************/ + +static WINAPI int WriteFile(uint32_t file, const void *buf, uint32_t len, + uint32_t *written, void *overlapped) +{ + int fd = -1, nwritten; + + if (!buf) { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + if (file == HANDLE_STDIN) { + SetLastError(ERROR_ACCESS_DENIED); + return 0; + } else if (file == HANDLE_STDOUT) { + D((fd = 1)); + } else if (file == HANDLE_STDERR) { + D((fd = 2)); + } else { + SetLastError(ERROR_INVALID_HANDLE); + return 0; + } + if (len == 0) { + if (written) + *written = 0; + return 1; + } + if (fd < 0) { + /* Suppress stdout/stderr output in non-debug mode */ + if (written) + *written = len; + return 1; + } + + do { + errno = 0; + nwritten = write(fd, buf, len); + } while (nwritten <= 0 && errno == EINTR); + if (nwritten <= 0) { + if (errno == EBADF || errno == EINVAL) + SetLastError(ERROR_ACCESS_DENIED); + else if (errno == EFAULT) + SetLastError(ERROR_INVALID_ACCESS); + else if (errno == EPIPE) + SetLastError(ERROR_BROKEN_PIPE); + else if (errno == EAGAIN) + SetLastError(ERROR_IO_PENDING); + else if (errno == ENOSPC || errno == EFBIG) + SetLastError(ERROR_DISK_FULL); + else if (errno == EIO) + SetLastError(ERROR_WRITE_FAULT); + else + SetLastError(ERROR_UNKNOWN); + return 0; + } + + if (written) + *written = (uint32_t)nwritten; + return 1; +} + +/*************************************************************************/ +/*************************************************************************/ + +/* USER32 functions. */ + +/*************************************************************************/ + +static WINAPI uint32_t GetActiveWindow(void) +{ + return HANDLE_WINDOW; +} + +/*************************************************************************/ + +#define OUT(str) do { \ + const char *__s = str; \ + do { \ + int __len, __lpad, __rpad; \ + const char *__t = __s + strlen(__s); \ + if (__t - __s > maxline) \ + __t = __s + maxline; \ + __len = __t - __s; \ + __lpad = (maxline - __len) / 2; \ + __rpad = maxline - __len - __lpad; \ + fprintf(stderr, "|%*s%.*s%*s|\n", __lpad, "", __len, __s, __rpad, "");\ + __s = __t; \ + } while (*__s); \ +} while (0) +#define MAXLINEWIDTH 77 + +static WINAPI int MessageBoxA(uint32_t window, const char *text, + const char *title, unsigned int type) +{ + char *mytext, *s; + int maxline, i; + char dashbuf[MAXLINEWIDTH+1]; + + if (!text || !title) { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + mytext = strdup(text); // make sure we can strtok() it + if (!mytext) { + SetLastError(ERROR_OUTOFMEMORY); + return 0; + } + + maxline = strlen(title); + for (s = mytext; *s; s += strspn(s, "\r\n")) { + char *t = s + strcspn(s, "\r\n"); + if (t-s > maxline) + maxline = t-s; + s = t; + } + if (maxline > MAXLINEWIDTH) + maxline = MAXLINEWIDTH; + for (i = 0; i < maxline; i++) + dashbuf[i] = '-'; + dashbuf[maxline] = 0; + + fprintf(stderr, "+%s+\n", dashbuf); + OUT(title); + fprintf(stderr, "+%s+\n", dashbuf); + for (s = strtok(mytext,"\r\n"); s; s = strtok(NULL,"\r\n")) + OUT(s); + fprintf(stderr, "+%s+\n", dashbuf); + + free(mytext); + return 1; +} + +#undef OUT +#undef MAXLINEWIDTH + +/*************************************************************************/ + +static WINAPI int MessageBoxW(uint32_t window, const uint16_t *text, + const uint16_t *title, unsigned int type) +{ + char textbuf[10000], titlebuf[1000]; + if (!WideCharToMultiByte(0, 0, text, 0, textbuf, sizeof(textbuf), 0, 0)) + strcpy(textbuf, "<<buffer overflow>>"); + if (!WideCharToMultiByte(0, 0, title, 0, titlebuf, sizeof(titlebuf), 0, 0)) + strcpy(titlebuf, "<<buffer overflow>>"); + return MessageBoxA(window, textbuf, titlebuf, type);; +} + +/*************************************************************************/ +/*************************************************************************/ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ |
