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__
20 #include <sys/types.h>
27 #include <sys/cygwin.h>
30 #include "transport.h"
31 #include "transport_pipes.h"
33 #ifndef __INSIDE_CYGWIN__
34 #include "cygserver.h"
35 #include "cygserver_ipc.h"
40 #ifdef __INSIDE_CYGWIN__
41 #define SET_ERRNO(err) set_errno (err)
43 #define SET_ERRNO(err) errno = (err)
48 MAX_WAIT_NAMED_PIPE_RETRY = 64,
49 WAIT_NAMED_PIPE_TIMEOUT = 10 // milliseconds
52 #ifndef __INSIDE_CYGWIN__
54 static pthread_once_t pipe_instance_lock_once = PTHREAD_ONCE_INIT;
55 static CRITICAL_SECTION pipe_instance_lock;
56 static long pipe_instance = 0;
59 initialise_pipe_instance_lock ()
61 assert (pipe_instance == 0);
62 InitializeCriticalSection (&pipe_instance_lock);
65 #endif /* !__INSIDE_CYGWIN__ */
67 #ifndef __INSIDE_CYGWIN__
69 transport_layer_pipes::transport_layer_pipes (const HANDLE hPipe)
71 _is_accepted_endpoint (true),
72 _is_listening_endpoint (false)
75 assert (_hPipe != INVALID_HANDLE_VALUE);
76 _pipe_name[0] = L'\0';
79 #endif /* !__INSIDE_CYGWIN__ */
81 transport_layer_pipes::transport_layer_pipes ()
83 _is_accepted_endpoint (false),
84 _is_listening_endpoint (false)
86 #ifdef __INSIDE_CYGWIN__
87 extern WCHAR installation_key_buf[18];
88 wcpcpy (wcpcpy (wcpcpy (_pipe_name, PIPE_NAME_PREFIX), installation_key_buf),
91 wchar_t cyg_instkey[18];
93 wchar_t *p = wcpcpy (_pipe_name, PIPE_NAME_PREFIX);
94 if (!cygwin_internal (CW_GET_INSTKEY, cyg_instkey))
95 wcpcpy (wcpcpy (p, cyg_instkey), PIPE_NAME_SUFFIX);
99 transport_layer_pipes::~transport_layer_pipes ()
104 #ifndef __INSIDE_CYGWIN__
107 transport_layer_pipes::listen ()
110 assert (!_is_accepted_endpoint);
111 assert (!_is_listening_endpoint);
113 _is_listening_endpoint = true;
119 class transport_layer_pipes *
120 transport_layer_pipes::accept (bool *const recoverable)
123 assert (!_is_accepted_endpoint);
124 assert (_is_listening_endpoint);
126 pthread_once (&pipe_instance_lock_once, &initialise_pipe_instance_lock);
128 EnterCriticalSection (&pipe_instance_lock);
130 // Read: http://www.securityinternals.com/research/papers/namedpipe.php
131 // See also the Microsoft security bulletins MS00-053 and MS01-031.
133 // FIXME: Remove FILE_CREATE_PIPE_INSTANCE.
135 const bool first_instance = (pipe_instance == 0);
137 debug ("Try to create named pipe: %ls", _pipe_name);
139 const HANDLE accept_pipe =
140 CreateNamedPipeW (_pipe_name,
142 | (first_instance ? FILE_FLAG_FIRST_PIPE_INSTANCE : 0)),
143 (PIPE_TYPE_BYTE | PIPE_WAIT),
144 PIPE_UNLIMITED_INSTANCES,
148 const bool duplicate = (accept_pipe == INVALID_HANDLE_VALUE
149 && pipe_instance == 0
150 && GetLastError () == ERROR_ACCESS_DENIED);
152 if (accept_pipe != INVALID_HANDLE_VALUE)
153 InterlockedIncrement (&pipe_instance);
155 LeaveCriticalSection (&pipe_instance_lock);
159 *recoverable = false;
160 system_printf ("failed to create named pipe: "
161 "is the daemon already running?");
165 if (accept_pipe == INVALID_HANDLE_VALUE)
167 debug_printf ("error creating pipe (%lu).", GetLastError ());
168 *recoverable = true; // FIXME: case analysis?
172 assert (accept_pipe);
174 if (!ConnectNamedPipe (accept_pipe, NULL)
175 && GetLastError () != ERROR_PIPE_CONNECTED)
177 debug_printf ("error connecting to pipe (%lu)", GetLastError ());
178 (void) CloseHandle (accept_pipe);
179 *recoverable = true; // FIXME: case analysis?
183 return new transport_layer_pipes (accept_pipe);
186 #endif /* !__INSIDE_CYGWIN__ */
189 transport_layer_pipes::close ()
191 // verbose: debug_printf ("closing pipe %p", _hPipe);
195 assert (_hPipe != INVALID_HANDLE_VALUE);
197 #ifndef __INSIDE_CYGWIN__
199 if (_is_accepted_endpoint)
201 (void) FlushFileBuffers (_hPipe); // Blocks until client reads.
202 (void) DisconnectNamedPipe (_hPipe);
203 EnterCriticalSection (&pipe_instance_lock);
204 (void) CloseHandle (_hPipe);
205 assert (pipe_instance > 0);
206 InterlockedDecrement (&pipe_instance);
207 LeaveCriticalSection (&pipe_instance_lock);
210 (void) CloseHandle (_hPipe);
212 #else /* __INSIDE_CYGWIN__ */
214 assert (!_is_accepted_endpoint);
215 (void) ForceCloseHandle (_hPipe);
217 #endif /* __INSIDE_CYGWIN__ */
224 transport_layer_pipes::read (void *const buf, const size_t len)
226 // verbose: debug_printf ("reading from pipe %p", _hPipe);
229 assert (_hPipe != INVALID_HANDLE_VALUE);
230 assert (!_is_listening_endpoint);
233 if (!ReadFile (_hPipe, buf, len, &count, NULL))
235 debug_printf ("error reading from pipe (%lu)", GetLastError ());
236 SET_ERRNO (EINVAL); // FIXME?
244 transport_layer_pipes::write (void *const buf, const size_t len)
246 // verbose: debug_printf ("writing to pipe %p", _hPipe);
249 assert (_hPipe != INVALID_HANDLE_VALUE);
250 assert (!_is_listening_endpoint);
253 if (!WriteFile (_hPipe, buf, len, &count, NULL))
255 debug_printf ("error writing to pipe, error = %lu", GetLastError ());
256 SET_ERRNO (EINVAL); // FIXME?
264 * This routine holds a static variable, assume_cygserver, that is set
265 * if the transport has good reason to think that cygserver is
266 * running, i.e. if if successfully connected to it with the previous
267 * attempt. If this is set, the code tries a lot harder to get a
268 * connection, making the assumption that any failures are just
269 * congestion and overloading problems.
273 transport_layer_pipes::connect ()
276 assert (!_is_accepted_endpoint);
277 assert (!_is_listening_endpoint);
279 static bool assume_cygserver = false;
284 debug_printf ("Try to connect to named pipe: %W", _pipe_name);
287 _hPipe = CreateFileW (_pipe_name,
288 GENERIC_READ | GENERIC_WRITE,
289 FILE_SHARE_READ | FILE_SHARE_WRITE,
292 SECURITY_IMPERSONATION,
295 if (_hPipe != INVALID_HANDLE_VALUE)
298 #ifdef __INSIDE_CYGWIN__
299 ProtectHandle (_hPipe);
301 assume_cygserver = true;
307 if (!assume_cygserver && GetLastError () != ERROR_PIPE_BUSY)
309 debug_printf ("Error opening the pipe (%lu)", GetLastError ());
313 /* Note: `If no instances of the specified named pipe exist, the
314 * WaitNamedPipe function returns immediately, regardless of the
315 * time-out value.' Thus the explicit Sleep if the call fails
316 * with ERROR_FILE_NOT_FOUND.
318 while (retries != MAX_WAIT_NAMED_PIPE_RETRY
319 && !(rc = WaitNamedPipeW (_pipe_name, WAIT_NAMED_PIPE_TIMEOUT)))
321 if (GetLastError () == ERROR_FILE_NOT_FOUND)
322 Sleep (0); // Give the server a chance.
328 assert (retries == MAX_WAIT_NAMED_PIPE_RETRY);
330 system_printf ("lost connection to cygserver, error = %lu",
333 assume_cygserver = false;
338 #ifndef __INSIDE_CYGWIN__
341 transport_layer_pipes::impersonate_client ()
344 assert (_hPipe != INVALID_HANDLE_VALUE);
345 assert (_is_accepted_endpoint);
347 if (_hPipe && !ImpersonateNamedPipeClient (_hPipe))
349 debug_printf ("Failed to Impersonate client, (%lu)", GetLastError ());
357 transport_layer_pipes::revert_to_self ()
359 assert (_is_accepted_endpoint);
361 if (!RevertToSelf ())
363 debug_printf ("Failed to RevertToSelf, (%lu)", GetLastError ());
369 #endif /* !__INSIDE_CYGWIN__ */