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
;
36 /* PuTTY Socket machinery */
41 static Plug
sk_namedpipeserver_plug(Socket s
, Plug p
)
43 Named_Pipe_Server_Socket ps
= (Named_Pipe_Server_Socket
) s
;
50 static void sk_namedpipeserver_close(Socket s
)
52 Named_Pipe_Server_Socket ps
= (Named_Pipe_Server_Socket
) s
;
54 CloseHandle(ps
->pipehandle
);
55 CloseHandle(ps
->connect_ovl
.hEvent
);
65 static const char *sk_namedpipeserver_socket_error(Socket s
)
67 Named_Pipe_Server_Socket ps
= (Named_Pipe_Server_Socket
) s
;
71 static int create_named_pipe(Named_Pipe_Server_Socket ps
, int first_instance
)
73 SECURITY_ATTRIBUTES sa
;
75 memset(&sa
, 0, sizeof(sa
));
76 sa
.nLength
= sizeof(sa
);
77 sa
.lpSecurityDescriptor
= ps
->psd
;
78 sa
.bInheritHandle
= FALSE
;
80 ps
->pipehandle
= CreateNamedPipe
86 FILE_FLAG_OVERLAPPED
|
87 (first_instance
? FILE_FLAG_FIRST_PIPE_INSTANCE
: 0),
90 PIPE_TYPE_BYTE
| PIPE_READMODE_BYTE
| PIPE_WAIT
91 #ifdef PIPE_REJECT_REMOTE_CLIENTS
92 | PIPE_REJECT_REMOTE_CLIENTS
97 PIPE_UNLIMITED_INSTANCES
,
99 /* nOutBufferSize, nInBufferSize */
100 4096, 4096, /* FIXME: think harder about buffer sizes? */
102 /* nDefaultTimeOut */
103 0 /* default timeout */,
105 /* lpSecurityAttributes */
108 return ps
->pipehandle
!= INVALID_HANDLE_VALUE
;
111 static Socket
named_pipe_accept(accept_ctx_t ctx
, Plug plug
)
113 HANDLE conn
= (HANDLE
)ctx
.p
;
115 return make_handle_socket(conn
, conn
, plug
, TRUE
);
119 * Dummy SockAddr type which just holds a named pipe address. Only
120 * used for calling plug_log from named_pipe_accept_loop() here.
122 SockAddr
sk_namedpipe_addr(const char *pipename
);
124 static void named_pipe_accept_loop(Named_Pipe_Server_Socket ps
,
131 if (got_one_already
) {
132 /* If we were called with a connection already waiting,
134 got_one_already
= FALSE
;
138 * Call ConnectNamedPipe, which might succeed or might
139 * tell us that an overlapped operation is in progress and
140 * we should wait for our event object.
142 if (ConnectNamedPipe(ps
->pipehandle
, &ps
->connect_ovl
))
145 error
= GetLastError();
147 if (error
== ERROR_IO_PENDING
)
151 if (error
== 0 || error
== ERROR_PIPE_CONNECTED
) {
153 * We've successfully retrieved an incoming connection, so
154 * ps->pipehandle now refers to that connection. So
155 * convert that handle into a separate connection-type
156 * Socket, and create a fresh one to be the new listening
159 HANDLE conn
= ps
->pipehandle
;
162 actx
.p
= (void *)conn
;
163 if (plug_accepting(ps
->plug
, named_pipe_accept
, actx
)) {
165 * If the plug didn't want the connection, might as
166 * well close this handle.
171 if (!create_named_pipe(ps
, FALSE
)) {
172 error
= GetLastError();
175 * Go round again to see if more connections can be
176 * got, or to begin waiting on the event object.
182 errmsg
= dupprintf("Error while listening to named pipe: %s",
183 win_strerror(error
));
184 plug_log(ps
->plug
, 1, sk_namedpipe_addr(ps
->pipename
), 0,
191 static void named_pipe_connect_callback(void *vps
)
193 Named_Pipe_Server_Socket ps
= (Named_Pipe_Server_Socket
)vps
;
194 named_pipe_accept_loop(ps
, TRUE
);
197 Socket
new_named_pipe_listener(const char *pipename
, Plug plug
)
200 * This socket type is only used for listening, so it should never
201 * be asked to write or flush or set_frozen.
203 static const struct socket_function_table socket_fn_table
= {
204 sk_namedpipeserver_plug
,
205 sk_namedpipeserver_close
,
207 NULL
/* write_oob */,
208 NULL
/* write_eof */,
210 NULL
/* set_frozen */,
211 sk_namedpipeserver_socket_error
214 Named_Pipe_Server_Socket ret
;
216 ret
= snew(struct Socket_named_pipe_server_tag
);
217 ret
->fn
= &socket_fn_table
;
221 ret
->pipename
= dupstr(pipename
);
224 assert(strncmp(pipename
, "\\\\.\\pipe\\", 9) == 0);
225 assert(strchr(pipename
+ 9, '\\') == NULL
);
227 if (!make_private_security_descriptor(GENERIC_READ
| GENERIC_WRITE
,
228 &ret
->psd
, &ret
->acl
, &ret
->error
)) {
232 if (!create_named_pipe(ret
, TRUE
)) {
233 ret
->error
= dupprintf("unable to create named pipe '%s': %s",
234 pipename
, win_strerror(GetLastError()));
238 memset(&ret
->connect_ovl
, 0, sizeof(ret
->connect_ovl
));
239 ret
->connect_ovl
.hEvent
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
240 handle_add_foreign_event(ret
->connect_ovl
.hEvent
,
241 named_pipe_connect_callback
, ret
);
242 named_pipe_accept_loop(ret
, FALSE
);
248 #endif /* !defined NO_SECURITY */