M InjectedLib/dllmain.cpp => InjectedLib/dllmain.cpp +0 -7
@@ 43,7 43,6 @@ static std::wstring inject_asm_path(void)
static void load_managed_assembly(void)
{
ICLRMetaHost *rt_meta = nullptr;
- IEnumUnknown *rt_itr = nullptr;
IUnknown *rt_variant = nullptr;
ICLRRuntimeInfo *rt_info = nullptr;
HRESULT hr;
@@ 53,12 52,6 @@ static void load_managed_assembly(void)
show_err(L"Failed to create instance of runtime meta host.", hr);
return;
}
-
- hr = rt_meta->EnumerateInstalledRuntimes(&rt_itr);
- if (FAILED(hr)) {
- show_err(L"Failed to enumerate installed runtimes.", hr);
- return;
- }
hr = rt_meta->GetRuntime(L"v4.0.30319", IID_PPV_ARGS(&rt_info));
if (FAILED(hr)) {
A InjectedManagedAssembly/BoardState.cs => InjectedManagedAssembly/BoardState.cs +68 -0
@@ 0,0 1,68 @@
+using System.Collections.Generic;
+using System.ComponentModel;
+
+namespace SolitaireOracle
+{
+ /* The associated values are consistent with the game. */
+ public enum Suit : int
+ {
+ [Description("S")]
+ Sword = 0,
+
+ [Description("C")]
+ Cup = 1,
+
+ [Description("T")]
+ Star = 2,
+
+ [Description("W")]
+ Wand = 3,
+
+ [Description("M")]
+ Major = 4,
+ }
+
+ public struct Card
+ {
+ public Suit Suit { get; }
+ public int Value { get; }
+
+ public Card(Suit suit, int value)
+ {
+ Suit = suit;
+ Value = value;
+ }
+
+ public override string ToString()
+ {
+ return Suit.ToString() + Value;
+ }
+ }
+
+ public struct BoardState
+ {
+ public List<List<Card>> TableauCells { get; }
+ public List<List<Card>> MinorFoundationCells { get; }
+ public List<Card> LowerMajorFoundationCell { get; }
+ public List<Card> UpperMajorFoundationCell { get; }
+ public List<Card> FinalMajorFoundationCell { get; }
+ public Card? FreeCell { get; }
+
+ public BoardState(
+ List<List<Card>> tableauCells,
+ List<List<Card>> minorFoundationCells,
+ List<Card> lowerMajorFoundationCell,
+ List<Card> upperMajorFoundationCell,
+ List<Card> finalMajorFoundationCell,
+ Card? freeCell
+ )
+ {
+ TableauCells = tableauCells;
+ MinorFoundationCells = minorFoundationCells;
+ LowerMajorFoundationCell = lowerMajorFoundationCell;
+ UpperMajorFoundationCell = upperMajorFoundationCell;
+ FinalMajorFoundationCell = finalMajorFoundationCell;
+ FreeCell = freeCell;
+ }
+ }
+}
A InjectedManagedAssembly/GameState.cs => InjectedManagedAssembly/GameState.cs +115 -0
@@ 0,0 1,115 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace SolitaireOracle
+{
+ public class MilanScreenNotVisibleException : Exception
+ {
+ public MilanScreenNotVisibleException() : base(
+ "The \"Fortune's Foundation\" game screen is not active."
+ )
+ { }
+ }
+
+ public class GameState
+ {
+ private Assembly _assembly;
+ private Type _screenStackType;
+ private Type _gameScreenType;
+ private Type _unknownControllerType;
+ private Type _boardStateType;
+ private Type _solitaireItemType;
+
+ public GameState(Assembly assembly)
+ {
+ this._assembly = assembly;
+ this._screenStackType = assembly.GetType("ScreenStack");
+ this._gameScreenType = assembly.GetType("Milan.GameScreen");
+ this._unknownControllerType = assembly.GetType("#=q0pk7ja$d6EGfjmD$pwqkUf_tDQr2NjwNEBTC6S3S6pw=");
+ this._boardStateType = assembly.GetType("Milan.BoardState");
+ this._solitaireItemType = assembly.GetType("Milan.SolitaireItem");
+ }
+
+ public BoardState BoardState
+ {
+ get
+ {
+ InternalBoardState internalState = InternalBoardState;
+
+ List<List<Card>> tableauCells = new List<List<Card>>();
+ List<InternalSolitaireItem> internalTableauCells = internalState.TableauCells;
+ foreach (InternalSolitaireItem item in internalTableauCells)
+ {
+ tableauCells.Add(item.Cards);
+ }
+
+ List<List<Card>> minorFoundationCells = new List<List<Card>>();
+ List<InternalSolitaireItem> internalMinorFoundationCells = internalState.MinorFoundationCells;
+ foreach (InternalSolitaireItem item in internalMinorFoundationCells)
+ {
+ minorFoundationCells.Add(item.Cards);
+ }
+
+ List<Card> lowerMajorFoundationCell = internalState.LowerMajorFoundationCell.Cards;
+ List<Card> upperMajorFoundationCell = internalState.UpperMajorFoundationCell.Cards;
+ List<Card> finalMajorFoundationCell = internalState.FinalMajorFoundationCell.Cards;
+
+ InternalSolitaireItem freeCellItem = internalState.FreeCell;
+ Card? freeCell = null;
+ if (freeCellItem.Cards.Count > 0)
+ {
+ freeCell = freeCellItem.Cards[0];
+ }
+
+ return new BoardState(
+ tableauCells,
+ minorFoundationCells,
+ lowerMajorFoundationCell,
+ upperMajorFoundationCell,
+ finalMajorFoundationCell,
+ freeCell
+ );
+ }
+ }
+
+ private IList ScreenStack
+ {
+ get
+ {
+ MethodInfo getScreensMethod = _screenStackType.GetMethod("#=qwDu4tl5WqE$CaaOI6JbyYOihTs6X_cSn8YUJgM$9Kpc=", BindingFlags.Public | BindingFlags.Static);
+ return getScreensMethod.Invoke(null, null) as IList;
+ }
+ }
+
+ private object MilanGameScreen
+ {
+ get
+ {
+ IList screens = this.ScreenStack;
+ object topScreen = screens.Count > 0 ? screens[0] : null;
+
+ if (topScreen == null || topScreen.GetType() != this._gameScreenType)
+ {
+ throw new MilanScreenNotVisibleException();
+ }
+
+ return topScreen;
+ }
+ }
+
+ private InternalBoardState InternalBoardState
+ {
+ get
+ {
+ object gameScreen = MilanGameScreen;
+ MethodInfo getControllerMethod = this._gameScreenType.GetMethod("#=qt9YAlgdQ0iozKkKJ_tz6wg==", BindingFlags.NonPublic | BindingFlags.Instance);
+ object controller = getControllerMethod.Invoke(gameScreen, null);
+
+ FieldInfo boardStateField = this._unknownControllerType.GetField("#=qggOaeeswRk1DSyXZZarAEQ==", BindingFlags.Public | BindingFlags.Instance);
+ return new InternalBoardState(boardStateField.GetValue(controller), _boardStateType, _solitaireItemType);
+ }
+ }
+ }
+}
M InjectedManagedAssembly/InjectedManagedAssembly.csproj => InjectedManagedAssembly/InjectedManagedAssembly.csproj +3 -0
@@ 45,6 45,9 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="BoardState.cs" />
+ <Compile Include="GameState.cs" />
+ <Compile Include="InternalBoardState.cs" />
<Compile Include="Main.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
A InjectedManagedAssembly/InternalBoardState.cs => InjectedManagedAssembly/InternalBoardState.cs +135 -0
@@ 0,0 1,135 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace SolitaireOracle
+{
+ public class InternalSolitaireItem
+ {
+ private object _internalState;
+ private Type _type;
+
+ public InternalSolitaireItem(object internalState, Type type)
+ {
+ _internalState = internalState;
+ _type = type;
+ }
+
+ public List<Card> Cards
+ {
+ get
+ {
+ MethodInfo getIteratorMethod = _type.GetMethod("#=q3T5hVjfGdlmlcVuQneFNdGZgSGtulISaq7a1odM4P8Q=", BindingFlags.Public | BindingFlags.Instance);
+ IEnumerable iterator = getIteratorMethod.Invoke(_internalState, null) as IEnumerable;
+ List<Card> result = new List<Card>();
+
+ foreach (object itemObj in iterator)
+ {
+ InternalSolitaireItem item = new InternalSolitaireItem(itemObj, _type);
+ Card card = new Card(item.CardSuit, item.CardValue);
+ result.Add(card);
+ }
+
+ return result;
+ }
+ }
+
+ private Suit CardSuit
+ {
+ get
+ {
+ FieldInfo field = _type.GetField("#=qrVeI19YFRrL$TYnUhjJkGg==", BindingFlags.Public | BindingFlags.Instance);
+ return (Suit)field.GetValue(_internalState);
+ }
+ }
+
+ private int CardValue
+ {
+ get
+ {
+ FieldInfo field = _type.GetField("#=qGa_rTwBFoHeQRSVVfaUd_Q==", BindingFlags.Public | BindingFlags.Instance);
+ return (int)field.GetValue(_internalState);
+ }
+ }
+ }
+
+ public class InternalBoardState
+ {
+ private object _internalState;
+ private Type _boardType;
+ private Type _itemType;
+
+ public InternalBoardState(object internalState, Type boardType, Type itemType)
+ {
+ _internalState = internalState;
+ _boardType = boardType;
+ _itemType = itemType;
+ }
+
+ public List<InternalSolitaireItem> TableauCells
+ {
+ get
+ {
+ FieldInfo field = _boardType.GetField("#=qzsOQ0cf1yO$i8Y9aA3nQSA==", BindingFlags.Public | BindingFlags.Instance);
+ return GetCells(field.GetValue(_internalState) as IList);
+ }
+ }
+
+ public List<InternalSolitaireItem> MinorFoundationCells
+ {
+ get
+ {
+ FieldInfo field = _boardType.GetField("#=qiTVSpq2PBgg8V050hDJn5oQb0VXwpTjrAZwWKRXR8hs=", BindingFlags.Public | BindingFlags.Instance);
+ return GetCells(field.GetValue(_internalState) as IList);
+ }
+ }
+
+ public InternalSolitaireItem LowerMajorFoundationCell
+ {
+ get
+ {
+ FieldInfo field = _boardType.GetField("#=qXTqemQdLoqSMR1UppWwmcud0M0zWMkRPfKUp$A23pQE=", BindingFlags.Public | BindingFlags.Instance);
+ return new InternalSolitaireItem(field.GetValue(_internalState), _itemType);
+ }
+ }
+
+ public InternalSolitaireItem UpperMajorFoundationCell
+ {
+ get
+ {
+ FieldInfo field = _boardType.GetField("#=qULFxwKOM5DOP9orpqK5SDiQQQPfH6OfkOPzcjwx4pdY=", BindingFlags.Public | BindingFlags.Instance);
+ return new InternalSolitaireItem(field.GetValue(_internalState), _itemType);
+ }
+ }
+
+ public InternalSolitaireItem FinalMajorFoundationCell
+ {
+ get
+ {
+ FieldInfo field = _boardType.GetField("#=q68Ek4QcjyWoJ0OYSV2IVI2L7fgwXBz$QyDNQuIS9AM0=", BindingFlags.Public | BindingFlags.Instance);
+ return new InternalSolitaireItem(field.GetValue(_internalState), _itemType);
+ }
+ }
+
+ public InternalSolitaireItem FreeCell
+ {
+ get
+ {
+ FieldInfo field = _boardType.GetField("#=qfmGFvCGS9zpXaXWksXqNSQ==", BindingFlags.Public | BindingFlags.Instance);
+ return new InternalSolitaireItem(field.GetValue(_internalState), _itemType);
+ }
+ }
+
+ private List<InternalSolitaireItem> GetCells(IList items)
+ {
+ List<InternalSolitaireItem> cells = new List<InternalSolitaireItem>();
+ foreach (object item in items)
+ {
+ cells.Add(new InternalSolitaireItem(item, _itemType));
+ }
+
+ return cells;
+ }
+ }
+}
M InjectedManagedAssembly/Main.cs => InjectedManagedAssembly/Main.cs +55 -88
@@ 1,6 1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
+using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
@@ 13,108 14,74 @@ namespace SolitaireOracle
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool AllocConsole();
- private static readonly Assembly GameAssembly = Assembly.GetEntryAssembly();
-
public static int Initialize(String arg)
{
AllocConsole();
Console.WriteLine("injection assembly initialized");
- IList tableauCells = GetTableauCells();
- foreach (object cell in tableauCells) {
- foreach (object card in GetCellIterator(cell)) {
- Console.WriteLine("suite = {0}, value = {1}", GetCardSuit(card), GetCardValue(card));
+ try
+ {
+ GameState gameState = new GameState(Assembly.GetEntryAssembly());
+ BoardState boardState = gameState.BoardState;
+
+ Console.WriteLine("tableau =");
+ foreach (List<Card> cell in boardState.TableauCells)
+ {
+ foreach (Card card in cell)
+ {
+ Console.WriteLine(card.ToString());
+ }
+ Console.WriteLine("================================");
+ Console.WriteLine("");
}
- Console.WriteLine("================================");
- Console.WriteLine("");
- }
-
- return 1337;
- }
-
- public static object GetGameLogic()
- {
- Type gameLogicT = GameAssembly.GetType("GameLogic");
- FieldInfo instanceField = gameLogicT.GetField("#=qScrhqyNr4nqz94n2Zvdliw==", BindingFlags.Public | BindingFlags.Static);
- return instanceField.GetValue(gameLogicT);
- }
-
- public static IList GetScreenStack()
- {
- Type screenStackT = GameAssembly.GetType("ScreenStack");
- MethodInfo getScreensMethod = screenStackT.GetMethod("#=qwDu4tl5WqE$CaaOI6JbyYOihTs6X_cSn8YUJgM$9Kpc=", BindingFlags.Public | BindingFlags.Static);
- return getScreensMethod.Invoke(null, null) as IList;
- }
-
- public static object GetMilanGameScreen()
- {
- Type milanGameScreenType = GameAssembly.GetType("Milan.GameScreen");
- IList screens = GetScreenStack();
- object topScreen = screens.Count > 0 ? screens[0] : null;
-
- if (topScreen == null || topScreen.GetType() != milanGameScreenType) {
- MessageBox.Show("\"Fortune's Foundation\" game screen is not visible.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
- }
+ Console.WriteLine("minor foundation =");
+ foreach (List<Card> cell in boardState.MinorFoundationCells)
+ {
+ foreach (Card card in cell)
+ {
+ Console.WriteLine(card.ToString());
+ }
+ Console.WriteLine("================================");
+ Console.WriteLine("");
+ }
- return topScreen;
- }
+ Console.WriteLine("lower major foundation =");
+ foreach (Card card in boardState.LowerMajorFoundationCell)
+ {
+ Console.WriteLine(card.ToString());
+ }
+ Console.WriteLine("");
- public static object GetUnknownController()
- {
- object gameScreen = GetMilanGameScreen();
- if (gameScreen == null) {
- return null;
- }
+ Console.WriteLine("upper major foundation =");
+ foreach (Card card in boardState.UpperMajorFoundationCell)
+ {
+ Console.WriteLine(card.ToString());
+ }
+ Console.WriteLine("");
- Type milanGameScreenType = GameAssembly.GetType("Milan.GameScreen");
- MethodInfo getControllerMethod = milanGameScreenType.GetMethod("#=qt9YAlgdQ0iozKkKJ_tz6wg==", BindingFlags.NonPublic | BindingFlags.Instance);
- return getControllerMethod.Invoke(gameScreen, null);
- }
+ Console.WriteLine("final major foundation =");
+ foreach (Card card in boardState.FinalMajorFoundationCell)
+ {
+ Console.WriteLine(card.ToString());
+ }
+ Console.WriteLine("");
- public static object GetBoardState()
- {
- object controller = GetUnknownController();
- if (controller == null) {
- return null;
+ if (boardState.FreeCell is Card freeCell)
+ {
+ Console.WriteLine("free cell = {0}", freeCell.ToString());
+ }
+ else
+ {
+ Console.WriteLine("<nothing in free cell>");
+ }
}
-
- Type controllerType = GameAssembly.GetType("#=q0pk7ja$d6EGfjmD$pwqkUf_tDQr2NjwNEBTC6S3S6pw=");
- FieldInfo boardStateField = controllerType.GetField("#=qggOaeeswRk1DSyXZZarAEQ==", BindingFlags.Public | BindingFlags.Instance);
- return boardStateField.GetValue(controller);
- }
-
- public static IList GetTableauCells()
- {
- object boardState = GetBoardState();
- if (boardState == null) {
- return new List<object>();
+ catch (MilanScreenNotVisibleException e)
+ {
+ MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
- Type boardStateType = GameAssembly.GetType("Milan.BoardState");
- FieldInfo tableauItemsField = boardStateType.GetField("#=qzsOQ0cf1yO$i8Y9aA3nQSA==", BindingFlags.Public | BindingFlags.Instance);
- return tableauItemsField.GetValue(boardState) as IList;
- }
-
- public static IEnumerable GetCellIterator(object item)
- {
- Type itemType = GameAssembly.GetType("Milan.SolitaireItem");
- MethodInfo getIteratorMethod = itemType.GetMethod("#=q3T5hVjfGdlmlcVuQneFNdGZgSGtulISaq7a1odM4P8Q=", BindingFlags.Public | BindingFlags.Instance);
- return getIteratorMethod.Invoke(item, null) as IEnumerable;
- }
-
- public static int GetCardSuit(object item)
- {
- Type itemType = GameAssembly.GetType("Milan.SolitaireItem");
- FieldInfo field = itemType.GetField("#=qrVeI19YFRrL$TYnUhjJkGg==", BindingFlags.Public | BindingFlags.Instance);
- return (int) field.GetValue(item);
- }
-
- public static int GetCardValue(object item)
- {
- Type itemType = GameAssembly.GetType("Milan.SolitaireItem");
- FieldInfo field = itemType.GetField("#=qGa_rTwBFoHeQRSVVfaUd_Q==", BindingFlags.Public | BindingFlags.Instance);
- return (int)field.GetValue(item);
+ return 1337;
}
}
}