Last active
August 29, 2015 14:26
-
-
Save YaLTeR/33913232dec8cc80de36 to your computer and use it in GitHub Desktop.
A tool to read and write the Skype quote clipboard.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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