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.

599 lines
12 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. HANDLE
  30. GetStandardStream(
  31. IN HANDLE Handle,
  32. IN STREAMACCESS Access
  33. );
  34. HANDLE hInput;
  35. HANDLE hOutput;
  36. HANDLE hError;
  37. #define STDIN 0
  38. #define STDOUT 1
  39. #define STDERR 2
  40. BOOL ConsoleInput;
  41. BOOL ConsoleOutput;
  42. BOOL ConsoleError;
  43. int
  44. FileIsConsole(int fh)
  45. {
  46. unsigned htype;
  47. DWORD dwMode;
  48. HANDLE hFile;
  49. hFile = (HANDLE)_get_osfhandle(fh);
  50. htype = GetFileType(hFile);
  51. htype &= ~FILE_TYPE_REMOTE;
  52. if (FILE_TYPE_CHAR == htype) {
  53. switch (fh) {
  54. case STDIN:
  55. hFile = GetStdHandle(STD_INPUT_HANDLE);
  56. break;
  57. case STDOUT:
  58. hFile = GetStdHandle(STD_OUTPUT_HANDLE);
  59. break;
  60. case STDERR:
  61. hFile = GetStdHandle(STD_ERROR_HANDLE);
  62. break;
  63. }
  64. if (GetConsoleMode(hFile, &dwMode)) {
  65. return TRUE;
  66. }
  67. }
  68. return FALSE;
  69. }
  70. VOID
  71. InitializeIoStreams()
  72. {
  73. hInput = GetStdHandle(STD_INPUT_HANDLE);
  74. ConsoleInput = FileIsConsole(STDIN);
  75. hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
  76. ConsoleOutput = FileIsConsole(STDOUT);
  77. hError = GetStdHandle(STD_ERROR_HANDLE);
  78. ConsoleError = FileIsConsole(STDERR);
  79. }
  80. VOID
  81. DisplayMsg(DWORD MsgNum, ... )
  82. {
  83. DWORD len, bytes_written;
  84. BOOL success = FALSE;
  85. DWORD status;
  86. va_list ap;
  87. LPTSTR DisplayBuffer;
  88. va_start(ap, MsgNum);
  89. len = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  90. NULL, MsgNum, 0,
  91. (LPVOID)&DisplayBuffer, 0, &ap);
  92. if (len && DisplayBuffer) {
  93. if (ConsoleOutput) {
  94. success = WriteConsole(hOutput, (LPVOID)DisplayBuffer, len,
  95. &bytes_written, NULL);
  96. } else {
  97. DWORD ascii_len;
  98. LPSTR DisplayBufferAscii;
  99. len = lstrlen(DisplayBuffer);
  100. ascii_len = WideCharToMultiByte(
  101. CP_OEMCP, // Unicode -> OEM
  102. 0, // gives best visual match
  103. DisplayBuffer, len+1, // source & length
  104. NULL, 0, // dest & length
  105. NULL, // default char
  106. NULL);
  107. DisplayBufferAscii = LocalAlloc(LPTR, ascii_len);
  108. if (DisplayBufferAscii != NULL) {
  109. WideCharToMultiByte(
  110. CP_OEMCP,
  111. 0,
  112. DisplayBuffer, len+1,
  113. DisplayBufferAscii, ascii_len,
  114. NULL,
  115. NULL);
  116. success = WriteFile(hOutput, (LPVOID)DisplayBufferAscii, ascii_len,
  117. &bytes_written, NULL);
  118. len = ascii_len;
  119. LocalFree(DisplayBufferAscii);
  120. }
  121. }
  122. if (!success || bytes_written != len) {
  123. status = GetLastError();
  124. }
  125. LocalFree(DisplayBuffer);
  126. }
  127. va_end(ap);
  128. }
  129. VOID
  130. DisplayErr(
  131. PTCHAR Prefix,
  132. DWORD MsgNum,
  133. ...
  134. )
  135. {
  136. DWORD len, bytes_written, PrefixLen;
  137. BOOL success = FALSE;
  138. DWORD status;
  139. va_list ap;
  140. LPTSTR DisplayBuffer;
  141. LPTSTR MessageBuffer;
  142. #define PREFIX_MSG TEXT(": ")
  143. va_start(ap, MsgNum);
  144. len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  145. NULL, MsgNum, 0,
  146. (LPVOID)&MessageBuffer, 0, &ap);
  147. if (len && MessageBuffer) {
  148. if (Prefix == NULL) {
  149. PrefixLen = 0;
  150. } else {
  151. PrefixLen = wcslen(Prefix)+wcslen(PREFIX_MSG);
  152. }
  153. DisplayBuffer = LocalAlloc(LPTR, (len+PrefixLen+1) * sizeof(WCHAR));
  154. if (DisplayBuffer != NULL) {
  155. if (NULL != Prefix) {
  156. lstrcpy(DisplayBuffer, Prefix);
  157. lstrcat(DisplayBuffer, PREFIX_MSG);
  158. } else {
  159. DisplayBuffer[0] = UNICODE_NULL;
  160. }
  161. lstrcat(DisplayBuffer, MessageBuffer);
  162. len = lstrlen(DisplayBuffer);
  163. if (ConsoleError) {
  164. success = WriteConsole(hError, (LPVOID)DisplayBuffer, len,
  165. &bytes_written, NULL);
  166. } else {
  167. DWORD ascii_len;
  168. LPSTR DisplayBufferAscii;
  169. ascii_len = WideCharToMultiByte(
  170. CP_OEMCP, // Unicode -> OEM
  171. 0, // gives best visual match
  172. DisplayBuffer, len+1, // source & length
  173. NULL, 0, // dest & length
  174. NULL, // default char
  175. NULL);
  176. DisplayBufferAscii = LocalAlloc(LPTR, ascii_len);
  177. if (DisplayBufferAscii != NULL) {
  178. WideCharToMultiByte(
  179. CP_OEMCP,
  180. 0,
  181. DisplayBuffer, len+1,
  182. DisplayBufferAscii, ascii_len,
  183. NULL,
  184. NULL);
  185. success = WriteFile(hError, (LPVOID)DisplayBufferAscii, ascii_len,
  186. &bytes_written, NULL);
  187. LocalFree(DisplayBufferAscii);
  188. }
  189. }
  190. LocalFree(DisplayBuffer);
  191. }
  192. if (!success) {
  193. status = GetLastError();
  194. }
  195. LocalFree(MessageBuffer);
  196. }
  197. va_end(ap);
  198. }
  199. DWORD
  200. GetResourceString(
  201. LPWSTR *OutStr,
  202. DWORD MsgNum,
  203. ...
  204. )
  205. {
  206. DWORD rc = ERROR_SUCCESS;
  207. DWORD len;
  208. va_list ap;
  209. va_start(ap, MsgNum);
  210. *OutStr = NULL;
  211. len = FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  212. NULL,
  213. MsgNum,
  214. 0,
  215. (LPVOID)OutStr,
  216. 0,
  217. &ap
  218. );
  219. if (len && *OutStr) {
  220. //
  221. // Let's get rid of \n
  222. //
  223. len = wcslen( *OutStr );
  224. if (((*OutStr)[len-1] == 0x000a) && ((*OutStr)[len-2] == 0x000d) ) {
  225. (*OutStr)[len-2] = 0;
  226. }
  227. } else {
  228. rc = ERROR_NOT_ENOUGH_MEMORY;
  229. }
  230. va_end(ap);
  231. return rc;
  232. }
  233. BOOLEAN
  234. IsNtldr(
  235. PTCHAR Path
  236. )
  237. /*++
  238. Routine Description:
  239. Used to keep the user from compressing \NTLDR (which would prevent
  240. the machine from booting).
  241. Arguments:
  242. Path - the path to examine.
  243. Return Value:
  244. TRUE - the path looks like \ntldr.
  245. FALSE - the path does not look like \ntldr.
  246. --*/
  247. {
  248. PTCHAR pch;
  249. // try "X:\ntldr"
  250. if (0 == lstricmp(Path + 2, TEXT("\\ntldr"))) {
  251. return TRUE;
  252. }
  253. // try "\\machine\share\ntldr"
  254. if ('\\' == Path[0] && '\\' != Path[1]) {
  255. pch = lstrchr(Path + 2, '\\');
  256. if (NULL == pch) {
  257. return FALSE;
  258. }
  259. pch = lstrchr(pch + 1, '\\');
  260. if (NULL == pch) {
  261. return FALSE;
  262. }
  263. if (0 == lstricmp(pch, TEXT("\\ntldr"))) {
  264. return TRUE;
  265. }
  266. }
  267. return FALSE;
  268. }
  269. BOOLEAN
  270. IsUncRoot(
  271. PTCHAR Path
  272. )
  273. /*++
  274. Routine Description:
  275. Determine whether the given path is of the form \\server\share.
  276. Arguments:
  277. Path - the path to examine.
  278. Return Value:
  279. TRUE - the path looks like a unc share name.
  280. FALSE - the path does not look like that.
  281. --*/
  282. {
  283. PTCHAR pch;
  284. if ('\\' != *Path || '\\' != *(Path + 1)) {
  285. return FALSE;
  286. }
  287. pch = lstrchr(Path + 2, '\\');
  288. if (NULL == pch) {
  289. //
  290. // There is no slash to seperate server and share.
  291. //
  292. return FALSE;
  293. }
  294. pch = lstrchr(pch + 1, '\\');
  295. if (NULL != pch) {
  296. //
  297. // There are additional component -- no match.
  298. //
  299. return FALSE;
  300. }
  301. if ('\\' == *(Path + lstrlen(Path))) {
  302. //
  303. // The string ends in slash -- it doesn't match.
  304. //
  305. return FALSE;
  306. }
  307. return TRUE;
  308. }
  309. ULONG
  310. FormatFileSize(
  311. IN PLARGE_INTEGER FileSize,
  312. IN DWORD Width,
  313. OUT PTCHAR FormattedSize,
  314. IN BOOLEAN Commas
  315. )
  316. {
  317. TCHAR Buffer[100];
  318. PTCHAR s, s1;
  319. ULONG DigitIndex, Digit;
  320. ULONG Size;
  321. LARGE_INTEGER TempSize;
  322. s = &Buffer[ 99 ];
  323. *s = TEXT('\0');
  324. DigitIndex = 0;
  325. TempSize = *FileSize;
  326. while (TempSize.HighPart != 0) {
  327. if (TempSize.HighPart != 0) {
  328. Digit = (ULONG)(TempSize.QuadPart % 10);
  329. TempSize.QuadPart = TempSize.QuadPart / 10;
  330. } else {
  331. Digit = TempSize.LowPart % 10;
  332. TempSize.LowPart = TempSize.LowPart / 10;
  333. }
  334. *--s = (TCHAR)(TEXT('0') + Digit);
  335. if ((++DigitIndex % 3) == 0 && Commas) {
  336. *--s = TEXT(',');
  337. }
  338. }
  339. Size = TempSize.LowPart;
  340. while (Size != 0) {
  341. *--s = (TCHAR)(TEXT('0') + (Size % 10));
  342. Size = Size / 10;
  343. if ((++DigitIndex % 3) == 0 && Commas) {
  344. *--s = TEXT(',');
  345. }
  346. }
  347. if (DigitIndex == 0) {
  348. *--s = TEXT('0');
  349. } else if (Commas && *s == TEXT(',')) {
  350. s += 1;
  351. }
  352. Size = lstrlen( s );
  353. if (Width != 0 && Size < Width) {
  354. s1 = FormattedSize;
  355. while (Width > Size) {
  356. Width -= 1;
  357. *s1++ = TEXT(' ');
  358. }
  359. lstrcpy( s1, s );
  360. } else {
  361. lstrcpy( FormattedSize, s );
  362. }
  363. return lstrlen( FormattedSize );
  364. }
  365. PTOKEN_USER
  366. GetTokenUser(
  367. VOID
  368. )
  369. {
  370. HANDLE TokenHandle;
  371. BOOL b;
  372. DWORD ReturnLength;
  373. PTOKEN_USER TokenInfo;
  374. //
  375. // If we're impersonating, use the thread token, otherwise
  376. // use the process token.
  377. //
  378. PTOKEN_USER Result = NULL;
  379. b = OpenThreadToken(
  380. GetCurrentThread(),
  381. TOKEN_QUERY,
  382. FALSE,
  383. &TokenHandle
  384. );
  385. if (!b) {
  386. if (GetLastError() == ERROR_NO_TOKEN) {
  387. //
  388. // We're not impersonating, try the process token
  389. //
  390. b = OpenProcessToken(
  391. GetCurrentProcess(),
  392. TOKEN_QUERY,
  393. &TokenHandle
  394. );
  395. if (!b) {
  396. return( Result );
  397. }
  398. } else {
  399. //
  400. // We failed for some unexpected reason, return NULL and
  401. // let the caller figure it out if he so chooses.
  402. //
  403. return( Result );
  404. }
  405. }
  406. ReturnLength = GetSidLengthRequired( SID_MAX_SUB_AUTHORITIES ) + sizeof( TOKEN_USER );
  407. TokenInfo = (PTOKEN_USER)malloc( ReturnLength );
  408. if (TokenInfo != NULL) {
  409. b = GetTokenInformation (
  410. TokenHandle,
  411. TokenUser,
  412. TokenInfo,
  413. ReturnLength,
  414. &ReturnLength
  415. );
  416. if (b) {
  417. Result = TokenInfo;
  418. } else {
  419. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
  420. //
  421. // Reallocate TokenInfo
  422. //
  423. free( TokenInfo );
  424. TokenInfo = (PTOKEN_USER)malloc( ReturnLength );
  425. if (TokenInfo != NULL) {
  426. b = GetTokenInformation (
  427. TokenHandle,
  428. TokenUser,
  429. TokenInfo,
  430. ReturnLength,
  431. &ReturnLength
  432. );
  433. if (b) {
  434. Result = TokenInfo;
  435. }
  436. } else {
  437. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  438. }
  439. }
  440. }
  441. } else {
  442. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  443. }
  444. CloseHandle( TokenHandle );
  445. return( Result );
  446. }