private void ProcessPipeMessage() { NativeOverlapped overlapped = new NativeOverlapped(); byte[] readMessage; using (MemoryStream ms = new MemoryStream()) { while (true) { // Loop as follows: // Peek at the pipe to see how much data is available // Read the data and append it to the buffer // If we get ERROR_MORE_DATA, repeat UInt32 bytesRead, bytesAvailable, bytesLeft; // First peek into the pipe to see how much data is waiting. byte[] peekBuf = new byte[0]; if (!PeekNamedPipe(Handle, peekBuf, (UInt32)peekBuf.Length, out bytesRead, out bytesAvailable, out bytesLeft)) { throw new Win32Exception( string.Format("PeekNamedPipe failed. bytesRead={0} bytesAvailable={1} bytesLeft={2}", bytesRead, bytesAvailable, bytesLeft), new Win32Exception()); } // Sanity check: throw away message if it is > 1 MB if (ms.Length + bytesLeft > 1024 * 1024) { throw new Exception("Indecently large message sent into named pipe: rejecting."); } // Now allocate a buffer of the correct size and read in the message. byte[] readBuf = new byte[bytesAvailable]; if (!ReadFile(Handle, readBuf, (UInt32)readBuf.Length, out bytesRead, ref overlapped)) { Win32Exception exn = new Win32Exception(); if (exn.NativeErrorCode == ERROR_MORE_DATA) { // The peek may have looked into the pipe before the write operation // had completed, and so reported a message size before the whole // message was sent. In this case we need to go round the loop again // with a larger buffer. ms.Write(readBuf, 0, (int)bytesRead); continue; } else { throw new Win32Exception( string.Format("ReadFile failed. readBuf.Length={0} bytesRead={1}", readBuf.Length, bytesRead), exn); } } else { ms.Write(readBuf, 0, (int)bytesRead); break; } } readMessage = ms.ToArray(); } // Now perform a zero-byte write. This causes the CallNamedPipe call to // return successfully in the splash screen. UInt32 bytesWritten; byte[] toWrite = new byte[0]; if (!WriteFile(Handle, toWrite, (UInt32)toWrite.Length, out bytesWritten, ref overlapped)) { throw new Win32Exception( string.Format("WriteFile failed. toWrite.Length={0} bytesWritten={1}", toWrite.Length, bytesWritten), new Win32Exception()); } PipeReadEventArgs e = new PipeReadEventArgs(readMessage); if (e.Message == STOP_LISTENING_MSG) { log.Debug("NamedPipe thread was told to stop listening"); run = false; return; } // Now inform any listeners of the received data. if (Read != null) { Read(null, e); } }