Windows clipboard dumper

Inspired by this bug report, I just wrote a small, quick and dirty utility to dump the current clipboard content on Windows. Windows development to me is still pretty much an uncharted territory, so even a utility as simple as this took me some time. Anyway, you can download the binary from here: clipdump.exe. Note that this is a console utility, so you need to run this from the console window.

Here is the source code.

#include <Windows.h>
 
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <vector>
 
using namespace std;
 
size_t char_per_line = 16;
typedef vector<WORD> line_store_type;
 
void dump_line(const line_store_type& line)
{
    if (line.empty())
        return;
 
    size_t fill_size = char_per_line - line.size();
 
    line_store_type::const_iterator i = line.begin(), iend = line.end();
    for (; i != iend; ++i)
        printf("%04X ", *i);
 
    while (fill_size--)
        cout << "     ";
 
    cout << ' ';
    i = line.begin();
    for (; i != iend; ++i)
    {
        WORD c = *i;
        if (32 <= c && c <= 126)
            // ASCII printable range
            cout << static_cast<char>(c);
        else
            // non-printable range
            cout << '.';
    }
 
    cout << endl;
}
 
void dump_clip(HANDLE hdl)
{
    if (!hdl)
        return;
 
    LPTSTR buf = static_cast<LPTSTR>(GlobalLock(hdl));
    if (!buf)
        return;
 
    line_store_type line;
    line.reserve(char_per_line);
    for (size_t i = 0, n = GlobalSize(hdl); i < n; ++i)
    {
        line.push_back(buf[i]);
        if (line.size() == char_per_line)
        {
            dump_line(line);
            line.clear();
        }
    }
    dump_line(line);
 
    GlobalUnlock(hdl);
}
 
int main()
{
    if (!OpenClipboard(NULL))
        return EXIT_FAILURE;
 
    UINT fmt = 0;
    for (fmt = EnumClipboardFormats(fmt); fmt; fmt = EnumClipboardFormats(fmt))
    {
        char name[100];
        int len = GetClipboardFormatName(fmt, name, 100);
        if (!len)
            continue;
 
        cout << "---" << endl;
        cout << "format code: " << fmt << endl;
        cout << "name: " << name << endl << endl;
 
        HANDLE hdl = GetClipboardData(fmt);
        dump_clip(hdl);
    }
 
    CloseClipboard();
    return EXIT_SUCCESS;
}

It’s nothing sophisticated, and it could probably use more polishing and perhaps some GUI (since it’s a Windows app). But for now it serves the purpose for me.

Update:
Tor has submitted his version in the comment section. Much more sophisticated than mine (and it’s C not C++).

