Windows clipboard dumper

Share Button

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++).

About Kohei Yoshida

LibreOffice hacker, spreadsheet nerd, and machine learning beginner.
This entry was posted in and tagged , , . Bookmark the permalink.

7 Responses to Windows clipboard dumper

  1. Tor Lillqvist says:

    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;
    }

  2. Tor Lillqvist says:

    Ah, sanely formatted: http://pastebin.com/4nieRnLa

    • Kohei Yoshida says:

      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).

    • Kohei Yoshida says:

      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;
      }
  3. Tran says:

    Hi! Can you tell me the way to present C code in the post? Thank you!

Comments are closed.