Skip to content

Commit c758f66

Browse files
Mark Dietzerbenpye
authored andcommitted
Refactor code structure to split up files
1 parent f1bdb88 commit c758f66

File tree

6 files changed

+465
-321
lines changed

6 files changed

+465
-321
lines changed

PageantHandler.cs

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
using System.Text;
4+
5+
namespace WslSSHPageant
6+
{
7+
public class PageantException : Exception
8+
{
9+
internal PageantException(string message) : base(message)
10+
{
11+
}
12+
}
13+
14+
static class PageantHandler
15+
{
16+
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
17+
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
18+
19+
[DllImport("kernel32.dll")]
20+
static extern uint GetCurrentThreadId();
21+
22+
[DllImport("kernel32.dll", SetLastError = true)]
23+
public static extern IntPtr CreateFileMapping(
24+
IntPtr hFile,
25+
IntPtr lpFileMappingAttributes,
26+
FileMapProtection flProtect,
27+
uint dwMaximumSizeHigh,
28+
uint dwMaximumSizeLow,
29+
string lpName);
30+
31+
[Flags]
32+
public enum FileMapProtection : uint
33+
{
34+
PageReadonly = 0x02,
35+
PageReadWrite = 0x04,
36+
PageWriteCopy = 0x08,
37+
PageExecuteRead = 0x20,
38+
PageExecuteReadWrite = 0x40,
39+
SectionCommit = 0x8000000,
40+
SectionImage = 0x1000000,
41+
SectionNoCache = 0x10000000,
42+
SectionReserve = 0x4000000,
43+
}
44+
45+
static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
46+
47+
[DllImport("kernel32.dll", SetLastError = true)]
48+
static extern IntPtr MapViewOfFile(
49+
IntPtr hFileMappingObject,
50+
FileMapAccess dwDesiredAccess,
51+
UInt32 dwFileOffsetHigh,
52+
UInt32 dwFileOffsetLow,
53+
UIntPtr dwNumberOfBytesToMap);
54+
55+
[Flags]
56+
public enum FileMapAccess : uint
57+
{
58+
FileMapCopy = 0x0001,
59+
FileMapWrite = 0x0002,
60+
FileMapRead = 0x0004,
61+
FileMapAllAccess = 0x001f,
62+
FileMapExecute = 0x0020,
63+
}
64+
65+
[DllImport("user32.dll")]
66+
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
67+
68+
[StructLayout(LayoutKind.Sequential)]
69+
struct COPYDATASTRUCT
70+
{
71+
public IntPtr dwData; // Any value the sender chooses. Perhaps its main window handle?
72+
public int cbData; // The count of bytes in the message.
73+
public IntPtr lpData; // The address of the message.
74+
}
75+
76+
const int WM_COPYDATA = 0x004A;
77+
78+
[DllImport("kernel32.dll", SetLastError = true)]
79+
static extern bool UnmapViewOfFile(IntPtr lpBaseAddress);
80+
81+
[DllImport("kernel32.dll", SetLastError = true)]
82+
static extern bool CloseHandle(IntPtr hHandle);
83+
84+
internal const uint AGENT_MAX_MSGLEN = 8192;
85+
static readonly IntPtr AGENT_COPYDATA_ID = new IntPtr(0x804e50ba);
86+
87+
// Send ssh-agent query to Pageant, ssh-agent and Pageant use same messages
88+
internal static byte[] Query(ArraySegment<byte> buf)
89+
{
90+
var hwnd = FindWindowByCaption(IntPtr.Zero, "Pageant");
91+
if (hwnd == IntPtr.Zero)
92+
{
93+
throw new PageantException("HWND not found");
94+
}
95+
96+
var mapName = String.Format("PageantRequest{0:x8}", GetCurrentThreadId());
97+
var fileMap = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, FileMapProtection.PageReadWrite, 0, AGENT_MAX_MSGLEN, mapName);
98+
var sharedMemory = MapViewOfFile(fileMap, FileMapAccess.FileMapWrite, 0, 0, UIntPtr.Zero);
99+
Marshal.Copy(buf.Array, buf.Offset, sharedMemory, buf.Count);
100+
101+
var mapNameBytes = Encoding.UTF8.GetBytes(mapName + '\0');
102+
var gch = GCHandle.Alloc(mapNameBytes);
103+
104+
var cds = new COPYDATASTRUCT();
105+
cds.dwData = AGENT_COPYDATA_ID;
106+
cds.cbData = mapNameBytes.Length;
107+
cds.lpData = Marshal.UnsafeAddrOfPinnedArrayElement(mapNameBytes, 0);
108+
109+
var data = Marshal.AllocHGlobal(Marshal.SizeOf(cds));
110+
Marshal.StructureToPtr(cds, data, false);
111+
var rcode = SendMessage(hwnd, WM_COPYDATA, IntPtr.Zero, data);
112+
if (rcode == IntPtr.Zero)
113+
{
114+
throw new PageantException("WM_COPYDATA failed");
115+
}
116+
117+
var len = (Marshal.ReadByte(sharedMemory, 0) << 24) |
118+
(Marshal.ReadByte(sharedMemory, 1) << 16) |
119+
(Marshal.ReadByte(sharedMemory, 2) << 8) |
120+
(Marshal.ReadByte(sharedMemory, 3));
121+
122+
len += 4;
123+
if (len > AGENT_MAX_MSGLEN)
124+
{
125+
throw new PageantException("Message too long");
126+
}
127+
128+
var ret = new byte[len];
129+
Marshal.Copy(sharedMemory, ret, 0, len);
130+
131+
UnmapViewOfFile(sharedMemory);
132+
CloseHandle(fileMap);
133+
134+
return ret;
135+
}
136+
}
137+
}

0 commit comments

Comments
 (0)