@@ -30,20 +30,36 @@ enum FileType : uint
30
30
FileTypePipe = 0x0003 ,
31
31
FileTypeRemote = 0x8000 ,
32
32
FileTypeUnknown = 0x0000 ,
33
+ FileTypeUnknownError = 0xFFFE ,
34
+ FileTypeUnknownHandleInvalid = 0xFFFF ,
33
35
}
34
36
const int STD_INPUT_HANDLE = - 10 ;
35
37
const int STD_OUTPUT_HANDLE = - 11 ;
36
38
const int STD_ERROR_HANDLE = - 12 ;
37
39
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();
40
58
41
59
private const int SW_SHOW = 5 ;
42
60
[ DllImport ( "User32" ) ]
43
61
private static extern int ShowWindow ( int hwnd , int nCmdShow ) ;
44
62
45
- [ DllImport ( "kernel32.dll" ) ]
46
- static extern FileType GetFileType ( IntPtr hFile ) ;
47
63
[ DllImport ( "Kernel32.dll" , SetLastError = true ) ]
48
64
static extern IntPtr GetStdHandle ( int nStdHandle ) ;
49
65
@@ -79,6 +95,8 @@ struct app_state
79
95
public Stream strmToApp ;
80
96
public Stream strmFromExt ;
81
97
public Stream strmToExt ;
98
+ //public Stream strmErrToExt;
99
+ public Stream strmErrFromApp ;
82
100
public Process procParent ;
83
101
}
84
102
@@ -91,6 +109,7 @@ private static async Task WriteToApp(string sMessage)
91
109
{
92
110
try
93
111
{
112
+ if ( null == oSettings . strmToApp ) return ;
94
113
byte [ ] arrPayload = Encoding . UTF8 . GetBytes ( sMessage ) ;
95
114
byte [ ] arrSize = BitConverter . GetBytes ( ( UInt32 ) arrPayload . Length ) ;
96
115
await oSettings . strmToApp . WriteAsync ( arrSize , 0 , 4 ) ;
@@ -257,6 +276,7 @@ private void detachApp()
257
276
log ( "Detaching NativeHost App pipes." ) ;
258
277
if ( null != oSettings . strmToApp ) { oSettings . strmToApp . Close ( ) ; oSettings . strmToApp = null ; }
259
278
if ( null != oSettings . strmFromApp ) { oSettings . strmFromApp . Close ( ) ; oSettings . strmFromApp = null ; }
279
+ if ( null != oSettings . strmErrFromApp ) { oSettings . strmErrFromApp . Close ( ) ; oSettings . strmErrFromApp = null ; }
260
280
log ( "NativeHost App pipes detached." ) ;
261
281
markAppDetached ( ) ;
262
282
if ( oSettings . bPropagateClosures ) detachExtension ( ) ;
@@ -296,7 +316,7 @@ private async Task MessageShufflerForExtension()
296
316
297
317
if ( cbBodyPromised >= Int32 . MaxValue )
298
318
{
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." ) ;
300
320
detachExtension ( ) ;
301
321
return ;
302
322
}
@@ -321,6 +341,7 @@ private async Task MessageShufflerForExtension()
321
341
322
342
if ( oSettings . bSendToFiddler )
323
343
{
344
+ log ( "Forwarding message to Fiddler..." ) ;
324
345
try
325
346
{
326
347
HttpContent entity = new ByteArrayContent ( buffer ) ;
@@ -350,16 +371,39 @@ private async Task MessageShufflerForExtension()
350
371
log ( $ "!!! ERROR: JSON Parsing failed at offset { oErrors . iErrorIndex } { oErrors . sWarningText } . Note:Strings must be double-quoted.") ;
351
372
}
352
373
353
- if ( oSettings . bReflectToExtension &&
354
- ( sMessage . Length < ( 1024 * 1024 ) ) ) // Don't reflect messages over 1mb. They're illegal!
374
+ if ( oSettings . bReflectToExtension )
355
375
{
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 !!" ) ;
357
383
}
358
384
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 )
360
401
{
361
- await WriteToApp ( sMessage ) ;
402
+ return ;
362
403
}
404
+ //MaybeWriteBytesToLogfile("-RawRead: ", arrLenBytes, cbSizeRead, cbThisRead);
405
+ string sMessage = Encoding . UTF8 . GetString ( arrErrString , 0 , ( int ) cbThisRead ) ;
406
+ log ( "App wrote Std_Err: " + sMessage , false ) ;
363
407
}
364
408
}
365
409
@@ -534,6 +578,8 @@ private void frmMain_Load(object sender, EventArgs e)
534
578
log ( $ "I am{ sExtraInfo } , launched by [{ ( ( null != oSettings . procParent ) ? ( oSettings . procParent . ProcessName + ':' + oSettings . procParent . Id ) : "unknown" ) } ].") ;
535
579
lblVersion . Text = $ "v{ Application . ProductVersion } [{ ( ( 8 == IntPtr . Size ) ? "64" : "32" ) } -bit]";
536
580
Text += sExtraInfo ; // Append extra info to form caption.
581
+ log ( Utilities . DescribeStartupHandles ( ) ) ;
582
+ log ( DescribeStandardHandles ( ) ) ;
537
583
538
584
var arrArgs = Environment . GetCommandLineArgs ( ) ;
539
585
if ( arrArgs . Length > 1 ) oSettings . sExtensionID = arrArgs [ 1 ] ;
@@ -584,17 +630,9 @@ private void WaitForMessages()
584
630
{
585
631
try
586
632
{
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 ( ) ) ;
593
634
oSettings . strmFromExt = Console . OpenStandardInput ( ) ;
594
635
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 } ).") ;
598
636
pbExt . BackColor = Color . FromArgb ( 159 , 255 , 159 ) ;
599
637
Task . Run ( async ( ) => await MessageShufflerForExtension ( ) ) ;
600
638
}
@@ -604,6 +642,19 @@ private void WaitForMessages()
604
642
}
605
643
}
606
644
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
+
607
658
private void clbOptions_ItemCheck ( object sender , ItemCheckEventArgs e )
608
659
{
609
660
if ( e . Index == 0 ) { oSettings . bReflectToExtension = ( e . NewValue == CheckState . Checked ) ; return ; }
@@ -714,14 +765,15 @@ private bool ConnectApp(string sFilename)
714
765
myProcess . StartInfo . UseShellExecute = false ;
715
766
myProcess . StartInfo . WorkingDirectory = Path . GetDirectoryName ( myProcess . StartInfo . FileName ) ;
716
767
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
719
771
myProcess . StartInfo . CreateNoWindow = true ;
720
772
myProcess . StartInfo . WindowStyle = ProcessWindowStyle . Hidden ; // Does this do anything?
721
773
722
774
myProcess . StartInfo . RedirectStandardInput = true ;
723
775
myProcess . StartInfo . RedirectStandardOutput = true ;
724
- // TODO: STDERR?
776
+ myProcess . StartInfo . RedirectStandardError = true ;
725
777
726
778
try
727
779
{
@@ -741,8 +793,10 @@ private bool ConnectApp(string sFilename)
741
793
// https://docs.microsoft.com/en-us/dotnet/api/system.console?view=net-5.0#Streams
742
794
oSettings . strmToApp = myProcess . StandardInput . BaseStream ;
743
795
oSettings . strmFromApp = myProcess . StandardOutput . BaseStream ;
796
+ oSettings . strmErrFromApp = myProcess . StandardError . BaseStream ;
744
797
log ( $ "Started { oSettings . sExeName } as the proxied NativeMessagingHost.") ;
745
798
Task . Run ( async ( ) => await MessageShufflerForApp ( ) ) ;
799
+ Task . Run ( async ( ) => await WatchStdErrFromApp ( ) ) ;
746
800
return true ;
747
801
}
748
802
}
@@ -952,12 +1006,12 @@ private void frmMain_FormClosed(object sender, FormClosedEventArgs e)
952
1006
953
1007
private void txtSendToApp_TextChanged ( object sender , EventArgs e )
954
1008
{
955
- btnSendToApp . Enabled = ( ( txtSendToApp . TextLength > 0 ) && IsAppAttached ( ) ) ;
1009
+ btnSendToApp . Enabled = ( /* (txtSendToApp.TextLength > 0) && */ IsAppAttached ( ) ) ;
956
1010
}
957
1011
958
1012
private void txtSendToExtension_TextChanged ( object sender , EventArgs e )
959
1013
{
960
- btnSendToExtension . Enabled = ( ( txtSendToExtension . TextLength > 0 ) && IsExtensionAttached ( ) ) ;
1014
+ btnSendToExtension . Enabled = ( /* (txtSendToExtension.TextLength > 0) && */ IsExtensionAttached ( ) ) ;
961
1015
}
962
1016
963
1017
private async void btnSendToApp_Click ( object sender , EventArgs e )
@@ -1001,5 +1055,10 @@ private void frmMain_KeyDown(object sender, KeyEventArgs e)
1001
1055
}
1002
1056
}
1003
1057
}
1058
+
1059
+ private void btnPokeStdErr_Click ( object sender , EventArgs e )
1060
+ {
1061
+ Console . Error . WriteLine ( "Poking StdErr @" + DateTime . Now . ToString ( ) ) ;
1062
+ }
1004
1063
}
1005
1064
}
0 commit comments