mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-21 04:33:56 +00:00
Add MinGW to CI (#343)
Honestly, this was really pain. During this excruciating process, I was reminded multiple times why I don't like MinGW. However, giving up is pussy shit. So there is now at least partial support for MinGW (rust code won't compile and I cba to fix that). This belongs to #335.
This commit is contained in:
44
.github/workflows/build.yml
vendored
44
.github/workflows/build.yml
vendored
@@ -166,6 +166,7 @@ jobs:
|
||||
platform:
|
||||
- Windows x86
|
||||
- Windows x86_64
|
||||
- MinGW x86_64
|
||||
- Linux x86_64 GCC
|
||||
- Linux x86_64 GCC Sanitizer
|
||||
- Linux x86_64 Clang
|
||||
@@ -190,6 +191,10 @@ jobs:
|
||||
- platform: Windows x86_64
|
||||
runner: windows-latest
|
||||
devcmd_arch: x64
|
||||
- platform: MinGW x86_64
|
||||
runner: ubuntu-24.04
|
||||
rust-target: x86_64-pc-windows-gnu
|
||||
cmake-options: "-DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/cmake/toolchain/mingw-w64.cmake"
|
||||
- platform: Linux x86_64 GCC Sanitizer
|
||||
runner: ubuntu-24.04
|
||||
cmake-options: "-DMOMO_ENABLE_SANITIZER=On"
|
||||
@@ -251,6 +256,12 @@ jobs:
|
||||
sudo update-alternatives --set cc /usr/bin/clang-${{ matrix.clang-version }}
|
||||
sudo update-alternatives --set c++ /usr/bin/clang++-${{ matrix.clang-version }}
|
||||
|
||||
- name: Set up MinGW
|
||||
uses: egor-tensin/setup-mingw@v2
|
||||
if: "${{ startsWith(matrix.platform, 'MinGW') }}"
|
||||
with:
|
||||
platform: x64
|
||||
|
||||
- name: Enable Developer Command Prompt
|
||||
uses: ilammy/msvc-dev-cmd@v1.13.0
|
||||
if: ${{ startsWith(matrix.platform, 'Windows') }}
|
||||
@@ -473,11 +484,6 @@ jobs:
|
||||
runs-on: ubuntu-24.04
|
||||
needs: [create-emulation-root, build]
|
||||
steps:
|
||||
- name: Checkout Source
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Download Artifacts
|
||||
uses: pyTooling/download-artifact@v4
|
||||
with:
|
||||
@@ -505,6 +511,32 @@ jobs:
|
||||
EMULATOR_ROOT: ${{github.workspace}}/build/release/artifacts/root
|
||||
EMULATOR_VERBOSE: ${{ github.event.inputs.verbose }}
|
||||
|
||||
smoke-test-mingw:
|
||||
name: Smoke Test MinGW x86_64
|
||||
runs-on: windows-latest
|
||||
needs: [create-emulation-root, build]
|
||||
steps:
|
||||
- name: Download Artifacts
|
||||
uses: pyTooling/download-artifact@v4
|
||||
with:
|
||||
name: MinGW x86_64 Release Artifacts
|
||||
path: build/release/artifacts
|
||||
|
||||
- name: Download Emulation Root
|
||||
uses: pyTooling/download-artifact@v4
|
||||
with:
|
||||
name: Windows 2022 Emulation Root
|
||||
path: build/release/artifacts/root
|
||||
|
||||
- name: Copy Test Sample
|
||||
run: cp build/release/artifacts/test-sample.exe build/release/artifacts/root/filesys/c/
|
||||
|
||||
- name: CMake Test
|
||||
run: cd build/release/artifacts && ./windows-emulator-test.exe && ./analyzer.exe -e root c:/test-sample.exe
|
||||
env:
|
||||
EMULATOR_ROOT: ${{github.workspace}}/build/release/artifacts/root
|
||||
EMULATOR_VERBOSE: ${{ github.event.inputs.verbose }}
|
||||
|
||||
|
||||
smoke-test-android:
|
||||
name: Smoke Test Android
|
||||
@@ -652,7 +684,7 @@ jobs:
|
||||
summary:
|
||||
name: Pipeline Summary
|
||||
runs-on: ubuntu-24.04
|
||||
needs: [build-page, clang-tidy, build-apiset-dumper, smoke-test-node, smoke-test-android, create-emulation-root, build, test, win-test, verify-formatting]
|
||||
needs: [build-page, clang-tidy, build-apiset-dumper, smoke-test-node, smoke-test-mingw, smoke-test-android, create-emulation-root, build, test, win-test, verify-formatting]
|
||||
if: always()
|
||||
steps:
|
||||
- uses: geekyeggo/delete-artifact@v5
|
||||
|
||||
@@ -25,21 +25,7 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
##########################################
|
||||
|
||||
if(MINGW)
|
||||
# Minimum version check for MinGW compiler
|
||||
set(MINGW_C_COMPILER_MIN_VERSION "14.0.0")
|
||||
set(MINGW_CXX_COMPILER_MIN_VERSION "14.0.0")
|
||||
|
||||
if (${CMAKE_C_COMPILER_VERSION} VERSION_LESS_EQUAL ${MINGW_C_COMPILER_MIN_VERSION})
|
||||
message(FATAL_ERROR "${CMAKE_C_COMPILER} version should >= ${MINGW_C_COMPILER_MIN_VERSION}")
|
||||
endif()
|
||||
if (${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS_EQUAL ${MINGW_CXX_COMPILER_MIN_VERSION})
|
||||
message(FATAL_ERROR "${CMAKE_C_COMPILER} version should >= ${MINGW_CXX_COMPILER_MIN_VERSION}")
|
||||
endif()
|
||||
|
||||
# MinGW LTO will cause errors in compile stage, We just disable it
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF)
|
||||
elseif(NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten")
|
||||
if(NOT MINGW AND NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten")
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
|
||||
endif()
|
||||
|
||||
@@ -53,7 +39,14 @@ endif()
|
||||
|
||||
##########################################
|
||||
|
||||
if(MOMO_ENABLE_RUST_CODE)
|
||||
set(MOMO_ENABLE_RUST OFF)
|
||||
if(MOMO_ENABLE_RUST_CODE AND NOT MINGW AND NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten")
|
||||
set(MOMO_ENABLE_RUST ON)
|
||||
endif()
|
||||
|
||||
##########################################
|
||||
|
||||
if(MOMO_ENABLE_RUST)
|
||||
add_compile_definitions(MOMO_ENABLE_RUST_CODE=1)
|
||||
else()
|
||||
add_compile_definitions(MOMO_ENABLE_RUST_CODE=0)
|
||||
@@ -70,6 +63,21 @@ endif()
|
||||
|
||||
##########################################
|
||||
|
||||
if(MINGW)
|
||||
add_link_options(
|
||||
-static-libstdc++
|
||||
-static-libgcc
|
||||
-static
|
||||
-lwinpthread
|
||||
)
|
||||
|
||||
momo_add_c_and_cxx_compile_options(
|
||||
-Wno-array-bounds
|
||||
)
|
||||
endif()
|
||||
|
||||
##########################################
|
||||
|
||||
if(LINUX)
|
||||
add_link_options(
|
||||
-Wl,--no-undefined
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
include_guard()
|
||||
|
||||
find_program(SCCACHE sccache)
|
||||
if(CMAKE_GENERATOR STREQUAL "Ninja")
|
||||
find_program(SCCACHE sccache)
|
||||
|
||||
if (SCCACHE)
|
||||
file(TO_CMAKE_PATH "${SCCACHE}" SCCACHE)
|
||||
set(CMAKE_C_COMPILER_LAUNCHER ${SCCACHE})
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER ${SCCACHE})
|
||||
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded)
|
||||
if (SCCACHE)
|
||||
file(TO_CMAKE_PATH "${SCCACHE}" SCCACHE)
|
||||
set(CMAKE_C_COMPILER_LAUNCHER ${SCCACHE})
|
||||
set(CMAKE_CXX_COMPILER_LAUNCHER ${SCCACHE})
|
||||
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded)
|
||||
|
||||
if(POLICY CMP0141)
|
||||
cmake_policy(SET CMP0141 NEW)
|
||||
if(POLICY CMP0141)
|
||||
cmake_policy(SET CMP0141 NEW)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@@ -9,9 +9,6 @@ momo_add_subdirectory_and_get_targets("backends" BACKEND_TARGETS)
|
||||
momo_targets_set_folder("backends" ${BACKEND_TARGETS})
|
||||
|
||||
if (NOT MOMO_BUILD_AS_LIBRARY)
|
||||
if (MINGW)
|
||||
add_link_options(-static-libstdc++ -static -lwinpthread)
|
||||
endif()
|
||||
add_subdirectory(analyzer)
|
||||
add_subdirectory(debugger)
|
||||
add_subdirectory(fuzzing-engine)
|
||||
|
||||
@@ -473,45 +473,50 @@ namespace
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
int run_main(const int argc, char** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto args = bundle_arguments(argc, argv);
|
||||
if (args.empty())
|
||||
{
|
||||
print_help();
|
||||
return 1;
|
||||
}
|
||||
|
||||
const auto options = parse_options(args);
|
||||
|
||||
bool result{};
|
||||
|
||||
do
|
||||
{
|
||||
result = run(options, args);
|
||||
} while (options.use_gdb);
|
||||
|
||||
return result ? 0 : 1;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
puts(e.what());
|
||||
|
||||
#if defined(_WIN32) && 0
|
||||
MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int main(const int argc, char** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto args = bundle_arguments(argc, argv);
|
||||
if (args.empty())
|
||||
{
|
||||
print_help();
|
||||
return 1;
|
||||
}
|
||||
|
||||
const auto options = parse_options(args);
|
||||
|
||||
bool result{};
|
||||
|
||||
do
|
||||
{
|
||||
result = run(options, args);
|
||||
} while (options.use_gdb);
|
||||
|
||||
return result ? 0 : 1;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
puts(e.what());
|
||||
|
||||
#if defined(_WIN32) && 0
|
||||
MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1;
|
||||
return run_main(argc, argv);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
int WINAPI WinMain(HINSTANCE, HINSTANCE, PSTR, int)
|
||||
{
|
||||
return main(__argc, __argv);
|
||||
return run_main(__argc, __argv);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -16,7 +16,7 @@ target_link_libraries(backend-selection PRIVATE
|
||||
unicorn-emulator
|
||||
)
|
||||
|
||||
if (MOMO_ENABLE_RUST_CODE)
|
||||
if (MOMO_ENABLE_RUST)
|
||||
target_link_libraries(backend-selection PRIVATE
|
||||
icicle-emulator
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
add_subdirectory(unicorn-emulator)
|
||||
|
||||
if (MOMO_ENABLE_RUST_CODE)
|
||||
if (MOMO_ENABLE_RUST)
|
||||
add_subdirectory(icicle-emulator)
|
||||
endif()
|
||||
|
||||
@@ -13,7 +13,9 @@ endif()
|
||||
set(CARGO_TRIPLE)
|
||||
set(CARGO_OPTIONS)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
|
||||
if (MINGW)
|
||||
set(CARGO_TRIPLE "x86_64-pc-windows-gnu")
|
||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
|
||||
set(CARGO_TRIPLE "wasm32-unknown-emscripten")
|
||||
elseif(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
set(CARGO_TRIPLE "i686-pc-windows-msvc")
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#include <unicorn/unicorn.h>
|
||||
|
||||
#ifdef __clang__
|
||||
|
||||
@@ -17,7 +17,7 @@ target_link_libraries(emulator-common PUBLIC
|
||||
zlibstatic
|
||||
)
|
||||
|
||||
if(MINGW)
|
||||
if(WIN)
|
||||
target_link_libraries(emulator-common PUBLIC
|
||||
ws2_32
|
||||
)
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
|
||||
#ifdef _WIN32
|
||||
using socklen_t = int;
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
#endif
|
||||
|
||||
namespace network
|
||||
|
||||
@@ -20,11 +20,13 @@
|
||||
#endif
|
||||
|
||||
#ifdef OS_WINDOWS
|
||||
#define EXPORT_SYMBOL __declspec(dllexport)
|
||||
#define IMPORT_SYMBOL __declspec(dllimport)
|
||||
#define NO_INLINE __declspec(noinline)
|
||||
#define EXPORT_SYMBOL __declspec(dllexport)
|
||||
#define IMPORT_SYMBOL __declspec(dllimport)
|
||||
#define NO_INLINE __declspec(noinline)
|
||||
|
||||
#ifndef DECLSPEC_ALIGN
|
||||
#define DECLSPEC_ALIGN(n) __declspec(align(n))
|
||||
#endif
|
||||
|
||||
#define RESTRICTED_POINTER
|
||||
|
||||
|
||||
@@ -72,8 +72,10 @@
|
||||
#define SL_RETURN_SINGLE_ENTRY 0x02
|
||||
#define SL_NO_CURSOR_UPDATE 0x10
|
||||
|
||||
#define SEC_IMAGE 0x01000000
|
||||
#define SEC_RESERVE 0x04000000
|
||||
#ifndef SEC_IMAGE
|
||||
#define SEC_IMAGE 0x01000000
|
||||
#define SEC_RESERVE 0x04000000
|
||||
#endif
|
||||
|
||||
typedef enum _FSINFOCLASS
|
||||
{
|
||||
@@ -395,6 +397,11 @@ typedef struct _FILE_BOTH_DIR_INFORMATION
|
||||
} FILE_BOTH_DIR_INFORMATION, *PFILE_BOTH_DIR_INFORMATION;
|
||||
|
||||
#ifndef OS_WINDOWS
|
||||
typedef struct _FILE_ID_128
|
||||
{
|
||||
BYTE Identifier[16];
|
||||
} FILE_ID_128, *PFILE_ID_128;
|
||||
|
||||
typedef BOOLEAN SECURITY_CONTEXT_TRACKING_MODE, *PSECURITY_CONTEXT_TRACKING_MODE;
|
||||
typedef struct _SECURITY_QUALITY_OF_SERVICE
|
||||
{
|
||||
@@ -406,6 +413,27 @@ typedef struct _SECURITY_QUALITY_OF_SERVICE
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
typedef struct _FILE_STAT_BASIC_INFORMATION
|
||||
{
|
||||
LARGE_INTEGER FileId;
|
||||
LARGE_INTEGER CreationTime;
|
||||
LARGE_INTEGER LastAccessTime;
|
||||
LARGE_INTEGER LastWriteTime;
|
||||
LARGE_INTEGER ChangeTime;
|
||||
LARGE_INTEGER AllocationSize;
|
||||
LARGE_INTEGER EndOfFile;
|
||||
ULONG FileAttributes;
|
||||
ULONG ReparseTag;
|
||||
ULONG NumberOfLinks;
|
||||
ULONG DeviceType;
|
||||
ULONG DeviceCharacteristics;
|
||||
ULONG Reserved;
|
||||
LARGE_INTEGER VolumeSerialNumber;
|
||||
FILE_ID_128 FileId128;
|
||||
} FILE_STAT_BASIC_INFORMATION, *PFILE_STAT_BASIC_INFORMATION;
|
||||
#endif
|
||||
|
||||
typedef struct _PORT_VIEW64
|
||||
{
|
||||
ULONG Length;
|
||||
@@ -423,4 +451,10 @@ typedef struct _REMOTE_PORT_VIEW64
|
||||
EmulatorTraits<Emu64>::PVOID ViewBase;
|
||||
} REMOTE_PORT_VIEW64, *PREMOTE_PORT_VIEW64;
|
||||
|
||||
typedef struct _OBJECT_HANDLE_FLAG_INFORMATION
|
||||
{
|
||||
BOOLEAN Inherit;
|
||||
BOOLEAN ProtectFromClose;
|
||||
} OBJECT_HANDLE_FLAG_INFORMATION, *POBJECT_HANDLE_FLAG_INFORMATION;
|
||||
|
||||
// NOLINTEND(modernize-use-using,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||
|
||||
@@ -2,23 +2,24 @@
|
||||
|
||||
// NOLINTBEGIN(modernize-use-using)
|
||||
|
||||
#define PAGE_EXECUTE 0x10
|
||||
#define PAGE_EXECUTE_READ 0x20
|
||||
#define PAGE_EXECUTE_READWRITE 0x40
|
||||
#define PAGE_EXECUTE_WRITECOPY 0x80
|
||||
#define PAGE_EXECUTE 0x10
|
||||
#define PAGE_EXECUTE_READ 0x20
|
||||
#define PAGE_EXECUTE_READWRITE 0x40
|
||||
#define PAGE_EXECUTE_WRITECOPY 0x80
|
||||
|
||||
#define PAGE_NOACCESS 0x01
|
||||
#define PAGE_READONLY 0x02
|
||||
#define PAGE_READWRITE 0x04
|
||||
#define PAGE_WRITECOPY 0x08
|
||||
#define PAGE_NOACCESS 0x01
|
||||
#define PAGE_READONLY 0x02
|
||||
#define PAGE_READWRITE 0x04
|
||||
#define PAGE_WRITECOPY 0x08
|
||||
|
||||
#define PAGE_TARGETS_INVALID 0x40000000
|
||||
#define PAGE_TARGETS_NO_UPDATE 0x40000000
|
||||
#define PAGE_TARGETS_INVALID 0x40000000
|
||||
#define PAGE_TARGETS_NO_UPDATE 0x40000000
|
||||
|
||||
#define PAGE_GUARD 0x100
|
||||
#define PAGE_NOCACHE 0x200
|
||||
#define PAGE_WRITECOMBINE 0x400
|
||||
#define PAGE_GUARD 0x100
|
||||
#define PAGE_NOCACHE 0x200
|
||||
#define PAGE_WRITECOMBINE 0x400
|
||||
|
||||
#ifndef MEM_64K_PAGES
|
||||
#define MEM_COMMIT 0x00001000
|
||||
#define MEM_RESERVE 0x00002000
|
||||
#define MEM_DECOMMIT 0x00004000
|
||||
@@ -37,6 +38,7 @@
|
||||
#define MEM_DOS_LIM 0x40000000
|
||||
#define MEM_4MB_PAGES 0x80000000
|
||||
#define MEM_64K_PAGES (MEM_LARGE_PAGES | MEM_PHYSICAL)
|
||||
#endif
|
||||
|
||||
typedef enum _MEMORY_INFORMATION_CLASS
|
||||
{
|
||||
@@ -64,7 +66,11 @@ typedef enum _SECTION_INHERIT
|
||||
ViewUnmap = 2
|
||||
} SECTION_INHERIT;
|
||||
|
||||
typedef struct DECLSPEC_ALIGN(16) _EMU_MEMORY_BASIC_INFORMATION64
|
||||
typedef struct
|
||||
#ifndef __MINGW64__
|
||||
DECLSPEC_ALIGN(16)
|
||||
#endif
|
||||
_EMU_MEMORY_BASIC_INFORMATION64
|
||||
{
|
||||
uint64_t BaseAddress;
|
||||
uint64_t AllocationBase;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(__MINGW64__)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4201) // nameless struct/union
|
||||
#pragma warning(disable : 4702) // unreachable code
|
||||
@@ -31,6 +31,6 @@
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef OS_WINDOWS
|
||||
#if defined(_WIN32) && !defined(__MINGW64__)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
@@ -591,7 +591,11 @@ using NEON128 = struct _NEON128
|
||||
LONGLONG High;
|
||||
};
|
||||
|
||||
typedef struct DECLSPEC_ALIGN(16) _CONTEXT64
|
||||
typedef struct
|
||||
#if !defined(__MINGW64__)
|
||||
DECLSPEC_ALIGN(16)
|
||||
#endif
|
||||
_CONTEXT64
|
||||
{
|
||||
DWORD64 P1Home;
|
||||
DWORD64 P2Home;
|
||||
|
||||
@@ -19,7 +19,7 @@ target_link_libraries(fuzzer PRIVATE
|
||||
windows-emulator
|
||||
)
|
||||
|
||||
if (MOMO_ENABLE_RUST_CODE)
|
||||
if (MOMO_ENABLE_RUST)
|
||||
target_link_libraries(fuzzer PRIVATE
|
||||
icicle-emulator
|
||||
)
|
||||
|
||||
@@ -166,46 +166,51 @@ namespace
|
||||
forward_emulator(win_emu);
|
||||
run_fuzzer(win_emu);
|
||||
}
|
||||
|
||||
int run_main(const int argc, char** argv)
|
||||
{
|
||||
if (argc <= 1)
|
||||
{
|
||||
puts("Application not specified!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// setvbuf(stdout, nullptr, _IOFBF, 0x10000);
|
||||
if (argc > 2 && argv[1] == "-d"s)
|
||||
{
|
||||
use_gdb = true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
do
|
||||
{
|
||||
run(argv[use_gdb ? 2 : 1]);
|
||||
} while (use_gdb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
puts(e.what());
|
||||
|
||||
#if defined(_WIN32) && 0
|
||||
MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int main(const int argc, char** argv)
|
||||
{
|
||||
if (argc <= 1)
|
||||
{
|
||||
puts("Application not specified!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// setvbuf(stdout, nullptr, _IOFBF, 0x10000);
|
||||
if (argc > 2 && argv[1] == "-d"s)
|
||||
{
|
||||
use_gdb = true;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
do
|
||||
{
|
||||
run(argv[use_gdb ? 2 : 1]);
|
||||
} while (use_gdb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
puts(e.what());
|
||||
|
||||
#if defined(_WIN32) && 0
|
||||
MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1;
|
||||
return run_main(argc, argv);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
int WINAPI WinMain(HINSTANCE, HINSTANCE, PSTR, int)
|
||||
{
|
||||
return main(__argc, __argv);
|
||||
return run_main(__argc, __argv);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -8,7 +8,7 @@ list(SORT SRC_FILES)
|
||||
|
||||
add_executable(test-sample ${SRC_FILES})
|
||||
|
||||
if(MINGW)
|
||||
if(WIN)
|
||||
target_link_libraries(test-sample PRIVATE ws2_32)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
#include <filesystem>
|
||||
#include <string_view>
|
||||
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <intrin.h>
|
||||
|
||||
@@ -23,8 +25,6 @@
|
||||
#include <WS2tcpip.h>
|
||||
#endif
|
||||
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
// Externally visible and potentially modifiable state
|
||||
@@ -570,8 +570,10 @@ namespace
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sendto(sender, send_data.data(), static_cast<int>(send_data.size()), 0,
|
||||
reinterpret_cast<sockaddr*>(&destination), sizeof(destination)) != send_data.size())
|
||||
const auto sent_bytes = sendto(sender, send_data.data(), static_cast<int>(send_data.size()), 0,
|
||||
reinterpret_cast<sockaddr*>(&destination), sizeof(destination));
|
||||
|
||||
if (static_cast<size_t>(sent_bytes) != send_data.size())
|
||||
{
|
||||
puts("Failed to send data!");
|
||||
return false;
|
||||
@@ -593,6 +595,7 @@ namespace
|
||||
return send_data == std::string_view(buffer, len);
|
||||
}
|
||||
|
||||
#ifndef __MINGW64__
|
||||
void throw_access_violation()
|
||||
{
|
||||
if (do_the_task)
|
||||
@@ -601,7 +604,6 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __MINGW64__
|
||||
bool test_access_violation_exception()
|
||||
{
|
||||
__try
|
||||
|
||||
@@ -24,14 +24,14 @@ int main()
|
||||
const auto peb = static_cast<PPEB64>(GetCurrentProcessPeb());
|
||||
const auto api_set_map = reinterpret_cast<API_SET_NAMESPACE*>(peb->ApiSetMap);
|
||||
|
||||
printf("APISET: 0x%p\n", api_set_map);
|
||||
printf("Version: %d\n", api_set_map->Version);
|
||||
printf("Size: %08X\n", api_set_map->Size);
|
||||
printf("Flags: %08X\n", api_set_map->Flags);
|
||||
printf("Count: %d\n", api_set_map->Count);
|
||||
printf("EntryOffset: %08X\n", api_set_map->EntryOffset);
|
||||
printf("HashOffset: %08X\n", api_set_map->HashOffset);
|
||||
printf("HashFactor: %08X\n", api_set_map->HashFactor);
|
||||
printf("APISET: 0x%p\n", static_cast<void*>(api_set_map));
|
||||
printf("Version: %lu\n", api_set_map->Version);
|
||||
printf("Size: %08lX\n", api_set_map->Size);
|
||||
printf("Flags: %08lX\n", api_set_map->Flags);
|
||||
printf("Count: %lu\n", api_set_map->Count);
|
||||
printf("EntryOffset: %08lX\n", api_set_map->EntryOffset);
|
||||
printf("HashOffset: %08lX\n", api_set_map->HashOffset);
|
||||
printf("HashFactor: %08lX\n", api_set_map->HashFactor);
|
||||
// print_apiset(apiSetMap);
|
||||
|
||||
// Compress the API-SET binary blob
|
||||
@@ -68,7 +68,7 @@ void print_apiset(PAPI_SET_NAMESPACE api_set_map)
|
||||
|
||||
std::wstring name(reinterpret_cast<wchar_t*>(reinterpret_cast<ULONG_PTR>(api_set_map) + entry->NameOffset),
|
||||
entry->NameLength / sizeof(wchar_t));
|
||||
printf("-----------\n[%05d]: Contract Name: %ls\n", i, name.data());
|
||||
printf("-----------\n[%05lu]: Contract Name: %ls\n", i, name.data());
|
||||
|
||||
for (ULONG x = 0; x < entry->ValueCount; x++)
|
||||
{
|
||||
|
||||
@@ -56,6 +56,19 @@ class file_system
|
||||
return root;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void access_mapped_entries(const windows_path& win_path, const F& accessor) const
|
||||
{
|
||||
for (const auto& mapping : this->mappings_)
|
||||
{
|
||||
const auto& mapped_path = mapping.first;
|
||||
if (!mapped_path.empty() && mapped_path.parent() == win_path)
|
||||
{
|
||||
accessor(mapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
windows_path local_to_windows_path(const std::filesystem::path& local_path) const
|
||||
{
|
||||
const auto absolute_local_path = weakly_canonical(absolute(local_path));
|
||||
|
||||
@@ -1,36 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4005)
|
||||
#pragma warning(disable : 4127)
|
||||
#pragma warning(disable : 4201)
|
||||
#pragma warning(disable : 4244)
|
||||
#pragma warning(disable : 4245)
|
||||
#pragma warning(disable : 4324)
|
||||
#pragma warning(disable : 4458)
|
||||
#pragma warning(disable : 4471)
|
||||
#pragma warning(disable : 4505)
|
||||
#pragma warning(disable : 4702)
|
||||
#pragma warning(disable : 4996)
|
||||
#pragma warning(disable : 5054)
|
||||
#pragma warning(disable : 6011)
|
||||
#pragma warning(disable : 6297)
|
||||
#pragma warning(disable : 6385)
|
||||
#pragma warning(disable : 6386)
|
||||
#pragma warning(disable : 6387)
|
||||
#pragma warning(disable : 26110)
|
||||
#pragma warning(disable : 26451)
|
||||
#pragma warning(disable : 26444)
|
||||
#pragma warning(disable : 26451)
|
||||
#pragma warning(disable : 26489)
|
||||
#pragma warning(disable : 26495)
|
||||
#pragma warning(disable : 26498)
|
||||
#pragma warning(disable : 26812)
|
||||
#pragma warning(disable : 28020)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <list>
|
||||
|
||||
@@ -217,14 +217,15 @@ NTSTATUS handle_query_internal(x86_64_emulator& emu, const uint64_t buffer, cons
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
template <typename ResponseType, typename Action>
|
||||
template <typename ResponseType, typename Action, typename LengthType>
|
||||
requires(std::is_integral_v<LengthType>)
|
||||
NTSTATUS handle_query(x86_64_emulator& emu, const uint64_t buffer, const uint32_t length,
|
||||
const emulator_object<uint32_t> return_length, const Action& action)
|
||||
const emulator_object<LengthType> return_length, const Action& action)
|
||||
{
|
||||
const auto length_setter = [&](const uint32_t required_size) {
|
||||
const auto length_setter = [&](const size_t required_size) {
|
||||
if (return_length)
|
||||
{
|
||||
return_length.write(required_size);
|
||||
return_length.write(static_cast<LengthType>(required_size));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -66,6 +66,10 @@ namespace syscalls
|
||||
NTSTATUS handle_NtQueryInformationFile(const syscall_context& c, handle file_handle,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
uint64_t file_information, uint32_t length, uint32_t info_class);
|
||||
NTSTATUS handle_NtQueryInformationByName(
|
||||
const syscall_context& c, emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, uint64_t file_information,
|
||||
uint32_t length, uint32_t info_class);
|
||||
NTSTATUS handle_NtReadFile(const syscall_context& c, handle file_handle, uint64_t /*event*/,
|
||||
uint64_t /*apc_routine*/, uint64_t /*apc_context*/,
|
||||
emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, uint64_t buffer,
|
||||
@@ -1091,6 +1095,7 @@ void syscall_dispatcher::add_handlers(std::map<std::string, syscall_handler>& ha
|
||||
add_handler(NtUserSetProp2);
|
||||
add_handler(NtUserChangeWindowMessageFilterEx);
|
||||
add_handler(NtUserDestroyWindow);
|
||||
add_handler(NtQueryInformationByName);
|
||||
|
||||
#undef add_handler
|
||||
}
|
||||
|
||||
@@ -17,6 +17,35 @@
|
||||
|
||||
namespace syscalls
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::pair<utils::file_handle, NTSTATUS> open_file(const file_system& file_sys, const windows_path& path,
|
||||
const std::u16string& mode)
|
||||
{
|
||||
FILE* file{};
|
||||
const auto error = open_unicode(&file, file_sys.translate(path), mode);
|
||||
|
||||
if (file)
|
||||
{
|
||||
return {file, STATUS_SUCCESS};
|
||||
}
|
||||
|
||||
using fh = utils::file_handle;
|
||||
|
||||
switch (error)
|
||||
{
|
||||
case ENOENT:
|
||||
return {fh{}, STATUS_OBJECT_NAME_NOT_FOUND};
|
||||
case EACCES:
|
||||
return {fh{}, STATUS_ACCESS_DENIED};
|
||||
case EISDIR:
|
||||
return {fh{}, STATUS_FILE_IS_A_DIRECTORY};
|
||||
default:
|
||||
return {fh{}, STATUS_NOT_SUPPORTED};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtSetInformationFile(const syscall_context& c, const handle file_handle,
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
const uint64_t file_information, const ULONG length,
|
||||
@@ -117,10 +146,13 @@ namespace syscalls
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<file_entry> scan_directory(const std::filesystem::path& dir, const std::u16string_view file_mask)
|
||||
std::vector<file_entry> scan_directory(const file_system& file_sys, const windows_path& win_path,
|
||||
const std::u16string_view file_mask)
|
||||
{
|
||||
std::vector<file_entry> files{};
|
||||
|
||||
const auto dir = file_sys.translate(win_path);
|
||||
|
||||
if (file_mask.empty() || file_mask == u"*")
|
||||
{
|
||||
files.emplace_back(file_entry{.file_path = ".", .is_directory = true});
|
||||
@@ -142,6 +174,27 @@ namespace syscalls
|
||||
});
|
||||
}
|
||||
|
||||
file_sys.access_mapped_entries(win_path, [&](const std::pair<windows_path, std::filesystem::path>& entry) {
|
||||
const auto filename = entry.first.leaf();
|
||||
|
||||
if (!file_mask.empty() && !utils::wildcard::match_filename(filename, file_mask))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const std::filesystem::directory_entry dir_entry(entry.second, ec);
|
||||
if (ec || !dir_entry.exists())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
files.emplace_back(file_entry{
|
||||
.file_path = filename,
|
||||
.file_size = dir_entry.file_size(),
|
||||
.is_directory = dir_entry.is_directory(),
|
||||
});
|
||||
});
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
@@ -166,7 +219,7 @@ namespace syscalls
|
||||
}
|
||||
|
||||
f->enumeration_state.emplace(file_enumeration_state{});
|
||||
f->enumeration_state->files = scan_directory(c.win_emu.file_sys.translate(f->name), mask);
|
||||
f->enumeration_state->files = scan_directory(c.win_emu.file_sys, f->name, mask);
|
||||
}
|
||||
|
||||
auto& enum_state = *f->enumeration_state;
|
||||
@@ -464,6 +517,72 @@ namespace syscalls
|
||||
return ret(STATUS_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtQueryInformationByName(
|
||||
const syscall_context& c, const emulator_object<OBJECT_ATTRIBUTES<EmulatorTraits<Emu64>>> object_attributes,
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block, const uint64_t file_information,
|
||||
const uint32_t length, const uint32_t info_class)
|
||||
{
|
||||
IO_STATUS_BLOCK<EmulatorTraits<Emu64>> block{};
|
||||
block.Status = STATUS_SUCCESS;
|
||||
block.Information = 0;
|
||||
|
||||
const auto _ = utils::finally([&] {
|
||||
if (io_status_block)
|
||||
{
|
||||
io_status_block.write(block);
|
||||
}
|
||||
});
|
||||
|
||||
const auto attributes = object_attributes.read();
|
||||
auto filename = read_unicode_string(c.emu, attributes.ObjectName);
|
||||
|
||||
c.win_emu.log.print(color::dark_gray, "--> Query file info: %s\n", u16_to_u8(filename).c_str()); //
|
||||
|
||||
const auto ret = [&](const NTSTATUS status) {
|
||||
block.Status = status;
|
||||
return status;
|
||||
};
|
||||
|
||||
if (info_class == FileStatBasicInformation)
|
||||
{
|
||||
block.Information = sizeof(FILE_STAT_BASIC_INFORMATION);
|
||||
|
||||
if (length < block.Information)
|
||||
{
|
||||
return ret(STATUS_BUFFER_OVERFLOW);
|
||||
}
|
||||
|
||||
auto [native_file_handle, status] = open_file(c.win_emu.file_sys, filename, u"r");
|
||||
if (status != STATUS_SUCCESS)
|
||||
{
|
||||
return ret(status);
|
||||
}
|
||||
|
||||
struct _stat64 file_stat{};
|
||||
if (fstat64(native_file_handle, &file_stat) != 0)
|
||||
{
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
FILE_STAT_BASIC_INFORMATION i{};
|
||||
|
||||
i.CreationTime = utils::convert_unix_to_windows_time(file_stat.st_atime);
|
||||
i.LastAccessTime = utils::convert_unix_to_windows_time(file_stat.st_atime);
|
||||
i.LastWriteTime = utils::convert_unix_to_windows_time(file_stat.st_mtime);
|
||||
i.ChangeTime = i.LastWriteTime;
|
||||
i.FileAttributes = (file_stat.st_mode & S_IFDIR) != 0 ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
|
||||
|
||||
c.emu.write_memory(file_information, i);
|
||||
|
||||
return ret(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
c.win_emu.log.error("Unsupported query name info class: %X\n", info_class);
|
||||
c.emu.stop();
|
||||
|
||||
return ret(STATUS_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
void commit_file_data(const std::string_view data, emulator& emu,
|
||||
const emulator_object<IO_STATUS_BLOCK<EmulatorTraits<Emu64>>> io_status_block,
|
||||
const uint64_t buffer)
|
||||
@@ -739,26 +858,13 @@ namespace syscalls
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
FILE* file{};
|
||||
|
||||
const auto error = open_unicode(&file, c.win_emu.file_sys.translate(path), mode);
|
||||
|
||||
if (!file)
|
||||
auto [native_file_handle, status] = open_file(c.win_emu.file_sys, path, mode);
|
||||
if (status != STATUS_SUCCESS)
|
||||
{
|
||||
switch (error)
|
||||
{
|
||||
case ENOENT:
|
||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
case EACCES:
|
||||
return STATUS_ACCESS_DENIED;
|
||||
case EISDIR:
|
||||
return STATUS_FILE_IS_A_DIRECTORY;
|
||||
default:
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
f.handle = file;
|
||||
f.handle = std::move(native_file_handle);
|
||||
|
||||
const auto handle = c.proc.files.store(std::move(f));
|
||||
file_handle.write(handle);
|
||||
@@ -982,4 +1088,4 @@ namespace syscalls
|
||||
(void)fflush(f->handle);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,6 +99,16 @@ namespace syscalls
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (object_information_class == ObjectHandleFlagInformation)
|
||||
{
|
||||
return handle_query<OBJECT_HANDLE_FLAG_INFORMATION>(c.emu, object_information, object_information_length,
|
||||
return_length,
|
||||
[&](OBJECT_HANDLE_FLAG_INFORMATION& info) {
|
||||
info.Inherit = 0;
|
||||
info.ProtectFromClose = 0;
|
||||
});
|
||||
}
|
||||
|
||||
c.win_emu.log.error("Unsupported object info class: %X\n", object_information_class);
|
||||
c.emu.stop();
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
@@ -176,4 +186,4 @@ namespace syscalls
|
||||
{
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,6 +224,16 @@ class windows_path
|
||||
return {this->drive_, std::move(folders)};
|
||||
}
|
||||
|
||||
std::u16string leaf() const
|
||||
{
|
||||
if (this->folders_.empty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return this->folders_.back();
|
||||
}
|
||||
|
||||
void serialize(utils::buffer_serializer& buffer) const
|
||||
{
|
||||
buffer.write_optional(this->drive_);
|
||||
|
||||
Reference in New Issue
Block a user