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
9.0 KiB

  1. /*++
  2. Copyright (c) 1994-1995 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. Revision History:
  10. --*/
  11. #define UNICODE
  12. #define _UNICODE
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <io.h>
  16. #include <windows.h>
  17. #include <tchar.h>
  18. #include <limits.h>
  19. #include "support.h"
  20. #include "msg.h"
  21. //
  22. // Declare routines to put out internationalized messages
  23. //
  24. typedef enum {
  25. READ_ACCESS,
  26. WRITE_ACCESS
  27. } STREAMACCESS;
  28. HANDLE
  29. GetStandardStream(
  30. IN HANDLE Handle,
  31. IN STREAMACCESS Access
  32. );
  33. BOOLEAN
  34. IsFile(
  35. IN PTCHAR File,
  36. IN PTCHAR Path
  37. );
  38. HANDLE hInput;
  39. HANDLE hOutput;
  40. HANDLE hError;
  41. #define STDIN 0
  42. #define STDOUT 1
  43. #define STDERR 2
  44. BOOL ConsoleInput;
  45. BOOL ConsoleOutput;
  46. BOOL ConsoleError;
  47. TCHAR ThousandSeparator[8];
  48. TCHAR DecimalPlace[8];
  49. int
  50. FileIsConsole(int fh)
  51. {
  52. unsigned htype;
  53. DWORD dwMode;
  54. HANDLE hFile;
  55. hFile = (HANDLE)_get_osfhandle(fh);
  56. htype = GetFileType(hFile);
  57. htype &= ~FILE_TYPE_REMOTE;
  58. if (FILE_TYPE_CHAR == htype) {
  59. switch (fh) {
  60. case STDIN:
  61. hFile = GetStdHandle(STD_INPUT_HANDLE);
  62. break;
  63. case STDOUT:
  64. hFile = GetStdHandle(STD_OUTPUT_HANDLE);
  65. break;
  66. case STDERR:
  67. hFile = GetStdHandle(STD_ERROR_HANDLE);
  68. break;
  69. }
  70. if (GetConsoleMode(hFile, &dwMode)) {
  71. return TRUE;
  72. }
  73. }
  74. return FALSE;
  75. }
  76. VOID
  77. InitializeIoStreams()
  78. {
  79. #ifdef FE_SB
  80. LANGID LangId;
  81. LCID lcid;
  82. switch (GetConsoleOutputCP()) {
  83. case 932:
  84. LangId = MAKELANGID( LANG_JAPANESE, SUBLANG_DEFAULT );
  85. break;
  86. case 949:
  87. LangId = MAKELANGID( LANG_KOREAN, SUBLANG_KOREAN );
  88. break;
  89. case 936:
  90. LangId = MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED );
  91. break;
  92. case 950:
  93. LangId = MAKELANGID( LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL );
  94. break;
  95. default:
  96. LangId = PRIMARYLANGID(LANGIDFROMLCID( GetUserDefaultLCID() ));
  97. if (LangId == LANG_JAPANESE ||
  98. LangId == LANG_KOREAN ||
  99. LangId == LANG_CHINESE ) {
  100. LangId = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
  101. }
  102. else {
  103. LangId = MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT );
  104. }
  105. break;
  106. }
  107. SetThreadLocale( lcid = MAKELCID(LangId, SORT_DEFAULT) );
  108. if (!GetLocaleInfo(lcid, LOCALE_STHOUSAND, ThousandSeparator, sizeof(ThousandSeparator)/sizeof(ThousandSeparator[0]))) {
  109. _tcscpy(ThousandSeparator, TEXT(","));
  110. }
  111. if (!GetLocaleInfo(lcid, LOCALE_SDECIMAL, DecimalPlace, sizeof(DecimalPlace)/sizeof(DecimalPlace[0]))) {
  112. _tcscpy(DecimalPlace, TEXT("."));
  113. }
  114. #endif
  115. hInput = GetStdHandle(STD_INPUT_HANDLE);
  116. ConsoleInput = FileIsConsole(STDIN);
  117. hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  118. ConsoleOutput = FileIsConsole(STDOUT);
  119. hError = GetStdHandle(STD_ERROR_HANDLE);
  120. ConsoleError = FileIsConsole(STDERR);
  121. }
  122. TCHAR DisplayBuffer[4096];
  123. CHAR DisplayBuffer2[4096];
  124. VOID
  125. DisplayMsg(DWORD MsgNum, ... )
  126. {
  127. DWORD len, bytes_written;
  128. BOOL success;
  129. DWORD status;
  130. va_list ap;
  131. va_start(ap, MsgNum);
  132. len = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE, NULL, MsgNum, 0,
  133. DisplayBuffer, 4096, &ap);
  134. if (ConsoleOutput) {
  135. success = WriteConsole(hOutput, (LPVOID)DisplayBuffer, len,
  136. &bytes_written, NULL);
  137. } else {
  138. CharToOem(DisplayBuffer, DisplayBuffer2);
  139. success = WriteFile(hOutput, (LPVOID)DisplayBuffer2, len,
  140. &bytes_written, NULL);
  141. }
  142. if (!success || bytes_written != len) {
  143. status = GetLastError();
  144. }
  145. va_end(ap);
  146. }
  147. VOID
  148. DisplayErr(
  149. PTCHAR Prefix,
  150. DWORD MsgNum,
  151. ...
  152. )
  153. {
  154. DWORD len, bytes_written;
  155. BOOL success;
  156. DWORD status;
  157. va_list ap;
  158. ULONG i;
  159. va_start(ap, MsgNum);
  160. if (NULL != Prefix) {
  161. lstrcpy(DisplayBuffer, Prefix);
  162. lstrcat(DisplayBuffer, TEXT(": "));
  163. } else {
  164. DisplayBuffer[0] = UNICODE_NULL;
  165. }
  166. i = lstrlen(DisplayBuffer);
  167. len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, MsgNum, 0,
  168. DisplayBuffer + i, 4096 - i, &ap);
  169. if (ConsoleError) {
  170. success = WriteConsole(hError, (LPVOID)DisplayBuffer, len + i,
  171. &bytes_written, NULL);
  172. } else {
  173. CharToOem(DisplayBuffer, DisplayBuffer2);
  174. success = WriteFile(hError, (LPVOID)DisplayBuffer2, len + i,
  175. &bytes_written, NULL);
  176. }
  177. if (!success) {
  178. status = GetLastError();
  179. }
  180. va_end(ap);
  181. }
  182. BOOLEAN
  183. ExcludeThisFile(
  184. IN PTCHAR Path
  185. )
  186. /*++
  187. Routine Description:
  188. Used to keep the user from compressing certain files
  189. which the machine needs to boot up.
  190. Arguments:
  191. File - name to check for
  192. Path - the path to examine.
  193. Return Value:
  194. TRUE - the path looks like one that should not be compressed
  195. FALSE - the path looks like one that can be compressed
  196. --*/
  197. {
  198. return IsFile(TEXT("\\ntldr"), Path) ||
  199. IsFile(TEXT("\\cmldr"), Path);
  200. }
  201. BOOLEAN
  202. IsFile(
  203. IN PTCHAR File,
  204. IN PTCHAR Path
  205. )
  206. /*++
  207. Routine Description:
  208. Checks to see if the given File matches that specified by Path.
  209. Arguments:
  210. File - Name to look for
  211. Path - Path to examine
  212. Return Value:
  213. TRUE - the path looks like the specified file.
  214. FALSE - the path does not look like the specified file.
  215. --*/
  216. {
  217. PTCHAR pch;
  218. // try "X:\<File>"
  219. if (0 == lstricmp(Path + 2, File)) {
  220. return TRUE;
  221. }
  222. // try "\\machine\share\<File>"
  223. if ('\\' == Path[0] && '\\' != Path[1]) {
  224. pch = lstrchr(Path + 2, '\\');
  225. if (NULL == pch) {
  226. return FALSE;
  227. }
  228. pch = lstrchr(pch + 1, '\\');
  229. if (NULL == pch) {
  230. return FALSE;
  231. }
  232. if (0 == lstricmp(pch, File)) {
  233. return TRUE;
  234. }
  235. }
  236. return FALSE;
  237. }
  238. BOOLEAN
  239. IsUncRoot(
  240. PTCHAR Path
  241. )
  242. /*++
  243. Routine Description:
  244. Determine whether the given path is of the form \\server\share.
  245. Arguments:
  246. Path - the path to examine.
  247. Return Value:
  248. TRUE - the path looks like a unc share name.
  249. FALSE - the path does not look like that.
  250. --*/
  251. {
  252. PTCHAR pch;
  253. if ('\\' != *Path || '\\' != *(Path + 1)) {
  254. return FALSE;
  255. }
  256. pch = lstrchr(Path + 2, '\\');
  257. if (NULL == pch) {
  258. //
  259. // There is no slash to seperate server and share.
  260. //
  261. return FALSE;
  262. }
  263. pch = lstrchr(pch + 1, '\\');
  264. if (NULL != pch) {
  265. //
  266. // There are additional component -- no match.
  267. //
  268. return FALSE;
  269. }
  270. if ('\\' == *(Path + lstrlen(Path))) {
  271. //
  272. // The string ends in slash -- it doesn't match.
  273. //
  274. return FALSE;
  275. }
  276. return TRUE;
  277. }
  278. ULONG
  279. FormatFileSize(
  280. IN PLARGE_INTEGER FileSize,
  281. IN DWORD Width,
  282. OUT PTCHAR FormattedSize,
  283. IN BOOLEAN Commas
  284. )
  285. {
  286. TCHAR Buffer[100];
  287. PTCHAR s, s1;
  288. ULONG DigitIndex, Digit;
  289. ULONG Size;
  290. LARGE_INTEGER TempSize;
  291. ULONG tslen;
  292. s = &Buffer[ 99 ];
  293. *s = TEXT('\0');
  294. DigitIndex = 0;
  295. TempSize = *FileSize;
  296. while (TempSize.HighPart != 0) {
  297. if (TempSize.HighPart != 0) {
  298. Digit = (ULONG)(TempSize.QuadPart % 10);
  299. TempSize.QuadPart = TempSize.QuadPart / 10;
  300. } else {
  301. Digit = TempSize.LowPart % 10;
  302. TempSize.LowPart = TempSize.LowPart / 10;
  303. }
  304. *--s = (TCHAR)(TEXT('0') + Digit);
  305. if ((++DigitIndex % 3) == 0 && Commas) {
  306. tslen = _tcslen(ThousandSeparator);
  307. s -= tslen;
  308. _tcsncpy(s, ThousandSeparator, tslen);
  309. }
  310. }
  311. Size = TempSize.LowPart;
  312. while (Size != 0) {
  313. *--s = (TCHAR)(TEXT('0') + (Size % 10));
  314. Size = Size / 10;
  315. if ((++DigitIndex % 3) == 0 && Commas) {
  316. tslen = _tcslen(ThousandSeparator);
  317. s -= tslen;
  318. _tcsncpy(s, ThousandSeparator, tslen);
  319. }
  320. }
  321. if (DigitIndex == 0) {
  322. *--s = TEXT('0');
  323. } else if (Commas && !_tcsncmp(s, ThousandSeparator, tslen)) {
  324. s += 1;
  325. }
  326. Size = lstrlen( s );
  327. if (Width != 0 && Size < Width) {
  328. s1 = FormattedSize;
  329. while (Width > Size) {
  330. Width -= 1;
  331. *s1++ = TEXT(' ');
  332. }
  333. lstrcpy( s1, s );
  334. } else {
  335. lstrcpy( FormattedSize, s );
  336. }
  337. return lstrlen( FormattedSize );
  338. }