/* Pipe.cpp Written by Matthew Fisher A pipe is a connection between two programs, possibly on different computers. */ #include Pipe::Pipe() { _Handle = NULL; } Pipe::~Pipe() { ClosePipe(); } void Pipe::ClosePipe() { if(_Handle != NULL) { FlushFileBuffers(_Handle); DisconnectNamedPipe(_Handle); CloseHandle(_Handle); _Handle = NULL; } } void Pipe::CreatePipe(const String &PipeName) { ClosePipe(); const UINT PipeBufferSize = 100000; DWORD dwRes; PSID pEveryoneSID = NULL, pAdminSID = NULL; PACL pACL = NULL; PSECURITY_DESCRIPTOR pSD = NULL; EXPLICIT_ACCESS ea[1]; SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; SECURITY_ATTRIBUTES Attributes; HKEY hkSub = NULL; // Create a well-known SID for the Everyone group. BOOL Success = AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID); Assert(Success != FALSE, "AllocateAndInitializeSid failed in Pipe::CreatePipe"); // Initialize an EXPLICIT_ACCESS structure for an ACE. // The ACE will allow Everyone read access to the key. ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); ea[0].grfAccessPermissions = FILE_ALL_ACCESS; ea[0].grfAccessMode = SET_ACCESS; ea[0].grfInheritance= NO_INHERITANCE; ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; ea[0].Trustee.ptstrName = (LPTSTR) pEveryoneSID; // Create a new ACL that contains the new ACEs. dwRes = SetEntriesInAcl(1, ea, NULL, &pACL); Assert(dwRes == ERROR_SUCCESS, "SetEntriesInAcl failed in Pipe::CreatePipe"); // Initialize a security descriptor. pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); Assert(pSD != NULL, "LocalAlloc failed in Pipe::CreatePipe"); Success = InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION); Assert(Success != FALSE, "InitializeSecurityDescriptor failed in Pipe::CreatePipe"); // Add the ACL to the security descriptor. Success = SetSecurityDescriptorDacl(pSD, TRUE, // bDaclPresent flag pACL, FALSE); Assert(Success != FALSE, "SetSecurityDescriptorDacl failed in Pipe::CreatePipe"); // Initialize a security attributes structure. Attributes.nLength = sizeof(SECURITY_ATTRIBUTES); Attributes.lpSecurityDescriptor = pSD; Attributes.bInheritHandle = FALSE; String FullPipeName = String("\\\\.\\pipe\\") + PipeName; _Handle = CreateNamedPipe( FullPipeName.CString(), // pipe name PIPE_ACCESS_DUPLEX, // read/write access PIPE_TYPE_MESSAGE | // message type pipe PIPE_READMODE_MESSAGE | // message-read mode PIPE_WAIT, // blocking mode PIPE_UNLIMITED_INSTANCES, // max. instances PipeBufferSize, // output buffer size PipeBufferSize, // input buffer size NMPWAIT_USE_DEFAULT_WAIT, // client time-out &Attributes); // default security attribute Assert(_Handle != INVALID_HANDLE_VALUE, "CreateNamedPipe failed in Pipe::CreatePipe"); // // Block until a connection comes in // BOOL Connected = (ConnectNamedPipe(_Handle, NULL) != 0); Assert(Connected != FALSE, "ConnectNamedPipe failed in Pipe::CreatePipe"); } void Pipe::ConnectToLocalPipe(const String &PipeName) { ConnectToPipe(String("\\\\.\\pipe\\") + PipeName); } void Pipe::ConnectToPipe(const String &PipeName) { ClosePipe(); bool Done = false; while(!Done) { _Handle = CreateFile( PipeName.CString(), // pipe name GENERIC_READ | // read and write access GENERIC_WRITE, 0, // no sharing NULL, // default security attributes OPEN_EXISTING, // opens existing pipe 0, // default attributes NULL); // no template file if(_Handle != INVALID_HANDLE_VALUE) { Done = true; } Sleep(100); } DWORD Mode = PIPE_READMODE_MESSAGE; BOOL Success = SetNamedPipeHandleState( _Handle, // pipe handle &Mode, // new pipe mode NULL, // don't set maximum bytes NULL); // don't set maximum time Assert(Success != FALSE, "SetNamedPipeHandleState failed in Pipe::ConnectToPipe"); } bool Pipe::MessagePresent() { Assert(_Handle != NULL, "Pipe invalid in Pipe::MessagePresent"); DWORD BytesReady = 0; BOOL Success = PeekNamedPipe( _Handle, NULL, 0, NULL, &BytesReady, NULL); Assert(Success != FALSE, "PeekNamedPipe failed in Pipe::MessagePresent"); return (BytesReady > 0); } bool Pipe::ReadMessage(Vector &Message) { Assert(_Handle != NULL, "Pipe invalid in Pipe::ReadMessage"); DWORD BytesReady = 0; BOOL Success = PeekNamedPipe( _Handle, NULL, 0, NULL, &BytesReady, NULL); Assert(Success != FALSE, "PeekNamedPipe failed in Pipe::ReadMessage"); Message.Allocate(BytesReady); if(BytesReady == 0) { return false; } DWORD BytesRead; Success = ReadFile( _Handle, // handle to pipe Message.CArray(), // buffer to receive data Message.Length(), // size of buffer &BytesRead, // number of bytes read NULL); // not overlapped I/O Assert(Success != FALSE && BytesRead > 0, "ReadFile failed in Pipe::ReadMessage"); return true; } void Pipe::SendMessage(const Vector &Message) { SendMessage(Message.CArray(), Message.Length()); } void Pipe::SendMessage(const BYTE *Message, UINT MessageLength) { Assert(_Handle != NULL, "Pipe invalid in Pipe::SendMessage"); DWORD BytesWritten; BOOL Success = WriteFile( _Handle, // pipe handle Message, // message MessageLength, // message length &BytesWritten, // bytes written NULL); // not overlapped Assert(Success != FALSE, "WriteFile failed in Pipe::ReadMessage"); Assert(BytesWritten == MessageLength, "WriteFile failed to send entire message in Pipe::ReadMessage"); } UINT Pipe::ActiveInstances() { Assert(_Handle != NULL, "Pipe invalid in Pipe::ActiveInstances"); DWORD Instances; BOOL Success = GetNamedPipeHandleState( _Handle, NULL, &Instances, NULL, NULL, NULL, 0); Assert(Success != FALSE, "GetNamedPipeHandleState failed in Pipe::ActiveInstances"); return Instances; } String Pipe::UserName() { Assert(_Handle != NULL, "Pipe invalid in Pipe::UserName"); char Buffer[512]; BOOL Success = GetNamedPipeHandleState( _Handle, NULL, NULL, NULL, NULL, Buffer, 512); Assert(Success != FALSE, "GetNamedPipeHandleState failed in Pipe::UserName"); return String(Buffer); }