X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=windows%2Fwinhsock.c;h=8acb82be61b5493195c26e1600d03b62878a295e;hb=23fbc4f56b04ca5d387c16720caa05ddf2d63e2f;hp=6b088bb8217336d10cb693e311d1ec99be600402;hpb=c8f83979a368d10e8def1796cdadd7f8f3bebf74;p=PuTTY.git diff --git a/windows/winhsock.c b/windows/winhsock.c index 6b088bb8..8acb82be 100644 --- a/windows/winhsock.c +++ b/windows/winhsock.c @@ -18,8 +18,8 @@ struct Socket_handle_tag { const struct socket_function_table *fn; /* the above variable absolutely *must* be the first in this structure */ - HANDLE send_H, recv_H; - struct handle *send_h, *recv_h; + HANDLE send_H, recv_H, stderr_H; + struct handle *send_h, *recv_h, *stderr_h; /* * Freezing one of these sockets is a slightly fiddly business, @@ -39,6 +39,11 @@ struct Socket_handle_tag { /* We buffer data here if we receive it from winhandl while frozen. */ bufchain inputdata; + /* Data received from stderr_H, if we have one. */ + bufchain stderrdata; + + int defer_close, deferred_close; /* in case of re-entrance */ + char *error; Plug plug; @@ -54,7 +59,7 @@ static int handle_gotdata(struct handle *h, void *data, int len) } else if (len == 0) { return plug_closing(ps->plug, NULL, 0, 0); } else { - assert(ps->frozen != FREEZING && ps->frozen != THAWING); + assert(ps->frozen != FROZEN && ps->frozen != THAWING); if (ps->frozen == FREEZING) { /* * If we've received data while this socket is supposed to @@ -63,6 +68,7 @@ static int handle_gotdata(struct handle *h, void *data, int len) * the data for when we unfreeze. */ bufchain_add(&ps->inputdata, data, len); + ps->frozen = FROZEN; /* * And return a very large backlog, to prevent further @@ -75,6 +81,16 @@ static int handle_gotdata(struct handle *h, void *data, int len) } } +static int handle_stderr(struct handle *h, void *data, int len) +{ + Handle_Socket ps = (Handle_Socket) handle_get_privdata(h); + + if (len > 0) + log_proxy_stderr(ps->plug, &ps->stderrdata, data, len); + + return 0; +} + static void handle_sentdata(struct handle *h, int new_backlog) { Handle_Socket ps = (Handle_Socket) handle_get_privdata(h); @@ -95,12 +111,18 @@ static void sk_handle_close(Socket s) { Handle_Socket ps = (Handle_Socket) s; + if (ps->defer_close) { + ps->deferred_close = TRUE; + return; + } + handle_free(ps->send_h); handle_free(ps->recv_h); CloseHandle(ps->send_H); if (ps->recv_H != ps->send_H) CloseHandle(ps->recv_H); bufchain_clear(&ps->inputdata); + bufchain_clear(&ps->stderrdata); sfree(ps); } @@ -154,9 +176,17 @@ static void handle_socket_unfreeze(void *psv) assert(len > 0); /* - * Hand it off to the plug. + * Hand it off to the plug. Be careful of re-entrance - that might + * have the effect of trying to close this socket. */ + ps->defer_close = TRUE; new_backlog = plug_receive(ps->plug, 0, data, len); + bufchain_consume(&ps->inputdata, len); + ps->defer_close = FALSE; + if (ps->deferred_close) { + sk_handle_close(ps); + return; + } if (bufchain_size(&ps->inputdata) > 0) { /* @@ -236,11 +266,31 @@ static const char *sk_handle_socket_error(Socket s) static char *sk_handle_peer_info(Socket s) { + Handle_Socket ps = (Handle_Socket) s; + ULONG pid; + static HMODULE kernel32_module; + DECL_WINDOWS_FUNCTION(static, BOOL, GetNamedPipeClientProcessId, + (HANDLE, PULONG)); + + if (!kernel32_module) { + kernel32_module = load_system32_dll("kernel32.dll"); + GET_WINDOWS_FUNCTION(kernel32_module, GetNamedPipeClientProcessId); + } + + /* + * Of course, not all handles managed by this module will be + * server ends of named pipes, but if they are, then it's useful + * to log what we can find out about the client end. + */ + if (p_GetNamedPipeClientProcessId && + p_GetNamedPipeClientProcessId(ps->send_H, &pid)) + return dupprintf("process id %lu", (unsigned long)pid); + return NULL; } -Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, Plug plug, - int overlapped) +Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, HANDLE stderr_H, + Plug plug, int overlapped) { static const struct socket_function_table socket_fn_table = { sk_handle_plug, @@ -263,11 +313,18 @@ Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, Plug plug, ret->error = NULL; ret->frozen = UNFROZEN; bufchain_init(&ret->inputdata); + bufchain_init(&ret->stderrdata); ret->recv_H = recv_H; ret->recv_h = handle_input_new(ret->recv_H, handle_gotdata, ret, flags); ret->send_H = send_H; ret->send_h = handle_output_new(ret->send_H, handle_sentdata, ret, flags); + ret->stderr_H = stderr_H; + if (ret->stderr_H) + ret->stderr_h = handle_input_new(ret->stderr_H, handle_stderr, + ret, flags); + + ret->defer_close = ret->deferred_close = FALSE; return (Socket) ret; }