Created
August 5, 2018 13:46
-
-
Save aspann/f37f48015fe910e763f52d7f3844b661 to your computer and use it in GitHub Desktop.
wine3.13_battle-net.patch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @@ -, +, @@ | |
| kernel32: Add AttachConsole implementation. | |
| --- a/dlls/kernel32/console.c | |
| +++ a/dlls/kernel32/console.c | |
| @@ -2909,8 +2909,23 @@ BOOL WINAPI ScrollConsoleScreenBufferW(HANDLE hConsoleOutput, LPSMALL_RECT lpScr | |
| */ | |
| BOOL WINAPI AttachConsole(DWORD dwProcessId) | |
| { | |
| - FIXME("stub %x\n",dwProcessId); | |
| - return TRUE; | |
| + BOOL ret; | |
| + | |
| + TRACE("(%x)\n", dwProcessId); | |
| + | |
| + SERVER_START_REQ( attach_console ) | |
| + { | |
| + req->pid = dwProcessId; | |
| + ret = !wine_server_call_err( req ); | |
| + if (ret) | |
| + { | |
| + SetStdHandle(STD_INPUT_HANDLE, wine_server_ptr_handle(reply->std_in)); | |
| + SetStdHandle(STD_OUTPUT_HANDLE, wine_server_ptr_handle(reply->std_out)); | |
| + SetStdHandle(STD_ERROR_HANDLE, wine_server_ptr_handle(reply->std_err)); | |
| + } | |
| + } | |
| + SERVER_END_REQ; | |
| + return ret; | |
| } | |
| /****************************************************************** | |
| --- a/dlls/kernel32/tests/console.c | |
| +++ a/dlls/kernel32/tests/console.c | |
| @@ -208,19 +208,29 @@ static void testEmptyWrite(HANDLE hCon) | |
| okCURSOR(hCon, c); | |
| } | |
| -static void testWriteSimple(HANDLE hCon) | |
| +static void simple_write_console(HANDLE console, const char *text) | |
| { | |
| - COORD c; | |
| - DWORD len; | |
| - const char* mytest = "abcdefg"; | |
| - const int mylen = strlen(mytest); | |
| + DWORD len; | |
| + COORD c = {0, 0}; | |
| + BOOL ret; | |
| /* single line write */ | |
| c.X = c.Y = 0; | |
| - ok(SetConsoleCursorPosition(hCon, c) != 0, "Cursor in upper-left\n"); | |
| + ok(SetConsoleCursorPosition(console, c) != 0, "Cursor in upper-left\n"); | |
| + | |
| + ret = WriteConsoleA(console, text, strlen(text), &len, NULL); | |
| + ok(ret, "WriteConsoleA failed: %u\n", GetLastError()); | |
| + ok(len == strlen(text), "unexpected len %u\n", len); | |
| +} | |
| + | |
| +static void testWriteSimple(HANDLE hCon) | |
| +{ | |
| + const char* mytest = "abcdefg"; | |
| + int mylen = strlen(mytest); | |
| + COORD c = {0, 0}; | |
| + | |
| + simple_write_console(hCon, mytest); | |
| - ok(WriteConsoleA(hCon, mytest, mylen, &len, NULL) != 0 && len == mylen, "WriteConsole\n"); | |
| - c.Y = 0; | |
| for (c.X = 0; c.X < mylen; c.X++) | |
| { | |
| okCHAR(hCon, c, mytest[c.X], TEST_ATTRIB); | |
| @@ -3019,6 +3029,98 @@ static void test_GetConsoleScreenBufferInfoEx(HANDLE std_output) | |
| ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError()); | |
| } | |
| +static void test_AttachConsole_child(DWORD console_pid) | |
| +{ | |
| + HANDLE pipe_in, pipe_out; | |
| + COORD c = {0,0}; | |
| + HANDLE console; | |
| + char buf[32]; | |
| + DWORD len; | |
| + BOOL res; | |
| + | |
| + res = CreatePipe(&pipe_in, &pipe_out, NULL, 0); | |
| + ok(res, "CreatePipe failed: %u\n", GetLastError()); | |
| + | |
| + res = AttachConsole(console_pid); | |
| + ok(!res && GetLastError() == ERROR_ACCESS_DENIED, | |
| + "AttachConsole returned: %x(%u)\n", res, GetLastError()); | |
| + | |
| + res = FreeConsole(); | |
| + ok(res, "FreeConsole failed: %u\n", GetLastError()); | |
| + | |
| + SetStdHandle(STD_ERROR_HANDLE, pipe_out); | |
| + | |
| + res = AttachConsole(console_pid); | |
| + ok(res, "AttachConsole failed: %u\n", GetLastError()); | |
| + | |
| + ok(pipe_out != GetStdHandle(STD_ERROR_HANDLE), "std handle not set to console\n"); | |
| + | |
| + console = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); | |
| + ok(console != INVALID_HANDLE_VALUE, "Could not open console\n"); | |
| + | |
| + res = ReadConsoleOutputCharacterA(console, buf, 6, c, &len); | |
| + ok(res, "ReadConsoleOutputCharacterA failed: %u\n", GetLastError()); | |
| + ok(len == 6, "len = %u\n", len); | |
| + ok(!memcmp(buf, "Parent", 6), "Unexpected console output\n"); | |
| + | |
| + res = FreeConsole(); | |
| + ok(res, "FreeConsole failed: %u\n", GetLastError()); | |
| + | |
| + SetStdHandle(STD_INPUT_HANDLE, pipe_in); | |
| + SetStdHandle(STD_OUTPUT_HANDLE, pipe_out); | |
| + | |
| + res = AttachConsole(ATTACH_PARENT_PROCESS); | |
| + ok(res, "AttachConsole failed: %u\n", GetLastError()); | |
| + | |
| + ok(pipe_in != GetStdHandle(STD_INPUT_HANDLE), "std handle not set to console\n"); | |
| + ok(pipe_out != GetStdHandle(STD_OUTPUT_HANDLE), "std handle not set to console\n"); | |
| + | |
| + console = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0); | |
| + ok(console != INVALID_HANDLE_VALUE, "Could not open console\n"); | |
| + | |
| + res = ReadConsoleOutputCharacterA(console, buf, 6, c, &len); | |
| + ok(res, "ReadConsoleOutputCharacterA failed: %u\n", GetLastError()); | |
| + ok(len == 6, "len = %u\n", len); | |
| + ok(!memcmp(buf, "Parent", 6), "Unexpected console output\n"); | |
| + | |
| + simple_write_console(console, "Child"); | |
| + CloseHandle(console); | |
| + | |
| + res = FreeConsole(); | |
| + ok(res, "FreeConsole failed: %u\n", GetLastError()); | |
| + | |
| + res = CloseHandle(pipe_in); | |
| + ok(res, "pipe_in is no longer valid\n"); | |
| + res = CloseHandle(pipe_out); | |
| + ok(res, "pipe_out is no longer valid\n"); | |
| +} | |
| + | |
| +static void test_AttachConsole(HANDLE console) | |
| +{ | |
| + STARTUPINFOA si = { sizeof(si) }; | |
| + PROCESS_INFORMATION info; | |
| + char **argv, buf[MAX_PATH]; | |
| + COORD c = {0,0}; | |
| + DWORD len; | |
| + BOOL res; | |
| + | |
| + simple_write_console(console, "Parent console"); | |
| + | |
| + winetest_get_mainargs(&argv); | |
| + sprintf(buf, "\"%s\" console attach_console %x", argv[0], GetCurrentProcessId()); | |
| + res = CreateProcessA(NULL, buf, NULL, NULL, TRUE, 0, NULL, NULL, &si, &info); | |
| + ok(res, "CreateProcess failed: %u\n", GetLastError()); | |
| + CloseHandle(info.hThread); | |
| + | |
| + winetest_wait_child_process(info.hProcess); | |
| + CloseHandle(info.hProcess); | |
| + | |
| + res = ReadConsoleOutputCharacterA(console, buf, 5, c, &len); | |
| + ok(res, "ReadConsoleOutputCharacterA failed: %u\n", GetLastError()); | |
| + ok(len == 5, "len = %u\n", len); | |
| + ok(!memcmp(buf, "Child", 5), "Unexpected console output\n"); | |
| +} | |
| + | |
| START_TEST(console) | |
| { | |
| static const char font_name[] = "Lucida Console"; | |
| @@ -3030,9 +3132,21 @@ START_TEST(console) | |
| char old_font[LF_FACESIZE]; | |
| BOOL delete = FALSE; | |
| DWORD size; | |
| + char **argv; | |
| + int argc; | |
| init_function_pointers(); | |
| + argc = winetest_get_mainargs(&argv); | |
| + | |
| + if (argc > 3 && !strcmp(argv[2], "attach_console")) | |
| + { | |
| + DWORD parent_pid; | |
| + sscanf(argv[3], "%x", &parent_pid); | |
| + test_AttachConsole_child(parent_pid); | |
| + return; | |
| + } | |
| + | |
| /* be sure we have a clean console (and that's our own) | |
| * FIXME: this will make the test fail (currently) if we don't run | |
| * under X11 | |
| @@ -3170,4 +3284,5 @@ START_TEST(console) | |
| test_GetConsoleFontInfo(hConOut); | |
| test_SetConsoleFont(hConOut); | |
| test_GetConsoleScreenBufferInfoEx(hConOut); | |
| + test_AttachConsole(hConOut); | |
| } | |
| --- a/include/wine/server_protocol.h | |
| +++ a/include/wine/server_protocol.h | |
| @@ -1839,6 +1839,22 @@ struct open_console_reply | |
| +struct attach_console_request | |
| +{ | |
| + struct request_header __header; | |
| + process_id_t pid; | |
| +}; | |
| +struct attach_console_reply | |
| +{ | |
| + struct reply_header __header; | |
| + obj_handle_t std_in; | |
| + obj_handle_t std_out; | |
| + obj_handle_t std_err; | |
| + char __pad_20[4]; | |
| +}; | |
| + | |
| + | |
| + | |
| struct get_console_wait_event_request | |
| { | |
| struct request_header __header; | |
| @@ -5697,6 +5713,7 @@ enum request | |
| REQ_free_console, | |
| REQ_get_console_renderer_events, | |
| REQ_open_console, | |
| + REQ_attach_console, | |
| REQ_get_console_wait_event, | |
| REQ_get_console_mode, | |
| REQ_set_console_mode, | |
| @@ -5993,6 +6010,7 @@ union generic_request | |
| struct free_console_request free_console_request; | |
| struct get_console_renderer_events_request get_console_renderer_events_request; | |
| struct open_console_request open_console_request; | |
| + struct attach_console_request attach_console_request; | |
| struct get_console_wait_event_request get_console_wait_event_request; | |
| struct get_console_mode_request get_console_mode_request; | |
| struct set_console_mode_request set_console_mode_request; | |
| @@ -6287,6 +6305,7 @@ union generic_reply | |
| struct free_console_reply free_console_reply; | |
| struct get_console_renderer_events_reply get_console_renderer_events_reply; | |
| struct open_console_reply open_console_reply; | |
| + struct attach_console_reply attach_console_reply; | |
| struct get_console_wait_event_reply get_console_wait_event_reply; | |
| struct get_console_mode_reply get_console_mode_reply; | |
| struct set_console_mode_reply set_console_mode_reply; | |
| @@ -6514,6 +6533,6 @@ union generic_reply | |
| struct terminate_job_reply terminate_job_reply; | |
| }; | |
| -#define SERVER_PROTOCOL_VERSION 555 | |
| +#define SERVER_PROTOCOL_VERSION 560 | |
| #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ | |
| --- a/server/console.c | |
| +++ a/server/console.c | |
| @@ -1546,6 +1546,49 @@ DECL_HANDLER(open_console) | |
| else if (!get_error()) set_error( STATUS_ACCESS_DENIED ); | |
| } | |
| +/* attach to a other process's console */ | |
| +DECL_HANDLER(attach_console) | |
| +{ | |
| + struct process *process; | |
| + | |
| + if (current->process->console) | |
| + { | |
| + set_error( STATUS_ACCESS_DENIED ); | |
| + return; | |
| + } | |
| + | |
| + process = get_process_from_id( req->pid == ATTACH_PARENT_PROCESS | |
| + ? current->process->parent_id : req->pid ); | |
| + if (!process) return; | |
| + | |
| + if (process->console && process->console->active ) | |
| + { | |
| + reply->std_in = alloc_handle( current->process, process->console, GENERIC_READ, 0 ); | |
| + if (!reply->std_in) goto error; | |
| + | |
| + reply->std_out = alloc_handle( current->process, process->console->active, GENERIC_WRITE, 0 ); | |
| + if (!reply->std_out) goto error; | |
| + | |
| + reply->std_err = alloc_handle( current->process, process->console->active, GENERIC_WRITE, 0 ); | |
| + if (!reply->std_err) goto error; | |
| + | |
| + current->process->console = (struct console_input*)grab_object( process->console ); | |
| + current->process->console->num_proc++; | |
| + } | |
| + else | |
| + { | |
| + set_error( STATUS_INVALID_HANDLE ); | |
| + } | |
| + | |
| + release_object( process ); | |
| + return; | |
| + | |
| +error: | |
| + if (reply->std_in) close_handle( current->process, reply->std_in); | |
| + if (reply->std_out) close_handle( current->process, reply->std_out); | |
| + release_object( process ); | |
| +} | |
| + | |
| /* set info about a console input */ | |
| DECL_HANDLER(set_console_input_info) | |
| { | |
| --- a/server/protocol.def | |
| +++ a/server/protocol.def | |
| @@ -1463,6 +1463,16 @@ struct console_renderer_event | |
| @END | |
| +/* Attach to a other process's console */ | |
| +@REQ(attach_console) | |
| + process_id_t pid; /* pid of attached console process */ | |
| +@REPLY | |
| + obj_handle_t std_in; /* attached stdin */ | |
| + obj_handle_t std_out; /* attached stdout */ | |
| + obj_handle_t std_err; /* attached stderr */ | |
| +@END | |
| + | |
| + | |
| /* Get the input queue wait event */ | |
| @REQ(get_console_wait_event) | |
| @REPLY | |
| --- a/server/request.h | |
| +++ a/server/request.h | |
| @@ -176,6 +176,7 @@ DECL_HANDLER(alloc_console); | |
| DECL_HANDLER(free_console); | |
| DECL_HANDLER(get_console_renderer_events); | |
| DECL_HANDLER(open_console); | |
| +DECL_HANDLER(attach_console); | |
| DECL_HANDLER(get_console_wait_event); | |
| DECL_HANDLER(get_console_mode); | |
| DECL_HANDLER(set_console_mode); | |
| @@ -471,6 +472,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = | |
| (req_handler)req_free_console, | |
| (req_handler)req_get_console_renderer_events, | |
| (req_handler)req_open_console, | |
| + (req_handler)req_attach_console, | |
| (req_handler)req_get_console_wait_event, | |
| (req_handler)req_get_console_mode, | |
| (req_handler)req_set_console_mode, | |
| @@ -1120,6 +1122,12 @@ C_ASSERT( FIELD_OFFSET(struct open_console_request, share) == 24 ); | |
| C_ASSERT( sizeof(struct open_console_request) == 32 ); | |
| C_ASSERT( FIELD_OFFSET(struct open_console_reply, handle) == 8 ); | |
| C_ASSERT( sizeof(struct open_console_reply) == 16 ); | |
| +C_ASSERT( FIELD_OFFSET(struct attach_console_request, pid) == 12 ); | |
| +C_ASSERT( sizeof(struct attach_console_request) == 16 ); | |
| +C_ASSERT( FIELD_OFFSET(struct attach_console_reply, std_in) == 8 ); | |
| +C_ASSERT( FIELD_OFFSET(struct attach_console_reply, std_out) == 12 ); | |
| +C_ASSERT( FIELD_OFFSET(struct attach_console_reply, std_err) == 16 ); | |
| +C_ASSERT( sizeof(struct attach_console_reply) == 24 ); | |
| C_ASSERT( sizeof(struct get_console_wait_event_request) == 16 ); | |
| C_ASSERT( FIELD_OFFSET(struct get_console_wait_event_reply, handle) == 8 ); | |
| C_ASSERT( sizeof(struct get_console_wait_event_reply) == 16 ); | |
| --- a/server/trace.c | |
| +++ a/server/trace.c | |
| @@ -1989,6 +1989,18 @@ static void dump_open_console_reply( const struct open_console_reply *req ) | |
| fprintf( stderr, " handle=%04x", req->handle ); | |
| } | |
| +static void dump_attach_console_request( const struct attach_console_request *req ) | |
| +{ | |
| + fprintf( stderr, " pid=%04x", req->pid ); | |
| +} | |
| + | |
| +static void dump_attach_console_reply( const struct attach_console_reply *req ) | |
| +{ | |
| + fprintf( stderr, " std_in=%04x", req->std_in ); | |
| + fprintf( stderr, ", std_out=%04x", req->std_out ); | |
| + fprintf( stderr, ", std_err=%04x", req->std_err ); | |
| +} | |
| + | |
| static void dump_get_console_wait_event_request( const struct get_console_wait_event_request *req ) | |
| { | |
| } | |
| @@ -4595,6 +4607,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { | |
| (dump_func)dump_free_console_request, | |
| (dump_func)dump_get_console_renderer_events_request, | |
| (dump_func)dump_open_console_request, | |
| + (dump_func)dump_attach_console_request, | |
| (dump_func)dump_get_console_wait_event_request, | |
| (dump_func)dump_get_console_mode_request, | |
| (dump_func)dump_set_console_mode_request, | |
| @@ -4887,6 +4900,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { | |
| NULL, | |
| (dump_func)dump_get_console_renderer_events_reply, | |
| (dump_func)dump_open_console_reply, | |
| + (dump_func)dump_attach_console_reply, | |
| (dump_func)dump_get_console_wait_event_reply, | |
| (dump_func)dump_get_console_mode_reply, | |
| NULL, | |
| @@ -5179,6 +5193,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { | |
| "free_console", | |
| "get_console_renderer_events", | |
| "open_console", | |
| + "attach_console", | |
| "get_console_wait_event", | |
| "get_console_mode", | |
| "set_console_mode", |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment