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.

485 lines
11 KiB

  1. /*++
  2. Copyright (c) 1994-1999 Microsoft Corporation
  3. Module Name:
  4. Support.c
  5. Abstract:
  6. Support routines for compact utility
  7. Author:
  8. Matthew Bradburn [mattbr] 05-Oct-1994
  9. Robert Reichel [RobertRe] 01-Apr-1997
  10. Revision History:
  11. --*/
  12. #undef UNICODE
  13. #define UNICODE
  14. #undef _UNICODE
  15. #define _UNICODE
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <io.h>
  19. #include <windows.h>
  20. #include "support.h"
  21. #include "msg.h"
  22. //
  23. // Declare routines to put out internationalized messages
  24. //
  25. typedef enum {
  26. READ_ACCESS,
  27. WRITE_ACCESS
  28. } STREAMACCESS;
  29. DWORD MySetThreadUILanguage(DWORD dwParam)
  30. {
  31. HMODULE hKernel32Dll = NULL;
  32. DWORD hr = ERROR_SUCCESS;
  33. typedef LANGID (WINAPI * SetThreadUILanguageFunc)(DWORD dwReserved);
  34. SetThreadUILanguageFunc pSetThreadUILanguage = NULL;
  35. hKernel32Dll = LoadLibraryW(L"kernel32.dll");
  36. if (NULL == hKernel32Dll) {
  37. return GetLastError();
  38. }
  39. pSetThreadUILanguage = (SetThreadUILanguageFunc)GetProcAddress(hKernel32Dll, "SetThreadUILanguage");
  40. if (NULL != pSetThreadUILanguage) {
  41. pSetThreadUILanguage(dwParam);
  42. } else {
  43. hr = GetLastError();
  44. }
  45. FreeLibrary(hKernel32Dll);
  46. return hr;
  47. }
  48. HANDLE
  49. GetStandardStream(
  50. IN HANDLE Handle,
  51. IN STREAMACCESS Access
  52. );
  53. HANDLE hInput;
  54. HANDLE hOutput;
  55. HANDLE hError;
  56. #define STDIN 0
  57. #define STDOUT 1
  58. #define STDERR 2
  59. BOOL ConsoleInput;
  60. BOOL ConsoleOutput;
  61. BOOL ConsoleError;
  62. int
  63. FileIsConsole(int fh)
  64. {
  65. unsigned htype;
  66. DWORD dwMode;
  67. HANDLE hFile;
  68. hFile = (HANDLE)_get_osfhandle(fh);
  69. htype = GetFileType(hFile);
  70. htype &= ~FILE_TYPE_REMOTE;
  71. if (FILE_TYPE_CHAR == htype) {
  72. switch (fh) {
  73. case STDIN:
  74. hFile = GetStdHandle(STD_INPUT_HANDLE);
  75. break;
  76. case STDOUT:
  77. hFile = GetStdHandle(STD_OUTPUT_HANDLE);
  78. break;
  79. case STDERR:
  80. hFile = GetStdHandle(STD_ERROR_HANDLE);
  81. break;
  82. }
  83. if (GetConsoleMode(hFile, &dwMode)) {
  84. return TRUE;
  85. }
  86. }
  87. return FALSE;
  88. }
  89. VOID
  90. InitializeIoStreams()
  91. {
  92. hInput = GetStdHandle(STD_INPUT_HANDLE);
  93. ConsoleInput = FileIsConsole(STDIN);
  94. hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  95. ConsoleOutput = FileIsConsole(STDOUT);
  96. hError = GetStdHandle(STD_ERROR_HANDLE);
  97. ConsoleError = FileIsConsole(STDERR);
  98. }
  99. VOID
  100. DisplayMsg(DWORD MsgNum, ... )
  101. {
  102. DWORD len, bytes_written = 0;
  103. BOOL success = FALSE;
  104. DWORD status;
  105. va_list ap;
  106. LPTSTR DisplayBuffer;
  107. MySetThreadUILanguage(0);
  108. va_start(ap, MsgNum);
  109. len = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  110. NULL, MsgNum, 0,
  111. (LPVOID)&DisplayBuffer, 0, &ap);
  112. if (len && DisplayBuffer) {
  113. if (ConsoleOutput) {
  114. success = WriteConsole(hOutput, (LPVOID)DisplayBuffer, len,
  115. &bytes_written, NULL);
  116. } else {
  117. DWORD ascii_len;
  118. LPSTR DisplayBufferAscii;
  119. len = lstrlen(DisplayBuffer);
  120. ascii_len = WideCharToMultiByte(
  121. CP_OEMCP, // Unicode -> OEM
  122. 0, // gives best visual match
  123. DisplayBuffer, len+1, // source & length
  124. NULL, 0, // dest & length
  125. NULL, // default char
  126. NULL);
  127. if (ascii_len) {
  128. DisplayBufferAscii = LocalAlloc(LPTR, ascii_len);
  129. if (DisplayBufferAscii != NULL) {
  130. ascii_len = WideCharToMultiByte(
  131. CP_OEMCP,
  132. 0,
  133. DisplayBuffer, len+1,
  134. DisplayBufferAscii, ascii_len,
  135. NULL,
  136. NULL);
  137. if (ascii_len) {
  138. success = WriteFile(hOutput, (LPVOID)DisplayBufferAscii, ascii_len,
  139. &bytes_written, NULL);
  140. len = ascii_len;
  141. }
  142. LocalFree(DisplayBufferAscii);
  143. }
  144. }
  145. }
  146. if (!success || bytes_written != len) {
  147. status = GetLastError();
  148. }
  149. LocalFree(DisplayBuffer);
  150. }
  151. va_end(ap);
  152. }
  153. VOID
  154. DisplayErr(
  155. PTCHAR Prefix,
  156. DWORD MsgNum,
  157. ...
  158. )
  159. {
  160. DWORD len, bytes_written, PrefixLen;
  161. BOOL success = FALSE;
  162. BOOL errset = FALSE;
  163. DWORD status;
  164. va_list ap;
  165. LPTSTR DisplayBuffer;
  166. LPTSTR MessageBuffer;
  167. #define PREFIX_MSG TEXT(": ")
  168. MySetThreadUILanguage(0);
  169. va_start(ap, MsgNum);
  170. len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  171. NULL, MsgNum, 0,
  172. (LPVOID)&MessageBuffer, 0, &ap);
  173. if (len && MessageBuffer) {
  174. if (Prefix == NULL) {
  175. PrefixLen = 0;
  176. } else {
  177. PrefixLen = wcslen(Prefix)+wcslen(PREFIX_MSG);
  178. }
  179. DisplayBuffer = LocalAlloc(LPTR, (len+PrefixLen+1) * sizeof(WCHAR));
  180. if (DisplayBuffer != NULL) {
  181. if (NULL != Prefix) {
  182. lstrcpy(DisplayBuffer, Prefix);
  183. lstrcat(DisplayBuffer, PREFIX_MSG);
  184. } else {
  185. DisplayBuffer[0] = UNICODE_NULL;
  186. }
  187. lstrcat(DisplayBuffer, MessageBuffer);
  188. len = lstrlen(DisplayBuffer);
  189. if (ConsoleError) {
  190. success = WriteConsole(hError, (LPVOID)DisplayBuffer, len,
  191. &bytes_written, NULL);
  192. } else {
  193. DWORD ascii_len;
  194. LPSTR DisplayBufferAscii;
  195. ascii_len = WideCharToMultiByte(
  196. CP_OEMCP, // Unicode -> OEM
  197. 0, // gives best visual match
  198. DisplayBuffer, len+1, // source & length
  199. NULL, 0, // dest & length
  200. NULL, // default char
  201. NULL);
  202. if (ascii_len) {
  203. DisplayBufferAscii = LocalAlloc(LPTR, ascii_len);
  204. if (DisplayBufferAscii != NULL) {
  205. ascii_len = WideCharToMultiByte(
  206. CP_OEMCP,
  207. 0,
  208. DisplayBuffer, len+1,
  209. DisplayBufferAscii, ascii_len,
  210. NULL,
  211. NULL);
  212. if (ascii_len) {
  213. success = WriteFile(hError, (LPVOID)DisplayBufferAscii, ascii_len,
  214. &bytes_written, NULL);
  215. } else {
  216. status = GetLastError();
  217. errset = TRUE;
  218. }
  219. LocalFree(DisplayBufferAscii);
  220. } else {
  221. status = ERROR_NOT_ENOUGH_MEMORY;
  222. errset = TRUE;
  223. }
  224. } else {
  225. status = GetLastError();
  226. //
  227. // No need to get last error again
  228. //
  229. errset = TRUE;
  230. }
  231. }
  232. LocalFree(DisplayBuffer);
  233. }
  234. if (!success && !errset) {
  235. status = GetLastError();
  236. }
  237. LocalFree(MessageBuffer);
  238. }
  239. va_end(ap);
  240. }
  241. DWORD
  242. GetResourceString(
  243. LPWSTR *OutStr,
  244. DWORD MsgNum,
  245. ...
  246. )
  247. {
  248. DWORD rc = ERROR_SUCCESS;
  249. DWORD len;
  250. va_list ap;
  251. MySetThreadUILanguage(0);
  252. va_start(ap, MsgNum);
  253. *OutStr = NULL;
  254. len = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  255. NULL,
  256. MsgNum,
  257. 0,
  258. (LPVOID)OutStr,
  259. 0,
  260. &ap
  261. );
  262. if (len && *OutStr) {
  263. //
  264. // Let's get rid of \n
  265. //
  266. len = wcslen( *OutStr );
  267. if (((*OutStr)[len-1] == 0x000a) && ((*OutStr)[len-2] == 0x000d) ) {
  268. (*OutStr)[len-2] = 0;
  269. }
  270. } else {
  271. rc = ERROR_NOT_ENOUGH_MEMORY;
  272. }
  273. va_end(ap);
  274. return rc;
  275. }
  276. BOOLEAN
  277. IsNtldr(
  278. PTCHAR Path
  279. )
  280. /*++
  281. Routine Description:
  282. Used to keep the user from compressing \NTLDR (which would prevent
  283. the machine from booting).
  284. Arguments:
  285. Path - the path to examine.
  286. Return Value:
  287. TRUE - the path looks like \ntldr.
  288. FALSE - the path does not look like \ntldr.
  289. --*/
  290. {
  291. PTCHAR pch;
  292. // try "X:\ntldr"
  293. if (0 == lstricmp(Path + 2, TEXT("\\ntldr"))) {
  294. return TRUE;
  295. }
  296. // try "\\machine\share\ntldr"
  297. if ('\\' == Path[0] && '\\' != Path[1]) {
  298. pch = lstrchr(Path + 2, '\\');
  299. if (NULL == pch) {
  300. return FALSE;
  301. }
  302. pch = lstrchr(pch + 1, '\\');
  303. if (NULL == pch) {
  304. return FALSE;
  305. }
  306. if (0 == lstricmp(pch, TEXT("\\ntldr"))) {
  307. return TRUE;
  308. }
  309. }
  310. return FALSE;
  311. }
  312. ULONG
  313. FormatFileSize(
  314. IN PLARGE_INTEGER FileSize,
  315. IN DWORD Width,
  316. OUT PTCHAR FormattedSize,
  317. IN BOOLEAN Commas
  318. )
  319. {
  320. TCHAR Buffer[100];
  321. PTCHAR s, s1;
  322. ULONG DigitIndex, Digit;
  323. ULONG Size;
  324. LARGE_INTEGER TempSize;
  325. s = &Buffer[ 99 ];
  326. *s = TEXT('\0');
  327. DigitIndex = 0;
  328. TempSize = *FileSize;
  329. while (TempSize.HighPart != 0) {
  330. if (TempSize.HighPart != 0) {
  331. Digit = (ULONG)(TempSize.QuadPart % 10);
  332. TempSize.QuadPart = TempSize.QuadPart / 10;
  333. } else {
  334. Digit = TempSize.LowPart % 10;
  335. TempSize.LowPart = TempSize.LowPart / 10;
  336. }
  337. *--s = (TCHAR)(TEXT('0') + Digit);
  338. if ((++DigitIndex % 3) == 0 && Commas) {
  339. *--s = TEXT(',');
  340. }
  341. }
  342. Size = TempSize.LowPart;
  343. while (Size != 0) {
  344. *--s = (TCHAR)(TEXT('0') + (Size % 10));
  345. Size = Size / 10;
  346. if ((++DigitIndex % 3) == 0 && Commas) {
  347. *--s = TEXT(',');
  348. }
  349. }
  350. if (DigitIndex == 0) {
  351. *--s = TEXT('0');
  352. } else if (Commas && *s == TEXT(',')) {
  353. s += 1;
  354. }
  355. Size = lstrlen( s );
  356. if (Width != 0 && Size < Width) {
  357. s1 = FormattedSize;
  358. while (Width > Size) {
  359. Width -= 1;
  360. *s1++ = TEXT(' ');
  361. }
  362. lstrcpy( s1, s );
  363. } else {
  364. lstrcpy( FormattedSize, s );
  365. }
  366. return lstrlen( FormattedSize );
  367. }