mirror of
https://github.com/decompals/wibo.git
synced 2025-12-12 06:45:05 +00:00
Numerous msvcrt/crt fixes; support variable resolution
This commit is contained in:
26
dll/crt.cpp
26
dll/crt.cpp
@@ -15,6 +15,25 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
FILE *mapToHostFile(_FILE *file) {
|
||||||
|
if (!file)
|
||||||
|
return nullptr;
|
||||||
|
switch (file->_file) {
|
||||||
|
case STDIN_FILENO:
|
||||||
|
return stdin;
|
||||||
|
case STDOUT_FILENO:
|
||||||
|
return stdout;
|
||||||
|
case STDERR_FILENO:
|
||||||
|
return stderr;
|
||||||
|
default:
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace crt {
|
namespace crt {
|
||||||
|
|
||||||
int _commode = 0;
|
int _commode = 0;
|
||||||
@@ -302,11 +321,14 @@ void *CDECL __acrt_iob_func(unsigned int index) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL_NO_CONV __stdio_common_vfprintf(unsigned long long options, FILE *stream, const char *format, void *locale,
|
int CDECL_NO_CONV __stdio_common_vfprintf(unsigned long long options, _FILE *stream, const char *format, void *locale,
|
||||||
va_list args) {
|
va_list args) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("__stdio_common_vfprintf(%llu, %p, %s, %p, %p)\n", options, stream, format, locale, args);
|
DEBUG_LOG("__stdio_common_vfprintf(%llu, %p, %s, %p, %p)\n", options, stream, format, locale, args);
|
||||||
return vfprintf(stream, format, args);
|
FILE *hostFile = mapToHostFile(stream);
|
||||||
|
if (!hostFile)
|
||||||
|
return -1;
|
||||||
|
return vfprintf(hostFile, format, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL_NO_CONV __stdio_common_vsprintf(unsigned long long options, char *buffer, SIZE_T len, const char *format,
|
int CDECL_NO_CONV __stdio_common_vsprintf(unsigned long long options, char *buffer, SIZE_T len, const char *format,
|
||||||
|
|||||||
16
dll/crt.h
16
dll/crt.h
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
typedef void (_CC_CDECL *_PVFV)();
|
typedef void(_CC_CDECL *_PVFV)();
|
||||||
typedef int (_CC_CDECL *_PIFV)();
|
typedef int(_CC_CDECL *_PIFV)();
|
||||||
typedef void (_CC_CDECL *_invalid_parameter_handler)(const WCHAR *, const WCHAR *, const WCHAR *, UINT, UINT_PTR);
|
typedef void(_CC_CDECL *_invalid_parameter_handler)(const WCHAR *, const WCHAR *, const WCHAR *, UINT, UINT_PTR);
|
||||||
|
|
||||||
typedef enum _crt_app_type {
|
typedef enum _crt_app_type {
|
||||||
_crt_unknown_app,
|
_crt_unknown_app,
|
||||||
@@ -18,12 +18,14 @@ typedef enum _crt_argv_mode {
|
|||||||
_crt_argv_expanded_arguments,
|
_crt_argv_expanded_arguments,
|
||||||
} _crt_argv_mode;
|
} _crt_argv_mode;
|
||||||
|
|
||||||
typedef void (_CC_CDECL *signal_handler)(int);
|
typedef void(_CC_CDECL *signal_handler)(int);
|
||||||
typedef int (_CC_CDECL *sort_compare)(const void *, const void *);
|
typedef int(_CC_CDECL *sort_compare)(const void *, const void *);
|
||||||
using FILE = struct _IO_FILE;
|
|
||||||
|
|
||||||
namespace crt {
|
namespace crt {
|
||||||
|
|
||||||
|
extern int _commode;
|
||||||
|
extern int _fmode;
|
||||||
|
|
||||||
void CDECL _initterm(const _PVFV *ppfn, const _PVFV *end);
|
void CDECL _initterm(const _PVFV *ppfn, const _PVFV *end);
|
||||||
int CDECL _initterm_e(const _PIFV *ppfn, const _PIFV *end);
|
int CDECL _initterm_e(const _PIFV *ppfn, const _PIFV *end);
|
||||||
void CDECL _set_app_type(_crt_app_type type);
|
void CDECL _set_app_type(_crt_app_type type);
|
||||||
@@ -65,7 +67,7 @@ void CDECL _exit(int status);
|
|||||||
void CDECL abort();
|
void CDECL abort();
|
||||||
signal_handler CDECL signal(int signum, signal_handler handler);
|
signal_handler CDECL signal(int signum, signal_handler handler);
|
||||||
void *CDECL __acrt_iob_func(unsigned int index);
|
void *CDECL __acrt_iob_func(unsigned int index);
|
||||||
int CDECL_NO_CONV __stdio_common_vfprintf(unsigned long long options, FILE *stream, const char *format, void *locale,
|
int CDECL_NO_CONV __stdio_common_vfprintf(unsigned long long options, _FILE *stream, const char *format, void *locale,
|
||||||
va_list args);
|
va_list args);
|
||||||
int CDECL_NO_CONV __stdio_common_vsprintf(unsigned long long options, char *buffer, SIZE_T len, const char *format,
|
int CDECL_NO_CONV __stdio_common_vsprintf(unsigned long long options, char *buffer, SIZE_T len, const char *format,
|
||||||
void *locale, va_list args);
|
void *locale, va_list args);
|
||||||
|
|||||||
230
dll/msvcrt.cpp
230
dll/msvcrt.cpp
@@ -34,6 +34,7 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <spawn.h>
|
#include <spawn.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -50,7 +51,48 @@
|
|||||||
#define O_BINARY 0
|
#define O_BINARY 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using _onexit_t = _PIFV;
|
namespace {
|
||||||
|
|
||||||
|
std::mutex g_fileMutex;
|
||||||
|
std::unordered_map<int, FILE *> g_files;
|
||||||
|
|
||||||
|
FILE *mapToHostFile(_FILE *file) {
|
||||||
|
if (!file)
|
||||||
|
return nullptr;
|
||||||
|
switch (file->_file) {
|
||||||
|
case -1:
|
||||||
|
return nullptr;
|
||||||
|
case STDIN_FILENO:
|
||||||
|
return stdin;
|
||||||
|
case STDOUT_FILENO:
|
||||||
|
return stdout;
|
||||||
|
case STDERR_FILENO:
|
||||||
|
return stderr;
|
||||||
|
default:
|
||||||
|
return g_files[file->_file];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_FILE *mapToGuestFile(FILE *file) {
|
||||||
|
if (!file)
|
||||||
|
return nullptr;
|
||||||
|
int fd = file->_fileno;
|
||||||
|
_FILE *out = new (wibo::heap::guestMalloc(sizeof(_FILE))) _FILE(fd);
|
||||||
|
std::lock_guard lock(g_fileMutex);
|
||||||
|
g_files[fd] = file;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
int closeGuestFile(_FILE *file) {
|
||||||
|
if (!file)
|
||||||
|
return -1;
|
||||||
|
int fd = file->_file;
|
||||||
|
std::lock_guard lock(g_fileMutex);
|
||||||
|
g_files.erase(fd);
|
||||||
|
return close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace msvcrt {
|
namespace msvcrt {
|
||||||
int _commode;
|
int _commode;
|
||||||
@@ -59,13 +101,15 @@ namespace msvcrt {
|
|||||||
uint16_t** __winitenv;
|
uint16_t** __winitenv;
|
||||||
uint16_t* _wpgmptr = nullptr;
|
uint16_t* _wpgmptr = nullptr;
|
||||||
char* _pgmptr = nullptr;
|
char* _pgmptr = nullptr;
|
||||||
|
int __mb_cur_max = 1;
|
||||||
|
_FILE _iob[_IOB_ENTRIES] = {_FILE{STDOUT_FILENO}, _FILE{STDERR_FILENO}, _FILE{STDIN_FILENO}};
|
||||||
|
|
||||||
constexpr int MB_CP_ANSI = -3;
|
constexpr int MB_CP_ANSI = -3;
|
||||||
constexpr int MB_CP_OEM = -2;
|
constexpr int MB_CP_OEM = -2;
|
||||||
constexpr int MB_CP_LOCALE = -4;
|
constexpr int MB_CP_LOCALE = -4;
|
||||||
constexpr int MB_CP_SBCS = 0;
|
constexpr int MB_CP_SBCS = 0;
|
||||||
constexpr int MB_CP_UTF8 = -5;
|
constexpr int MB_CP_UTF8 = -5;
|
||||||
|
|
||||||
static unsigned int mbCurMaxValue = 1;
|
|
||||||
static int mbCodePageSetting = MB_CP_ANSI;
|
static int mbCodePageSetting = MB_CP_ANSI;
|
||||||
static unsigned int floatingPointControlWord = 0x0009001F; // _CW_DEFAULT for x87
|
static unsigned int floatingPointControlWord = 0x0009001F; // _CW_DEFAULT for x87
|
||||||
|
|
||||||
@@ -103,7 +147,7 @@ namespace msvcrt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int mbCurMaxForCodePage(int codepage);
|
int mbCurMaxForCodePage(int codepage);
|
||||||
|
|
||||||
void updateMbctypeForCodePage(int codepage) {
|
void updateMbctypeForCodePage(int codepage) {
|
||||||
auto &table = mbctypeTable();
|
auto &table = mbctypeTable();
|
||||||
@@ -158,7 +202,7 @@ namespace msvcrt {
|
|||||||
void ensureMbctypeInitialized() {
|
void ensureMbctypeInitialized() {
|
||||||
std::call_once(mbctypeInitFlag(), []() {
|
std::call_once(mbctypeInitFlag(), []() {
|
||||||
updateMbctypeForCodePage(mbCodePageSetting);
|
updateMbctypeForCodePage(mbCodePageSetting);
|
||||||
mbCurMaxValue = mbCurMaxForCodePage(mbCodePageSetting);
|
__mb_cur_max = mbCurMaxForCodePage(mbCodePageSetting);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,52 +249,21 @@ namespace msvcrt {
|
|||||||
return storage;
|
return storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
IOBProxy *standardIobEntries() {
|
_FILE *standardIobEntries() {
|
||||||
static IOBProxy entries[3] = {};
|
return _iob;
|
||||||
return entries;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IOBProxy *CDECL __iob_func() {
|
_FILE *CDECL __iob_func() {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
return standardIobEntries();
|
return _iob;
|
||||||
}
|
}
|
||||||
|
|
||||||
IOBProxy *CDECL __p__iob() {
|
_FILE *CDECL __p__iob() {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
return standardIobEntries();
|
return _iob;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<void *, FILE *> &iobMapping() {
|
void CDECL setbuf(_FILE *stream, char *buffer) {
|
||||||
static std::unordered_map<void *, FILE *> mapping;
|
|
||||||
return mapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::once_flag &iobInitFlag() {
|
|
||||||
static std::once_flag flag;
|
|
||||||
return flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
void initializeIobMapping() {
|
|
||||||
std::call_once(iobInitFlag(), []() {
|
|
||||||
auto &mapping = iobMapping();
|
|
||||||
IOBProxy *entries = standardIobEntries();
|
|
||||||
mapping.emplace(static_cast<void *>(&entries[0]), stdin);
|
|
||||||
mapping.emplace(static_cast<void *>(&entries[1]), stdout);
|
|
||||||
mapping.emplace(static_cast<void *>(&entries[2]), stderr);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *mapToHostFile(FILE *stream) {
|
|
||||||
initializeIobMapping();
|
|
||||||
auto &mapping = iobMapping();
|
|
||||||
auto it = mapping.find(stream);
|
|
||||||
if (it != mapping.end()) {
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDECL setbuf(FILE *stream, char *buffer) {
|
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("setbuf(%p, %p)\n", stream, buffer);
|
DEBUG_LOG("setbuf(%p, %p)\n", stream, buffer);
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
@@ -329,7 +342,7 @@ namespace msvcrt {
|
|||||||
ext ? ext : "");
|
ext ? ext : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL _fileno(FILE *stream) {
|
int CDECL _fileno(_FILE *stream) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("_fileno(%p)\n", stream);
|
DEBUG_LOG("_fileno(%p)\n", stream);
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
@@ -340,7 +353,7 @@ namespace msvcrt {
|
|||||||
return ::fileno(host);
|
return ::fileno(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int mbCurMaxForCodePage(int codepage) {
|
int mbCurMaxForCodePage(int codepage) {
|
||||||
switch (codepage) {
|
switch (codepage) {
|
||||||
case MB_CP_SBCS:
|
case MB_CP_SBCS:
|
||||||
case MB_CP_ANSI:
|
case MB_CP_ANSI:
|
||||||
@@ -363,7 +376,7 @@ namespace msvcrt {
|
|||||||
|
|
||||||
void refreshMbCurMax() {
|
void refreshMbCurMax() {
|
||||||
ensureMbctypeInitialized();
|
ensureMbctypeInitialized();
|
||||||
mbCurMaxValue = mbCurMaxForCodePage(mbCodePageSetting);
|
__mb_cur_max = mbCurMaxForCodePage(mbCodePageSetting);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL _getmbcp() {
|
int CDECL _getmbcp() {
|
||||||
@@ -373,11 +386,11 @@ namespace msvcrt {
|
|||||||
return mbCodePageSetting;
|
return mbCodePageSetting;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int* CDECL __p___mb_cur_max() {
|
int* CDECL __p___mb_cur_max() {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
ensureMbctypeInitialized();
|
ensureMbctypeInitialized();
|
||||||
DEBUG_LOG("__p___mb_cur_max() -> %u\n", mbCurMaxValue);
|
DEBUG_LOG("__p___mb_cur_max() -> %u\n", __mb_cur_max);
|
||||||
return &mbCurMaxValue;
|
return &__mb_cur_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL _setmbcp(int codepage) {
|
int CDECL _setmbcp(int codepage) {
|
||||||
@@ -402,7 +415,7 @@ namespace msvcrt {
|
|||||||
|
|
||||||
mbCodePageSetting = codepage;
|
mbCodePageSetting = codepage;
|
||||||
updateMbctypeForCodePage(codepage);
|
updateMbctypeForCodePage(codepage);
|
||||||
mbCurMaxValue = mbCurMaxForCodePage(codepage);
|
__mb_cur_max = mbCurMaxForCodePage(codepage);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -729,11 +742,20 @@ namespace msvcrt {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_PIFV CDECL _onexit(_PIFV func) {
|
static void runExitFunc(int status, void *arg) {
|
||||||
|
(void)status;
|
||||||
|
(void)call__onexit_t(reinterpret_cast<_onexit_t>(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
_onexit_t CDECL _onexit(_onexit_t func) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("_onexit(%p)\n", func);
|
DEBUG_LOG("_onexit(%p)\n", func);
|
||||||
if(!func) return nullptr;
|
if (!func) {
|
||||||
if (atexit(reinterpret_cast<void (*)()>(func)) != 0) return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (on_exit(runExitFunc, reinterpret_cast<void *>(func)) != 0) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1129,7 +1151,7 @@ namespace msvcrt {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *CDECL fgets(char *str, int count, FILE *stream) {
|
char *CDECL fgets(char *str, int count, _FILE *stream) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("fgets(%p, %d, %p)\n", str, count, stream);
|
DEBUG_LOG("fgets(%p, %d, %p)\n", str, count, stream);
|
||||||
if (!str || count <= 0) {
|
if (!str || count <= 0) {
|
||||||
@@ -1139,14 +1161,14 @@ namespace msvcrt {
|
|||||||
return ::fgets(str, count, host);
|
return ::fgets(str, count, host);
|
||||||
}
|
}
|
||||||
|
|
||||||
SIZE_T CDECL fread(void *buffer, SIZE_T size, SIZE_T count, FILE *stream) {
|
SIZE_T CDECL fread(void *buffer, SIZE_T size, SIZE_T count, _FILE *stream) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("fread(%p, %zu, %zu, %p)\n", buffer, size, count, stream);
|
DEBUG_LOG("fread(%p, %zu, %zu, %p)\n", buffer, size, count, stream);
|
||||||
FILE *host = mapToHostFile(stream);
|
FILE *host = mapToHostFile(stream);
|
||||||
return ::fread(buffer, size, count, host);
|
return ::fread(buffer, size, count, host);
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *CDECL _fsopen(const char *filename, const char *mode, int shflag) {
|
_FILE *CDECL _fsopen(const char *filename, const char *mode, int shflag) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("_fsopen(%s, %s, %d)\n", filename ? filename : "(null)", mode ? mode : "(null)", shflag);
|
DEBUG_LOG("_fsopen(%s, %s, %d)\n", filename ? filename : "(null)", mode ? mode : "(null)", shflag);
|
||||||
(void)shflag;
|
(void)shflag;
|
||||||
@@ -1155,7 +1177,7 @@ namespace msvcrt {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto hostPath = files::pathFromWindows(filename);
|
auto hostPath = files::pathFromWindows(filename);
|
||||||
return ::fopen(hostPath.c_str(), mode);
|
return mapToGuestFile(::fopen(hostPath.c_str(), mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL _sopen(const char *path, int oflag, int shflag, int pmode) {
|
int CDECL _sopen(const char *path, int oflag, int shflag, int pmode) {
|
||||||
@@ -1802,13 +1824,18 @@ namespace msvcrt {
|
|||||||
return std::memcmp(lhs, rhs, count);
|
return std::memcmp(lhs, rhs, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDECL qsort(void *base, SIZE_T num, SIZE_T size, int (*compar)(const void *, const void *)) {
|
static thread_local sort_compare currentCompare = nullptr;
|
||||||
|
|
||||||
|
static int doCompare(const void *a, const void *b) { return call_sort_compare(currentCompare, a, b); }
|
||||||
|
|
||||||
|
void CDECL qsort(void *base, SIZE_T num, SIZE_T size, sort_compare compare) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("qsort(%p, %zu, %zu, %p)\n", base, num, size, compar);
|
DEBUG_LOG("qsort(%p, %zu, %zu, %p)\n", base, num, size, compare);
|
||||||
std::qsort(base, num, size, compar);
|
currentCompare = compare;
|
||||||
|
::qsort(base, num, size, doCompare);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL fflush(FILE *stream) {
|
int CDECL fflush(_FILE *stream) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("fflush(%p)\n", stream);
|
DEBUG_LOG("fflush(%p)\n", stream);
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
@@ -1818,10 +1845,10 @@ namespace msvcrt {
|
|||||||
return std::fflush(host);
|
return std::fflush(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL_NO_CONV vfwprintf(FILE *stream, const uint16_t *format, va_list args) {
|
int CDECL_NO_CONV vfwprintf(_FILE *stream, const uint16_t *format, va_list args) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("vfwprintf(%p, %s, ...)\n", stream, wideStringToString(format).c_str());
|
DEBUG_LOG("vfwprintf(%p, %s, ...)\n", stream, wideStringToString(format).c_str());
|
||||||
FILE *host = mapToHostFile(stream ? stream : stdout);
|
FILE *host = mapToHostFile(stream ? stream : &_iob[0]);
|
||||||
std::wstring fmt;
|
std::wstring fmt;
|
||||||
if (format) {
|
if (format) {
|
||||||
for (const uint16_t *ptr = format; *ptr; ++ptr) {
|
for (const uint16_t *ptr = format; *ptr; ++ptr) {
|
||||||
@@ -1832,10 +1859,10 @@ namespace msvcrt {
|
|||||||
return std::vfwprintf(host, fmt.c_str(), args);
|
return std::vfwprintf(host, fmt.c_str(), args);
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *CDECL fopen(const char *filename, const char *mode) {
|
_FILE *CDECL fopen(const char *filename, const char *mode) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("fopen(%s, %s)\n", filename ? filename : "(null)", mode ? mode : "(null)");
|
DEBUG_LOG("fopen(%s, %s)\n", filename ? filename : "(null)", mode ? mode : "(null)");
|
||||||
return std::fopen(filename, mode);
|
return mapToGuestFile(std::fopen(filename, mode));
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL _dup2(int fd1, int fd2) {
|
int CDECL _dup2(int fd1, int fd2) {
|
||||||
@@ -1850,25 +1877,28 @@ namespace msvcrt {
|
|||||||
return isatty(fd);
|
return isatty(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL fseek(FILE *stream, long offset, int origin) {
|
int CDECL fseek(_FILE *stream, long offset, int origin) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("fseek(%p, %ld, %d)\n", stream, offset, origin);
|
VERBOSE_LOG("fseek(%p, %ld, %d)\n", stream, offset, origin);
|
||||||
return std::fseek(stream, offset, origin);
|
FILE* host = mapToHostFile(stream);
|
||||||
|
return std::fseek(host, offset, origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
long CDECL ftell(FILE *stream) {
|
long CDECL ftell(_FILE *stream) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("ftell(%p)\n", stream);
|
VERBOSE_LOG("ftell(%p)\n", stream);
|
||||||
return std::ftell(stream);
|
FILE* host = mapToHostFile(stream);
|
||||||
|
return std::ftell(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL feof(FILE *stream) {
|
int CDECL feof(_FILE *stream) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("feof(%p)\n", stream);
|
VERBOSE_LOG("feof(%p)\n", stream);
|
||||||
return std::feof(stream);
|
FILE* host = mapToHostFile(stream);
|
||||||
|
return std::feof(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL fputws(const uint16_t *str, FILE *stream) {
|
int CDECL fputws(const uint16_t *str, _FILE *stream) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("fputws(%s, %p)\n", wideStringToString(str).c_str(), stream);
|
DEBUG_LOG("fputws(%s, %p)\n", wideStringToString(str).c_str(), stream);
|
||||||
std::wstring temp;
|
std::wstring temp;
|
||||||
@@ -1877,23 +1907,25 @@ namespace msvcrt {
|
|||||||
temp.push_back(static_cast<wchar_t>(*cursor));
|
temp.push_back(static_cast<wchar_t>(*cursor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return std::fputws(temp.c_str(), stream);
|
FILE* host = mapToHostFile(stream);
|
||||||
|
return std::fputws(temp.c_str(), host);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL _cputws(const uint16_t *string) {
|
int CDECL _cputws(const uint16_t *string) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("_cputws(%s)\n", wideStringToString(string).c_str());
|
DEBUG_LOG("_cputws(%s)\n", wideStringToString(string).c_str());
|
||||||
return fputws(string, stdout);
|
return fputws(string, &_iob[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t* CDECL fgetws(uint16_t *buffer, int size, FILE *stream) {
|
uint16_t* CDECL fgetws(uint16_t *buffer, int size, _FILE *stream) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("fgetws(%p, %d, %p)\n", buffer, size, stream);
|
DEBUG_LOG("fgetws(%p, %d, %p)\n", buffer, size, stream);
|
||||||
if (!buffer || size <= 0) {
|
if (!buffer || size <= 0) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
std::vector<wchar_t> temp(static_cast<SIZE_T>(size));
|
std::vector<wchar_t> temp(static_cast<SIZE_T>(size));
|
||||||
wchar_t *res = std::fgetws(temp.data(), size, stream);
|
FILE* host = mapToHostFile(stream);
|
||||||
|
wchar_t *res = std::fgetws(temp.data(), size, host);
|
||||||
if (!res) {
|
if (!res) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -1906,13 +1938,14 @@ namespace msvcrt {
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
WINT_T CDECL fgetwc(FILE *stream) {
|
WINT_T CDECL fgetwc(_FILE *stream) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("fgetwc(%p)\n", stream);
|
VERBOSE_LOG("fgetwc(%p)\n", stream);
|
||||||
return std::fgetwc(stream);
|
FILE* host = mapToHostFile(stream);
|
||||||
|
return std::fgetwc(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL _wfopen_s(FILE **stream, const uint16_t *filename, const uint16_t *mode) {
|
int CDECL _wfopen_s(_FILE **stream, const uint16_t *filename, const uint16_t *mode) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("_wfopen_s(%p, %s, %s)\n", stream, wideStringToString(filename).c_str(),
|
DEBUG_LOG("_wfopen_s(%p, %s, %s)\n", stream, wideStringToString(filename).c_str(),
|
||||||
wideStringToString(mode).c_str());
|
wideStringToString(mode).c_str());
|
||||||
@@ -1927,7 +1960,7 @@ namespace msvcrt {
|
|||||||
*stream = nullptr;
|
*stream = nullptr;
|
||||||
return errno ? errno : EINVAL;
|
return errno ? errno : EINVAL;
|
||||||
}
|
}
|
||||||
*stream = handle;
|
*stream = mapToGuestFile(handle);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2210,21 +2243,14 @@ namespace msvcrt {
|
|||||||
std::fflush(nullptr);
|
std::fflush(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FILE *resolveFileStream(FILE *stream) {
|
int CDECL_NO_CONV vfprintf(_FILE *stream, const char *format, va_list args) {
|
||||||
if (!stream) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return mapToHostFile(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
int CDECL_NO_CONV vfprintf(FILE *stream, const char *format, va_list args) {
|
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("vfprintf(stream=%p, format=%s, args=%p)\n", stream, format, args);
|
DEBUG_LOG("vfprintf(stream=%p, format=%s, args=%p)\n", stream, format, args);
|
||||||
if (!format || !stream) {
|
if (!format || !stream) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
FILE *native = resolveFileStream(stream);
|
FILE *native = mapToHostFile(stream);
|
||||||
if (!native) {
|
if (!native) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
@@ -2236,7 +2262,7 @@ namespace msvcrt {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL_NO_CONV fprintf(FILE *stream, const char *format, ...) {
|
int CDECL_NO_CONV fprintf(_FILE *stream, const char *format, ...) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("fprintf(%p, %s, ...)\n", stream, format);
|
DEBUG_LOG("fprintf(%p, %s, ...)\n", stream, format);
|
||||||
va_list args;
|
va_list args;
|
||||||
@@ -2246,14 +2272,14 @@ namespace msvcrt {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL fputc(int ch, FILE *stream) {
|
int CDECL fputc(int ch, _FILE *stream) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("fputc(%d, %p)\n", ch, stream);
|
DEBUG_LOG("fputc(%d, %p)\n", ch, stream);
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return EOF;
|
return EOF;
|
||||||
}
|
}
|
||||||
FILE *native = resolveFileStream(stream);
|
FILE *native = mapToHostFile(stream);
|
||||||
if (!native) {
|
if (!native) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return EOF;
|
return EOF;
|
||||||
@@ -2261,14 +2287,14 @@ namespace msvcrt {
|
|||||||
return std::fputc(ch, native);
|
return std::fputc(ch, native);
|
||||||
}
|
}
|
||||||
|
|
||||||
SIZE_T CDECL fwrite(const void *buffer, SIZE_T size, SIZE_T count, FILE *stream) {
|
SIZE_T CDECL fwrite(const void *buffer, SIZE_T size, SIZE_T count, _FILE *stream) {
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
DEBUG_LOG("fwrite(%p, %zu, %zu, %p)\n", buffer, size, count, stream);
|
DEBUG_LOG("fwrite(%p, %zu, %zu, %p)\n", buffer, size, count, stream);
|
||||||
if (!buffer || !stream) {
|
if (!buffer || !stream) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
FILE *native = resolveFileStream(stream);
|
FILE *native = mapToHostFile(stream);
|
||||||
if (!native) {
|
if (!native) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2808,7 +2834,7 @@ namespace msvcrt {
|
|||||||
return wstrtoul(strSource, endptr, base);
|
return wstrtoul(strSource, endptr, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* CDECL _wfsopen(const uint16_t* filename, const uint16_t* mode, int shflag){
|
_FILE* CDECL _wfsopen(const uint16_t* filename, const uint16_t* mode, int shflag){
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
if (!filename || !mode) return nullptr;
|
if (!filename || !mode) return nullptr;
|
||||||
std::string fname_str = wideStringToString(filename);
|
std::string fname_str = wideStringToString(filename);
|
||||||
@@ -2832,10 +2858,10 @@ namespace msvcrt {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL fclose(FILE* stream){
|
int CDECL fclose(_FILE* stream){
|
||||||
HOST_CONTEXT_GUARD();
|
HOST_CONTEXT_GUARD();
|
||||||
VERBOSE_LOG("fclose(%p)\n", stream);
|
VERBOSE_LOG("fclose(%p)\n", stream);
|
||||||
return ::fclose(stream);
|
return closeGuestFile(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CDECL _flushall(){
|
int CDECL _flushall(){
|
||||||
@@ -2843,9 +2869,15 @@ namespace msvcrt {
|
|||||||
DEBUG_LOG("_flushall()\n");
|
DEBUG_LOG("_flushall()\n");
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
if (msvcrt::fflush(stdin) == 0) count++;
|
if (::fflush(stdin) == 0) count++;
|
||||||
if (msvcrt::fflush(stdout) == 0) count++;
|
if (::fflush(stdout) == 0) count++;
|
||||||
if (msvcrt::fflush(stderr) == 0) count++;
|
if (::fflush(stderr) == 0) count++;
|
||||||
|
|
||||||
|
std::lock_guard lock(g_fileMutex);
|
||||||
|
for (auto &file : g_files) {
|
||||||
|
if (::fflush(file.second) == 0)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|||||||
79
dll/msvcrt.h
79
dll/msvcrt.h
@@ -7,7 +7,9 @@ using WINT_T = unsigned short;
|
|||||||
|
|
||||||
typedef void(_CC_CDECL *_PVFV)();
|
typedef void(_CC_CDECL *_PVFV)();
|
||||||
typedef int(_CC_CDECL *_PIFV)();
|
typedef int(_CC_CDECL *_PIFV)();
|
||||||
using _onexit_t = _PIFV;
|
typedef int(_CC_CDECL *_onexit_t)();
|
||||||
|
typedef void(_CC_CDECL *signal_handler)(int);
|
||||||
|
typedef int(_CC_CDECL *sort_compare)(const void *, const void *);
|
||||||
|
|
||||||
struct _utimbuf {
|
struct _utimbuf {
|
||||||
long actime;
|
long actime;
|
||||||
@@ -21,31 +23,26 @@ struct _timeb {
|
|||||||
short dstflag;
|
short dstflag;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void(_CC_CDECL *signal_handler)(int);
|
|
||||||
using FILE = struct _IO_FILE;
|
|
||||||
|
|
||||||
struct IOBProxy {
|
|
||||||
char *_ptr;
|
|
||||||
int _cnt;
|
|
||||||
char *_base;
|
|
||||||
int _flag;
|
|
||||||
int _file;
|
|
||||||
int _charbuf;
|
|
||||||
int _bufsiz;
|
|
||||||
char *_tmpfname;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct lconv;
|
struct lconv;
|
||||||
|
|
||||||
namespace msvcrt {
|
namespace msvcrt {
|
||||||
|
|
||||||
IOBProxy *CDECL __iob_func();
|
extern int _commode;
|
||||||
IOBProxy *CDECL __p__iob();
|
extern int _fmode;
|
||||||
void CDECL setbuf(FILE *stream, char *buffer);
|
extern char **__initenv;
|
||||||
|
extern WCHAR **__winitenv;
|
||||||
|
extern WCHAR *_wpgmptr;
|
||||||
|
extern char *_pgmptr;
|
||||||
|
extern int __mb_cur_max;
|
||||||
|
extern _FILE _iob[_IOB_ENTRIES];
|
||||||
|
|
||||||
|
_FILE *CDECL __iob_func();
|
||||||
|
_FILE *CDECL __p__iob();
|
||||||
|
void CDECL setbuf(_FILE *stream, char *buffer);
|
||||||
void CDECL _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext);
|
void CDECL _splitpath(const char *path, char *drive, char *dir, char *fname, char *ext);
|
||||||
int CDECL _fileno(FILE *stream);
|
int CDECL _fileno(_FILE *stream);
|
||||||
int CDECL _getmbcp();
|
int CDECL _getmbcp();
|
||||||
unsigned int *CDECL __p___mb_cur_max();
|
int *CDECL __p___mb_cur_max();
|
||||||
int CDECL _setmbcp(int codepage);
|
int CDECL _setmbcp(int codepage);
|
||||||
unsigned char *CDECL __p__mbctype();
|
unsigned char *CDECL __p__mbctype();
|
||||||
unsigned short **CDECL __p__pctype();
|
unsigned short **CDECL __p__pctype();
|
||||||
@@ -57,7 +54,7 @@ void CDECL _initterm(const _PVFV *ppfn, const _PVFV *end);
|
|||||||
int CDECL _initterm_e(const _PIFV *ppfn, const _PIFV *end);
|
int CDECL _initterm_e(const _PIFV *ppfn, const _PIFV *end);
|
||||||
unsigned int CDECL _controlfp(unsigned int newControl, unsigned int mask);
|
unsigned int CDECL _controlfp(unsigned int newControl, unsigned int mask);
|
||||||
int CDECL _controlfp_s(unsigned int *currentControl, unsigned int newControl, unsigned int mask);
|
int CDECL _controlfp_s(unsigned int *currentControl, unsigned int newControl, unsigned int mask);
|
||||||
_PIFV CDECL _onexit(_PIFV func);
|
_onexit_t CDECL _onexit(_onexit_t func);
|
||||||
int CDECL __wgetmainargs(int *wargc, WCHAR ***wargv, WCHAR ***wenv, int doWildcard, int *startInfo);
|
int CDECL __wgetmainargs(int *wargc, WCHAR ***wargv, WCHAR ***wenv, int doWildcard, int *startInfo);
|
||||||
int CDECL __getmainargs(int *argc, char ***argv, char ***env, int doWildcard, int *startInfo);
|
int CDECL __getmainargs(int *argc, char ***argv, char ***env, int doWildcard, int *startInfo);
|
||||||
char *CDECL getenv(const char *varname);
|
char *CDECL getenv(const char *varname);
|
||||||
@@ -92,9 +89,9 @@ int CDECL_NO_CONV _snprintf(char *buffer, SIZE_T count, const char *format, ...)
|
|||||||
int CDECL_NO_CONV sprintf(char *buffer, const char *format, ...);
|
int CDECL_NO_CONV sprintf(char *buffer, const char *format, ...);
|
||||||
int CDECL_NO_CONV printf(const char *format, ...);
|
int CDECL_NO_CONV printf(const char *format, ...);
|
||||||
int CDECL_NO_CONV sscanf(const char *buffer, const char *format, ...);
|
int CDECL_NO_CONV sscanf(const char *buffer, const char *format, ...);
|
||||||
char *CDECL fgets(char *str, int count, FILE *stream);
|
char *CDECL fgets(char *str, int count, _FILE *stream);
|
||||||
SIZE_T CDECL fread(void *buffer, SIZE_T size, SIZE_T count, FILE *stream);
|
SIZE_T CDECL fread(void *buffer, SIZE_T size, SIZE_T count, _FILE *stream);
|
||||||
FILE *CDECL _fsopen(const char *filename, const char *mode, int shflag);
|
_FILE *CDECL _fsopen(const char *filename, const char *mode, int shflag);
|
||||||
int CDECL _sopen(const char *path, int oflag, int shflag, int pmode);
|
int CDECL _sopen(const char *path, int oflag, int shflag, int pmode);
|
||||||
int CDECL _read(int fd, void *buffer, unsigned int count);
|
int CDECL _read(int fd, void *buffer, unsigned int count);
|
||||||
int CDECL _close(int fd);
|
int CDECL _close(int fd);
|
||||||
@@ -144,20 +141,20 @@ void CDECL free(void *ptr);
|
|||||||
void *CDECL memcpy(void *dest, const void *src, SIZE_T count);
|
void *CDECL memcpy(void *dest, const void *src, SIZE_T count);
|
||||||
void *CDECL memmove(void *dest, const void *src, SIZE_T count);
|
void *CDECL memmove(void *dest, const void *src, SIZE_T count);
|
||||||
int CDECL memcmp(const void *lhs, const void *rhs, SIZE_T count);
|
int CDECL memcmp(const void *lhs, const void *rhs, SIZE_T count);
|
||||||
void CDECL qsort(void *base, SIZE_T num, SIZE_T size, int (*compar)(const void *, const void *));
|
void CDECL qsort(void *base, SIZE_T num, SIZE_T size, sort_compare compare);
|
||||||
int CDECL fflush(FILE *stream);
|
int CDECL fflush(_FILE *stream);
|
||||||
int CDECL_NO_CONV vfwprintf(FILE *stream, const WCHAR *format, va_list args);
|
int CDECL_NO_CONV vfwprintf(_FILE *stream, const WCHAR *format, va_list args);
|
||||||
FILE *CDECL fopen(const char *filename, const char *mode);
|
_FILE *CDECL fopen(const char *filename, const char *mode);
|
||||||
int CDECL _dup2(int fd1, int fd2);
|
int CDECL _dup2(int fd1, int fd2);
|
||||||
int CDECL _isatty(int fd);
|
int CDECL _isatty(int fd);
|
||||||
int CDECL fseek(FILE *stream, long offset, int origin);
|
int CDECL fseek(_FILE *stream, long offset, int origin);
|
||||||
long CDECL ftell(FILE *stream);
|
long CDECL ftell(_FILE *stream);
|
||||||
int CDECL feof(FILE *stream);
|
int CDECL feof(_FILE *stream);
|
||||||
int CDECL fputws(const WCHAR *str, FILE *stream);
|
int CDECL fputws(const WCHAR *str, _FILE *stream);
|
||||||
int CDECL _cputws(const WCHAR *string);
|
int CDECL _cputws(const WCHAR *string);
|
||||||
WCHAR *CDECL fgetws(WCHAR *buffer, int size, FILE *stream);
|
WCHAR *CDECL fgetws(WCHAR *buffer, int size, _FILE *stream);
|
||||||
WINT_T CDECL fgetwc(FILE *stream);
|
WINT_T CDECL fgetwc(_FILE *stream);
|
||||||
int CDECL _wfopen_s(FILE **stream, const WCHAR *filename, const WCHAR *mode);
|
int CDECL _wfopen_s(_FILE **stream, const WCHAR *filename, const WCHAR *mode);
|
||||||
int CDECL _wcsicmp(const WCHAR *lhs, const WCHAR *rhs);
|
int CDECL _wcsicmp(const WCHAR *lhs, const WCHAR *rhs);
|
||||||
int CDECL _wmakepath_s(WCHAR *path, SIZE_T sizeInWords, const WCHAR *drive, const WCHAR *dir, const WCHAR *fname,
|
int CDECL _wmakepath_s(WCHAR *path, SIZE_T sizeInWords, const WCHAR *drive, const WCHAR *dir, const WCHAR *fname,
|
||||||
const WCHAR *ext);
|
const WCHAR *ext);
|
||||||
@@ -175,10 +172,10 @@ int CDECL _crt_debugger_hook(int value);
|
|||||||
int CDECL _configthreadlocale(int mode);
|
int CDECL _configthreadlocale(int mode);
|
||||||
void CDECL __setusermatherr(void *handler);
|
void CDECL __setusermatherr(void *handler);
|
||||||
void CDECL _cexit();
|
void CDECL _cexit();
|
||||||
int CDECL_NO_CONV vfprintf(FILE *stream, const char *format, va_list args);
|
int CDECL_NO_CONV vfprintf(_FILE *stream, const char *format, va_list args);
|
||||||
int CDECL_NO_CONV fprintf(FILE *stream, const char *format, ...);
|
int CDECL_NO_CONV fprintf(_FILE *stream, const char *format, ...);
|
||||||
int CDECL fputc(int ch, FILE *stream);
|
int CDECL fputc(int ch, _FILE *stream);
|
||||||
SIZE_T CDECL fwrite(const void *buffer, SIZE_T size, SIZE_T count, FILE *stream);
|
SIZE_T CDECL fwrite(const void *buffer, SIZE_T size, SIZE_T count, _FILE *stream);
|
||||||
char *CDECL strerror(int errnum);
|
char *CDECL strerror(int errnum);
|
||||||
char *CDECL strchr(const char *str, int character);
|
char *CDECL strchr(const char *str, int character);
|
||||||
struct lconv *CDECL localeconv();
|
struct lconv *CDECL localeconv();
|
||||||
@@ -220,9 +217,9 @@ int CDECL iswdigit(WINT_T w);
|
|||||||
const WCHAR *CDECL wcschr(const WCHAR *str, WCHAR c);
|
const WCHAR *CDECL wcschr(const WCHAR *str, WCHAR c);
|
||||||
const WCHAR *CDECL wcsrchr(const WCHAR *str, WCHAR c);
|
const WCHAR *CDECL wcsrchr(const WCHAR *str, WCHAR c);
|
||||||
unsigned long CDECL wcstoul(const WCHAR *strSource, WCHAR **endptr, int base);
|
unsigned long CDECL wcstoul(const WCHAR *strSource, WCHAR **endptr, int base);
|
||||||
FILE *CDECL _wfsopen(const WCHAR *filename, const WCHAR *mode, int shflag);
|
_FILE *CDECL _wfsopen(const WCHAR *filename, const WCHAR *mode, int shflag);
|
||||||
int CDECL puts(const char *str);
|
int CDECL puts(const char *str);
|
||||||
int CDECL fclose(FILE *stream);
|
int CDECL fclose(_FILE *stream);
|
||||||
int CDECL _flushall();
|
int CDECL _flushall();
|
||||||
int *CDECL _errno();
|
int *CDECL _errno();
|
||||||
LONG_PTR CDECL _wspawnvp(int mode, const WCHAR *cmdname, const WCHAR *const *argv);
|
LONG_PTR CDECL _wspawnvp(int mode, const WCHAR *cmdname, const WCHAR *const *argv);
|
||||||
|
|||||||
16
src/types.h
16
src/types.h
@@ -444,3 +444,19 @@ typedef struct _MEMORY_BASIC_INFORMATION {
|
|||||||
DWORD Protect;
|
DWORD Protect;
|
||||||
DWORD Type;
|
DWORD Type;
|
||||||
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
|
} MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
|
||||||
|
|
||||||
|
#define _IOB_ENTRIES 20
|
||||||
|
|
||||||
|
typedef struct _iobuf {
|
||||||
|
_iobuf() : _file(-1) {}
|
||||||
|
explicit _iobuf(int file) : _file(file) {}
|
||||||
|
|
||||||
|
char *_ptr = nullptr;
|
||||||
|
int _cnt = 0;
|
||||||
|
char *_base = nullptr;
|
||||||
|
int _flag = 0;
|
||||||
|
int _file;
|
||||||
|
int _charbuf = 0;
|
||||||
|
int _bufsiz = 0;
|
||||||
|
char *_tmpfname = nullptr;
|
||||||
|
} _FILE;
|
||||||
|
|||||||
@@ -29,14 +29,13 @@ from clang.cindex import (
|
|||||||
Cursor,
|
Cursor,
|
||||||
CursorKind,
|
CursorKind,
|
||||||
Index,
|
Index,
|
||||||
|
StorageClass,
|
||||||
TranslationUnit,
|
TranslationUnit,
|
||||||
Type,
|
Type,
|
||||||
TypeKind,
|
TypeKind,
|
||||||
conf,
|
conf,
|
||||||
)
|
)
|
||||||
from clang.cindex import (
|
from clang.cindex import Type as CXType
|
||||||
Type as CXType,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Allow libclang path to be specified via environment variable
|
# Allow libclang path to be specified via environment variable
|
||||||
if "LIBCLANG_PATH" in os.environ:
|
if "LIBCLANG_PATH" in os.environ:
|
||||||
@@ -123,6 +122,12 @@ class TypedefInfo:
|
|||||||
args: List[ArgInfo] = field(default_factory=list)
|
args: List[ArgInfo] = field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class VarInfo:
|
||||||
|
qualified_ns: str
|
||||||
|
name: str
|
||||||
|
|
||||||
|
|
||||||
def parse_tu(
|
def parse_tu(
|
||||||
headers: List[str], include_dirs: List[str], target: str
|
headers: List[str], include_dirs: List[str], target: str
|
||||||
) -> TranslationUnit:
|
) -> TranslationUnit:
|
||||||
@@ -338,6 +343,35 @@ def collect_typedefs(tu: TranslationUnit) -> List[TypedefInfo]:
|
|||||||
return sorted(out.values(), key=lambda t: t.name)
|
return sorted(out.values(), key=lambda t: t.name)
|
||||||
|
|
||||||
|
|
||||||
|
def collect_variables(tu: TranslationUnit, ns_filter: Optional[str]) -> List[VarInfo]:
|
||||||
|
"""Collect extern variable declarations from the translation unit."""
|
||||||
|
want_ns = ns_filter.split("::") if ns_filter else None
|
||||||
|
out: dict[str, VarInfo] = {}
|
||||||
|
|
||||||
|
def visit(node: Cursor) -> None:
|
||||||
|
if node.kind == CursorKind.VAR_DECL:
|
||||||
|
if node.storage_class != StorageClass.EXTERN or node.is_definition():
|
||||||
|
return
|
||||||
|
ns_parts = _cursor_namespace(node)
|
||||||
|
if want_ns is not None and ns_parts != want_ns:
|
||||||
|
return
|
||||||
|
name = node.spelling
|
||||||
|
if not name:
|
||||||
|
return
|
||||||
|
out[name] = VarInfo(
|
||||||
|
qualified_ns="::".join(ns_parts),
|
||||||
|
name=name,
|
||||||
|
)
|
||||||
|
|
||||||
|
if node.kind in (CursorKind.TRANSLATION_UNIT, CursorKind.NAMESPACE):
|
||||||
|
for c in node.get_children():
|
||||||
|
visit(c)
|
||||||
|
|
||||||
|
if tu.cursor is not None:
|
||||||
|
visit(tu.cursor)
|
||||||
|
return sorted(out.values(), key=lambda v: v.name)
|
||||||
|
|
||||||
|
|
||||||
def emit_cc_thunk(f: FuncInfo | TypedefInfo, lines: List[str]):
|
def emit_cc_thunk(f: FuncInfo | TypedefInfo, lines: List[str]):
|
||||||
if isinstance(f, TypedefInfo):
|
if isinstance(f, TypedefInfo):
|
||||||
# Host-to-guest
|
# Host-to-guest
|
||||||
@@ -543,7 +577,10 @@ def emit_host_to_guest_thunks(
|
|||||||
|
|
||||||
|
|
||||||
def emit_header_mapping(
|
def emit_header_mapping(
|
||||||
dll: str, funcs: Iterable[FuncInfo], typedefs: Iterable[TypedefInfo]
|
dll: str,
|
||||||
|
funcs: Iterable[FuncInfo],
|
||||||
|
typedefs: Iterable[TypedefInfo],
|
||||||
|
variables: Iterable[VarInfo],
|
||||||
) -> str:
|
) -> str:
|
||||||
guard = f"WIBO_GEN_{dll.upper()}_THUNKS_H"
|
guard = f"WIBO_GEN_{dll.upper()}_THUNKS_H"
|
||||||
lines: List[str] = []
|
lines: List[str] = []
|
||||||
@@ -616,6 +653,11 @@ def emit_header_mapping(
|
|||||||
lines.append(
|
lines.append(
|
||||||
f'\tif (strcmp(name, "{f.name}") == 0) return (void*)&thunk_{dll}_{f.name};'
|
f'\tif (strcmp(name, "{f.name}") == 0) return (void*)&thunk_{dll}_{f.name};'
|
||||||
)
|
)
|
||||||
|
for v in variables:
|
||||||
|
qualified = f"{v.qualified_ns}::{v.name}" if v.qualified_ns else v.name
|
||||||
|
lines.append(
|
||||||
|
f'\tif (strcmp(name, "{v.name}") == 0) return (void*)&{qualified};'
|
||||||
|
)
|
||||||
lines.append("\treturn NULL;")
|
lines.append("\treturn NULL;")
|
||||||
lines.append("}")
|
lines.append("}")
|
||||||
|
|
||||||
@@ -644,9 +686,10 @@ def main() -> int:
|
|||||||
tu = parse_tu(args.headers, args.incs, target)
|
tu = parse_tu(args.headers, args.incs, target)
|
||||||
funcs = collect_functions(tu, args.ns)
|
funcs = collect_functions(tu, args.ns)
|
||||||
typedefs = collect_typedefs(tu)
|
typedefs = collect_typedefs(tu)
|
||||||
|
variables = collect_variables(tu, args.ns)
|
||||||
|
|
||||||
if not funcs and not typedefs:
|
if not funcs and not typedefs and not variables:
|
||||||
sys.stderr.write("No functions or typedefs found for generation.\n")
|
sys.stderr.write("No functions, typedefs, or variables found for generation.\n")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
lines: List[str] = []
|
lines: List[str] = []
|
||||||
@@ -659,7 +702,7 @@ def main() -> int:
|
|||||||
emit_host_to_guest_thunks(lines, typedefs)
|
emit_host_to_guest_thunks(lines, typedefs)
|
||||||
|
|
||||||
asm = "\n".join(lines) + "\n"
|
asm = "\n".join(lines) + "\n"
|
||||||
hdr = emit_header_mapping(args.dll, funcs, typedefs)
|
hdr = emit_header_mapping(args.dll, funcs, typedefs, variables)
|
||||||
|
|
||||||
args.out_asm.parent.mkdir(parents=True, exist_ok=True)
|
args.out_asm.parent.mkdir(parents=True, exist_ok=True)
|
||||||
args.out_hdr.parent.mkdir(parents=True, exist_ok=True)
|
args.out_hdr.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user