kernel32: Move AllocConsole to kernelbase.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2020-07-01 16:27:56 +02:00 committed by Alexandre Julliard
parent e43f51640a
commit 2175c7c25e
4 changed files with 108 additions and 172 deletions

View File

@ -519,176 +519,6 @@ DWORD WINAPI GetConsoleTitleA(LPSTR title, DWORD size)
static WCHAR* S_EditString /* = NULL */; static WCHAR* S_EditString /* = NULL */;
static unsigned S_EditStrPos /* = 0 */; static unsigned S_EditStrPos /* = 0 */;
/******************************************************************
* start_console_renderer
*
* helper for AllocConsole
* starts the renderer process
*/
static BOOL start_console_renderer_helper(const char* appname, STARTUPINFOA* si,
HANDLE hEvent)
{
char buffer[1024];
int ret;
PROCESS_INFORMATION pi;
/* FIXME: use dynamic allocation for most of the buffers below */
ret = snprintf(buffer, sizeof(buffer), "%s --use-event=%ld", appname, (DWORD_PTR)hEvent);
if ((ret > -1) && (ret < sizeof(buffer)) &&
CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS,
NULL, NULL, si, &pi))
{
HANDLE wh[2];
DWORD res;
wh[0] = hEvent;
wh[1] = pi.hProcess;
res = WaitForMultipleObjects(2, wh, FALSE, INFINITE);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
if (res != WAIT_OBJECT_0) return FALSE;
TRACE("Started wineconsole pid=%08x tid=%08x\n",
pi.dwProcessId, pi.dwThreadId);
return TRUE;
}
return FALSE;
}
static BOOL start_console_renderer(STARTUPINFOA* si)
{
HANDLE hEvent = 0;
LPSTR p;
OBJECT_ATTRIBUTES attr;
BOOL ret = FALSE;
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.Attributes = OBJ_INHERIT;
attr.ObjectName = NULL;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
NtCreateEvent(&hEvent, EVENT_ALL_ACCESS, &attr, NotificationEvent, FALSE);
if (!hEvent) return FALSE;
/* first try environment variable */
if ((p = getenv("WINECONSOLE")) != NULL)
{
ret = start_console_renderer_helper(p, si, hEvent);
if (!ret)
ERR("Couldn't launch Wine console from WINECONSOLE env var (%s)... "
"trying default access\n", p);
}
/* then try the regular PATH */
if (!ret)
ret = start_console_renderer_helper("wineconsole", si, hEvent);
CloseHandle(hEvent);
return ret;
}
/***********************************************************************
* AllocConsole (KERNEL32.@)
*
* creates an xterm with a pty to our program
*/
BOOL WINAPI AllocConsole(void)
{
HANDLE handle_in = INVALID_HANDLE_VALUE;
HANDLE handle_out = INVALID_HANDLE_VALUE;
HANDLE handle_err = INVALID_HANDLE_VALUE;
STARTUPINFOA siCurrent;
STARTUPINFOA siConsole;
char buffer[1024];
TRACE("()\n");
handle_in = OpenConsoleW( coninW, GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
FALSE, OPEN_EXISTING );
if (VerifyConsoleIoHandle(handle_in))
{
/* we already have a console opened on this process, don't create a new one */
CloseHandle(handle_in);
return FALSE;
}
GetStartupInfoA(&siCurrent);
memset(&siConsole, 0, sizeof(siConsole));
siConsole.cb = sizeof(siConsole);
/* setup a view arguments for wineconsole (it'll use them as default values) */
if (siCurrent.dwFlags & STARTF_USECOUNTCHARS)
{
siConsole.dwFlags |= STARTF_USECOUNTCHARS;
siConsole.dwXCountChars = siCurrent.dwXCountChars;
siConsole.dwYCountChars = siCurrent.dwYCountChars;
}
if (siCurrent.dwFlags & STARTF_USEFILLATTRIBUTE)
{
siConsole.dwFlags |= STARTF_USEFILLATTRIBUTE;
siConsole.dwFillAttribute = siCurrent.dwFillAttribute;
}
if (siCurrent.dwFlags & STARTF_USESHOWWINDOW)
{
siConsole.dwFlags |= STARTF_USESHOWWINDOW;
siConsole.wShowWindow = siCurrent.wShowWindow;
}
/* FIXME (should pass the unicode form) */
if (siCurrent.lpTitle)
siConsole.lpTitle = siCurrent.lpTitle;
else if (GetModuleFileNameA(0, buffer, sizeof(buffer)))
{
buffer[sizeof(buffer) - 1] = '\0';
siConsole.lpTitle = buffer;
}
if (!start_console_renderer(&siConsole))
goto the_end;
if( !(siCurrent.dwFlags & STARTF_USESTDHANDLES) ) {
/* all std I/O handles are inheritable by default */
handle_in = OpenConsoleW( coninW, GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
TRUE, OPEN_EXISTING );
if (handle_in == INVALID_HANDLE_VALUE) goto the_end;
handle_out = OpenConsoleW( conoutW, GENERIC_READ|GENERIC_WRITE,
TRUE, OPEN_EXISTING );
if (handle_out == INVALID_HANDLE_VALUE) goto the_end;
if (!DuplicateHandle(GetCurrentProcess(), handle_out, GetCurrentProcess(),
&handle_err, 0, TRUE, DUPLICATE_SAME_ACCESS))
goto the_end;
} else {
/* STARTF_USESTDHANDLES flag: use handles from StartupInfo */
handle_in = siCurrent.hStdInput;
handle_out = siCurrent.hStdOutput;
handle_err = siCurrent.hStdError;
}
/* NT resets the STD_*_HANDLEs on console alloc */
SetStdHandle(STD_INPUT_HANDLE, handle_in);
SetStdHandle(STD_OUTPUT_HANDLE, handle_out);
SetStdHandle(STD_ERROR_HANDLE, handle_err);
SetLastError(ERROR_SUCCESS);
return TRUE;
the_end:
ERR("Can't allocate console\n");
if (handle_in != INVALID_HANDLE_VALUE) CloseHandle(handle_in);
if (handle_out != INVALID_HANDLE_VALUE) CloseHandle(handle_out);
if (handle_err != INVALID_HANDLE_VALUE) CloseHandle(handle_err);
FreeConsole();
return FALSE;
}
/*********************************************************************** /***********************************************************************
* ReadConsoleA (KERNEL32.@) * ReadConsoleA (KERNEL32.@)

View File

@ -150,7 +150,7 @@
@ stdcall AddVectoredContinueHandler(long ptr) ntdll.RtlAddVectoredContinueHandler @ stdcall AddVectoredContinueHandler(long ptr) ntdll.RtlAddVectoredContinueHandler
@ stdcall AddVectoredExceptionHandler(long ptr) ntdll.RtlAddVectoredExceptionHandler @ stdcall AddVectoredExceptionHandler(long ptr) ntdll.RtlAddVectoredExceptionHandler
# @ stub AdjustCalendarDate # @ stub AdjustCalendarDate
@ stdcall AllocConsole() @ stdcall -import AllocConsole()
@ stub -i386 AllocLSCallback @ stub -i386 AllocLSCallback
@ stdcall -i386 -private AllocSLCallback(ptr ptr) krnl386.exe16.AllocSLCallback @ stdcall -i386 -private AllocSLCallback(ptr ptr) krnl386.exe16.AllocSLCallback
@ stdcall -import AllocateUserPhysicalPages(long ptr ptr) @ stdcall -import AllocateUserPhysicalPages(long ptr ptr)

View File

@ -198,6 +198,112 @@ BOOL WINAPI DECLSPEC_HOTPATCH AttachConsole( DWORD pid )
} }
/******************************************************************
* AllocConsole (kernelbase.@)
*/
BOOL WINAPI AllocConsole(void)
{
SECURITY_ATTRIBUTES inheritable_attr = { sizeof(inheritable_attr), NULL, TRUE };
HANDLE std_in = INVALID_HANDLE_VALUE;
HANDLE std_out = INVALID_HANDLE_VALUE;
HANDLE std_err = INVALID_HANDLE_VALUE;
STARTUPINFOW app_si, console_si;
WCHAR buffer[1024], cmd[256];
PROCESS_INFORMATION pi;
HANDLE event;
DWORD mode;
BOOL ret;
TRACE("()\n");
std_in = CreateFileW( L"CONIN$", GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 0, NULL, OPEN_EXISTING, 0, 0 );
if (GetConsoleMode( std_in, &mode ))
{
/* we already have a console opened on this process, don't create a new one */
CloseHandle( std_in );
return FALSE;
}
GetStartupInfoW(&app_si);
memset(&console_si, 0, sizeof(console_si));
console_si.cb = sizeof(console_si);
/* setup a view arguments for wineconsole (it'll use them as default values) */
if (app_si.dwFlags & STARTF_USECOUNTCHARS)
{
console_si.dwFlags |= STARTF_USECOUNTCHARS;
console_si.dwXCountChars = app_si.dwXCountChars;
console_si.dwYCountChars = app_si.dwYCountChars;
}
if (app_si.dwFlags & STARTF_USEFILLATTRIBUTE)
{
console_si.dwFlags |= STARTF_USEFILLATTRIBUTE;
console_si.dwFillAttribute = app_si.dwFillAttribute;
}
if (app_si.dwFlags & STARTF_USESHOWWINDOW)
{
console_si.dwFlags |= STARTF_USESHOWWINDOW;
console_si.wShowWindow = app_si.wShowWindow;
}
if (app_si.lpTitle)
console_si.lpTitle = app_si.lpTitle;
else if (GetModuleFileNameW(0, buffer, ARRAY_SIZE(buffer)))
{
buffer[ARRAY_SIZE(buffer) - 1] = 0;
console_si.lpTitle = buffer;
}
if (!(event = CreateEventW( &inheritable_attr, TRUE, FALSE, NULL ))) return FALSE;
swprintf( cmd, ARRAY_SIZE(cmd), L"wineconsole --use-event=%ld", (DWORD_PTR)event );
if ((ret = CreateProcessW( NULL, cmd, NULL, NULL, TRUE, DETACHED_PROCESS, NULL, NULL, &console_si, &pi )))
{
HANDLE wait_handles[2] = { event, pi.hProcess };
ret = WaitForMultipleObjects( ARRAY_SIZE(wait_handles), wait_handles, FALSE, INFINITE ) == WAIT_OBJECT_0;
CloseHandle( pi.hThread );
CloseHandle( pi.hProcess );
}
CloseHandle( event );
if (!ret) goto error;
TRACE( "Started wineconsole pid=%08x tid=%08x\n", pi.dwProcessId, pi.dwThreadId );
if (!(app_si.dwFlags & STARTF_USESTDHANDLES))
{
std_in = CreateFileW( L"CONIN$", GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 0, &inheritable_attr,
OPEN_EXISTING, 0, 0);
if (std_in == INVALID_HANDLE_VALUE) goto error;
std_out = CreateFileW( L"CONOUT$", GENERIC_READ | GENERIC_WRITE, 0, &inheritable_attr, OPEN_EXISTING, 0, 0);
if (std_out == INVALID_HANDLE_VALUE) goto error;
if (!DuplicateHandle( GetCurrentProcess(), std_out, GetCurrentProcess(),
&std_err, 0, TRUE, DUPLICATE_SAME_ACCESS) )
goto error;
}
else
{
std_in = app_si.hStdInput;
std_out = app_si.hStdOutput;
std_err = app_si.hStdError;
}
SetStdHandle( STD_INPUT_HANDLE, std_in );
SetStdHandle( STD_OUTPUT_HANDLE, std_out );
SetStdHandle( STD_ERROR_HANDLE, std_err );
SetLastError( ERROR_SUCCESS );
return TRUE;
error:
ERR("Can't allocate console\n");
if (std_in != INVALID_HANDLE_VALUE) CloseHandle(std_in);
if (std_out != INVALID_HANDLE_VALUE) CloseHandle(std_out);
if (std_err != INVALID_HANDLE_VALUE) CloseHandle(std_err);
FreeConsole();
return FALSE;
}
/****************************************************************************** /******************************************************************************
* CreateConsoleScreenBuffer (kernelbase.@) * CreateConsoleScreenBuffer (kernelbase.@)
*/ */

View File

@ -29,7 +29,7 @@
@ stdcall AddVectoredExceptionHandler(long ptr) ntdll.RtlAddVectoredExceptionHandler @ stdcall AddVectoredExceptionHandler(long ptr) ntdll.RtlAddVectoredExceptionHandler
@ stdcall AdjustTokenGroups(long long ptr long ptr ptr) @ stdcall AdjustTokenGroups(long long ptr long ptr ptr)
@ stdcall AdjustTokenPrivileges(long long ptr long ptr ptr) @ stdcall AdjustTokenPrivileges(long long ptr long ptr ptr)
@ stdcall AllocConsole() kernel32.AllocConsole @ stdcall AllocConsole()
@ stdcall AllocateAndInitializeSid(ptr long long long long long long long long long ptr) @ stdcall AllocateAndInitializeSid(ptr long long long long long long long long long ptr)
@ stdcall AllocateLocallyUniqueId(ptr) @ stdcall AllocateLocallyUniqueId(ptr)
@ stdcall AllocateUserPhysicalPages(long ptr ptr) @ stdcall AllocateUserPhysicalPages(long ptr ptr)