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