/* cygserver_transport_pipes.cc Copyright 2001, 2002 Red Hat Inc. Written by Robert Collins This file is part of Cygwin. This software is a copyrighted work licensed under the terms of the Cygwin license. Please consult the file "CYGWIN_LICENSE" for details. */ #include #include #include #include #include #include #include #include "wincap.h" #include "cygwin/cygserver_transport.h" #include "cygwin/cygserver_transport_pipes.h" /* to allow this to link into cygwin and the .dll, a little magic is needed. */ #ifndef __OUTSIDE_CYGWIN__ #include "winsup.h" #else #define DEBUG 0 #define debug_printf if (DEBUG) printf #endif //SECURITY_DESCRIPTOR transport_layer_pipes::sd; //SECURITY_ATTRIBUTES transport_layer_pipes::sec_none_nih, transport_layer_pipes::sec_all_nih; //bool transport_layer_pipes::inited = false; transport_layer_pipes::transport_layer_pipes (HANDLE new_pipe) { inited = false; //FIXME: allow inited, sd, all_nih_.. to be static members pipe = new_pipe; if (inited != true) init_security(); }; transport_layer_pipes::transport_layer_pipes () { inited = false; pipe = NULL; strcpy(pipe_name, "\\\\.\\pipe\\cygwin_lpc"); if (inited != true) init_security(); } void transport_layer_pipes::init_security() { /* FIXME: pthread_once or equivalent needed */ InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl (&sd, TRUE, 0, FALSE); sec_none_nih.nLength = sec_all_nih.nLength = sizeof (SECURITY_ATTRIBUTES); sec_none_nih.bInheritHandle = sec_all_nih.bInheritHandle = FALSE; sec_none_nih.lpSecurityDescriptor = NULL; sec_all_nih.lpSecurityDescriptor = &sd; inited = true; } void transport_layer_pipes::listen () { /* no-op */ } class transport_layer_pipes * transport_layer_pipes::accept () { if (pipe) { debug_printf ("Already have a pipe in this %p\n",this); return NULL; } pipe = CreateNamedPipe (pipe_name, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 0, 0, 1000, &sec_all_nih ); if (pipe == INVALID_HANDLE_VALUE) { debug_printf ("error creating pipe (%lu)\n.", GetLastError ()); return NULL; } if ( !ConnectNamedPipe ( pipe, NULL ) && GetLastError () != ERROR_PIPE_CONNECTED) { printf ("error connecting to pipe (%lu)\n.", GetLastError ()); CloseHandle (pipe); pipe = NULL; return NULL; } transport_layer_pipes *new_conn = new transport_layer_pipes (pipe); pipe = NULL; return new_conn; } void transport_layer_pipes::close() { debug_printf ("closing pipe %p\n", pipe); if (pipe && pipe != INVALID_HANDLE_VALUE) { FlushFileBuffers (pipe); DisconnectNamedPipe (pipe); CloseHandle (pipe); } } ssize_t transport_layer_pipes::read (char *buf, size_t len) { debug_printf ("reading from pipe %p\n", pipe); if (!pipe || pipe == INVALID_HANDLE_VALUE) return -1; DWORD bytes_read; DWORD rc = ReadFile (pipe, buf, len, &bytes_read, NULL); if (!rc) { debug_printf ("error reading from pipe (%lu)\n", GetLastError ()); return -1; } return bytes_read; } ssize_t transport_layer_pipes::write (char *buf, size_t len) { debug_printf ("writing to pipe %p\n", pipe); DWORD bytes_written, rc; if (!pipe || pipe == INVALID_HANDLE_VALUE) return -1; rc = WriteFile (pipe, buf, len, &bytes_written, NULL); if (!rc) { debug_printf ("error writing to pipe (%lu)\n", GetLastError ()); return -1; } return bytes_written; } bool transport_layer_pipes::connect () { if (pipe && pipe != INVALID_HANDLE_VALUE) { debug_printf ("Already have a pipe in this %p\n",this); return false; } while (1) { pipe = CreateFile (pipe_name, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sec_all_nih, OPEN_EXISTING, 0, NULL); if (pipe != INVALID_HANDLE_VALUE) /* got the pipe */ return true; if (GetLastError () != ERROR_PIPE_BUSY) { debug_printf ("Error opening the pipe (%lu)\n", GetLastError ()); pipe = NULL; return false; } if (!WaitNamedPipe (pipe_name, 20000)) debug_printf ( "error connecting to server pipe after 20 seconds (%lu)\n", GetLastError () ); /* We loop here, because the pipe exists but is busy. If it doesn't exist * the != ERROR_PIPE_BUSY will catch it. */ } } void transport_layer_pipes::impersonate_client () { debug_printf ("impersonating pipe %p\n", pipe); if (pipe && pipe != INVALID_HANDLE_VALUE) { BOOL rv = ImpersonateNamedPipeClient (pipe); if (!rv) debug_printf ("Failed to Impersonate the client, (%lu)\n", GetLastError ()); } debug_printf("I am who you are\n"); } void transport_layer_pipes::revert_to_self () { RevertToSelf (); debug_printf("I am who I yam\n"); }