11using System ;
22using 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
58namespace 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