Skip to content

Instantly share code, notes, and snippets.

@YaLTeR
Last active August 29, 2015 14:26
Show Gist options
  • Save YaLTeR/33913232dec8cc80de36 to your computer and use it in GitHub Desktop.
Save YaLTeR/33913232dec8cc80de36 to your computer and use it in GitHub Desktop.
A tool to read and write the Skype quote clipboard.
#include <cstring>
#include <iostream>
#include <memory>
#include <Windows.h>
using std::cerr;
using std::cin;
using std::cout;
void ProcessSMF(UINT format) {
auto data = GetClipboardData(format);
if (!data) {
cerr << "Error getting the clipboard data: " << GetLastError() << "\n";
return;
}
auto size = GlobalSize(data);
if (!size) {
cerr << "Error getting the clipboard data size: " << GetLastError() << "\n";
return;
}
auto ptr = GlobalLock(data);
if (!ptr) {
cerr << "Error locking the clipboard data: " << GetLastError() << "\n";
return;
}
auto copiedString = reinterpret_cast<char*>(std::malloc(size + 1));
copiedString[size] = 0; // Add 0 manually for correct output.
std::memcpy(copiedString, ptr, size);
// Don't worry if the clipboard data was locked more than once.
if (!GlobalUnlock(data)) {
auto err = GetLastError();
if (err != NO_ERROR)
cerr << "Error unlocking the clipboard data: " << GetLastError() << "\n";
}
cout << copiedString;
std::free(copiedString);
}
void usage() {
cerr << "Usage:\n\tSkypeClipboard.exe -i\t- Read from stdin, put into the clipboard.\n\tSkypeClipboard.exe -o\t- Read from the clipboard, put into stdout.\n";
}
int main(int argc, char* argv[]) {
if (argc != 2 || std::strlen(argv[1]) != 2) {
usage();
return 1;
}
switch (argv[1][1]) {
case 'o':
{
if (!OpenClipboard(NULL)) {
cerr << "Error opening clipboard: " << GetLastError() << "\n";
return 1;
}
auto format = EnumClipboardFormats(0);
for (;;) {
if (!format) {
auto error = GetLastError();
if (error != ERROR_SUCCESS) {
cerr << "Error enumerating clipboard formats: " << error << "\n";
return 1;
}
break;
}
char formatName[21];
if (GetClipboardFormatNameA(format, formatName, sizeof(formatName)) && !std::strcmp(formatName, "SkypeMessageFragment"))
ProcessSMF(format);
format = EnumClipboardFormats(format);
}
if (!CloseClipboard())
cerr << "Error closing clipboard: " << GetLastError() << "\n";
} break;
case 'i':
{
auto console_window = GetConsoleWindow();
if (!console_window) {
cerr << "Error getting console window: " << GetLastError() << "\n";
return 1;
}
auto format = RegisterClipboardFormat(TEXT("SkypeMessageFragment"));
if (!format) {
cerr << "Error registering the clipboard format: " << GetLastError() << "\n";
return 1;
}
cin.seekg(0, std::ios::end);
auto size = cin.tellg();
cin.seekg(0, std::ios::beg);
auto data = GlobalAlloc(GMEM_MOVEABLE, size);
if (!data) {
cerr << "Error allocating memory: " << GetLastError() << "\n";
return 1;
}
auto ptr = GlobalLock(data);
if (!ptr) {
cerr << "Error locking memory: " << GetLastError() << "\n";
if (GlobalFree(data))
cerr << "Error freeing memory: " << GetLastError() << "\n";
return 1;
}
cin.read(reinterpret_cast<char*>(ptr), size);
if (GlobalUnlock(data)) {
cerr << "Error: memory was locked more than once.\n";
if (GlobalFree(data))
cerr << "Error freeing memory: " << GetLastError() << "\n";
return 1;
} else {
auto err = GetLastError();
if (err != NO_ERROR) {
cerr << "Error unlocking memory: " << GetLastError() << "\n";
if (GlobalFree(data))
cerr << "Error freeing memory: " << GetLastError() << "\n";
return 1;
}
}
if (!OpenClipboard(console_window)) {
cerr << "Error opening clipboard: " << GetLastError() << "\n";
return 1;
}
if (!SetClipboardData(format, data)) {
cerr << "Error setting clipboard data: " << GetLastError() << "\n";
return 1;
}
if (!CloseClipboard())
cerr << "Error closing clipboard: " << GetLastError() << "\n";
} break;
default:
{
usage();
return 1;
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment