diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1ff0c42
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/Bitness/App.config b/Bitness/App.config
new file mode 100644
index 0000000..88fa402
--- /dev/null
+++ b/Bitness/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Bitness/Bitness.csproj b/Bitness/Bitness.csproj
new file mode 100644
index 0000000..be5b3d1
--- /dev/null
+++ b/Bitness/Bitness.csproj
@@ -0,0 +1,60 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {26DC4DFB-F0B0-421A-AAAD-CA225C762AFF}
+ Exe
+ Properties
+ Bitness
+ Bitness
+ v4.5.2
+ 512
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Bitness/Program.cs b/Bitness/Program.cs
new file mode 100644
index 0000000..bdf0979
--- /dev/null
+++ b/Bitness/Program.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Bitness
+{
+ class Program
+ {
+
+ ///
+ /// Source: https://docs.microsoft.com/en-gb/windows/desktop/debug/pe-format
+ ///
+ private static Dictionary MachineType = new Dictionary()
+ {
+ {0x0000, "The contents of this field are assumed to be applicable to any machine type"},
+ {0x01d3, "Matsushita AM33"},
+ {0x8664, "x64"},
+ {0x01c0, "ARM little endian"},
+ {0xaa64, "ARM64 little endian"},
+ {0x01c4, "ARM Thumb-2 little endian"},
+ {0x0ebc, "EFI byte code"},
+ {0x014c, "Intel 386 or later processors and compatible processors"},
+ {0x0200, "Intel Itanium processor family"},
+ {0x9041, "Mitsubishi M32R little endian"},
+ {0x0266, "MIPS16"},
+ {0x0366, "MIPS with FPU"},
+ {0x0466, "MIPS16 with FPU"},
+ {0x01f0, "Power PC little endian"},
+ {0x01f1, "Power PC with floating point support"},
+ {0x0166, "MIPS little endian"},
+ {0x5032, "RISC-V 32-bit address space"},
+ {0x5064, "RISC-V 64-bit address space"},
+ {0x5128, "RISC-V 128-bit address space"},
+ {0x01a2, "Hitachi SH3"},
+ {0x01a3, "Hitachi SH3 DSP"},
+ {0x01a6, "Hitachi SH4"},
+ {0x01a8, "Hitachi SH5"},
+ {0x01c2, "Thumb"},
+ {0x0169, "MIPS little-endian WCE v2"}
+ };
+
+ static void Main(string[] args)
+ {
+ // Initial checks.
+ if (args.Length != 1) { Environment.Exit(0); } // Wrong args (probably none). Just get out of here.
+ if (!File.Exists(args[0])) { Environment.Exit(2); } // File not found
+
+ // File exists. Get PE offset from position 0x3c. FileShare.ReadWrite means we can read the file even if it's in use.
+ var Stream = new FileStream(args[0], FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+ byte[] PeOffset = new byte[2];
+ Stream.Seek(0x3c, SeekOrigin.Begin);
+ Stream.Read(PeOffset, 0, 2);
+
+ // Jump to offset specified in MS-DOS stub and read the PE signature.
+ Stream.Seek(PeOffset[0] | PeOffset[1] << 8, SeekOrigin.Begin);
+ byte[] Values = new byte[4];
+ Stream.Read(Values, 0, 4);
+
+ // For sanity's sake, make sure we've got an actual PE signature - "P E NULL NULL"?
+ if (Values.SequenceEqual(new byte[] { 0x50, 0x45, 0x00, 0x00 }))
+ {
+ // Machine type is the next 2 bytes after the signature.
+ Stream.Read(Values, 0, 2);
+ Int32 TypeId = Values[0] | Values[1] << 8;
+ string TypeName;
+ if (MachineType.TryGetValue(TypeId, out TypeName))
+ {
+ Console.WriteLine("This assembly is compiled for {0}.", TypeName);
+ }
+ else
+ {
+ Console.WriteLine("Machine type could not be determined for this assembly.");
+ }
+ }
+ else
+ {
+ Console.WriteLine("Machine type could not be determined for this assembly.");
+ }
+ Console.WriteLine("Press any key to exit.");
+ Console.ReadKey();
+ }
+ }
+}
diff --git a/Bitness/Properties/AssemblyInfo.cs b/Bitness/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..d196f59
--- /dev/null
+++ b/Bitness/Properties/AssemblyInfo.cs
@@ -0,0 +1,25 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Bitness")]
+[assembly: AssemblyDescription("Determine machine type for a Windows assembly.")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Bitness")]
+[assembly: AssemblyCopyright("Copyright © 2019 Daniel Price and contributors")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("26dc4dfb-f0b0-421a-aaad-ca225c762aff")]
+
+[assembly: AssemblyVersion("1.0.*")]
diff --git a/MouseSpeed/App.config b/MouseSpeed/App.config
new file mode 100644
index 0000000..72a71af
--- /dev/null
+++ b/MouseSpeed/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/MouseSpeed/MouseOptions.cs b/MouseSpeed/MouseOptions.cs
new file mode 100644
index 0000000..737316f
--- /dev/null
+++ b/MouseSpeed/MouseOptions.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace MouseSpeed
+{
+ public class MouseOptions
+ {
+
+ ///
+ /// Use System Parameters Info from User32 to get the current mouse speed.
+ ///
+ /// Current mouse speed.
+ public static int GetMouseSpeed()
+ {
+ IntPtr Ptr;
+ Ptr = Marshal.AllocCoTaskMem(4);
+ SPI.SystemParametersInfo(SPI.SPI_GETMOUSESPEED, 0, Ptr, 0);
+ int Speed = Marshal.ReadInt32(Ptr);
+ Marshal.FreeCoTaskMem(Ptr);
+
+ return Speed;
+ }
+
+ ///
+ /// Use System Parameters Info to set the mouse speed to a new value.
+ ///
+ /// Value to set the mouse speed to. Accepts integers from 1 to 20.
+ /// True if speed was changed successfully.
+ public static bool SetMouseSpeed(int speed)
+ {
+ // Range of values allowed by Windows is 1 to 20.
+ if (speed < 1 || speed > 20)
+ {
+ throw new ArgumentOutOfRangeException("Valid speeds are integer values from 1 to 20.");
+ }
+
+ IntPtr ptr = new IntPtr(speed);
+ return SPI.SystemParametersInfo(SPI.SPI_SETMOUSESPEED, 0, ptr, SPI.SPIF_SENDWININICHANGE);
+ }
+ }
+}
+
diff --git a/MouseSpeed/MouseSpeed.csproj b/MouseSpeed/MouseSpeed.csproj
new file mode 100644
index 0000000..194064c
--- /dev/null
+++ b/MouseSpeed/MouseSpeed.csproj
@@ -0,0 +1,49 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {AC97B715-0D18-4C7E-A991-1F53C2CDF921}
+ Exe
+ MouseSpeed
+ MouseSpeed
+ v4.0
+ 512
+ true
+ false
+
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ true
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MouseSpeed/Program.cs b/MouseSpeed/Program.cs
new file mode 100644
index 0000000..350cab3
--- /dev/null
+++ b/MouseSpeed/Program.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace MouseSpeed
+{
+ partial class Program
+ {
+ static unsafe void Main(string[] args)
+ {
+ int NewSpeed;
+
+ // A single cmd line argument? Set speed and exit if it's an integer.
+ if (args.Length == 1 && int.TryParse(args[0], out NewSpeed))
+ {
+ if (MouseOptions.SetMouseSpeed(NewSpeed))
+ {
+ Console.WriteLine("Mouse speed changed to {0}", NewSpeed);
+ Environment.Exit(0);
+ }
+ }
+
+ // Otherwise, tell the user the existing speed and prompt for a new one.
+ Console.WriteLine("Mouse speed is currently set to {0}.", MouseOptions.GetMouseSpeed());
+ Console.WriteLine("Enter a new speed [1..20] to set the speed, or any other value to exit.");
+ string Entry = Console.ReadLine();
+ if (int.TryParse(Entry, out NewSpeed))
+ {
+ if (NewSpeed > 0 && NewSpeed < 21)
+ {
+ bool Success = MouseOptions.SetMouseSpeed(NewSpeed);
+ if (Success)
+ {
+ Console.WriteLine("Speed changed to {0}", NewSpeed);
+ }
+ else
+ {
+ Console.WriteLine("Unable to set speed.");
+ }
+ Console.WriteLine("Press any key to exit.");
+ Console.ReadKey();
+ }
+ }
+ }
+ }
+}
diff --git a/MouseSpeed/Properties/AssemblyInfo.cs b/MouseSpeed/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ba209ad
--- /dev/null
+++ b/MouseSpeed/Properties/AssemblyInfo.cs
@@ -0,0 +1,29 @@
+using System.Resources;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("MouseSpeed")]
+[assembly: AssemblyDescription("Change Windows' mouse speed quickly from the console.")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MouseSpeed")]
+[assembly: AssemblyCopyright("Copyright © 2019 Daniel Price & contributors")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("ac97b715-0d18-4c7e-a991-1f53c2cdf921")]
+
+ [assembly: AssemblyVersion("1.0.*")]
+[assembly: NeutralResourcesLanguage("en-GB")]
+
diff --git a/MouseSpeed/SPI.cs b/MouseSpeed/SPI.cs
new file mode 100644
index 0000000..f02478f
--- /dev/null
+++ b/MouseSpeed/SPI.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace MouseSpeed
+{
+ ///
+ /// References the SystemParametersInfo method from WinUser.
+ /// More details at https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-systemparametersinfoa
+ ///
+ internal class SPI
+ {
+ public const uint SPI_GETMOUSESPEED = 0x0070;
+ public const uint SPI_SETMOUSESPEED = 0x0071;
+ public const uint SPIF_UPDATEINIFILE = 0x01;
+ public const uint SPIF_SENDWININICHANGE = 0x02;
+
+ ///
+ /// Retrieves or sets the value of one of the system-wide parameters. This function can also update the user profile while setting a parameter.
+ ///
+ /// The system-wide parameter to be retrieved or set. The possible values are organized in a table at the above URI
+ /// Usage depends on which parameter value is set in . For this app, we leave it at 0.
+ /// Usage depends on which parameter value is set in . For this app, we reference it to an IntPtr to get/set the mouse speed.
+ /// If a system parameter is being set, specifies whether the user profile is to be updated,
+ /// and if so, whether the WM_SETTINGCHANGE message is to be broadcast to all top-level windows to notify them of the change. For this app we leave it at
+ /// If the function succeeds, the return value is a nonzero value. If the function fails, the return value is zero.To get extended error information, call GetLastError.
+ [DllImport("User32.dll")]
+ public static extern bool SystemParametersInfo(UInt32 uiAction, UInt32 uiParam, IntPtr pvParam, UInt32 fWinIni);
+ }
+}
diff --git a/README.md b/README.md
index 3058b2a..9b2a25b 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,17 @@
# TinyUtils
A collection of tiny Windows utilities.
+
+## Bitness
+Reads the PE and COFF headers of an assembly to find the machine type it was compiled for.
+
+#### Usage
+`Bitness [path to assembly]` will output the machine type.
+
+## MouseSpeed
+Get and/or set Windows' mouse speed from the command line.
+
+#### Usage
+`MouseSpeed` - enter interactive mode. Tells you the current mouse speed and prompts for a new one.
+
+`MouseSpeed [speed]` - set the mouse speed to `[speed]` directly.
+
diff --git a/TinyUtils.sln b/TinyUtils.sln
new file mode 100644
index 0000000..e191962
--- /dev/null
+++ b/TinyUtils.sln
@@ -0,0 +1,34 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bitness", "Bitness\Bitness.csproj", "{26DC4DFB-F0B0-421A-AAAD-CA225C762AFF}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{29101AF1-0ACE-48E2-9807-7367C7BDBF3D}"
+ ProjectSection(SolutionItems) = preProject
+ LICENSE = LICENSE
+ README.md = README.md
+ EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MouseSpeed", "MouseSpeed\MouseSpeed.csproj", "{AC97B715-0D18-4C7E-A991-1F53C2CDF921}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {26DC4DFB-F0B0-421A-AAAD-CA225C762AFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {26DC4DFB-F0B0-421A-AAAD-CA225C762AFF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {26DC4DFB-F0B0-421A-AAAD-CA225C762AFF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {26DC4DFB-F0B0-421A-AAAD-CA225C762AFF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AC97B715-0D18-4C7E-A991-1F53C2CDF921}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AC97B715-0D18-4C7E-A991-1F53C2CDF921}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AC97B715-0D18-4C7E-A991-1F53C2CDF921}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AC97B715-0D18-4C7E-A991-1F53C2CDF921}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal