⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cygserver_transport_pipes.cc

📁 cygwin, 著名的在win32下模拟unix操作系统的东东
💻 CC
字号:
/* cygserver_transport_pipes.cc   Copyright 2001, 2002 Red Hat Inc.   Written by Robert Collins <rbtcollins@hotmail.com>This file is part of Cygwin.This software is a copyrighted work licensed under the terms of theCygwin license.  Please consult the file "CYGWIN_LICENSE" fordetails. *//* to allow this to link into cygwin and the .dll, a little magic is needed. */#ifdef __OUTSIDE_CYGWIN__#include "woutsup.h"#else#include "winsup.h"#endif#include <sys/types.h>#include <assert.h>#include <errno.h>#include <netdb.h>#include <pthread.h>#include <unistd.h>#include "cygerrno.h"#include "cygwin/cygserver_transport.h"#include "cygwin/cygserver_transport_pipes.h"#ifndef __INSIDE_CYGWIN__#include "cygwin/cygserver.h"#endifenum  {    MAX_WAIT_NAMED_PIPE_RETRY = 64,    WAIT_NAMED_PIPE_TIMEOUT = 10 // milliseconds  };#ifndef __INSIDE_CYGWIN__static pthread_once_t pipe_instance_lock_once = PTHREAD_ONCE_INIT;static CRITICAL_SECTION pipe_instance_lock;static long pipe_instance = 0;static voidinitialise_pipe_instance_lock (){  assert (pipe_instance == 0);  InitializeCriticalSection (&pipe_instance_lock);}#endif /* !__INSIDE_CYGWIN__ */#ifndef __INSIDE_CYGWIN__transport_layer_pipes::transport_layer_pipes (const HANDLE hPipe)  : _pipe_name (""),    _hPipe (hPipe),    _is_accepted_endpoint (true),    _is_listening_endpoint (false){  assert (_hPipe);  assert (_hPipe != INVALID_HANDLE_VALUE);  init_security ();}#endif /* !__INSIDE_CYGWIN__ */transport_layer_pipes::transport_layer_pipes ()  : _pipe_name ("\\\\.\\pipe\\cygwin_lpc"),    _hPipe (NULL),    _is_accepted_endpoint (false),    _is_listening_endpoint (false){  init_security ();}voidtransport_layer_pipes::init_security (){  assert (wincap.has_security ());  /* FIXME: pthread_once or equivalent needed */  InitializeSecurityDescriptor (&_sd, SECURITY_DESCRIPTOR_REVISION);  SetSecurityDescriptorDacl (&_sd, TRUE, NULL, FALSE);  _sec_all_nih.nLength = sizeof (SECURITY_ATTRIBUTES);  _sec_all_nih.lpSecurityDescriptor = &_sd;  _sec_all_nih.bInheritHandle = FALSE;}transport_layer_pipes::~transport_layer_pipes (){  close ();}#ifndef __INSIDE_CYGWIN__inttransport_layer_pipes::listen (){  assert (!_hPipe);  assert (!_is_accepted_endpoint);  assert (!_is_listening_endpoint);  _is_listening_endpoint = true;  /* no-op */  return 0;}class transport_layer_pipes *transport_layer_pipes::accept (bool *const recoverable){  assert (!_hPipe);  assert (!_is_accepted_endpoint);  assert (_is_listening_endpoint);  pthread_once (&pipe_instance_lock_once, &initialise_pipe_instance_lock);  EnterCriticalSection (&pipe_instance_lock);  // Read: http://www.securityinternals.com/research/papers/namedpipe.php  // See also the Microsoft security bulletins MS00-053 and MS01-031.  // FIXME: Remove FILE_CREATE_PIPE_INSTANCE.  const bool first_instance = (pipe_instance == 0);  const HANDLE accept_pipe =    CreateNamedPipe (_pipe_name,		     (PIPE_ACCESS_DUPLEX		      | (first_instance ? FILE_FLAG_FIRST_PIPE_INSTANCE : 0)),		     (PIPE_TYPE_BYTE | PIPE_WAIT),		     PIPE_UNLIMITED_INSTANCES,		     0, 0, 1000,		     &_sec_all_nih);  const bool duplicate = (accept_pipe == INVALID_HANDLE_VALUE			  && pipe_instance == 0			  && GetLastError () == ERROR_ACCESS_DENIED);  if (accept_pipe != INVALID_HANDLE_VALUE)    InterlockedIncrement (&pipe_instance);  LeaveCriticalSection (&pipe_instance_lock);  if (duplicate)    {      *recoverable = false;      system_printf ("failed to create named pipe: "		     "is the daemon already running?");      return NULL;    }  if (accept_pipe == INVALID_HANDLE_VALUE)    {      debug_printf ("error creating pipe (%lu).", GetLastError ());      *recoverable = true;	// FIXME: case analysis?      return NULL;    }  assert (accept_pipe);  if (!ConnectNamedPipe (accept_pipe, NULL)      && GetLastError () != ERROR_PIPE_CONNECTED)    {      debug_printf ("error connecting to pipe (%lu)", GetLastError ());      (void) CloseHandle (accept_pipe);      *recoverable = true;	// FIXME: case analysis?      return NULL;    }  return safe_new (transport_layer_pipes, accept_pipe);}#endif /* !__INSIDE_CYGWIN__ */voidtransport_layer_pipes::close (){  // verbose: debug_printf ("closing pipe %p", _hPipe);  if (_hPipe)    {      assert (_hPipe != INVALID_HANDLE_VALUE);#ifndef __INSIDE_CYGWIN__      if (_is_accepted_endpoint)	{	  (void) FlushFileBuffers (_hPipe); // Blocks until client reads.	  (void) DisconnectNamedPipe (_hPipe);	  EnterCriticalSection (&pipe_instance_lock);	  (void) CloseHandle (_hPipe);	  assert (pipe_instance > 0);	  InterlockedDecrement (&pipe_instance);	  LeaveCriticalSection (&pipe_instance_lock);	}      else	(void) CloseHandle (_hPipe);#else /* __INSIDE_CYGWIN__ */      assert (!_is_accepted_endpoint);      (void) ForceCloseHandle (_hPipe);#endif /* __INSIDE_CYGWIN__ */      _hPipe = NULL;    }}ssize_ttransport_layer_pipes::read (void *const buf, const size_t len){  // verbose: debug_printf ("reading from pipe %p", _hPipe);  assert (_hPipe);  assert (_hPipe != INVALID_HANDLE_VALUE);  assert (!_is_listening_endpoint);  DWORD count;  if (!ReadFile (_hPipe, buf, len, &count, NULL))    {      debug_printf ("error reading from pipe (%lu)", GetLastError ());      set_errno (EINVAL);	// FIXME?      return -1;    }  return count;}ssize_ttransport_layer_pipes::write (void *const buf, const size_t len){  // verbose: debug_printf ("writing to pipe %p", _hPipe);  assert (_hPipe);  assert (_hPipe != INVALID_HANDLE_VALUE);  assert (!_is_listening_endpoint);  DWORD count;  if (!WriteFile (_hPipe, buf, len, &count, NULL))    {      debug_printf ("error writing to pipe, error = %lu", GetLastError ());      set_errno (EINVAL);	// FIXME?      return -1;    }  return count;}/* * This routine holds a static variable, assume_cygserver, that is set * if the transport has good reason to think that cygserver is * running, i.e. if if successfully connected to it with the previous * attempt.  If this is set, the code tries a lot harder to get a * connection, making the assumption that any failures are just * congestion and overloading problems. */inttransport_layer_pipes::connect (){  assert (!_hPipe);  assert (!_is_accepted_endpoint);  assert (!_is_listening_endpoint);  static bool assume_cygserver = false;  BOOL rc = TRUE;  int retries = 0;  while (rc)    {      _hPipe = CreateFile (_pipe_name,			   GENERIC_READ | GENERIC_WRITE,			   FILE_SHARE_READ | FILE_SHARE_WRITE,			   &_sec_all_nih,			   OPEN_EXISTING,			   SECURITY_IMPERSONATION,			   NULL);      if (_hPipe != INVALID_HANDLE_VALUE)	{	  assert (_hPipe);#ifdef __INSIDE_CYGWIN__	  ProtectHandle (_hPipe);#endif	  assume_cygserver = true;	  return 0;	}      _hPipe = NULL;      if (!assume_cygserver && GetLastError () != ERROR_PIPE_BUSY)	{	  debug_printf ("Error opening the pipe (%lu)", GetLastError ());	  return -1;	}      /* Note: `If no instances of the specified named pipe exist, the       * WaitNamedPipe function returns immediately, regardless of the       * time-out value.'  Thus the explicit Sleep if the call fails       * with ERROR_FILE_NOT_FOUND.       */      while (retries != MAX_WAIT_NAMED_PIPE_RETRY	     && !(rc = WaitNamedPipe (_pipe_name, WAIT_NAMED_PIPE_TIMEOUT)))	{	  if (GetLastError () == ERROR_FILE_NOT_FOUND)	    Sleep (0);		// Give the server a chance.	  retries += 1;	}    }  assert (retries == MAX_WAIT_NAMED_PIPE_RETRY);  system_printf ("lost connection to cygserver, error = %lu",		 GetLastError ());  assume_cygserver = false;  return -1;}#ifndef __INSIDE_CYGWIN__voidtransport_layer_pipes::impersonate_client (){  assert (_hPipe);  assert (_hPipe != INVALID_HANDLE_VALUE);  assert (_is_accepted_endpoint);  // verbose: debug_printf ("impersonating pipe %p", _hPipe);  if (_hPipe)    {      assert (_hPipe != INVALID_HANDLE_VALUE);      if (!ImpersonateNamedPipeClient (_hPipe))	debug_printf ("Failed to Impersonate the client, (%lu)",		      GetLastError ());    }  // verbose: debug_printf ("I am who you are");}voidtransport_layer_pipes::revert_to_self (){  assert (_is_accepted_endpoint);  RevertToSelf ();  // verbose: debug_printf ("I am who I yam");}#endif /* !__INSIDE_CYGWIN__ */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -