3 Copyright 2001, 2002, 2003, 2004, 2009 Red Hat Inc.
5 Written by Robert Collins <rbtcollins@hotmail.com>
7 This file is part of Cygwin.
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
13 /* to allow this to link into cygwin and the .dll, a little magic is needed. */
14 #ifdef __OUTSIDE_CYGWIN__
21 #include <sys/types.h>
28 #include <sys/cygwin.h>
31 #include "transport.h"
32 #include "transport_pipes.h"
34 #ifndef __INSIDE_CYGWIN__
35 #include "cygserver.h"
36 #include "cygserver_ipc.h"
41 #ifdef __INSIDE_CYGWIN__
42 #define SET_ERRNO(err) set_errno (err)
44 #define SET_ERRNO(err) errno = (err)
49 MAX_WAIT_NAMED_PIPE_RETRY
= 64,
50 WAIT_NAMED_PIPE_TIMEOUT
= 10 // milliseconds
53 #ifndef __INSIDE_CYGWIN__
55 static pthread_once_t pipe_instance_lock_once
= PTHREAD_ONCE_INIT
;
56 static CRITICAL_SECTION pipe_instance_lock
;
57 static long pipe_instance
= 0;
60 initialise_pipe_instance_lock ()
62 assert (pipe_instance
== 0);
63 InitializeCriticalSection (&pipe_instance_lock
);
66 #endif /* !__INSIDE_CYGWIN__ */
68 #ifndef __INSIDE_CYGWIN__
70 transport_layer_pipes::transport_layer_pipes (const HANDLE hPipe
)
72 _is_accepted_endpoint (true),
73 _is_listening_endpoint (false)
76 assert (_hPipe
!= INVALID_HANDLE_VALUE
);
77 _pipe_name
[0] = L
'\0';
80 #endif /* !__INSIDE_CYGWIN__ */
82 transport_layer_pipes::transport_layer_pipes ()
84 _is_accepted_endpoint (false),
85 _is_listening_endpoint (false)
87 #ifdef __INSIDE_CYGWIN__
88 extern WCHAR installation_key_buf
[18];
89 wcpcpy (wcpcpy (wcpcpy (_pipe_name
, PIPE_NAME_PREFIX
), installation_key_buf
),
92 wchar_t cyg_instkey
[18];
94 wchar_t *p
= wcpcpy (_pipe_name
, PIPE_NAME_PREFIX
);
95 if (!cygwin_internal (CW_GET_INSTKEY
, cyg_instkey
))
96 wcpcpy (wcpcpy (p
, cyg_instkey
), PIPE_NAME_SUFFIX
);
100 transport_layer_pipes::~transport_layer_pipes ()
105 #ifndef __INSIDE_CYGWIN__
108 transport_layer_pipes::listen ()
111 assert (!_is_accepted_endpoint
);
112 assert (!_is_listening_endpoint
);
114 _is_listening_endpoint
= true;
120 class transport_layer_pipes
*
121 transport_layer_pipes::accept (bool *const recoverable
)
124 assert (!_is_accepted_endpoint
);
125 assert (_is_listening_endpoint
);
127 pthread_once (&pipe_instance_lock_once
, &initialise_pipe_instance_lock
);
129 EnterCriticalSection (&pipe_instance_lock
);
131 // Read: http://www.securityinternals.com/research/papers/namedpipe.php
132 // See also the Microsoft security bulletins MS00-053 and MS01-031.
134 // FIXME: Remove FILE_CREATE_PIPE_INSTANCE.
136 const bool first_instance
= (pipe_instance
== 0);
138 debug ("Try to create named pipe: %ls", _pipe_name
);
140 const HANDLE accept_pipe
=
141 CreateNamedPipeW (_pipe_name
,
143 | (first_instance
? FILE_FLAG_FIRST_PIPE_INSTANCE
: 0)),
144 (PIPE_TYPE_BYTE
| PIPE_WAIT
),
145 PIPE_UNLIMITED_INSTANCES
,
149 const bool duplicate
= (accept_pipe
== INVALID_HANDLE_VALUE
150 && pipe_instance
== 0
151 && GetLastError () == ERROR_ACCESS_DENIED
);
153 if (accept_pipe
!= INVALID_HANDLE_VALUE
)
154 InterlockedIncrement (&pipe_instance
);
156 LeaveCriticalSection (&pipe_instance_lock
);
160 *recoverable
= false;
161 system_printf ("failed to create named pipe: "
162 "is the daemon already running?");
166 if (accept_pipe
== INVALID_HANDLE_VALUE
)
168 debug_printf ("error creating pipe (%lu).", GetLastError ());
169 *recoverable
= true; // FIXME: case analysis?
173 assert (accept_pipe
);
175 if (!ConnectNamedPipe (accept_pipe
, NULL
)
176 && GetLastError () != ERROR_PIPE_CONNECTED
)
178 debug_printf ("error connecting to pipe (%lu)", GetLastError ());
179 (void) CloseHandle (accept_pipe
);
180 *recoverable
= true; // FIXME: case analysis?
184 return new transport_layer_pipes (accept_pipe
);
187 #endif /* !__INSIDE_CYGWIN__ */
190 transport_layer_pipes::close ()
192 // verbose: debug_printf ("closing pipe %p", _hPipe);
196 assert (_hPipe
!= INVALID_HANDLE_VALUE
);
198 #ifndef __INSIDE_CYGWIN__
200 if (_is_accepted_endpoint
)
202 (void) FlushFileBuffers (_hPipe
); // Blocks until client reads.
203 (void) DisconnectNamedPipe (_hPipe
);
204 EnterCriticalSection (&pipe_instance_lock
);
205 (void) CloseHandle (_hPipe
);
206 assert (pipe_instance
> 0);
207 InterlockedDecrement (&pipe_instance
);
208 LeaveCriticalSection (&pipe_instance_lock
);
211 (void) CloseHandle (_hPipe
);
213 #else /* __INSIDE_CYGWIN__ */
215 assert (!_is_accepted_endpoint
);
216 (void) ForceCloseHandle (_hPipe
);
218 #endif /* __INSIDE_CYGWIN__ */
225 transport_layer_pipes::read (void *const buf
, const size_t len
)
227 // verbose: debug_printf ("reading from pipe %p", _hPipe);
230 assert (_hPipe
!= INVALID_HANDLE_VALUE
);
231 assert (!_is_listening_endpoint
);
234 if (!ReadFile (_hPipe
, buf
, len
, &count
, NULL
))
236 debug_printf ("error reading from pipe (%lu)", GetLastError ());
237 SET_ERRNO (EINVAL
); // FIXME?
245 transport_layer_pipes::write (void *const buf
, const size_t len
)
247 // verbose: debug_printf ("writing to pipe %p", _hPipe);
250 assert (_hPipe
!= INVALID_HANDLE_VALUE
);
251 assert (!_is_listening_endpoint
);
254 if (!WriteFile (_hPipe
, buf
, len
, &count
, NULL
))
256 debug_printf ("error writing to pipe, error = %lu", GetLastError ());
257 SET_ERRNO (EINVAL
); // FIXME?
265 * This routine holds a static variable, assume_cygserver, that is set
266 * if the transport has good reason to think that cygserver is
267 * running, i.e. if if successfully connected to it with the previous
268 * attempt. If this is set, the code tries a lot harder to get a
269 * connection, making the assumption that any failures are just
270 * congestion and overloading problems.
274 transport_layer_pipes::connect ()
277 assert (!_is_accepted_endpoint
);
278 assert (!_is_listening_endpoint
);
280 static bool assume_cygserver
= false;
285 debug_printf ("Try to connect to named pipe: %W", _pipe_name
);
288 _hPipe
= CreateFileW (_pipe_name
,
289 GENERIC_READ
| GENERIC_WRITE
,
290 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
293 SECURITY_IMPERSONATION
,
296 if (_hPipe
!= INVALID_HANDLE_VALUE
)
299 #ifdef __INSIDE_CYGWIN__
300 ProtectHandle (_hPipe
);
302 assume_cygserver
= true;
308 if (!assume_cygserver
&& GetLastError () != ERROR_PIPE_BUSY
)
310 debug_printf ("Error opening the pipe (%lu)", GetLastError ());
314 /* Note: `If no instances of the specified named pipe exist, the
315 * WaitNamedPipe function returns immediately, regardless of the
316 * time-out value.' Thus the explicit Sleep if the call fails
317 * with ERROR_FILE_NOT_FOUND.
319 while (retries
!= MAX_WAIT_NAMED_PIPE_RETRY
320 && !(rc
= WaitNamedPipeW (_pipe_name
, WAIT_NAMED_PIPE_TIMEOUT
)))
322 if (GetLastError () == ERROR_FILE_NOT_FOUND
)
323 Sleep (0); // Give the server a chance.
329 assert (retries
== MAX_WAIT_NAMED_PIPE_RETRY
);
331 system_printf ("lost connection to cygserver, error = %lu",
334 assume_cygserver
= false;
339 #ifndef __INSIDE_CYGWIN__
342 transport_layer_pipes::impersonate_client ()
345 assert (_hPipe
!= INVALID_HANDLE_VALUE
);
346 assert (_is_accepted_endpoint
);
348 if (_hPipe
&& !ImpersonateNamedPipeClient (_hPipe
))
350 debug_printf ("Failed to Impersonate client, (%lu)", GetLastError ());
358 transport_layer_pipes::revert_to_self ()
360 assert (_is_accepted_endpoint
);
362 if (!RevertToSelf ())
364 debug_printf ("Failed to RevertToSelf, (%lu)", GetLastError ());
370 #endif /* !__INSIDE_CYGWIN__ */