|
|
/*++
Copyright (C) Microsoft Corporation All rights reserved.
Module Name: clip.cpp
Abstract Clip.exe copies input from console standard input (stdin) to the Windows clipboard in CF_TEXT format.
Author:
Author: Charles Stacy Harris III Date: 15 March 1995
Revision History:
Oct 1996 - (a-martih) Resolved bug 15274 - reporting errors did not work.
Feb 1997 - (a-josehu) Resolved bug 69727 - app hangs when clip typed on cmd line Add -? /? Help message Remove MessageBox from ReportError
July 2nd 2001 - Wipro Technologies Changed to have the localization. Handled for exceptions.
--*/
#include "pch.h"
#include "resource.h"
//
// function prototypes
//
BOOL DisplayHelp(); DWORD Clip_OnCreate(); BYTE* ReadFileIntoMemory( HANDLE hFile, DWORD *cb ); BOOL SaveDataToClipboard( IN LPVOID pvData, IN DWORD dwSize, UINT uiFormat ); DWORD ProcessOptions( DWORD argc, LPCWSTR argv[], PBOOL pbUsage );
//
// implementation
//
DWORD __cdecl wmain( IN DWORD argc, IN LPCWSTR argv[] ) /*++
Routine description : main function which calls necessary functions to copy the contents of standart input file onto clipboard
Arguments : Standard arguments for wmain
Return Value : DWORD 0 : if it is successful 1 : if it is failure --*/ { DWORD dwStatus = 0; BOOL bUsage = FALSE;
// process the command line options
dwStatus = ProcessOptions( argc, argv, &bUsage );
// check the result
if( EXIT_FAILURE == dwStatus ) { ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL ); }
// parser will not allow this situation -- but still better to check
else if( TRUE == bUsage && argc > 2 ) { SetLastError( (DWORD) MK_E_SYNTAX ); ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL ); ShowMessage( stderr, GetResString2( IDS_HELP_MESSAGE, 0 ) ); dwStatus = EXIT_FAILURE; }
// user requested to display the usage
else if( TRUE == bUsage ) { dwStatus = EXIT_SUCCESS; DisplayHelp(); }
// original functionality
else if ( dwStatus == EXIT_SUCCESS ) { dwStatus = Clip_OnCreate(); }
ReleaseGlobals(); return dwStatus; }
DWORD Clip_OnCreate() /*++
Routine Description : copies the contents of clipboard 1. Open the clipboard 2. Empty the clipboard 3. Copy stdin into memory 4. Set the clipboard data
Arguments: [ in ] argc : argument count [ in ] argv : a pointer to command line argument
Return Type : DWORD returns EXIT_SUCCESS or EXIT_FAILURE according copying to clipboard successful or not. --*/ { DWORD dwSize = 0; LONG lLength = 0; LPVOID pvData = NULL; LPWSTR pwszBuffer = NULL; HANDLE hStdInput = NULL; BOOL bResult = FALSE; UINT uiFormat = 0;
hStdInput = GetStdHandle( STD_INPUT_HANDLE ); if( INVALID_HANDLE_VALUE == hStdInput ) { return EXIT_FAILURE; }
if ( FILE_TYPE_CHAR == GetFileType( hStdInput ) ) // bug 69727
{ // error with GetStdHandle()
ShowMessageEx( stdout, 2, TRUE, L"\n%s %s", TAG_INFORMATION, GetResString2( IDS_HELP_MESSAGE, 0 ) ); return EXIT_SUCCESS; }
//place the contents in a global memory from stdin
pvData = ReadFileIntoMemory( hStdInput, &dwSize );
//check for allocation failed or not
if( NULL == pvData ) { ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_SYSTEM ); return EXIT_FAILURE; }
//convert contents into console code page if they are unicode
uiFormat = CF_UNICODETEXT; if ( IsTextUnicode( pvData, dwSize, NULL ) == FALSE ) { lLength = MultiByteToWideChar( GetConsoleOutputCP(), 0, (LPCSTR) pvData, -1, NULL, 0);
if( lLength > 0 ) { pwszBuffer = (LPWSTR) AllocateMemory( (lLength + 5) * sizeof(WCHAR) ); if( pwszBuffer == NULL ) { ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_SYSTEM ); FreeMemory( &pvData ); return EXIT_FAILURE; }
lLength = MultiByteToWideChar( GetConsoleOutputCP(), 0, (LPCSTR) pvData, -1, pwszBuffer, lLength ); if ( lLength <= 0 ) { ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_SYSTEM ); FreeMemory( &pvData ); FreeMemory( (LPVOID*) &pwszBuffer ); return EXIT_FAILURE; }
dwSize = lLength * sizeof( WCHAR ); FreeMemory( &pvData ); pvData = pwszBuffer; } else { uiFormat = CF_TEXT; } }
bResult = SaveDataToClipboard( pvData, dwSize, uiFormat ); if ( bResult == FALSE ) { ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL ); }
// release the memory
FreeMemory( &pvData );
return (bResult == TRUE ) ? EXIT_SUCCESS : EXIT_FAILURE; }
BOOL SaveDataToClipboard( IN LPVOID pvData, IN DWORD dwSize, UINT uiFormat ) /*++
Routine Description : It places the data into clipboard.
Arguments: [ in ] pvData : Pointer to memory block whose contents are to be placed into clipboard. [ in ] dwSize : Size of the memory block. [ in ] uiFormat : format that needs to copied onto the clipboard Return Value: Returns TRUE if successfully saves, FALSE otherwise. --*/ { // local variables
HANDLE hClipData = NULL; HGLOBAL hGlobalMemory = NULL; LPVOID pvGlobalMemoryBuffer = NULL;
// check the input
if ( pvData == NULL || dwSize == 0 ) { SetLastError( ERROR_INVALID_PARAMETER ); SaveLastError(); return FALSE; }
//open the clipboard and display error if it fails
if( OpenClipboard( NULL ) == FALSE ) { SaveLastError(); return FALSE; }
//take the ownership for this window on clipboard and display
//error if it fails
if( EmptyClipboard() == FALSE ) { SaveLastError(); CloseClipboard(); return FALSE; }
hGlobalMemory = GlobalAlloc( GMEM_SHARE | GMEM_MOVEABLE, dwSize + 10 ); if( hGlobalMemory == NULL ) { SaveLastError(); CloseClipboard(); return FALSE; }
if ( (pvGlobalMemoryBuffer = GlobalLock( hGlobalMemory )) == NULL ) { SaveLastError(); GlobalFree( hGlobalMemory ); CloseClipboard(); return FALSE; }
SecureZeroMemory( pvGlobalMemoryBuffer, dwSize + 10 ); CopyMemory( pvGlobalMemoryBuffer, pvData, dwSize );
if( FALSE == GlobalUnlock( hGlobalMemory ) ) { if ( GetLastError() != NO_ERROR ) { SaveLastError(); GlobalFree( hGlobalMemory ); CloseClipboard(); return FALSE; } }
hClipData = SetClipboardData( uiFormat, hGlobalMemory ); if( NULL == hClipData ) { SaveLastError(); GlobalFree( hGlobalMemory ); CloseClipboard(); return FALSE; }
//close the clipboard and display error if it fails
CloseClipboard();
GlobalFree( hGlobalMemory ); return TRUE; }
DWORD ProcessOptions( IN DWORD argc, IN LPCWSTR argv[], OUT PBOOL pbUsage ) /*++
Routine Description : Function used to process the main options
Arguments: [ in ] argc : Number of command line arguments [ in ] argv : Array containing command line arguments [ out ] pbUsage : Pointer to boolean variable returns true if usage option specified in the command line.
Return Type : DWORD A Integer value indicating EXIT_SUCCESS on successful parsing of command line else EXIT_FAILURE
--*/ { DWORD dwOptionsCount = 0; TCMDPARSER2 cmdOptions[ 1 ];
dwOptionsCount = SIZE_OF_ARRAY( cmdOptions ); SecureZeroMemory( cmdOptions, sizeof( TCMDPARSER2 ) * dwOptionsCount );
StringCopyA( cmdOptions[ 0 ].szSignature, "PARSER2", 8 ); cmdOptions[ 0 ].dwCount = 1; cmdOptions[ 0 ].dwFlags = CP2_USAGE; cmdOptions[ 0 ].dwType = CP_TYPE_BOOLEAN; cmdOptions[ 0 ].pValue = pbUsage; cmdOptions[ 0 ].pwszOptions = L"?";
if( DoParseParam2( argc, argv, -1, dwOptionsCount, cmdOptions, 0 ) == FALSE ) { return EXIT_FAILURE; }
SetLastError( ERROR_SUCCESS ); return EXIT_SUCCESS; }
/*
ReadFileIntoMemory ~~~~~~~~~~~~~~~~~~ Read the contents of a file into GMEM_SHARE memory. This function could be modified to take allocation flags as a parameter. */ BYTE* ReadFileIntoMemory( IN HANDLE hFile, OUT DWORD* pdwBytes ) /*++
Routine Description : Read the contents of a file into GMEM_SHARE memory. This function could be modified to take allocation flags as a parameter. Arguments: [ in ] hFile : Handle to a file which is nothing but handle to stdin file. [ out] cb : returns the copied buffer length
Return Type : Handle to memory object.
--*/ { BYTE* pb = NULL; DWORD dwNew = 0; DWORD dwRead = 0; DWORD dwAlloc = 0; const size_t dwGrow = 1024;
// check the inputs
if ( hFile == NULL || pdwBytes == NULL ) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; }
do { if ( dwAlloc - dwRead < dwGrow ) { dwAlloc += dwGrow; if( NULL == pb ) { pb = (BYTE*) AllocateMemory( dwAlloc + 10 ); } else if( FALSE == ReallocateMemory( (LPVOID*) &pb, dwAlloc + 10 ) ) { FreeMemory( (LPVOID*) &pb ); SetLastError( ERROR_OUTOFMEMORY ); return NULL; } }
if ( FALSE == ReadFile( hFile, pb + dwRead, (dwAlloc - dwRead), &dwNew, 0 ) ) { break; }
dwRead += dwNew; } while (dwNew != 0 );
*pdwBytes = dwRead; SecureZeroMemory( pb + dwRead, (dwAlloc - dwRead) ); SetLastError( ERROR_SUCCESS ); return pb; }
BOOL DisplayHelp() /*++
Routine Description : Displays the help usage to console or to file if redirected.
Arguments:
Return Type : EXIT_SUCCESS if successful,EXIT_FAILURE otherwise.
--*/
{ //changing the help by taking the strings from resource file
for( DWORD dw=IDS_MAIN_HELP_BEGIN;dw<=IDS_MAIN_HELP_END;dw++) { ShowMessage( stdout, GetResString2( dw, 0 ) ); }
SetLastError( ERROR_SUCCESS ); return TRUE; }
|