PageRenderTime 78ms CodeModel.GetById 40ms RepoModel.GetById 0ms app.codeStats 1ms

/src/System.Console/src/System/ConsolePal.Windows.cs

https://gitlab.com/0072016/0072016-corefx-
C# | 1124 lines | 833 code | 158 blank | 133 comment | 185 complexity | ae48fd54f690f54da0c4de689ded9e2d MD5 | raw file
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. using System.IO;
  5. using System.Diagnostics;
  6. using System.Diagnostics.Contracts;
  7. using System.Runtime.InteropServices;
  8. using System.Text;
  9. using System.Threading;
  10. namespace System
  11. {
  12. // Provides Windows-based support for System.Console.
  13. internal static class ConsolePal
  14. {
  15. private const int DefaultConsoleBufferSize = 256; // default size of buffer used in stream readers/writers
  16. private static IntPtr s_InvalidHandleValue = new IntPtr(-1);
  17. public static Stream OpenStandardInput()
  18. {
  19. return GetStandardFile(Interop.mincore.HandleTypes.STD_INPUT_HANDLE, FileAccess.Read);
  20. }
  21. public static Stream OpenStandardOutput()
  22. {
  23. return GetStandardFile(Interop.mincore.HandleTypes.STD_OUTPUT_HANDLE, FileAccess.Write);
  24. }
  25. public static Stream OpenStandardError()
  26. {
  27. return GetStandardFile(Interop.mincore.HandleTypes.STD_ERROR_HANDLE, FileAccess.Write);
  28. }
  29. private static IntPtr InputHandle
  30. {
  31. get { return Interop.mincore.GetStdHandle(Interop.mincore.HandleTypes.STD_INPUT_HANDLE); }
  32. }
  33. private static IntPtr OutputHandle
  34. {
  35. get { return Interop.mincore.GetStdHandle(Interop.mincore.HandleTypes.STD_OUTPUT_HANDLE); }
  36. }
  37. private static IntPtr ErrorHandle
  38. {
  39. get { return Interop.mincore.GetStdHandle(Interop.mincore.HandleTypes.STD_ERROR_HANDLE); }
  40. }
  41. private static Stream GetStandardFile(int handleType, FileAccess access)
  42. {
  43. IntPtr handle = Interop.mincore.GetStdHandle(handleType);
  44. // If someone launches a managed process via CreateProcess, stdout,
  45. // stderr, & stdin could independently be set to INVALID_HANDLE_VALUE.
  46. // Additionally they might use 0 as an invalid handle. We also need to
  47. // ensure that if the handle is meant to be writable it actually is.
  48. if (handle == IntPtr.Zero || handle == s_InvalidHandleValue ||
  49. (access != FileAccess.Read && !ConsoleHandleIsWritable(handle)))
  50. {
  51. return Stream.Null;
  52. }
  53. return new WindowsConsoleStream(handle, access, GetUseFileAPIs(handleType));
  54. }
  55. // Checks whether stdout or stderr are writable. Do NOT pass
  56. // stdin here! The console handles are set to values like 3, 7,
  57. // and 11 OR if you've been created via CreateProcess, possibly -1
  58. // or 0. -1 is definitely invalid, while 0 is probably invalid.
  59. // Also note each handle can independently be invalid or good.
  60. // For Windows apps, the console handles are set to values like 3, 7,
  61. // and 11 but are invalid handles - you may not write to them. However,
  62. // you can still spawn a Windows app via CreateProcess and read stdout
  63. // and stderr. So, we always need to check each handle independently for validity
  64. // by trying to write or read to it, unless it is -1.
  65. private static unsafe bool ConsoleHandleIsWritable(IntPtr outErrHandle)
  66. {
  67. // Windows apps may have non-null valid looking handle values for
  68. // stdin, stdout and stderr, but they may not be readable or
  69. // writable. Verify this by calling WriteFile in the
  70. // appropriate modes. This must handle console-less Windows apps.
  71. int bytesWritten;
  72. byte junkByte = 0x41;
  73. int r = Interop.mincore.WriteFile(outErrHandle, &junkByte, 0, out bytesWritten, IntPtr.Zero);
  74. return r != 0; // In Win32 apps w/ no console, bResult should be 0 for failure.
  75. }
  76. public static Encoding InputEncoding
  77. {
  78. get { return EncodingHelper.GetSupportedConsoleEncoding((int)Interop.mincore.GetConsoleCP()); }
  79. }
  80. public static void SetConsoleInputEncoding(Encoding enc)
  81. {
  82. if (enc.CodePage != Encoding.Unicode.CodePage)
  83. {
  84. if (!Interop.mincore.SetConsoleCP(enc.CodePage))
  85. Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  86. }
  87. }
  88. public static Encoding OutputEncoding
  89. {
  90. get { return EncodingHelper.GetSupportedConsoleEncoding((int)Interop.mincore.GetConsoleOutputCP()); }
  91. }
  92. public static void SetConsoleOutputEncoding(Encoding enc)
  93. {
  94. if (enc.CodePage != Encoding.Unicode.CodePage)
  95. {
  96. if (!Interop.mincore.SetConsoleOutputCP(enc.CodePage))
  97. Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  98. }
  99. }
  100. private static bool GetUseFileAPIs(int handleType)
  101. {
  102. switch (handleType)
  103. {
  104. case Interop.mincore.HandleTypes.STD_INPUT_HANDLE:
  105. return Console.InputEncoding.CodePage != Encoding.Unicode.CodePage || Console.IsInputRedirected;
  106. case Interop.mincore.HandleTypes.STD_OUTPUT_HANDLE:
  107. return Console.OutputEncoding.CodePage != Encoding.Unicode.CodePage || Console.IsOutputRedirected;
  108. case Interop.mincore.HandleTypes.STD_ERROR_HANDLE:
  109. return Console.OutputEncoding.CodePage != Encoding.Unicode.CodePage || Console.IsErrorRedirected;
  110. default:
  111. // This can never happen.
  112. Debug.Assert(false, "Unexpected handleType value (" + handleType + ")");
  113. return true;
  114. }
  115. }
  116. /// <summary>Gets whether Console.In is targeting a terminal display.</summary>
  117. public static bool IsInputRedirectedCore()
  118. {
  119. return IsHandleRedirected(InputHandle);
  120. }
  121. /// <summary>Gets whether Console.Out is targeting a terminal display.</summary>
  122. public static bool IsOutputRedirectedCore()
  123. {
  124. return IsHandleRedirected(OutputHandle);
  125. }
  126. /// <summary>Gets whether Console.In is targeting a terminal display.</summary>
  127. public static bool IsErrorRedirectedCore()
  128. {
  129. return IsHandleRedirected(ErrorHandle);
  130. }
  131. private static bool IsHandleRedirected(IntPtr handle)
  132. {
  133. // If handle is not to a character device, we must be redirected:
  134. uint fileType = Interop.mincore.GetFileType(handle);
  135. if ((fileType & Interop.mincore.FileTypes.FILE_TYPE_CHAR) != Interop.mincore.FileTypes.FILE_TYPE_CHAR)
  136. return true;
  137. // We are on a char device if GetConsoleMode succeeds and so we are not redirected.
  138. return (!Interop.mincore.IsGetConsoleModeCallSuccessful(handle));
  139. }
  140. internal static TextReader GetOrCreateReader()
  141. {
  142. Stream inputStream = OpenStandardInput();
  143. return SyncTextReader.GetSynchronizedTextReader(inputStream == Stream.Null ?
  144. StreamReader.Null :
  145. new StreamReader(
  146. stream: inputStream,
  147. encoding: new ConsoleEncoding(Console.InputEncoding),
  148. detectEncodingFromByteOrderMarks: false,
  149. bufferSize: DefaultConsoleBufferSize,
  150. leaveOpen: true));
  151. }
  152. // Use this for blocking in Console.ReadKey, which needs to protect itself in case multiple threads call it simultaneously.
  153. // Use a ReadKey-specific lock though, to allow other fields to be initialized on this type.
  154. private static readonly Object s_readKeySyncObject = new object();
  155. // ReadLine & Read can't use this because they need to use ReadFile
  156. // to be able to handle redirected input. We have to accept that
  157. // we will lose repeated keystrokes when someone switches from
  158. // calling ReadKey to calling Read or ReadLine. Those methods should
  159. // ideally flush this cache as well.
  160. [System.Security.SecurityCritical] // auto-generated
  161. private static Interop.InputRecord _cachedInputRecord;
  162. // Skip non key events. Generally we want to surface only KeyDown event
  163. // and suppress KeyUp event from the same Key press but there are cases
  164. // where the assumption of KeyDown-KeyUp pairing for a given key press
  165. // is invalid. For example in IME Unicode keyboard input, we often see
  166. // only KeyUp until the key is released.
  167. [System.Security.SecurityCritical] // auto-generated
  168. private static bool IsKeyDownEvent(Interop.InputRecord ir)
  169. {
  170. return (ir.eventType == Interop.KEY_EVENT && ir.keyEvent.keyDown);
  171. }
  172. [System.Security.SecurityCritical] // auto-generated
  173. private static bool IsModKey(Interop.InputRecord ir)
  174. {
  175. // We should also skip over Shift, Control, and Alt, as well as caps lock.
  176. // Apparently we don't need to check for 0xA0 through 0xA5, which are keys like
  177. // Left Control & Right Control. See the ConsoleKey enum for these values.
  178. short keyCode = ir.keyEvent.virtualKeyCode;
  179. return ((keyCode >= 0x10 && keyCode <= 0x12)
  180. || keyCode == 0x14 || keyCode == 0x90 || keyCode == 0x91);
  181. }
  182. [Flags]
  183. internal enum ControlKeyState
  184. {
  185. RightAltPressed = 0x0001,
  186. LeftAltPressed = 0x0002,
  187. RightCtrlPressed = 0x0004,
  188. LeftCtrlPressed = 0x0008,
  189. ShiftPressed = 0x0010,
  190. NumLockOn = 0x0020,
  191. ScrollLockOn = 0x0040,
  192. CapsLockOn = 0x0080,
  193. EnhancedKey = 0x0100
  194. }
  195. // For tracking Alt+NumPad unicode key sequence. When you press Alt key down
  196. // and press a numpad unicode decimal sequence and then release Alt key, the
  197. // desired effect is to translate the sequence into one Unicode KeyPress.
  198. // We need to keep track of the Alt+NumPad sequence and surface the final
  199. // unicode char alone when the Alt key is released.
  200. [System.Security.SecurityCritical] // auto-generated
  201. private static bool IsAltKeyDown(Interop.InputRecord ir)
  202. {
  203. return (((ControlKeyState)ir.keyEvent.controlKeyState)
  204. & (ControlKeyState.LeftAltPressed | ControlKeyState.RightAltPressed)) != 0;
  205. }
  206. private const int NumberLockVKCode = 0x90;
  207. private const int CapsLockVKCode = 0x14;
  208. public static bool NumberLock
  209. {
  210. get
  211. {
  212. try
  213. {
  214. short s = Interop.mincore.GetKeyState(NumberLockVKCode);
  215. return (s & 1) == 1;
  216. }
  217. catch (Exception)
  218. {
  219. // Since we depend on an extension api-set here
  220. // it is not guaranteed to work across the board.
  221. // In case of exception we simply throw PNSE
  222. throw new PlatformNotSupportedException();
  223. }
  224. }
  225. }
  226. public static bool CapsLock
  227. {
  228. get
  229. {
  230. try
  231. {
  232. short s = Interop.mincore.GetKeyState(CapsLockVKCode);
  233. return (s & 1) == 1;
  234. }
  235. catch (Exception)
  236. {
  237. // Since we depend on an extension api-set here
  238. // it is not guaranteed to work across the board.
  239. // In case of exception we simply throw PNSE
  240. throw new PlatformNotSupportedException();
  241. }
  242. }
  243. }
  244. public static bool KeyAvailable
  245. {
  246. get
  247. {
  248. if (_cachedInputRecord.eventType == Interop.KEY_EVENT)
  249. return true;
  250. Interop.InputRecord ir = new Interop.InputRecord();
  251. int numEventsRead = 0;
  252. while (true)
  253. {
  254. bool r = Interop.mincore.PeekConsoleInput(InputHandle, out ir, 1, out numEventsRead);
  255. if (!r)
  256. {
  257. int errorCode = Marshal.GetLastWin32Error();
  258. if (errorCode == Interop.mincore.Errors.ERROR_INVALID_HANDLE)
  259. throw new InvalidOperationException(SR.InvalidOperation_ConsoleKeyAvailableOnFile);
  260. throw Win32Marshal.GetExceptionForWin32Error(errorCode, "stdin");
  261. }
  262. if (numEventsRead == 0)
  263. return false;
  264. // Skip non key-down && mod key events.
  265. if (!IsKeyDownEvent(ir) || IsModKey(ir))
  266. {
  267. r = Interop.mincore.ReadConsoleInput(InputHandle, out ir, 1, out numEventsRead);
  268. if (!r)
  269. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  270. }
  271. else
  272. {
  273. return true;
  274. }
  275. }
  276. } // get
  277. }
  278. private const short AltVKCode = 0x12;
  279. public static ConsoleKeyInfo ReadKey(bool intercept)
  280. {
  281. Interop.InputRecord ir;
  282. int numEventsRead = -1;
  283. bool r;
  284. lock (s_readKeySyncObject)
  285. {
  286. if (_cachedInputRecord.eventType == Interop.KEY_EVENT)
  287. {
  288. // We had a previous keystroke with repeated characters.
  289. ir = _cachedInputRecord;
  290. if (_cachedInputRecord.keyEvent.repeatCount == 0)
  291. _cachedInputRecord.eventType = -1;
  292. else
  293. {
  294. _cachedInputRecord.keyEvent.repeatCount--;
  295. }
  296. // We will return one key from this method, so we decrement the
  297. // repeatCount here, leaving the cachedInputRecord in the "queue".
  298. }
  299. else
  300. { // We did NOT have a previous keystroke with repeated characters:
  301. while (true)
  302. {
  303. r = Interop.mincore.ReadConsoleInput(InputHandle, out ir, 1, out numEventsRead);
  304. if (!r || numEventsRead == 0)
  305. {
  306. // This will fail when stdin is redirected from a file or pipe.
  307. // We could theoretically call Console.Read here, but I
  308. // think we might do some things incorrectly then.
  309. throw new InvalidOperationException(SR.InvalidOperation_ConsoleReadKeyOnFile);
  310. }
  311. short keyCode = ir.keyEvent.virtualKeyCode;
  312. // First check for non-keyboard events & discard them. Generally we tap into only KeyDown events and ignore the KeyUp events
  313. // but it is possible that we are dealing with a Alt+NumPad unicode key sequence, the final unicode char is revealed only when
  314. // the Alt key is released (i.e when the sequence is complete). To avoid noise, when the Alt key is down, we should eat up
  315. // any intermediate key strokes (from NumPad) that collectively forms the Unicode character.
  316. if (!IsKeyDownEvent(ir))
  317. {
  318. // REVIEW: Unicode IME input comes through as KeyUp event with no accompanying KeyDown.
  319. if (keyCode != AltVKCode)
  320. continue;
  321. }
  322. char ch = (char)ir.keyEvent.uChar;
  323. // In a Alt+NumPad unicode sequence, when the alt key is released uChar will represent the final unicode character, we need to
  324. // surface this. VirtualKeyCode for this event will be Alt from the Alt-Up key event. This is probably not the right code,
  325. // especially when we don't expose ConsoleKey.Alt, so this will end up being the hex value (0x12). VK_PACKET comes very
  326. // close to being useful and something that we could look into using for this purpose...
  327. if (ch == 0)
  328. {
  329. // Skip mod keys.
  330. if (IsModKey(ir))
  331. continue;
  332. }
  333. // When Alt is down, it is possible that we are in the middle of a Alt+NumPad unicode sequence.
  334. // Escape any intermediate NumPad keys whether NumLock is on or not (notepad behavior)
  335. ConsoleKey key = (ConsoleKey)keyCode;
  336. if (IsAltKeyDown(ir) && ((key >= ConsoleKey.NumPad0 && key <= ConsoleKey.NumPad9)
  337. || (key == ConsoleKey.Clear) || (key == ConsoleKey.Insert)
  338. || (key >= ConsoleKey.PageUp && key <= ConsoleKey.DownArrow)))
  339. {
  340. continue;
  341. }
  342. if (ir.keyEvent.repeatCount > 1)
  343. {
  344. ir.keyEvent.repeatCount--;
  345. _cachedInputRecord = ir;
  346. }
  347. break;
  348. }
  349. } // we did NOT have a previous keystroke with repeated characters.
  350. }
  351. ControlKeyState state = (ControlKeyState)ir.keyEvent.controlKeyState;
  352. bool shift = (state & ControlKeyState.ShiftPressed) != 0;
  353. bool alt = (state & (ControlKeyState.LeftAltPressed | ControlKeyState.RightAltPressed)) != 0;
  354. bool control = (state & (ControlKeyState.LeftCtrlPressed | ControlKeyState.RightCtrlPressed)) != 0;
  355. ConsoleKeyInfo info = new ConsoleKeyInfo((char)ir.keyEvent.uChar, (ConsoleKey)ir.keyEvent.virtualKeyCode, shift, alt, control);
  356. if (!intercept)
  357. Console.Write(ir.keyEvent.uChar);
  358. return info;
  359. }
  360. public static bool TreatControlCAsInput
  361. {
  362. get
  363. {
  364. IntPtr handle = InputHandle;
  365. if (handle == s_InvalidHandleValue)
  366. throw new IOException(SR.IO_NoConsole);
  367. int mode = 0;
  368. if (!Interop.mincore.GetConsoleMode(handle, out mode))
  369. Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  370. return (mode & Interop.mincore.ENABLE_PROCESSED_INPUT) == 0;
  371. }
  372. set
  373. {
  374. IntPtr handle = InputHandle;
  375. if (handle == s_InvalidHandleValue)
  376. throw new IOException(SR.IO_NoConsole);
  377. int mode = 0;
  378. Interop.mincore.GetConsoleMode(handle, out mode); // failure ignored in full framework
  379. if (value)
  380. {
  381. mode &= ~Interop.mincore.ENABLE_PROCESSED_INPUT;
  382. }
  383. else
  384. {
  385. mode |= Interop.mincore.ENABLE_PROCESSED_INPUT;
  386. }
  387. if (!Interop.mincore.SetConsoleMode(handle, mode))
  388. Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  389. }
  390. }
  391. // For ResetColor
  392. private static volatile bool _haveReadDefaultColors;
  393. private static volatile byte _defaultColors;
  394. public static ConsoleColor BackgroundColor
  395. {
  396. get
  397. {
  398. bool succeeded;
  399. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded);
  400. return succeeded ?
  401. ColorAttributeToConsoleColor((Interop.mincore.Color)csbi.wAttributes & Interop.mincore.Color.BackgroundMask) :
  402. ConsoleColor.Black; // for code that may be used from Windows app w/ no console
  403. }
  404. set
  405. {
  406. Interop.mincore.Color c = ConsoleColorToColorAttribute(value, true);
  407. bool succeeded;
  408. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded);
  409. // For code that may be used from Windows app w/ no console
  410. if (!succeeded)
  411. return;
  412. Debug.Assert(_haveReadDefaultColors, "Setting the background color before we've read the default foreground color!");
  413. short attrs = csbi.wAttributes;
  414. attrs &= ~((short)Interop.mincore.Color.BackgroundMask);
  415. // C#'s bitwise-or sign-extends to 32 bits.
  416. attrs = (short)(((uint)(ushort)attrs) | ((uint)(ushort)c));
  417. // Ignore errors here - there are some scenarios for running code that wants
  418. // to print in colors to the console in a Windows application.
  419. Interop.mincore.SetConsoleTextAttribute(OutputHandle, attrs);
  420. }
  421. }
  422. public static ConsoleColor ForegroundColor
  423. {
  424. get
  425. {
  426. bool succeeded;
  427. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded);
  428. // For code that may be used from Windows app w/ no console
  429. return succeeded ?
  430. ColorAttributeToConsoleColor((Interop.mincore.Color)csbi.wAttributes & Interop.mincore.Color.ForegroundMask) :
  431. ConsoleColor.Gray;
  432. }
  433. set
  434. {
  435. Interop.mincore.Color c = ConsoleColorToColorAttribute(value, false);
  436. bool succeeded;
  437. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded);
  438. // For code that may be used from Windows app w/ no console
  439. if (!succeeded)
  440. return;
  441. Debug.Assert(_haveReadDefaultColors, "Setting the foreground color before we've read the default foreground color!");
  442. short attrs = csbi.wAttributes;
  443. attrs &= ~((short)Interop.mincore.Color.ForegroundMask);
  444. // C#'s bitwise-or sign-extends to 32 bits.
  445. attrs = (short)(((uint)(ushort)attrs) | ((uint)(ushort)c));
  446. // Ignore errors here - there are some scenarios for running code that wants
  447. // to print in colors to the console in a Windows application.
  448. Interop.mincore.SetConsoleTextAttribute(OutputHandle, attrs);
  449. }
  450. }
  451. public static void ResetColor()
  452. {
  453. bool succeeded;
  454. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo(false, out succeeded);
  455. if (!succeeded)
  456. return; // For code that may be used from Windows app w/ no console
  457. Debug.Assert(_haveReadDefaultColors, "Resetting color before we've read the default foreground color!");
  458. // Ignore errors here - there are some scenarios for running code that wants
  459. // to print in colors to the console in a Windows application.
  460. Interop.mincore.SetConsoleTextAttribute(OutputHandle, (short)(ushort)_defaultColors);
  461. }
  462. public static int CursorSize
  463. {
  464. get
  465. {
  466. Interop.mincore.CONSOLE_CURSOR_INFO cci;
  467. if (!Interop.mincore.GetConsoleCursorInfo(OutputHandle, out cci))
  468. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  469. return cci.dwSize;
  470. }
  471. set
  472. {
  473. // Value should be a percentage from [1, 100].
  474. if (value < 1 || value > 100)
  475. throw new ArgumentOutOfRangeException(nameof(value), value, SR.ArgumentOutOfRange_CursorSize);
  476. Contract.EndContractBlock();
  477. Interop.mincore.CONSOLE_CURSOR_INFO cci;
  478. if (!Interop.mincore.GetConsoleCursorInfo(OutputHandle, out cci))
  479. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  480. cci.dwSize = value;
  481. if (!Interop.mincore.SetConsoleCursorInfo(OutputHandle, ref cci))
  482. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  483. }
  484. }
  485. public static bool CursorVisible
  486. {
  487. get
  488. {
  489. Interop.mincore.CONSOLE_CURSOR_INFO cci;
  490. if (!Interop.mincore.GetConsoleCursorInfo(OutputHandle, out cci))
  491. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  492. return cci.bVisible;
  493. }
  494. set
  495. {
  496. Interop.mincore.CONSOLE_CURSOR_INFO cci;
  497. if (!Interop.mincore.GetConsoleCursorInfo(OutputHandle, out cci))
  498. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  499. cci.bVisible = value;
  500. if (!Interop.mincore.SetConsoleCursorInfo(OutputHandle, ref cci))
  501. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  502. }
  503. }
  504. public static int CursorLeft
  505. {
  506. get
  507. {
  508. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
  509. return csbi.dwCursorPosition.X;
  510. }
  511. }
  512. public static int CursorTop
  513. {
  514. get
  515. {
  516. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
  517. return csbi.dwCursorPosition.Y;
  518. }
  519. }
  520. // Although msdn states that the max allowed limit is 65K,
  521. // desktop limits this to 24500 as buffer sizes greater than it
  522. // throw.
  523. private const int MaxConsoleTitleLength = 24500;
  524. public static string Title
  525. {
  526. [System.Security.SecuritySafeCritical] // auto-generated
  527. get
  528. {
  529. string title = null;
  530. int titleLength = -1;
  531. int r = Interop.mincore.GetConsoleTitle(out title, out titleLength);
  532. if (0 != r)
  533. {
  534. throw Win32Marshal.GetExceptionForWin32Error(r, string.Empty);
  535. }
  536. if (titleLength > MaxConsoleTitleLength)
  537. throw new InvalidOperationException(SR.ArgumentOutOfRange_ConsoleTitleTooLong);
  538. Debug.Assert(title.Length == titleLength);
  539. return title;
  540. }
  541. [System.Security.SecuritySafeCritical] // auto-generated
  542. set
  543. {
  544. if (value == null)
  545. throw new ArgumentNullException(nameof(value));
  546. if (value.Length > MaxConsoleTitleLength)
  547. throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_ConsoleTitleTooLong);
  548. Contract.EndContractBlock();
  549. if (!Interop.mincore.SetConsoleTitle(value))
  550. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  551. }
  552. }
  553. private const int BeepFrequencyInHz = 800;
  554. private const int BeepDurationInMs = 200;
  555. public static void Beep()
  556. {
  557. Interop.mincore.Beep(BeepFrequencyInHz, BeepDurationInMs);
  558. }
  559. private const int MinBeepFrequency = 37;
  560. private const int MaxBeepFrequency = 32767;
  561. public static void Beep(int frequency, int duration)
  562. {
  563. if (frequency < MinBeepFrequency || frequency > MaxBeepFrequency)
  564. throw new ArgumentOutOfRangeException(nameof(frequency), frequency, SR.Format(SR.ArgumentOutOfRange_BeepFrequency, MinBeepFrequency, MaxBeepFrequency));
  565. if (duration <= 0)
  566. throw new ArgumentOutOfRangeException(nameof(duration), duration, SR.ArgumentOutOfRange_NeedPosNum);
  567. Contract.EndContractBlock();
  568. Interop.mincore.Beep(frequency, duration);
  569. }
  570. public unsafe static void MoveBufferArea(int sourceLeft, int sourceTop,
  571. int sourceWidth, int sourceHeight, int targetLeft, int targetTop,
  572. char sourceChar, ConsoleColor sourceForeColor,
  573. ConsoleColor sourceBackColor)
  574. {
  575. if (sourceForeColor < ConsoleColor.Black || sourceForeColor > ConsoleColor.White)
  576. throw new ArgumentException(SR.Arg_InvalidConsoleColor, nameof(sourceForeColor));
  577. if (sourceBackColor < ConsoleColor.Black || sourceBackColor > ConsoleColor.White)
  578. throw new ArgumentException(SR.Arg_InvalidConsoleColor, nameof(sourceBackColor));
  579. Contract.EndContractBlock();
  580. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
  581. Interop.mincore.COORD bufferSize = csbi.dwSize;
  582. if (sourceLeft < 0 || sourceLeft > bufferSize.X)
  583. throw new ArgumentOutOfRangeException(nameof(sourceLeft), sourceLeft, SR.ArgumentOutOfRange_ConsoleBufferBoundaries);
  584. if (sourceTop < 0 || sourceTop > bufferSize.Y)
  585. throw new ArgumentOutOfRangeException(nameof(sourceTop), sourceTop, SR.ArgumentOutOfRange_ConsoleBufferBoundaries);
  586. if (sourceWidth < 0 || sourceWidth > bufferSize.X - sourceLeft)
  587. throw new ArgumentOutOfRangeException(nameof(sourceWidth), sourceWidth, SR.ArgumentOutOfRange_ConsoleBufferBoundaries);
  588. if (sourceHeight < 0 || sourceTop > bufferSize.Y - sourceHeight)
  589. throw new ArgumentOutOfRangeException(nameof(sourceHeight), sourceHeight, SR.ArgumentOutOfRange_ConsoleBufferBoundaries);
  590. // Note: if the target range is partially in and partially out
  591. // of the buffer, then we let the OS clip it for us.
  592. if (targetLeft < 0 || targetLeft > bufferSize.X)
  593. throw new ArgumentOutOfRangeException(nameof(targetLeft), targetLeft, SR.ArgumentOutOfRange_ConsoleBufferBoundaries);
  594. if (targetTop < 0 || targetTop > bufferSize.Y)
  595. throw new ArgumentOutOfRangeException(nameof(targetTop), targetTop, SR.ArgumentOutOfRange_ConsoleBufferBoundaries);
  596. // If we're not doing any work, bail out now (Windows will return
  597. // an error otherwise)
  598. if (sourceWidth == 0 || sourceHeight == 0)
  599. return;
  600. // Read data from the original location, blank it out, then write
  601. // it to the new location. This will handle overlapping source and
  602. // destination regions correctly.
  603. // Read the old data
  604. Interop.mincore.CHAR_INFO[] data = new Interop.mincore.CHAR_INFO[sourceWidth * sourceHeight];
  605. bufferSize.X = (short)sourceWidth;
  606. bufferSize.Y = (short)sourceHeight;
  607. Interop.mincore.COORD bufferCoord = new Interop.mincore.COORD();
  608. Interop.mincore.SMALL_RECT readRegion = new Interop.mincore.SMALL_RECT();
  609. readRegion.Left = (short)sourceLeft;
  610. readRegion.Right = (short)(sourceLeft + sourceWidth - 1);
  611. readRegion.Top = (short)sourceTop;
  612. readRegion.Bottom = (short)(sourceTop + sourceHeight - 1);
  613. bool r;
  614. fixed (Interop.mincore.CHAR_INFO* pCharInfo = data)
  615. r = Interop.mincore.ReadConsoleOutput(OutputHandle, pCharInfo, bufferSize, bufferCoord, ref readRegion);
  616. if (!r)
  617. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  618. // Overwrite old section
  619. Interop.mincore.COORD writeCoord = new Interop.mincore.COORD();
  620. writeCoord.X = (short)sourceLeft;
  621. Interop.mincore.Color c = ConsoleColorToColorAttribute(sourceBackColor, true);
  622. c |= ConsoleColorToColorAttribute(sourceForeColor, false);
  623. short attr = (short)c;
  624. int numWritten;
  625. for (int i = sourceTop; i < sourceTop + sourceHeight; i++)
  626. {
  627. writeCoord.Y = (short)i;
  628. r = Interop.mincore.FillConsoleOutputCharacter(OutputHandle, sourceChar, sourceWidth, writeCoord, out numWritten);
  629. Debug.Assert(numWritten == sourceWidth, "FillConsoleOutputCharacter wrote the wrong number of chars!");
  630. if (!r)
  631. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  632. r = Interop.mincore.FillConsoleOutputAttribute(OutputHandle, attr, sourceWidth, writeCoord, out numWritten);
  633. if (!r)
  634. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  635. }
  636. // Write text to new location
  637. Interop.mincore.SMALL_RECT writeRegion = new Interop.mincore.SMALL_RECT();
  638. writeRegion.Left = (short)targetLeft;
  639. writeRegion.Right = (short)(targetLeft + sourceWidth);
  640. writeRegion.Top = (short)targetTop;
  641. writeRegion.Bottom = (short)(targetTop + sourceHeight);
  642. fixed (Interop.mincore.CHAR_INFO* pCharInfo = data)
  643. Interop.mincore.WriteConsoleOutput(OutputHandle, pCharInfo, bufferSize, bufferCoord, ref writeRegion);
  644. }
  645. public static void Clear()
  646. {
  647. Interop.mincore.COORD coordScreen = new Interop.mincore.COORD();
  648. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi;
  649. bool success;
  650. int conSize;
  651. IntPtr hConsole = OutputHandle;
  652. if (hConsole == s_InvalidHandleValue)
  653. throw new IOException(SR.IO_NoConsole);
  654. // get the number of character cells in the current buffer
  655. // Go through my helper method for fetching a screen buffer info
  656. // to correctly handle default console colors.
  657. csbi = GetBufferInfo();
  658. conSize = csbi.dwSize.X * csbi.dwSize.Y;
  659. // fill the entire screen with blanks
  660. int numCellsWritten = 0;
  661. success = Interop.mincore.FillConsoleOutputCharacter(hConsole, ' ',
  662. conSize, coordScreen, out numCellsWritten);
  663. if (!success)
  664. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  665. // now set the buffer's attributes accordingly
  666. numCellsWritten = 0;
  667. success = Interop.mincore.FillConsoleOutputAttribute(hConsole, csbi.wAttributes,
  668. conSize, coordScreen, out numCellsWritten);
  669. if (!success)
  670. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  671. // put the cursor at (0, 0)
  672. success = Interop.mincore.SetConsoleCursorPosition(hConsole, coordScreen);
  673. if (!success)
  674. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  675. }
  676. public static void SetCursorPosition(int left, int top)
  677. {
  678. // Note on argument checking - the upper bounds are NOT correct
  679. // here! But it looks slightly expensive to compute them. Let
  680. // Windows calculate them, then we'll give a nice error message.
  681. if (left < 0 || left >= short.MaxValue)
  682. throw new ArgumentOutOfRangeException(nameof(left), left, SR.ArgumentOutOfRange_ConsoleBufferBoundaries);
  683. if (top < 0 || top >= short.MaxValue)
  684. throw new ArgumentOutOfRangeException(nameof(top), top, SR.ArgumentOutOfRange_ConsoleBufferBoundaries);
  685. Contract.EndContractBlock();
  686. IntPtr hConsole = OutputHandle;
  687. Interop.mincore.COORD coords = new Interop.mincore.COORD();
  688. coords.X = (short)left;
  689. coords.Y = (short)top;
  690. if (!Interop.mincore.SetConsoleCursorPosition(hConsole, coords))
  691. {
  692. // Give a nice error message for out of range sizes
  693. int errorCode = Marshal.GetLastWin32Error();
  694. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
  695. if (left < 0 || left >= csbi.dwSize.X)
  696. throw new ArgumentOutOfRangeException(nameof(left), left, SR.ArgumentOutOfRange_ConsoleBufferBoundaries);
  697. if (top < 0 || top >= csbi.dwSize.Y)
  698. throw new ArgumentOutOfRangeException(nameof(top), top, SR.ArgumentOutOfRange_ConsoleBufferBoundaries);
  699. throw Win32Marshal.GetExceptionForWin32Error(errorCode);
  700. }
  701. }
  702. public static int BufferWidth
  703. {
  704. [System.Security.SecuritySafeCritical] // auto-generated
  705. get
  706. {
  707. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
  708. return csbi.dwSize.X;
  709. }
  710. set
  711. {
  712. SetBufferSize(value, BufferHeight);
  713. }
  714. }
  715. public static int BufferHeight
  716. {
  717. [System.Security.SecuritySafeCritical] // auto-generated
  718. get
  719. {
  720. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
  721. return csbi.dwSize.Y;
  722. }
  723. set
  724. {
  725. SetBufferSize(BufferWidth, value);
  726. }
  727. }
  728. [System.Security.SecuritySafeCritical] // auto-generated
  729. public static void SetBufferSize(int width, int height)
  730. {
  731. // Ensure the new size is not smaller than the console window
  732. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
  733. Interop.mincore.SMALL_RECT srWindow = csbi.srWindow;
  734. if (width < srWindow.Right + 1 || width >= short.MaxValue)
  735. throw new ArgumentOutOfRangeException(nameof(width), width, SR.ArgumentOutOfRange_ConsoleBufferLessThanWindowSize);
  736. if (height < srWindow.Bottom + 1 || height >= short.MaxValue)
  737. throw new ArgumentOutOfRangeException(nameof(height), height, SR.ArgumentOutOfRange_ConsoleBufferLessThanWindowSize);
  738. Interop.mincore.COORD size = new Interop.mincore.COORD();
  739. size.X = (short)width;
  740. size.Y = (short)height;
  741. if (!Interop.mincore.SetConsoleScreenBufferSize(OutputHandle, size))
  742. {
  743. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  744. }
  745. }
  746. public static int LargestWindowWidth
  747. {
  748. [System.Security.SecuritySafeCritical] // auto-generated
  749. get
  750. {
  751. // Note this varies based on current screen resolution and
  752. // current console font. Do not cache this value.
  753. Interop.mincore.COORD bounds = Interop.mincore.GetLargestConsoleWindowSize(OutputHandle);
  754. return bounds.X;
  755. }
  756. }
  757. public static int LargestWindowHeight
  758. {
  759. [System.Security.SecuritySafeCritical] // auto-generated
  760. get
  761. {
  762. // Note this varies based on current screen resolution and
  763. // current console font. Do not cache this value.
  764. Interop.mincore.COORD bounds = Interop.mincore.GetLargestConsoleWindowSize(OutputHandle);
  765. return bounds.Y;
  766. }
  767. }
  768. public static int WindowLeft
  769. {
  770. get
  771. {
  772. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
  773. return csbi.srWindow.Left;
  774. }
  775. set
  776. {
  777. SetWindowPosition(value, WindowTop);
  778. }
  779. }
  780. public static int WindowTop
  781. {
  782. get
  783. {
  784. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
  785. return csbi.srWindow.Left;
  786. }
  787. set
  788. {
  789. SetWindowPosition(WindowLeft, value);
  790. }
  791. }
  792. public static int WindowWidth
  793. {
  794. get
  795. {
  796. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
  797. return csbi.srWindow.Right - csbi.srWindow.Left + 1;
  798. }
  799. set
  800. {
  801. SetWindowSize(value, WindowHeight);
  802. }
  803. }
  804. public static int WindowHeight
  805. {
  806. get
  807. {
  808. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
  809. return csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
  810. }
  811. set
  812. {
  813. SetWindowSize(WindowWidth, value);
  814. }
  815. }
  816. public static unsafe void SetWindowPosition(int left, int top)
  817. {
  818. // Get the size of the current console window
  819. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
  820. Interop.mincore.SMALL_RECT srWindow = csbi.srWindow;
  821. // Check for arithmetic underflows & overflows.
  822. int newRight = left + srWindow.Right - srWindow.Left + 1;
  823. if (left < 0 || newRight > csbi.dwSize.X || newRight < 0)
  824. throw new ArgumentOutOfRangeException(nameof(left), left, SR.ArgumentOutOfRange_ConsoleWindowPos);
  825. int newBottom = top + srWindow.Bottom - srWindow.Top + 1;
  826. if (top < 0 || newBottom > csbi.dwSize.Y || newBottom < 0)
  827. throw new ArgumentOutOfRangeException(nameof(top), top, SR.ArgumentOutOfRange_ConsoleWindowPos);
  828. // Preserve the size, but move the position.
  829. srWindow.Bottom -= (short)(srWindow.Top - top);
  830. srWindow.Right -= (short)(srWindow.Left - left);
  831. srWindow.Left = (short)left;
  832. srWindow.Top = (short)top;
  833. bool r = Interop.mincore.SetConsoleWindowInfo(OutputHandle, true, &srWindow);
  834. if (!r)
  835. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  836. }
  837. public static unsafe void SetWindowSize(int width, int height)
  838. {
  839. if (width <= 0)
  840. throw new ArgumentOutOfRangeException(nameof(width), width, SR.ArgumentOutOfRange_NeedPosNum);
  841. if (height <= 0)
  842. throw new ArgumentOutOfRangeException(nameof(height), height, SR.ArgumentOutOfRange_NeedPosNum);
  843. // Get the position of the current console window
  844. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi = GetBufferInfo();
  845. // If the buffer is smaller than this new window size, resize the
  846. // buffer to be large enough. Include window position.
  847. bool resizeBuffer = false;
  848. Interop.mincore.COORD size = new Interop.mincore.COORD();
  849. size.X = csbi.dwSize.X;
  850. size.Y = csbi.dwSize.Y;
  851. if (csbi.dwSize.X < csbi.srWindow.Left + width)
  852. {
  853. if (csbi.srWindow.Left >= short.MaxValue - width)
  854. throw new ArgumentOutOfRangeException(nameof(width), SR.ArgumentOutOfRange_ConsoleWindowBufferSize);
  855. size.X = (short)(csbi.srWindow.Left + width);
  856. resizeBuffer = true;
  857. }
  858. if (csbi.dwSize.Y < csbi.srWindow.Top + height)
  859. {
  860. if (csbi.srWindow.Top >= short.MaxValue - height)
  861. throw new ArgumentOutOfRangeException(nameof(height), SR.ArgumentOutOfRange_ConsoleWindowBufferSize);
  862. size.Y = (short)(csbi.srWindow.Top + height);
  863. resizeBuffer = true;
  864. }
  865. if (resizeBuffer)
  866. {
  867. if (!Interop.mincore.SetConsoleScreenBufferSize(OutputHandle, size))
  868. throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastWin32Error());
  869. }
  870. Interop.mincore.SMALL_RECT srWindow = csbi.srWindow;
  871. // Preserve the position, but change the size.
  872. srWindow.Bottom = (short)(srWindow.Top + height - 1);
  873. srWindow.Right = (short)(srWindow.Left + width - 1);
  874. if (!Interop.mincore.SetConsoleWindowInfo(OutputHandle, true, &srWindow))
  875. {
  876. int errorCode = Marshal.GetLastWin32Error();
  877. // If we resized the buffer, un-resize it.
  878. if (resizeBuffer)
  879. {
  880. Interop.mincore.SetConsoleScreenBufferSize(OutputHandle, csbi.dwSize);
  881. }
  882. // Try to give a better error message here
  883. Interop.mincore.COORD bounds = Interop.mincore.GetLargestConsoleWindowSize(OutputHandle);
  884. if (width > bounds.X)
  885. throw new ArgumentOutOfRangeException(nameof(width), width, SR.Format(SR.ArgumentOutOfRange_ConsoleWindowSize_Size, bounds.X));
  886. if (height > bounds.Y)
  887. throw new ArgumentOutOfRangeException(nameof(height), height, SR.Format(SR.ArgumentOutOfRange_ConsoleWindowSize_Size, bounds.Y));
  888. throw Win32Marshal.GetExceptionForWin32Error(errorCode);
  889. }
  890. }
  891. private static Interop.mincore.Color ConsoleColorToColorAttribute(ConsoleColor color, bool isBackground)
  892. {
  893. if ((((int)color) & ~0xf) != 0)
  894. throw new ArgumentException(SR.Arg_InvalidConsoleColor);
  895. Contract.EndContractBlock();
  896. Interop.mincore.Color c = (Interop.mincore.Color)color;
  897. // Make these background colors instead of foreground
  898. if (isBackground)
  899. c = (Interop.mincore.Color)((int)c << 4);
  900. return c;
  901. }
  902. private static ConsoleColor ColorAttributeToConsoleColor(Interop.mincore.Color c)
  903. {
  904. // Turn background colors into foreground colors.
  905. if ((c & Interop.mincore.Color.BackgroundMask) != 0)
  906. {
  907. c = (Interop.mincore.Color)(((int)c) >> 4);
  908. }
  909. return (ConsoleColor)c;
  910. }
  911. private static Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO GetBufferInfo()
  912. {
  913. bool unused;
  914. return GetBufferInfo(true, out unused);
  915. }
  916. // For apps that don't have a console (like Windows apps), they might
  917. // run other code that includes color console output. Allow a mechanism
  918. // where that code won't throw an exception for simple errors.
  919. private static Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO GetBufferInfo(bool throwOnNoConsole, out bool succeeded)
  920. {
  921. succeeded = false;
  922. IntPtr outputHandle = OutputHandle;
  923. if (outputHandle == s_InvalidHandleValue)
  924. {
  925. if (throwOnNoConsole)
  926. {
  927. throw new IOException(SR.IO_NoConsole);
  928. }
  929. return new Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO();
  930. }
  931. // Note that if stdout is redirected to a file, the console handle may be a file.
  932. // First try stdout; if this fails, try stderr and then stdin.
  933. Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO csbi;
  934. if (!Interop.mincore.GetConsoleScreenBufferInfo(outputHandle, out csbi) &&
  935. !Interop.mincore.GetConsoleScreenBufferInfo(ErrorHandle, out csbi) &&
  936. !Interop.mincore.GetConsoleScreenBufferInfo(InputHandle, out csbi))
  937. {
  938. int errorCode = Marshal.GetLastWin32Error();
  939. if (errorCode == Interop.mincore.Errors.ERROR_INVALID_HANDLE && !throwOnNoConsole)
  940. return new Interop.mincore.CONSOLE_SCREEN_BUFFER_INFO();
  941. throw Win32Marshal.GetExceptionForWin32Error(errorCode);
  942. }
  943. if (!_haveReadDefaultColors)
  944. {
  945. // Fetch the default foreground and background color for the ResetColor method.
  946. Debug.Assert((int)Interop.mincore.Color.ColorMask == 0xff, "Make sure one byte is large enough to store a Console color value!");
  947. _defaultColors = (byte)(csbi.wAttributes & (short)Interop.mincore.Color.ColorMask);
  948. _haveReadDefaultColors = true;
  949. }
  950. succeeded = true;
  951. return csbi;
  952. }
  953. private sealed class WindowsConsoleStream : ConsoleStream
  954. {
  955. // We know that if we are using console APIs rather than file APIs, then the encoding
  956. // is Encoding.Unicode implying 2 bytes per character:
  957. const int BytesPerWChar = 2;
  958. private readonly bool _isPipe; // When reading from pipes, we need to properly handle EOF cases.
  959. private IntPtr _handle;
  960. private readonly bool _useFileAPIs;
  961. internal WindowsConsoleStream(IntPtr handle, FileAccess access, bool useFileAPIs)
  962. : base(access)
  963. {
  964. Debug.Assert(handle != IntPtr.Zero && handle != s_InvalidHandleValue, "ConsoleStream expects a valid handle!");
  965. _handle = handle;
  966. _isPipe = Interop.mincore.GetFileType(handle) == Interop.mincore.FileTypes.FILE_TYPE_P