private async void RunPipeClient(NamedPipeClientStream pipe) { try { Log("Connecting to pipe stream..."); await pipe.ConnectAsync(_ctsPipeClient.Token); Log("done\r\n"); while (!_die) { byte[] buffer = new byte[512]; int bytesRead = await pipe.ReadAsync(buffer, 0, buffer.Length, _ctsPipeClient.Token); if (bytesRead == Marshal.SizeOf <PipeMessage>()) { // assume that it is, in fact, a pipe_msg GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); PipeMessage message = (PipeMessage)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PipeMessage)); handle.Free(); HandleMessage(message); } } } catch { Log("Pipe connection broken\r\n"); } }
private void RequestFrame(bool log) { if (_pipeClient == null) { Log("No pipe to write to!"); return; } if (_surfaceRequestType != _lastFrame.SurfaceType) { // We are requesting a different surface type than the last one we received, which means hook DLL will likely // have to reallocate the shared memory, so we must release our handles to it, as it will be allocated under // the same name. ReleaseHandles(); } // define request var msg = new PipeMessage(); msg.MessageType = PipeMessageType.FrameRequest; msg.request = new PipeRequest(); msg.request.DestinationBuffer = _lastRequest.DestinationBuffer == DestinationBuffer.Buffer1 ? DestinationBuffer.Buffer2 : DestinationBuffer.Buffer1; // alternate msg.request.SurfaceType = _surfaceRequestType; msg.request.CustomOffset = _customRequestOffset; // convert to payload int size = Marshal.SizeOf(msg); byte[] buff = new byte[size]; IntPtr ptr = Marshal.AllocHGlobal(size); Marshal.StructureToPtr(msg, ptr, true); Marshal.Copy(ptr, buff, 0, size); Marshal.FreeHGlobal(ptr); try { if (log) { Log("Requesting next frame..."); } lock (requestLock) { _pipeClient.Write(buff, 0, size); _lastRequest = msg.request; } if (log) { Log("done\r\n"); } } catch (ObjectDisposedException) { } catch (IOException) { } }
private void HandleMessage(PipeMessage message) { if (message.MessageType == PipeMessageType.FrameAvailable) { lock (requestLock) { if (message.frame.DestBuffer != _lastRequest.DestinationBuffer) { // Drop this frame, it's from an older outstanding request for which we may no longer // have the associated map view handles. return; } } Bitmap img; failCounter = 0; lock (mapViewLock) img = ImageFromMappedFileView(message.frame); lock (canvas.ImageLock) canvas.Image = img; if (cbAutoRefresh.Checked) { // request next image in alternating buffer RequestFrame(false); } else { Log($"Received frame #{message.frame.FrameNumber} of size {message.frame.Width}x{message.frame.Height} in buffer {(int)message.frame.DestBuffer}\r\n"); } } else if (message.MessageType == PipeMessageType.FrameRequestFailed) { failCounter++; if (failCounter < 2) { RequestFrame(false); } else { BeginInvoke((Action) delegate { Log("Outstanding request failed successively, disabling auto-refresh\r\n"); cbAutoRefresh.Checked = false; }); } } }