Ejemplo n.º 1
0
        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);
                }
            }
        }