diff --git a/reactos/base/applications/cmdutils/CMakeLists.txt b/reactos/base/applications/cmdutils/CMakeLists.txt index 782baed5919..473ac1ff13a 100644 --- a/reactos/base/applications/cmdutils/CMakeLists.txt +++ b/reactos/base/applications/cmdutils/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(clip) add_subdirectory(comp) add_subdirectory(cscript) add_subdirectory(dbgprint) diff --git a/reactos/base/applications/cmdutils/clip/CMakeLists.txt b/reactos/base/applications/cmdutils/clip/CMakeLists.txt new file mode 100644 index 00000000000..53b3991b620 --- /dev/null +++ b/reactos/base/applications/cmdutils/clip/CMakeLists.txt @@ -0,0 +1,5 @@ + +add_executable(clip clip.c clip.rc) +set_module_type(clip win32cui UNICODE) +add_importlibs(clip user32 msvcrt kernel32 advapi32) +add_cd_file(TARGET clip DESTINATION reactos/system32 FOR all) diff --git a/reactos/base/applications/cmdutils/clip/clip.c b/reactos/base/applications/cmdutils/clip/clip.c new file mode 100644 index 00000000000..237cac30579 --- /dev/null +++ b/reactos/base/applications/cmdutils/clip/clip.c @@ -0,0 +1,137 @@ +#include + +#include +#include +#include + +#include "resource.h" + +static void PrintError(void) +{ + DWORD dwError; + LPWSTR lpMsgBuf = NULL; + + dwError = GetLastError(); + if (dwError == NO_ERROR) + return; + + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, dwError, 0, (LPWSTR)&lpMsgBuf, 0, NULL); + wprintf(L"%s", lpMsgBuf); + LocalFree(lpMsgBuf); +} + +static void PrintResourceString(UINT uID) +{ + WCHAR buff[500]; + + if (LoadStringW(GetModuleHandle(NULL), uID, buff, ARRAYSIZE(buff))) + { + wprintf(L"%s", buff); + } +} + +static BOOL IsDataUnicode(HGLOBAL hGlobal) +{ + BOOL bReturn; + LPVOID lpBuffer; + + lpBuffer = GlobalLock(hGlobal); + bReturn = IsTextUnicode(lpBuffer, GlobalSize(hGlobal), NULL); + GlobalUnlock(hGlobal); + + return bReturn; +} + +int wmain(int argc, wchar_t** argv) +{ + HANDLE hInput; + DWORD dwBytesRead; + BOOL bStatus; + HGLOBAL hBuffer; + HGLOBAL hTemp; + LPBYTE lpBuffer; + SIZE_T dwSize = 0; + + hInput = GetStdHandle(STD_INPUT_HANDLE); + + /* Check for usage */ + if (argc > 1 && wcsncmp(argv[1], L"/?", 2) == 0) + { + PrintResourceString(IDS_HELP); + return 0; + } + + if (GetFileType(hInput) == FILE_TYPE_CHAR) + { + PrintResourceString(IDS_USAGE); + return 0; + } + + /* Initialize a growable buffer for holding clipboard data */ + hBuffer = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 4096); + if (!hBuffer) + { + PrintError(); + return -1; + } + + /* + * Read data from the input stream by chunks of 4096 bytes + * and resize the buffer each time when needed. + */ + do + { + lpBuffer = GlobalLock(hBuffer); + if (!lpBuffer) + goto cleanup; + + bStatus = ReadFile(hInput, lpBuffer + dwSize, 4096, &dwBytesRead, NULL); + dwSize += dwBytesRead; + GlobalUnlock(hBuffer); + + hTemp = GlobalReAlloc(hBuffer, GlobalSize(hBuffer) + 4096, GMEM_ZEROINIT); + if (!hTemp) + goto cleanup; + + hBuffer = hTemp; + } + while (dwBytesRead > 0 && bStatus); + + /* + * Resize the buffer to the total size of data read. + * Note that, if the call fails, we still have the old buffer valid. + * The old buffer would be larger than the actual size of data it contains, + * but this is not a problem for us. + */ + hTemp = GlobalReAlloc(hBuffer, dwSize + sizeof(WCHAR), GMEM_ZEROINIT); + if (hTemp) + hBuffer = hTemp; + + /* Attempt to open the clipboard */ + if (!OpenClipboard(NULL)) + goto cleanup; + + /* Empty it, copy our data, then close it */ + + EmptyClipboard(); + + if (IsDataUnicode(hBuffer)) + { + SetClipboardData(CF_UNICODETEXT, hBuffer); + } + else + { + // TODO: Convert text from current console page to standard ANSI. + // Alternatively one can use CF_OEMTEXT as done here. + SetClipboardData(CF_OEMTEXT, hBuffer); + } + + CloseClipboard(); + return 0; + +cleanup: + GlobalFree(hBuffer); + PrintError(); + return -1; +} diff --git a/reactos/base/applications/cmdutils/clip/clip.rc b/reactos/base/applications/cmdutils/clip/clip.rc new file mode 100644 index 00000000000..88cfa9821ee --- /dev/null +++ b/reactos/base/applications/cmdutils/clip/clip.rc @@ -0,0 +1,21 @@ +#include + +#include "resource.h" + +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Clip Command" +#define REACTOS_STR_INTERNAL_NAME "clip" +#define REACTOS_STR_ORIGINAL_FILENAME "clip.exe" +#include + +/* UTF-8 */ +#pragma code_page(65001) + +#ifdef LANGUAGE_DE_DE + #include "lang/de-DE.rc" +#endif +#ifdef LANGUAGE_EN_US + #include "lang/en-US.rc" +#endif +#ifdef LANGUAGE_FR_FR + #include "lang/fr-FR.rc" +#endif diff --git a/reactos/base/applications/cmdutils/clip/lang/de-DE.rc b/reactos/base/applications/cmdutils/clip/lang/de-DE.rc new file mode 100644 index 00000000000..eeac1360385 --- /dev/null +++ b/reactos/base/applications/cmdutils/clip/lang/de-DE.rc @@ -0,0 +1,9 @@ +LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL + +STRINGTABLE +BEGIN + IDS_USAGE "\nGeben Sie ""CLIP /?"" ein, um die Syntax anzuzeigen.\n" + IDS_HELP "\nLeitet die Ausgabe von Befehlszeilenprogrammen in die Zwischenablage um.\n\n\ +CLIP [/?]\n\n\ + /? Zeigt diese Hilfe an.\n" +END diff --git a/reactos/base/applications/cmdutils/clip/lang/en-US.rc b/reactos/base/applications/cmdutils/clip/lang/en-US.rc new file mode 100644 index 00000000000..e51837a988a --- /dev/null +++ b/reactos/base/applications/cmdutils/clip/lang/en-US.rc @@ -0,0 +1,9 @@ +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +STRINGTABLE +BEGIN + IDS_USAGE "\nType ""CLIP /?"" for usage information.\n" + IDS_HELP "\nRedirects the output of command line programs to the clipboard.\n\n\ +CLIP [/?]\n\n\ + /? Show this help message.\n" +END diff --git a/reactos/base/applications/cmdutils/clip/lang/fr-FR.rc b/reactos/base/applications/cmdutils/clip/lang/fr-FR.rc new file mode 100644 index 00000000000..aed414397f6 --- /dev/null +++ b/reactos/base/applications/cmdutils/clip/lang/fr-FR.rc @@ -0,0 +1,9 @@ +LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL + +STRINGTABLE +BEGIN + IDS_USAGE "\nEntrez ""CLIP /?"" pour afficher la syntaxe.\n" + IDS_HELP "\nRedirige la sortie des programmes en ligne de commande vers le Presse-Papiers.\n\n\ +CLIP [/?]\n\n\ + /? Affiche ce message d'aide.\n" +END diff --git a/reactos/base/applications/cmdutils/clip/resource.h b/reactos/base/applications/cmdutils/clip/resource.h new file mode 100644 index 00000000000..026f35f5a61 --- /dev/null +++ b/reactos/base/applications/cmdutils/clip/resource.h @@ -0,0 +1,4 @@ +#pragma once + +#define IDS_USAGE 100 +#define IDS_HELP 101