Source code of Windows XP (NT5)
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.

197 lines
5.0 KiB

  1. #include "pch.h"
  2. #include <stdio.h>
  3. #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
  4. extern HINSTANCE g_hThisModule;
  5. HANDLE g_hStdout = NULL;
  6. HRESULT InitializeConsoleOutput() {
  7. g_hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
  8. if (INVALID_HANDLE_VALUE == g_hStdout) {
  9. return HRESULT_FROM_WIN32(GetLastError());
  10. }
  11. return S_OK;
  12. }
  13. BOOL
  14. FileIsConsole(
  15. HANDLE fp
  16. )
  17. {
  18. DWORD htype;
  19. htype = GetFileType(fp);
  20. htype &= ~FILE_TYPE_REMOTE;
  21. return htype == FILE_TYPE_CHAR;
  22. }
  23. HRESULT
  24. MyWriteConsole(
  25. HANDLE fp,
  26. LPWSTR lpBuffer,
  27. DWORD cchBuffer
  28. )
  29. {
  30. HRESULT hr;
  31. LPSTR lpAnsiBuffer = NULL;
  32. //
  33. // Jump through hoops for output because:
  34. //
  35. // 1. printf() family chokes on international output (stops
  36. // printing when it hits an unrecognized character)
  37. //
  38. // 2. WriteConsole() works great on international output but
  39. // fails if the handle has been redirected (i.e., when the
  40. // output is piped to a file)
  41. //
  42. // 3. WriteFile() works great when output is piped to a file
  43. // but only knows about bytes, so Unicode characters are
  44. // printed as two Ansi characters.
  45. //
  46. if (FileIsConsole(fp))
  47. {
  48. hr = WriteConsole(fp, lpBuffer, cchBuffer, &cchBuffer, NULL);
  49. _JumpIfError(hr, error, "WriteConsole");
  50. }
  51. else
  52. {
  53. lpAnsiBuffer = (LPSTR) LocalAlloc(LPTR, cchBuffer * sizeof(WCHAR));
  54. if (lpAnsiBuffer != NULL)
  55. {
  56. cchBuffer = WideCharToMultiByte(CP_OEMCP,
  57. 0,
  58. lpBuffer,
  59. cchBuffer,
  60. lpAnsiBuffer,
  61. cchBuffer * sizeof(WCHAR),
  62. NULL,
  63. NULL);
  64. if (cchBuffer != 0)
  65. {
  66. if (!WriteFile(fp, lpAnsiBuffer, cchBuffer, &cchBuffer, NULL))
  67. {
  68. hr = GetLastError();
  69. _JumpError(hr, error, "WriteFile");
  70. }
  71. }
  72. else
  73. {
  74. hr = GetLastError();
  75. _JumpError(hr, error, "WideCharToMultiByte");
  76. }
  77. }
  78. }
  79. error:
  80. if (NULL != lpAnsiBuffer)
  81. LocalFree(lpAnsiBuffer);
  82. return hr;
  83. }
  84. HRESULT LocalizedWPrintf(UINT nResourceID) {
  85. DWORD ccWritten;
  86. DWORD dwRetval;
  87. HRESULT hr;
  88. WCHAR rgwszString[512];
  89. dwRetval = LoadStringW(g_hThisModule, nResourceID, rgwszString, ARRAYSIZE(rgwszString));
  90. if (0 == dwRetval) {
  91. _JumpLastError(hr, error, "LoadStringW");
  92. }
  93. _Verify(512 > dwRetval, hr, error); // Shouldn't fill our buffer...
  94. hr = MyWriteConsole(g_hStdout, rgwszString, dwRetval);
  95. _JumpIfError(hr, error, "MyWriteConsole");
  96. hr = S_OK; // All done!
  97. error:
  98. return hr;
  99. }
  100. HRESULT LocalizedWPrintf2(UINT nResourceID, LPWSTR pwszFormat, ...) {
  101. DWORD ccWritten;
  102. va_list args;
  103. WCHAR pwszBuffer[1024];
  104. HRESULT hr = LocalizedWPrintf(nResourceID);
  105. _JumpIfError(hr, error, "LocalizedWPrintf");
  106. va_start(args, pwszFormat);
  107. _vsnwprintf(pwszBuffer, ARRAYSIZE(pwszBuffer), pwszFormat, args);
  108. va_end(args);
  109. hr = MyWriteConsole(g_hStdout, pwszBuffer, wcslen(pwszBuffer));
  110. _JumpIfError(hr, error, "MyWriteConsole");
  111. hr = S_OK;
  112. error:
  113. return hr;
  114. }
  115. // Same as LocalizedWPrintf, but adds a carriage return.
  116. HRESULT LocalizedWPrintfCR(UINT nResourceID) {
  117. HRESULT hr = LocalizedWPrintf(nResourceID);
  118. wprintf(L"\n");
  119. return hr;
  120. }
  121. VOID DisplayMsg(DWORD dwSource, DWORD dwMsgId, ... )
  122. {
  123. DWORD dwBytesWritten;
  124. DWORD dwLen;
  125. LPWSTR pwszDisplayBuffer = NULL;
  126. va_list ap;
  127. va_start(ap, dwMsgId);
  128. dwLen = FormatMessageW(dwSource | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  129. NULL,
  130. dwMsgId,
  131. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  132. (LPWSTR)&pwszDisplayBuffer,
  133. 0,
  134. &ap);
  135. if (dwLen && pwszDisplayBuffer) {
  136. MyWriteConsole(g_hStdout, pwszDisplayBuffer, dwLen);
  137. }
  138. if (NULL != pwszDisplayBuffer) { LocalFree(pwszDisplayBuffer); }
  139. va_end(ap);
  140. }
  141. BOOL WriteMsg(DWORD dwSource, DWORD dwMsgId, LPWSTR *ppMsg, ...)
  142. {
  143. DWORD dwBytesWritten;
  144. DWORD dwLen;
  145. LPWSTR pwszDisplayBuffer = NULL;
  146. va_list ap;
  147. va_start(ap, ppMsg);
  148. dwLen = FormatMessageW(dwSource | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  149. NULL,
  150. dwMsgId,
  151. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  152. (LPWSTR)ppMsg,
  153. 0,
  154. &ap);
  155. va_end(ap);
  156. // 0 is the error return value of FormatMessage.
  157. return (0 != dwLen);
  158. }