diff --git a/errsock.c b/errsock.c index a01e7cad..fc1bb956 100644 --- a/errsock.c +++ b/errsock.c @@ -55,7 +55,7 @@ static const SocketVtable ErrorSocket_sockvt = { sk_error_peer_info, }; -static Socket *new_error_socket_internal(char *errmsg, Plug *plug) +Socket *new_error_socket_consume_string(Plug *plug, char *errmsg) { ErrorSocket *es = snew(ErrorSocket); es->sock.vt = &ErrorSocket_sockvt; @@ -73,5 +73,5 @@ Socket *new_error_socket_fmt(Plug *plug, const char *fmt, ...) msg = dupvprintf(fmt, ap); va_end(ap); - return new_error_socket_internal(msg, plug); + return new_error_socket_consume_string(plug, msg); } diff --git a/network.h b/network.h index 355da2b3..2cd91325 100644 --- a/network.h +++ b/network.h @@ -264,8 +264,12 @@ char *get_hostname(void); /* * Trivial socket implementation which just stores an error. Found in * errsock.c. + * + * The consume_string variant takes an already-formatted dynamically + * allocated string, and takes over ownership of that string. */ Socket *new_error_socket_fmt(Plug *plug, const char *fmt, ...); +Socket *new_error_socket_consume_string(Plug *plug, char *errmsg); /* * Trivial plug that does absolutely nothing. Found in nullplug.c. diff --git a/windows/winnpc.c b/windows/winnpc.c index 4fcb9e26..eabfb4bc 100644 --- a/windows/winnpc.c +++ b/windows/winnpc.c @@ -15,7 +15,7 @@ #include "winsecur.h" -Socket *new_named_pipe_client(const char *pipename, Plug *plug) +HANDLE connect_to_named_pipe(const char *pipename, char **err) { HANDLE pipehandle; PSID usersid, pipeowner; @@ -33,9 +33,10 @@ Socket *new_named_pipe_client(const char *pipename, Plug *plug) break; if (GetLastError() != ERROR_PIPE_BUSY) { - return new_error_socket_fmt( - plug, "Unable to open named pipe '%s': %s", + *err = dupprintf( + "Unable to open named pipe '%s': %s", pipename, win_strerror(GetLastError())); + return INVALID_HANDLE_VALUE; } /* @@ -46,16 +47,18 @@ Socket *new_named_pipe_client(const char *pipename, Plug *plug) * take excessively long.) */ if (!WaitNamedPipe(pipename, NMPWAIT_USE_DEFAULT_WAIT)) { - return new_error_socket_fmt( - plug, "Error waiting for named pipe '%s': %s", + *err = dupprintf( + "Error waiting for named pipe '%s': %s", pipename, win_strerror(GetLastError())); + return INVALID_HANDLE_VALUE; } } if ((usersid = get_user_sid()) == NULL) { CloseHandle(pipehandle); - return new_error_socket_fmt( - plug, "Unable to get user SID: %s", win_strerror(GetLastError())); + *err = dupprintf( + "Unable to get user SID: %s", win_strerror(GetLastError())); + return INVALID_HANDLE_VALUE; } if (p_GetSecurityInfo(pipehandle, SE_KERNEL_OBJECT, @@ -63,21 +66,33 @@ Socket *new_named_pipe_client(const char *pipename, Plug *plug) &pipeowner, NULL, NULL, NULL, &psd) != ERROR_SUCCESS) { CloseHandle(pipehandle); - return new_error_socket_fmt( - plug, "Unable to get named pipe security information: %s", + *err = dupprintf( + "Unable to get named pipe security information: %s", win_strerror(GetLastError())); + return INVALID_HANDLE_VALUE; } if (!EqualSid(pipeowner, usersid)) { CloseHandle(pipehandle); LocalFree(psd); - return new_error_socket_fmt( - plug, "Owner of named pipe '%s' is not us", pipename); + *err = dupprintf( + "Owner of named pipe '%s' is not us", pipename); + return INVALID_HANDLE_VALUE; } LocalFree(psd); - return make_handle_socket(pipehandle, pipehandle, NULL, plug, true); + return pipehandle; +} + +Socket *new_named_pipe_client(const char *pipename, Plug *plug) +{ + char *err = NULL; + HANDLE pipehandle = connect_to_named_pipe(pipename, &err); + if (pipehandle == INVALID_HANDLE_VALUE) + return new_error_socket_consume_string(plug, err); + else + return make_handle_socket(pipehandle, pipehandle, NULL, plug, true); } #endif /* !defined NO_SECURITY */ diff --git a/windows/winstuff.h b/windows/winstuff.h index 5acd215f..b6cce929 100644 --- a/windows/winstuff.h +++ b/windows/winstuff.h @@ -373,6 +373,12 @@ Socket *make_handle_socket(HANDLE send_H, HANDLE recv_H, HANDLE stderr_H, Socket *new_named_pipe_client(const char *pipename, Plug *plug); /* winnpc */ Socket *new_named_pipe_listener(const char *pipename, Plug *plug); /* winnps */ +/* A lower-level function in winnpc.c, which does most of the work of + * new_named_pipe_client (including checking the ownership of what + * it's connected to), but returns a plain HANDLE instead of wrapping + * it into a Socket. */ +HANDLE connect_to_named_pipe(const char *pipename, char **err); + /* * Exports from winctrls.c. */