ionescu007 / lxss

Fun with the Windows Subsystem for Linux (WSL/LXSS)

Home Page:http://www.windows-internals.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Output to non-console handles?

ysc3839 opened this issue · comments

In lxlaunch.cpp:203 it checks whether the output handle is a console handle. I wonder if it's possible to make it supports non-console handles?

발견했습니다..
영어로 뭐라 해야되나..
i solved (??)

if (GetFileType(inHandle) != FILE_TYPE_CHAR)
{
stdHandles.StdIn.Handle = (ULONG)inHandle;
stdHandles.StdIn.Pipe = true;
}else{
oldInCp = GetConsoleCP();
SetConsoleCP(CP_UTF8);
GetConsoleMode(inHandle, &oldInMode);
SetConsoleMode(inHandle, oldInMode &
~(ENABLE_INSERT_MODE |
ENABLE_ECHO_INPUT |
ENABLE_LINE_INPUT |
ENABLE_PROCESSED_INPUT) |
(ENABLE_VIRTUAL_TERMINAL_INPUT |
ENABLE_WINDOW_INPUT));
}

Doesn't work...

유감

I guess this is caused by two lxss processes running in a console window.
The redirection to non-lxss works well.

I do not know what 2 means, but it will be good for you.

hr = ((PLX_INSTANCE_V2)iLxInstance)->CreateLxProcess(
(PLX_INSTANCE_V2)iLxInstance,
imageFileName,
cmdCount,
cmdLine,
"C:\windows\system32;c:\windows",
currentDirectory,
2,
// LX_CREATE_PROCESS_PRINT_UPDATE_INFO_FLAG,
&stdHandles,
&consoleData2,
0,
&processHandle,
&serverHandle);
}

I think it's because lxss requires a console to output. In RS2 it handles console input and output, so there's no way to output to non-console handles.

What do you mean? 🤔

I have confirmed that it works well, but I am sorry that I can not show it.
So I'll show you the code.

//...skip
ULONG Flag = LX_CREATE_PROCESS_PRINT_UPDATE_INFO_FLAG;
//
// Get, and validate, the output handle
//
outHandle = GetStdHandle(STD_OUTPUT_HANDLE);
if (GetFileType(outHandle) != FILE_TYPE_CHAR)
{
stdHandles.StdOut.Pipe = true;
stdHandles.StdOut.Handle = HandleToULong(outHandle);
Flag = 2;
}
else {
//
// Switch to VT-100 Output Console
//
GetConsoleMode(outHandle, &oldOutMode);
SetConsoleMode(outHandle, oldOutMode |
DISABLE_NEWLINE_AUTO_RETURN |
0x4 |
ENABLE_PROCESSED_OUTPUT);
//
// Switch output to UTF-8
//
oldOutCp = GetConsoleOutputCP();
SetConsoleOutputCP(CP_UTF8);
}

//
// Get, and validate, the output handle
//
inHandle = GetStdHandle(STD_INPUT_HANDLE);
if (GetFileType(inHandle) != FILE_TYPE_CHAR)
{
	stdHandles.StdIn.Handle = HandleToULong(inHandle);
	stdHandles.StdIn.Pipe = true;
}
else {
	//
	// Switch to VT-100 Input Console
	//
	GetConsoleMode(inHandle, &oldInMode);
	SetConsoleMode(inHandle, oldInMode &
		~(ENABLE_INSERT_MODE |
			ENABLE_ECHO_INPUT |
			ENABLE_LINE_INPUT |
			ENABLE_PROCESSED_INPUT) |
		(ENABLE_VIRTUAL_TERMINAL_INPUT |
			ENABLE_WINDOW_INPUT));


	//
	// Switch input to UTF-8
	//
	oldInCp = GetConsoleCP();
	SetConsoleCP(CP_UTF8);

}

//...skip
hr = ((PLX_INSTANCE_V2)iLxInstance)->CreateLxProcess(
(PLX_INSTANCE_V2
)iLxInstance,
imageFileName,
cmdCount,
cmdLine,
"C:\windows\system32;c:\windows",
currentDirectory,
Flag,
&stdHandles,
&consoleData2,
0,
&processHandle,
&serverHandle);

//...skip

@ionescu007 So you mean RS2 supports non-console handles? What about RS1?

@joshouamel Tested on 10.0.14393, still doesn't work...
My code: https://gist.github.com/ysc3839/078f3137ce5b5e8b3104ba5cbaa88d7b

Of course it will not work out. What about Anonymous pipes rather than named pipes? Two programs could not share a pipe. You do not have to wait if inhandle is in pipe mode at the end of the process.

waitArray[0] = UlongToHandle(processHandle);
waitArray[1] = GetStdHandle(STD_INPUT_HANDLE);
if(stdHandles.StdIn.Pipe)
WaitForSingleObject(waitArray[0], INFINITE);
else while (WaitForMultipleObjects(RTL_NUMBER_OF(waitArray),
waitArray,
FALSE,
INFINITE))
{
//
// Read the console input -- we only care about key pressses
//
assert(useRs2Logic == FALSE);
ReadConsoleInput(waitArray[1], &record, 1, &eventsRead);
if ((record.EventType == KEY_EVENT) &&
(record.Event.KeyEvent.bKeyDown != FALSE))
{
//
// Write into the Linux input pipe the character
//
WriteFile(inPipe,
&record.Event.KeyEvent.uChar.AsciiChar,
1,
&bytesWritten,
NULL);
}
}