@@ -30,20 +30,36 @@ enum FileType : uint
3030 FileTypePipe = 0x0003 ,
3131 FileTypeRemote = 0x8000 ,
3232 FileTypeUnknown = 0x0000 ,
33+ FileTypeUnknownError = 0xFFFE ,
34+ FileTypeUnknownHandleInvalid = 0xFFFF ,
3335 }
3436 const int STD_INPUT_HANDLE = - 10 ;
3537 const int STD_OUTPUT_HANDLE = - 11 ;
3638 const int STD_ERROR_HANDLE = - 12 ;
3739
38- // [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
39- // static extern bool FreeConsole();
40+ [ DllImport ( "kernel32.dll" , SetLastError = true ) ]
41+ static extern FileType GetFileType ( IntPtr hFile ) ;
42+ FileType GetFileType2 ( IntPtr hFile )
43+ {
44+ FileType ftResult = GetFileType ( hFile ) ;
45+
46+ if ( ftResult != FileType . FileTypeUnknown ) return ftResult ;
47+ int iError = Marshal . GetLastWin32Error ( ) ;
48+ if ( 0 == iError /* S_OK */ ) return FileType . FileTypeUnknown ;
49+ if ( 6 == iError /* ERROR_INVALID_HANDLE */ )
50+ {
51+ return FileType . FileTypeUnknownHandleInvalid ;
52+ }
53+ return FileType . FileTypeUnknownError ;
54+ }
55+
56+ // [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
57+ // static extern bool FreeConsole();
4058
4159 private const int SW_SHOW = 5 ;
4260 [ DllImport ( "User32" ) ]
4361 private static extern int ShowWindow ( int hwnd , int nCmdShow ) ;
4462
45- [ DllImport ( "kernel32.dll" ) ]
46- static extern FileType GetFileType ( IntPtr hFile ) ;
4763 [ DllImport ( "Kernel32.dll" , SetLastError = true ) ]
4864 static extern IntPtr GetStdHandle ( int nStdHandle ) ;
4965
@@ -79,6 +95,8 @@ struct app_state
7995 public Stream strmToApp ;
8096 public Stream strmFromExt ;
8197 public Stream strmToExt ;
98+ //public Stream strmErrToExt;
99+ public Stream strmErrFromApp ;
82100 public Process procParent ;
83101 }
84102
@@ -91,6 +109,7 @@ private static async Task WriteToApp(string sMessage)
91109 {
92110 try
93111 {
112+ if ( null == oSettings . strmToApp ) return ;
94113 byte [ ] arrPayload = Encoding . UTF8 . GetBytes ( sMessage ) ;
95114 byte [ ] arrSize = BitConverter . GetBytes ( ( UInt32 ) arrPayload . Length ) ;
96115 await oSettings . strmToApp . WriteAsync ( arrSize , 0 , 4 ) ;
@@ -257,6 +276,7 @@ private void detachApp()
257276 log ( "Detaching NativeHost App pipes." ) ;
258277 if ( null != oSettings . strmToApp ) { oSettings . strmToApp . Close ( ) ; oSettings . strmToApp = null ; }
259278 if ( null != oSettings . strmFromApp ) { oSettings . strmFromApp . Close ( ) ; oSettings . strmFromApp = null ; }
279+ if ( null != oSettings . strmErrFromApp ) { oSettings . strmErrFromApp . Close ( ) ; oSettings . strmErrFromApp = null ; }
260280 log ( "NativeHost App pipes detached." ) ;
261281 markAppDetached ( ) ;
262282 if ( oSettings . bPropagateClosures ) detachExtension ( ) ;
@@ -296,7 +316,7 @@ private async Task MessageShufflerForExtension()
296316
297317 if ( cbBodyPromised >= Int32 . MaxValue )
298318 {
299- log ( "Was promised a message >=2gb. Technically this is legal but this app only allows 2GB due to .NET Framework size limits." ) ;
319+ log ( "Was promised a message >=2gb. Technically this is legal, but this debugger only allows 2GB due to .NET Framework size limits." ) ;
300320 detachExtension ( ) ;
301321 return ;
302322 }
@@ -321,6 +341,7 @@ private async Task MessageShufflerForExtension()
321341
322342 if ( oSettings . bSendToFiddler )
323343 {
344+ log ( "Forwarding message to Fiddler..." ) ;
324345 try
325346 {
326347 HttpContent entity = new ByteArrayContent ( buffer ) ;
@@ -350,16 +371,39 @@ private async Task MessageShufflerForExtension()
350371 log ( $ "!!! ERROR: JSON Parsing failed at offset { oErrors . iErrorIndex } { oErrors . sWarningText } . Note:Strings must be double-quoted.") ;
351372 }
352373
353- if ( oSettings . bReflectToExtension &&
354- ( sMessage . Length < ( 1024 * 1024 ) ) ) // Don't reflect messages over 1mb. They're illegal!
374+ if ( oSettings . bReflectToExtension )
355375 {
356- await WriteToExtension ( sMessage ) ;
376+ // Don't reflect messages over 1mb. They're illegal!)
377+ if ( sMessage . Length < ( 1024 * 1024 ) )
378+ {
379+ log ( "Reflecting message to extension..." ) ;
380+ await WriteToExtension ( sMessage ) ;
381+ }
382+ else log ( "!! Message was over 1mb and must not be reflected !!" ) ;
357383 }
358384
359- if ( null != oSettings . strmToApp )
385+ await WriteToApp ( sMessage ) ;
386+ }
387+ }
388+
389+ /// <summary>
390+ /// This function sits around waiting for messages from the browser extension.
391+ /// </summary>
392+ private async Task WatchStdErrFromApp ( )
393+ {
394+ //if (null == oSettings.strmErrFromApp) return;
395+ byte [ ] arrErrString = new byte [ 1024 ] ;
396+
397+ while ( true )
398+ {
399+ int cbThisRead = await oSettings . strmErrFromApp . ReadAsync ( arrErrString , 0 , arrErrString . Length , ctsApp . Token ) ;
400+ if ( cbThisRead < 1 )
360401 {
361- await WriteToApp ( sMessage ) ;
402+ return ;
362403 }
404+ //MaybeWriteBytesToLogfile("-RawRead: ", arrLenBytes, cbSizeRead, cbThisRead);
405+ string sMessage = Encoding . UTF8 . GetString ( arrErrString , 0 , ( int ) cbThisRead ) ;
406+ log ( "App wrote Std_Err: " + sMessage , false ) ;
363407 }
364408 }
365409
@@ -534,6 +578,8 @@ private void frmMain_Load(object sender, EventArgs e)
534578 log ( $ "I am{ sExtraInfo } , launched by [{ ( ( null != oSettings . procParent ) ? ( oSettings . procParent . ProcessName + ':' + oSettings . procParent . Id ) : "unknown" ) } ].") ;
535579 lblVersion . Text = $ "v{ Application . ProductVersion } [{ ( ( 8 == IntPtr . Size ) ? "64" : "32" ) } -bit]";
536580 Text += sExtraInfo ; // Append extra info to form caption.
581+ log ( Utilities . DescribeStartupHandles ( ) ) ;
582+ log ( DescribeStandardHandles ( ) ) ;
537583
538584 var arrArgs = Environment . GetCommandLineArgs ( ) ;
539585 if ( arrArgs . Length > 1 ) oSettings . sExtensionID = arrArgs [ 1 ] ;
@@ -584,17 +630,9 @@ private void WaitForMessages()
584630 {
585631 try
586632 {
587- var hIn = GetStdHandle ( STD_INPUT_HANDLE ) ;
588- var hInType = GetFileType ( hIn ) ;
589- var hOut = GetStdHandle ( STD_OUTPUT_HANDLE ) ;
590- var hOutType = GetFileType ( hOut ) ;
591- var hErr = GetStdHandle ( STD_ERROR_HANDLE ) ;
592- var hErrType = GetFileType ( hErr ) ;
633+ log ( DescribeStandardHandles ( ) ) ;
593634 oSettings . strmFromExt = Console . OpenStandardInput ( ) ;
594635 oSettings . strmToExt = Console . OpenStandardOutput ( ) ;
595- log ( $ "Attached stdin (0x{ hIn . ToInt64 ( ) : x} , { hInType } ) and " +
596- $ "stdout (0x{ hOut . ToInt64 ( ) : x} , { hOutType } ) streams.") ;
597- log ( $ "Not using stderr (0x{ hErr . ToInt64 ( ) : x} , { hErrType } ).") ;
598636 pbExt . BackColor = Color . FromArgb ( 159 , 255 , 159 ) ;
599637 Task . Run ( async ( ) => await MessageShufflerForExtension ( ) ) ;
600638 }
@@ -604,6 +642,19 @@ private void WaitForMessages()
604642 }
605643 }
606644
645+ private string DescribeStandardHandles ( )
646+ {
647+ var hIn = GetStdHandle ( STD_INPUT_HANDLE ) ;
648+ var hInType = GetFileType2 ( hIn ) ;
649+ var hOut = GetStdHandle ( STD_OUTPUT_HANDLE ) ;
650+ var hOutType = GetFileType2 ( hOut ) ;
651+ var hErr = GetStdHandle ( STD_ERROR_HANDLE ) ;
652+ var hErrType = GetFileType2 ( hErr ) ;
653+ return ( $ "GetStdHandle() says stdin=(0x{ hIn . ToInt64 ( ) : x} , { hInType } ); " +
654+ $ "stdout=(0x{ hOut . ToInt64 ( ) : x} , { hOutType } ); " +
655+ $ "stderr=(0x{ hErr . ToInt64 ( ) : x} , { hErrType } ).") ;
656+ }
657+
607658 private void clbOptions_ItemCheck ( object sender , ItemCheckEventArgs e )
608659 {
609660 if ( e . Index == 0 ) { oSettings . bReflectToExtension = ( e . NewValue == CheckState . Checked ) ; return ; }
@@ -714,14 +765,15 @@ private bool ConnectApp(string sFilename)
714765 myProcess . StartInfo . UseShellExecute = false ;
715766 myProcess . StartInfo . WorkingDirectory = Path . GetDirectoryName ( myProcess . StartInfo . FileName ) ;
716767
717- // Hide by default
718- // TODO: allow showing https://source.chromium.org/chromium/chromium/src/+/main:base/process/launch_win.cc;l=298;drc=1ad438dde6b39e1c0d04b8f8cb27c1a14ba6f90e
768+ // TODO: If the compat hack lands for Chrome, then we should use the same logic here to show GUI if the app targets SUBSYSTEM_WINDOWS
769+ // https://weblogs.asp.net/whaggard/223020
770+ // https://source.chromium.org/chromium/chromium/src/+/main:base/process/launch_win.cc;l=298;drc=1ad438dde6b39e1c0d04b8f8cb27c1a14ba6f90e
719771 myProcess . StartInfo . CreateNoWindow = true ;
720772 myProcess . StartInfo . WindowStyle = ProcessWindowStyle . Hidden ; // Does this do anything?
721773
722774 myProcess . StartInfo . RedirectStandardInput = true ;
723775 myProcess . StartInfo . RedirectStandardOutput = true ;
724- // TODO: STDERR?
776+ myProcess . StartInfo . RedirectStandardError = true ;
725777
726778 try
727779 {
@@ -741,8 +793,10 @@ private bool ConnectApp(string sFilename)
741793 // https://docs.microsoft.com/en-us/dotnet/api/system.console?view=net-5.0#Streams
742794 oSettings . strmToApp = myProcess . StandardInput . BaseStream ;
743795 oSettings . strmFromApp = myProcess . StandardOutput . BaseStream ;
796+ oSettings . strmErrFromApp = myProcess . StandardError . BaseStream ;
744797 log ( $ "Started { oSettings . sExeName } as the proxied NativeMessagingHost.") ;
745798 Task . Run ( async ( ) => await MessageShufflerForApp ( ) ) ;
799+ Task . Run ( async ( ) => await WatchStdErrFromApp ( ) ) ;
746800 return true ;
747801 }
748802 }
@@ -952,12 +1006,12 @@ private void frmMain_FormClosed(object sender, FormClosedEventArgs e)
9521006
9531007 private void txtSendToApp_TextChanged ( object sender , EventArgs e )
9541008 {
955- btnSendToApp . Enabled = ( ( txtSendToApp . TextLength > 0 ) && IsAppAttached ( ) ) ;
1009+ btnSendToApp . Enabled = ( /* (txtSendToApp.TextLength > 0) && */ IsAppAttached ( ) ) ;
9561010 }
9571011
9581012 private void txtSendToExtension_TextChanged ( object sender , EventArgs e )
9591013 {
960- btnSendToExtension . Enabled = ( ( txtSendToExtension . TextLength > 0 ) && IsExtensionAttached ( ) ) ;
1014+ btnSendToExtension . Enabled = ( /* (txtSendToExtension.TextLength > 0) && */ IsExtensionAttached ( ) ) ;
9611015 }
9621016
9631017 private async void btnSendToApp_Click ( object sender , EventArgs e )
@@ -1001,5 +1055,10 @@ private void frmMain_KeyDown(object sender, KeyEventArgs e)
10011055 }
10021056 }
10031057 }
1058+
1059+ private void btnPokeStdErr_Click ( object sender , EventArgs e )
1060+ {
1061+ Console . Error . WriteLine ( "Poking StdErr @" + DateTime . Now . ToString ( ) ) ;
1062+ }
10041063 }
10051064}
0 commit comments