win32 define and injector

This commit is contained in:
HolographicHat
2022-06-10 18:34:24 +08:00
parent 8aed3fd095
commit 12348a3941
17 changed files with 312 additions and 139 deletions

View File

@@ -5,41 +5,3 @@
![GitHub](https://img.shields.io/badge/License-GPL--3.0-brightgreen?style=flat-square) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/HolographicHat/genshin-achievement-export?color=brightgreen&label=Release&style=flat-square) ![GitHub issues](https://img.shields.io/github/issues/HolographicHat/genshin-achievement-export?label=Issues&style=flat-square) ![Downloads](https://img.shields.io/github/downloads/HolographicHat/genshin-achievement-export/total?color=brightgreen&label=Downloads&style=flat-square) ![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)
</div>
- 支持导出所有类别的成就
- 支持官服,渠道服与国际服
- 支持导出至[椰羊](https://cocogoat.work/achievement)、[SnapGenshin](https://github.com/DGP-Studio/Snap.Genshin)、[Paimon.moe](https://paimon.moe/achievement/)、[Seelie.me](https://seelie.me/achievements)和表格文件(csv)
- 没有窗口大小、游戏语言等要求
## 使用说明
**打开程序前需要关闭正在运行的原神主程序**
第一次打开需要先设置原神主程序(YuanShen.exe/GenshinImpact.exe)所在路径
![alt](https://upload-bbs.mihoyo.com/upload/2022/04/06/165631158/e540a5a6d50cd5fdee19665435548e00_514247033566841954.jpg)
### Windows7
系统变量添加名为```NODE_SKIP_PLATFORM_CHECK```的变量并将值设为```1```
[[?]如何添加环境变量](https://www.bing.com/search?q=windows+7+环境变量)
## 下载地址
[releases/latest](https://github.com/HolographicHat/genshin-achievement-export/releases/latest)
## 问题反馈
[issues](https://github.com/HolographicHat/genshin-achievement-export/issues)或[QQ群: 913777414](https://qm.qq.com/cgi-bin/qm/qr?k=9UGz-chQVTjZa4b82RA_A41vIcBVNpms&jump_from=webapi)
## 常见问题
0. Q: 程序异常退出或被强行终止后,程序报错:网络错误(22-1) 或 原神启动时报错: 无法连接网络(4201)
A: 用文本编辑器打开```C:\Windows\System32\drivers\etc\hosts```,删除```127.0.0.1 dispatch**global.yuanshen.com```后保存,重启原神
1. Q: 原神启动时报错: 数据异常(31-4302)
A: 不要把软件和原神主程序放一起
2. Q: 为什么需要管理员权限
A: 临时修改Hosts和启动原神
3. Q: 报毒?
A: 执行命令或修改hosts引发相关代码可在./utils.js,./appcenter.js下找到
4. Q: 原神进门后没有自动退出,程序输出停留在“加载完成”
A: 关闭代理后重试
5. Q: 网络错误,请检查网络后重试 (21-x)
A: 如果你是校园网用户使用流量上网并重试如果你是海外用户打开config.json将oversea_api的值设置为true并重试

View File

@@ -5,6 +5,7 @@
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
</Project>

View File

@@ -15,12 +15,10 @@ Global
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{83C3DF1A-6219-408E-98A3-C7040CCC96FD}.Debug|x64.ActiveCfg = Debug|x64
{83C3DF1A-6219-408E-98A3-C7040CCC96FD}.Debug|x64.Build.0 = Debug|x64
{83C3DF1A-6219-408E-98A3-C7040CCC96FD}.Debug|x86.ActiveCfg = Debug|Win32
{83C3DF1A-6219-408E-98A3-C7040CCC96FD}.Debug|x86.Build.0 = Debug|Win32
{83C3DF1A-6219-408E-98A3-C7040CCC96FD}.Debug|x86.ActiveCfg = Debug|x64
{83C3DF1A-6219-408E-98A3-C7040CCC96FD}.Release|x64.ActiveCfg = Release|x64
{83C3DF1A-6219-408E-98A3-C7040CCC96FD}.Release|x64.Build.0 = Release|x64
{83C3DF1A-6219-408E-98A3-C7040CCC96FD}.Release|x86.ActiveCfg = Release|Win32
{83C3DF1A-6219-408E-98A3-C7040CCC96FD}.Release|x86.Build.0 = Release|Win32
{83C3DF1A-6219-408E-98A3-C7040CCC96FD}.Release|x86.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -1,14 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
@@ -26,43 +18,25 @@
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<CharacterSet>MultiByte</CharacterSet>
<EnableASAN>false</EnableASAN>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
@@ -70,52 +44,16 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>build\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)build\$(Platform)\$(Configuration)\</OutDir>
<IntDir>build\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;YAEACHIEVEMENTLIB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;YAEACHIEVEMENTLIB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
@@ -124,6 +62,8 @@
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpplatest</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -141,6 +81,11 @@
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<LanguageStandard>stdcpplatest</LanguageStandard>
<LanguageStandard_C>stdc17</LanguageStandard_C>
<DebugInformationFormat>None</DebugInformationFormat>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -151,15 +96,13 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="framework.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="src\framework.h" />
<ClInclude Include="src\pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="pch.cpp">
<ClCompile Include="src\dllmain.cpp" />
<ClCompile Include="src\pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>

View File

@@ -1,19 +1,12 @@
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include "pch.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

View File

@@ -1,5 +1 @@
// pch.cpp: 与预编译标头对应的源文件
#include "pch.h"
// 当使用预编译的头时,需要使用此源文件,编译才能成功。
#include "pch.h"

5
src/GlobalVars.cs Normal file
View File

@@ -0,0 +1,5 @@
namespace YaeAchievement;
public static class GlobalVars {
public static bool Verbose = false;
}

53
src/Injector.cs Normal file
View File

@@ -0,0 +1,53 @@
using System.ComponentModel;
using YaeAchievement.Win32;
namespace YaeAchievement;
public static class Injector {
public static bool CreateProcess(string path, ref IntPtr phThread, ref IntPtr phProcess) {
ProcessInformation pi;
unsafe {
var si = new StartupInfo();
SecurityAttributes* attr = null;
var result = Native.CreateProcess(
path, null, ref *attr, ref *attr, false,
CreationFlags.CreateSuspended, IntPtr.Zero, null, ref si, out pi
);
if (!result) {
return false;
}
}
phThread = pi.hThread;
phProcess = pi.hProcess;
return true;
}
public static int LoadLibraryAndInject(IntPtr handle, string libPath) {
var hKernel = Native.GetModuleHandle("kernel32.dll");
if (hKernel == IntPtr.Zero) {
return new Win32Exception().PrintMsgAndReturnErrCode("GetModuleHandle fail");
}
var pLoadLibrary = Native.GetProcAddress(hKernel, "LoadLibraryA");
if (pLoadLibrary == IntPtr.Zero) {
return new Win32Exception().PrintMsgAndReturnErrCode("GetProcAddress fail");
}
var pBase = Native.VirtualAllocEx(handle, IntPtr.Zero, libPath.Length + 1, AllocationType.Reserve | AllocationType.Commit, MemoryProtection.ReadWrite);
if (pBase == IntPtr.Zero) {
return new Win32Exception().PrintMsgAndReturnErrCode("VirtualAllocEx fail");
}
if (!Native.WriteProcessMemory(handle, pBase, libPath.ToCharArray(), libPath.Length, out _)) {
return new Win32Exception().PrintMsgAndReturnErrCode("WriteProcessMemory fail");
}
var hThread = Native.CreateRemoteThread(handle, IntPtr.Zero, 0, pLoadLibrary, pBase, 0, out _);
if (hThread == IntPtr.Zero) {
var e = new Win32Exception();
if (!Native.VirtualFreeEx(handle, pBase, 0, AllocationType.Release)) {
new Win32Exception().PrintMsgAndReturnErrCode("VirtualFreeEx fail");
}
return e.PrintMsgAndReturnErrCode("CreateRemoteThread fail");
}
return !Native.CloseHandle(hThread) ? new Win32Exception().PrintMsgAndReturnErrCode("CloseHandle fail") : 0;
}
}

View File

@@ -1,3 +1,46 @@
// See https://aka.ms/new-console-template for more information
using System.ComponentModel;
using System.IO.Pipes;
using YaeAchievement;
using YaeAchievement.Win32;
Console.WriteLine("Hello, World!");
var hThread = IntPtr.Zero;
var hProcess = IntPtr.Zero;
if (!Injector.CreateProcess("exePath", ref hThread, ref hProcess)) {
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("ICreateProcess fail"));
}
if (Injector.LoadLibraryAndInject(hProcess, "YaeAchievementLib.dll") != 0) {
if (!Native.TerminateProcess(hProcess, 0)) {
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("TerminateProcess fail"));
}
}
if (Native.ResumeThread(hThread) == 0xFFFFFFFF) {
var e = new Win32Exception();
if (!Native.TerminateProcess(hProcess, 0)) {
new Win32Exception().PrintMsgAndReturnErrCode("TerminateProcess fail");
}
Environment.Exit(e.PrintMsgAndReturnErrCode("ResumeThread fail"));
}
if (!Native.CloseHandle(hProcess)) {
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("CloseHandle fail"));
}
bool OnXXXReceived(string something) {
return true;
}
var ts = new ThreadStart(() => {
var server = new NamedPipeServerStream("");
server.WaitForConnection();
var reader = new StreamReader(server);
while (true) {
var line = reader.ReadLine();
if (line?.Length > 0) {
if (OnXXXReceived(line)) {
break;
}
server.Disconnect();
server.WaitForConnection();
}
}
});
new Thread(ts).Start();

View File

@@ -0,0 +1,13 @@
namespace YaeAchievement.Win32;
public static class AllocationType {
public const int Commit = 0x1000;
public const int Reserve = 0x2000;
public const int Decommit = 0x4000;
public const int Release = 0x8000;
public const int Reset = 0x80000;
public const int Physical = 0x400000;
public const int TopDown = 0x100000;
public const int WriteWatch = 0x200000;
public const int LargePages = 0x20000000;
}

View File

@@ -0,0 +1,8 @@
namespace YaeAchievement.Win32;
public static class CreationFlags {
public const int CreateSuspended = 0x00000004;
public const int DetachedProcess = 0x00000008;
public const int CreateNoWindow = 0x08000000;
public const int ExtendedStartupInfoPresent = 0x00080000;
}

15
src/Win32/Extensions.cs Normal file
View File

@@ -0,0 +1,15 @@
using System.ComponentModel;
namespace YaeAchievement.Win32;
public static class Extensions {
public static int PrintMsgAndReturnErrCode(this Win32Exception ex, string msg) {
Console.WriteLine($"{msg}: {ex.Message}");
if (GlobalVars.Verbose) {
Console.WriteLine(ex.StackTrace);
}
return ex.NativeErrorCode;
}
}

View File

@@ -0,0 +1,15 @@
namespace YaeAchievement.Win32;
public static class MemoryProtection {
public const int Execute = 0x10;
public const int ExecuteRead = 0x20;
public const int ExecuteReadWrite = 0x40;
public const int ExecuteWriteCopy = 0x80;
public const int NoAccess = 0x01;
public const int ReadOnly = 0x02;
public const int ReadWrite = 0x04;
public const int WriteCopy = 0x08;
public const int GuardModifierFlag = 0x100;
public const int NoCacheModifierFlag = 0x200;
public const int WriteCombineModifierFlag = 0x400;
}

74
src/Win32/Native.cs Normal file
View File

@@ -0,0 +1,74 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Security;
namespace YaeAchievement.Win32;
[SuppressMessage("Interoperability", "CA1401:P/Invokes 应该是不可见的")]
public static class Native {
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CreateProcess(
string lpApplicationName,
string? lpCommandLine,
ref SecurityAttributes lpProcessAttributes,
ref SecurityAttributes lpThreadAttributes,
bool bInheritHandles,
int dwCreationFlags,
IntPtr lpEnvironment,
string? lpCurrentDirectory,
[In] ref StartupInfo lpStartupInfo,
out ProcessInformation lpProcessInformation
);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
[DllImport("kernel32.dll")]
public static extern bool WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
char[] lpBuffer,
int nSize,
out IntPtr lpNumberOfBytesWritten
);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
[SuppressMessage("Globalization", "CA2101:指定对 P/Invoke 字符串参数进行封送处理")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling=true)]
public static extern IntPtr VirtualAllocEx(
IntPtr hProcess,
IntPtr lpAddress,
int dwSize,
int flAllocationType,
int flProtect
);
[DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)]
public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, int dwFreeType);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint ResumeThread(IntPtr hThread);
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll")]
public static extern IntPtr CreateRemoteThread(
IntPtr hProcess,
IntPtr lpThreadAttributes,
int dwStackSize,
IntPtr lpStartAddress,
IntPtr lpParameter,
uint dwCreationFlags,
out IntPtr lpThreadId
);
}

View File

@@ -0,0 +1,14 @@
using System.Runtime.InteropServices;
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable FieldCanBeMadeReadOnly.Global
namespace YaeAchievement.Win32;
[StructLayout(LayoutKind.Sequential)]
public struct ProcessInformation {
public IntPtr hProcess;
public IntPtr hThread;
public int dwProcessId;
public int dwThreadId;
}

View File

@@ -0,0 +1,12 @@
using System.Runtime.InteropServices;
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable FieldCanBeMadeReadOnly.Global
namespace YaeAchievement.Win32;
[StructLayout(LayoutKind.Sequential)]
public struct SecurityAttributes {
public int nLength;
public IntPtr lpSecurityDescriptor;
}

28
src/Win32/StartupInfo.cs Normal file
View File

@@ -0,0 +1,28 @@
using System.Runtime.InteropServices;
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable FieldCanBeMadeReadOnly.Global
namespace YaeAchievement.Win32;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct StartupInfo {
public int cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public int dwX;
public int dwY;
public int dwXSize;
public int dwYSize;
public int dwXCountChars;
public int dwYCountChars;
public int dwFillAttribute;
public int dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}