Added *some* clipboard commands.

This commit is contained in:
That-One-Nerd 2023-03-28 19:27:44 -04:00
parent b89a076a14
commit ca71367f9c
6 changed files with 172 additions and 1 deletions

View File

@ -8,5 +8,7 @@ global using System.IO;
global using System.IO.Compression;
global using System.Linq;
global using System.Reflection;
global using System.Runtime.InteropServices;
global using System.Text;
global using System.Threading;
global using static SrcMod.Shell.Tools;

View File

@ -0,0 +1,11 @@
namespace SrcMod.Shell.Interop;
internal static partial class Kernel32
{
[LibraryImport("kernel32.dll", SetLastError = true)]
public static partial uint GetFinalPathNameByHandleA(nint hFile, [MarshalAs(UnmanagedType.LPTStr)] string lpszFilePath,
uint cchFilePath, uint dwFlags);
[LibraryImport("kernel32.dll")]
public static partial nuint GlobalSize(nint hPtr);
}

View File

@ -0,0 +1,29 @@
namespace SrcMod.Shell.Interop;
internal static partial class User32
{
[LibraryImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static partial bool CloseClipboard();
[LibraryImport("user32.dll")]
public static partial uint EnumClipboardFormats(uint uFormat);
[LibraryImport("user32.dll")]
public static partial nint GetClipboardData(uint uFormat);
[LibraryImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static partial bool IsClipboardFormatAvailable(uint uFormat);
[LibraryImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static partial bool OpenClipboard(nint hWndNewOwner);
[LibraryImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static partial bool EmptyClipboard();
[LibraryImport("user32.dll")]
public static partial nint SetClipboardData(uint uFormat, nint hMem);
}

View File

@ -0,0 +1,112 @@
using SrcMod.Shell.Interop;
namespace SrcMod.Shell.Modules;
[Module("clipboard")]
public static class ClipboardModule
{
[Command("clear")]
public static void ClearClipboard()
{
if (!ValidateUnsafe()) return;
User32.OpenClipboard(0);
User32.EmptyClipboard();
User32.CloseClipboard();
}
[Command("copy")]
public static void CopyClipboard(string text)
{
const uint format = 1;
if (!ValidateUnsafe()) return;
if (!text.EndsWith("\0")) text += "\0";
byte[] data = Encoding.Default.GetBytes(text);
nint hGlobal = Marshal.AllocHGlobal(data.Length + 1);
Marshal.Copy(data, 0, hGlobal, data.Length);
User32.OpenClipboard(0);
User32.EmptyClipboard();
User32.SetClipboardData(format, hGlobal);
User32.CloseClipboard();
}
[Command("view")]
public static void ViewClipboard()
{
// TODO (maybe): Make this support other formats?
// I spent way too long trying to make that a reality
// but the whole "clipboard format" thing is a nightmare.
if (!ValidateUnsafe()) return;
User32.OpenClipboard(0);
nint hClipboard;
uint format;
if (User32.IsClipboardFormatAvailable(format = (uint)ClipboardFormat.DspText) ||
User32.IsClipboardFormatAvailable(format = (uint)ClipboardFormat.OemText) ||
User32.IsClipboardFormatAvailable(format = (uint)ClipboardFormat.Text) ||
User32.IsClipboardFormatAvailable(format = (uint)ClipboardFormat.UnicodeText))
hClipboard = User32.GetClipboardData(format);
else throw new("Clipboard doesn't contain text data.");
nuint length = Kernel32.GlobalSize(hClipboard);
byte[] data = new byte[length];
Marshal.Copy(hClipboard, data, 0, (int)length);
User32.CloseClipboard();
string msg = (ClipboardFormat)format switch
{
ClipboardFormat.DspText or ClipboardFormat.OemText or ClipboardFormat.Text =>
Encoding.UTF8.GetString(data),
ClipboardFormat.UnicodeText => Encoding.Unicode.GetString(data),
_ => throw new("Unknown text format.")
};
Write(msg);
}
public enum ClipboardFormat
{
Biff5 = 49988,
Biff8 = 49986,
Biff12 = 50009,
Bitmap = 2,
Csv = 49989,
DataObject = 49161,
Dib = 8,
Dif = 5,
DspText = 129,
EmbedSource = 49163,
EnhancedMetafile = 14,
HandleDrop = 15,
HtmlFormat = 49381,
Hyperlink = 50006,
Link = 49985,
LinkSource = 49165,
LinkSourceDescriptor = 49167,
Locale = 16,
Max = 17,
MetafilePicture = 3,
Native = 49156,
ObjectDescriptor = 49166,
ObjectLink = 49154,
OemText = 7,
OlePrivateData = 49171,
OwnerLink = 49155,
Palette = 9,
RichTextFormat = 49308,
SYLK = 4,
Text = 1,
UnicodeText = 13,
XmlSpreadSheet = 50007
}
}

View File

@ -12,6 +12,7 @@
<Authors>That_One_Nerd</Authors>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<ApplicationIcon>Logo.ico</ApplicationIcon>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

View File

@ -1,4 +1,6 @@
namespace SrcMod.Shell;
using System.Text;
namespace SrcMod.Shell;
public static class Tools
{
@ -137,4 +139,18 @@ public static class Tools
Console.ForegroundColor = prevCol;
}
public static bool ValidateUnsafe()
{
Write("You are about to execute an unsafe command.\nProceed? > ", ConsoleColor.DarkYellow, false);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.CursorVisible = true;
string result = Console.ReadLine()!.Trim().ToLower();
Console.CursorVisible = false;
Console.ResetColor();
return result == "y" || result == "yes" || result == "t" ||
result == "true" || result == "p" || result == "proceed";
}
}