2 * Windows support module which deals with being a named-pipe server.
8 #define DEFINE_PLUG_METHOD_MACROS
15 #if !defined NO_SECURITY
19 Socket make_handle_socket(HANDLE send_H, HANDLE recv_H, Plug plug,
22 typedef struct Socket_named_pipe_server_tag *Named_Pipe_Server_Socket;
23 struct Socket_named_pipe_server_tag {
24 const struct socket_function_table *fn;
25 /* the above variable absolutely *must* be the first in this structure */
27 /* Parameters for (repeated) creation of named pipe objects */
28 PSECURITY_DESCRIPTOR psd;
32 /* The current named pipe object + attempt to connect to it */
34 OVERLAPPED connect_ovl;
35 struct handle *callback_handle; /* winhandl.c's reference */
37 /* PuTTY Socket machinery */
42 static Plug sk_namedpipeserver_plug(Socket s, Plug p)
44 Named_Pipe_Server_Socket ps = (Named_Pipe_Server_Socket) s;
51 static void sk_namedpipeserver_close(Socket s)
53 Named_Pipe_Server_Socket ps = (Named_Pipe_Server_Socket) s;
55 if (ps->callback_handle)
56 handle_free(ps->callback_handle);
57 CloseHandle(ps->pipehandle);
58 CloseHandle(ps->connect_ovl.hEvent);
68 static const char *sk_namedpipeserver_socket_error(Socket s)
70 Named_Pipe_Server_Socket ps = (Named_Pipe_Server_Socket) s;
74 static char *sk_namedpipeserver_peer_info(Socket s)
79 static int create_named_pipe(Named_Pipe_Server_Socket ps, int first_instance)
81 SECURITY_ATTRIBUTES sa;
83 memset(&sa, 0, sizeof(sa));
84 sa.nLength = sizeof(sa);
85 sa.lpSecurityDescriptor = ps->psd;
86 sa.bInheritHandle = FALSE;
88 ps->pipehandle = CreateNamedPipe
94 FILE_FLAG_OVERLAPPED |
95 (first_instance ? FILE_FLAG_FIRST_PIPE_INSTANCE : 0),
98 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT
99 #ifdef PIPE_REJECT_REMOTE_CLIENTS
100 | PIPE_REJECT_REMOTE_CLIENTS
105 PIPE_UNLIMITED_INSTANCES,
107 /* nOutBufferSize, nInBufferSize */
108 4096, 4096, /* FIXME: think harder about buffer sizes? */
110 /* nDefaultTimeOut */
111 0 /* default timeout */,
113 /* lpSecurityAttributes */
116 return ps->pipehandle != INVALID_HANDLE_VALUE;
119 static Socket named_pipe_accept(accept_ctx_t ctx, Plug plug)
121 HANDLE conn = (HANDLE)ctx.p;
123 return make_handle_socket(conn, conn, plug, TRUE);
127 * Dummy SockAddr type which just holds a named pipe address. Only
128 * used for calling plug_log from named_pipe_accept_loop() here.
130 SockAddr sk_namedpipe_addr(const char *pipename);
132 static void named_pipe_accept_loop(Named_Pipe_Server_Socket ps,
139 if (got_one_already) {
140 /* If we were called with a connection already waiting,
142 got_one_already = FALSE;
146 * Call ConnectNamedPipe, which might succeed or might
147 * tell us that an overlapped operation is in progress and
148 * we should wait for our event object.
150 if (ConnectNamedPipe(ps->pipehandle, &ps->connect_ovl))
153 error = GetLastError();
155 if (error == ERROR_IO_PENDING)
159 if (error == 0 || error == ERROR_PIPE_CONNECTED) {
161 * We've successfully retrieved an incoming connection, so
162 * ps->pipehandle now refers to that connection. So
163 * convert that handle into a separate connection-type
164 * Socket, and create a fresh one to be the new listening
167 HANDLE conn = ps->pipehandle;
170 actx.p = (void *)conn;
171 if (plug_accepting(ps->plug, named_pipe_accept, actx)) {
173 * If the plug didn't want the connection, might as
174 * well close this handle.
179 if (!create_named_pipe(ps, FALSE)) {
180 error = GetLastError();
183 * Go round again to see if more connections can be
184 * got, or to begin waiting on the event object.
190 errmsg = dupprintf("Error while listening to named pipe: %s",
191 win_strerror(error));
192 plug_log(ps->plug, 1, sk_namedpipe_addr(ps->pipename), 0,
199 static void named_pipe_connect_callback(void *vps)
201 Named_Pipe_Server_Socket ps = (Named_Pipe_Server_Socket)vps;
202 named_pipe_accept_loop(ps, TRUE);
205 Socket new_named_pipe_listener(const char *pipename, Plug plug)
208 * This socket type is only used for listening, so it should never
209 * be asked to write or flush or set_frozen.
211 static const struct socket_function_table socket_fn_table = {
212 sk_namedpipeserver_plug,
213 sk_namedpipeserver_close,
215 NULL /* write_oob */,
216 NULL /* write_eof */,
218 NULL /* set_frozen */,
219 sk_namedpipeserver_socket_error,
220 sk_namedpipeserver_peer_info,
223 Named_Pipe_Server_Socket ret;
225 ret = snew(struct Socket_named_pipe_server_tag);
226 ret->fn = &socket_fn_table;
230 ret->pipename = dupstr(pipename);
232 ret->callback_handle = NULL;
234 assert(strncmp(pipename, "\\\\.\\pipe\\", 9) == 0);
235 assert(strchr(pipename + 9, '\\') == NULL);
237 if (!make_private_security_descriptor(GENERIC_READ | GENERIC_WRITE,
238 &ret->psd, &ret->acl, &ret->error)) {
242 if (!create_named_pipe(ret, TRUE)) {
243 ret->error = dupprintf("unable to create named pipe '%s': %s",
244 pipename, win_strerror(GetLastError()));
248 memset(&ret->connect_ovl, 0, sizeof(ret->connect_ovl));
249 ret->connect_ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
250 ret->callback_handle =
251 handle_add_foreign_event(ret->connect_ovl.hEvent,
252 named_pipe_connect_callback, ret);
253 named_pipe_accept_loop(ret, FALSE);
259 #endif /* !defined NO_SECURITY */