You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
438 lines
12 KiB
438 lines
12 KiB
/*++
|
|
|
|
|
|
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;
|
|
}
|