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.

290 lines
7.2 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2001.
  5. //
  6. // File: cmdkey: IO.cpp
  7. //
  8. // Contents: Command line input/output routines suitable for international use
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. // History: 07-09-01 georgema Created
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <windows.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <lmerr.h>
  22. #include <malloc.h>
  23. #define IOCPP
  24. #include "io.h"
  25. #include "consmsg.h"
  26. /*** GetString -- read in string with echo
  27. *
  28. * DWORD GetString(char far *, USHORT, USHORT far *, char far *);
  29. *
  30. * ENTRY: buf buffer to put string in
  31. * buflen size of buffer
  32. * &len address of USHORT to place length in
  33. *
  34. * RETURNS:
  35. * 0 or NERR_BufTooSmall if user typed too much. Buffer
  36. * contents are only valid on 0 return. Len is ALWAYS valid.
  37. *
  38. * OTHER EFFECTS:
  39. * len is set to hold number of bytes typed, regardless of
  40. * buffer length.
  41. *
  42. * Read in a string a character at a time. Is aware of DBCS.
  43. *
  44. * History:
  45. * who when what
  46. * erichn 5/11/89 initial code
  47. * dannygl 5/28/89 modified DBCS usage
  48. * danhi 3/20/91 ported to 32 bits
  49. * cliffv 3/12/01 Stolen from netcmd
  50. */
  51. DWORD
  52. GetString(
  53. LPWSTR buf,
  54. DWORD buflen,
  55. PDWORD len
  56. )
  57. {
  58. DWORD c;
  59. DWORD err;
  60. buflen -= 1; /* make space for null terminator */
  61. *len = 0; /* GP fault probe (a la API's) */
  62. while (TRUE) {
  63. err = ReadConsole(GetStdHandle(STD_INPUT_HANDLE), buf, 1, &c, 0);
  64. if (!err || c != 1) {
  65. *buf = 0xffff;
  66. }
  67. if (*buf == (WCHAR)EOF) {
  68. break;
  69. }
  70. if (*buf == '\r' || *buf == '\n' ) {
  71. INPUT_RECORD ir;
  72. DWORD cr;
  73. if (PeekConsoleInput(GetStdHandle(STD_INPUT_HANDLE), &ir, 1, &cr)) {
  74. ReadConsole(GetStdHandle(STD_INPUT_HANDLE), buf, 1, &c, 0);
  75. }
  76. break;
  77. }
  78. buf += (*len < buflen) ? 1 : 0; /* don't overflow buf */
  79. (*len)++; /* always increment len */
  80. }
  81. *buf = '\0'; /* null terminate the string */
  82. return ((*len <= buflen) ? 0 : NERR_BufTooSmall);
  83. }
  84. VOID
  85. GetStdin(
  86. OUT LPWSTR Buffer,
  87. IN DWORD BufferMaxChars
  88. )
  89. /*++
  90. Routine Description:
  91. Input a string from stdin in the Console code page.
  92. We can't use fgetws since it uses the wrong code page.
  93. Arguments:
  94. Buffer - Buffer to put the read string into.
  95. The Buffer will be zero terminated and will have any traing CR/LF removed
  96. BufferMaxChars - Maximum number of characters to return in the buffer not including
  97. the trailing NULL.
  98. EchoChars - TRUE if the typed characters are to be echoed.
  99. FALSE if not.
  100. Return Values:
  101. None.
  102. --*/
  103. {
  104. DWORD NetStatus;
  105. DWORD Length;
  106. NetStatus = GetString( Buffer,
  107. BufferMaxChars+1,
  108. &Length );
  109. if ( NetStatus == NERR_BufTooSmall ) {
  110. Buffer[0] = '\0';
  111. }
  112. }
  113. VOID
  114. PutStdout(
  115. IN LPWSTR String
  116. )
  117. /*++
  118. Routine Description:
  119. Output a string to stdout in the Console code page
  120. We can't use fputws since it uses the wrong code page.
  121. Arguments:
  122. String - String to output
  123. Return Values:
  124. None.
  125. --*/
  126. {
  127. int size;
  128. LPSTR Buffer = NULL;
  129. DWORD dwcc = 0; // char count
  130. DWORD dwWritten = 0; // chars actually sent
  131. BOOL fIsConsole = TRUE; // default - tested and set
  132. HANDLE hC = GetStdHandle(STD_OUTPUT_HANDLE); // std output device handle
  133. if (INVALID_HANDLE_VALUE == hC) return; // output is unavailable
  134. if (NULL == String) return; // done if no string
  135. dwcc = wcslen(String);
  136. // Determine type of the output handle (Is a console?)
  137. DWORD ft = GetFileType(hC);
  138. ft &= ~FILE_TYPE_REMOTE;
  139. fIsConsole = (ft == FILE_TYPE_CHAR);
  140. if (fIsConsole)
  141. {
  142. WriteConsole(hC,String,dwcc,&dwWritten,NULL);
  143. return;
  144. }
  145. // Handle non-console output routing
  146. //
  147. // Compute the size of the converted string
  148. //
  149. size = WideCharToMultiByte( GetConsoleOutputCP(),
  150. 0,
  151. String,
  152. -1,
  153. NULL,
  154. 0,
  155. NULL,
  156. NULL );
  157. if ( size == 0 ) {
  158. return;
  159. }
  160. //
  161. // Allocate a buffer for it
  162. //
  163. __try {
  164. Buffer = static_cast<LPSTR>( alloca(size) );
  165. } __except(EXCEPTION_EXECUTE_HANDLER) {
  166. Buffer = NULL;
  167. }
  168. if ( Buffer == NULL) {
  169. return;
  170. }
  171. //
  172. // Convert the string to the console code page
  173. //
  174. size = WideCharToMultiByte( GetConsoleOutputCP(),
  175. 0,
  176. String,
  177. -1,
  178. Buffer,
  179. size,
  180. NULL,
  181. NULL );
  182. if ( size == 0 ) {
  183. return;
  184. }
  185. //
  186. // Write the string to stdout
  187. //
  188. //fputs( Buffer, stdout );
  189. WriteFile(hC,Buffer,size,&dwWritten,NULL);
  190. }
  191. // --------------------------------------------------------------------------
  192. //
  193. // MESSAGES GROUP
  194. //
  195. // --------------------------------------------------------------------------
  196. /* ++
  197. ComposeString is used to fetch a string from the message resources for the application, substituting
  198. argument values as appropriate. Argument values are placed in the global vector of argument
  199. pointers, szArg.
  200. The output string is delivered to the global string buffer, szOut.
  201. This means, of course, that you can't have multiple strings in play at the same time. If more than
  202. one string needs to be used, you must copy all but the last to external temporary buffers.
  203. -- */
  204. WCHAR *
  205. ComposeString(DWORD dwID)
  206. {
  207. if (NULL == hMod) hMod = GetModuleHandle(NULL);
  208. if (0 == dwID) return NULL;
  209. if (0 == FormatMessageW(FORMAT_MESSAGE_FROM_HMODULE |
  210. FORMAT_MESSAGE_ARGUMENT_ARRAY,
  211. hMod,
  212. dwID,
  213. 0,
  214. szOut,
  215. STRINGMAXLEN,
  216. (va_list *)szArg))
  217. {
  218. szOut[0] = 0;
  219. }
  220. return szOut;
  221. }
  222. /* ++
  223. Print a string from the message resources with argument substitution.
  224. -- */
  225. void
  226. PrintString(DWORD dwID)
  227. {
  228. PutStdout(ComposeString(dwID));
  229. }