Skip to content

Commit 04c9ec0

Browse files
gave92Marco Gavelli
authored andcommitted
Switch to CsWin32 for process api
1 parent 7c520c5 commit 04c9ec0

File tree

3 files changed

+93
-154
lines changed

3 files changed

+93
-154
lines changed

src/Files.App/Utils/Terminal/ConPTY/Native/ProcessApi.cs

Lines changed: 0 additions & 86 deletions
This file was deleted.

src/Files.App/Utils/Terminal/ConPTY/Processes/Process.cs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Runtime.InteropServices;
3-
using static Files.App.Utils.Terminal.ConPTY.ProcessApi;
3+
using Windows.Win32;
4+
using Windows.Win32.System.Threading;
45

56
namespace Files.App.Utils.Terminal.ConPTY
67
{
@@ -9,13 +10,13 @@ namespace Files.App.Utils.Terminal.ConPTY
910
/// </summary>
1011
internal sealed class Process : IDisposable
1112
{
12-
public Process(STARTUPINFOEX startupInfo, PROCESS_INFORMATION processInfo)
13+
public Process(STARTUPINFOEXW startupInfo, PROCESS_INFORMATION processInfo)
1314
{
1415
StartupInfo = startupInfo;
1516
ProcessInfo = processInfo;
1617
}
1718

18-
public STARTUPINFOEX StartupInfo { get; }
19+
public STARTUPINFOEXW StartupInfo { get; }
1920
public PROCESS_INFORMATION ProcessInfo { get; }
2021

2122
#region IDisposable Support
@@ -34,20 +35,23 @@ void Dispose(bool disposing)
3435
// dispose unmanaged state
3536

3637
// Free the attribute list
37-
if (StartupInfo.lpAttributeList != nint.Zero)
38+
unsafe
3839
{
39-
DeleteProcThreadAttributeList(StartupInfo.lpAttributeList);
40-
Marshal.FreeHGlobal(StartupInfo.lpAttributeList);
40+
if ((void*)StartupInfo.lpAttributeList != null)
41+
{
42+
PInvoke.DeleteProcThreadAttributeList(StartupInfo.lpAttributeList);
43+
Marshal.FreeHGlobal((nint)(void*)StartupInfo.lpAttributeList);
44+
}
4145
}
4246

4347
// Close process and thread handles
4448
if (ProcessInfo.hProcess != nint.Zero)
4549
{
46-
CloseHandle(ProcessInfo.hProcess);
50+
PInvoke.CloseHandle(ProcessInfo.hProcess);
4751
}
4852
if (ProcessInfo.hThread != nint.Zero)
4953
{
50-
CloseHandle(ProcessInfo.hThread);
54+
PInvoke.CloseHandle(ProcessInfo.hThread);
5155
}
5256

5357
disposedValue = true;
Lines changed: 81 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
using System;
22
using System.Runtime.InteropServices;
3-
using static Files.App.Utils.Terminal.ConPTY.ProcessApi;
3+
using Windows.Win32;
4+
using Windows.Win32.Foundation;
5+
using Windows.Win32.Security;
6+
using Windows.Win32.System.Threading;
47

58
namespace Files.App.Utils.Terminal.ConPTY
69
{
@@ -22,77 +25,95 @@ internal static Process Start(string command, string directory, nint attributes,
2225
return new Process(startupInfo, processInfo);
2326
}
2427

25-
private static STARTUPINFOEX ConfigureProcessThread(nint hPC, nint attributes)
28+
private static STARTUPINFOEXW ConfigureProcessThread(nint hPC, nint attributes)
2629
{
2730
// this method implements the behavior described in https://docs.microsoft.com/en-us/windows/console/creating-a-pseudoconsole-session#preparing-for-creation-of-the-child-process
28-
29-
var lpSize = nint.Zero;
30-
var success = InitializeProcThreadAttributeList(
31-
lpAttributeList: nint.Zero,
32-
dwAttributeCount: 1,
33-
dwFlags: 0,
34-
lpSize: ref lpSize
35-
);
36-
if (success || lpSize == nint.Zero) // we're not expecting `success` here, we just want to get the calculated lpSize
31+
unsafe
3732
{
38-
throw new InvalidOperationException("Could not calculate the number of bytes for the attribute list. " + Marshal.GetLastWin32Error());
39-
}
33+
var lpSize = nuint.Zero;
34+
var success = PInvoke.InitializeProcThreadAttributeList(
35+
lpAttributeList: new(null),
36+
dwAttributeCount: 1,
37+
lpSize: ref lpSize
38+
);
39+
if (success || lpSize == nuint.Zero) // we're not expecting `success` here, we just want to get the calculated lpSize
40+
{
41+
throw new InvalidOperationException("Could not calculate the number of bytes for the attribute list. " + Marshal.GetLastWin32Error());
42+
}
4043

41-
var startupInfo = new STARTUPINFOEX();
42-
startupInfo.StartupInfo.cb = Marshal.SizeOf<STARTUPINFOEX>();
43-
startupInfo.lpAttributeList = Marshal.AllocHGlobal(lpSize);
44+
var startupInfo = new STARTUPINFOEXW();
45+
startupInfo.StartupInfo.cb = (uint)Marshal.SizeOf<STARTUPINFOEXW>();
46+
startupInfo.lpAttributeList = new((void*)Marshal.AllocHGlobal((int)lpSize));
4447

45-
success = InitializeProcThreadAttributeList(
46-
lpAttributeList: startupInfo.lpAttributeList,
47-
dwAttributeCount: 1,
48-
dwFlags: 0,
49-
lpSize: ref lpSize
50-
);
51-
if (!success)
52-
{
53-
throw new InvalidOperationException("Could not set up attribute list. " + Marshal.GetLastWin32Error());
54-
}
48+
success = PInvoke.InitializeProcThreadAttributeList(
49+
lpAttributeList: startupInfo.lpAttributeList,
50+
dwAttributeCount: 1,
51+
lpSize: ref lpSize
52+
);
53+
if (!success)
54+
{
55+
throw new InvalidOperationException("Could not set up attribute list. " + Marshal.GetLastWin32Error());
56+
}
5557

56-
success = UpdateProcThreadAttribute(
57-
lpAttributeList: startupInfo.lpAttributeList,
58-
dwFlags: 0,
59-
attribute: attributes,
60-
lpValue: hPC,
61-
cbSize: nint.Size,
62-
lpPreviousValue: nint.Zero,
63-
lpReturnSize: nint.Zero
64-
);
65-
if (!success)
66-
{
67-
throw new InvalidOperationException("Could not set pseudoconsole thread attribute. " + Marshal.GetLastWin32Error());
68-
}
58+
success = PInvoke.UpdateProcThreadAttribute(
59+
lpAttributeList: startupInfo.lpAttributeList,
60+
dwFlags: 0,
61+
Attribute: (nuint)attributes,
62+
lpValue: (void*)hPC,
63+
cbSize: (nuint)nint.Size,
64+
lpPreviousValue: null,
65+
lpReturnSize: (nuint*)null
66+
);
67+
if (!success)
68+
{
69+
throw new InvalidOperationException("Could not set pseudoconsole thread attribute. " + Marshal.GetLastWin32Error());
70+
}
6971

70-
return startupInfo;
72+
return startupInfo;
73+
}
7174
}
7275

73-
private static PROCESS_INFORMATION RunProcess(ref STARTUPINFOEX sInfoEx, string commandLine, string directory)
76+
private static PROCESS_INFORMATION RunProcess(ref STARTUPINFOEXW sInfoEx, string commandLine, string directory)
7477
{
75-
int securityAttributeSize = Marshal.SizeOf<SECURITY_ATTRIBUTES>();
76-
var pSec = new SECURITY_ATTRIBUTES { nLength = securityAttributeSize };
77-
var tSec = new SECURITY_ATTRIBUTES { nLength = securityAttributeSize };
78-
var success = CreateProcess(
79-
lpApplicationName: null,
80-
lpCommandLine: commandLine,
81-
lpProcessAttributes: ref pSec,
82-
lpThreadAttributes: ref tSec,
83-
bInheritHandles: false,
84-
dwCreationFlags: EXTENDED_STARTUPINFO_PRESENT,
85-
lpEnvironment: nint.Zero,
86-
lpCurrentDirectory: directory,
87-
lpStartupInfo: ref sInfoEx,
88-
lpProcessInformation: out PROCESS_INFORMATION pInfo
89-
);
90-
if (!success)
78+
unsafe
9179
{
92-
throw new InvalidOperationException("Could not create process. " + Marshal.GetLastWin32Error());
93-
}
80+
var success = false;
81+
82+
int securityAttributeSize = Marshal.SizeOf<SECURITY_ATTRIBUTES>();
83+
var pSec = new SECURITY_ATTRIBUTES { nLength = (uint)securityAttributeSize };
84+
var tSec = new SECURITY_ATTRIBUTES { nLength = (uint)securityAttributeSize };
85+
86+
PROCESS_INFORMATION lpProcessInformation;
9487

95-
return pInfo;
88+
fixed (STARTUPINFOEXW* lpStartupInfo = &sInfoEx)
89+
{
90+
fixed (char* lpCurrentDirectory = directory)
91+
{
92+
fixed (char* lpCommandLine = commandLine)
93+
{
94+
success = PInvoke.CreateProcess(
95+
lpApplicationName: new PCWSTR(null),
96+
lpCommandLine: lpCommandLine,
97+
lpProcessAttributes: &pSec,
98+
lpThreadAttributes: &tSec,
99+
bInheritHandles: false,
100+
dwCreationFlags: PROCESS_CREATION_FLAGS.EXTENDED_STARTUPINFO_PRESENT,
101+
lpEnvironment: null,
102+
lpCurrentDirectory: lpCurrentDirectory,
103+
lpStartupInfo: (STARTUPINFOW*)lpStartupInfo,
104+
lpProcessInformation: &lpProcessInformation
105+
);
106+
}
107+
}
108+
}
109+
110+
if (!success)
111+
{
112+
throw new InvalidOperationException("Could not create process. " + Marshal.GetLastWin32Error());
113+
}
114+
115+
return lpProcessInformation;
116+
}
96117
}
97118
}
98119
}

0 commit comments

Comments
 (0)