Jacek Caban : kernelbase: Add CreatePseudoConsole implementation.
Alexandre Julliard
julliard at winehq.org
Fri Aug 21 16:43:26 CDT 2020
Module: wine
Branch: master
Commit: 7ea9f9edeed417a241d607bac282d68bdf5abd36
URL: https://source.winehq.org/git/wine.git/?a=commit;h=7ea9f9edeed417a241d607bac282d68bdf5abd36
Author: Jacek Caban <jacek at codeweavers.com>
Date: Thu Aug 20 23:48:54 2020 +0200
kernelbase: Add CreatePseudoConsole implementation.
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/kernelbase/console.c | 116 ++++++++++++++++++++++++++++++++++++++++++-
dlls/kernelbase/kernelbase.h | 7 +++
2 files changed, 121 insertions(+), 2 deletions(-)
diff --git a/dlls/kernelbase/console.c b/dlls/kernelbase/console.c
index e5a9fbd501..cb85061fc9 100644
--- a/dlls/kernelbase/console.c
+++ b/dlls/kernelbase/console.c
@@ -174,6 +174,40 @@ static COORD get_largest_console_window_size( HANDLE handle )
return c;
}
+static HANDLE create_console_server( void )
+{
+ OBJECT_ATTRIBUTES attr = {sizeof(attr)};
+ UNICODE_STRING string;
+ IO_STATUS_BLOCK iosb;
+ HANDLE handle;
+ NTSTATUS status;
+
+ RtlInitUnicodeString( &string, L"\\Device\\ConDrv\\Server" );
+ attr.ObjectName = &string;
+ attr.Attributes = OBJ_INHERIT;
+ status = NtCreateFile( &handle, FILE_WRITE_PROPERTIES | FILE_READ_PROPERTIES | SYNCHRONIZE,
+ &attr, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN,
+ FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
+ return set_ntstatus( status ) ? handle : NULL;
+}
+
+static HANDLE create_console_reference( HANDLE root )
+{
+ OBJECT_ATTRIBUTES attr = {sizeof(attr)};
+ UNICODE_STRING string;
+ IO_STATUS_BLOCK iosb;
+ HANDLE handle;
+ NTSTATUS status;
+
+ RtlInitUnicodeString( &string, L"Reference" );
+ attr.RootDirectory = root;
+ attr.ObjectName = &string;
+ status = NtCreateFile( &handle, FILE_READ_DATA | FILE_WRITE_DATA | FILE_WRITE_PROPERTIES |
+ FILE_READ_PROPERTIES | SYNCHRONIZE, &attr, &iosb, NULL, FILE_ATTRIBUTE_NORMAL,
+ 0, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0 );
+ return set_ntstatus( status ) ? handle : NULL;
+}
+
static BOOL init_console_std_handles(void)
{
HANDLE std_out = NULL, std_err = NULL, handle;
@@ -1578,13 +1612,91 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteConsoleOutputCharacterW( HANDLE handle, LPCWS
return ret;
}
+static HANDLE create_pseudo_console( COORD size, HANDLE input, HANDLE output, HANDLE signal,
+ DWORD flags, HANDLE *process )
+{
+ WCHAR cmd[MAX_PATH], conhost_path[MAX_PATH];
+ PROCESS_INFORMATION pi;
+ HANDLE server, console;
+ STARTUPINFOEXW si;
+ void *redir;
+ BOOL res;
+
+ if (!(server = create_console_server())) return NULL;
+
+ console = create_console_reference( server );
+ if (!console)
+ {
+ NtClose( server );
+ return NULL;
+ }
+
+ memset( &si, 0, sizeof(si) );
+ si.StartupInfo.cb = sizeof(STARTUPINFOEXW);
+ si.StartupInfo.hStdInput = input;
+ si.StartupInfo.hStdOutput = output;
+ si.StartupInfo.hStdError = output;
+ si.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
+ swprintf( conhost_path, ARRAY_SIZE(conhost_path), L"%s\\conhost.exe", system_dir );
+ swprintf( cmd, ARRAY_SIZE(cmd),
+ L"\"%s\" --headless %s--width %u --height %u --signal 0x%x --server 0x%x",
+ conhost_path, (flags & PSEUDOCONSOLE_INHERIT_CURSOR) ? L"--inheritcursor " : L"",
+ size.X, size.Y, signal, server );
+
+ Wow64DisableWow64FsRedirection( &redir );
+ res = CreateProcessW( conhost_path, cmd, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL,
+ &si.StartupInfo, &pi );
+ Wow64RevertWow64FsRedirection( redir );
+ NtClose( server );
+ if (!res)
+ {
+ NtClose( console );
+ return NULL;
+ }
+
+ NtClose( pi.hThread );
+ *process = pi.hProcess;
+ return console;
+}
+
/******************************************************************************
* CreatePseudoConsole (kernelbase.@)
*/
HRESULT WINAPI CreatePseudoConsole( COORD size, HANDLE input, HANDLE output, DWORD flags, HPCON *ret )
{
- FIXME( "(%u,%u) %p %p %x %p\n", size.X, size.Y, input, output, flags, ret );
- return E_NOTIMPL;
+ SECURITY_ATTRIBUTES inherit_attr = { sizeof(inherit_attr), NULL, TRUE };
+ struct pseudo_console *pseudo_console;
+ HANDLE signal = NULL;
+ WCHAR pipe_name[64];
+
+ TRACE( "(%u,%u) %p %p %x %p\n", size.X, size.Y, input, output, flags, ret );
+
+ if (!size.X || !size.Y || !ret) return E_INVALIDARG;
+
+ if (!(pseudo_console = HeapAlloc( GetProcessHeap(), 0, HEAP_ZERO_MEMORY ))) return E_OUTOFMEMORY;
+
+ swprintf( pipe_name, ARRAY_SIZE(pipe_name), L"\\\\.\\pipe\\wine_pty_signal_pipe%x",
+ GetCurrentThreadId() );
+ signal = CreateNamedPipeW( pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE,
+ PIPE_UNLIMITED_INSTANCES, 4096, 4096, NMPWAIT_USE_DEFAULT_WAIT, &inherit_attr );
+ if (signal == INVALID_HANDLE_VALUE)
+ {
+ HeapFree( GetProcessHeap(), 0, pseudo_console );
+ return HRESULT_FROM_WIN32( GetLastError() );
+ }
+ pseudo_console->signal = CreateFileW( pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
+ if (pseudo_console->signal != INVALID_HANDLE_VALUE)
+ pseudo_console->reference = create_pseudo_console( size, input, output, signal, flags,
+ &pseudo_console->process );
+ NtClose( signal );
+ if (!pseudo_console->reference)
+ {
+ ClosePseudoConsole( pseudo_console );
+ return HRESULT_FROM_WIN32( GetLastError() );
+ }
+
+ *ret = pseudo_console;
+ return S_OK;
}
/******************************************************************************
diff --git a/dlls/kernelbase/kernelbase.h b/dlls/kernelbase/kernelbase.h
index 59265bab2c..551542e572 100644
--- a/dlls/kernelbase/kernelbase.h
+++ b/dlls/kernelbase/kernelbase.h
@@ -24,6 +24,13 @@
#include "windef.h"
#include "winbase.h"
+struct pseudo_console
+{
+ HANDLE signal;
+ HANDLE reference;
+ HANDLE process;
+};
+
extern WCHAR *file_name_AtoW( LPCSTR name, BOOL alloc ) DECLSPEC_HIDDEN;
extern DWORD file_name_WtoA( LPCWSTR src, INT srclen, LPSTR dest, INT destlen ) DECLSPEC_HIDDEN;
extern void init_startup_info( RTL_USER_PROCESS_PARAMETERS *params ) DECLSPEC_HIDDEN;
More information about the wine-cvs
mailing list