mirror of https://github.com/decompals/wibo.git
Everything needed to run simple Rust programs (#40)
* Everything needed to run simple Rust programs * Add IsDBCSLeadByte implementation * Address PR comments
This commit is contained in:
parent
6e18120410
commit
94b44fd697
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
BasedOnStyle: LLVM
|
||||
IndentWidth: 4
|
||||
TabWidth: 4
|
||||
UseTab: Always
|
||||
ColumnLimit: 120
|
|
@ -0,0 +1,146 @@
|
|||
---
|
||||
Checks: '-*,
|
||||
bugprone-argument-comment,
|
||||
bugprone-assert-side-effect,
|
||||
bugprone-bad-signal-to-kill-thread,
|
||||
bugprone-branch-clone,
|
||||
bugprone-copy-constructor-init,
|
||||
bugprone-dangling-handle,
|
||||
bugprone-dynamic-static-initializers,
|
||||
bugprone-fold-init-type,
|
||||
bugprone-forward-declaration-namespace,
|
||||
bugprone-forwarding-reference-overload,
|
||||
bugprone-inaccurate-erase,
|
||||
bugprone-incorrect-roundings,
|
||||
bugprone-integer-division,
|
||||
bugprone-lambda-function-name,
|
||||
bugprone-macro-parentheses,
|
||||
bugprone-macro-repeated-side-effects,
|
||||
bugprone-misplaced-operator-in-strlen-in-alloc,
|
||||
bugprone-misplaced-pointer-arithmetic-in-alloc,
|
||||
bugprone-misplaced-widening-cast,
|
||||
bugprone-move-forwarding-reference,
|
||||
bugprone-multiple-statement-macro,
|
||||
bugprone-no-escape,
|
||||
bugprone-not-null-terminated-result,
|
||||
bugprone-parent-virtual-call,
|
||||
bugprone-posix-return,
|
||||
bugprone-sizeof-container,
|
||||
bugprone-sizeof-expression,
|
||||
bugprone-spuriously-wake-up-functions,
|
||||
bugprone-string-constructor,
|
||||
bugprone-string-integer-assignment,
|
||||
bugprone-string-literal-with-embedded-nul,
|
||||
bugprone-suspicious-enum-usage,
|
||||
bugprone-suspicious-include,
|
||||
bugprone-suspicious-memset-usage,
|
||||
bugprone-suspicious-missing-comma,
|
||||
bugprone-suspicious-semicolon,
|
||||
bugprone-suspicious-string-compare,
|
||||
bugprone-suspicious-memory-comparison,
|
||||
bugprone-suspicious-realloc-usage,
|
||||
bugprone-swapped-arguments,
|
||||
bugprone-terminating-continue,
|
||||
bugprone-throw-keyword-missing,
|
||||
bugprone-too-small-loop-variable,
|
||||
bugprone-undefined-memory-manipulation,
|
||||
bugprone-undelegated-constructor,
|
||||
bugprone-unhandled-self-assignment,
|
||||
bugprone-unused-raii,
|
||||
bugprone-unused-return-value,
|
||||
bugprone-use-after-move,
|
||||
bugprone-virtual-near-miss,
|
||||
cert-dcl21-cpp,
|
||||
cert-dcl58-cpp,
|
||||
cert-err34-c,
|
||||
cert-err52-cpp,
|
||||
cert-err60-cpp,
|
||||
cert-flp30-c,
|
||||
cert-msc50-cpp,
|
||||
cert-msc51-cpp,
|
||||
cert-str34-c,
|
||||
cppcoreguidelines-interfaces-global-init,
|
||||
cppcoreguidelines-narrowing-conversions,
|
||||
cppcoreguidelines-pro-type-member-init,
|
||||
cppcoreguidelines-pro-type-static-cast-downcast,
|
||||
cppcoreguidelines-slicing,
|
||||
google-default-arguments,
|
||||
google-explicit-constructor,
|
||||
google-runtime-operator,
|
||||
hicpp-exception-baseclass,
|
||||
hicpp-multiway-paths-covered,
|
||||
misc-misplaced-const,
|
||||
misc-new-delete-overloads,
|
||||
misc-no-recursion,
|
||||
misc-non-copyable-objects,
|
||||
misc-throw-by-value-catch-by-reference,
|
||||
misc-unconventional-assign-operator,
|
||||
misc-uniqueptr-reset-release,
|
||||
modernize-avoid-bind,
|
||||
modernize-concat-nested-namespaces,
|
||||
modernize-deprecated-headers,
|
||||
modernize-deprecated-ios-base-aliases,
|
||||
modernize-loop-convert,
|
||||
modernize-make-shared,
|
||||
modernize-make-unique,
|
||||
modernize-pass-by-value,
|
||||
modernize-raw-string-literal,
|
||||
modernize-redundant-void-arg,
|
||||
modernize-replace-auto-ptr,
|
||||
modernize-replace-disallow-copy-and-assign-macro,
|
||||
modernize-replace-random-shuffle,
|
||||
modernize-return-braced-init-list,
|
||||
modernize-shrink-to-fit,
|
||||
modernize-unary-static-assert,
|
||||
modernize-use-auto,
|
||||
modernize-use-bool-literals,
|
||||
modernize-use-emplace,
|
||||
modernize-use-equals-default,
|
||||
modernize-use-equals-delete,
|
||||
modernize-use-nodiscard,
|
||||
modernize-use-noexcept,
|
||||
modernize-use-nullptr,
|
||||
modernize-use-override,
|
||||
modernize-use-transparent-functors,
|
||||
modernize-use-uncaught-exceptions,
|
||||
mpi-buffer-deref,
|
||||
mpi-type-mismatch,
|
||||
openmp-use-default-none,
|
||||
performance-faster-string-find,
|
||||
performance-for-range-copy,
|
||||
performance-implicit-conversion-in-loop,
|
||||
performance-inefficient-algorithm,
|
||||
performance-inefficient-string-concatenation,
|
||||
performance-inefficient-vector-operation,
|
||||
performance-move-const-arg,
|
||||
performance-move-constructor-init,
|
||||
performance-no-automatic-move,
|
||||
performance-noexcept-move-constructor,
|
||||
performance-trivially-destructible,
|
||||
performance-type-promotion-in-math-fn,
|
||||
performance-unnecessary-copy-initialization,
|
||||
performance-unnecessary-value-param,
|
||||
portability-simd-intrinsics,
|
||||
readability-avoid-const-params-in-decls,
|
||||
readability-const-return-type,
|
||||
readability-container-size-empty,
|
||||
readability-convert-member-functions-to-static,
|
||||
readability-delete-null-pointer,
|
||||
readability-deleted-default,
|
||||
readability-inconsistent-declaration-parameter-name,
|
||||
readability-make-member-function-const,
|
||||
readability-misleading-indentation,
|
||||
readability-misplaced-array-index,
|
||||
readability-non-const-parameter,
|
||||
readability-redundant-control-flow,
|
||||
readability-redundant-declaration,
|
||||
readability-redundant-function-ptr-dereference,
|
||||
readability-redundant-smartptr-get,
|
||||
readability-redundant-string-cstr,
|
||||
readability-redundant-string-init,
|
||||
readability-simplify-subscript-expr,
|
||||
readability-static-accessed-through-instance,
|
||||
readability-static-definition-in-anonymous-namespace,
|
||||
readability-string-compare,
|
||||
readability-uniqueptr-delete-release,
|
||||
readability-use-anyofallof'
|
|
@ -16,10 +16,14 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -Wall")
|
|||
include_directories(.)
|
||||
add_executable(wibo
|
||||
dll/advapi32.cpp
|
||||
dll/bcrypt.cpp
|
||||
dll/crt.cpp
|
||||
dll/kernel32.cpp
|
||||
dll/lmgr.cpp
|
||||
dll/ntdll.cpp
|
||||
dll/ole32.cpp
|
||||
dll/user32.cpp
|
||||
dll/vcruntime.cpp
|
||||
dll/version.cpp
|
||||
files.cpp
|
||||
handles.cpp
|
||||
|
|
91
common.h
91
common.h
|
@ -1,10 +1,11 @@
|
|||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
// On Windows, the incoming stack is aligned to a 4 byte boundary.
|
||||
// force_align_arg_pointer will realign the stack to match GCC's 16 byte alignment.
|
||||
|
@ -12,25 +13,83 @@
|
|||
#define WIN_FUNC WIN_ENTRY __attribute__((stdcall))
|
||||
#define DEBUG_LOG(...) wibo::debug_log(__VA_ARGS__)
|
||||
|
||||
namespace user32 {
|
||||
int WIN_FUNC MessageBoxA(void *hwnd, const char *lpText, const char *lpCaption, unsigned int uType);
|
||||
}
|
||||
typedef void *HANDLE;
|
||||
typedef void *HMODULE;
|
||||
typedef void *PVOID;
|
||||
typedef void *LPVOID;
|
||||
typedef void *FARPROC;
|
||||
typedef uint32_t DWORD;
|
||||
typedef DWORD *PDWORD;
|
||||
typedef DWORD *LPDWORD;
|
||||
typedef int32_t LONG;
|
||||
typedef LONG *PLONG;
|
||||
typedef uint32_t ULONG;
|
||||
typedef ULONG *PULONG;
|
||||
typedef int64_t LARGE_INTEGER;
|
||||
typedef LARGE_INTEGER *PLARGE_INTEGER;
|
||||
typedef uintptr_t ULONG_PTR;
|
||||
typedef char *LPSTR;
|
||||
typedef const char *LPCSTR;
|
||||
typedef uint16_t *LPWSTR;
|
||||
typedef const uint16_t *LPCWSTR;
|
||||
typedef int BOOL;
|
||||
typedef BOOL *PBOOL;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef UCHAR *PUCHAR;
|
||||
typedef size_t SIZE_T;
|
||||
typedef SIZE_T *PSIZE_T;
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define ERROR_SUCCESS 0
|
||||
#define ERROR_FILE_NOT_FOUND 2
|
||||
#define ERROR_PATH_NOT_FOUND 3
|
||||
#define ERROR_ACCESS_DENIED 5
|
||||
#define ERROR_INVALID_HANDLE 6
|
||||
#define ERROR_READ_FAULT 30
|
||||
#define ERROR_HANDLE_EOF 38
|
||||
#define ERROR_NOT_SUPPORTED 50
|
||||
#define ERROR_INVALID_PARAMETER 87
|
||||
#define ERROR_NEGATIVE_SEEK 131
|
||||
#define ERROR_ALREADY_EXISTS 183
|
||||
|
||||
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
|
||||
#define INVALID_HANDLE_VALUE ((HANDLE)-1)
|
||||
|
||||
typedef int NTSTATUS;
|
||||
#define STATUS_SUCCESS ((NTSTATUS)0x00000000)
|
||||
#define STATUS_INVALID_HANDLE ((NTSTATUS)0xC0000008)
|
||||
#define STATUS_END_OF_FILE ((NTSTATUS)0xC0000011)
|
||||
#define STATUS_NOT_SUPPORTED ((NTSTATUS)0xC00000BB)
|
||||
#define STATUS_UNEXPECTED_IO_ERROR ((NTSTATUS)0xC00000E9)
|
||||
|
||||
typedef int HRESULT;
|
||||
#define S_OK ((HRESULT)0x00000000)
|
||||
|
||||
namespace wibo {
|
||||
extern uint32_t lastError;
|
||||
extern char **argv;
|
||||
extern int argc;
|
||||
extern char *commandLine;
|
||||
extern bool debugEnabled;
|
||||
|
||||
void debug_log(const char *fmt, ...);
|
||||
|
||||
void *resolveVersion(const char *name);
|
||||
void *resolveKernel32(const char *name);
|
||||
void *resolveUser32(const char *name);
|
||||
void *resolveOle32(const char *name);
|
||||
void *resolveAdvApi32(const char *name);
|
||||
void *resolveLmgr(uint16_t ordinal);
|
||||
void *resolveFuncByName(const char *dllName, const char *funcName);
|
||||
void *resolveFuncByOrdinal(const char *dllName, uint16_t ordinal);
|
||||
using ResolveByName = void *(*)(const char *);
|
||||
using ResolveByOrdinal = void *(*)(uint16_t);
|
||||
struct Module {
|
||||
const char** names;
|
||||
ResolveByName byName;
|
||||
ResolveByOrdinal byOrdinal;
|
||||
};
|
||||
extern const Module *modules[];
|
||||
|
||||
HMODULE loadModule(const char *name);
|
||||
void freeModule(HMODULE module);
|
||||
void *resolveFuncByName(HMODULE module, const char *funcName);
|
||||
void *resolveFuncByOrdinal(HMODULE module, uint16_t ordinal);
|
||||
|
||||
struct Executable {
|
||||
Executable();
|
||||
|
|
|
@ -7,8 +7,17 @@ namespace advapi32 {
|
|||
}
|
||||
}
|
||||
|
||||
void *wibo::resolveAdvApi32(const char *name) {
|
||||
static void *resolveByName(const char *name) {
|
||||
if (strcmp(name, "RegOpenKeyExA") == 0) return (void *) advapi32::RegOpenKeyExA;
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_advapi32 = {
|
||||
(const char *[]){
|
||||
"advapi32",
|
||||
"advapi32.dll",
|
||||
nullptr,
|
||||
},
|
||||
resolveByName,
|
||||
nullptr,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
#include "common.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <random>
|
||||
|
||||
typedef PVOID BCRYPT_ALG_HANDLE;
|
||||
|
||||
namespace bcrypt {
|
||||
|
||||
using random_bytes_engine = std::independent_bits_engine<std::default_random_engine, CHAR_BIT, unsigned char>;
|
||||
|
||||
NTSTATUS WIN_FUNC BCryptGenRandom(BCRYPT_ALG_HANDLE hAlgorithm, PUCHAR pbBuffer, ULONG cbBuffer, ULONG dwFlags) {
|
||||
DEBUG_LOG("BCryptGenRandom(%p, %p, %lu, %lu)\n", hAlgorithm, pbBuffer, cbBuffer, dwFlags);
|
||||
assert(hAlgorithm == nullptr);
|
||||
assert(dwFlags == 0 || dwFlags == 2 /* BCRYPT_USE_SYSTEM_PREFERRED_RNG */);
|
||||
random_bytes_engine rbe;
|
||||
std::generate(pbBuffer, pbBuffer + cbBuffer, std::ref(rbe));
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace bcrypt
|
||||
|
||||
static void *resolveByName(const char *name) {
|
||||
if (strcmp(name, "BCryptGenRandom") == 0)
|
||||
return (void *)bcrypt::BCryptGenRandom;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_bcrypt = {
|
||||
(const char *[]){
|
||||
"bcrypt",
|
||||
"bcrypt.dll",
|
||||
nullptr,
|
||||
},
|
||||
resolveByName,
|
||||
nullptr,
|
||||
};
|
|
@ -0,0 +1,140 @@
|
|||
#include "common.h"
|
||||
|
||||
typedef void (*_PVFV)();
|
||||
typedef int (*_PIFV)();
|
||||
|
||||
typedef enum _crt_app_type {
|
||||
_crt_unknown_app,
|
||||
_crt_console_app,
|
||||
_crt_gui_app,
|
||||
} _crt_app_type;
|
||||
|
||||
typedef enum _crt_argv_mode {
|
||||
_crt_argv_no_arguments,
|
||||
_crt_argv_unexpanded_arguments,
|
||||
_crt_argv_expanded_arguments,
|
||||
} _crt_argv_mode;
|
||||
|
||||
namespace crt {
|
||||
|
||||
int _commode = 0;
|
||||
|
||||
void WIN_ENTRY _initterm(const _PVFV *ppfn, const _PVFV *end) {
|
||||
do {
|
||||
if (_PVFV pfn = *++ppfn) {
|
||||
pfn();
|
||||
}
|
||||
} while (ppfn < end);
|
||||
}
|
||||
|
||||
int WIN_ENTRY _initterm_e(const _PIFV *ppfn, const _PIFV *end) {
|
||||
do {
|
||||
if (_PIFV pfn = *++ppfn) {
|
||||
if (int err = pfn())
|
||||
return err;
|
||||
}
|
||||
} while (ppfn < end);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void WIN_ENTRY _set_app_type(_crt_app_type type) { DEBUG_LOG("STUB: _set_app_type(%i)\n", type); }
|
||||
|
||||
int WIN_ENTRY _set_fmode(int mode) {
|
||||
DEBUG_LOG("STUB: _set_fmode(%i)\n", mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int *WIN_ENTRY __p__commode() { return &_commode; }
|
||||
|
||||
int WIN_ENTRY _crt_atexit(void (*func)()) {
|
||||
DEBUG_LOG("STUB: _crt_atexit(%p)\n", func);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WIN_ENTRY _configure_narrow_argv(_crt_argv_mode mode) {
|
||||
DEBUG_LOG("STUB: _configure_narrow_argv(%i)\n", mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WIN_ENTRY _controlfp_s(unsigned int *currentControl, unsigned int newControl, unsigned int mask) {
|
||||
DEBUG_LOG("STUB: _controlfp_s(%p, %u, %u)\n", currentControl, newControl, mask);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WIN_ENTRY _configthreadlocale(int per_thread_locale_type) {
|
||||
DEBUG_LOG("STUB: _configthreadlocale(%i)\n", per_thread_locale_type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WIN_ENTRY _initialize_narrow_environment() {
|
||||
DEBUG_LOG("STUB: _initialize_narrow_environment()\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int WIN_ENTRY _set_new_mode(int newhandlermode) {
|
||||
DEBUG_LOG("STUB: _set_new_mode(%i)\n", newhandlermode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char **WIN_ENTRY _get_initial_narrow_environment() { return environ; }
|
||||
|
||||
char ***WIN_ENTRY __p___argv() { return &wibo::argv; }
|
||||
|
||||
int *WIN_ENTRY __p___argc() { return &wibo::argc; }
|
||||
|
||||
size_t WIN_ENTRY strlen(const char *str) { return ::strlen(str); }
|
||||
|
||||
} // namespace crt
|
||||
|
||||
static void *resolveByName(const char *name) {
|
||||
if (strcmp(name, "_initterm") == 0)
|
||||
return (void *)crt::_initterm;
|
||||
if (strcmp(name, "_initterm_e") == 0)
|
||||
return (void *)crt::_initterm_e;
|
||||
if (strcmp(name, "_set_app_type") == 0)
|
||||
return (void *)crt::_set_app_type;
|
||||
if (strcmp(name, "_set_fmode") == 0)
|
||||
return (void *)crt::_set_fmode;
|
||||
if (strcmp(name, "__p__commode") == 0)
|
||||
return (void *)crt::__p__commode;
|
||||
if (strcmp(name, "_crt_atexit") == 0)
|
||||
return (void *)crt::_crt_atexit;
|
||||
if (strcmp(name, "_configure_narrow_argv") == 0)
|
||||
return (void *)crt::_configure_narrow_argv;
|
||||
if (strcmp(name, "_controlfp_s") == 0)
|
||||
return (void *)crt::_controlfp_s;
|
||||
if (strcmp(name, "_configthreadlocale") == 0)
|
||||
return (void *)crt::_configthreadlocale;
|
||||
if (strcmp(name, "_initialize_narrow_environment") == 0)
|
||||
return (void *)crt::_initialize_narrow_environment;
|
||||
if (strcmp(name, "_set_new_mode") == 0)
|
||||
return (void *)crt::_set_new_mode;
|
||||
if (strcmp(name, "_get_initial_narrow_environment") == 0)
|
||||
return (void *)crt::_get_initial_narrow_environment;
|
||||
if (strcmp(name, "__p___argv") == 0)
|
||||
return (void *)crt::__p___argv;
|
||||
if (strcmp(name, "__p___argc") == 0)
|
||||
return (void *)crt::__p___argc;
|
||||
if (strcmp(name, "strlen") == 0)
|
||||
return (void *)crt::strlen;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_crt = {
|
||||
(const char *[]){
|
||||
"api-ms-win-crt-heap-l1-1-0",
|
||||
"api-ms-win-crt-heap-l1-1-0.dll",
|
||||
"api-ms-win-crt-locale-l1-1-0",
|
||||
"api-ms-win-crt-locale-l1-1-0.dll",
|
||||
"api-ms-win-crt-runtime-l1-1-0",
|
||||
"api-ms-win-crt-runtime-l1-1-0.dll",
|
||||
"api-ms-win-crt-stdio-l1-1-0",
|
||||
"api-ms-win-crt-stdio-l1-1-0.dll",
|
||||
"api-ms-win-crt-string-l1-1-0",
|
||||
"api-ms-win-crt-string-l1-1-0.dll",
|
||||
nullptr,
|
||||
},
|
||||
resolveByName,
|
||||
nullptr,
|
||||
};
|
440
dll/kernel32.cpp
440
dll/kernel32.cpp
|
@ -12,6 +12,27 @@
|
|||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
typedef union _RTL_RUN_ONCE {
|
||||
PVOID Ptr;
|
||||
} RTL_RUN_ONCE, *PRTL_RUN_ONCE;
|
||||
typedef PRTL_RUN_ONCE LPINIT_ONCE;
|
||||
|
||||
#define EXCEPTION_MAXIMUM_PARAMETERS 15
|
||||
typedef struct _EXCEPTION_RECORD {
|
||||
DWORD ExceptionCode;
|
||||
DWORD ExceptionFlags;
|
||||
struct _EXCEPTION_RECORD *ExceptionRecord;
|
||||
PVOID ExceptionAddress;
|
||||
DWORD NumberParameters;
|
||||
ULONG_PTR ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
|
||||
} EXCEPTION_RECORD, *PEXCEPTION_RECORD;
|
||||
typedef void *PCONTEXT;
|
||||
typedef struct _EXCEPTION_POINTERS {
|
||||
PEXCEPTION_RECORD ExceptionRecord;
|
||||
PCONTEXT ContextRecord;
|
||||
} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;
|
||||
typedef LONG (*PVECTORED_EXCEPTION_HANDLER)(PEXCEPTION_POINTERS ExceptionInfo);
|
||||
|
||||
namespace kernel32 {
|
||||
static int wstrlen(const uint16_t *str) {
|
||||
int len = 0;
|
||||
|
@ -20,6 +41,17 @@ namespace kernel32 {
|
|||
return len;
|
||||
}
|
||||
|
||||
static int wstrncpy(uint16_t *dst, const uint16_t *src, int n) {
|
||||
int i = 0;
|
||||
while (i < n && src[i] != 0) {
|
||||
dst[i] = src[i];
|
||||
++i;
|
||||
}
|
||||
if (i < n)
|
||||
dst[i] = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
static void *doAlloc(unsigned int dwBytes, bool zero) {
|
||||
if (dwBytes == 0)
|
||||
dwBytes = 1;
|
||||
|
@ -99,15 +131,43 @@ namespace kernel32 {
|
|||
return st.st_size;
|
||||
}
|
||||
|
||||
void setLastErrorFromErrno() {
|
||||
switch (errno) {
|
||||
case 0:
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
break;
|
||||
case EACCES:
|
||||
wibo::lastError = ERROR_ACCESS_DENIED;
|
||||
break;
|
||||
case EEXIST:
|
||||
wibo::lastError = ERROR_ALREADY_EXISTS;
|
||||
break;
|
||||
case ENOENT:
|
||||
wibo::lastError = ERROR_FILE_NOT_FOUND;
|
||||
break;
|
||||
case ENOTDIR:
|
||||
wibo::lastError = ERROR_PATH_NOT_FOUND;
|
||||
break;
|
||||
default:
|
||||
wibo::lastError = ERROR_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t WIN_FUNC GetLastError() {
|
||||
return wibo::lastError;
|
||||
}
|
||||
|
||||
void WIN_FUNC SetLastError(unsigned int dwErrCode) {
|
||||
// DEBUG_LOG("SetLastError %u\n", dwErrCode);
|
||||
DEBUG_LOG("SetLastError(%u)\n", dwErrCode);
|
||||
wibo::lastError = dwErrCode;
|
||||
}
|
||||
|
||||
PVOID WIN_FUNC AddVectoredExceptionHandler(ULONG first, PVECTORED_EXCEPTION_HANDLER handler) {
|
||||
DEBUG_LOG("STUB: AddVectoredExceptionHandler(%u, %p)\n", first, handler);
|
||||
return (PVOID)handler;
|
||||
}
|
||||
|
||||
// @brief returns a pseudo handle to the current process
|
||||
void *WIN_FUNC GetCurrentProcess() {
|
||||
// pseudo handle is always returned, and is -1 (a special constant)
|
||||
|
@ -129,7 +189,7 @@ namespace kernel32 {
|
|||
|
||||
// Cast thread_id to unsigned int to fit a DWORD
|
||||
unsigned int u_thread_id = (unsigned int) thread_id;
|
||||
|
||||
|
||||
return u_thread_id;
|
||||
}
|
||||
|
||||
|
@ -224,6 +284,24 @@ namespace kernel32 {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int WIN_FUNC InitOnceBeginInitialize(LPINIT_ONCE lpInitOnce, DWORD dwFlags, PBOOL fPending, LPVOID* lpContext) {
|
||||
DEBUG_LOG("STUB: InitOnceBeginInitialize\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void WIN_FUNC AcquireSRWLockShared(void *SRWLock) { DEBUG_LOG("STUB: AcquireSRWLockShared(%p)\n", SRWLock); }
|
||||
|
||||
void WIN_FUNC ReleaseSRWLockShared(void *SRWLock) { DEBUG_LOG("STUB: ReleaseSRWLockShared(%p)\n", SRWLock); }
|
||||
|
||||
void WIN_FUNC AcquireSRWLockExclusive(void *SRWLock) { DEBUG_LOG("STUB: AcquireSRWLockExclusive(%p)\n", SRWLock); }
|
||||
|
||||
void WIN_FUNC ReleaseSRWLockExclusive(void *SRWLock) { DEBUG_LOG("STUB: ReleaseSRWLockExclusive(%p)\n", SRWLock); }
|
||||
|
||||
int WIN_FUNC TryAcquireSRWLockExclusive(void *SRWLock) {
|
||||
DEBUG_LOG("STUB: TryAcquireSRWLockExclusive(%p)\n", SRWLock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* TLS (Thread-Local Storage)
|
||||
*/
|
||||
|
@ -305,13 +383,13 @@ namespace kernel32 {
|
|||
/*
|
||||
* Environment
|
||||
*/
|
||||
char *WIN_FUNC GetCommandLineA() {
|
||||
LPSTR WIN_FUNC GetCommandLineA() {
|
||||
DEBUG_LOG("GetCommandLineA\n");
|
||||
return wibo::commandLine;
|
||||
}
|
||||
|
||||
uint16_t *WIN_FUNC GetCommandLineW() {
|
||||
DEBUG_LOG("GetCommandLineW\n");
|
||||
LPWSTR WIN_FUNC GetCommandLineW() {
|
||||
DEBUG_LOG("GetCommandLineW -> ");
|
||||
return stringToWideString(GetCommandLineA());
|
||||
}
|
||||
|
||||
|
@ -408,8 +486,8 @@ namespace kernel32 {
|
|||
assert(0);
|
||||
}
|
||||
|
||||
int WIN_FUNC CloseHandle(void *hObject) {
|
||||
DEBUG_LOG("CloseHandle %p\n", hObject);
|
||||
BOOL WIN_FUNC CloseHandle(HANDLE hObject) {
|
||||
DEBUG_LOG("CloseHandle(%p)\n", hObject);
|
||||
auto data = handles::dataFromHandle(hObject, true);
|
||||
if (data.type == handles::TYPE_FILE) {
|
||||
FILE *fp = (FILE *) data.ptr;
|
||||
|
@ -421,14 +499,14 @@ namespace kernel32 {
|
|||
munmap(data.ptr, data.size);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
unsigned int WIN_FUNC GetFullPathNameA(const char *lpFileName, unsigned int nBufferLength, char *lpBuffer, char **lpFilePart) {
|
||||
DEBUG_LOG("GetFullPathNameA(%s)...\n", lpFileName);
|
||||
DWORD WIN_FUNC GetFullPathNameA(LPCSTR lpFileName, DWORD nBufferLength, LPSTR lpBuffer, LPSTR *lpFilePart) {
|
||||
DEBUG_LOG("GetFullPathNameA(%s) ", lpFileName);
|
||||
std::filesystem::path absPath = std::filesystem::absolute(files::pathFromWindows(lpFileName));
|
||||
std::string absStr = files::pathToWindows(absPath);
|
||||
DEBUG_LOG("AbsPath: %s - %s\n", absPath.c_str(), absStr.c_str());
|
||||
DEBUG_LOG("-> %s\n", absStr.c_str());
|
||||
|
||||
// Enough space?
|
||||
if ((absStr.size() + 1) <= nBufferLength) {
|
||||
|
@ -450,13 +528,36 @@ namespace kernel32 {
|
|||
}
|
||||
}
|
||||
|
||||
DWORD WIN_FUNC GetFullPathNameW(LPCWSTR lpFileName, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR *lpFilePart) {
|
||||
const auto fileName = wideStringToString(lpFileName);
|
||||
DEBUG_LOG("GetFullPathNameW(%s) ", fileName.c_str());
|
||||
|
||||
const auto lpFileNameA = wideStringToString(lpFileName);
|
||||
std::filesystem::path absPath = std::filesystem::absolute(files::pathFromWindows(lpFileNameA.c_str()));
|
||||
std::string absStr = files::pathToWindows(absPath);
|
||||
const auto absStrW = stringToWideString(absStr.c_str());
|
||||
DEBUG_LOG("-> %s\n", absStr.c_str());
|
||||
|
||||
const DWORD absStrWLen = wstrlen(absStrW);
|
||||
const DWORD absStrWSize = absStrWLen * 2;
|
||||
if ((absStrWSize + 2) <= nBufferLength) {
|
||||
wstrncpy(lpBuffer, absStrW, (int)absStrWLen);
|
||||
assert(!lpFilePart);
|
||||
free(absStrW);
|
||||
return absStrWSize;
|
||||
} else {
|
||||
free(absStrW);
|
||||
return absStrWSize + 2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GetShortPathNameA: Retrieves the short path form of the specified path
|
||||
*
|
||||
*
|
||||
* @param[in] lpszLongPath The path string
|
||||
* @param[out] lpszShortPath A pointer to a buffer to receive
|
||||
* @param[in] cchBuffer The size of the buffer that lpszShortPath points to
|
||||
* @return unsigned int
|
||||
* @return unsigned int
|
||||
*/
|
||||
unsigned int WIN_FUNC GetShortPathNameA(const char* lpszLongPath, char* lpszShortPath, unsigned int cchBuffer) {
|
||||
DEBUG_LOG("GetShortPathNameA(%s)...\n",lpszShortPath);
|
||||
|
@ -640,7 +741,7 @@ namespace kernel32 {
|
|||
}
|
||||
|
||||
unsigned int WIN_FUNC WriteFile(void *hFile, const void *lpBuffer, unsigned int nNumberOfBytesToWrite, unsigned int *lpNumberOfBytesWritten, void *lpOverlapped) {
|
||||
DEBUG_LOG("WriteFile %p %d\n", hFile, nNumberOfBytesToWrite);
|
||||
DEBUG_LOG("WriteFile(%p, %d)\n", hFile, nNumberOfBytesToWrite);
|
||||
assert(!lpOverlapped);
|
||||
wibo::lastError = 0;
|
||||
|
||||
|
@ -704,27 +805,20 @@ namespace kernel32 {
|
|||
DEBUG_LOG("-> %p\n", handle);
|
||||
return handle;
|
||||
} else {
|
||||
switch (errno) {
|
||||
case EACCES:
|
||||
wibo::lastError = 5; // ERROR_ACCESS_DENIED
|
||||
break;
|
||||
case EEXIST:
|
||||
wibo::lastError = 183; // ERROR_ALREADY_EXISTS
|
||||
break;
|
||||
case ENOENT:
|
||||
wibo::lastError = 2; // ERROR_FILE_NOT_FOUND
|
||||
break;
|
||||
case ENOTDIR:
|
||||
wibo::lastError = 3; // ERROR_PATH_NOT_FOUND
|
||||
break;
|
||||
default:
|
||||
wibo::lastError = 50; // ERROR_NOT_SUPPORTED
|
||||
break;
|
||||
}
|
||||
return (void *) 0xFFFFFFFF; // INVALID_HANDLE_VALUE
|
||||
setLastErrorFromErrno();
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
void *WIN_FUNC CreateFileW(const uint16_t *lpFileName, unsigned int dwDesiredAccess, unsigned int dwShareMode,
|
||||
void *lpSecurityAttributes, unsigned int dwCreationDisposition, unsigned int dwFlagsAndAttributes,
|
||||
void *hTemplateFile) {
|
||||
DEBUG_LOG("CreateFileW -> ");
|
||||
const auto lpFileNameA = wideStringToString(lpFileName);
|
||||
return CreateFileA(lpFileNameA.c_str(), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
|
||||
dwFlagsAndAttributes, hTemplateFile);
|
||||
}
|
||||
|
||||
void *WIN_FUNC CreateFileMappingA(
|
||||
void *hFile,
|
||||
void *lpFileMappingAttributes,
|
||||
|
@ -790,22 +884,19 @@ namespace kernel32 {
|
|||
return 1;
|
||||
}
|
||||
|
||||
unsigned int WIN_FUNC SetFilePointer(void *hFile, int lDistanceToMove, int *lpDistanceToMoveHigh, int dwMoveMethod) {
|
||||
DEBUG_LOG("SetFilePointer %p %d %d\n", hFile, lDistanceToMove, dwMoveMethod);
|
||||
assert(!lpDistanceToMoveHigh);
|
||||
DWORD WIN_FUNC SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
|
||||
DEBUG_LOG("SetFilePointer(%p, %d, %d)\n", hFile, lDistanceToMove, dwMoveMethod);
|
||||
assert(!lpDistanceToMoveHigh || *lpDistanceToMoveHigh == 0);
|
||||
FILE *fp = files::fpFromHandle(hFile);
|
||||
wibo::lastError = 0;
|
||||
int r = fseek(fp, lDistanceToMove,
|
||||
dwMoveMethod == 0 ? SEEK_SET :
|
||||
dwMoveMethod == 1 ? SEEK_CUR :
|
||||
SEEK_END);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
int r = fseek(fp, lDistanceToMove, dwMoveMethod == 0 ? SEEK_SET : dwMoveMethod == 1 ? SEEK_CUR : SEEK_END);
|
||||
|
||||
if (r < 0) {
|
||||
if (errno == EINVAL)
|
||||
wibo::lastError = 131; // ERROR_NEGATIVE_SEEK
|
||||
wibo::lastError = ERROR_NEGATIVE_SEEK;
|
||||
else
|
||||
wibo::lastError = 87; // ERROR_INVALID_PARAMETER
|
||||
return 0xFFFFFFFF; // INVALID_SET_FILE_POINTER
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return INVALID_SET_FILE_POINTER;
|
||||
}
|
||||
|
||||
r = ftell(fp);
|
||||
|
@ -813,6 +904,27 @@ namespace kernel32 {
|
|||
return r;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC SetFilePointerEx(HANDLE hFile, LARGE_INTEGER lDistanceToMove, PLARGE_INTEGER lpDistanceToMoveHigh,
|
||||
DWORD dwMoveMethod) {
|
||||
assert(!lpDistanceToMoveHigh || *lpDistanceToMoveHigh == 0);
|
||||
DEBUG_LOG("SetFilePointerEx(%p, %ld, %d)\n", hFile, lDistanceToMove, dwMoveMethod);
|
||||
FILE *fp = files::fpFromHandle(hFile);
|
||||
wibo::lastError = ERROR_SUCCESS;
|
||||
int r = fseeko64(fp, lDistanceToMove, dwMoveMethod == 0 ? SEEK_SET : dwMoveMethod == 1 ? SEEK_CUR : SEEK_END);
|
||||
|
||||
if (r < 0) {
|
||||
if (errno == EINVAL)
|
||||
wibo::lastError = ERROR_NEGATIVE_SEEK;
|
||||
else
|
||||
wibo::lastError = ERROR_INVALID_PARAMETER;
|
||||
return INVALID_SET_FILE_POINTER;
|
||||
}
|
||||
|
||||
r = ftell(fp);
|
||||
assert(r >= 0);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int WIN_FUNC SetEndOfFile(void *hFile) {
|
||||
DEBUG_LOG("SetEndOfFile\n");
|
||||
FILE *fp = files::fpFromHandle(hFile);
|
||||
|
@ -931,6 +1043,53 @@ namespace kernel32 {
|
|||
return 1;
|
||||
}
|
||||
|
||||
struct BY_HANDLE_FILE_INFORMATION {
|
||||
unsigned long dwFileAttributes;
|
||||
FILETIME ftCreationTime;
|
||||
FILETIME ftLastAccessTime;
|
||||
FILETIME ftLastWriteTime;
|
||||
unsigned long dwVolumeSerialNumber;
|
||||
unsigned long nFileSizeHigh;
|
||||
unsigned long nFileSizeLow;
|
||||
unsigned long nNumberOfLinks;
|
||||
unsigned long nFileIndexHigh;
|
||||
unsigned long nFileIndexLow;
|
||||
};
|
||||
|
||||
int WIN_FUNC GetFileInformationByHandle(void *hFile, BY_HANDLE_FILE_INFORMATION *lpFileInformation) {
|
||||
DEBUG_LOG("GetFileInformationByHandle(%p, %p)\n", hFile, lpFileInformation);
|
||||
FILE* fp = files::fpFromHandle(hFile);
|
||||
if (fp == nullptr) {
|
||||
wibo::lastError = 6; // ERROR_INVALID_HANDLE
|
||||
return 0;
|
||||
}
|
||||
struct stat64 st{};
|
||||
if (fstat64(fileno(fp), &st)) {
|
||||
setLastErrorFromErrno();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lpFileInformation != nullptr) {
|
||||
lpFileInformation->dwFileAttributes = 0;
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
lpFileInformation->dwFileAttributes |= 0x10;
|
||||
}
|
||||
if (S_ISREG(st.st_mode)) {
|
||||
lpFileInformation->dwFileAttributes |= 0x80;
|
||||
}
|
||||
lpFileInformation->ftCreationTime = defaultFiletime;
|
||||
lpFileInformation->ftLastAccessTime = defaultFiletime;
|
||||
lpFileInformation->ftLastWriteTime = defaultFiletime;
|
||||
lpFileInformation->dwVolumeSerialNumber = 0;
|
||||
lpFileInformation->nFileSizeHigh = (unsigned long) (st.st_size >> 32);
|
||||
lpFileInformation->nFileSizeLow = (unsigned long) st.st_size;
|
||||
lpFileInformation->nNumberOfLinks = 0;
|
||||
lpFileInformation->nFileIndexHigh = 0;
|
||||
lpFileInformation->nFileIndexLow = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct TIME_ZONE_INFORMATION {
|
||||
int Bias;
|
||||
short StandardName[32];
|
||||
|
@ -951,7 +1110,7 @@ namespace kernel32 {
|
|||
* Console Nonsense
|
||||
*/
|
||||
int WIN_FUNC GetConsoleMode(void *hConsoleHandle, unsigned int *lpMode) {
|
||||
DEBUG_LOG("GetConsoleMode %p", hConsoleHandle);
|
||||
DEBUG_LOG("GetConsoleMode(%p)\n", hConsoleHandle);
|
||||
*lpMode = 0;
|
||||
return 1;
|
||||
}
|
||||
|
@ -988,6 +1147,25 @@ namespace kernel32 {
|
|||
return 1;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC WriteConsoleW(HANDLE hConsoleOutput, LPCWSTR lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten,
|
||||
LPVOID lpReserved) {
|
||||
DEBUG_LOG("WriteConsoleW(%p, %p, %u, %p, %p)\n", hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, lpNumberOfCharsWritten,
|
||||
lpReserved);
|
||||
const auto str = wideStringToString(lpBuffer, nNumberOfCharsToWrite);
|
||||
FILE *fp = files::fpFromHandle(hConsoleOutput);
|
||||
if (fp == stdout || fp == stderr) {
|
||||
fprintf(fp, "%s", str.c_str());
|
||||
if (lpNumberOfCharsWritten) {
|
||||
*lpNumberOfCharsWritten = nNumberOfCharsToWrite;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
if (lpNumberOfCharsWritten) {
|
||||
*lpNumberOfCharsWritten = 0;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
unsigned int WIN_FUNC GetSystemDirectoryA(char *lpBuffer, unsigned int uSize) {
|
||||
DEBUG_LOG("GetSystemDirectoryA(%p, %u)\n", lpBuffer, uSize);
|
||||
if (lpBuffer == nullptr) {
|
||||
|
@ -1056,8 +1234,8 @@ namespace kernel32 {
|
|||
return path.size();
|
||||
}
|
||||
|
||||
void* WIN_FUNC GetModuleHandleA(const char* lpModuleName) {
|
||||
DEBUG_LOG("GetModuleHandleA %s\n", lpModuleName);
|
||||
HMODULE WIN_FUNC GetModuleHandleA(LPCSTR lpModuleName) {
|
||||
DEBUG_LOG("GetModuleHandleA(%s)\n", lpModuleName);
|
||||
|
||||
if (!lpModuleName) {
|
||||
// If lpModuleName is NULL, GetModuleHandle returns a handle to the file
|
||||
|
@ -1067,21 +1245,17 @@ namespace kernel32 {
|
|||
}
|
||||
|
||||
// wibo::lastError = 0;
|
||||
return (void*)0x100001;
|
||||
return wibo::loadModule(lpModuleName);
|
||||
}
|
||||
|
||||
void* WIN_FUNC GetModuleHandleW(const uint16_t* lpModuleName) {
|
||||
if (wibo::debugEnabled) {
|
||||
std::string moduleName = lpModuleName ? wideStringToString(lpModuleName) : "<null>";
|
||||
DEBUG_LOG("GetModuleHandleW: %s\n", moduleName.c_str());
|
||||
HMODULE WIN_FUNC GetModuleHandleW(LPCWSTR lpModuleName) {
|
||||
DEBUG_LOG("GetModuleHandleW -> ");
|
||||
if (lpModuleName) {
|
||||
const auto lpModuleNameA = wideStringToString(lpModuleName);
|
||||
return GetModuleHandleA(lpModuleNameA.c_str());
|
||||
} else {
|
||||
return GetModuleHandleA(nullptr);
|
||||
}
|
||||
|
||||
if (!lpModuleName) {
|
||||
return wibo::mainModule->imageBuffer;
|
||||
}
|
||||
|
||||
// wibo::lastError = 0;
|
||||
return (void*)0x100001;
|
||||
}
|
||||
|
||||
unsigned int WIN_FUNC GetModuleFileNameA(void* hModule, char* lpFilename, unsigned int nSize) {
|
||||
|
@ -1122,23 +1296,22 @@ namespace kernel32 {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void* WIN_FUNC LoadLibraryA(const char* lpLibFileName) {
|
||||
DEBUG_LOG("LoadLibraryA %s\n", lpLibFileName);
|
||||
return (void*)0x100005;
|
||||
HMODULE WIN_FUNC LoadLibraryA(LPCSTR lpLibFileName) {
|
||||
DEBUG_LOG("LoadLibraryA(%s)\n", lpLibFileName);
|
||||
return wibo::loadModule(lpLibFileName);
|
||||
}
|
||||
|
||||
void* WIN_FUNC LoadLibraryExW(const uint16_t* lpLibFileName, void* hFile, unsigned int dwFlags) {
|
||||
if (wibo::debugEnabled) {
|
||||
std::string filename = wideStringToString(lpLibFileName);
|
||||
DEBUG_LOG("LoadLibraryExW: %s\n", filename.c_str());
|
||||
}
|
||||
|
||||
return (void*)0x100005;
|
||||
HMODULE WIN_FUNC LoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) {
|
||||
assert(!hFile);
|
||||
DEBUG_LOG("LoadLibraryExW(%x) -> ", dwFlags);
|
||||
const auto filename = wideStringToString(lpLibFileName);
|
||||
return LoadLibraryA(filename.c_str());
|
||||
}
|
||||
|
||||
int WIN_FUNC FreeLibrary(void* hLibModule) {
|
||||
DEBUG_LOG("FreeLibrary %p\n", hLibModule);
|
||||
return 1;
|
||||
BOOL WIN_FUNC FreeLibrary(HMODULE hLibModule) {
|
||||
DEBUG_LOG("FreeLibrary(%p)\n", hLibModule);
|
||||
wibo::freeModule(hLibModule);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const unsigned int MAJOR_VER = 6, MINOR_VER = 2, BUILD_NUMBER = 0; // Windows 8
|
||||
|
@ -1269,6 +1442,21 @@ namespace kernel32 {
|
|||
memset(lpStartupInfo, 0, sizeof(_STARTUPINFOW));
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC SetThreadStackGuarantee(PULONG StackSizeInBytes) {
|
||||
DEBUG_LOG("STUB: SetThreadStackGuarantee(%p)\n", StackSizeInBytes);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HANDLE WIN_FUNC GetCurrentThread() {
|
||||
DEBUG_LOG("STUB: GetCurrentThread\n");
|
||||
return (HANDLE)0x100007;
|
||||
}
|
||||
|
||||
HRESULT WIN_FUNC SetThreadDescription(HANDLE hThread, const void * /* PCWSTR */ lpThreadDescription) {
|
||||
DEBUG_LOG("STUB: SetThreadDescription(%p, %p)\n", hThread, lpThreadDescription);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
unsigned short WIN_FUNC GetFileType(void *hFile) {
|
||||
DEBUG_LOG("GetFileType %p\n", hFile);
|
||||
return 1; // FILE_TYPE_DISK
|
||||
|
@ -1392,32 +1580,32 @@ namespace kernel32 {
|
|||
return 1;
|
||||
}
|
||||
|
||||
void *WIN_FUNC GetProcAddress(void *hModule, char *lpProcName) {
|
||||
DEBUG_LOG("GetProcAddress: %s from %p\n", lpProcName, hModule);
|
||||
|
||||
if (strcmp(lpProcName, "IsProcessorFeaturePresent") == 0) return (void *) IsProcessorFeaturePresent;
|
||||
// if (strcmp(lpProcName, "InitializeCriticalSectionEx") == 0) return (void *) InitializeCriticalSectionEx;
|
||||
// if (strcmp(lpProcName, "FlsSetValue") == 0) return (void *) FlsSetValue;
|
||||
// if (strcmp(lpProcName, "FlsFree") == 0) return (void *) FlsFree;
|
||||
// if (strcmp(lpProcName, "LCMapStringEx") == 0) return (void *) LCMapStringEx;
|
||||
// if (strcmp(lpProcName, "LocaleNameToLCID") == 0) return (void *) LocaleNameToLCID;
|
||||
if (strcmp(lpProcName, "MessageBoxA") == 0) return (void *) user32::MessageBoxA;
|
||||
|
||||
return NULL;
|
||||
FARPROC WIN_FUNC GetProcAddress(HMODULE hModule, LPCSTR lpProcName) {
|
||||
FARPROC result;
|
||||
const auto proc = reinterpret_cast<uintptr_t>(lpProcName);
|
||||
if (proc & ~0xFFFF) {
|
||||
DEBUG_LOG("GetProcAddress(%p, %s) ", hModule, lpProcName);
|
||||
result = wibo::resolveFuncByName(hModule, lpProcName);
|
||||
} else {
|
||||
DEBUG_LOG("GetProcAddress(%p, %u) ", hModule, proc);
|
||||
result = wibo::resolveFuncByOrdinal(hModule, static_cast<uint16_t>(proc));
|
||||
}
|
||||
DEBUG_LOG("-> %p\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void *WIN_FUNC HeapAlloc(void *hHeap, unsigned int dwFlags, size_t dwBytes) {
|
||||
DEBUG_LOG("HeapAlloc(heap=%p, flags=%x, bytes=%u)\n", hHeap, dwFlags, dwBytes);
|
||||
DEBUG_LOG("HeapAlloc(heap=%p, flags=%x, bytes=%u) ", hHeap, dwFlags, dwBytes);
|
||||
|
||||
void *mem = doAlloc(dwBytes, dwFlags & 8);
|
||||
DEBUG_LOG("HeapAlloc returning %p\n", mem);
|
||||
DEBUG_LOG("-> %p\n", mem);
|
||||
return mem;
|
||||
}
|
||||
|
||||
void *WIN_FUNC HeapReAlloc(void *hHeap, unsigned int dwFlags, void *lpMem, size_t dwBytes) {
|
||||
DEBUG_LOG("HeapReAlloc(heap=%p, flags=%x, mem=%p, bytes=%u)\n", hHeap, dwFlags, lpMem, dwBytes);
|
||||
DEBUG_LOG("HeapReAlloc(heap=%p, flags=%x, mem=%p, bytes=%u) ", hHeap, dwFlags, lpMem, dwBytes);
|
||||
void *ret = doRealloc(lpMem, dwBytes, dwFlags & 8);
|
||||
DEBUG_LOG("HeapReAlloc returning %p\n", ret);
|
||||
DEBUG_LOG("-> %p\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1488,6 +1676,11 @@ namespace kernel32 {
|
|||
return Ptr;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC SetDllDirectoryA(LPCSTR lpPathName) {
|
||||
DEBUG_LOG("STUB: SetDllDirectoryA(%s)\n", lpPathName);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int WIN_FUNC CompareStringA(int Locale, unsigned int dwCmpFlags, const char *lpString1, unsigned int cchCount1, const char *lpString2, unsigned int cchCount2) {
|
||||
if (cchCount1 < 0)
|
||||
cchCount1 = strlen(lpString1);
|
||||
|
@ -1548,6 +1741,11 @@ namespace kernel32 {
|
|||
return 1;
|
||||
}
|
||||
|
||||
BOOL WIN_FUNC IsDBCSLeadByte(BYTE TestChar) {
|
||||
DEBUG_LOG("IsDBCSLeadByte(%u)\n", TestChar);
|
||||
return FALSE; // We're not multibyte (yet?)
|
||||
}
|
||||
|
||||
int WIN_FUNC LCMapStringW(int Locale, unsigned int dwMapFlags, const uint16_t* lpSrcStr, int cchSrc, uint16_t* lpDestStr, int cchDest) {
|
||||
DEBUG_LOG("LCMapStringW: (locale=%i, flags=%u, src=%p, dest=%p)\n", Locale, dwMapFlags, cchSrc, cchDest);
|
||||
if (cchSrc < 0) {
|
||||
|
@ -1566,11 +1764,47 @@ namespace kernel32 {
|
|||
return 0; // fail
|
||||
}
|
||||
|
||||
DWORD WIN_FUNC GetEnvironmentVariableA(LPCSTR lpName, LPSTR lpBuffer, DWORD nSize) {
|
||||
DEBUG_LOG("GetEnvironmentVariableA: %s\n", lpName);
|
||||
const char *value = getenv(lpName);
|
||||
if (!value) {
|
||||
return 0;
|
||||
}
|
||||
unsigned int len = strlen(value);
|
||||
if (nSize == 0) {
|
||||
return len + 1;
|
||||
}
|
||||
if (nSize < len) {
|
||||
return len;
|
||||
}
|
||||
memcpy(lpBuffer, value, len + 1);
|
||||
return len;
|
||||
}
|
||||
|
||||
unsigned int WIN_FUNC SetEnvironmentVariableA(const char *lpName, const char *lpValue) {
|
||||
DEBUG_LOG("SetEnvironmentVariableA: %s=%s\n", lpName, lpValue);
|
||||
return setenv(lpName, lpValue, 1 /* OVERWRITE */);
|
||||
}
|
||||
|
||||
DWORD WIN_FUNC GetEnvironmentVariableW(LPCWSTR lpName, LPWSTR lpBuffer, DWORD nSize) {
|
||||
DEBUG_LOG("GetEnvironmentVariableW: %s\n", wideStringToString(lpName).c_str());
|
||||
const char *value = getenv(wideStringToString(lpName).c_str());
|
||||
if (!value) {
|
||||
return 0;
|
||||
}
|
||||
unsigned int len = strlen(value) * 2;
|
||||
if (nSize == 0) {
|
||||
return len + 2;
|
||||
}
|
||||
if (nSize < len) {
|
||||
return len;
|
||||
}
|
||||
const uint16_t *wideValue = stringToWideString(value);
|
||||
memcpy(lpBuffer, wideValue, len + 2);
|
||||
free((void *)wideValue);
|
||||
return len;
|
||||
}
|
||||
|
||||
unsigned int WIN_FUNC QueryPerformanceCounter(unsigned long int *lpPerformanceCount) {
|
||||
DEBUG_LOG("QueryPerformanceCounter\n");
|
||||
*lpPerformanceCount = 0;
|
||||
|
@ -1653,10 +1887,11 @@ namespace kernel32 {
|
|||
}
|
||||
}
|
||||
|
||||
void *wibo::resolveKernel32(const char *name) {
|
||||
static void *resolveByName(const char *name) {
|
||||
// errhandlingapi.h
|
||||
if (strcmp(name, "GetLastError") == 0) return (void *) kernel32::GetLastError;
|
||||
if (strcmp(name, "SetLastError") == 0) return (void *) kernel32::SetLastError;
|
||||
if (strcmp(name, "AddVectoredExceptionHandler") == 0) return (void *) kernel32::AddVectoredExceptionHandler;
|
||||
|
||||
// processthreadsapi.h
|
||||
if (strcmp(name, "IsProcessorFeaturePresent") == 0) return (void *) kernel32::IsProcessorFeaturePresent;
|
||||
|
@ -1671,6 +1906,9 @@ void *wibo::resolveKernel32(const char *name) {
|
|||
if (strcmp(name, "TlsSetValue") == 0) return (void *) kernel32::TlsSetValue;
|
||||
if (strcmp(name, "GetStartupInfoA") == 0) return (void *) kernel32::GetStartupInfoA;
|
||||
if (strcmp(name, "GetStartupInfoW") == 0) return (void *) kernel32::GetStartupInfoW;
|
||||
if (strcmp(name, "SetThreadStackGuarantee") == 0) return (void *) kernel32::SetThreadStackGuarantee;
|
||||
if (strcmp(name, "GetCurrentThread") == 0) return (void *) kernel32::GetCurrentThread;
|
||||
if (strcmp(name, "SetThreadDescription") == 0) return (void *) kernel32::SetThreadDescription;
|
||||
|
||||
// winnls.h
|
||||
if (strcmp(name, "GetSystemDefaultLangID") == 0) return (void *) kernel32::GetSystemDefaultLangID;
|
||||
|
@ -1684,6 +1922,7 @@ void *wibo::resolveKernel32(const char *name) {
|
|||
if (strcmp(name, "LCMapStringA") == 0) return (void *) kernel32::LCMapStringA;
|
||||
if (strcmp(name, "GetLocaleInfoA") == 0) return (void *) kernel32::GetLocaleInfoA;
|
||||
if (strcmp(name, "GetUserDefaultLCID") == 0) return (void *) kernel32::GetUserDefaultLCID;
|
||||
if (strcmp(name, "IsDBCSLeadByte") == 0) return (void *) kernel32::IsDBCSLeadByte;
|
||||
|
||||
// synchapi.h
|
||||
if (strcmp(name, "InitializeCriticalSection") == 0) return (void *) kernel32::InitializeCriticalSection;
|
||||
|
@ -1692,6 +1931,13 @@ void *wibo::resolveKernel32(const char *name) {
|
|||
if (strcmp(name, "DeleteCriticalSection") == 0) return (void *) kernel32::DeleteCriticalSection;
|
||||
if (strcmp(name, "EnterCriticalSection") == 0) return (void *) kernel32::EnterCriticalSection;
|
||||
if (strcmp(name, "LeaveCriticalSection") == 0) return (void *) kernel32::LeaveCriticalSection;
|
||||
if (strcmp(name, "InitOnceBeginInitialize") == 0) return (void *) kernel32::InitOnceBeginInitialize;
|
||||
if (strcmp(name, "AcquireSRWLockShared") == 0) return (void *) kernel32::AcquireSRWLockShared;
|
||||
if (strcmp(name, "ReleaseSRWLockShared") == 0) return (void *) kernel32::ReleaseSRWLockShared;
|
||||
if (strcmp(name, "ReleaseSRWLockShared") == 0) return (void *) kernel32::AcquireSRWLockShared;
|
||||
if (strcmp(name, "AcquireSRWLockExclusive") == 0) return (void *) kernel32::AcquireSRWLockExclusive;
|
||||
if (strcmp(name, "ReleaseSRWLockExclusive") == 0) return (void *) kernel32::ReleaseSRWLockExclusive;
|
||||
if (strcmp(name, "TryAcquireSRWLockExclusive") == 0) return (void *) kernel32::TryAcquireSRWLockExclusive;
|
||||
|
||||
// winbase.h
|
||||
if (strcmp(name, "GlobalAlloc") == 0) return (void *) kernel32::GlobalAlloc;
|
||||
|
@ -1706,6 +1952,7 @@ void *wibo::resolveKernel32(const char *name) {
|
|||
if (strcmp(name, "GetComputerNameA") == 0) return (void *) kernel32::GetComputerNameA;
|
||||
if (strcmp(name, "EncodePointer") == 0) return (void *) kernel32::EncodePointer;
|
||||
if (strcmp(name, "DecodePointer") == 0) return (void *) kernel32::DecodePointer;
|
||||
if (strcmp(name, "SetDllDirectoryA") == 0) return (void *) kernel32::SetDllDirectoryA;
|
||||
|
||||
// processenv.h
|
||||
if (strcmp(name, "GetCommandLineA") == 0) return (void *) kernel32::GetCommandLineA;
|
||||
|
@ -1714,7 +1961,9 @@ void *wibo::resolveKernel32(const char *name) {
|
|||
if (strcmp(name, "FreeEnvironmentStringsA") == 0) return (void *) kernel32::FreeEnvironmentStringsA;
|
||||
if (strcmp(name, "GetEnvironmentStringsW") == 0) return (void *) kernel32::GetEnvironmentStringsW;
|
||||
if (strcmp(name, "FreeEnvironmentStringsW") == 0) return (void *) kernel32::FreeEnvironmentStringsW;
|
||||
if (strcmp(name, "GetEnvironmentVariableA") == 0) return (void *) kernel32::GetEnvironmentVariableA;
|
||||
if (strcmp(name, "SetEnvironmentVariableA") == 0) return (void *) kernel32::SetEnvironmentVariableA;
|
||||
if (strcmp(name, "GetEnvironmentVariableW") == 0) return (void *) kernel32::GetEnvironmentVariableW;
|
||||
|
||||
// console api
|
||||
if (strcmp(name, "GetStdHandle") == 0) return (void *) kernel32::GetStdHandle;
|
||||
|
@ -1724,9 +1973,11 @@ void *wibo::resolveKernel32(const char *name) {
|
|||
if (strcmp(name, "GetConsoleMode") == 0) return (void *) kernel32::GetConsoleMode;
|
||||
if (strcmp(name, "SetConsoleCtrlHandler") == 0) return (void *) kernel32::SetConsoleCtrlHandler;
|
||||
if (strcmp(name, "GetConsoleScreenBufferInfo") == 0) return (void *) kernel32::GetConsoleScreenBufferInfo;
|
||||
if (strcmp(name, "WriteConsoleW") == 0) return (void *) kernel32::WriteConsoleW;
|
||||
|
||||
// fileapi.h
|
||||
if (strcmp(name, "GetFullPathNameA") == 0) return (void *) kernel32::GetFullPathNameA;
|
||||
if (strcmp(name, "GetFullPathNameW") == 0) return (void *) kernel32::GetFullPathNameW;
|
||||
if (strcmp(name, "GetShortPathNameA") == 0) return (void *) kernel32::GetShortPathNameA;
|
||||
if (strcmp(name, "FindFirstFileA") == 0) return (void *) kernel32::FindFirstFileA;
|
||||
if (strcmp(name, "FindFirstFileExA") == 0) return (void *) kernel32::FindFirstFileExA;
|
||||
|
@ -1736,11 +1987,13 @@ void *wibo::resolveKernel32(const char *name) {
|
|||
if (strcmp(name, "WriteFile") == 0) return (void *) kernel32::WriteFile;
|
||||
if (strcmp(name, "ReadFile") == 0) return (void *) kernel32::ReadFile;
|
||||
if (strcmp(name, "CreateFileA") == 0) return (void *) kernel32::CreateFileA;
|
||||
if (strcmp(name, "CreateFileW") == 0) return (void *) kernel32::CreateFileW;
|
||||
if (strcmp(name, "CreateFileMappingA") == 0) return (void *) kernel32::CreateFileMappingA;
|
||||
if (strcmp(name, "MapViewOfFile") == 0) return (void *) kernel32::MapViewOfFile;
|
||||
if (strcmp(name, "UnmapViewOfFile") == 0) return (void *) kernel32::UnmapViewOfFile;
|
||||
if (strcmp(name, "DeleteFileA") == 0) return (void *) kernel32::DeleteFileA;
|
||||
if (strcmp(name, "SetFilePointer") == 0) return (void *) kernel32::SetFilePointer;
|
||||
if (strcmp(name, "SetFilePointerEx") == 0) return (void *) kernel32::SetFilePointerEx;
|
||||
if (strcmp(name, "SetEndOfFile") == 0) return (void *) kernel32::SetEndOfFile;
|
||||
if (strcmp(name, "CreateDirectoryA") == 0) return (void *) kernel32::CreateDirectoryA;
|
||||
if (strcmp(name, "RemoveDirectoryA") == 0) return (void *) kernel32::RemoveDirectoryA;
|
||||
|
@ -1750,6 +2003,7 @@ void *wibo::resolveKernel32(const char *name) {
|
|||
if (strcmp(name, "SetFileTime") == 0) return (void *) kernel32::SetFileTime;
|
||||
if (strcmp(name, "GetFileType") == 0) return (void *) kernel32::GetFileType;
|
||||
if (strcmp(name, "FileTimeToLocalFileTime") == 0) return (void *) kernel32::FileTimeToLocalFileTime;
|
||||
if (strcmp(name, "GetFileInformationByHandle") == 0) return (void *) kernel32::GetFileInformationByHandle;
|
||||
|
||||
// sysinfoapi.h
|
||||
if (strcmp(name, "GetSystemTime") == 0) return (void *) kernel32::GetSystemTime;
|
||||
|
@ -1819,3 +2073,13 @@ void *wibo::resolveKernel32(const char *name) {
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
wibo::Module lib_kernel32 = {
|
||||
(const char *[]){
|
||||
"kernel32",
|
||||
"kernel32.dll",
|
||||
nullptr,
|
||||
},
|
||||
resolveByName,
|
||||
nullptr,
|
||||
};
|
||||
|
|
16
dll/lmgr.cpp
16
dll/lmgr.cpp
|
@ -13,7 +13,7 @@ namespace lmgr {
|
|||
}
|
||||
}
|
||||
|
||||
void *wibo::resolveLmgr(uint16_t ordinal) {
|
||||
static void *resolveByOrdinal(uint16_t ordinal) {
|
||||
switch (ordinal) {
|
||||
case 189:
|
||||
return (void*)lmgr::lp_checkin;
|
||||
|
@ -22,3 +22,17 @@ void *wibo::resolveLmgr(uint16_t ordinal) {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
wibo::Module lib_lmgr = {
|
||||
(const char *[]){
|
||||
"lmgr11",
|
||||
"lmgr11.dll",
|
||||
"lmgr326b",
|
||||
"lmgr326b.dll",
|
||||
"lmgr8c",
|
||||
"lmgr8c.dll",
|
||||
nullptr,
|
||||
},
|
||||
nullptr,
|
||||
resolveByOrdinal,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
#include "common.h"
|
||||
#include "files.h"
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#define PIO_APC_ROUTINE void *
|
||||
|
||||
typedef struct _IO_STATUS_BLOCK {
|
||||
union {
|
||||
NTSTATUS Status;
|
||||
PVOID Pointer;
|
||||
};
|
||||
ULONG_PTR Information;
|
||||
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
|
||||
|
||||
namespace ntdll {
|
||||
|
||||
NTSTATUS WIN_FUNC NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext,
|
||||
PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset,
|
||||
PULONG Key) {
|
||||
DEBUG_LOG("NtReadFile(%p, %p, %p, %p, %p, %p, %u, %p, %p) ", FileHandle, Event, ApcRoutine, ApcContext,
|
||||
IoStatusBlock, Buffer, Length, ByteOffset, Key);
|
||||
assert(Event == nullptr);
|
||||
assert(ApcRoutine == nullptr);
|
||||
assert(ApcContext == nullptr);
|
||||
assert(ByteOffset == nullptr);
|
||||
assert(Key == nullptr);
|
||||
|
||||
wibo::lastError = 0;
|
||||
FILE *fp = files::fpFromHandle(FileHandle);
|
||||
if (!fp) {
|
||||
wibo::lastError = ERROR_INVALID_HANDLE;
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
size_t read = fread(Buffer, 1, Length, fp);
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
if (read < Length) {
|
||||
if (feof(fp)) {
|
||||
wibo::lastError = ERROR_HANDLE_EOF;
|
||||
status = STATUS_END_OF_FILE;
|
||||
} else {
|
||||
wibo::lastError = ERROR_READ_FAULT; // ?
|
||||
status = STATUS_UNEXPECTED_IO_ERROR;
|
||||
}
|
||||
}
|
||||
if (IoStatusBlock) {
|
||||
IoStatusBlock->Status = status;
|
||||
IoStatusBlock->Information = read;
|
||||
}
|
||||
DEBUG_LOG("-> 0x%x\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
#define PAGE_NOACCESS 0x1
|
||||
#define PAGE_READONLY 0x2
|
||||
#define PAGE_READWRITE 0x4
|
||||
#define PAGE_WRITECOPY 0x8
|
||||
#define PAGE_EXECUTE 0x10
|
||||
#define PAGE_EXECUTE_READ 0x20
|
||||
#define PAGE_EXECUTE_READWRITE 0x40
|
||||
#define PAGE_EXECUTE_WRITECOPY 0x80
|
||||
#define PAGE_GUARD 0x100
|
||||
#define PAGE_NOCACHE 0x200
|
||||
#define PAGE_WRITECOMBINE 0x400
|
||||
|
||||
NTSTATUS WIN_FUNC NtAllocateVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits,
|
||||
PSIZE_T RegionSize, ULONG AllocationType, ULONG Protect) {
|
||||
DEBUG_LOG("NtAllocateVirtualMemory(%p, %p, %lu, %p, %lu, %lu) ", ProcessHandle, BaseAddress, ZeroBits, RegionSize,
|
||||
AllocationType, Protect);
|
||||
assert(ProcessHandle == (HANDLE)-1);
|
||||
assert(ZeroBits == 0);
|
||||
|
||||
int prot = 0;
|
||||
if (Protect & PAGE_NOACCESS)
|
||||
prot |= PROT_NONE;
|
||||
if (Protect & PAGE_READONLY)
|
||||
prot |= PROT_READ;
|
||||
if (Protect & PAGE_READWRITE)
|
||||
prot |= PROT_READ | PROT_WRITE;
|
||||
if (Protect & PAGE_WRITECOPY)
|
||||
prot |= PROT_READ | PROT_WRITE;
|
||||
if (Protect & PAGE_EXECUTE)
|
||||
prot |= PROT_EXEC;
|
||||
if (Protect & PAGE_EXECUTE_READ)
|
||||
prot |= PROT_EXEC | PROT_READ;
|
||||
if (Protect & PAGE_EXECUTE_READWRITE)
|
||||
prot |= PROT_EXEC | PROT_READ | PROT_WRITE;
|
||||
assert(!(Protect & PAGE_EXECUTE_WRITECOPY));
|
||||
assert(!(Protect & PAGE_GUARD));
|
||||
assert(!(Protect & PAGE_NOCACHE));
|
||||
assert(!(Protect & PAGE_WRITECOMBINE));
|
||||
|
||||
void *addr = mmap(*BaseAddress, *RegionSize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (addr == MAP_FAILED) {
|
||||
perror("mmap");
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
*BaseAddress = addr;
|
||||
|
||||
DEBUG_LOG("-> 0x%x\n", STATUS_SUCCESS);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS WIN_FUNC NtProtectVirtualMemory(HANDLE ProcessHandle, PVOID *BaseAddress, PSIZE_T NumberOfBytesToProtect,
|
||||
ULONG NewAccessProtection, PULONG OldAccessProtection) {
|
||||
DEBUG_LOG("NtProtectVirtualMemory(%p, %p, %p, %lu, %p) ", ProcessHandle, BaseAddress, NumberOfBytesToProtect,
|
||||
NewAccessProtection, OldAccessProtection);
|
||||
assert(ProcessHandle == (HANDLE)-1);
|
||||
assert(NumberOfBytesToProtect != nullptr);
|
||||
|
||||
int prot = 0;
|
||||
if (NewAccessProtection & PAGE_NOACCESS)
|
||||
prot |= PROT_NONE;
|
||||
if (NewAccessProtection & PAGE_READONLY)
|
||||
prot |= PROT_READ;
|
||||
if (NewAccessProtection & PAGE_READWRITE)
|
||||
prot |= PROT_READ | PROT_WRITE;
|
||||
if (NewAccessProtection & PAGE_WRITECOPY)
|
||||
prot |= PROT_READ | PROT_WRITE;
|
||||
if (NewAccessProtection & PAGE_EXECUTE)
|
||||
prot |= PROT_EXEC;
|
||||
if (NewAccessProtection & PAGE_EXECUTE_READ)
|
||||
prot |= PROT_EXEC | PROT_READ;
|
||||
if (NewAccessProtection & PAGE_EXECUTE_READWRITE)
|
||||
prot |= PROT_EXEC | PROT_READ | PROT_WRITE;
|
||||
assert(!(NewAccessProtection & PAGE_EXECUTE_WRITECOPY));
|
||||
assert(!(NewAccessProtection & PAGE_GUARD));
|
||||
assert(!(NewAccessProtection & PAGE_NOCACHE));
|
||||
assert(!(NewAccessProtection & PAGE_WRITECOMBINE));
|
||||
|
||||
int ret = mprotect(*BaseAddress, *NumberOfBytesToProtect, prot);
|
||||
if (ret != 0) {
|
||||
perror("mprotect");
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (OldAccessProtection) {
|
||||
*OldAccessProtection = 0; // stub
|
||||
}
|
||||
DEBUG_LOG("-> 0x%x\n", STATUS_SUCCESS);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace ntdll
|
||||
|
||||
static void *resolveByName(const char *name) {
|
||||
if (strcmp(name, "NtReadFile") == 0)
|
||||
return (void *)ntdll::NtReadFile;
|
||||
if (strcmp(name, "NtAllocateVirtualMemory") == 0)
|
||||
return (void *)ntdll::NtAllocateVirtualMemory;
|
||||
if (strcmp(name, "NtProtectVirtualMemory") == 0)
|
||||
return (void *)ntdll::NtProtectVirtualMemory;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_ntdll = {
|
||||
(const char *[]){
|
||||
"ntdll",
|
||||
"ntdll.dll",
|
||||
nullptr,
|
||||
},
|
||||
resolveByName,
|
||||
nullptr,
|
||||
};
|
|
@ -29,8 +29,18 @@ namespace ole32 {
|
|||
}
|
||||
}
|
||||
|
||||
void *wibo::resolveOle32(const char *name) {
|
||||
static void *resolveByName(const char *name) {
|
||||
if (strcmp(name, "CoInitialize") == 0) return (void *) ole32::CoInitialize;
|
||||
if (strcmp(name, "CoCreateInstance") == 0) return (void *) ole32::CoCreateInstance;
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_ole32 = {
|
||||
(const char *[]){
|
||||
"ole32",
|
||||
"ole32.dll",
|
||||
nullptr,
|
||||
},
|
||||
resolveByName,
|
||||
nullptr,
|
||||
};
|
||||
|
|
|
@ -105,8 +105,18 @@ namespace user32 {
|
|||
}
|
||||
}
|
||||
|
||||
void *wibo::resolveUser32(const char *name) {
|
||||
static void *resolveByName(const char *name) {
|
||||
if (strcmp(name, "LoadStringA") == 0) return (void *) user32::LoadStringA;
|
||||
if (strcmp(name, "MessageBoxA") == 0) return (void *) user32::MessageBoxA;
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_user32 = {
|
||||
(const char *[]){
|
||||
"user32",
|
||||
"user32.dll",
|
||||
nullptr,
|
||||
},
|
||||
resolveByName,
|
||||
nullptr,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#include "common.h"
|
||||
|
||||
namespace vcruntime {
|
||||
|
||||
void *WIN_ENTRY memcpy(void *dest, const void *src, size_t count) { return ::memcpy(dest, src, count); }
|
||||
|
||||
void *WIN_ENTRY memset(void *dest, int ch, size_t count) { return ::memset(dest, ch, count); }
|
||||
|
||||
int WIN_ENTRY memcmp(const void *buf1, const void *buf2, size_t count) { return ::memcmp(buf1, buf2, count); }
|
||||
|
||||
} // namespace vcruntime
|
||||
|
||||
static void *resolveByName(const char *name) {
|
||||
if (strcmp(name, "memcpy") == 0)
|
||||
return (void *)vcruntime::memcpy;
|
||||
if (strcmp(name, "memset") == 0)
|
||||
return (void *)vcruntime::memset;
|
||||
if (strcmp(name, "memcmp") == 0)
|
||||
return (void *)vcruntime::memcmp;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_vcruntime = {
|
||||
(const char *[]){
|
||||
"vcruntime140",
|
||||
"vcruntime140.dll",
|
||||
nullptr,
|
||||
},
|
||||
resolveByName,
|
||||
nullptr,
|
||||
};
|
|
@ -9,7 +9,17 @@ namespace version {
|
|||
}
|
||||
}
|
||||
|
||||
void *wibo::resolveVersion(const char *name) {
|
||||
static void *resolveByName(const char *name) {
|
||||
if (strcmp(name, "GetFileVersionInfoSizeA") == 0) return (void *) version::GetFileVersionInfoSizeA;
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
wibo::Module lib_version = {
|
||||
(const char *[]){
|
||||
"version",
|
||||
"version.dll",
|
||||
nullptr,
|
||||
},
|
||||
resolveByName,
|
||||
nullptr,
|
||||
};
|
||||
|
|
|
@ -15,6 +15,11 @@ namespace files {
|
|||
std::string str = inStr;
|
||||
std::replace(str.begin(), str.end(), '\\', '/');
|
||||
|
||||
// Remove "//?/" prefix
|
||||
if (str.rfind("//?/", 0) == 0) {
|
||||
str.erase(0, 4);
|
||||
}
|
||||
|
||||
// Remove the drive letter
|
||||
if (str.rfind("z:/", 0) == 0 || str.rfind("Z:/", 0) == 0) {
|
||||
str.erase(0, 2);
|
||||
|
|
2
files.h
2
files.h
|
@ -11,6 +11,6 @@ namespace files {
|
|||
void init();
|
||||
}
|
||||
|
||||
static bool endsWith(const std::string &str, const std::string &suffix) {
|
||||
inline bool endsWith(const std::string &str, const std::string &suffix) {
|
||||
return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
|
||||
}
|
||||
|
|
|
@ -188,22 +188,24 @@ bool wibo::Executable::loadPE(FILE *file) {
|
|||
uint32_t *lookupTable = fromRVA(dir->importLookupTable);
|
||||
uint32_t *addressTable = fromRVA(dir->importAddressTable);
|
||||
|
||||
HMODULE module = loadModule(dllName);
|
||||
while (*lookupTable) {
|
||||
uint32_t lookup = *lookupTable;
|
||||
if (lookup & 0x80000000) {
|
||||
// Import by ordinal
|
||||
uint16_t ordinal = lookup & 0xFFFF;
|
||||
DEBUG_LOG(" Ordinal: %d\n", ordinal);
|
||||
*addressTable = (uint32_t) resolveFuncByOrdinal(dllName, ordinal);
|
||||
*addressTable = reinterpret_cast<uintptr_t>(resolveFuncByOrdinal(module, ordinal));
|
||||
} else {
|
||||
// Import by name
|
||||
PEHintNameTableEntry *hintName = fromRVA<PEHintNameTableEntry>(lookup);
|
||||
DEBUG_LOG(" Name: %s\n", hintName->name);
|
||||
*addressTable = (uint32_t) resolveFuncByName(dllName, hintName->name);
|
||||
*addressTable = reinterpret_cast<uintptr_t>(resolveFuncByName(module, hintName->name));
|
||||
}
|
||||
++lookupTable;
|
||||
++addressTable;
|
||||
}
|
||||
freeModule(module);
|
||||
|
||||
++dir;
|
||||
}
|
||||
|
|
112
main.cpp
112
main.cpp
|
@ -8,9 +8,11 @@
|
|||
#include <sys/syscall.h>
|
||||
#include <stdarg.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <fstream>
|
||||
|
||||
uint32_t wibo::lastError = 0;
|
||||
char** wibo::argv;
|
||||
int wibo::argc;
|
||||
char *wibo::commandLine;
|
||||
wibo::Executable *wibo::mainModule = 0;
|
||||
bool wibo::debugEnabled = false;
|
||||
|
@ -54,48 +56,85 @@ FOR_256
|
|||
#undef FOR_256_2
|
||||
#undef FOR_256
|
||||
|
||||
static void *resolveMissingFunc(const char *dllName, const char *funcName) {
|
||||
static void *resolveMissingFuncName(const char *dllName, const char *funcName) {
|
||||
DEBUG_LOG("Missing function: %s (%s)\n", dllName, funcName);
|
||||
assert(stubIndex < 0x100);
|
||||
assert(strlen(dllName) < 0x100);
|
||||
assert(strlen(funcName) < 0x100);
|
||||
strcpy(stubFuncNames[stubIndex], funcName);
|
||||
strcpy(stubDlls[stubIndex], dllName);
|
||||
return (void *) stubFuncs[stubIndex++];
|
||||
return (void *)stubFuncs[stubIndex++];
|
||||
}
|
||||
|
||||
void *wibo::resolveFuncByName(const char *dllName, const char *funcName) {
|
||||
void *func = nullptr;
|
||||
if (strcasecmp(dllName, "KERNEL32.dll") == 0) {
|
||||
func = wibo::resolveKernel32(funcName);
|
||||
} else if (strcasecmp(dllName, "USER32.dll") == 0) {
|
||||
func = wibo::resolveUser32(funcName);
|
||||
} else if (strcasecmp(dllName, "ADVAPI32.dll") == 0) {
|
||||
func = wibo::resolveAdvApi32(funcName);
|
||||
} else if (strcasecmp(dllName, "VERSION.dll") == 0) {
|
||||
func = wibo::resolveVersion(funcName);
|
||||
} else if (strcasecmp(dllName, "OLE32.dll") == 0) {
|
||||
func = wibo::resolveOle32(funcName);
|
||||
}
|
||||
|
||||
if (func)
|
||||
return func;
|
||||
return resolveMissingFunc(dllName, funcName);
|
||||
}
|
||||
|
||||
void *wibo::resolveFuncByOrdinal(const char *dllName, uint16_t ordinal) {
|
||||
void *func;
|
||||
if (strcmp(dllName, "LMGR11.dll") == 0 ||
|
||||
strcmp(dllName, "LMGR326B.dll") == 0 ||
|
||||
strcmp(dllName, "LMGR8C.dll") == 0) {
|
||||
func = wibo::resolveLmgr(ordinal);
|
||||
}
|
||||
|
||||
if (func)
|
||||
return func;
|
||||
static void *resolveMissingFuncOrdinal(const char *dllName, uint16_t ordinal) {
|
||||
char buf[16];
|
||||
sprintf(buf, "%d", ordinal);
|
||||
return resolveMissingFunc(dllName, buf);
|
||||
return resolveMissingFuncName(dllName, buf);
|
||||
}
|
||||
|
||||
extern const wibo::Module lib_advapi32;
|
||||
extern const wibo::Module lib_bcrypt;
|
||||
extern const wibo::Module lib_crt;
|
||||
extern const wibo::Module lib_kernel32;
|
||||
extern const wibo::Module lib_lmgr;
|
||||
extern const wibo::Module lib_ntdll;
|
||||
extern const wibo::Module lib_ole32;
|
||||
extern const wibo::Module lib_user32;
|
||||
extern const wibo::Module lib_vcruntime;
|
||||
extern const wibo::Module lib_version;
|
||||
const wibo::Module * wibo::modules[] = {
|
||||
&lib_advapi32,
|
||||
&lib_bcrypt,
|
||||
&lib_crt,
|
||||
&lib_kernel32,
|
||||
&lib_lmgr,
|
||||
&lib_ntdll,
|
||||
&lib_ole32,
|
||||
&lib_user32,
|
||||
&lib_vcruntime,
|
||||
&lib_version,
|
||||
nullptr,
|
||||
};
|
||||
|
||||
struct ModuleInfo {
|
||||
std::string name;
|
||||
const wibo::Module* module = nullptr;
|
||||
};
|
||||
|
||||
HMODULE wibo::loadModule(const char *dllName) {
|
||||
auto *result = new ModuleInfo;
|
||||
result->name = dllName;
|
||||
for (int i = 0; modules[i]; i++) {
|
||||
for (int j = 0; modules[i]->names[j]; j++) {
|
||||
if (strcasecmp(dllName, modules[i]->names[j]) == 0) {
|
||||
result->module = modules[i];
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void wibo::freeModule(HMODULE module) { delete static_cast<ModuleInfo *>(module); }
|
||||
|
||||
void *wibo::resolveFuncByName(HMODULE module, const char *funcName) {
|
||||
auto *info = static_cast<ModuleInfo *>(module);
|
||||
if (info && info->module && info->module->byName) {
|
||||
void *func = info->module->byName(funcName);
|
||||
if (func)
|
||||
return func;
|
||||
}
|
||||
return resolveMissingFuncName(info->name.c_str(), funcName);
|
||||
}
|
||||
|
||||
void *wibo::resolveFuncByOrdinal(HMODULE module, uint16_t ordinal) {
|
||||
auto *info = static_cast<ModuleInfo *>(module);
|
||||
if (info && info->module && info->module->byOrdinal) {
|
||||
void *func = info->module->byOrdinal(ordinal);
|
||||
if (func)
|
||||
return func;
|
||||
}
|
||||
return resolveMissingFuncOrdinal(info->name.c_str(), ordinal);
|
||||
}
|
||||
|
||||
struct UNICODE_STRING {
|
||||
|
@ -221,6 +260,9 @@ int main(int argc, char **argv) {
|
|||
wibo::commandLine = cmdLine.data();
|
||||
DEBUG_LOG("Command line: %s\n", wibo::commandLine);
|
||||
|
||||
wibo::argv = argv + 1;
|
||||
wibo::argc = argc - 1;
|
||||
|
||||
wibo::Executable exec;
|
||||
wibo::mainModule = &exec;
|
||||
|
||||
|
@ -259,13 +301,13 @@ int main(int argc, char **argv) {
|
|||
holdingMapStart = std::max(holdingMapStart, FILL_MEMORY_ABOVE);
|
||||
|
||||
void* holdingMap = mmap((void*) holdingMapStart, holdingMapEnd - holdingMapStart, PROT_READ, MAP_ANONYMOUS|MAP_FIXED|MAP_PRIVATE, -1, 0);
|
||||
|
||||
|
||||
if (holdingMap == MAP_FAILED) {
|
||||
perror("Failed to create holding map");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
lastMapEnd = mapEnd;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue