private static byte[] ReadWindowProperty(IntPtr display, ulong windowId, ulong property) { const long smallPropertyLength = 1024; LibX11.XGetWindowProperty ( display, windowId, property, 0, smallPropertyLength, 1, 0 /* AnyPropertyType */, out ulong type, out int format, out ulong nItems, out ulong bytes_after_return, out IntPtr bufferPtr ); if (bytes_after_return != 0) { if (bufferPtr != IntPtr.Zero) { LibX11.XFree(bufferPtr); } ulong actualLength = bytes_after_return + 4 * smallPropertyLength; if (bytes_after_return > int.MaxValue || actualLength > int.MaxValue) { throw new InvalidOperationException ( $"Property {property} is too long: {nameof(bytes_after_return)} = {bytes_after_return}." ); } LibX11.XGetWindowProperty ( display, windowId, property, 0, (long)(actualLength + 3) / 4, 1, 0 /* AnyPropertyType */, out type, out format, out nItems, out bytes_after_return, out bufferPtr ); } try { if ((nItems != 0) && (format <= 0 || format % 8 != 0)) { throw new InvalidOperationException($"{nameof(LibX11.XGetWindowProperty)} returned an invalid format: {format}."); } int chunkSize = (int)nItems * format / 8; byte[] res = new byte [chunkSize]; if (chunkSize != 0) { if (bufferPtr == IntPtr.Zero) { throw new InvalidOperationException($"{nameof(LibX11.XGetWindowProperty)} returned an empty buffer for a non-empty value."); } Marshal.Copy(bufferPtr, res, 0, chunkSize); } return(res); } finally { if (bufferPtr != IntPtr.Zero) { LibX11.XFree(bufferPtr); } } }