7 thoughts on “Windows clipboard dumper”

  1. Here is mine… unfortunately not really much documentation, but experimenting with the options and browsing the code should be informative.

    #include
    #include
    #include
    #include
    #include

    #ifndef CF_DIBV5
    #define CF_DIBV5 17
    #endif

    #define MAXDATA 1000

    static int maxdata = MAXDATA;
    static int interpret_newlines = 1;

    typedef enum {
    FORMAT_DEFAULT,
    FORMAT_STRING,
    FORMAT_WSTRING,
    FORMAT_HEX,
    FORMAT_BINARY
    } output_format_type;

    const char *
    clipboard_format_name (UINT format)
    {
    static char bfr[100];

    if (GetClipboardFormatName (format, bfr, sizeof (bfr)))
    return bfr;

    if (format >= CF_GDIOBJFIRST && format = CF_PRIVATEFIRST && format 0)
    return format;

    #define CASE(x) if (strcmp (string, “CF_” # x) == 0) return CF_##x
    CASE (BITMAP);
    CASE (DIB);
    CASE (DIBV5);
    CASE (DIF);
    CASE (DSPBITMAP);
    CASE (DSPENHMETAFILE);
    CASE (DSPMETAFILEPICT);
    CASE (DSPTEXT);
    CASE (ENHMETAFILE);
    CASE (HDROP);
    CASE (LOCALE);
    CASE (METAFILEPICT);
    CASE (OEMTEXT);
    CASE (OWNERDISPLAY);
    CASE (PALETTE);
    CASE (PENDATA);
    CASE (RIFF);
    CASE (SYLK);
    CASE (TEXT);
    CASE (WAVE);
    CASE (TIFF);
    CASE (UNICODETEXT);
    #undef CASE

    while ((format = EnumClipboardFormats (format)))
    if (strcmp (string, clipboard_format_name (format)) == 0)
    return format;

    return 0;
    }

    static void
    print_string_data (const unsigned char *data,
    size_t size)
    {
    int i;

    for (i = 0; i = maxdata)
    break;

    switch (*data)
    {
    case ‘\a’:
    printf (“\\a”);
    break;
    case ‘\b’:
    printf (“\\b”);
    break;
    case ‘\f’:
    printf (“\\f”);
    break;
    case ‘\n’:
    printf (“\\n”);
    break;
    case ‘\r’:
    if (interpret_newlines && data[1] == ‘\n’)
    {
    printf (“\n”);
    data++;
    }
    else
    printf (“\\r”);
    break;
    case ‘\t’:
    printf (“\\t”);
    break;
    case ‘\\’:
    printf (“\\\\”);
    break;
    default:
    if (*data >= ‘ ‘ && *data < 0177)
    printf ("%c", *data);
    else
    printf ("\\%03o", (int) *data);
    }
    }
    }

    static void
    print_unicode_data (const wchar_t *data,
    size_t size)
    {
    int i;

    for (i = 0; i = maxdata)
    break;

    switch (*data)
    {
    case ‘\a’:
    printf (“\\a”);
    break;
    case ‘\b’:
    printf (“\\b”);
    break;
    case ‘\f’:
    printf (“\\f”);
    break;
    case ‘\n’:
    printf (“\\n”);
    break;
    case ‘\r’:
    if (interpret_newlines && data[1] == ‘\n’)
    {
    printf (“\n”);
    data++;
    }
    else
    printf (“\\r”);
    break;
    case ‘\t’:
    printf (“\\t”);
    break;
    case ‘\\’:
    printf (“\\\\”);
    break;
    default:
    if (*data >= ‘ ‘ && *data < 0177)
    printf ("%c", *data);
    else
    printf ("\\u%04x", *data);
    }
    }
    }

    static void
    print_hex_data (const unsigned int *data,
    size_t size)
    {
    int i;

    for (i = 0; i = maxdata)
    break;

    printf (“%08x”, *data);
    if ((i % 8) == 7)
    printf (“\n”);
    else
    printf (” “);
    }
    }

    static int
    format_for_specific_handle (UINT format)
    {
    switch (format)
    {
    case CF_BITMAP:
    case CF_ENHMETAFILE:
    case CF_HDROP:
    return 1;
    }
    return 0;
    }

    static char *
    compression_type (DWORD compression)
    {
    static char buf[20];

    switch (compression)
    {
    #define CASE(x) case BI_##x: return “BI_”#x
    CASE (RGB);
    CASE (RLE8);
    CASE (RLE4);
    CASE (BITFIELDS);
    CASE (JPEG);
    CASE (PNG);
    #undef CASE
    default:
    sprintf (buf, “%#lx”, compression);
    return buf;
    }
    }

    static int
    print_colors (const BITMAPINFOHEADER *bi,
    const RGBQUAD *rgb)
    {
    if (bi->biCompression == BI_BITFIELDS &&
    bi->biSize == sizeof (BITMAPINFOHEADER))
    {
    const DWORD *mask = (DWORD *) rgb;

    printf (“{%08lx,%08lx,%08lx}”, mask[0], mask[1], mask[2]);

    return 3*4;
    }

    if (bi->biBitCount == 1)
    {
    int i;

    printf (“rgb[2]{“);
    for (i = 0; i biBitCount == 4 || bi->biBitCount == 8)
    {
    int ncolors = 16;
    int i;

    if (bi->biClrUsed > 0)
    ncolors = bi->biClrUsed;

    printf (“rgb[%d]{“, ncolors);
    for (i = 0; i < ncolors; i++)
    {
    printf ("%02x%02x%02x}",
    rgb[i].rgbRed, rgb[i].rgbGreen, rgb[i].rgbBlue);
    if (i bmiHeader.biSize, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, bmi->bmiHeader.biPlanes, bmi->bmiHeader.biBitCount,
    compression_type (bmi->bmiHeader.biCompression),
    bmi->bmiHeader.biSizeImage, bmi->bmiHeader.biXPelsPerMeter, bmi->bmiHeader.biYPelsPerMeter,
    bmi->bmiHeader.biClrUsed, bmi->bmiHeader.biClrImportant);

    color_table_size = print_colors (&bmi->bmiHeader, bmi->bmiColors);
    image_size = ((((bmi->bmiHeader.biBitCount * bmi->bmiHeader.biWidth) / 8) + 3 ) & ~3) * bmi->bmiHeader.biHeight;
    printf (“\n”
    “},\n”);
    print_hex_data ((const unsigned int *)((char *) data +
    bmi->bmiHeader.biSize +
    color_table_size),
    image_size/4);
    }

    static void
    print_dibv5 (const void *data,
    SIZE_T size)
    {
    const BITMAPV5HEADER *bV5 = (BITMAPV5HEADER *) data;
    int color_table_size;
    int image_size;

    printf (“bV5{\n”
    ” Size=%ld, Width=%ld, Height=%ld, Planes=%d, BitCount=%d,\n”
    ” Compression=%s, SizeImage=%ld, XPelsPerMeter=%ld, YPelsPerMeter=%ld,\n”
    ” ClrUsed=%ld, ClrImportant=%ld,\n”
    ” RedMask=%08lx, GreenMask=%08lx, BlueMask=%08lx, AlphaMask=%08lx,\n”
    ” CsType=%ld (%c%c%c%c)\n”
    “},\n”,
    bV5->bV5Size, bV5->bV5Width, bV5->bV5Height, bV5->bV5Planes, bV5->bV5BitCount,
    compression_type (bV5->bV5Compression),
    bV5->bV5SizeImage, bV5->bV5XPelsPerMeter, bV5->bV5YPelsPerMeter,
    bV5->bV5ClrUsed, bV5->bV5ClrImportant,
    bV5->bV5RedMask, bV5->bV5GreenMask, bV5->bV5BlueMask, bV5->bV5AlphaMask,
    bV5->bV5CSType,
    ((char *)&bV5->bV5CSType)[3], ((char *)&bV5->bV5CSType)[2],
    ((char *)&bV5->bV5CSType)[1], ((char *)&bV5->bV5CSType)[0]);
    printf (“colortable”);
    color_table_size = print_colors ((BITMAPINFOHEADER *) bV5,
    (RGBQUAD*) ((char *)bV5) + bV5->bV5Size);
    image_size = ((((bV5->bV5BitCount * bV5->bV5Width) / 8) + 3 ) & ~3) * bV5->bV5Height;
    printf (“\n”);
    print_hex_data ((const unsigned int *)((char *) data +
    bV5->bV5Size +
    color_table_size),
    image_size/4);
    }

    static void
    print_data (output_format_type output_format,
    UINT format,
    const unsigned char *data,
    SIZE_T size)
    {
    switch (output_format)
    {
    case FORMAT_DEFAULT:
    switch (format)
    {
    case CF_DIB:
    print_dib (data, size);
    break;
    case CF_DIBV5:
    print_dibv5 (data, size);
    break;
    default:
    goto _FORMAT_STRING;
    }
    break;
    case FORMAT_STRING: _FORMAT_STRING:
    print_string_data (data, size);
    break;
    case FORMAT_WSTRING:
    print_unicode_data ((wchar_t *) data, (size+1)/2);
    break;
    case FORMAT_HEX:
    print_hex_data ((unsigned int *) data, (size+3)/4);
    break;
    case FORMAT_BINARY:
    _setmode (fileno (stdout), O_BINARY);
    fwrite (data, size, 1, stdout);
    return;
    }
    printf (“\n”);
    }

    static void
    print_format_for_specific_handle (UINT format,
    HANDLE handle)
    {
    switch (format)
    {
    case CF_BITMAP:
    {
    HANDLE handle = GetClipboardData (format);
    BITMAP bm;

    if (!GetObject (handle, sizeof (BITMAP), (void *) &bm))
    fprintf (stderr, “GetObject failed.\n”), exit (1);

    printf (“bm{\n”
    ” Type=%ld, Width=%ld, Height=%ld, WidthBytes=%ld,\n”
    ” Planes=%d, BitsPixel=%d,\n”
    ” bmBits=”,
    bm.bmType, bm.bmWidth, bm.bmHeight, bm.bmWidthBytes,
    bm.bmPlanes, bm.bmBitsPixel);
    if (bm.bmBits != NULL)
    print_data (FORMAT_HEX, CF_BITMAP, bm.bmBits, bm.bmHeight*bm.bmWidthBytes);
    else
    printf (“0”);
    printf (“\n”
    “}”);
    }
    break;
    default:
    printf (“%p”, handle);
    }
    }

    static void
    usage (const char *progname)
    {
    fprintf (stderr, “Usage: %s [-m maxdata] [-b|-h|-n|-u|-i filename|-o filename]… (-l|-g format|-p format)\n”, progname);
    }

    int
    main (int argc,
    char **argv)
    {
    UINT format = 0;
    HANDLE handle;
    int i;
    output_format_type output_format = FORMAT_DEFAULT;

    if (argc < 2)
    usage (argv[0]), exit (1);

    if (!OpenClipboard (NULL))
    fprintf (stderr, "OpenClipboard failed.\n"), exit (1);

    /* Traverse options twice, first set flags */
    for (i = 1; i < argc; i++)
    {
    if (strcmp (argv[i], "-i") == 0)
    {
    if (i + 1 == argc)
    usage (argv[0]), exit (1);

    i++;
    if (freopen (argv[i], "r", stdin) == NULL)
    fprintf (stderr, "Could not open %s for reading.\n", argv[i]), exit (1);
    }
    else if (strcmp (argv[i], "-o") == 0)
    {
    if (i + 1 == argc)
    usage (argv[0]), exit (1);

    i++;
    if (freopen (argv[i], "w", stdout) == NULL)
    fprintf (stderr, "Could not open %s for writing.\n", argv[i]), exit (1);
    }
    else if (strcmp (argv[i], "-n") == 0)
    {
    interpret_newlines = 0;
    }
    else if (strcmp (argv[i], "-u") == 0)
    {
    output_format = FORMAT_WSTRING;
    }
    else if (strcmp (argv[i], "-h") == 0)
    {
    output_format = FORMAT_HEX;
    }
    else if (strcmp (argv[i], "-b") == 0)
    {
    output_format = FORMAT_BINARY;
    }
    else if (strcmp (argv[i], "-g") == 0)
    {
    if (i + 1 == argc)
    usage (argv[0]), exit (1);

    i++;
    }
    else if (strcmp (argv[i], "-m") == 0)
    {
    if (argc < 3 || (maxdata = atoi (argv[i+1])) <= 0)
    usage (argv[0]), exit (1);
    }
    else if (strcmp (argv[i], "-p") == 0)
    {
    if (i + 1 == argc)
    usage (argv[0]), exit (1);
    }
    }

    /* Then interpret what to do */
    for (i = 1; i 0)
    {
    if (nread < buffer_size – in_use && ferror (stdin))
    fprintf (stderr, "Error reading after %d bytes.\n", in_use + nread), exit (1);
    in_use += nread;
    if (in_use == buffer_size)
    {
    buffer_size *= 1.5;
    GlobalUnlock (handle);
    if ((handle = GlobalReAlloc (handle, buffer_size, GMEM_MOVEABLE)) == NULL)
    fprintf (stderr, "GlobalReAlloc(%d) failed.\n", buffer_size), exit (1);
    buffer = GlobalLock (handle);
    }
    }

    GlobalUnlock (handle);
    if ((handle = GlobalReAlloc (handle, in_use, GMEM_MOVEABLE)) == NULL)
    fprintf (stderr, "GlobalReAlloc(%d) failed.\n", in_use), exit (1);

    if (SetClipboardData (format, handle) == NULL)
    fprintf (stderr, "GetClipboardData(%d) failed.\n", format), exit (1);

    GlobalUnlock (handle);

    }
    }

    CloseClipboard ();

    return 0;
    }

    1. Thanks Tor! It helps a lot. I’ve added your version to my post (so that it will stay after pastebin decides to delete it).

    2. Actually I’ve decided to put your code here instead of putting it in my post (to keep my post from being too long).

      #include <stdlib.h>
      #include <stdio.h>
      #include <io.h>
      #include <fcntl.h>
      #include <windows.h>
       
      #ifndef CF_DIBV5
      #define CF_DIBV5 17
      #endif
       
      #define MAXDATA 1000
       
      static int maxdata = MAXDATA;
      static int interpret_newlines = 1;
       
      typedef enum {
        FORMAT_DEFAULT,
        FORMAT_STRING,
        FORMAT_WSTRING,
        FORMAT_HEX,
        FORMAT_BINARY
      } output_format_type;
       
      const char *
      clipboard_format_name (UINT format)
      {
        static char bfr[100];
       
        if (GetClipboardFormatName (format, bfr, sizeof (bfr)))
          return bfr;
       
        if (format >= CF_GDIOBJFIRST && format <= CF_GDIOBJLAST)
          {
            sprintf (bfr, "CF_GDIOBJFIRST+%d", format - CF_GDIOBJFIRST);
            return bfr;
          }
       
        if (format >= CF_PRIVATEFIRST && format <= CF_PRIVATELAST)
          {
            sprintf (bfr, "CF_PRIVATEFIRST+%d", format - CF_PRIVATEFIRST);
            return bfr;
          }
       
        switch (format)
          {
      #define CASE(x) case CF_##x: return "CF_" # x
            CASE (BITMAP);
            CASE (DIB);
            CASE (DIBV5);
            CASE (DIF);
            CASE (DSPBITMAP);
            CASE (DSPENHMETAFILE);
            CASE (DSPMETAFILEPICT);
            CASE (DSPTEXT);
            CASE (ENHMETAFILE);
            CASE (HDROP);
            CASE (LOCALE);
            CASE (METAFILEPICT);
            CASE (OEMTEXT);
            CASE (OWNERDISPLAY);
            CASE (PALETTE);
            CASE (PENDATA);
            CASE (RIFF);
            CASE (SYLK);
            CASE (TEXT);
            CASE (WAVE);
            CASE (TIFF);
            CASE (UNICODETEXT);
      #undef CASE
          default:
            sprintf (bfr, "UNKNOWN");
            return bfr;
          }
      }
       
      static UINT
      parse_clipboard_format_name (const char *string)
      {
        UINT format;
       
        if ((format = atoi (string)) > 0)
          return format;
       
      #define CASE(x) if (strcmp (string, "CF_" # x) == 0) return CF_##x
        CASE (BITMAP);
        CASE (DIB);
        CASE (DIBV5);
        CASE (DIF);
        CASE (DSPBITMAP);
        CASE (DSPENHMETAFILE);
        CASE (DSPMETAFILEPICT);
        CASE (DSPTEXT);
        CASE (ENHMETAFILE);
        CASE (HDROP);
        CASE (LOCALE);
        CASE (METAFILEPICT);
        CASE (OEMTEXT);
        CASE (OWNERDISPLAY);
        CASE (PALETTE);
        CASE (PENDATA);
        CASE (RIFF);
        CASE (SYLK);
        CASE (TEXT);
        CASE (WAVE);
        CASE (TIFF);
        CASE (UNICODETEXT);
      #undef CASE
       
        while ((format = EnumClipboardFormats (format)))
          if (strcmp (string, clipboard_format_name (format)) == 0)
            return format;
       
        return 0;
      }
       
      static void
      print_string_data (const unsigned char *data,
                         size_t               size)
      {
        int i;
       
        for (i = 0; i < size; i++, data++)
          {
            if (i >= maxdata)
              break;
       
            switch (*data)
              {
              case 'a':
                printf ("a");
                break;
              case 'b':
                printf ("b");
                break;
              case 'f':
                printf ("f");
                break;
              case 'n':
                printf ("n");
                break;
              case 'r':
                if (interpret_newlines && data[1] == 'n')
                  {
                    printf ("n");
                    data++;
                  }
                else
                  printf ("r");
                break;
              case 't':
                printf ("t");
                break;
              case '':
                printf ("");
                break;
              default:
                if (*data >= ' ' && *data < 0177)
                  printf ("%c", *data);
                else
                  printf ("%03o", (int) *data);
              }
          }
      }
       
      static void
      print_unicode_data (const wchar_t *data,
                          size_t         size)
      {
        int i;
       
        for (i = 0; i < size; i++, data++)
          {
            if (i >= maxdata)
              break;
       
            switch (*data)
              {
              case 'a':
                printf ("a");
                break;
              case 'b':
                printf ("b");
                break;
              case 'f':
                printf ("f");
                break;
              case 'n':
                printf ("n");
                break;
              case 'r':
                if (interpret_newlines && data[1] == 'n')
                  {
                    printf ("n");
                    data++;
                  }
                else
                  printf ("r");
                break;
              case 't':
                printf ("t");
                break;
              case '':
                printf ("");
                break;
              default:
                if (*data >= ' ' && *data < 0177)
                  printf ("%c", *data);
                else
                  printf ("u%04x", *data);
              }
          }
      }
       
       
      static void
      print_hex_data (const unsigned int *data,
                      size_t              size)
      {
        int i;
       
        for (i = 0; i < size; i++, data++)
          {
            if (i >= maxdata)
              break;
       
            printf ("%08x", *data);
            if ((i % 8) == 7)
              printf ("n");
            else
              printf (" ");
          }  
      }
       
      static int 
      format_for_specific_handle (UINT format)
      {
        switch (format)
          {
          case CF_BITMAP:
          case CF_ENHMETAFILE:
          case CF_HDROP:
            return 1;
          }
        return 0;
      }
       
      static char *
      compression_type (DWORD compression)
      {
        static char buf[20];
       
        switch (compression)
          {
      #define CASE(x) case BI_##x: return "BI_"#x
            CASE (RGB);
            CASE (RLE8);
            CASE (RLE4);
            CASE (BITFIELDS);
            CASE (JPEG);
            CASE (PNG);
      #undef CASE
          default:
            sprintf (buf, "%#lx", compression);
            return buf;
          }
      }
       
      static int
      print_colors (const BITMAPINFOHEADER *bi,
                    const RGBQUAD          *rgb)
      {
        if (bi->biCompression == BI_BITFIELDS &&
            bi->biSize == sizeof (BITMAPINFOHEADER))
          {
            const DWORD *mask = (DWORD *) rgb;
       
            printf ("{%08lx,%08lx,%08lx}", mask[0], mask[1], mask[2]);
       
            return 3*4;
          }
       
        if (bi->biBitCount == 1)
          {
            int i;
       
            printf ("rgb[2]{");
            for (i = 0; i < 2; i++)
              {
                printf ("%02x%02x%02x}",
                        rgb[i].rgbRed, rgb[i].rgbGreen, rgb[i].rgbBlue);
                if (i == 0)
                  printf (",");
              }
            printf ("}");
       
            return 2*4;
          }
       
        if (bi->biBitCount == 4 || bi->biBitCount == 8)
          {
            int ncolors = 16;
            int i;
       
            if (bi->biClrUsed > 0)
              ncolors = bi->biClrUsed;
       
            printf ("rgb[%d]{", ncolors);
            for (i = 0; i < ncolors; i++)
              {
                printf ("%02x%02x%02x}",
                        rgb[i].rgbRed, rgb[i].rgbGreen, rgb[i].rgbBlue);
                if (i < ncolors-1)
                  printf (",");
              }
            printf ("}");
       
            return ncolors * 4;
          }
       
        printf ("{}");
        return 0;
      }
       
      static void
      print_dib (const void *data,
                 SIZE_T      size)
      {
        const BITMAPINFO *bmi = (BITMAPINFO *) data;
        int color_table_size;
        int image_size;
       
        printf ("bmi{n"
                " Header=n"
                " bi{n"
                "  Size=%ld, Width=%ld, Height=%ld, Planes=%d, BitCount=%d,n"
                "  Compression=%s, SizeImage=%ld, XPelsPerMeter=%ld, YPelsPerMeter=%ld,n"
                "  ClrUsed=%ld, ClrImportant=%ldn"
                " },Colors=",
                bmi->bmiHeader.biSize, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, bmi->bmiHeader.biPlanes, bmi->bmiHeader.biBitCount,
                compression_type (bmi->bmiHeader.biCompression),
                bmi->bmiHeader.biSizeImage, bmi->bmiHeader.biXPelsPerMeter, bmi->bmiHeader.biYPelsPerMeter,
                bmi->bmiHeader.biClrUsed, bmi->bmiHeader.biClrImportant);
       
        color_table_size = print_colors (&bmi->bmiHeader, bmi->bmiColors);
        image_size = ((((bmi->bmiHeader.biBitCount * bmi->bmiHeader.biWidth) / 8) + 3 ) &  ~3) * bmi->bmiHeader.biHeight;
        printf ("n"
                "},n");
        print_hex_data ((const unsigned int *)((char *) data +
                                               bmi->bmiHeader.biSize +
                                               color_table_size),
                        image_size/4);
      }
       
      static void
      print_dibv5 (const void *data,
                   SIZE_T      size)
      {
        const BITMAPV5HEADER *bV5 = (BITMAPV5HEADER *) data;
        int color_table_size;
        int image_size;
       
        printf ("bV5{n"
                " Size=%ld, Width=%ld, Height=%ld, Planes=%d, BitCount=%d,n"
                " Compression=%s, SizeImage=%ld, XPelsPerMeter=%ld, YPelsPerMeter=%ld,n"
                " ClrUsed=%ld, ClrImportant=%ld,n"
                " RedMask=%08lx, GreenMask=%08lx, BlueMask=%08lx, AlphaMask=%08lx,n"
                " CsType=%ld (%c%c%c%c)n"
                "},n",
                bV5->bV5Size, bV5->bV5Width, bV5->bV5Height, bV5->bV5Planes, bV5->bV5BitCount,
                compression_type (bV5->bV5Compression),
                bV5->bV5SizeImage, bV5->bV5XPelsPerMeter, bV5->bV5YPelsPerMeter,
                bV5->bV5ClrUsed, bV5->bV5ClrImportant,
                bV5->bV5RedMask, bV5->bV5GreenMask, bV5->bV5BlueMask, bV5->bV5AlphaMask,
                bV5->bV5CSType,
                ((char *)&bV5->bV5CSType)[3], ((char *)&bV5->bV5CSType)[2],
                ((char *)&bV5->bV5CSType)[1], ((char *)&bV5->bV5CSType)[0]);
        printf ("colortable");
        color_table_size = print_colors ((BITMAPINFOHEADER *) bV5,
                                         (RGBQUAD*) ((char *)bV5) + bV5->bV5Size);
        image_size = ((((bV5->bV5BitCount * bV5->bV5Width) / 8) + 3 ) &  ~3) * bV5->bV5Height;
        printf ("n");
        print_hex_data ((const unsigned int *)((char *) data +
                                               bV5->bV5Size +
                                               color_table_size),
                        image_size/4);
      }
       
      static void
      print_data (output_format_type   output_format,
                  UINT                 format,
                  const unsigned char *data,
                  SIZE_T               size)
      {
        switch (output_format)
          {
          case FORMAT_DEFAULT:
            switch (format)
              {
              case CF_DIB:
                print_dib (data, size);
                break;
              case CF_DIBV5:
                print_dibv5 (data, size);
                break;
              default:
                goto _FORMAT_STRING;
              }
            break;
          case FORMAT_STRING: _FORMAT_STRING:
            print_string_data (data, size);
            break;
          case FORMAT_WSTRING:
            print_unicode_data ((wchar_t *) data, (size+1)/2);
            break;
          case FORMAT_HEX:
            print_hex_data ((unsigned int *) data, (size+3)/4);
            break;
          case FORMAT_BINARY:
            _setmode (fileno (stdout), O_BINARY);
            fwrite (data, size, 1, stdout);
            return;
          }
        printf ("n");
      }
       
      static void
      print_format_for_specific_handle (UINT   format,
                                        HANDLE handle)
      {
        switch (format)
          {
          case CF_BITMAP:
            {
              HANDLE handle = GetClipboardData (format);
              BITMAP bm;
       
              if (!GetObject (handle, sizeof (BITMAP), (void *) &bm))
                fprintf (stderr, "GetObject failed.n"), exit (1);
       
              printf ("bm{n"
                      " Type=%ld, Width=%ld, Height=%ld, WidthBytes=%ld,n"
                      " Planes=%d, BitsPixel=%d,n"
                      " bmBits=",
                      bm.bmType, bm.bmWidth, bm.bmHeight, bm.bmWidthBytes,
                      bm.bmPlanes, bm.bmBitsPixel);
              if (bm.bmBits != NULL)
                print_data (FORMAT_HEX, CF_BITMAP, bm.bmBits, bm.bmHeight*bm.bmWidthBytes);
              else
                printf ("0");
              printf ("n"
                      "}");
            }
            break;
          default:
            printf ("%p", handle);
          }
      }
       
      static void
      usage (const char *progname)
      {
        fprintf (stderr, "Usage: %s [-m maxdata] [-b|-h|-n|-u|-i filename|-o filename]... (-l|-g format|-p format)n", progname);
      }
       
      int
      main (int    argc,
            char **argv)
      {
        UINT format = 0;
        HANDLE handle;
        int i;
        output_format_type output_format = FORMAT_DEFAULT;
       
        if (argc < 2)
          usage (argv[0]), exit (1);
       
        if (!OpenClipboard (NULL))
          fprintf (stderr, "OpenClipboard failed.n"), exit (1);
       
        /* Traverse options twice, first set flags */
        for (i = 1; i < argc; i++)
          {
            if (strcmp (argv[i], "-i") == 0)
              {
                if (i + 1 == argc)
                  usage (argv[0]), exit (1);
       
                i++;
                if (freopen (argv[i], "r", stdin) == NULL)
                  fprintf (stderr, "Could not open %s for reading.n", argv[i]), exit (1);
              }
            else if (strcmp (argv[i], "-o") == 0)
              {
                if (i + 1 == argc)
                  usage (argv[0]), exit (1);
       
                i++;
                if (freopen (argv[i], "w", stdout) == NULL)
                  fprintf (stderr, "Could not open %s for writing.n", argv[i]), exit (1);
              }
            else if (strcmp (argv[i], "-n") == 0)
              {
                interpret_newlines = 0;
              }
            else if (strcmp (argv[i], "-u") == 0)
              {
                output_format = FORMAT_WSTRING;
              }
            else if (strcmp (argv[i], "-h") == 0)
              {
                output_format = FORMAT_HEX;
              }
            else if (strcmp (argv[i], "-b") == 0)
              {
                output_format = FORMAT_BINARY;
              }
            else if (strcmp (argv[i], "-g") == 0)
              {
                if (i + 1 == argc)
                  usage (argv[0]), exit (1);
       
                i++;
              }
            else if (strcmp (argv[i], "-m") == 0)
              {
                if (argc < 3 || (maxdata = atoi (argv[i+1])) <= 0)
                  usage (argv[0]), exit (1);
              }
            else if (strcmp (argv[i], "-p") == 0)
              {
                if (i + 1 == argc)
                  usage (argv[0]), exit (1);
              }
          }
       
        /* Then interpret what to do */
        for (i = 1; i < argc; i++)
          {
            if (strcmp (argv[i], "-e") == 0)
              {
                if (!EmptyClipboard ())
                  fprintf (stderr, "EmptyClipboard() failed.n"), exit (1);
              }
            else if (strcmp (argv[i], "-l") == 0)
              {
                HWND owner = GetClipboardOwner ();
                DWORD owner_id = 0;
       
                if (owner == NULL)
                  printf ("no ownern");
                else if (GetWindowThreadProcessId (owner, &owner_id) != 0 && owner_id != 0)
                  printf ("owner: %p (pid: %ld)n", owner, owner_id);
                else
                  printf ("owner: %pn", owner);
       
                while ((format = EnumClipboardFormats (format)))
                  printf ("%d: %sn", format, clipboard_format_name (format));
              }
            else if (strcmp (argv[i], "-g") == 0)
              {
                if ((format = parse_clipboard_format_name (argv[i+1])) == 0)
                  fprintf (stderr, "Unrecognized clipboard format %s.n", argv[i+1]), exit (1);
       
                if ((handle = GetClipboardData (format)) == NULL)
                  fprintf (stderr, "GetClipboardData(%d) failed.n", format), exit (1);
       
                if (format_for_specific_handle (format))
                  {
                    print_format_for_specific_handle (format, handle);
                  }
                else
                  {
                    SIZE_T size;
                    unsigned char *data;
       
                    if ((size = GlobalSize (handle)) == 0)
                      fprintf (stderr, "GlobalSize(%p) failed.n", handle), exit (1);
       
                    if ((data = GlobalLock (handle)) == NULL)
                      fprintf (stderr, "GlobalLock(%p) failed.n", handle), exit (1);
                    print_data (output_format, format, data, size);
                    GlobalUnlock (handle);
                  }
       
                i++;
              }
            else if (strcmp (argv[i], "-p") == 0)
              {
                int buffer_size = 1000;
                int in_use = 0;
                int nread;
                char *buffer;
       
                if ((format = parse_clipboard_format_name (argv[i+1])) == 0)
                  {
                    if ((format = RegisterClipboardFormat (argv[i+1])) == 0)
                      fprintf (stderr, "RegisterClipboardFormat(%s) failed.n", argv[i+1]), exit (1);
                  }
       
                if ((handle = GlobalAlloc (GMEM_MOVEABLE, buffer_size)) == NULL)
                  fprintf (stderr, "GlobalAlloc(%d) failed.n", buffer_size), exit (1);
       
                buffer = GlobalLock (handle);
       
                if (output_format == FORMAT_BINARY)
                  _setmode (fileno (stdin), O_BINARY);
       
                while ((nread = fread (buffer + in_use, 1, buffer_size - in_use, stdin)) > 0)
                  {
                    if (nread < buffer_size - in_use && ferror (stdin))
                      fprintf (stderr, "Error reading after %d bytes.n", in_use + nread), exit (1);
                    in_use += nread;
                    if (in_use == buffer_size)
                      {
                        buffer_size *= 1.5;
                        GlobalUnlock (handle);
                        if ((handle = GlobalReAlloc (handle, buffer_size, GMEM_MOVEABLE)) == NULL)
                          fprintf (stderr, "GlobalReAlloc(%d) failed.n", buffer_size), exit (1);
                        buffer = GlobalLock (handle);
                      }
                  }
       
                GlobalUnlock (handle);
                if ((handle = GlobalReAlloc (handle, in_use, GMEM_MOVEABLE)) == NULL)
                  fprintf (stderr, "GlobalReAlloc(%d) failed.n", in_use), exit (1);
       
                if (SetClipboardData (format, handle) == NULL)
                  fprintf (stderr, "GetClipboardData(%d) failed.n", format), exit (1);
       
                GlobalUnlock (handle);
       
              }
          }
       
        CloseClipboard ();
       
        return 0;
      }
      1. BTW this plugin seems to work in the comments too.

        void do_foo()
        {
            return something;
        }

Comments are closed.