-
Notifications
You must be signed in to change notification settings - Fork 3
/
WarbandLoader.cs
137 lines (116 loc) · 4.55 KB
/
WarbandLoader.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
using System;
using System.Runtime.InteropServices;
using System.Windows;
namespace Launcher
{
public sealed unsafe class WarbandLoader : LoaderBase
{
// ReSharper disable MemberCanBePrivate.Local
// ReSharper disable FieldCanBeMadeReadOnly.Local
// ReSharper disable InconsistentNaming
private const uint LMEM_FIXED = 0;
private const uint HIGH_PRIORITY_CLASS = 128;
private const uint INFINITE = 0xFFFFFFFFu;
[DllImport("Kernel32.dll")]
private static extern IntPtr LocalAlloc(
uint uFlags,
UIntPtr uBytes
);
[DllImport("Kernel32.dll", SetLastError = true)]
private static extern IntPtr LocalFree(
IntPtr hMem
);
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode, EntryPoint = "GetModuleHandleW")]
private static extern IntPtr GetModuleHandle(
IntPtr lpModuleName
);
[DllImport("Kernel32.dll", CharSet = CharSet.Unicode, EntryPoint = "GetModuleFileNameW")]
private static extern uint GetModuleFileName(
IntPtr hModule,
char* lpFilename,
uint nSize
);
[DllImport("Shlwapi.dll", CharSet = CharSet.Unicode, EntryPoint = "PathRemoveFileSpecW")]
private static extern bool PathRemoveFileSpec(
char* pszPath
);
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "CreateProcessW")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CreateProcess(
string lpApplicationName,
IntPtr lpCommandLine,
IntPtr lpProcessAttributes,
IntPtr lpThreadAttributes,
[MarshalAs(UnmanagedType.Bool)]bool bInheritHandles,
uint dwCreationFlags,
IntPtr lpEnvironment,
IntPtr lpCurrentDirectory,
[In] ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation
);
[DllImport("User32.dll")]
private static extern uint WaitForInputIdle(
IntPtr hProcess,
uint dwMilliseconds
);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct STARTUPINFO
{
public uint cb;
public string lpReserved;
public string lpDesktop;
public string lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
private struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
// ReSharper restore MemberCanBePrivate.Local
// ReSharper restore FieldCanBeMadeReadOnly.Local
// ReSharper restore InconsistentNaming
public override void LoadGame()
{
SetActiveMod("Native");
var szPath = (char*)LocalAlloc(LMEM_FIXED, (UIntPtr)1024u);
GetModuleFileName(GetModuleHandle(IntPtr.Zero), szPath, 1024u);
PathRemoveFileSpec(szPath);
var pathToExe = new string(szPath);
var warbandPath = FindWarbandPath(pathToExe, out var warbandFound);
if (!warbandFound)
{
MessageBox.Show("Could not find mb_warband.exe");
goto clear_mem;
}
var si = new STARTUPINFO();
var created = CreateProcess(warbandPath, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, false, HIGH_PRIORITY_CLASS, IntPtr.Zero,
IntPtr.Zero, ref si, out var pi);
if (!created)
{
MessageBox.Show("CreateProcess failed " + Marshal.GetLastWin32Error());
goto clear_mem;
}
WaitForInputIdle(pi.hProcess, INFINITE);
PushPlayButton();
clear_mem:
LocalFree((IntPtr)szPath);
}
}
}