Leaked source code of windows server 2003
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

  1. /*++
  2. Copyright (C) Microsoft Corporation
  3. All rights reserved.
  4. Module Name: clip.cpp
  5. Abstract
  6. Clip.exe copies input from console standard input (stdin)
  7. to the Windows clipboard in CF_TEXT format.
  8. Author:
  9. Author: Charles Stacy Harris III
  10. Date: 15 March 1995
  11. Revision History:
  12. Oct 1996 - (a-martih)
  13. Resolved bug 15274 - reporting errors did not work.
  14. Feb 1997 - (a-josehu)
  15. Resolved bug 69727 - app hangs when clip typed on cmd line
  16. Add -? /? Help message
  17. Remove MessageBox from ReportError
  18. July 2nd 2001 - Wipro Technologies
  19. Changed to have the localization.
  20. Handled for exceptions.
  21. --*/
  22. #include "pch.h"
  23. #include "resource.h"
  24. //
  25. // function prototypes
  26. //
  27. BOOL DisplayHelp();
  28. DWORD Clip_OnCreate();
  29. BYTE* ReadFileIntoMemory( HANDLE hFile, DWORD *cb );
  30. BOOL SaveDataToClipboard( IN LPVOID pvData, IN DWORD dwSize, UINT uiFormat );
  31. DWORD ProcessOptions( DWORD argc, LPCWSTR argv[], PBOOL pbUsage );
  32. //
  33. // implementation
  34. //
  35. DWORD
  36. __cdecl wmain( IN DWORD argc,
  37. IN LPCWSTR argv[] )
  38. /*++
  39. Routine description : main function which calls necessary functions to copy the
  40. contents of standart input file onto clipboard
  41. Arguments : Standard arguments for wmain
  42. Return Value : DWORD
  43. 0 : if it is successful
  44. 1 : if it is failure
  45. --*/
  46. {
  47. DWORD dwStatus = 0;
  48. BOOL bUsage = FALSE;
  49. // process the command line options
  50. dwStatus = ProcessOptions( argc, argv, &bUsage );
  51. // check the result
  52. if( EXIT_FAILURE == dwStatus )
  53. {
  54. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  55. }
  56. // parser will not allow this situation -- but still better to check
  57. else if( TRUE == bUsage && argc > 2 )
  58. {
  59. SetLastError( (DWORD) MK_E_SYNTAX );
  60. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  61. ShowMessage( stderr, GetResString2( IDS_HELP_MESSAGE, 0 ) );
  62. dwStatus = EXIT_FAILURE;
  63. }
  64. // user requested to display the usage
  65. else if( TRUE == bUsage )
  66. {
  67. dwStatus = EXIT_SUCCESS;
  68. DisplayHelp();
  69. }
  70. // original functionality
  71. else if ( dwStatus == EXIT_SUCCESS )
  72. {
  73. dwStatus = Clip_OnCreate();
  74. }
  75. ReleaseGlobals();
  76. return dwStatus;
  77. }
  78. DWORD
  79. Clip_OnCreate()
  80. /*++
  81. Routine Description : copies the contents of clipboard
  82. 1. Open the clipboard
  83. 2. Empty the clipboard
  84. 3. Copy stdin into memory
  85. 4. Set the clipboard data
  86. Arguments:
  87. [ in ] argc : argument count
  88. [ in ] argv : a pointer to command line argument
  89. Return Type : DWORD
  90. returns EXIT_SUCCESS or EXIT_FAILURE according copying to clipboard
  91. successful or not.
  92. --*/
  93. {
  94. DWORD dwSize = 0;
  95. LONG lLength = 0;
  96. LPVOID pvData = NULL;
  97. LPWSTR pwszBuffer = NULL;
  98. HANDLE hStdInput = NULL;
  99. BOOL bResult = FALSE;
  100. UINT uiFormat = 0;
  101. hStdInput = GetStdHandle( STD_INPUT_HANDLE );
  102. if( INVALID_HANDLE_VALUE == hStdInput )
  103. {
  104. return EXIT_FAILURE;
  105. }
  106. if ( FILE_TYPE_CHAR == GetFileType( hStdInput ) ) // bug 69727
  107. {
  108. // error with GetStdHandle()
  109. ShowMessageEx( stdout, 2, TRUE, L"\n%s %s",
  110. TAG_INFORMATION, GetResString2( IDS_HELP_MESSAGE, 0 ) );
  111. return EXIT_SUCCESS;
  112. }
  113. //place the contents in a global memory from stdin
  114. pvData = ReadFileIntoMemory( hStdInput, &dwSize );
  115. //check for allocation failed or not
  116. if( NULL == pvData )
  117. {
  118. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_SYSTEM );
  119. return EXIT_FAILURE;
  120. }
  121. //convert contents into console code page if they are unicode
  122. uiFormat = CF_UNICODETEXT;
  123. if ( IsTextUnicode( pvData, dwSize, NULL ) == FALSE )
  124. {
  125. lLength = MultiByteToWideChar(
  126. GetConsoleOutputCP(), 0, (LPCSTR) pvData, -1, NULL, 0);
  127. if( lLength > 0 )
  128. {
  129. pwszBuffer = (LPWSTR) AllocateMemory( (lLength + 5) * sizeof(WCHAR) );
  130. if( pwszBuffer == NULL )
  131. {
  132. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_SYSTEM );
  133. FreeMemory( &pvData );
  134. return EXIT_FAILURE;
  135. }
  136. lLength = MultiByteToWideChar(
  137. GetConsoleOutputCP(), 0, (LPCSTR) pvData, -1, pwszBuffer, lLength );
  138. if ( lLength <= 0 )
  139. {
  140. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_SYSTEM );
  141. FreeMemory( &pvData );
  142. FreeMemory( (LPVOID*) &pwszBuffer );
  143. return EXIT_FAILURE;
  144. }
  145. dwSize = lLength * sizeof( WCHAR );
  146. FreeMemory( &pvData );
  147. pvData = pwszBuffer;
  148. }
  149. else
  150. {
  151. uiFormat = CF_TEXT;
  152. }
  153. }
  154. bResult = SaveDataToClipboard( pvData, dwSize, uiFormat );
  155. if ( bResult == FALSE )
  156. {
  157. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  158. }
  159. // release the memory
  160. FreeMemory( &pvData );
  161. return (bResult == TRUE ) ? EXIT_SUCCESS : EXIT_FAILURE;
  162. }
  163. BOOL
  164. SaveDataToClipboard( IN LPVOID pvData,
  165. IN DWORD dwSize,
  166. UINT uiFormat )
  167. /*++
  168. Routine Description :
  169. It places the data into clipboard.
  170. Arguments:
  171. [ in ] pvData : Pointer to memory block whose contents are to
  172. be placed into clipboard.
  173. [ in ] dwSize : Size of the memory block.
  174. [ in ] uiFormat : format that needs to copied onto the clipboard
  175. Return Value:
  176. Returns TRUE if successfully saves,
  177. FALSE otherwise.
  178. --*/
  179. {
  180. // local variables
  181. HANDLE hClipData = NULL;
  182. HGLOBAL hGlobalMemory = NULL;
  183. LPVOID pvGlobalMemoryBuffer = NULL;
  184. // check the input
  185. if ( pvData == NULL || dwSize == 0 )
  186. {
  187. SetLastError( ERROR_INVALID_PARAMETER );
  188. SaveLastError();
  189. return FALSE;
  190. }
  191. //open the clipboard and display error if it fails
  192. if( OpenClipboard( NULL ) == FALSE )
  193. {
  194. SaveLastError();
  195. return FALSE;
  196. }
  197. //take the ownership for this window on clipboard and display
  198. //error if it fails
  199. if( EmptyClipboard() == FALSE )
  200. {
  201. SaveLastError();
  202. CloseClipboard();
  203. return FALSE;
  204. }
  205. hGlobalMemory = GlobalAlloc( GMEM_SHARE | GMEM_MOVEABLE, dwSize + 10 );
  206. if( hGlobalMemory == NULL )
  207. {
  208. SaveLastError();
  209. CloseClipboard();
  210. return FALSE;
  211. }
  212. if ( (pvGlobalMemoryBuffer = GlobalLock( hGlobalMemory )) == NULL )
  213. {
  214. SaveLastError();
  215. GlobalFree( hGlobalMemory );
  216. CloseClipboard();
  217. return FALSE;
  218. }
  219. SecureZeroMemory( pvGlobalMemoryBuffer, dwSize + 10 );
  220. CopyMemory( pvGlobalMemoryBuffer, pvData, dwSize );
  221. if( FALSE == GlobalUnlock( hGlobalMemory ) )
  222. {
  223. if ( GetLastError() != NO_ERROR )
  224. {
  225. SaveLastError();
  226. GlobalFree( hGlobalMemory );
  227. CloseClipboard();
  228. return FALSE;
  229. }
  230. }
  231. hClipData = SetClipboardData( uiFormat, hGlobalMemory );
  232. if( NULL == hClipData )
  233. {
  234. SaveLastError();
  235. GlobalFree( hGlobalMemory );
  236. CloseClipboard();
  237. return FALSE;
  238. }
  239. //close the clipboard and display error if it fails
  240. CloseClipboard();
  241. GlobalFree( hGlobalMemory );
  242. return TRUE;
  243. }
  244. DWORD
  245. ProcessOptions( IN DWORD argc,
  246. IN LPCWSTR argv[],
  247. OUT PBOOL pbUsage )
  248. /*++
  249. Routine Description : Function used to process the main options
  250. Arguments:
  251. [ in ] argc : Number of command line arguments
  252. [ in ] argv : Array containing command line arguments
  253. [ out ] pbUsage : Pointer to boolean variable returns true if
  254. usage option specified in the command line.
  255. Return Type : DWORD
  256. A Integer value indicating EXIT_SUCCESS on successful parsing of
  257. command line else EXIT_FAILURE
  258. --*/
  259. {
  260. DWORD dwOptionsCount = 0;
  261. TCMDPARSER2 cmdOptions[ 1 ];
  262. dwOptionsCount = SIZE_OF_ARRAY( cmdOptions );
  263. SecureZeroMemory( cmdOptions, sizeof( TCMDPARSER2 ) * dwOptionsCount );
  264. StringCopyA( cmdOptions[ 0 ].szSignature, "PARSER2", 8 );
  265. cmdOptions[ 0 ].dwCount = 1;
  266. cmdOptions[ 0 ].dwFlags = CP2_USAGE;
  267. cmdOptions[ 0 ].dwType = CP_TYPE_BOOLEAN;
  268. cmdOptions[ 0 ].pValue = pbUsage;
  269. cmdOptions[ 0 ].pwszOptions = L"?";
  270. if( DoParseParam2( argc, argv, -1,
  271. dwOptionsCount, cmdOptions, 0 ) == FALSE )
  272. {
  273. return EXIT_FAILURE;
  274. }
  275. SetLastError( ERROR_SUCCESS );
  276. return EXIT_SUCCESS;
  277. }
  278. /*
  279. ReadFileIntoMemory
  280. ~~~~~~~~~~~~~~~~~~
  281. Read the contents of a file into GMEM_SHARE memory.
  282. This function could be modified to take allocation flags
  283. as a parameter.
  284. */
  285. BYTE*
  286. ReadFileIntoMemory( IN HANDLE hFile,
  287. OUT DWORD* pdwBytes )
  288. /*++
  289. Routine Description : Read the contents of a file into GMEM_SHARE memory.
  290. This function could be modified to take allocation
  291. flags as a parameter.
  292. Arguments:
  293. [ in ] hFile : Handle to a file which is nothing but handle to
  294. stdin file.
  295. [ out] cb : returns the copied buffer length
  296. Return Type : Handle to memory object.
  297. --*/
  298. {
  299. BYTE* pb = NULL;
  300. DWORD dwNew = 0;
  301. DWORD dwRead = 0;
  302. DWORD dwAlloc = 0;
  303. const size_t dwGrow = 1024;
  304. // check the inputs
  305. if ( hFile == NULL || pdwBytes == NULL )
  306. {
  307. SetLastError( ERROR_INVALID_PARAMETER );
  308. return FALSE;
  309. }
  310. do
  311. {
  312. if ( dwAlloc - dwRead < dwGrow )
  313. {
  314. dwAlloc += dwGrow;
  315. if( NULL == pb )
  316. {
  317. pb = (BYTE*) AllocateMemory( dwAlloc + 10 );
  318. }
  319. else if( FALSE == ReallocateMemory( (LPVOID*) &pb, dwAlloc + 10 ) )
  320. {
  321. FreeMemory( (LPVOID*) &pb );
  322. SetLastError( ERROR_OUTOFMEMORY );
  323. return NULL;
  324. }
  325. }
  326. if ( FALSE == ReadFile( hFile, pb + dwRead, (dwAlloc - dwRead), &dwNew, 0 ) )
  327. {
  328. break;
  329. }
  330. dwRead += dwNew;
  331. } while (dwNew != 0 );
  332. *pdwBytes = dwRead;
  333. SecureZeroMemory( pb + dwRead, (dwAlloc - dwRead) );
  334. SetLastError( ERROR_SUCCESS );
  335. return pb;
  336. }
  337. BOOL
  338. DisplayHelp()
  339. /*++
  340. Routine Description : Displays the help usage to console or to file
  341. if redirected.
  342. Arguments:
  343. Return Type : EXIT_SUCCESS if successful,EXIT_FAILURE otherwise.
  344. --*/
  345. {
  346. //changing the help by taking the strings from resource file
  347. for( DWORD dw=IDS_MAIN_HELP_BEGIN;dw<=IDS_MAIN_HELP_END;dw++)
  348. {
  349. ShowMessage( stdout, GetResString2( dw, 0 ) );
  350. }
  351. SetLastError( ERROR_SUCCESS );
  352. return TRUE;
  353. }