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.

3649 lines
119 KiB

  1. /*++
  2. Copyright (c) 1985 - 1999, Microsoft Corporation
  3. Module Name:
  4. private.c
  5. Abstract:
  6. This file implements private APIs for Hardware Desktop Support.
  7. Author:
  8. Therese Stowell (thereses) 12-13-1991
  9. Revision History:
  10. Notes:
  11. --*/
  12. #include "precomp.h"
  13. #include "vdm.h"
  14. #pragma hdrstop
  15. #if defined(FE_SB)
  16. BOOL fFullScreenGraphics ; // Do not trun graphics mode.
  17. #if defined(i386)
  18. extern ULONG gdwMachineId;
  19. #endif // i386
  20. #endif
  21. //
  22. // initial palette registers
  23. //
  24. #define PAL_BLACK 0
  25. #define PAL_BLUE 1
  26. #define PAL_GREEN 2
  27. #define PAL_RED 4
  28. #define PAL_YELLOW (PAL_RED | PAL_GREEN)
  29. #define PAL_CYAN (PAL_GREEN | PAL_BLUE)
  30. #define PAL_MAGENTA (PAL_BLUE | PAL_RED)
  31. #define PAL_WHITE (PAL_RED | PAL_GREEN | PAL_BLUE)
  32. #define PAL_I_BLACK (PAL_BLACK + (PAL_WHITE << 3))
  33. #define PAL_I_RED (PAL_RED + (PAL_RED << 3))
  34. #define PAL_I_GREEN (PAL_GREEN + (PAL_GREEN << 3))
  35. #define PAL_I_YELLOW (PAL_YELLOW + (PAL_YELLOW << 3))
  36. #define PAL_I_BLUE (PAL_BLUE + (PAL_BLUE << 3))
  37. #define PAL_I_CYAN (PAL_CYAN + (PAL_CYAN << 3))
  38. #define PAL_I_MAGENTA (PAL_MAGENTA + (PAL_MAGENTA << 3))
  39. #define PAL_I_WHITE (PAL_WHITE + (PAL_WHITE << 3))
  40. #define INITIAL_PALETTE_SIZE 18
  41. USHORT InitialPalette[INITIAL_PALETTE_SIZE] = {
  42. 16, // 16 entries
  43. 0, // start with first palette register
  44. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F
  45. };
  46. #if defined(FE_SB)
  47. PUSHORT RegInitialPalette = InitialPalette;
  48. #endif
  49. UCHAR ColorBuffer[] = {
  50. 16, // 16 entries
  51. 0,
  52. 0,
  53. 0, // start with first palette register
  54. 0x00, 0x00, 0x00, 0x00, // black
  55. 0x00, 0x00, 0x2A, 0x00, // blue
  56. 0x00, 0x2A, 0x00, 0x00, // green
  57. 0x00, 0x2A, 0x2A, 0x00, // cyan
  58. 0x2A, 0x00, 0x00, 0x00, // red
  59. 0x2A, 0x00, 0x2A, 0x00, // magenta
  60. 0x2A, 0x2A, 0x00, 0x00, // mustard/brown
  61. 0x36, 0x36, 0x36, 0x00, // light gray 39
  62. 0x28, 0x28, 0x28, 0x00, // dark gray 2A
  63. 0x00, 0x00, 0x3F, 0x00, // bright blue
  64. 0x00, 0x3F, 0x00, 0x00, // bright green
  65. 0x00, 0x3F, 0x3F, 0x00, // bright cyan
  66. 0x3F, 0x00, 0x00, 0x00, // bright red
  67. 0x3F, 0x00, 0x3F, 0x00, // bright magenta
  68. 0x3F, 0x3F, 0x00, 0x00, // bright yellow
  69. 0x3F, 0x3F, 0x3F, 0x00 // bright white
  70. };
  71. #if defined(FE_SB)
  72. PUCHAR RegColorBuffer = ColorBuffer;
  73. PUCHAR RegColorBufferNoTranslate = NULL;
  74. #endif
  75. #if defined(FE_SB)
  76. MODE_FONT_PAIR ModeFontPairs[] = {
  77. {FS_MODE_TEXT, 80, 21, 640, 350, 8, 16},
  78. {FS_MODE_TEXT, 80, 25, 720, 400, 8, 16},
  79. {FS_MODE_TEXT, 80, 28, 720, 400, 8, 14},
  80. {FS_MODE_TEXT, 80, 43, 640, 350, 8, 8 },
  81. {FS_MODE_TEXT, 80, 50, 720, 400, 8, 8 }
  82. };
  83. DWORD NUMBER_OF_MODE_FONT_PAIRS = sizeof(ModeFontPairs)/sizeof(MODE_FONT_PAIR);
  84. PMODE_FONT_PAIR RegModeFontPairs = ModeFontPairs;
  85. SINGLE_LIST_ENTRY gRegFullScreenCodePage; // This list contain FS_CODEPAGE data.
  86. #else
  87. typedef struct _MODE_FONT_PAIR {
  88. ULONG Height;
  89. COORD Resolution;
  90. COORD FontSize;
  91. } MODE_FONT_PAIR, PMODE_FONT_PAIR;
  92. #define NUMBER_OF_MODE_FONT_PAIRS 5
  93. MODE_FONT_PAIR ModeFontPairs[NUMBER_OF_MODE_FONT_PAIRS] = {
  94. {21, 640, 350, 8, 16},
  95. {25, 720, 400, 8, 16},
  96. {28, 720, 400, 8, 14},
  97. {43, 640, 350, 8, 8 },
  98. {50, 720, 400, 8, 8 }
  99. };
  100. #endif
  101. HANDLE hCPIFile; // handle to font file
  102. typedef struct _FONTFILEHEADER {
  103. BYTE ffhFileTag[8]; // SHOULD BE 0FFH,"FONT___"
  104. BYTE ffhReserved[8];
  105. WORD ffhPointers;
  106. BYTE ffhPointerType;
  107. BYTE ffhOffset1;
  108. WORD ffhOffset2;
  109. BYTE ffhOffset3;
  110. } FONTFILEHEADER, *LPFONTFILEHEADER;
  111. typedef struct _FONTINFOHEADER {
  112. WORD fihCodePages;
  113. } FONTINFOHEADER, *LPFONTINFOHEADER;
  114. typedef struct _CPENTRYHEADER {
  115. WORD cpeLength;
  116. WORD cpeNext1;
  117. WORD cpeNext2;
  118. WORD cpeDevType;
  119. BYTE cpeDevSubtype[8];
  120. WORD cpeCodepageID;
  121. BYTE cpeReserved[6];
  122. DWORD cpeOffset;
  123. } CPENTRYHEADER, *LPCPENTRYHEADER;
  124. typedef struct _FONTDATAHEADER {
  125. WORD fdhReserved;
  126. WORD fdhFonts;
  127. WORD fdhLength;
  128. } FONTDATAHEADER, *LPFONTDATAHEADER;
  129. typedef struct _SCREENFONTHEADER {
  130. BYTE sfhHeight;
  131. BYTE sfhWidth;
  132. WORD sfhAspect;
  133. WORD sfhCharacters;
  134. } SCREENFONTHEADER, *LPSCREENFONTHEADER;
  135. #define CONSOLE_WINDOWS_DIR_LENGTH 256
  136. #define CONSOLE_EGACPI_LENGTH 9 // includes NULL
  137. #define CONSOLE_EGACPI "\\ega.cpi"
  138. #define CONSOLE_FONT_BUFFER_LENGTH 50
  139. #define CONSOLE_DEFAULT_ROM_FONT 437
  140. #ifdef i386
  141. VOID
  142. ReverseMousePointer(
  143. IN PSCREEN_INFORMATION ScreenInfo,
  144. IN PSMALL_RECT Region
  145. );
  146. VOID
  147. ReadRectFromScreenBuffer(
  148. IN PSCREEN_INFORMATION ScreenInfo,
  149. IN COORD SourcePoint,
  150. IN PCHAR_INFO Target,
  151. IN COORD TargetSize,
  152. IN PSMALL_RECT TargetRect
  153. );
  154. #endif
  155. NTSTATUS
  156. MapViewOfSection(
  157. PHANDLE SectionHandle,
  158. ULONG CommitSize,
  159. PVOID *BaseAddress,
  160. PSIZE_T ViewSize,
  161. HANDLE ClientHandle,
  162. PVOID *BaseClientAddress
  163. );
  164. NTSTATUS
  165. ConnectToEmulator(
  166. IN BOOL Connect,
  167. IN PCONSOLE_INFORMATION Console
  168. );
  169. ULONG
  170. SrvSetConsoleCursor(
  171. IN OUT PCSR_API_MSG m,
  172. IN OUT PCSR_REPLY_STATUS ReplyStatus
  173. )
  174. /*++
  175. Description:
  176. Sets the mouse pointer for the specified screen buffer.
  177. Parameters:
  178. hConsoleOutput - Supplies a console output handle.
  179. hCursor - win32 cursor handle, should be NULL to set the default
  180. cursor.
  181. Return value:
  182. TRUE - The operation was successful.
  183. FALSE/NULL - The operation failed. Extended error status is available
  184. using GetLastError.
  185. --*/
  186. {
  187. PCONSOLE_SETCURSOR_MSG a = (PCONSOLE_SETCURSOR_MSG)&m->u.ApiMessageData;
  188. NTSTATUS Status;
  189. PCONSOLE_INFORMATION Console;
  190. PHANDLE_DATA HandleData;
  191. UNREFERENCED_PARAMETER(ReplyStatus);
  192. Status = ApiPreamble(a->ConsoleHandle,
  193. &Console
  194. );
  195. if (!NT_SUCCESS(Status)) {
  196. return Status;
  197. }
  198. Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
  199. a->OutputHandle,
  200. CONSOLE_GRAPHICS_OUTPUT_HANDLE,
  201. GENERIC_WRITE,
  202. &HandleData
  203. );
  204. if (NT_SUCCESS(Status)) {
  205. if (a->CursorHandle == NULL) {
  206. HandleData->Buffer.ScreenBuffer->CursorHandle = ghNormalCursor;
  207. } else {
  208. HandleData->Buffer.ScreenBuffer->CursorHandle = a->CursorHandle;
  209. }
  210. PostMessage(HandleData->Buffer.ScreenBuffer->Console->hWnd,
  211. WM_SETCURSOR,
  212. 0,
  213. -1
  214. );
  215. }
  216. UnlockConsole(Console);
  217. return Status;
  218. }
  219. #ifdef i386
  220. VOID
  221. FullScreenCursor(
  222. IN PSCREEN_INFORMATION ScreenInfo,
  223. IN BOOL On
  224. )
  225. {
  226. if (On) {
  227. if (ScreenInfo->CursorDisplayCount < 0) {
  228. ScreenInfo->CursorDisplayCount = 0;
  229. ReverseMousePointer(ScreenInfo, &ScreenInfo->Window);
  230. }
  231. } else {
  232. if (ScreenInfo->CursorDisplayCount >= 0) {
  233. ReverseMousePointer(ScreenInfo, &ScreenInfo->Window);
  234. ScreenInfo->CursorDisplayCount = -1;
  235. }
  236. }
  237. }
  238. #endif
  239. ULONG
  240. SrvShowConsoleCursor(
  241. IN OUT PCSR_API_MSG m,
  242. IN OUT PCSR_REPLY_STATUS ReplyStatus
  243. )
  244. /*++
  245. Description:
  246. Sets the mouse pointer visibility counter. If the counter is less than
  247. zero, the mouse pointer is not shown.
  248. Parameters:
  249. hOutput - Supplies a console output handle.
  250. bShow - if TRUE, the display count is to be increased. if FALSE,
  251. decreased.
  252. Return value:
  253. The return value specifies the new display count.
  254. --*/
  255. {
  256. PCONSOLE_SHOWCURSOR_MSG a = (PCONSOLE_SHOWCURSOR_MSG)&m->u.ApiMessageData;
  257. NTSTATUS Status;
  258. PCONSOLE_INFORMATION Console;
  259. PHANDLE_DATA HandleData;
  260. UNREFERENCED_PARAMETER(ReplyStatus);
  261. Status = ApiPreamble(a->ConsoleHandle,
  262. &Console
  263. );
  264. if (!NT_SUCCESS(Status)) {
  265. return Status;
  266. }
  267. Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
  268. a->OutputHandle,
  269. CONSOLE_OUTPUT_HANDLE | CONSOLE_GRAPHICS_OUTPUT_HANDLE,
  270. GENERIC_WRITE,
  271. &HandleData
  272. );
  273. if (NT_SUCCESS(Status)) {
  274. if (!(Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE)) {
  275. if (a->bShow) {
  276. HandleData->Buffer.ScreenBuffer->CursorDisplayCount += 1;
  277. } else {
  278. HandleData->Buffer.ScreenBuffer->CursorDisplayCount -= 1;
  279. }
  280. if (HandleData->Buffer.ScreenBuffer == Console->CurrentScreenBuffer) {
  281. PostMessage(HandleData->Buffer.ScreenBuffer->Console->hWnd,
  282. WM_SETCURSOR,
  283. 0,
  284. -1
  285. );
  286. }
  287. } else {
  288. #ifdef i386
  289. if (HandleData->HandleType != CONSOLE_GRAPHICS_OUTPUT_HANDLE &&
  290. Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE &&
  291. HandleData->Buffer.ScreenBuffer == Console->CurrentScreenBuffer) {
  292. FullScreenCursor(HandleData->Buffer.ScreenBuffer, a->bShow);
  293. }
  294. #endif
  295. }
  296. a->DisplayCount = HandleData->Buffer.ScreenBuffer->CursorDisplayCount;
  297. }
  298. UnlockConsole(Console);
  299. return Status;
  300. }
  301. ULONG
  302. SrvConsoleMenuControl(
  303. IN OUT PCSR_API_MSG m,
  304. IN OUT PCSR_REPLY_STATUS ReplyStatus
  305. )
  306. /*++
  307. Description:
  308. Sets the command id range for the current screen buffer and returns the
  309. menu handle.
  310. Parameters:
  311. hConsoleOutput - Supplies a console output handle.
  312. dwCommandIdLow - Specifies the lowest command id to store in the input buffer.
  313. dwCommandIdHigh - Specifies the highest command id to store in the input
  314. buffer.
  315. Return value:
  316. TRUE - The operation was successful.
  317. FALSE/NULL - The operation failed. Extended error status is available
  318. using GetLastError.
  319. --*/
  320. {
  321. PCONSOLE_MENUCONTROL_MSG a = (PCONSOLE_MENUCONTROL_MSG)&m->u.ApiMessageData;
  322. NTSTATUS Status;
  323. PCONSOLE_INFORMATION Console;
  324. PHANDLE_DATA HandleData;
  325. UNREFERENCED_PARAMETER(ReplyStatus);
  326. Status = ApiPreamble(a->ConsoleHandle,
  327. &Console
  328. );
  329. if (!NT_SUCCESS(Status)) {
  330. return Status;
  331. }
  332. Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
  333. a->OutputHandle,
  334. CONSOLE_OUTPUT_HANDLE | CONSOLE_GRAPHICS_OUTPUT_HANDLE,
  335. GENERIC_WRITE,
  336. &HandleData
  337. );
  338. if (NT_SUCCESS(Status)) {
  339. a->hMenu = HandleData->Buffer.ScreenBuffer->Console->hMenu;
  340. HandleData->Buffer.ScreenBuffer->CommandIdLow = a->CommandIdLow;
  341. HandleData->Buffer.ScreenBuffer->CommandIdHigh = a->CommandIdHigh;
  342. }
  343. UnlockConsole(Console);
  344. return Status;
  345. }
  346. ULONG
  347. SrvSetConsolePalette(
  348. IN OUT PCSR_API_MSG m,
  349. IN OUT PCSR_REPLY_STATUS ReplyStatus
  350. )
  351. /*++
  352. Description:
  353. Sets the palette for the console screen buffer.
  354. Parameters:
  355. hOutput - Supplies a console output handle.
  356. hPalette - Supplies a handle to the palette to set.
  357. dwUsage - Specifies use of the system palette.
  358. SYSPAL_NOSTATIC - System palette contains no static colors
  359. except black and white.
  360. SYSPAL_STATIC - System palette contains static colors
  361. which will not change when an application
  362. realizes its logical palette.
  363. Return value:
  364. TRUE - The operation was successful.
  365. FALSE/NULL - The operation failed. Extended error status is available
  366. using GetLastError.
  367. --*/
  368. {
  369. PCONSOLE_SETPALETTE_MSG a = (PCONSOLE_SETPALETTE_MSG)&m->u.ApiMessageData;
  370. NTSTATUS Status;
  371. PCONSOLE_INFORMATION Console;
  372. PHANDLE_DATA HandleData;
  373. HPALETTE hOldPalette;
  374. UNREFERENCED_PARAMETER(ReplyStatus);
  375. Status = ApiPreamble(a->ConsoleHandle,
  376. &Console
  377. );
  378. if (!NT_SUCCESS(Status)) {
  379. return Status;
  380. }
  381. Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
  382. a->OutputHandle,
  383. CONSOLE_GRAPHICS_OUTPUT_HANDLE,
  384. GENERIC_WRITE,
  385. &HandleData
  386. );
  387. if (NT_SUCCESS(Status)) {
  388. USERTHREAD_USEDESKTOPINFO utudi;
  389. BOOL bReset = FALSE;
  390. /*
  391. * Palette handle was converted in the client.
  392. */
  393. if (GetCurrentThreadId() != HandleData->Buffer.ScreenBuffer->
  394. Console->InputThreadInfo->ThreadId) {
  395. bReset = TRUE;
  396. utudi.hThread = HandleData->Buffer.ScreenBuffer->Console->InputThreadInfo->ThreadHandle;
  397. utudi.drdRestore.pdeskRestore = NULL;
  398. NtUserSetInformationThread(NtCurrentThread(),
  399. UserThreadUseDesktop,
  400. &utudi, sizeof(utudi));
  401. }
  402. NtUserConsoleControl(ConsolePublicPalette, &(a->hPalette), sizeof(HPALETTE));
  403. hOldPalette = SelectPalette(
  404. HandleData->Buffer.ScreenBuffer->Console->hDC,
  405. a->hPalette,
  406. FALSE);
  407. if (hOldPalette == NULL) {
  408. Status = STATUS_INVALID_PARAMETER;
  409. } else {
  410. if ((HandleData->Buffer.ScreenBuffer->hPalette != NULL) &&
  411. (a->hPalette != HandleData->Buffer.ScreenBuffer->hPalette)) {
  412. DeleteObject(HandleData->Buffer.ScreenBuffer->hPalette);
  413. }
  414. HandleData->Buffer.ScreenBuffer->hPalette = a->hPalette;
  415. HandleData->Buffer.ScreenBuffer->dwUsage = a->dwUsage;
  416. if (!(HandleData->Buffer.ScreenBuffer->Console->Flags & CONSOLE_IS_ICONIC) &&
  417. HandleData->Buffer.ScreenBuffer->Console->FullScreenFlags == 0) {
  418. SetSystemPaletteUse(HandleData->Buffer.ScreenBuffer->Console->hDC,
  419. HandleData->Buffer.ScreenBuffer->dwUsage);
  420. RealizePalette(HandleData->Buffer.ScreenBuffer->Console->hDC);
  421. }
  422. if (HandleData->Buffer.ScreenBuffer->Console->hSysPalette == NULL) {
  423. HandleData->Buffer.ScreenBuffer->Console->hSysPalette = hOldPalette;
  424. }
  425. }
  426. if (bReset) {
  427. utudi.hThread = NULL;
  428. NtUserSetInformationThread(NtCurrentThread(),
  429. UserThreadUseDesktop, &utudi, sizeof(utudi));
  430. }
  431. }
  432. UnlockConsole(Console);
  433. return Status;
  434. }
  435. VOID
  436. SetActivePalette(
  437. IN PSCREEN_INFORMATION ScreenInfo
  438. )
  439. {
  440. USERTHREAD_USEDESKTOPINFO utudi;
  441. BOOL bReset = FALSE;
  442. if (GetCurrentThreadId() != ScreenInfo->Console->InputThreadInfo->ThreadId) {
  443. bReset = TRUE;
  444. utudi.hThread = ScreenInfo->Console->InputThreadInfo->ThreadHandle;
  445. utudi.drdRestore.pdeskRestore = NULL;
  446. NtUserSetInformationThread(NtCurrentThread(),
  447. UserThreadUseDesktop,
  448. &utudi, sizeof(utudi));
  449. }
  450. SetSystemPaletteUse(ScreenInfo->Console->hDC,
  451. ScreenInfo->dwUsage
  452. );
  453. RealizePalette(ScreenInfo->Console->hDC);
  454. if (bReset == TRUE) {
  455. utudi.hThread = NULL;
  456. NtUserSetInformationThread(NtCurrentThread(),
  457. UserThreadUseDesktop, &utudi, sizeof(utudi));
  458. }
  459. }
  460. VOID
  461. UnsetActivePalette(
  462. IN PSCREEN_INFORMATION ScreenInfo
  463. )
  464. {
  465. USERTHREAD_USEDESKTOPINFO utudi;
  466. BOOL bReset = FALSE;
  467. if (GetCurrentThreadId() != ScreenInfo->Console->InputThreadInfo->ThreadId) {
  468. bReset = TRUE;
  469. utudi.hThread = ScreenInfo->Console->InputThreadInfo->ThreadHandle;
  470. utudi.drdRestore.pdeskRestore = NULL;
  471. NtUserSetInformationThread(NtCurrentThread(),
  472. UserThreadUseDesktop,
  473. &utudi, sizeof(utudi));
  474. }
  475. SetSystemPaletteUse(ScreenInfo->Console->hDC,
  476. SYSPAL_STATIC
  477. );
  478. RealizePalette(ScreenInfo->Console->hDC);
  479. if (bReset == TRUE) {
  480. utudi.hThread = NULL;
  481. NtUserSetInformationThread(NtCurrentThread(),
  482. UserThreadUseDesktop, &utudi, sizeof(utudi));
  483. }
  484. }
  485. NTSTATUS
  486. ConvertToFullScreen(
  487. IN PCONSOLE_INFORMATION Console
  488. )
  489. {
  490. #ifdef i386
  491. PSCREEN_INFORMATION Cur;
  492. COORD WindowedWindowSize, WindowSize;
  493. // for each charmode screenbuffer
  494. // match window size to a mode/font
  495. // grow screen buffer if necessary
  496. // save old window dimensions
  497. // set new window dimensions
  498. for (Cur=Console->ScreenBuffers;Cur!=NULL;Cur=Cur->Next) {
  499. if (Cur->Flags & CONSOLE_GRAPHICS_BUFFER) {
  500. continue;
  501. }
  502. // save old window dimensions
  503. WindowedWindowSize.X = CONSOLE_WINDOW_SIZE_X(Cur);
  504. WindowedWindowSize.Y = CONSOLE_WINDOW_SIZE_Y(Cur);
  505. Cur->BufferInfo.TextInfo.WindowedWindowSize = WindowedWindowSize;
  506. Cur->BufferInfo.TextInfo.WindowedScreenSize = Cur->ScreenBufferSize;
  507. // match window size to a mode/font
  508. Cur->BufferInfo.TextInfo.ModeIndex = MatchWindowSize(
  509. Console->OutputCP,
  510. Cur->ScreenBufferSize, &WindowSize);
  511. // grow screen buffer if necessary
  512. if (WindowSize.X > Cur->ScreenBufferSize.X ||
  513. WindowSize.Y > Cur->ScreenBufferSize.Y) {
  514. COORD NewScreenSize;
  515. NewScreenSize.X = max(WindowSize.X, Cur->ScreenBufferSize.X);
  516. NewScreenSize.Y = max(WindowSize.Y, Cur->ScreenBufferSize.Y);
  517. if (ResizeScreenBuffer(Cur, NewScreenSize, FALSE) == STATUS_INVALID_HANDLE) {
  518. return STATUS_INVALID_HANDLE;
  519. }
  520. }
  521. //
  522. // Set new window dimensions.
  523. // We always resize horizontally from the right (change the
  524. // right edge).
  525. // We resize vertically from the bottom, keeping the cursor visible.
  526. //
  527. if (WindowedWindowSize.X != WindowSize.X) {
  528. Cur->Window.Right -= WindowedWindowSize.X - WindowSize.X;
  529. if (Cur->Window.Right >= Cur->ScreenBufferSize.X) {
  530. Cur->Window.Left -= Cur->Window.Right - Cur->ScreenBufferSize.X + 1;
  531. Cur->Window.Right -= Cur->Window.Right - Cur->ScreenBufferSize.X + 1;
  532. }
  533. }
  534. if (WindowedWindowSize.Y > WindowSize.Y) {
  535. Cur->Window.Bottom -= WindowedWindowSize.Y - WindowSize.Y;
  536. if (Cur->Window.Bottom >= Cur->ScreenBufferSize.Y) {
  537. Cur->Window.Top -= Cur->Window.Bottom - Cur->ScreenBufferSize.Y + 1;
  538. Cur->Window.Bottom = Cur->ScreenBufferSize.Y - 1;
  539. }
  540. } else if (WindowedWindowSize.Y < WindowSize.Y) {
  541. Cur->Window.Top -= WindowSize.Y - WindowedWindowSize.Y;
  542. if (Cur->Window.Top < 0) {
  543. Cur->Window.Bottom -= Cur->Window.Top;
  544. Cur->Window.Top = 0;
  545. }
  546. }
  547. if (Cur->BufferInfo.TextInfo.CursorPosition.Y > Cur->Window.Bottom) {
  548. Cur->Window.Top += Cur->BufferInfo.TextInfo.CursorPosition.Y - Cur->Window.Bottom;
  549. Cur->Window.Bottom = Cur->BufferInfo.TextInfo.CursorPosition.Y;
  550. }
  551. UserAssert(WindowSize.X == CONSOLE_WINDOW_SIZE_X(Cur));
  552. UserAssert(WindowSize.Y == CONSOLE_WINDOW_SIZE_Y(Cur));
  553. Cur->BufferInfo.TextInfo.MousePosition.X = Cur->Window.Left;
  554. Cur->BufferInfo.TextInfo.MousePosition.Y = Cur->Window.Top;
  555. if (Cur->Flags & CONSOLE_OEMFONT_DISPLAY) {
  556. DBGCHARS(("ConvertToFullScreen converts UnicodeOem -> Unicode\n"));
  557. FalseUnicodeToRealUnicode(
  558. Cur->BufferInfo.TextInfo.TextRows,
  559. Cur->ScreenBufferSize.X * Cur->ScreenBufferSize.Y,
  560. Console->OutputCP);
  561. } else {
  562. DBGCHARS(("ConvertToFullScreen needs no conversion\n"));
  563. }
  564. DBGCHARS(("Cur->BufferInfo.TextInfo.Rows = %lx\n",
  565. Cur->BufferInfo.TextInfo.Rows));
  566. DBGCHARS(("Cur->BufferInfo.TextInfo.TextRows = %lx\n",
  567. Cur->BufferInfo.TextInfo.TextRows));
  568. }
  569. Cur = Console->CurrentScreenBuffer;
  570. if (Cur->Flags & CONSOLE_TEXTMODE_BUFFER) {
  571. if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) {
  572. PCONVERSIONAREA_INFORMATION ConvAreaInfo;
  573. ConvAreaInfo = Console->ConsoleIme.ConvAreaRoot;
  574. while (ConvAreaInfo) {
  575. NTSTATUS Status;
  576. Status = StoreTextBufferFontInfo(ConvAreaInfo->ScreenBuffer,
  577. SCR_FONTNUMBER(Cur),
  578. SCR_FONTSIZE(Cur),
  579. SCR_FAMILY(Cur),
  580. SCR_FONTWEIGHT(Cur),
  581. SCR_FACENAME(Cur),
  582. SCR_FONTCODEPAGE(Cur));
  583. if (!NT_SUCCESS(Status)) {
  584. return((ULONG) Status);
  585. }
  586. ConvAreaInfo->ScreenBuffer->BufferInfo.TextInfo.ModeIndex = Cur->BufferInfo.TextInfo.ModeIndex;
  587. ConvAreaInfo = ConvAreaInfo->ConvAreaNext;
  588. }
  589. }
  590. Cur->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT;
  591. }
  592. SetWindowSize(Cur);
  593. WriteToScreen(Cur, &Console->CurrentScreenBuffer->Window);
  594. #else
  595. UNREFERENCED_PARAMETER(Console);
  596. #endif
  597. return STATUS_SUCCESS;
  598. }
  599. NTSTATUS
  600. ConvertToWindowed(
  601. IN PCONSOLE_INFORMATION Console
  602. )
  603. {
  604. #ifdef i386
  605. PSCREEN_INFORMATION Cur;
  606. SMALL_RECT WindowedWindow;
  607. // for each charmode screenbuffer
  608. // restore window dimensions
  609. for (Cur=Console->ScreenBuffers;Cur!=NULL;Cur=Cur->Next) {
  610. if ((Cur->Flags & CONSOLE_TEXTMODE_BUFFER) == 0) {
  611. continue;
  612. }
  613. if (ResizeScreenBuffer(Cur,
  614. Cur->BufferInfo.TextInfo.WindowedScreenSize,
  615. FALSE) == STATUS_INVALID_HANDLE) {
  616. /*
  617. * Something really went wrong. All we can do is just to
  618. * bail out.
  619. */
  620. return STATUS_INVALID_HANDLE;
  621. }
  622. WindowedWindow.Right = Cur->Window.Right;
  623. WindowedWindow.Bottom = Cur->Window.Bottom;
  624. WindowedWindow.Left = Cur->Window.Right + 1 -
  625. Cur->BufferInfo.TextInfo.WindowedWindowSize.X;
  626. WindowedWindow.Top = Cur->Window.Bottom + 1 -
  627. Cur->BufferInfo.TextInfo.WindowedWindowSize.Y;
  628. if (WindowedWindow.Left > Cur->Window.Left) {
  629. WindowedWindow.Right -= WindowedWindow.Left - Cur->Window.Left;
  630. WindowedWindow.Left = Cur->Window.Left;
  631. }
  632. if (WindowedWindow.Right < Cur->BufferInfo.TextInfo.CursorPosition.X) {
  633. WindowedWindow.Left += Cur->BufferInfo.TextInfo.CursorPosition.X - WindowedWindow.Right;
  634. WindowedWindow.Right = Cur->BufferInfo.TextInfo.CursorPosition.X;
  635. }
  636. if (WindowedWindow.Top > Cur->Window.Top) {
  637. WindowedWindow.Bottom -= WindowedWindow.Top - Cur->Window.Top;
  638. WindowedWindow.Top = Cur->Window.Top;
  639. }
  640. if (WindowedWindow.Bottom < Cur->BufferInfo.TextInfo.CursorPosition.Y) {
  641. WindowedWindow.Top += Cur->BufferInfo.TextInfo.CursorPosition.Y - WindowedWindow.Bottom;
  642. WindowedWindow.Bottom = Cur->BufferInfo.TextInfo.CursorPosition.Y;
  643. }
  644. ResizeWindow(Cur, &WindowedWindow, FALSE);
  645. if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) {
  646. SetFont(Cur);
  647. }
  648. if (Cur->Flags & CONSOLE_OEMFONT_DISPLAY) {
  649. DBGCHARS(("ConvertToWindowed converts Unicode -> UnicodeOem\n"));
  650. RealUnicodeToFalseUnicode(
  651. Cur->BufferInfo.TextInfo.TextRows,
  652. Cur->ScreenBufferSize.X * Cur->ScreenBufferSize.Y,
  653. Console->OutputCP);
  654. } else {
  655. DBGCHARS(("ConvertToWindowed needs no conversion\n"));
  656. }
  657. DBGCHARS(("Cur->BufferInfo.TextInfo.Rows = %lx\n",
  658. Cur->BufferInfo.TextInfo.Rows));
  659. DBGCHARS(("Cur->BufferInfo.TextInfo.TextRows = %lx\n",
  660. Cur->BufferInfo.TextInfo.TextRows));
  661. }
  662. Cur = Console->CurrentScreenBuffer;
  663. if (Cur->Flags & CONSOLE_TEXTMODE_BUFFER) {
  664. if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) {
  665. PCONVERSIONAREA_INFORMATION ConvAreaInfo;
  666. ConvAreaInfo = Console->ConsoleIme.ConvAreaRoot;
  667. while (ConvAreaInfo) {
  668. NTSTATUS Status;
  669. Status = StoreTextBufferFontInfo(ConvAreaInfo->ScreenBuffer,
  670. SCR_FONTNUMBER(Cur),
  671. SCR_FONTSIZE(Cur),
  672. SCR_FAMILY(Cur),
  673. SCR_FONTWEIGHT(Cur),
  674. SCR_FACENAME(Cur),
  675. SCR_FONTCODEPAGE(Cur));
  676. if (!NT_SUCCESS(Status)) {
  677. return((ULONG) Status);
  678. }
  679. ConvAreaInfo->ScreenBuffer->BufferInfo.TextInfo.ModeIndex = Cur->BufferInfo.TextInfo.ModeIndex;
  680. ConvAreaInfo = ConvAreaInfo->ConvAreaNext;
  681. }
  682. }
  683. Cur->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT;
  684. }
  685. SetWindowSize(Cur);
  686. WriteToScreen(Cur, &Console->CurrentScreenBuffer->Window);
  687. #else
  688. UNREFERENCED_PARAMETER(Console);
  689. #endif
  690. return STATUS_SUCCESS;
  691. }
  692. ULONG
  693. SrvSetConsoleDisplayMode(
  694. IN OUT PCSR_API_MSG m,
  695. IN OUT PCSR_REPLY_STATUS ReplyStatus
  696. )
  697. /*++
  698. Description:
  699. This routine sets the console display mode for an output buffer.
  700. This API is only supported on x86 machines.
  701. Parameters:
  702. hConsoleOutput - Supplies a console output handle.
  703. dwFlags - Specifies the display mode. Options are:
  704. CONSOLE_FULLSCREEN_MODE - data is displayed fullscreen
  705. CONSOLE_WINDOWED_MODE - data is displayed in a window
  706. lpNewScreenBufferDimensions - On output, contains the new dimensions of
  707. the screen buffer. The dimensions are in rows and columns for
  708. textmode screen buffers.
  709. Return value:
  710. TRUE - The operation was successful.
  711. FALSE/NULL - The operation failed. Extended error status is available
  712. using GetLastError.
  713. --*/
  714. {
  715. PCONSOLE_SETDISPLAYMODE_MSG a = (PCONSOLE_SETDISPLAYMODE_MSG)&m->u.ApiMessageData;
  716. NTSTATUS Status;
  717. PCONSOLE_INFORMATION Console;
  718. PHANDLE_DATA HandleData;
  719. PSCREEN_INFORMATION ScreenInfo;
  720. UINT State;
  721. HANDLE hEvent = NULL;
  722. UNREFERENCED_PARAMETER(ReplyStatus);
  723. Status = ApiPreamble(a->ConsoleHandle,
  724. &Console
  725. );
  726. if (!NT_SUCCESS(Status)) {
  727. return Status;
  728. }
  729. Status = NtDuplicateObject(CONSOLE_CLIENTPROCESSHANDLE(),
  730. a->hEvent,
  731. NtCurrentProcess(),
  732. &hEvent,
  733. 0,
  734. FALSE,
  735. DUPLICATE_SAME_ACCESS
  736. );
  737. if (!NT_SUCCESS(Status)) {
  738. goto SrvSetConsoleDisplayModeFailure;
  739. }
  740. Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
  741. a->OutputHandle,
  742. CONSOLE_OUTPUT_HANDLE | CONSOLE_GRAPHICS_OUTPUT_HANDLE,
  743. GENERIC_WRITE,
  744. &HandleData
  745. );
  746. if (NT_SUCCESS(Status)) {
  747. ScreenInfo = HandleData->Buffer.ScreenBuffer;
  748. if (!ACTIVE_SCREEN_BUFFER(ScreenInfo)) {
  749. Status = STATUS_INVALID_PARAMETER;
  750. goto SrvSetConsoleDisplayModeFailure;
  751. }
  752. if (a->dwFlags == CONSOLE_FULLSCREEN_MODE) {
  753. #if !defined(_X86_)
  754. if (ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER) {
  755. Status = STATUS_INVALID_PARAMETER;
  756. goto SrvSetConsoleDisplayModeFailure;
  757. }
  758. #else
  759. if (!FullScreenInitialized || GetSystemMetrics(SM_REMOTESESSION)) {
  760. Status = STATUS_INVALID_PARAMETER;
  761. goto SrvSetConsoleDisplayModeFailure;
  762. }
  763. #endif
  764. if (Console->FullScreenFlags & CONSOLE_FULLSCREEN) {
  765. KdPrint(("CONSRV: VDM converting to fullscreen twice\n"));
  766. Status = STATUS_SUCCESS;
  767. goto SrvSetConsoleDisplayModeFailure;
  768. }
  769. State = FULLSCREEN;
  770. } else {
  771. if (Console->FullScreenFlags == 0) {
  772. KdPrint(("CONSRV: VDM converting to windowed twice\n"));
  773. Status = STATUS_SUCCESS;
  774. goto SrvSetConsoleDisplayModeFailure;
  775. }
  776. State = WINDOWED;
  777. }
  778. Status = QueueConsoleMessage(Console,
  779. CM_MODE_TRANSITION,
  780. State,
  781. (LPARAM)hEvent
  782. );
  783. if (!NT_SUCCESS(Status)) {
  784. goto SrvSetConsoleDisplayModeFailure;
  785. }
  786. }
  787. UnlockConsole(Console);
  788. return Status;
  789. SrvSetConsoleDisplayModeFailure:
  790. if (hEvent) {
  791. NtSetEvent(hEvent, NULL);
  792. NtClose(hEvent);
  793. }
  794. UnlockConsole(Console);
  795. return Status;
  796. }
  797. VOID
  798. UnregisterVDM(
  799. IN PCONSOLE_INFORMATION Console
  800. )
  801. {
  802. // williamh, Feb 2 1994.
  803. // catch multiple calls to unregister vdm. Believe it or not, this could
  804. // happen
  805. //UserAssert(Console->Flags & CONSOLE_VDM_REGISTERED);
  806. if (!(Console->Flags & CONSOLE_VDM_REGISTERED))
  807. return;
  808. #if defined(FE_SB) && defined(i386)
  809. // When HDOS apps exit, console screen resolution is changed to 640*400. Because HBIOS set
  810. // Screen resolution to 640*400. So, we should replace current screen resoultion(640*480).
  811. // 09/11/96 bklee
  812. {
  813. if ((Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) &&
  814. ( Console->OutputCP == KOREAN_CP ||
  815. (Console->OutputCP == JAPAN_CP && ISNECPC98(gdwMachineId) ) )) {
  816. ULONG Index;
  817. DEVMODEW Devmode;
  818. BOOL fGraphics = fFullScreenGraphics ? IsAvailableFsCodePage(Console->OutputCP) : FALSE;
  819. Index = Console->CurrentScreenBuffer->BufferInfo.TextInfo.ModeIndex;
  820. ZeroMemory(&Devmode, sizeof(Devmode));
  821. Devmode.dmSize = sizeof(Devmode);
  822. Devmode.dmDriverExtra = 0;
  823. Devmode.dmFields = DM_BITSPERPEL |
  824. DM_PELSWIDTH |
  825. DM_PELSHEIGHT |
  826. DM_DISPLAYFLAGS;
  827. Devmode.dmBitsPerPel = 4;
  828. Devmode.dmPelsWidth = RegModeFontPairs[Index].Resolution.X;
  829. Devmode.dmPelsHeight = RegModeFontPairs[Index].Resolution.Y;
  830. Devmode.dmDisplayFlags = (fGraphics && (RegModeFontPairs[Index].Mode & FS_MODE_GRAPHICS)) ? 0 : DMDISPLAYFLAGS_TEXTMODE;
  831. GdiFullscreenControl(FullscreenControlSetMode,
  832. &Devmode,
  833. sizeof(Devmode),
  834. NULL,
  835. NULL);
  836. }
  837. }
  838. #endif
  839. #ifdef i386
  840. if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE &&
  841. Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR) {
  842. NtUserConsoleControl(ConsoleSetVDMCursorBounds, NULL, 0);
  843. // connect emulator
  844. ConnectToEmulator(FALSE, Console);
  845. }
  846. if (FullScreenInitialized) {
  847. CloseHandle(Console->VDMStartHardwareEvent);
  848. CloseHandle(Console->VDMEndHardwareEvent);
  849. if (Console->VDMErrorHardwareEvent) {
  850. CloseHandle(Console->VDMErrorHardwareEvent);
  851. Console->VDMErrorHardwareEvent = NULL;
  852. }
  853. NtUnmapViewOfSection(NtCurrentProcess(), Console->StateBuffer);
  854. NtUnmapViewOfSection(Console->VDMProcessHandle, Console->StateBufferClient);
  855. NtClose(Console->StateSectionHandle);
  856. Console->StateLength = 0;
  857. }
  858. #endif
  859. Console->Flags &= ~CONSOLE_VDM_REGISTERED;
  860. if (Console->Flags & CONSOLE_HAS_FOCUS) {
  861. USERTHREAD_FLAGS Flags;
  862. Flags.dwFlags = 0;
  863. Flags.dwMask = (TIF_VDMAPP | TIF_DOSEMULATOR);
  864. NtUserSetInformationThread(Console->InputThreadInfo->ThreadHandle,
  865. UserThreadFlags, &Flags, sizeof(Flags));
  866. }
  867. Console->Flags &= ~CONSOLE_WOW_REGISTERED;
  868. UserAssert(Console->VDMBuffer != NULL);
  869. if (Console->VDMBuffer != NULL) {
  870. NtUnmapViewOfSection(Console->VDMProcessHandle, Console->VDMBufferClient);
  871. NtUnmapViewOfSection(NtCurrentProcess(), Console->VDMBuffer);
  872. NtClose(Console->VDMBufferSectionHandle);
  873. Console->VDMBuffer = NULL;
  874. }
  875. #ifdef i386
  876. if (Console->CurrentScreenBuffer &&
  877. Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) {
  878. Console->CurrentScreenBuffer->BufferInfo.TextInfo.MousePosition.X = 0;
  879. Console->CurrentScreenBuffer->BufferInfo.TextInfo.MousePosition.Y = 0;
  880. }
  881. #endif
  882. UserAssert(Console->VDMProcessHandle);
  883. CloseHandle(Console->VDMProcessHandle);
  884. Console->VDMProcessHandle = NULL;
  885. #if defined(FE_SB) && defined(FE_IME) && defined(i386)
  886. {
  887. if (Console->FullScreenFlags & CONSOLE_FULLSCREEN) {
  888. Console->Flags |= CONSOLE_JUST_VDM_UNREGISTERED ;
  889. }
  890. else if (Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) {
  891. AdjustCursorPosition(Console->CurrentScreenBuffer,
  892. Console->CurrentScreenBuffer->BufferInfo.TextInfo.CursorPosition,
  893. TRUE,
  894. NULL);
  895. }
  896. }
  897. #endif
  898. }
  899. ULONG
  900. SrvRegisterConsoleVDM(
  901. IN OUT PCSR_API_MSG m,
  902. IN OUT PCSR_REPLY_STATUS ReplyStatus
  903. )
  904. {
  905. PCONSOLE_REGISTERVDM_MSG a = (PCONSOLE_REGISTERVDM_MSG)&m->u.ApiMessageData;
  906. NTSTATUS Status;
  907. PCONSOLE_INFORMATION Console;
  908. SIZE_T ViewSize;
  909. VDM_QUERY_VDM_PROCESS_DATA QueryVdmProcessData;
  910. #ifdef i386
  911. VIDEO_REGISTER_VDM RegisterVdm;
  912. ULONG RegisterVdmSize = sizeof(RegisterVdm);
  913. VIDEO_VDM Vdm;
  914. #endif //i386
  915. Status = ApiPreamble(a->ConsoleHandle,
  916. &Console
  917. );
  918. if (!NT_SUCCESS(Status)) {
  919. return Status;
  920. }
  921. //
  922. // First make sure the caller is a VDM process
  923. //
  924. QueryVdmProcessData.ProcessHandle = CONSOLE_CLIENTPROCESSHANDLE();
  925. Status = NtVdmControl(VdmQueryVdmProcess, &QueryVdmProcessData);
  926. if (!NT_SUCCESS(Status) || QueryVdmProcessData.IsVdmProcess == FALSE) {
  927. UnlockConsole(Console);
  928. return STATUS_ACCESS_DENIED;
  929. }
  930. if (a->RegisterFlags & CONSOLE_REGISTER_VDM) {
  931. ConsoleNotifyWinEvent(Console,
  932. EVENT_CONSOLE_START_APPLICATION,
  933. HandleToUlong(CONSOLE_CLIENTPROCESSID()),
  934. CONSOLE_APPLICATION_16BIT);
  935. } else if (a->RegisterFlags == 0) {
  936. ConsoleNotifyWinEvent(Console,
  937. EVENT_CONSOLE_END_APPLICATION,
  938. HandleToUlong(CONSOLE_CLIENTPROCESSID()),
  939. CONSOLE_APPLICATION_16BIT);
  940. }
  941. if (!a->RegisterFlags) {
  942. // williamh, Jan 28 1994
  943. // do not do an assert here because we may have unregistered the ntvdm
  944. // and the ntvdm doesn't necessarily know this(and it could post another
  945. // unregistervdm). Return error here so NTVDM knows what to do
  946. // UserAssert(Console->Flags & CONSOLE_VDM_REGISTERED);
  947. if (Console->Flags & CONSOLE_VDM_REGISTERED) {
  948. UserAssert(!(Console->Flags & CONSOLE_FULLSCREEN_NOPAINT));
  949. UnregisterVDM(Console);
  950. #ifdef i386
  951. if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE &&
  952. Console->CurrentScreenBuffer->Flags & CONSOLE_TEXTMODE_BUFFER) {
  953. // SetVideoMode(Console->CurrentScreenBuffer);
  954. // Set up cursor
  955. SetCursorInformationHW(Console->CurrentScreenBuffer,
  956. Console->CurrentScreenBuffer->BufferInfo.TextInfo.CursorSize,
  957. Console->CurrentScreenBuffer->BufferInfo.TextInfo.CursorVisible);
  958. SetCursorPositionHW(Console->CurrentScreenBuffer,
  959. Console->CurrentScreenBuffer->BufferInfo.TextInfo.CursorPosition);
  960. }
  961. #endif // i386
  962. Status = STATUS_SUCCESS;
  963. } else {
  964. Status = STATUS_ACCESS_DENIED;
  965. }
  966. UnlockConsole(Console);
  967. return Status;
  968. }
  969. if (!CsrValidateMessageBuffer(m, &a->VDMBufferSectionName, a->VDMBufferSectionNameLength, sizeof(BYTE))) {
  970. UnlockConsole(Console);
  971. return STATUS_INVALID_PARAMETER;
  972. }
  973. // check it out. A console should have only one VDM registered.
  974. UserAssert(!(Console->Flags & CONSOLE_VDM_REGISTERED));
  975. if (Console->Flags & CONSOLE_VDM_REGISTERED) {
  976. UnlockConsole(Console);
  977. return (ULONG) STATUS_ACCESS_DENIED;
  978. }
  979. UserAssert(!Console->VDMProcessHandle);
  980. Status = NtDuplicateObject(NtCurrentProcess(), CONSOLE_CLIENTPROCESSHANDLE(),
  981. NtCurrentProcess(), &Console->VDMProcessHandle,
  982. 0, FALSE, DUPLICATE_SAME_ACCESS);
  983. if (!NT_SUCCESS(Status)) {
  984. UnlockConsole(Console);
  985. return Status;
  986. }
  987. Console->VDMProcessId = CONSOLE_CLIENTPROCESSID();
  988. #ifdef i386
  989. Vdm.ProcessHandle = Console->VDMProcessHandle;
  990. //
  991. // Assume fullscreen initialization will fail.
  992. // have state length set to zero so that NTVDM will know
  993. // full screen is disabled.
  994. //
  995. a->StateLength = 0;
  996. Console->StateLength = 0;
  997. Console->StateBufferClient = NULL;
  998. Console->VDMErrorHardwareEvent = NULL;
  999. if (FullScreenInitialized) {
  1000. Status = NtDuplicateObject(CONSOLE_CLIENTPROCESSHANDLE(),
  1001. a->StartEvent,
  1002. NtCurrentProcess(),
  1003. &Console->VDMStartHardwareEvent,
  1004. 0,
  1005. FALSE,
  1006. DUPLICATE_SAME_ACCESS
  1007. );
  1008. if (NT_SUCCESS(Status)) {
  1009. Status = NtDuplicateObject(CONSOLE_CLIENTPROCESSHANDLE(),
  1010. a->EndEvent,
  1011. NtCurrentProcess(),
  1012. &Console->VDMEndHardwareEvent,
  1013. 0,
  1014. FALSE,
  1015. DUPLICATE_SAME_ACCESS
  1016. );
  1017. if (NT_SUCCESS(Status)) {
  1018. if (a->ErrorEvent) {
  1019. Status = NtDuplicateObject(CONSOLE_CLIENTPROCESSHANDLE(),
  1020. a->ErrorEvent,
  1021. NtCurrentProcess(),
  1022. &Console->VDMErrorHardwareEvent,
  1023. 0,
  1024. FALSE,
  1025. DUPLICATE_SAME_ACCESS
  1026. );
  1027. }
  1028. if (NT_SUCCESS(Status)) {
  1029. Status = GdiFullscreenControl(FullscreenControlRegisterVdm,
  1030. &Vdm,
  1031. sizeof(Vdm),
  1032. &RegisterVdm,
  1033. &RegisterVdmSize
  1034. );
  1035. if (NT_SUCCESS(Status)) {
  1036. //
  1037. // create state section and map a view of it into server and vdm.
  1038. // this section is used to get/set video hardware state during
  1039. // the fullscreen<->windowed transition. we create the section
  1040. // instead of the vdm for security purposes.
  1041. //
  1042. Status = MapViewOfSection(&Console->StateSectionHandle,
  1043. RegisterVdm.MinimumStateSize,
  1044. &Console->StateBuffer,
  1045. &ViewSize,
  1046. Console->VDMProcessHandle,
  1047. &a->StateBuffer
  1048. );
  1049. if (NT_SUCCESS(Status)) {
  1050. a->StateLength = RegisterVdm.MinimumStateSize;
  1051. Console->StateLength = RegisterVdm.MinimumStateSize;
  1052. Console->StateBufferClient = a->StateBuffer;
  1053. } else {
  1054. CloseHandle(Console->VDMStartHardwareEvent);
  1055. CloseHandle(Console->VDMEndHardwareEvent);
  1056. if (Console->VDMErrorHardwareEvent) {
  1057. CloseHandle(Console->VDMErrorHardwareEvent);
  1058. }
  1059. }
  1060. } else {
  1061. CloseHandle(Console->VDMStartHardwareEvent);
  1062. CloseHandle(Console->VDMEndHardwareEvent);
  1063. if (Console->VDMErrorHardwareEvent) {
  1064. CloseHandle(Console->VDMErrorHardwareEvent);
  1065. }
  1066. }
  1067. } else {
  1068. CloseHandle(Console->VDMStartHardwareEvent);
  1069. CloseHandle(Console->VDMEndHardwareEvent);
  1070. }
  1071. } else {
  1072. CloseHandle(Console->VDMStartHardwareEvent);
  1073. }
  1074. }
  1075. //
  1076. // If we failed to duplicate screen switch events or map
  1077. // view to video state shared buffer, fail this API.
  1078. //
  1079. if (!NT_SUCCESS(Status)) {
  1080. UnlockConsole(Console);
  1081. return Status;
  1082. }
  1083. }
  1084. #endif // i386
  1085. //
  1086. // Create vdm char section and map a view of it into server and vdm.
  1087. // This section is used by the vdm to update the screen when in a
  1088. // charmode window. This is a performance optimization. We create
  1089. // the section instead of the vdm for security purposes.
  1090. //
  1091. Status = MapViewOfSection(&Console->VDMBufferSectionHandle,
  1092. #ifdef i386
  1093. a->VDMBufferSize.X * a->VDMBufferSize.Y * 2,
  1094. #else
  1095. a->VDMBufferSize.X * a->VDMBufferSize.Y * 4,
  1096. #endif // i386
  1097. &Console->VDMBuffer,
  1098. &ViewSize,
  1099. Console->VDMProcessHandle,
  1100. &a->VDMBuffer
  1101. );
  1102. if (!NT_SUCCESS(Status)) {
  1103. Console->VDMBuffer = NULL;
  1104. #ifdef i386
  1105. if (FullScreenInitialized) {
  1106. NtUnmapViewOfSection(NtCurrentProcess(), Console->StateBuffer);
  1107. NtUnmapViewOfSection(Console->VDMProcessHandle, Console->StateBufferClient);
  1108. NtClose(Console->StateSectionHandle);
  1109. CloseHandle(Console->VDMStartHardwareEvent);
  1110. CloseHandle(Console->VDMEndHardwareEvent);
  1111. if (Console->VDMErrorHardwareEvent) {
  1112. CloseHandle(Console->VDMErrorHardwareEvent);
  1113. }
  1114. }
  1115. #endif // i386
  1116. CloseHandle(Console->VDMProcessHandle);
  1117. Console->VDMProcessHandle = NULL;
  1118. UnlockConsole(Console);
  1119. return Status;
  1120. }
  1121. Console->VDMBufferClient = a->VDMBuffer;
  1122. Console->Flags |= CONSOLE_VDM_REGISTERED;
  1123. if (Console->Flags & CONSOLE_HAS_FOCUS) {
  1124. USERTHREAD_FLAGS Flags;
  1125. Flags.dwFlags = TIF_VDMAPP;
  1126. Flags.dwMask = TIF_VDMAPP;
  1127. NtUserSetInformationThread(Console->InputThreadInfo->ThreadHandle,
  1128. UserThreadFlags,
  1129. &Flags,
  1130. sizeof(Flags));
  1131. }
  1132. Console->VDMBufferSize = a->VDMBufferSize;
  1133. if (a->RegisterFlags & CONSOLE_REGISTER_WOW) {
  1134. Console->Flags |= CONSOLE_WOW_REGISTERED;
  1135. } else {
  1136. Console->Flags &= ~CONSOLE_WOW_REGISTERED;
  1137. }
  1138. //
  1139. // If we're already in fullscreen and we run a DOS app for
  1140. // the first time, connect the emulator.
  1141. //
  1142. #ifdef i386
  1143. if (Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE) {
  1144. RECT CursorRect = {-32767, -32767, 32767, 32767};
  1145. NtUserConsoleControl(ConsoleSetVDMCursorBounds, &CursorRect, sizeof(RECT));
  1146. UserAssert(!(Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR));
  1147. ConnectToEmulator(TRUE, Console);
  1148. }
  1149. #endif
  1150. UnlockConsole(Console);
  1151. return Status;
  1152. UNREFERENCED_PARAMETER(ReplyStatus);
  1153. }
  1154. NTSTATUS
  1155. SrvConsoleNotifyLastClose(
  1156. IN OUT PCSR_API_MSG m,
  1157. IN OUT PCSR_REPLY_STATUS ReplyStatus
  1158. )
  1159. {
  1160. PCONSOLE_NOTIFYLASTCLOSE_MSG a = (PCONSOLE_NOTIFYLASTCLOSE_MSG)&m->u.ApiMessageData;
  1161. NTSTATUS Status;
  1162. PCONSOLE_INFORMATION Console;
  1163. UNREFERENCED_PARAMETER(ReplyStatus);
  1164. Status = ApiPreamble(a->ConsoleHandle,
  1165. &Console
  1166. );
  1167. if (!NT_SUCCESS(Status)) {
  1168. return Status;
  1169. }
  1170. //
  1171. // Don't allow two or more processes to have last-close notify on
  1172. // the same console.
  1173. //
  1174. if (Console->Flags & CONSOLE_NOTIFY_LAST_CLOSE) {
  1175. UnlockConsole(Console);
  1176. return STATUS_ACCESS_DENIED;
  1177. }
  1178. Status = NtDuplicateObject(NtCurrentProcess(), CONSOLE_CLIENTPROCESSHANDLE(),
  1179. NtCurrentProcess(),
  1180. &Console->hProcessLastNotifyClose,
  1181. 0, FALSE, DUPLICATE_SAME_ACCESS
  1182. );
  1183. if (!NT_SUCCESS(Status)) {
  1184. UnlockConsole(Console);
  1185. return Status;
  1186. }
  1187. Console->Flags |= CONSOLE_NOTIFY_LAST_CLOSE;
  1188. Console->ProcessIdLastNotifyClose = CONSOLE_CLIENTPROCESSID();
  1189. UnlockConsole(Console);
  1190. return Status;
  1191. }
  1192. NTSTATUS
  1193. MapViewOfSection(
  1194. PHANDLE SectionHandle,
  1195. ULONG CommitSize,
  1196. PVOID *BaseAddress,
  1197. PSIZE_T ViewSize,
  1198. HANDLE ClientHandle,
  1199. PVOID *BaseClientAddress
  1200. )
  1201. {
  1202. OBJECT_ATTRIBUTES Obja;
  1203. NTSTATUS Status;
  1204. LARGE_INTEGER secSize;
  1205. //
  1206. // open section and map a view of it.
  1207. //
  1208. InitializeObjectAttributes(
  1209. &Obja,
  1210. NULL,
  1211. OBJ_CASE_INSENSITIVE,
  1212. NULL,
  1213. NULL
  1214. );
  1215. secSize.QuadPart = CommitSize;
  1216. Status = NtCreateSection (SectionHandle,
  1217. SECTION_ALL_ACCESS,
  1218. &Obja,
  1219. &secSize,
  1220. PAGE_READWRITE,
  1221. SEC_RESERVE,
  1222. NULL
  1223. );
  1224. if (!NT_SUCCESS(Status)) {
  1225. return((ULONG) Status);
  1226. }
  1227. *BaseAddress = 0;
  1228. *ViewSize = 0;
  1229. Status = NtMapViewOfSection(*SectionHandle,
  1230. NtCurrentProcess(),
  1231. BaseAddress, // Receives the base
  1232. // address of the section.
  1233. 0, // No specific type of
  1234. // address required.
  1235. CommitSize, // Commit size. It was
  1236. // passed by the caller.
  1237. // NULL for a save, and
  1238. // size of the section
  1239. // for a set.
  1240. NULL, // Section offset it NULL;
  1241. // Map from the start.
  1242. ViewSize, // View Size is NULL since
  1243. // we want to map the
  1244. // entire section.
  1245. ViewUnmap,
  1246. 0L,
  1247. PAGE_READWRITE
  1248. );
  1249. if (!NT_SUCCESS(Status)) {
  1250. NtClose(*SectionHandle);
  1251. return Status;
  1252. }
  1253. *BaseClientAddress = 0;
  1254. *ViewSize = 0;
  1255. Status = NtMapViewOfSection(*SectionHandle,
  1256. ClientHandle,
  1257. BaseClientAddress, // Receives the base
  1258. // address of the section.
  1259. 0, // No specific type of
  1260. // address required.
  1261. CommitSize, // Commit size. It was
  1262. // passed by the caller.
  1263. // NULL for a save, and
  1264. // size of the section
  1265. // for a set.
  1266. NULL, // Section offset it NULL;
  1267. // Map from the start.
  1268. ViewSize, // View Size is NULL since
  1269. // we want to map the
  1270. // entire section.
  1271. ViewUnmap,
  1272. // williamh, Jan 28 1994
  1273. // This MEM_TOP_DOWN is necessary.
  1274. // if the console has VDM registered, ntvdm would have released its video memory
  1275. // address space(0xA0000 ~ 0xBFFFF). Without the MEM_TOP_DOWN, the
  1276. // NtMapViewOfSection can grab the address space and we will have trouble of
  1277. // mapping the address space to the physical video ram. We don't do a test
  1278. // for VDM because there is no harm of doing this for non-vdm application.
  1279. MEM_TOP_DOWN,
  1280. PAGE_READWRITE
  1281. );
  1282. if (!NT_SUCCESS(Status)) {
  1283. NtUnmapViewOfSection(NtCurrentProcess(), *BaseAddress);
  1284. NtClose(*SectionHandle);
  1285. }
  1286. return((ULONG) Status);
  1287. }
  1288. NTSTATUS
  1289. ConnectToEmulator(
  1290. IN BOOL Connect,
  1291. IN PCONSOLE_INFORMATION Console
  1292. )
  1293. {
  1294. NTSTATUS Status;
  1295. FULLSCREENCONTROL fsctl;
  1296. VIDEO_VDM ConnectInfo;
  1297. HANDLE ProcessHandle = Console->VDMProcessHandle;
  1298. USERTHREAD_FLAGS Flags;
  1299. DBGFULLSCR(("ConnectToEmulator : %s - entering\n", Connect ? "CONNECT" : "DISCONNECT"));
  1300. Flags.dwMask = TIF_DOSEMULATOR;
  1301. if (Connect) {
  1302. fsctl = FullscreenControlEnable;
  1303. UserAssert((Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR) == 0);
  1304. Console->Flags |= CONSOLE_CONNECTED_TO_EMULATOR;
  1305. Flags.dwFlags = TIF_DOSEMULATOR;
  1306. #if DBG
  1307. RtlWalkFrameChain(Console->ConnectStack,
  1308. ARRAY_SIZE(Console->ConnectStack),
  1309. 0);
  1310. #endif
  1311. } else {
  1312. fsctl = FullscreenControlDisable;
  1313. UserAssert((Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR) != 0);
  1314. Console->Flags &= ~CONSOLE_CONNECTED_TO_EMULATOR;
  1315. Flags.dwFlags = 0;
  1316. #if DBG
  1317. RtlWalkFrameChain(Console->DisconnectStack,
  1318. ARRAY_SIZE(Console->DisconnectStack),
  1319. 0);
  1320. #endif
  1321. }
  1322. if (Console->Flags & CONSOLE_HAS_FOCUS) {
  1323. NtUserSetInformationThread(Console->InputThreadInfo->ThreadHandle,
  1324. UserThreadFlags, &Flags, sizeof(Flags));
  1325. }
  1326. ConnectInfo.ProcessHandle = ProcessHandle;
  1327. Status = GdiFullscreenControl(fsctl,
  1328. &ConnectInfo,
  1329. sizeof(ConnectInfo),
  1330. NULL,
  1331. NULL);
  1332. UserAssert(Status == STATUS_SUCCESS ||
  1333. Status == STATUS_CONFLICTING_ADDRESSES ||
  1334. Status == STATUS_PROCESS_IS_TERMINATING);
  1335. DBGFULLSCR(("ConnectToEmulator : leaving, staus = %08lx\n", Status));
  1336. return Status;
  1337. }
  1338. #define CONSOLE_VDM_TIMEOUT 20000
  1339. #ifdef i386
  1340. VOID
  1341. LockConsoleForCurrentThread(
  1342. IN PCONSOLE_INFORMATION Console,
  1343. IN DWORD Count)
  1344. {
  1345. while (Console->ConsoleLock.RecursionCount != Count) {
  1346. LockConsole(Console);
  1347. }
  1348. }
  1349. DWORD
  1350. UnlockConsoleForCurrentThread(
  1351. IN PCONSOLE_INFORMATION Console)
  1352. {
  1353. DWORD Count, i;
  1354. Count = Console->ConsoleLock.RecursionCount;
  1355. ASSERT(Count > 0);
  1356. for (i = 0; i < Count; i++) {
  1357. UnlockConsole(Console);
  1358. }
  1359. return Count;
  1360. }
  1361. #endif
  1362. NTSTATUS
  1363. DisplayModeTransition(
  1364. IN BOOL bForeground,
  1365. IN PCONSOLE_INFORMATION Console,
  1366. IN PSCREEN_INFORMATION ScreenInfo
  1367. )
  1368. {
  1369. #ifdef i386
  1370. NTSTATUS Status;
  1371. LARGE_INTEGER li;
  1372. DWORD WaitCount;
  1373. HANDLE WaitHandles[2];
  1374. if (!FullScreenInitialized || GetSystemMetrics(SM_REMOTESESSION)) {
  1375. return STATUS_SUCCESS;
  1376. }
  1377. WaitCount = 1;
  1378. WaitHandles[0] = Console->VDMEndHardwareEvent;
  1379. if (Console->VDMErrorHardwareEvent) {
  1380. WaitHandles[1] = Console->VDMErrorHardwareEvent;
  1381. WaitCount++;
  1382. }
  1383. if (bForeground) {
  1384. if (!(Console->FullScreenFlags & CONSOLE_FULLSCREEN)) {
  1385. KdPrint(("CONSRV: received fullscreen message too early\n"));
  1386. return STATUS_UNSUCCESSFUL;
  1387. }
  1388. } else {
  1389. //
  1390. // Check first to see if we're not already fullscreen. If we aren't,
  1391. // don't allow this. Temporary BETA fix till USER gets fixed.
  1392. //
  1393. if (!(Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE)) {
  1394. KdPrint(("CONSRV: received multiple windowed messages\n"));
  1395. return STATUS_SUCCESS;
  1396. }
  1397. }
  1398. //
  1399. // Before actually doing any mode switching work, notify ntvdm to give it
  1400. // a chance to bring all threads to a stoppable state.
  1401. //
  1402. if (Console->Flags & CONSOLE_VDM_REGISTERED) {
  1403. //
  1404. // make a special case for ntvdm during switching because
  1405. // ntvdm has to suspend its main thread which may be making
  1406. // console api calls before it can be suspended.
  1407. //
  1408. HANDLE ConsoleHandle = Console->ConsoleHandle;
  1409. NTSTATUS Statusx;
  1410. //
  1411. // Make timeout longer than usual. It will take long to
  1412. // stop ntvdm threads under stress.
  1413. //
  1414. li.QuadPart = (LONGLONG)-10000 * CONSOLE_VDM_TIMEOUT * 3;
  1415. Status = NtSetEvent(Console->VDMStartHardwareEvent, NULL);
  1416. if (NT_SUCCESS(Status)) {
  1417. HANDLE OwningThread;
  1418. DWORD RecursionCount;
  1419. //
  1420. // After notifying ntvdm to do screen switch, we must release
  1421. // console locks to avoid deadlock. Before doing so, we need to
  1422. // remember how many locks are released and who releases them, in
  1423. // case that we fail to get the locks back.
  1424. //
  1425. OwningThread = Console->ConsoleLock.OwningThread;
  1426. Console->UnlockConsoleOwningThread = OwningThread;
  1427. RecursionCount = UnlockConsoleForCurrentThread(Console);
  1428. Status = NtWaitForMultipleObjects(WaitCount, WaitHandles, WaitAny, FALSE, &li);
  1429. Statusx = RevalidateConsole(ConsoleHandle, &Console);
  1430. if (!NT_SUCCESS(Statusx)) {
  1431. Console->UnlockConsoleSkipCount = RecursionCount;
  1432. NtSetEvent(Console->VDMErrorHardwareEvent, NULL);
  1433. return Statusx;
  1434. }
  1435. //
  1436. // Get back the original number of locks. Since the lock is owned
  1437. // by us already (by calling RevalidateConsole), the following call
  1438. // simply increases the recursion count of the lock.
  1439. //
  1440. LockConsoleForCurrentThread(Console, RecursionCount);
  1441. Console->UnlockConsoleOwningThread = NULL;
  1442. }
  1443. if (Status != 0) {
  1444. Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT;
  1445. NtSetEvent(Console->VDMErrorHardwareEvent, NULL);
  1446. UnregisterVDM(Console);
  1447. KdPrint(("CONSRV: VDM not responding to initial request.\n"));
  1448. }
  1449. }
  1450. if (bForeground) {
  1451. PSCREEN_INFORMATION ScreenInfo = Console->CurrentScreenBuffer;
  1452. NTSTATUS Status;
  1453. KdPrint((" CONSRV - Display Mode transition to fullscreen \n"));
  1454. Console->FullScreenFlags |= CONSOLE_FULLSCREEN_HARDWARE;
  1455. //
  1456. // Fire off an event to let accessibility apps know the layout has
  1457. // changed. We only want to do this while going *to* full-screen;
  1458. // on the way back we'll send this event from InternalUpdateScrollBars.
  1459. //
  1460. ConsoleNotifyWinEvent(ScreenInfo->Console,
  1461. EVENT_CONSOLE_LAYOUT,
  1462. 0,
  1463. 0);
  1464. if (!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)) {
  1465. #if defined(FE_SB)
  1466. BOOL fGraphics = fFullScreenGraphics ? IsAvailableFsCodePage(Console->OutputCP) : FALSE;
  1467. #endif
  1468. #if 1
  1469. DEVMODEW Devmode;
  1470. ULONG Index;
  1471. Index = Console->CurrentScreenBuffer->BufferInfo.TextInfo.ModeIndex;
  1472. //
  1473. // set mode to go to full screen
  1474. //
  1475. ZeroMemory(&Devmode, sizeof(Devmode));
  1476. Devmode.dmSize = sizeof(Devmode);
  1477. Devmode.dmDriverExtra = 0;
  1478. Devmode.dmFields = DM_BITSPERPEL |
  1479. DM_PELSWIDTH |
  1480. DM_PELSHEIGHT |
  1481. DM_DISPLAYFLAGS;
  1482. Devmode.dmBitsPerPel = 4;
  1483. #if defined(FE_SB)
  1484. Devmode.dmPelsWidth = RegModeFontPairs[Index].Resolution.X;
  1485. Devmode.dmPelsHeight = RegModeFontPairs[Index].Resolution.Y;
  1486. Devmode.dmDisplayFlags = (fGraphics && (RegModeFontPairs[Index].Mode & FS_MODE_GRAPHICS)) ? 0 : DMDISPLAYFLAGS_TEXTMODE;
  1487. #else
  1488. Devmode.dmPelsWidth = ModeFontPairs[Index].Resolution.X;
  1489. Devmode.dmPelsHeight = ModeFontPairs[Index].Resolution.Y;
  1490. Devmode.dmDisplayFlags = DMDISPLAYFLAGS_TEXTMODE;
  1491. #endif
  1492. if (NT_SUCCESS(GdiFullscreenControl(FullscreenControlSetMode,
  1493. &Devmode,
  1494. sizeof(Devmode),
  1495. NULL,
  1496. NULL)))
  1497. {
  1498. #endif
  1499. // set video mode and font
  1500. if (SetVideoMode(ScreenInfo)) {
  1501. #if defined(FE_SB)
  1502. if (!(Console->Flags & CONSOLE_VDM_REGISTERED)) {
  1503. int i ;
  1504. for (i = 0 ; i < ScreenInfo->ScreenBufferSize.Y; i++) {
  1505. ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.OldLeft = INVALID_OLD_LENGTH ;
  1506. ScreenInfo->BufferInfo.TextInfo.Rows[i].CharRow.OldRight = INVALID_OLD_LENGTH ;
  1507. }
  1508. }
  1509. #endif
  1510. //set up cursor
  1511. SetCursorInformationHW(ScreenInfo,
  1512. ScreenInfo->BufferInfo.TextInfo.CursorSize,
  1513. ScreenInfo->BufferInfo.TextInfo.CursorVisible);
  1514. SetCursorPositionHW(ScreenInfo,
  1515. ScreenInfo->BufferInfo.TextInfo.CursorPosition);
  1516. }
  1517. }
  1518. }
  1519. // tell VDM to unmap memory
  1520. if (Console->Flags & CONSOLE_VDM_REGISTERED) {
  1521. //
  1522. // Increase the regular timeout value, since ntvdm needs to
  1523. // do A LOT of transitions between kernel mode and user mode
  1524. // to collect the video state information. (During stress, it may
  1525. // take a long time.)
  1526. //
  1527. li.QuadPart = (LONGLONG)-10000 * CONSOLE_VDM_TIMEOUT * 3;
  1528. Status = NtSetEvent(Console->VDMStartHardwareEvent, NULL);
  1529. if (NT_SUCCESS(Status)) {
  1530. Status = NtWaitForMultipleObjects(WaitCount, WaitHandles, WaitAny, FALSE, &li);
  1531. }
  1532. if (Status != 0) {
  1533. Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT;
  1534. NtSetEvent(Console->VDMErrorHardwareEvent, NULL);
  1535. UnregisterVDM(Console);
  1536. KdPrint(("CONSRV: VDM not responding or in error state.\n"));
  1537. }
  1538. }
  1539. if (!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)) {
  1540. WriteRegionToScreen(ScreenInfo, &ScreenInfo->Window);
  1541. }
  1542. if (Console->Flags & CONSOLE_VDM_REGISTERED) {
  1543. // connect emulator and map memory into the VDMs address space.
  1544. UserAssert(!(Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR));
  1545. Status = ConnectToEmulator(TRUE, Console);
  1546. if (NT_SUCCESS(Status)) {
  1547. VIDEO_HARDWARE_STATE State;
  1548. ULONG StateSize = sizeof(State);
  1549. State.StateHeader = Console->StateBuffer;
  1550. State.StateLength = Console->StateLength;
  1551. Status = GdiFullscreenControl(FullscreenControlRestoreHardwareState,
  1552. &State,
  1553. StateSize,
  1554. &State,
  1555. &StateSize);
  1556. }
  1557. if (Status != STATUS_SUCCESS) {
  1558. Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT;
  1559. NtSetEvent(Console->VDMErrorHardwareEvent, NULL);
  1560. UnregisterVDM(Console);
  1561. KdPrint(("CONSRV: set hardware state failed.\n"));
  1562. } else {
  1563. //
  1564. // tell VDM that it's getting the hardware.
  1565. //
  1566. RECT CursorRect;
  1567. CursorRect.left = -32767;
  1568. CursorRect.top = -32767;
  1569. CursorRect.right = 32767;
  1570. CursorRect.bottom = 32767;
  1571. NtUserConsoleControl(ConsoleSetVDMCursorBounds,
  1572. &CursorRect, sizeof(RECT));
  1573. //
  1574. // wait for vdm to say ok. We could initiate another switch
  1575. // (set hStartHardwareEvent which vdm is now waiting for to
  1576. // complete the handshaking) when we return (WM_FULLSCREEN
  1577. // could be in the message queue already). If we don't wait
  1578. // for vdm to get signaled here, the hStartHardwareEvent
  1579. // can get set twice and signaled once so the vdm will never
  1580. // gets the newly switch request we may post after return.
  1581. //
  1582. // Also, we can not simply continue if timeout or error occurs.
  1583. // We could set hStartHardwareEvent twice if a new mode switch
  1584. // request is in our queue. This will cause us and ntvdm
  1585. // out of sync.
  1586. //
  1587. li.QuadPart = (LONGLONG)-10000 * CONSOLE_VDM_TIMEOUT;
  1588. NtSetEvent(Console->VDMStartHardwareEvent, NULL);
  1589. Status = NtWaitForMultipleObjects(WaitCount, WaitHandles, WaitAny, FALSE, &li);
  1590. if (Status != 0) {
  1591. Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT;
  1592. NtSetEvent(Console->VDMErrorHardwareEvent, NULL);
  1593. UnregisterVDM(Console);
  1594. KdPrint(("CONSRV: VDM not responding or in error state.\n"));
  1595. }
  1596. }
  1597. }
  1598. //
  1599. // let the app know that it has the focus.
  1600. //
  1601. HandleFocusEvent(Console, TRUE);
  1602. // unset palette
  1603. if (ScreenInfo->hPalette != NULL) {
  1604. SelectPalette(ScreenInfo->Console->hDC,
  1605. ScreenInfo->Console->hSysPalette,
  1606. FALSE);
  1607. UnsetActivePalette(ScreenInfo);
  1608. }
  1609. SetConsoleReserveKeys(Console->hWnd, Console->ReserveKeys);
  1610. HandleFocusEvent(Console, TRUE);
  1611. } else {
  1612. KdPrint((" CONSRV - Display Mode transition to windowed \n"));
  1613. // turn off mouse pointer so VDM doesn't see it when saving
  1614. // hardware
  1615. if (!(ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)) {
  1616. ReverseMousePointer(ScreenInfo, &ScreenInfo->Window);
  1617. }
  1618. Console->FullScreenFlags &= ~CONSOLE_FULLSCREEN_HARDWARE;
  1619. if (Console->Flags & CONSOLE_VDM_REGISTERED) {
  1620. //
  1621. // tell vdm that it's losing the hardware
  1622. //
  1623. li.QuadPart = (LONGLONG)-10000 * CONSOLE_VDM_TIMEOUT;
  1624. Status = NtSetEvent(Console->VDMStartHardwareEvent, NULL);
  1625. if (NT_SUCCESS(Status)) {
  1626. Status = NtWaitForMultipleObjects(WaitCount, WaitHandles, WaitAny, FALSE, &li);
  1627. if (Status == STATUS_TIMEOUT || Status == 1) {
  1628. Status = STATUS_UNSUCCESSFUL;
  1629. }
  1630. }
  1631. // if ntvdm didn't respond or we failed to save the video hardware
  1632. // states, kick ntvdm out of our world. The ntvdm process eventually
  1633. // would die but what choice do have here?
  1634. if (NT_SUCCESS(Status)) {
  1635. VIDEO_HARDWARE_STATE State;
  1636. ULONG StateSize = sizeof(State);
  1637. State.StateHeader = Console->StateBuffer;
  1638. State.StateLength = Console->StateLength;
  1639. Status = GdiFullscreenControl(FullscreenControlSaveHardwareState,
  1640. &State,
  1641. StateSize,
  1642. &State,
  1643. &StateSize);
  1644. }
  1645. if (NT_SUCCESS(Status)) {
  1646. NtUserConsoleControl(ConsoleSetVDMCursorBounds, NULL, 0);
  1647. // disconnect emulator and unmap video memory
  1648. UserAssert(Console->Flags & CONSOLE_CONNECTED_TO_EMULATOR);
  1649. ConnectToEmulator(FALSE, Console);
  1650. } else {
  1651. Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT;
  1652. NtSetEvent(Console->VDMErrorHardwareEvent, NULL);
  1653. UnregisterVDM(Console);
  1654. if (Status != 0) {
  1655. KdPrint(("CONSRV: VDM not responding.\n"));
  1656. } else {
  1657. KdPrint(("CONSRV: Save Video States Failed\n"));
  1658. }
  1659. }
  1660. }
  1661. // tell VDM to map memory
  1662. if (Console->Flags & CONSOLE_VDM_REGISTERED) {
  1663. // make a special case for ntvdm during switching because
  1664. // ntvdm has to make console api calls. We don't want to
  1665. // unlock the console at this moment because as soon as
  1666. // we release the lock, other theads which are waiting
  1667. // for the lock will claim the lock and the ntvdm thread doing
  1668. // the screen switch will have to wait for the lock. In an
  1669. // extreme case, the following NtWaitForSingleObject will time
  1670. // out because the ntvdm may be still waiting for the lock.
  1671. // We keep this thing in a single global variable because
  1672. // there is only one process who can own the screen at any moment.
  1673. RtlEnterCriticalSection(&ConsoleVDMCriticalSection);
  1674. ConsoleVDMOnSwitching = Console;
  1675. RtlLeaveCriticalSection(&ConsoleVDMCriticalSection);
  1676. //
  1677. // Increase the regular timeout value, since ntvdm needs to
  1678. // do A LOT of transitions between kernel mode and user mode
  1679. // before it can signal console back. (During stress, it may
  1680. // take a long time.)
  1681. //
  1682. li.QuadPart = (LONGLONG)-10000 * CONSOLE_VDM_TIMEOUT * 3;
  1683. Status = NtSetEvent(Console->VDMStartHardwareEvent, NULL);
  1684. if (NT_SUCCESS(Status)) {
  1685. Status = NtWaitForMultipleObjects(WaitCount, WaitHandles, WaitAny, FALSE, &li);
  1686. }
  1687. // time to go back to normal
  1688. RtlEnterCriticalSection(&ConsoleVDMCriticalSection);
  1689. ConsoleVDMOnSwitching = NULL;
  1690. RtlLeaveCriticalSection(&ConsoleVDMCriticalSection);
  1691. if (Status != 0) {
  1692. Console->Flags &= ~CONSOLE_FULLSCREEN_NOPAINT;
  1693. NtSetEvent(Console->VDMErrorHardwareEvent, NULL);
  1694. UnregisterVDM(Console);
  1695. KdPrint(("CONSRV: VDM not responding. - second wait\n"));
  1696. return Status;
  1697. }
  1698. ScreenInfo = Console->CurrentScreenBuffer;
  1699. }
  1700. // set palette
  1701. if (ScreenInfo->hPalette != NULL) {
  1702. SelectPalette(ScreenInfo->Console->hDC,
  1703. ScreenInfo->hPalette,
  1704. FALSE);
  1705. SetActivePalette(ScreenInfo);
  1706. }
  1707. SetConsoleReserveKeys(Console->hWnd, CONSOLE_NOSHORTCUTKEY);
  1708. HandleFocusEvent(Console, FALSE);
  1709. }
  1710. /*
  1711. * Boost or lower the priority if we are going fullscreen or away.
  1712. *
  1713. * Note that console usually boosts and lowers its priority based on
  1714. * WM_FOCUS and WM_KILLFOCUS but when you switch to full screen the
  1715. * implementation actually sends a WM_KILLFOCUS so we reboost the
  1716. * correct console here.
  1717. */
  1718. ModifyConsoleProcessFocus(Console, bForeground);
  1719. #else
  1720. UNREFERENCED_PARAMETER(bForeground);
  1721. UNREFERENCED_PARAMETER(Console);
  1722. UNREFERENCED_PARAMETER(ScreenInfo);
  1723. #endif
  1724. return STATUS_SUCCESS;
  1725. }
  1726. #if defined(_X86_)
  1727. BOOL
  1728. SetVideoMode(
  1729. IN PSCREEN_INFORMATION ScreenInfo
  1730. )
  1731. {
  1732. NTSTATUS Status;
  1733. UINT i, j;
  1734. #if defined(FE_SB)
  1735. //
  1736. // load RAM font
  1737. //
  1738. Status = SetRAMFontCodePage(ScreenInfo);
  1739. #endif
  1740. //
  1741. // load ROM font
  1742. //
  1743. Status = SetROMFontCodePage(ScreenInfo->Console->OutputCP,
  1744. ScreenInfo->BufferInfo.TextInfo.ModeIndex);
  1745. if (Status == STATUS_INVALID_PARAMETER) {
  1746. Status = SetROMFontCodePage(GetOEMCP(),
  1747. ScreenInfo->BufferInfo.TextInfo.ModeIndex);
  1748. if (Status == STATUS_INVALID_PARAMETER) {
  1749. Status = SetROMFontCodePage(CONSOLE_DEFAULT_ROM_FONT,
  1750. ScreenInfo->BufferInfo.TextInfo.ModeIndex);
  1751. }
  1752. }
  1753. //
  1754. // initialize palette
  1755. //
  1756. #if defined(FE_SB)
  1757. Status = GdiFullscreenControl(FullscreenControlSetPalette,
  1758. (PVOID) RegInitialPalette,
  1759. RegInitialPalette[0] * sizeof(USHORT) + sizeof(DWORD),
  1760. NULL,
  1761. NULL);
  1762. #else
  1763. Status = GdiFullscreenControl(FullscreenControlSetPalette,
  1764. (PVOID) &InitialPalette,
  1765. sizeof (InitialPalette),
  1766. NULL,
  1767. NULL);
  1768. #endif
  1769. if (Status != STATUS_SUCCESS) {
  1770. RIPMSG1(RIP_WARNING, "FullscreenControlSetPalette failed - Status = 0x%x",
  1771. Status);
  1772. return FALSE;
  1773. }
  1774. //
  1775. // initialize color table
  1776. //
  1777. #if defined(FE_SB)
  1778. if (RegColorBufferNoTranslate)
  1779. {
  1780. Status = GdiFullscreenControl(FullscreenControlSetColors,
  1781. (PVOID) RegColorBufferNoTranslate,
  1782. RegColorBufferNoTranslate[0] * sizeof(DWORD) + sizeof(DWORD),
  1783. NULL,
  1784. NULL);
  1785. }
  1786. else
  1787. {
  1788. for (i = 0, j = 4; i < 16; i++) {
  1789. RegColorBuffer[j++] = ((((GetRValue(ScreenInfo->Console->ColorTable[i]) +
  1790. 0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
  1791. RegColorBuffer[j++] = ((((GetGValue(ScreenInfo->Console->ColorTable[i]) +
  1792. 0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
  1793. RegColorBuffer[j++] = ((((GetBValue(ScreenInfo->Console->ColorTable[i]) +
  1794. 0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
  1795. RegColorBuffer[j++] = 0;
  1796. }
  1797. Status = GdiFullscreenControl(FullscreenControlSetColors,
  1798. (PVOID) RegColorBuffer,
  1799. RegColorBuffer[0] * sizeof(DWORD) + sizeof(DWORD),
  1800. NULL,
  1801. NULL);
  1802. }
  1803. #else
  1804. for (i = 0, j = 4; i < 16; i++) {
  1805. ColorBuffer[j++] = ((((GetRValue(ScreenInfo->Console->ColorTable[i]) +
  1806. 0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
  1807. ColorBuffer[j++] = ((((GetGValue(ScreenInfo->Console->ColorTable[i]) +
  1808. 0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
  1809. ColorBuffer[j++] = ((((GetBValue(ScreenInfo->Console->ColorTable[i]) +
  1810. 0x2A) * 0x02) / 0x55) * 0x15) / 0x02;
  1811. ColorBuffer[j++] = 0;
  1812. }
  1813. Status = GdiFullscreenControl(FullscreenControlSetColors,
  1814. (PVOID) &ColorBuffer,
  1815. sizeof (ColorBuffer),
  1816. NULL,
  1817. NULL);
  1818. #endif
  1819. if (Status != STATUS_SUCCESS) {
  1820. RIPMSG1(RIP_WARNING, "FullscreenControlSetColors failed - Status = 0x%x",
  1821. Status);
  1822. return FALSE;
  1823. }
  1824. return TRUE;
  1825. }
  1826. #endif
  1827. #if defined(_X86_)
  1828. NTSTATUS
  1829. ChangeDispSettings(
  1830. PCONSOLE_INFORMATION Console,
  1831. HWND hwnd,
  1832. DWORD dwFlags)
  1833. {
  1834. DEVMODEW Devmode;
  1835. ULONG Index;
  1836. CONSOLE_FULLSCREEN_SWITCH switchBlock;
  1837. if (dwFlags == CDS_FULLSCREEN) {
  1838. #if defined(FE_SB)
  1839. BOOL fGraphics = fFullScreenGraphics ? IsAvailableFsCodePage(Console->OutputCP) : FALSE;
  1840. #endif
  1841. Index = Console->CurrentScreenBuffer->BufferInfo.TextInfo.ModeIndex;
  1842. //
  1843. // set mode to go to full screen
  1844. //
  1845. ZeroMemory(&Devmode, sizeof(Devmode));
  1846. Devmode.dmSize = sizeof(Devmode);
  1847. Devmode.dmDriverExtra = 0;
  1848. Devmode.dmFields = DM_BITSPERPEL |
  1849. DM_PELSWIDTH |
  1850. DM_PELSHEIGHT |
  1851. DM_DISPLAYFLAGS;
  1852. Devmode.dmBitsPerPel = 4;
  1853. #if defined(FE_SB)
  1854. Devmode.dmPelsWidth = RegModeFontPairs[Index].Resolution.X;
  1855. Devmode.dmPelsHeight = RegModeFontPairs[Index].Resolution.Y;
  1856. Devmode.dmDisplayFlags = (fGraphics && (RegModeFontPairs[Index].Mode & FS_MODE_GRAPHICS)) ? 0 : DMDISPLAYFLAGS_TEXTMODE;
  1857. #else
  1858. Devmode.dmPelsWidth = ModeFontPairs[Index].Resolution.X;
  1859. Devmode.dmPelsHeight = ModeFontPairs[Index].Resolution.Y;
  1860. Devmode.dmDisplayFlags = DMDISPLAYFLAGS_TEXTMODE;
  1861. #endif
  1862. switchBlock.bFullscreenSwitch = TRUE;
  1863. switchBlock.hwnd = hwnd;
  1864. switchBlock.pNewMode = &Devmode;
  1865. } else {
  1866. switchBlock.bFullscreenSwitch = FALSE;
  1867. switchBlock.hwnd = hwnd;
  1868. switchBlock.pNewMode = NULL;
  1869. }
  1870. return NtUserConsoleControl(ConsoleFullscreenSwitch,
  1871. &switchBlock,
  1872. sizeof(CONSOLE_FULLSCREEN_SWITCH));
  1873. }
  1874. #endif
  1875. BOOL
  1876. InitializeFullScreen( VOID )
  1877. {
  1878. UNICODE_STRING vgaString;
  1879. DEVMODEW devmode;
  1880. ULONG i;
  1881. #ifdef FE_SB
  1882. DWORD mode1 = 0;
  1883. DWORD mode2 = 0;
  1884. #else
  1885. BOOLEAN mode1 = FALSE;
  1886. BOOLEAN mode2 = FALSE;
  1887. #endif
  1888. CHAR WindowsDir[CONSOLE_WINDOWS_DIR_LENGTH + CONSOLE_EGACPI_LENGTH];
  1889. UINT WindowsDirLength;
  1890. //
  1891. // query number of available modes
  1892. //
  1893. ZeroMemory(&devmode, sizeof(DEVMODEW));
  1894. devmode.dmSize = sizeof(DEVMODEW);
  1895. RtlInitUnicodeString(&vgaString, L"VGACOMPATIBLE");
  1896. DBGCHARS(("Number of modes = %d\n", NUMBER_OF_MODE_FONT_PAIRS));
  1897. for (i=0; ; i++)
  1898. {
  1899. DBGCHARS(("EnumDisplaySettings %d\n", i));
  1900. if (!(NT_SUCCESS(NtUserEnumDisplaySettings(&vgaString,
  1901. i,
  1902. &devmode,
  1903. 0))))
  1904. {
  1905. break;
  1906. }
  1907. #if defined(FE_SB)
  1908. {
  1909. ULONG Index;
  1910. DBGCHARS(("Mode X = %d, Y = %d\n",
  1911. devmode.dmPelsWidth, devmode.dmPelsHeight));
  1912. for (Index=0;Index<NUMBER_OF_MODE_FONT_PAIRS;Index++)
  1913. {
  1914. if ((SHORT)devmode.dmPelsWidth == RegModeFontPairs[Index].Resolution.X &&
  1915. (SHORT)devmode.dmPelsHeight == RegModeFontPairs[Index].Resolution.Y )
  1916. {
  1917. if (devmode.dmDisplayFlags & DMDISPLAYFLAGS_TEXTMODE)
  1918. {
  1919. if (RegModeFontPairs[Index].Mode & FS_MODE_TEXT)
  1920. {
  1921. RegModeFontPairs[Index].Mode |= FS_MODE_FIND;
  1922. mode1++;
  1923. }
  1924. }
  1925. else
  1926. {
  1927. if (RegModeFontPairs[Index].Mode & FS_MODE_GRAPHICS)
  1928. {
  1929. RegModeFontPairs[Index].Mode |= FS_MODE_FIND;
  1930. mode2++;
  1931. }
  1932. }
  1933. }
  1934. }
  1935. DBGCHARS(("mode1 = %d, mode2 = %d\n", mode1, mode2));
  1936. }
  1937. #else
  1938. if (devmode.dmPelsWidth == 720 &&
  1939. devmode.dmPelsHeight == 400)
  1940. {
  1941. mode1 = TRUE;
  1942. }
  1943. if (devmode.dmPelsWidth == 640 &&
  1944. devmode.dmPelsHeight == 350)
  1945. {
  1946. mode2 = TRUE;
  1947. }
  1948. #endif
  1949. }
  1950. #if !defined(FE_SB)
  1951. if (!(mode1 && mode2))
  1952. #else
  1953. if (mode1 < 2)
  1954. #endif
  1955. {
  1956. //
  1957. // One of the modes we expected to get was not returned.
  1958. // lets just fail fullscreen initialization.
  1959. //
  1960. KdPrint(("CONSRV: InitializeFullScreen Missing text mode\n"));
  1961. return FALSE;
  1962. }
  1963. #if defined(FE_SB)
  1964. if (mode2 > 0)
  1965. {
  1966. // Can do trun graphics mode.
  1967. fFullScreenGraphics = TRUE;
  1968. }
  1969. #endif
  1970. //
  1971. // open ega.cpi
  1972. //
  1973. WindowsDirLength = GetSystemDirectoryA(WindowsDir,
  1974. CONSOLE_WINDOWS_DIR_LENGTH);
  1975. if (WindowsDirLength == 0)
  1976. {
  1977. KdPrint(("CONSRV: InitializeFullScreen Finding Font file failed\n"));
  1978. return FALSE;
  1979. }
  1980. RtlCopyMemory(&WindowsDir[WindowsDirLength],
  1981. CONSOLE_EGACPI,
  1982. CONSOLE_EGACPI_LENGTH);
  1983. if ((hCPIFile = CreateFileA(WindowsDir,
  1984. GENERIC_READ,
  1985. FILE_SHARE_READ,
  1986. NULL,
  1987. OPEN_EXISTING,
  1988. 0,
  1989. NULL)) == INVALID_HANDLE_VALUE)
  1990. {
  1991. KdPrint(("CONSRV: InitializeFullScreen Opening Font file failed\n"));
  1992. return FALSE;
  1993. }
  1994. return TRUE;
  1995. }
  1996. ULONG
  1997. SrvGetConsoleHardwareState(
  1998. IN OUT PCSR_API_MSG m,
  1999. IN OUT PCSR_REPLY_STATUS ReplyStatus
  2000. )
  2001. {
  2002. #ifdef i386
  2003. PCONSOLE_GETHARDWARESTATE_MSG a = (PCONSOLE_GETHARDWARESTATE_MSG)&m->u.ApiMessageData;
  2004. NTSTATUS Status;
  2005. PCONSOLE_INFORMATION Console;
  2006. PHANDLE_DATA HandleData;
  2007. PSCREEN_INFORMATION ScreenInfo;
  2008. Status = ApiPreamble(a->ConsoleHandle,
  2009. &Console
  2010. );
  2011. if (!NT_SUCCESS(Status)) {
  2012. return Status;
  2013. }
  2014. Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
  2015. a->OutputHandle,
  2016. CONSOLE_OUTPUT_HANDLE,
  2017. GENERIC_READ,
  2018. &HandleData
  2019. );
  2020. if (NT_SUCCESS(Status)) {
  2021. ScreenInfo = HandleData->Buffer.ScreenBuffer;
  2022. if (ScreenInfo->BufferInfo.TextInfo.ModeIndex == -1) {
  2023. UnlockConsole(Console);
  2024. return STATUS_UNSUCCESSFUL;
  2025. }
  2026. #if defined(FE_SB)
  2027. a->Resolution = RegModeFontPairs[ScreenInfo->BufferInfo.TextInfo.ModeIndex].Resolution;
  2028. a->FontSize = RegModeFontPairs[ScreenInfo->BufferInfo.TextInfo.ModeIndex].FontSize;
  2029. #else
  2030. a->Resolution = ModeFontPairs[ScreenInfo->BufferInfo.TextInfo.ModeIndex].Resolution;
  2031. a->FontSize = ModeFontPairs[ScreenInfo->BufferInfo.TextInfo.ModeIndex].FontSize;
  2032. #endif
  2033. }
  2034. UnlockConsole(Console);
  2035. return Status;
  2036. #else
  2037. return STATUS_UNSUCCESSFUL;
  2038. UNREFERENCED_PARAMETER(m);
  2039. #endif
  2040. UNREFERENCED_PARAMETER(ReplyStatus);
  2041. }
  2042. ULONG
  2043. SrvSetConsoleHardwareState(
  2044. IN OUT PCSR_API_MSG m,
  2045. IN OUT PCSR_REPLY_STATUS ReplyStatus
  2046. )
  2047. {
  2048. #ifdef i386
  2049. PCONSOLE_SETHARDWARESTATE_MSG a = (PCONSOLE_SETHARDWARESTATE_MSG)&m->u.ApiMessageData;
  2050. NTSTATUS Status;
  2051. PCONSOLE_INFORMATION Console;
  2052. PHANDLE_DATA HandleData;
  2053. PSCREEN_INFORMATION ScreenInfo;
  2054. ULONG Index;
  2055. Status = ApiPreamble(a->ConsoleHandle,
  2056. &Console
  2057. );
  2058. if (!NT_SUCCESS(Status)) {
  2059. return Status;
  2060. }
  2061. if (!(Console->FullScreenFlags & CONSOLE_FULLSCREEN_HARDWARE)) {
  2062. UnlockConsole(Console);
  2063. return STATUS_UNSUCCESSFUL;
  2064. }
  2065. Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
  2066. a->OutputHandle,
  2067. CONSOLE_OUTPUT_HANDLE,
  2068. GENERIC_READ,
  2069. &HandleData
  2070. );
  2071. if (NT_SUCCESS(Status)) {
  2072. #if defined(FE_SB)
  2073. BOOL fGraphics = fFullScreenGraphics ? IsAvailableFsCodePage(Console->OutputCP) : FALSE;
  2074. #endif
  2075. ScreenInfo = HandleData->Buffer.ScreenBuffer;
  2076. // match requested mode
  2077. for (Index=0;Index<NUMBER_OF_MODE_FONT_PAIRS;Index++) {
  2078. #if defined(FE_SB)
  2079. if (a->Resolution.X == RegModeFontPairs[Index].Resolution.X &&
  2080. a->Resolution.Y == RegModeFontPairs[Index].Resolution.Y &&
  2081. a->FontSize.Y == RegModeFontPairs[Index].FontSize.Y &&
  2082. a->FontSize.X == RegModeFontPairs[Index].FontSize.X &&
  2083. ( ( fGraphics && (RegModeFontPairs[Index].Mode & FS_GRAPHICS)==FS_GRAPHICS) ||
  2084. (!fGraphics && (RegModeFontPairs[Index].Mode & FS_TEXT)==FS_TEXT) )
  2085. ) {
  2086. break;
  2087. }
  2088. #else
  2089. if (a->Resolution.X == ModeFontPairs[Index].Resolution.X &&
  2090. a->Resolution.Y == ModeFontPairs[Index].Resolution.Y &&
  2091. a->FontSize.Y == ModeFontPairs[Index].FontSize.Y &&
  2092. a->FontSize.X == ModeFontPairs[Index].FontSize.X) {
  2093. break;
  2094. }
  2095. #endif
  2096. }
  2097. if (Index == NUMBER_OF_MODE_FONT_PAIRS) {
  2098. Status = STATUS_INVALID_PARAMETER;
  2099. } else {
  2100. // set requested mode
  2101. ScreenInfo->BufferInfo.TextInfo.ModeIndex = Index;
  2102. SetVideoMode(ScreenInfo);
  2103. }
  2104. }
  2105. UnlockConsole(Console);
  2106. return Status;
  2107. #else
  2108. return STATUS_UNSUCCESSFUL;
  2109. UNREFERENCED_PARAMETER(m);
  2110. #endif
  2111. UNREFERENCED_PARAMETER(ReplyStatus);
  2112. }
  2113. ULONG
  2114. SrvGetConsoleDisplayMode(
  2115. IN OUT PCSR_API_MSG m,
  2116. IN OUT PCSR_REPLY_STATUS ReplyStatus
  2117. )
  2118. {
  2119. PCONSOLE_GETDISPLAYMODE_MSG a = (PCONSOLE_GETDISPLAYMODE_MSG)&m->u.ApiMessageData;
  2120. NTSTATUS Status;
  2121. PCONSOLE_INFORMATION Console;
  2122. Status = ApiPreamble(a->ConsoleHandle,
  2123. &Console
  2124. );
  2125. if (NT_SUCCESS(Status)) {
  2126. a->ModeFlags = Console->FullScreenFlags;
  2127. UnlockConsole(Console);
  2128. }
  2129. return Status;
  2130. UNREFERENCED_PARAMETER(ReplyStatus);
  2131. }
  2132. ULONG
  2133. SrvSetConsoleMenuClose(
  2134. IN OUT PCSR_API_MSG m,
  2135. IN OUT PCSR_REPLY_STATUS ReplyStatus
  2136. )
  2137. {
  2138. PCONSOLE_SETMENUCLOSE_MSG a = (PCONSOLE_SETMENUCLOSE_MSG)&m->u.ApiMessageData;
  2139. NTSTATUS Status;
  2140. PCONSOLE_INFORMATION Console;
  2141. UNREFERENCED_PARAMETER(ReplyStatus);
  2142. Status = ApiPreamble(a->ConsoleHandle,
  2143. &Console
  2144. );
  2145. if (!NT_SUCCESS(Status)) {
  2146. return Status;
  2147. }
  2148. if (a->Enable) {
  2149. Console->Flags &= ~CONSOLE_DISABLE_CLOSE;
  2150. } else {
  2151. Console->Flags |= CONSOLE_DISABLE_CLOSE;
  2152. }
  2153. UnlockConsole(Console);
  2154. return Status;
  2155. }
  2156. DWORD
  2157. ConvertHotKey(
  2158. IN LPAPPKEY UserAppKey
  2159. )
  2160. {
  2161. DWORD wParam;
  2162. wParam = MapVirtualKey(UserAppKey->ScanCode,1);
  2163. if (UserAppKey->Modifier & CONSOLE_MODIFIER_SHIFT) {
  2164. wParam |= 0x0100;
  2165. }
  2166. if (UserAppKey->Modifier & CONSOLE_MODIFIER_CONTROL) {
  2167. wParam |= 0x0200;
  2168. }
  2169. if (UserAppKey->Modifier & CONSOLE_MODIFIER_ALT) {
  2170. wParam |= 0x0400;
  2171. }
  2172. return wParam;
  2173. }
  2174. ULONG
  2175. SrvSetConsoleKeyShortcuts(
  2176. IN OUT PCSR_API_MSG m,
  2177. IN OUT PCSR_REPLY_STATUS ReplyStatus
  2178. )
  2179. {
  2180. PCONSOLE_SETKEYSHORTCUTS_MSG a = (PCONSOLE_SETKEYSHORTCUTS_MSG)&m->u.ApiMessageData;
  2181. NTSTATUS Status;
  2182. PCONSOLE_INFORMATION Console;
  2183. UNREFERENCED_PARAMETER(ReplyStatus);
  2184. Status = ApiPreamble(a->ConsoleHandle,
  2185. &Console
  2186. );
  2187. if (!NT_SUCCESS(Status)) {
  2188. return Status;
  2189. }
  2190. /*
  2191. * We only call CsrCaptureMessageBuffer() in SetConsoleKeyShortcuts if
  2192. * a->NumAppKeys != 0, so we only want to call CsrValidateMessageBuffer when
  2193. * that condition's true.
  2194. */
  2195. if (a->NumAppKeys != 0 && !CsrValidateMessageBuffer(m, &a->AppKeys, a->NumAppKeys, sizeof(*a->AppKeys))) {
  2196. UnlockConsole(Console);
  2197. return STATUS_INVALID_PARAMETER;
  2198. }
  2199. if (a->NumAppKeys <= CONSOLE_MAX_APP_SHORTCUTS) {
  2200. Console->ReserveKeys = a->ReserveKeys;
  2201. if (Console->Flags & CONSOLE_HAS_FOCUS) {
  2202. if (!(SetConsoleReserveKeys(Console->hWnd, a->ReserveKeys))) {
  2203. Status = STATUS_INVALID_PARAMETER;
  2204. }
  2205. }
  2206. if (a->NumAppKeys) {
  2207. PostMessage(Console->hWnd,
  2208. WM_SETHOTKEY,
  2209. ConvertHotKey(a->AppKeys),
  2210. 0
  2211. );
  2212. }
  2213. } else {
  2214. Status = STATUS_INVALID_PARAMETER;
  2215. }
  2216. UnlockConsole(Console);
  2217. return Status;
  2218. }
  2219. #ifdef i386
  2220. ULONG
  2221. MatchWindowSize(
  2222. #if defined(FE_SB)
  2223. IN UINT CodePage,
  2224. #endif
  2225. IN COORD WindowSize,
  2226. OUT PCOORD pWindowSize
  2227. )
  2228. /*++
  2229. find the best match font. it's the one that's the same size
  2230. or slightly larger than the window size.
  2231. --*/
  2232. {
  2233. ULONG i;
  2234. #if defined(FE_SB)
  2235. BOOL fGraphics = fFullScreenGraphics ? IsAvailableFsCodePage(CodePage) : FALSE;
  2236. #endif
  2237. for (i=0;i<NUMBER_OF_MODE_FONT_PAIRS;i++) {
  2238. #if defined(FE_SB)
  2239. if (WindowSize.Y <= RegModeFontPairs[i].ScreenSize.Y &&
  2240. ( ( fGraphics && (RegModeFontPairs[i].Mode & FS_GRAPHICS)==FS_GRAPHICS) ||
  2241. (!fGraphics && (RegModeFontPairs[i].Mode & FS_TEXT)==FS_TEXT) )
  2242. )
  2243. #else
  2244. if (WindowSize.Y <= (SHORT)ModeFontPairs[i].Height)
  2245. #endif
  2246. {
  2247. break;
  2248. }
  2249. }
  2250. if (i == NUMBER_OF_MODE_FONT_PAIRS)
  2251. #if defined(FE_SB)
  2252. {
  2253. DWORD Find;
  2254. ULONG FindIndex;
  2255. COORD WindowSizeDelta;
  2256. FindIndex = 0;
  2257. Find = (DWORD)-1;
  2258. for (i=0; i<NUMBER_OF_MODE_FONT_PAIRS;i++) {
  2259. if ( ( fGraphics && (RegModeFontPairs[i].Mode & FS_GRAPHICS)==FS_GRAPHICS) ||
  2260. (!fGraphics && (RegModeFontPairs[i].Mode & FS_TEXT)==FS_TEXT) )
  2261. {
  2262. WindowSizeDelta.Y = (SHORT) abs(WindowSize.Y - RegModeFontPairs[i].ScreenSize.Y);
  2263. if (Find > (DWORD)(WindowSizeDelta.Y))
  2264. {
  2265. Find = (DWORD)(WindowSizeDelta.Y);
  2266. FindIndex = i;
  2267. }
  2268. }
  2269. }
  2270. i = FindIndex;
  2271. }
  2272. #else
  2273. i-=1;
  2274. #endif
  2275. #if defined(FE_SB)
  2276. *pWindowSize = RegModeFontPairs[i].ScreenSize;
  2277. #else
  2278. pWindowSize->X = 80;
  2279. pWindowSize->Y = (SHORT)ModeFontPairs[i].Height;
  2280. #endif
  2281. return i;
  2282. }
  2283. VOID
  2284. ReadRegionFromScreenHW(
  2285. IN PSCREEN_INFORMATION ScreenInfo,
  2286. IN PSMALL_RECT Region,
  2287. IN PCHAR_INFO ReadBufPtr
  2288. )
  2289. {
  2290. ULONG CurFrameBufPtr; // offset in frame buffer
  2291. SHORT FrameY;
  2292. SHORT WindowY, WindowX, WindowSizeX;
  2293. //
  2294. // get pointer to start of region in frame buffer
  2295. //
  2296. WindowY = Region->Top - ScreenInfo->Window.Top;
  2297. WindowX = Region->Left - ScreenInfo->Window.Left;
  2298. WindowSizeX = CONSOLE_WINDOW_SIZE_X(ScreenInfo);
  2299. //
  2300. // copy the chars and attrs from the frame buffer
  2301. //
  2302. for (FrameY = Region->Top;
  2303. FrameY <= Region->Bottom;
  2304. FrameY++, WindowY++) {
  2305. CurFrameBufPtr = SCREEN_BUFFER_POINTER(WindowX,
  2306. WindowY,
  2307. WindowSizeX,
  2308. sizeof(VGA_CHAR));
  2309. GdiFullscreenControl(FullscreenControlReadFromFrameBuffer,
  2310. (PULONG) CurFrameBufPtr,
  2311. (Region->Right - Region->Left + 1) *
  2312. sizeof(VGA_CHAR),
  2313. ReadBufPtr, NULL);
  2314. ReadBufPtr += (Region->Right - Region->Left + 1);
  2315. }
  2316. }
  2317. VOID
  2318. ReverseMousePointer(
  2319. IN PSCREEN_INFORMATION ScreenInfo,
  2320. IN PSMALL_RECT Region
  2321. )
  2322. {
  2323. ULONG CurFrameBufPtr; // offset in frame buffer
  2324. SHORT WindowSizeX;
  2325. #ifdef FE_SB
  2326. // fail safe
  2327. UserAssert(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER);
  2328. if (!(ScreenInfo->Flags & CONSOLE_TEXTMODE_BUFFER)) {
  2329. return;
  2330. }
  2331. #endif
  2332. WindowSizeX = CONSOLE_WINDOW_SIZE_X(ScreenInfo);
  2333. if (ScreenInfo->BufferInfo.TextInfo.MousePosition.X < Region->Left ||
  2334. ScreenInfo->BufferInfo.TextInfo.MousePosition.X > Region->Right ||
  2335. ScreenInfo->BufferInfo.TextInfo.MousePosition.Y < Region->Top ||
  2336. ScreenInfo->BufferInfo.TextInfo.MousePosition.Y > Region->Bottom ||
  2337. ScreenInfo->CursorDisplayCount < 0 ||
  2338. !(ScreenInfo->Console->InputBuffer.InputMode & ENABLE_MOUSE_INPUT) ||
  2339. ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED) {
  2340. return;
  2341. }
  2342. #if defined(FE_SB)
  2343. {
  2344. FSVIDEO_REVERSE_MOUSE_POINTER MousePointer;
  2345. SHORT RowIndex;
  2346. PROW Row;
  2347. COORD TargetPoint;
  2348. TargetPoint.X = ScreenInfo->BufferInfo.TextInfo.MousePosition.X;
  2349. TargetPoint.Y = ScreenInfo->BufferInfo.TextInfo.MousePosition.Y;
  2350. RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+TargetPoint.Y) % ScreenInfo->ScreenBufferSize.Y;
  2351. Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
  2352. if (!CONSOLE_IS_DBCS_CP(ScreenInfo->Console))
  2353. MousePointer.dwType = CHAR_TYPE_SBCS;
  2354. else if (Row->CharRow.KAttrs[TargetPoint.X] & ATTR_TRAILING_BYTE)
  2355. MousePointer.dwType = CHAR_TYPE_TRAILING;
  2356. else if (Row->CharRow.KAttrs[TargetPoint.X] & ATTR_LEADING_BYTE)
  2357. MousePointer.dwType = CHAR_TYPE_LEADING;
  2358. else
  2359. MousePointer.dwType = CHAR_TYPE_SBCS;
  2360. MousePointer.Screen.Position.X = TargetPoint.X - ScreenInfo->Window.Left;
  2361. MousePointer.Screen.Position.Y = TargetPoint.Y - ScreenInfo->Window.Top;
  2362. MousePointer.Screen.ScreenSize.X = WindowSizeX;
  2363. MousePointer.Screen.ScreenSize.Y = CONSOLE_WINDOW_SIZE_Y(ScreenInfo);
  2364. MousePointer.Screen.nNumberOfChars = 0;
  2365. GdiFullscreenControl(FullscreenControlReverseMousePointerDB,
  2366. &MousePointer,
  2367. sizeof(MousePointer),
  2368. NULL,
  2369. NULL);
  2370. UNREFERENCED_PARAMETER(CurFrameBufPtr);
  2371. }
  2372. #else
  2373. CurFrameBufPtr = SCREEN_BUFFER_POINTER(ScreenInfo->BufferInfo.TextInfo.MousePosition.X - ScreenInfo->Window.Left,
  2374. ScreenInfo->BufferInfo.TextInfo.MousePosition.Y - ScreenInfo->Window.Top,
  2375. WindowSizeX,
  2376. sizeof(VGA_CHAR));
  2377. GdiFullscreenControl(FullscreenControlReverseMousePointer,
  2378. (PULONG)CurFrameBufPtr,
  2379. 0,
  2380. NULL,
  2381. NULL);
  2382. #endif
  2383. }
  2384. VOID
  2385. CopyVideoMemory(
  2386. SHORT SourceY,
  2387. SHORT TargetY,
  2388. SHORT Length,
  2389. IN PSCREEN_INFORMATION ScreenInfo
  2390. )
  2391. /*++
  2392. Routine Description:
  2393. This routine copies rows of characters in video memory. It only copies
  2394. complete rows.
  2395. Arguments:
  2396. SourceY - Row to copy from.
  2397. TargetY - Row to copy to.
  2398. Length - Number of rows to copy.
  2399. Return Value:
  2400. --*/
  2401. {
  2402. ULONG SourcePtr, TargetPtr;
  2403. SHORT WindowSizeX, WindowSizeY;
  2404. WindowSizeX = CONSOLE_WINDOW_SIZE_X(ScreenInfo);
  2405. WindowSizeY = CONSOLE_WINDOW_SIZE_Y(ScreenInfo);
  2406. if (max(SourceY, TargetY) + Length > WindowSizeY) {
  2407. Length = WindowSizeY - max(SourceY, TargetY);
  2408. if (Length <= 0 ) {
  2409. return;
  2410. }
  2411. }
  2412. #if defined(FE_SB)
  2413. {
  2414. FSCNTL_SCREEN_INFO FsCntlSrc;
  2415. FSCNTL_SCREEN_INFO FsCntlDest;
  2416. FsCntlSrc.Position.X = 0;
  2417. FsCntlSrc.Position.Y = SourceY;
  2418. FsCntlSrc.ScreenSize.X = WindowSizeX;
  2419. FsCntlSrc.ScreenSize.Y = CONSOLE_WINDOW_SIZE_Y(ScreenInfo);
  2420. FsCntlSrc.nNumberOfChars = Length * WindowSizeX;
  2421. FsCntlDest.Position.X = 0;
  2422. FsCntlDest.Position.Y = TargetY;
  2423. FsCntlDest.ScreenSize.X = WindowSizeX;
  2424. FsCntlDest.ScreenSize.Y = CONSOLE_WINDOW_SIZE_Y(ScreenInfo);
  2425. FsCntlDest.nNumberOfChars = Length * WindowSizeX;
  2426. GdiFullscreenControl(FullscreenControlCopyFrameBufferDB,
  2427. &FsCntlSrc,
  2428. sizeof(FsCntlSrc),
  2429. &FsCntlDest,
  2430. (PULONG)sizeof(FsCntlDest));
  2431. UNREFERENCED_PARAMETER(SourcePtr);
  2432. UNREFERENCED_PARAMETER(TargetPtr);
  2433. }
  2434. #else
  2435. SourcePtr = SCREEN_BUFFER_POINTER(0,
  2436. SourceY,
  2437. WindowSizeX,
  2438. sizeof(VGA_CHAR));
  2439. TargetPtr = SCREEN_BUFFER_POINTER(0,
  2440. TargetY,
  2441. WindowSizeX,
  2442. sizeof(VGA_CHAR));
  2443. GdiFullscreenControl(FullscreenControlCopyFrameBuffer,
  2444. (PULONG) SourcePtr,
  2445. Length * WindowSizeX * sizeof(VGA_CHAR),
  2446. (PULONG) TargetPtr,
  2447. (PULONG) (Length * WindowSizeX * sizeof(VGA_CHAR)));
  2448. #endif
  2449. }
  2450. VOID
  2451. ScrollHW(
  2452. IN PSCREEN_INFORMATION ScreenInfo,
  2453. IN PSMALL_RECT ScrollRect,
  2454. IN PSMALL_RECT MergeRect,
  2455. IN COORD TargetPoint
  2456. )
  2457. {
  2458. SMALL_RECT TargetRectangle;
  2459. if (ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED)
  2460. return;
  2461. TargetRectangle.Left = TargetPoint.X;
  2462. TargetRectangle.Top = TargetPoint.Y;
  2463. TargetRectangle.Right = TargetPoint.X + ScrollRect->Right - ScrollRect->Left;
  2464. TargetRectangle.Bottom = TargetPoint.Y + ScrollRect->Bottom - ScrollRect->Top;
  2465. //
  2466. // if the scroll region is as wide as the screen, we can update
  2467. // the screen by copying the video memory. if we scroll this
  2468. // way, we then must clip and update the fill region.
  2469. //
  2470. if (ScrollRect->Left == ScreenInfo->Window.Left &&
  2471. TargetRectangle.Left == ScreenInfo->Window.Left &&
  2472. ScrollRect->Right == ScreenInfo->Window.Right &&
  2473. TargetRectangle.Right == ScreenInfo->Window.Right &&
  2474. ScrollRect->Top >= ScreenInfo->Window.Top &&
  2475. TargetRectangle.Top >= ScreenInfo->Window.Top &&
  2476. ScrollRect->Bottom <= ScreenInfo->Window.Bottom &&
  2477. TargetRectangle.Bottom <= ScreenInfo->Window.Bottom) {
  2478. //
  2479. // we must first make the mouse pointer invisible because
  2480. // otherwise it would get copied to another place on the
  2481. // screen if it were part of the scroll region.
  2482. //
  2483. ReverseMousePointer(ScreenInfo, &ScreenInfo->Window);
  2484. CopyVideoMemory((SHORT) (ScrollRect->Top - ScreenInfo->Window.Top),
  2485. (SHORT) (TargetRectangle.Top - ScreenInfo->Window.Top),
  2486. (SHORT) (TargetRectangle.Bottom - TargetRectangle.Top + 1),
  2487. ScreenInfo);
  2488. //
  2489. // update the fill region. first we ensure that the scroll and
  2490. // target regions aren't the same. if they are, we don't fill.
  2491. //
  2492. if (TargetRectangle.Top != ScrollRect->Top) {
  2493. //
  2494. // if scroll and target regions overlap, with scroll
  2495. // region above target region, clip scroll region.
  2496. //
  2497. if (TargetRectangle.Top <= ScrollRect->Bottom &&
  2498. TargetRectangle.Bottom >= ScrollRect->Bottom) {
  2499. ScrollRect->Bottom = (SHORT)(TargetRectangle.Top-1);
  2500. }
  2501. else if (TargetRectangle.Top <= ScrollRect->Top &&
  2502. TargetRectangle.Bottom >= ScrollRect->Top) {
  2503. ScrollRect->Top = (SHORT)(TargetRectangle.Bottom+1);
  2504. }
  2505. WriteToScreen(ScreenInfo, ScrollRect);
  2506. //
  2507. // WriteToScreen should take care of writing the mouse pointer.
  2508. // however, the update region may be clipped so that the
  2509. // mouse pointer is not written. in that case, we draw the
  2510. // mouse pointer here.
  2511. //
  2512. if (ScreenInfo->BufferInfo.TextInfo.MousePosition.Y < ScrollRect->Top ||
  2513. ScreenInfo->BufferInfo.TextInfo.MousePosition.Y > ScrollRect->Bottom) {
  2514. ReverseMousePointer(ScreenInfo, &ScreenInfo->Window);
  2515. }
  2516. }
  2517. if (MergeRect) {
  2518. WriteToScreen(ScreenInfo, MergeRect);
  2519. }
  2520. }
  2521. else {
  2522. if (MergeRect) {
  2523. WriteToScreen(ScreenInfo, MergeRect);
  2524. }
  2525. WriteToScreen(ScreenInfo, ScrollRect);
  2526. WriteToScreen(ScreenInfo, &TargetRectangle);
  2527. }
  2528. }
  2529. VOID
  2530. UpdateMousePosition(
  2531. PSCREEN_INFORMATION ScreenInfo,
  2532. COORD Position
  2533. )
  2534. /*++
  2535. Routine Description:
  2536. This routine moves the mouse pointer.
  2537. Arguments:
  2538. ScreenInfo - Pointer to screen buffer information.
  2539. Position - Contains the new position of the mouse in screen buffer
  2540. coordinates.
  2541. Return Value:
  2542. none.
  2543. --*/
  2544. // Note: CurrentConsole lock must be held in share mode when calling this routine
  2545. {
  2546. SMALL_RECT CursorRegion;
  2547. #ifdef FE_SB
  2548. SHORT RowIndex;
  2549. PROW Row;
  2550. BOOL fOneMore = FALSE;
  2551. #endif
  2552. if ((ScreenInfo->Console->Flags & CONSOLE_VDM_REGISTERED) ||
  2553. (ScreenInfo->Flags & CONSOLE_GRAPHICS_BUFFER)) {
  2554. return;
  2555. }
  2556. if (Position.X < ScreenInfo->Window.Left ||
  2557. Position.X > ScreenInfo->Window.Right ||
  2558. Position.Y < ScreenInfo->Window.Top ||
  2559. Position.Y > ScreenInfo->Window.Bottom) {
  2560. return;
  2561. }
  2562. if (Position.X == ScreenInfo->BufferInfo.TextInfo.MousePosition.X &&
  2563. Position.Y == ScreenInfo->BufferInfo.TextInfo.MousePosition.Y) {
  2564. return;
  2565. }
  2566. #ifdef FE_SB
  2567. if (CONSOLE_IS_DBCS_CP(ScreenInfo->Console)) {
  2568. RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+Position.Y) % ScreenInfo->ScreenBufferSize.Y;
  2569. Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
  2570. if (Row->CharRow.KAttrs[Position.X] & ATTR_LEADING_BYTE) {
  2571. if (Position.X != ScreenInfo->ScreenBufferSize.X - 1) {
  2572. fOneMore = TRUE;
  2573. }
  2574. } else if (Row->CharRow.KAttrs[Position.X] & ATTR_TRAILING_BYTE) {
  2575. if (Position.X != 0) {
  2576. fOneMore = TRUE;
  2577. Position.X--;
  2578. }
  2579. }
  2580. }
  2581. #endif
  2582. if (ScreenInfo->CursorDisplayCount < 0 || !(ScreenInfo->Console->InputBuffer.InputMode & ENABLE_MOUSE_INPUT)) {
  2583. ScreenInfo->BufferInfo.TextInfo.MousePosition = Position;
  2584. return;
  2585. }
  2586. // turn off old mouse position.
  2587. CursorRegion.Left = CursorRegion.Right = ScreenInfo->BufferInfo.TextInfo.MousePosition.X;
  2588. CursorRegion.Top = CursorRegion.Bottom = ScreenInfo->BufferInfo.TextInfo.MousePosition.Y;
  2589. #ifdef FE_SB
  2590. if (CONSOLE_IS_DBCS_CP(ScreenInfo->Console)) {
  2591. RowIndex = (ScreenInfo->BufferInfo.TextInfo.FirstRow+CursorRegion.Top) % ScreenInfo->ScreenBufferSize.Y;
  2592. Row = &ScreenInfo->BufferInfo.TextInfo.Rows[RowIndex];
  2593. if (Row->CharRow.KAttrs[CursorRegion.Left] & ATTR_LEADING_BYTE) {
  2594. if (CursorRegion.Left != ScreenInfo->ScreenBufferSize.X - 1) {
  2595. CursorRegion.Right++;
  2596. }
  2597. }
  2598. }
  2599. #endif
  2600. // store new mouse position
  2601. ScreenInfo->BufferInfo.TextInfo.MousePosition.X = Position.X;
  2602. ScreenInfo->BufferInfo.TextInfo.MousePosition.Y = Position.Y;
  2603. WriteToScreen(ScreenInfo, &CursorRegion);
  2604. // turn on new mouse position
  2605. CursorRegion.Left = CursorRegion.Right = Position.X;
  2606. CursorRegion.Top = CursorRegion.Bottom = Position.Y;
  2607. #ifdef FE_SB
  2608. if (fOneMore)
  2609. CursorRegion.Right++;
  2610. #endif
  2611. WriteToScreen(ScreenInfo, &CursorRegion);
  2612. }
  2613. NTSTATUS
  2614. SetROMFontCodePage(
  2615. IN UINT wCodePage,
  2616. IN ULONG ModeIndex
  2617. )
  2618. /*
  2619. this function opens ega.cpi and looks for the desired font in the
  2620. specified codepage. if found, it loads it into the video ROM.
  2621. */
  2622. {
  2623. BYTE Buffer[CONSOLE_FONT_BUFFER_LENGTH];
  2624. DWORD dwBytesRead;
  2625. LPFONTFILEHEADER lpFontFileHeader=(LPFONTFILEHEADER)Buffer;
  2626. LPFONTINFOHEADER lpFontInfoHeader=(LPFONTINFOHEADER)Buffer;
  2627. LPFONTDATAHEADER lpFontDataHeader=(LPFONTDATAHEADER)Buffer;
  2628. LPCPENTRYHEADER lpCPEntryHeader=(LPCPENTRYHEADER)Buffer;
  2629. LPSCREENFONTHEADER lpScreenFontHeader=(LPSCREENFONTHEADER)Buffer;
  2630. WORD NumEntries;
  2631. COORD FontDimensions;
  2632. NTSTATUS Status;
  2633. BOOL Found;
  2634. LONG FilePtr;
  2635. BOOL bDOS = FALSE;
  2636. FontDimensions = ModeFontPairs[ModeIndex].FontSize;
  2637. //
  2638. // read FONTINFOHEADER
  2639. //
  2640. // do {
  2641. // read CPENTRYHEADER
  2642. // if (correct codepage)
  2643. // break;
  2644. // } while (codepages)
  2645. // if (codepage found)
  2646. // read FONTDATAHEADER
  2647. //
  2648. // read FONTFILEHEADER
  2649. FilePtr = 0;
  2650. if (SetFilePointer(hCPIFile, FilePtr, NULL, FILE_BEGIN) == -1) {
  2651. Status = STATUS_INVALID_PARAMETER;
  2652. goto DoExit;
  2653. }
  2654. if (!ReadFile(hCPIFile, Buffer, sizeof(FONTFILEHEADER), &dwBytesRead, NULL) ||
  2655. dwBytesRead != sizeof(FONTFILEHEADER)) {
  2656. Status = STATUS_INVALID_PARAMETER;
  2657. goto DoExit;
  2658. }
  2659. // verify signature
  2660. if (memcmp(lpFontFileHeader->ffhFileTag, "\xFF""FONT.NT",8) ) {
  2661. if (memcmp(lpFontFileHeader->ffhFileTag, "\xFF""FONT ",8) ) {
  2662. Status = STATUS_INVALID_PARAMETER;
  2663. goto DoExit;
  2664. } else {
  2665. bDOS = TRUE;
  2666. }
  2667. }
  2668. // seek to FONTINFOHEADER. jump through hoops to get the offset value.
  2669. FilePtr = lpFontFileHeader->ffhOffset1;
  2670. FilePtr |= (lpFontFileHeader->ffhOffset2 << 8);
  2671. FilePtr |= (lpFontFileHeader->ffhOffset3 << 24);
  2672. if (SetFilePointer(hCPIFile, FilePtr, NULL, FILE_BEGIN) == -1) {
  2673. Status = STATUS_INVALID_PARAMETER;
  2674. goto DoExit;
  2675. }
  2676. // read FONTINFOHEADER
  2677. if (!ReadFile(hCPIFile, Buffer, sizeof(FONTINFOHEADER), &dwBytesRead, NULL) ||
  2678. dwBytesRead != sizeof(FONTINFOHEADER)) {
  2679. Status = STATUS_INVALID_PARAMETER;
  2680. goto DoExit;
  2681. }
  2682. FilePtr += dwBytesRead;
  2683. NumEntries = lpFontInfoHeader->fihCodePages;
  2684. Found = FALSE;
  2685. while (NumEntries &&
  2686. ReadFile(hCPIFile, Buffer, sizeof(CPENTRYHEADER), &dwBytesRead, NULL) &&
  2687. dwBytesRead == sizeof(CPENTRYHEADER)) {
  2688. if (lpCPEntryHeader->cpeCodepageID == wCodePage) {
  2689. Found = TRUE;
  2690. break;
  2691. }
  2692. // seek to next CPEENTRYHEADER
  2693. if (bDOS) {
  2694. FilePtr = MAKELONG(lpCPEntryHeader->cpeNext1, lpCPEntryHeader->cpeNext2);
  2695. } else {
  2696. FilePtr += MAKELONG(lpCPEntryHeader->cpeNext1, lpCPEntryHeader->cpeNext2);
  2697. }
  2698. if (SetFilePointer(hCPIFile, FilePtr, NULL, FILE_BEGIN) == -1) {
  2699. Status = STATUS_INVALID_PARAMETER;
  2700. goto DoExit;
  2701. }
  2702. NumEntries -= 1;
  2703. }
  2704. if (!Found) {
  2705. Status = STATUS_INVALID_PARAMETER;
  2706. goto DoExit;
  2707. }
  2708. // seek to FONTDATAHEADER
  2709. if (bDOS) {
  2710. FilePtr = lpCPEntryHeader->cpeOffset;
  2711. } else {
  2712. FilePtr += lpCPEntryHeader->cpeOffset;
  2713. }
  2714. if (SetFilePointer(hCPIFile, FilePtr, NULL, FILE_BEGIN) == -1) {
  2715. Status = STATUS_INVALID_PARAMETER;
  2716. goto DoExit;
  2717. }
  2718. // read FONTDATAHEADER
  2719. if (!ReadFile(hCPIFile, Buffer, sizeof(FONTDATAHEADER), &dwBytesRead, NULL) ||
  2720. dwBytesRead != sizeof(FONTDATAHEADER)) {
  2721. Status = STATUS_INVALID_PARAMETER;
  2722. goto DoExit;
  2723. }
  2724. FilePtr += dwBytesRead;
  2725. NumEntries = lpFontDataHeader->fdhFonts;
  2726. while (NumEntries) {
  2727. if (!ReadFile(hCPIFile, Buffer, sizeof(SCREENFONTHEADER), &dwBytesRead, NULL) ||
  2728. dwBytesRead != sizeof(SCREENFONTHEADER)) {
  2729. Status = STATUS_INVALID_PARAMETER;
  2730. goto DoExit;
  2731. }
  2732. if (lpScreenFontHeader->sfhHeight == (BYTE)FontDimensions.Y &&
  2733. lpScreenFontHeader->sfhWidth == (BYTE)FontDimensions.X) {
  2734. PVIDEO_LOAD_FONT_INFORMATION FontInformation;
  2735. FontInformation = ConsoleHeapAlloc(TMP_TAG,
  2736. lpScreenFontHeader->sfhCharacters *
  2737. lpScreenFontHeader->sfhHeight +
  2738. sizeof(VIDEO_LOAD_FONT_INFORMATION));
  2739. if (FontInformation == NULL) {
  2740. RIPMSG1(RIP_WARNING, "SetROMFontCodePage: failed to memory allocation %d bytes",
  2741. lpScreenFontHeader->sfhCharacters * lpScreenFontHeader->sfhHeight +
  2742. sizeof(VIDEO_LOAD_FONT_INFORMATION));
  2743. return STATUS_NO_MEMORY;
  2744. }
  2745. if (!ReadFile(hCPIFile, FontInformation->Font,
  2746. lpScreenFontHeader->sfhCharacters*lpScreenFontHeader->sfhHeight,
  2747. &dwBytesRead, NULL) ||
  2748. dwBytesRead != (DWORD)(lpScreenFontHeader->sfhCharacters*lpScreenFontHeader->sfhHeight)) {
  2749. ConsoleHeapFree(FontInformation);
  2750. return STATUS_INVALID_PARAMETER;
  2751. }
  2752. FontInformation->WidthInPixels = FontDimensions.X;
  2753. FontInformation->HeightInPixels = FontDimensions.Y;
  2754. FontInformation->FontSize = lpScreenFontHeader->sfhCharacters*lpScreenFontHeader->sfhHeight;
  2755. Status = GdiFullscreenControl(FullscreenControlLoadFont,
  2756. FontInformation,
  2757. lpScreenFontHeader->sfhCharacters*lpScreenFontHeader->sfhHeight + sizeof(VIDEO_LOAD_FONT_INFORMATION),
  2758. NULL,
  2759. NULL);
  2760. ConsoleHeapFree(FontInformation);
  2761. return Status;
  2762. } else {
  2763. FilePtr = lpScreenFontHeader->sfhCharacters*lpScreenFontHeader->sfhHeight;
  2764. if (SetFilePointer(hCPIFile, FilePtr, NULL, FILE_CURRENT) == -1) {
  2765. Status = STATUS_INVALID_PARAMETER;
  2766. goto DoExit;
  2767. }
  2768. }
  2769. NumEntries -= 1;
  2770. }
  2771. DoExit:
  2772. return Status;
  2773. }
  2774. #endif
  2775. NTSTATUS
  2776. GetThreadConsoleDesktop(
  2777. DWORD dwThreadId,
  2778. HDESK *phdeskConsole)
  2779. {
  2780. PCSR_THREAD pcsrt;
  2781. PCONSOLE_PER_PROCESS_DATA ProcessData;
  2782. PCONSOLE_INFORMATION Console;
  2783. NTSTATUS Status;
  2784. HANDLE ConsoleHandle = NULL;
  2785. *phdeskConsole = NULL;
  2786. Status = CsrLockThreadByClientId(LongToHandle(dwThreadId), &pcsrt);
  2787. if (NT_SUCCESS(Status)) {
  2788. ProcessData = CONSOLE_FROMTHREADPERPROCESSDATA(pcsrt);
  2789. ConsoleHandle = ProcessData->ConsoleHandle;
  2790. CsrUnlockThread(pcsrt);
  2791. }
  2792. //
  2793. // If this process is a console app, return the
  2794. // handle to its desktop. Otherwise, return NULL.
  2795. //
  2796. if (ConsoleHandle != NULL) {
  2797. Status = RevalidateConsole(ConsoleHandle, &Console);
  2798. if (NT_SUCCESS(Status)) {
  2799. *phdeskConsole = Console->hDesk;
  2800. }
  2801. UnlockConsole(Console);
  2802. }
  2803. return STATUS_SUCCESS;
  2804. }
  2805. NTSTATUS
  2806. SetRAMFontCodePage(
  2807. IN PSCREEN_INFORMATION ScreenInfo
  2808. )
  2809. {
  2810. FSVIDEO_SCREEN_INFORMATION ScreenInformation;
  2811. ULONG ModeIndex = ScreenInfo->BufferInfo.TextInfo.ModeIndex;
  2812. COORD FontSize;
  2813. WCHAR wChar;
  2814. WCHAR wCharBuf[2];
  2815. LPSTRINGBITMAP StringBitmap;
  2816. DWORD BufferSize;
  2817. PWORD FontImage;
  2818. PFONT_CACHE_INFORMATION FontCache;
  2819. WCHAR AltFaceName[LF_FACESIZE];
  2820. COORD AltFontSize;
  2821. BYTE AltFontFamily;
  2822. ULONG AltFontIndex = 0;
  2823. HFONT hOldFont;
  2824. NTSTATUS Status;
  2825. ScreenInformation.ScreenSize = RegModeFontPairs[ModeIndex].ScreenSize;
  2826. ScreenInformation.FontSize = RegModeFontPairs[ModeIndex].FontSize;
  2827. if (ScreenInfo->Console->FontCacheInformation == NULL)
  2828. {
  2829. Status = CreateFontCache(&FontCache);
  2830. if (!NT_SUCCESS(Status)) {
  2831. RIPMSG1(RIP_WARNING, "SetRAMFontCodePage: failed in CreateFontCache. Status=%08x", Status);
  2832. return STATUS_UNSUCCESSFUL;
  2833. }
  2834. (PFONT_CACHE_INFORMATION)ScreenInfo->Console->FontCacheInformation = FontCache;
  2835. MakeAltRasterFont(SCR_FONTCODEPAGE(ScreenInfo),
  2836. RegModeFontPairs[ModeIndex].FontSize,
  2837. &AltFontSize, &AltFontFamily, &AltFontIndex, AltFaceName);
  2838. FontCache->FullScreenFontIndex = AltFontIndex;
  2839. FontCache->FullScreenFontSize = AltFontSize;
  2840. BufferSize = CalcBitmapBufferSize(FontCache->FullScreenFontSize, BYTE_ALIGN);
  2841. StringBitmap = ConsoleHeapAlloc(TMP_DBCS_TAG,
  2842. sizeof(STRINGBITMAP) + sizeof(StringBitmap->ajBits) * BufferSize);
  2843. if (StringBitmap==NULL) {
  2844. RIPMSG0(RIP_WARNING, "SetRAMFontCodePage: failed to allocate StringBitmap");
  2845. return STATUS_UNSUCCESSFUL;
  2846. }
  2847. /*
  2848. * Change GDI font to full screen font that best matched.
  2849. */
  2850. hOldFont = SelectObject(ScreenInfo->Console->hDC, FontInfo[FontCache->FullScreenFontIndex].hFont);
  2851. for (wChar=0x00; wChar < 0x80; wChar++) {
  2852. wCharBuf[0] = wChar;
  2853. wCharBuf[1] = TEXT('\0');
  2854. GetStringBitmapW(ScreenInfo->Console->hDC,
  2855. wCharBuf,
  2856. 1,
  2857. (ULONG)ConsoleHeapSize(StringBitmap),
  2858. (BYTE*)StringBitmap
  2859. );
  2860. FontSize.X = (SHORT)StringBitmap->uiWidth;
  2861. FontSize.Y = (SHORT)StringBitmap->uiHeight;
  2862. #if defined(LATER_DBCS_FOR_GRID_CHAR) // by kazum
  2863. BufferSize = CalcBitmapBufferSize(FontSize, BYTE_ALIGN);
  2864. *(StringBitmap->ajBits + BufferSize) = 0;
  2865. *(StringBitmap->ajBits + BufferSize + 1) = 0;
  2866. if (gpGridCharacter) {
  2867. PGRID_CHARACTER_INFORMATION GridCharacter;
  2868. PWCHAR CodePoint;
  2869. GridCharacter = gpGridCharacter;
  2870. do {
  2871. if (GridCharacter->CodePage == OEMCP) {
  2872. CodePoint = GridCharacter->CodePoint;
  2873. while (*CodePoint) {
  2874. if (*CodePoint == wChar) {
  2875. if (FontSize.X <= 8)
  2876. *(StringBitmap->ajBits + BufferSize) = *(StringBitmap->ajBits + BufferSize - 1);
  2877. else {
  2878. *(StringBitmap->ajBits + BufferSize) = *(StringBitmap->ajBits + BufferSize - 2);
  2879. *(StringBitmap->ajBits + BufferSize + 1) = *(StringBitmap->ajBits + BufferSize - 1);
  2880. }
  2881. break;
  2882. }
  2883. else
  2884. CodePoint++;
  2885. }
  2886. break;
  2887. }
  2888. } while (GridCharacter = GridCharacter->pNext);
  2889. }
  2890. #endif // LATER_DBCS_FOR_GRID_CHAR // by kazum
  2891. Status = SetFontImage(ScreenInfo->Console->FontCacheInformation,
  2892. wChar,
  2893. FontSize,
  2894. BYTE_ALIGN,
  2895. StringBitmap->ajBits
  2896. );
  2897. if (!NT_SUCCESS(Status)) {
  2898. RIPMSG3(RIP_WARNING, "SetRAMFontCodePage: failed to set font image. wc=%04x sz=(%x, %x).",
  2899. wChar, FontSize.X, FontSize.Y);
  2900. }
  2901. if (FontSize.X != ScreenInformation.FontSize.X ||
  2902. FontSize.Y != ScreenInformation.FontSize.Y) {
  2903. BufferSize = CalcBitmapBufferSize(ScreenInformation.FontSize, WORD_ALIGN);
  2904. FontImage = ConsoleHeapAlloc(TMP_DBCS_TAG, BufferSize);
  2905. if (FontImage!=NULL) {
  2906. GetExpandFontImage(ScreenInfo->Console->FontCacheInformation,
  2907. wChar,
  2908. FontSize,
  2909. ScreenInformation.FontSize,
  2910. FontImage);
  2911. Status = SetFontImage(ScreenInfo->Console->FontCacheInformation,
  2912. wChar,
  2913. ScreenInformation.FontSize,
  2914. WORD_ALIGN,
  2915. FontImage);
  2916. if (!NT_SUCCESS(Status)) {
  2917. RIPMSG3(RIP_WARNING, "SetRAMFontCodePage: failed to set font image. wc=%04x, sz=(%x,%x)",
  2918. wChar, ScreenInformation.FontSize.X, ScreenInformation.FontSize.Y);
  2919. }
  2920. ConsoleHeapFree(FontImage);
  2921. } else {
  2922. RIPMSG0(RIP_WARNING, "SetRAMFontCodePage: failed to allocate FontImage.");
  2923. }
  2924. }
  2925. }
  2926. ConsoleHeapFree(StringBitmap);
  2927. /*
  2928. * Back to GDI font
  2929. */
  2930. SelectObject(ScreenInfo->Console->hDC, hOldFont);
  2931. }
  2932. Status = GdiFullscreenControl(FullscreenControlSetScreenInformation,
  2933. &ScreenInformation,
  2934. sizeof(ScreenInformation),
  2935. NULL,
  2936. NULL);
  2937. return Status;
  2938. }
  2939. NTSTATUS
  2940. SetRAMFont(
  2941. IN PSCREEN_INFORMATION ScreenInfo,
  2942. IN PCHAR_INFO ScreenBufPtr,
  2943. IN DWORD Length
  2944. )
  2945. {
  2946. ULONG ModeIndex = ScreenInfo->BufferInfo.TextInfo.ModeIndex;
  2947. COORD FsFontSize1 = RegModeFontPairs[ModeIndex].FontSize;
  2948. COORD FsFontSize2 = FsFontSize1;
  2949. COORD GdiFontSize1;
  2950. COORD GdiFontSize2;
  2951. COORD RetFontSize;
  2952. WCHAR wCharBuf[2];
  2953. LPSTRINGBITMAP StringBitmap;
  2954. DWORD BufferSize;
  2955. PWORD FontImage;
  2956. PFONT_CACHE_INFORMATION FontCache;
  2957. HFONT hOldFont;
  2958. NTSTATUS Status;
  2959. FontCache = (PFONT_CACHE_INFORMATION)ScreenInfo->Console->FontCacheInformation;
  2960. if (FontCache==NULL)
  2961. {
  2962. RIPMSG0(RIP_ERROR, "SetRAMFont: ScreenInfo->Console->FontCacheInformation == NULL.");
  2963. return STATUS_UNSUCCESSFUL;
  2964. }
  2965. GdiFontSize1 = FontCache->FullScreenFontSize;
  2966. GdiFontSize2 = GdiFontSize1;
  2967. GdiFontSize2.X *= 2;
  2968. FsFontSize2.X *= 2;
  2969. BufferSize = CalcBitmapBufferSize(GdiFontSize2, BYTE_ALIGN);
  2970. StringBitmap = ConsoleHeapAlloc(TMP_DBCS_TAG,
  2971. sizeof(STRINGBITMAP) + sizeof(StringBitmap->ajBits) * BufferSize);
  2972. if (StringBitmap == NULL) {
  2973. RIPMSG0(RIP_WARNING, "SetRAMFont: failed to allocate StringBitmap");
  2974. return STATUS_UNSUCCESSFUL;
  2975. }
  2976. /*
  2977. * Change GDI font to full screen font that best matched.
  2978. */
  2979. hOldFont = SelectObject(ScreenInfo->Console->hDC, FontInfo[FontCache->FullScreenFontIndex].hFont);
  2980. while (Length--) {
  2981. Status = GetFontImage(ScreenInfo->Console->FontCacheInformation,
  2982. ScreenBufPtr->Char.UnicodeChar,
  2983. (ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? FsFontSize2 : FsFontSize1,
  2984. 0,
  2985. NULL);
  2986. if (!NT_SUCCESS(Status)) {
  2987. wCharBuf[0] = ScreenBufPtr->Char.UnicodeChar;
  2988. wCharBuf[1] = TEXT('\0');
  2989. GetStringBitmapW(ScreenInfo->Console->hDC,
  2990. wCharBuf,
  2991. 1,
  2992. (ULONG)ConsoleHeapSize(StringBitmap),
  2993. (BYTE*)StringBitmap
  2994. );
  2995. RetFontSize.X = (SHORT)StringBitmap->uiWidth;
  2996. RetFontSize.Y = (SHORT)StringBitmap->uiHeight;
  2997. Status = SetFontImage(ScreenInfo->Console->FontCacheInformation,
  2998. ScreenBufPtr->Char.UnicodeChar,
  2999. RetFontSize,
  3000. BYTE_ALIGN,
  3001. StringBitmap->ajBits
  3002. );
  3003. if (!NT_SUCCESS(Status)) {
  3004. RIPMSG3(RIP_WARNING, "SetRAMFont: failed to set font image. wc=%04x sz=(%x,%x)",
  3005. ScreenBufPtr->Char.UnicodeChar, RetFontSize.X, RetFontSize.Y);
  3006. }
  3007. if (((ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) &&
  3008. (GdiFontSize2.X != FsFontSize2.X || GdiFontSize2.Y != FsFontSize2.Y)) ||
  3009. (!(ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) &&
  3010. (GdiFontSize1.X != FsFontSize1.X || GdiFontSize1.Y != FsFontSize1.Y))) {
  3011. BufferSize = CalcBitmapBufferSize(FsFontSize2, WORD_ALIGN);
  3012. FontImage = ConsoleHeapAlloc(TMP_DBCS_TAG, BufferSize);
  3013. if (FontImage != NULL) {
  3014. GetExpandFontImage(ScreenInfo->Console->FontCacheInformation,
  3015. ScreenBufPtr->Char.UnicodeChar,
  3016. (ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? GdiFontSize2 : GdiFontSize1,
  3017. (ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? FsFontSize2 : FsFontSize1,
  3018. FontImage
  3019. );
  3020. Status = SetFontImage(ScreenInfo->Console->FontCacheInformation,
  3021. ScreenBufPtr->Char.UnicodeChar,
  3022. (ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? FsFontSize2 : FsFontSize1,
  3023. WORD_ALIGN,
  3024. FontImage
  3025. );
  3026. if (!NT_SUCCESS(Status)) {
  3027. RIPMSG3(RIP_WARNING, "SetRAMFont: failed to set font image. wc=%04x sz=(%x,%x)",
  3028. ScreenBufPtr->Char.UnicodeChar,
  3029. ((ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? FsFontSize2 : FsFontSize1).X,
  3030. ((ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) ? FsFontSize2 : FsFontSize1).Y);
  3031. }
  3032. ConsoleHeapFree(FontImage);
  3033. } else {
  3034. RIPMSG0(RIP_WARNING, "SetRAMFont: failed to allocate FontImage.");
  3035. }
  3036. }
  3037. }
  3038. if (ScreenBufPtr->Attributes & COMMON_LVB_SBCSDBCS) {
  3039. ScreenBufPtr += 2;
  3040. if (Length >= 1) {
  3041. Length -= 1;
  3042. } else {
  3043. break;
  3044. }
  3045. } else {
  3046. ScreenBufPtr++;
  3047. }
  3048. }
  3049. ConsoleHeapFree(StringBitmap);
  3050. /*
  3051. * Back to GDI font
  3052. */
  3053. SelectObject(ScreenInfo->Console->hDC, hOldFont);
  3054. return Status;
  3055. }
  3056. #ifdef i386
  3057. #if defined(FE_SB)
  3058. #define WWSB_NOFE
  3059. #include "_priv.h"
  3060. #undef WWSB_NOFE
  3061. #define WWSB_FE
  3062. #include "_priv.h"
  3063. #undef WWSB_FE
  3064. #endif // FE_SB
  3065. #endif // i386