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.

1740 lines
59 KiB

  1. /*++
  2. Copyright (c) 1985 - 1999, Microsoft Corporation
  3. Module Name:
  4. directio.c
  5. Abstract:
  6. This file implements the NT console direct I/O API
  7. Author:
  8. Therese Stowell (thereses) 6-Nov-1990
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #if defined(FE_SB)
  14. #define WWSB_FE
  15. #include "dispatch.h" // get the FE_ prototypes
  16. #undef WWSB_FE
  17. #pragma alloc_text(FE_TEXT, FE_TranslateInputToOem)
  18. #pragma alloc_text(FE_TEXT, FE_TranslateInputToUnicode)
  19. #pragma alloc_text(FE_TEXT, FE_TranslateOutputToOem)
  20. #pragma alloc_text(FE_TEXT, FE_TranslateOutputToOemUnicode)
  21. #pragma alloc_text(FE_TEXT, FE_TranslateOutputToUnicode)
  22. #pragma alloc_text(FE_TEXT, FE_TranslateOutputToAnsiUnicode)
  23. #endif
  24. #if defined(FE_SB)
  25. ULONG
  26. SB_TranslateInputToOem
  27. #else
  28. NTSTATUS
  29. TranslateInputToOem
  30. #endif
  31. (
  32. IN PCONSOLE_INFORMATION Console,
  33. IN OUT PINPUT_RECORD InputRecords,
  34. IN ULONG NumRecords
  35. )
  36. {
  37. ULONG i;
  38. DBGCHARS(("TranslateInputToOem\n"));
  39. for (i=0;i<NumRecords;i++) {
  40. if (InputRecords[i].EventType == KEY_EVENT) {
  41. InputRecords[i].Event.KeyEvent.uChar.AsciiChar = WcharToChar(
  42. Console->CP, InputRecords[i].Event.KeyEvent.uChar.UnicodeChar);
  43. }
  44. }
  45. #if defined(FE_SB)
  46. return NumRecords;
  47. #else
  48. return STATUS_SUCCESS;
  49. #endif
  50. }
  51. #if defined(FE_SB)
  52. ULONG
  53. FE_TranslateInputToOem(
  54. IN PCONSOLE_INFORMATION Console,
  55. IN OUT PINPUT_RECORD InputRecords,
  56. IN ULONG NumRecords, // in : ASCII byte count
  57. IN ULONG UnicodeLength, // in : Number of events (char count)
  58. OUT PINPUT_RECORD DbcsLeadInpRec
  59. )
  60. {
  61. ULONG i,j;
  62. PINPUT_RECORD TmpInpRec;
  63. BYTE AsciiDbcs[2];
  64. ULONG NumBytes;
  65. ASSERT(NumRecords >= UnicodeLength);
  66. TmpInpRec = ConsoleHeapAlloc(TMP_DBCS_TAG, NumRecords*sizeof(INPUT_RECORD));
  67. if (TmpInpRec == NULL)
  68. return 0;
  69. memcpy(TmpInpRec,InputRecords,NumRecords*sizeof(INPUT_RECORD));
  70. AsciiDbcs[1] = 0;
  71. for (i=0,j=0; i<UnicodeLength; i++,j++) {
  72. if (TmpInpRec[i].EventType == KEY_EVENT) {
  73. if (IsConsoleFullWidth(Console->hDC,
  74. Console->CP,TmpInpRec[i].Event.KeyEvent.uChar.UnicodeChar)) {
  75. NumBytes = sizeof(AsciiDbcs);
  76. ConvertToOem(Console->CP,
  77. &TmpInpRec[i].Event.KeyEvent.uChar.UnicodeChar,
  78. 1,
  79. &AsciiDbcs[0],
  80. NumBytes
  81. );
  82. if (IsDBCSLeadByteConsole(AsciiDbcs[0],&Console->CPInfo)) {
  83. if (j < NumRecords-1) { // -1 is safe DBCS in buffer
  84. InputRecords[j] = TmpInpRec[i];
  85. InputRecords[j].Event.KeyEvent.uChar.UnicodeChar = 0;
  86. InputRecords[j].Event.KeyEvent.uChar.AsciiChar = AsciiDbcs[0];
  87. j++;
  88. InputRecords[j] = TmpInpRec[i];
  89. InputRecords[j].Event.KeyEvent.uChar.UnicodeChar = 0;
  90. InputRecords[j].Event.KeyEvent.uChar.AsciiChar = AsciiDbcs[1];
  91. AsciiDbcs[1] = 0;
  92. }
  93. else if (j == NumRecords-1) {
  94. InputRecords[j] = TmpInpRec[i];
  95. InputRecords[j].Event.KeyEvent.uChar.UnicodeChar = 0;
  96. InputRecords[j].Event.KeyEvent.uChar.AsciiChar = AsciiDbcs[0];
  97. j++;
  98. break;
  99. }
  100. else {
  101. AsciiDbcs[1] = 0;
  102. break;
  103. }
  104. }
  105. else {
  106. InputRecords[j] = TmpInpRec[i];
  107. InputRecords[j].Event.KeyEvent.uChar.UnicodeChar = 0;
  108. InputRecords[j].Event.KeyEvent.uChar.AsciiChar = AsciiDbcs[0];
  109. AsciiDbcs[1] = 0;
  110. }
  111. }
  112. else {
  113. InputRecords[j] = TmpInpRec[i];
  114. ConvertToOem(Console->CP,
  115. &InputRecords[j].Event.KeyEvent.uChar.UnicodeChar,
  116. 1,
  117. &InputRecords[j].Event.KeyEvent.uChar.AsciiChar,
  118. 1
  119. );
  120. }
  121. }
  122. }
  123. if (DbcsLeadInpRec) {
  124. if (AsciiDbcs[1]) {
  125. *DbcsLeadInpRec = TmpInpRec[i];
  126. DbcsLeadInpRec->Event.KeyEvent.uChar.AsciiChar = AsciiDbcs[1];
  127. }
  128. else {
  129. RtlZeroMemory(DbcsLeadInpRec,sizeof(INPUT_RECORD));
  130. }
  131. }
  132. ConsoleHeapFree(TmpInpRec);
  133. return j;
  134. }
  135. #endif
  136. #if defined(FE_SB)
  137. ULONG
  138. SB_TranslateInputToUnicode
  139. #else
  140. NTSTATUS
  141. TranslateInputToUnicode
  142. #endif
  143. (
  144. IN PCONSOLE_INFORMATION Console,
  145. IN OUT PINPUT_RECORD InputRecords,
  146. IN ULONG NumRecords
  147. )
  148. {
  149. ULONG i;
  150. DBGCHARS(("TranslateInputToUnicode\n"));
  151. for (i=0;i<NumRecords;i++) {
  152. if (InputRecords[i].EventType == KEY_EVENT) {
  153. #if defined(FE_SB)
  154. InputRecords[i].Event.KeyEvent.uChar.UnicodeChar = SB_CharToWchar(
  155. Console->CP, InputRecords[i].Event.KeyEvent.uChar.AsciiChar);
  156. #else
  157. InputRecords[i].Event.KeyEvent.uChar.UnicodeChar = CharToWchar(
  158. Console->CP, InputRecords[i].Event.KeyEvent.uChar.AsciiChar);
  159. #endif
  160. }
  161. }
  162. #if defined(FE_SB)
  163. return i;
  164. #else
  165. return STATUS_SUCCESS;
  166. #endif
  167. }
  168. #if defined(FE_SB)
  169. ULONG
  170. FE_TranslateInputToUnicode(
  171. IN PCONSOLE_INFORMATION Console,
  172. IN OUT PINPUT_RECORD InputRecords,
  173. IN ULONG NumRecords,
  174. IN OUT PINPUT_RECORD DBCSLeadByte
  175. )
  176. {
  177. ULONG i,j;
  178. INPUT_RECORD AsciiDbcs[2];
  179. CHAR Strings[2];
  180. WCHAR UnicodeDbcs[2];
  181. PWCHAR Uni;
  182. ULONG NumBytes;
  183. if (DBCSLeadByte->Event.KeyEvent.uChar.AsciiChar) {
  184. AsciiDbcs[0] = *DBCSLeadByte;
  185. Strings[0] = DBCSLeadByte->Event.KeyEvent.uChar.AsciiChar;
  186. }
  187. else{
  188. RtlZeroMemory(AsciiDbcs,sizeof(AsciiDbcs));
  189. }
  190. for (i=j=0; i<NumRecords; i++) {
  191. if (InputRecords[i].EventType == KEY_EVENT) {
  192. if (AsciiDbcs[0].Event.KeyEvent.uChar.AsciiChar) {
  193. AsciiDbcs[1] = InputRecords[i];
  194. Strings[1] = InputRecords[i].Event.KeyEvent.uChar.AsciiChar;
  195. NumBytes = sizeof(Strings);
  196. NumBytes = ConvertInputToUnicode(Console->CP,
  197. &Strings[0],
  198. NumBytes,
  199. &UnicodeDbcs[0],
  200. NumBytes);
  201. Uni = &UnicodeDbcs[0];
  202. while (NumBytes--) {
  203. InputRecords[j] = AsciiDbcs[0];
  204. InputRecords[j].Event.KeyEvent.uChar.UnicodeChar = *Uni++;
  205. j++;
  206. }
  207. RtlZeroMemory(AsciiDbcs,sizeof(AsciiDbcs));
  208. if (DBCSLeadByte->Event.KeyEvent.uChar.AsciiChar)
  209. RtlZeroMemory(DBCSLeadByte,sizeof(INPUT_RECORD));
  210. }
  211. else if (IsDBCSLeadByteConsole(InputRecords[i].Event.KeyEvent.uChar.AsciiChar,&Console->CPInfo)) {
  212. if (i < NumRecords-1) {
  213. AsciiDbcs[0] = InputRecords[i];
  214. Strings[0] = InputRecords[i].Event.KeyEvent.uChar.AsciiChar;
  215. }
  216. else {
  217. *DBCSLeadByte = InputRecords[i];
  218. break;
  219. }
  220. }
  221. else {
  222. CHAR c;
  223. InputRecords[j] = InputRecords[i];
  224. c = InputRecords[i].Event.KeyEvent.uChar.AsciiChar;
  225. ConvertInputToUnicode(Console->CP,
  226. &c,
  227. 1,
  228. &InputRecords[j].Event.KeyEvent.uChar.UnicodeChar,
  229. 1);
  230. j++;
  231. }
  232. }
  233. else {
  234. InputRecords[j++] = InputRecords[i];
  235. }
  236. }
  237. return j;
  238. }
  239. #endif
  240. BOOLEAN
  241. DirectReadWaitRoutine(
  242. IN PLIST_ENTRY WaitQueue,
  243. IN PCSR_THREAD WaitingThread,
  244. IN PCSR_API_MSG WaitReplyMessage,
  245. IN PVOID WaitParameter,
  246. IN PVOID SatisfyParameter1,
  247. IN PVOID SatisfyParameter2,
  248. IN ULONG WaitFlags
  249. )
  250. /*++
  251. Routine Description:
  252. This routine is called to complete a direct read that blocked in
  253. ReadInputBuffer. The context of the read was saved in the DirectReadData
  254. structure. This routine is called when events have been written to
  255. the input buffer. It is called in the context of the writing thread.
  256. Arguments:
  257. WaitQueue - Pointer to queue containing wait block.
  258. WaitingThread - Pointer to waiting thread.
  259. WaitReplyMessage - Pointer to reply message to return to dll when
  260. read is completed.
  261. DirectReadData - Context of read.
  262. SatisfyParameter1 - Unused.
  263. SatisfyParameter2 - Unused.
  264. WaitFlags - Flags indicating status of wait.
  265. Return Value:
  266. --*/
  267. {
  268. PCONSOLE_GETCONSOLEINPUT_MSG a;
  269. PINPUT_RECORD Buffer;
  270. NTSTATUS Status;
  271. PCONSOLE_INFORMATION Console;
  272. PDIRECT_READ_DATA DirectReadData;
  273. PHANDLE_DATA HandleData;
  274. BOOLEAN RetVal = TRUE;
  275. #if defined(FE_SB)
  276. BOOLEAN fAddDbcsLead = FALSE;
  277. PDWORD nLength;
  278. #endif
  279. a = (PCONSOLE_GETCONSOLEINPUT_MSG)&WaitReplyMessage->u.ApiMessageData;
  280. DirectReadData = (PDIRECT_READ_DATA) WaitParameter;
  281. Status = DereferenceIoHandleNoCheck(DirectReadData->ProcessData,
  282. DirectReadData->HandleIndex,
  283. &HandleData
  284. );
  285. ASSERT (NT_SUCCESS(Status));
  286. if (!NT_SUCCESS(Status)) {
  287. return TRUE;
  288. }
  289. //
  290. // see if this routine was called by CloseInputHandle. if it
  291. // was, see if this wait block corresponds to the dying handle.
  292. // if it doesn't, just return.
  293. //
  294. if (SatisfyParameter1 != NULL &&
  295. SatisfyParameter1 != HandleData) {
  296. return FALSE;
  297. }
  298. //
  299. // if ctrl-c or ctrl-break was seen, ignore it.
  300. //
  301. if ((ULONG_PTR)SatisfyParameter2 & (CONSOLE_CTRL_C_SEEN | CONSOLE_CTRL_BREAK_SEEN)) {
  302. return FALSE;
  303. }
  304. Console = DirectReadData->Console;
  305. #if defined(FE_SB)
  306. if (CONSOLE_IS_DBCS_CP(Console) && !a->Unicode) {
  307. if (HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte.Event.KeyEvent.uChar.AsciiChar) {
  308. if (a->NumRecords == 1) {
  309. Buffer = &a->Record[0];
  310. *Buffer = HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte;
  311. if (!(a->Flags & CONSOLE_READ_NOREMOVE))
  312. RtlZeroMemory(&HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte,sizeof(INPUT_RECORD));
  313. return TRUE;
  314. }
  315. }
  316. }
  317. #endif
  318. //
  319. // this routine should be called by a thread owning the same
  320. // lock on the same console as we're reading from.
  321. //
  322. try {
  323. LockReadCount(HandleData);
  324. ASSERT(HandleData->InputReadData->ReadCount);
  325. HandleData->InputReadData->ReadCount -= 1;
  326. UnlockReadCount(HandleData);
  327. //
  328. // see if called by CsrDestroyProcess or CsrDestroyThread
  329. // via CsrNotifyWaitBlock. if so, just decrement the ReadCount
  330. // and return.
  331. //
  332. if (WaitFlags & CSR_PROCESS_TERMINATING) {
  333. Status = STATUS_THREAD_IS_TERMINATING;
  334. leave;
  335. }
  336. //
  337. // We must see if we were woken up because the handle is being
  338. // closed. if so, we decrement the read count. if it goes to
  339. // zero, we wake up the close thread. otherwise, we wake up any
  340. // other thread waiting for data.
  341. //
  342. if (HandleData->InputReadData->InputHandleFlags & HANDLE_CLOSING) {
  343. ASSERT (SatisfyParameter1 == HandleData);
  344. Status = STATUS_ALERTED;
  345. leave;
  346. }
  347. //
  348. // if we get to here, this routine was called either by the input
  349. // thread or a write routine. both of these callers grab the
  350. // current console lock.
  351. //
  352. //
  353. // this routine should be called by a thread owning the same
  354. // lock on the same console as we're reading from.
  355. //
  356. ASSERT (ConsoleLocked(Console));
  357. //
  358. // if the read buffer is contained within the message, we need to
  359. // reset the buffer pointer because the message copied from the
  360. // stack to heap space when the wait block was created.
  361. //
  362. if (a->NumRecords <= INPUT_RECORD_BUFFER_SIZE) {
  363. Buffer = a->Record;
  364. } else {
  365. Buffer = a->BufPtr;
  366. }
  367. #if defined(FE_SB)
  368. if (CONSOLE_IS_DBCS_CP(Console) ) {
  369. Console->ReadConInpNumBytesUnicode = a->NumRecords;
  370. if (!a->Unicode) {
  371. /*
  372. * ASCII : a->NumRecords is ASCII byte count
  373. */
  374. if (HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte.Event.KeyEvent.uChar.AsciiChar) {
  375. /*
  376. * Saved DBCS Traling byte
  377. */
  378. if (Console->ReadConInpNumBytesUnicode != 1) {
  379. Console->ReadConInpNumBytesUnicode--;
  380. Buffer++;
  381. fAddDbcsLead = TRUE;
  382. nLength = &Console->ReadConInpNumBytesUnicode;
  383. }
  384. else {
  385. ASSERT(Console->ReadConInpNumBytesUnicode==1);
  386. }
  387. }
  388. else {
  389. nLength = &Console->ReadConInpNumBytesUnicode;
  390. }
  391. }
  392. else {
  393. nLength = &a->NumRecords;
  394. }
  395. }
  396. else {
  397. nLength = &a->NumRecords;
  398. }
  399. Status = ReadInputBuffer(DirectReadData->InputInfo,
  400. Buffer,
  401. nLength,
  402. !!(a->Flags & CONSOLE_READ_NOREMOVE),
  403. !(a->Flags & CONSOLE_READ_NOWAIT),
  404. FALSE,
  405. Console,
  406. HandleData,
  407. WaitReplyMessage,
  408. DirectReadWaitRoutine,
  409. &DirectReadData,
  410. sizeof(DirectReadData),
  411. TRUE,
  412. a->Unicode
  413. );
  414. #else
  415. Status = ReadInputBuffer(DirectReadData->InputInfo,
  416. Buffer,
  417. &a->NumRecords,
  418. !!(a->Flags & CONSOLE_READ_NOREMOVE),
  419. !(a->Flags & CONSOLE_READ_NOWAIT),
  420. FALSE,
  421. Console,
  422. HandleData,
  423. WaitReplyMessage,
  424. DirectReadWaitRoutine,
  425. &DirectReadData,
  426. sizeof(DirectReadData),
  427. TRUE
  428. );
  429. #endif
  430. if (Status == CONSOLE_STATUS_WAIT) {
  431. RetVal = FALSE;
  432. }
  433. } finally {
  434. //
  435. // if the read was completed (status != wait), free the direct read
  436. // data.
  437. //
  438. if (Status != CONSOLE_STATUS_WAIT) {
  439. if (Status == STATUS_SUCCESS && !a->Unicode) {
  440. #if defined(FE_SB)
  441. if (CONSOLE_IS_DBCS_CP(Console) ) {
  442. if (fAddDbcsLead &&
  443. HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte.Event.KeyEvent.uChar.AsciiChar) {
  444. a->NumRecords--;
  445. }
  446. a->NumRecords = FE_TranslateInputToOem(
  447. Console,
  448. Buffer,
  449. a->NumRecords,
  450. Console->ReadConInpNumBytesUnicode,
  451. a->Flags & CONSOLE_READ_NOREMOVE ?
  452. NULL :
  453. &HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte);
  454. if (fAddDbcsLead &&
  455. HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte.Event.KeyEvent.uChar.AsciiChar) {
  456. *(Buffer-1) = HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte;
  457. if (!(a->Flags & CONSOLE_READ_NOREMOVE))
  458. RtlZeroMemory(&HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte,sizeof(INPUT_RECORD));
  459. a->NumRecords++;
  460. Buffer--;
  461. }
  462. }
  463. else {
  464. TranslateInputToOem(Console,
  465. Buffer,
  466. a->NumRecords,
  467. Console->ReadConInpNumBytesUnicode,
  468. a->Flags & CONSOLE_READ_NOREMOVE ?
  469. NULL :
  470. &HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte
  471. );
  472. }
  473. #else
  474. TranslateInputToOem(Console,
  475. Buffer,
  476. a->NumRecords
  477. );
  478. #endif
  479. }
  480. WaitReplyMessage->ReturnValue = Status;
  481. ConsoleHeapFree(DirectReadData);
  482. }
  483. }
  484. return RetVal;
  485. //
  486. // satisfy the unreferenced parameter warnings.
  487. //
  488. UNREFERENCED_PARAMETER(WaitQueue);
  489. UNREFERENCED_PARAMETER(WaitingThread);
  490. UNREFERENCED_PARAMETER(SatisfyParameter2);
  491. }
  492. ULONG
  493. SrvGetConsoleInput(
  494. IN OUT PCSR_API_MSG m,
  495. IN OUT PCSR_REPLY_STATUS ReplyStatus
  496. )
  497. /*++
  498. Routine Description:
  499. This routine reads or peeks input events. In both cases, the events
  500. are copied to the user's buffer. In the read case they are removed
  501. from the input buffer and in the peek case they are not.
  502. Arguments:
  503. m - message containing api parameters
  504. ReplyStatus - Indicates whether to reply to the dll port.
  505. Return Value:
  506. --*/
  507. {
  508. PCONSOLE_GETCONSOLEINPUT_MSG a = (PCONSOLE_GETCONSOLEINPUT_MSG)&m->u.ApiMessageData;
  509. PCONSOLE_INFORMATION Console;
  510. PHANDLE_DATA HandleData;
  511. NTSTATUS Status;
  512. PINPUT_RECORD Buffer;
  513. DIRECT_READ_DATA DirectReadData;
  514. #ifdef FE_SB
  515. BOOLEAN fAddDbcsLead = FALSE;
  516. PDWORD nLength;
  517. #endif
  518. if (a->Flags & ~CONSOLE_READ_VALID) {
  519. return (ULONG)STATUS_INVALID_PARAMETER;
  520. }
  521. Status = ApiPreamble(a->ConsoleHandle,
  522. &Console
  523. );
  524. if (!NT_SUCCESS(Status)) {
  525. return Status;
  526. }
  527. Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
  528. a->InputHandle,
  529. CONSOLE_INPUT_HANDLE,
  530. GENERIC_READ,
  531. &HandleData
  532. );
  533. if (!NT_SUCCESS(Status)) {
  534. a->NumRecords = 0;
  535. } else {
  536. if (a->NumRecords <= INPUT_RECORD_BUFFER_SIZE) {
  537. Buffer = a->Record;
  538. } else {
  539. Buffer = a->BufPtr;
  540. if (!CsrValidateMessageBuffer(m, &a->BufPtr, a->NumRecords, sizeof(*Buffer))) {
  541. UnlockConsole(Console);
  542. return STATUS_INVALID_PARAMETER;
  543. }
  544. }
  545. //
  546. // if we're reading, wait for data. if we're peeking, don't.
  547. //
  548. DirectReadData.InputInfo = HandleData->Buffer.InputBuffer;
  549. DirectReadData.Console = Console;
  550. DirectReadData.ProcessData = CONSOLE_PERPROCESSDATA();
  551. DirectReadData.HandleIndex = HANDLE_TO_INDEX(a->InputHandle);
  552. #if defined(FE_SB)
  553. if (CONSOLE_IS_DBCS_CP(Console) ) {
  554. Console->ReadConInpNumBytesUnicode = a->NumRecords;
  555. if (!a->Unicode) {
  556. /*
  557. * ASCII : a->NumRecords is ASCII byte count
  558. */
  559. if (HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte.Event.KeyEvent.uChar.AsciiChar) {
  560. /*
  561. * Saved DBCS Traling byte
  562. */
  563. *Buffer = HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte;
  564. if (!(a->Flags & CONSOLE_READ_NOREMOVE))
  565. RtlZeroMemory(&HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte,sizeof(INPUT_RECORD));
  566. if (Console->ReadConInpNumBytesUnicode == 1) {
  567. UnlockConsole(Console);
  568. return STATUS_SUCCESS;
  569. }
  570. else {
  571. Console->ReadConInpNumBytesUnicode--;
  572. Buffer++;
  573. fAddDbcsLead = TRUE;
  574. nLength = &Console->ReadConInpNumBytesUnicode;
  575. }
  576. }
  577. else {
  578. nLength = &Console->ReadConInpNumBytesUnicode;
  579. }
  580. }
  581. else {
  582. nLength = &a->NumRecords;
  583. }
  584. }
  585. else {
  586. nLength = &a->NumRecords;
  587. }
  588. Status = ReadInputBuffer(HandleData->Buffer.InputBuffer,
  589. Buffer,
  590. nLength,
  591. !!(a->Flags & CONSOLE_READ_NOREMOVE),
  592. !(a->Flags & CONSOLE_READ_NOWAIT),
  593. FALSE,
  594. Console,
  595. HandleData,
  596. m,
  597. DirectReadWaitRoutine,
  598. &DirectReadData,
  599. sizeof(DirectReadData),
  600. FALSE,
  601. a->Unicode
  602. );
  603. if (Status == CONSOLE_STATUS_WAIT) {
  604. *ReplyStatus = CsrReplyPending;
  605. } else if (!a->Unicode) {
  606. a->NumRecords = TranslateInputToOem(Console,
  607. Buffer,
  608. fAddDbcsLead ?
  609. a->NumRecords-1 :
  610. a->NumRecords,
  611. Console->ReadConInpNumBytesUnicode,
  612. a->Flags & CONSOLE_READ_NOREMOVE ?
  613. NULL :
  614. &HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte
  615. );
  616. if (fAddDbcsLead)
  617. {
  618. a->NumRecords++;
  619. Buffer--;
  620. }
  621. }
  622. #else
  623. Status = ReadInputBuffer(HandleData->Buffer.InputBuffer,
  624. Buffer,
  625. &a->NumRecords,
  626. !!(a->Flags & CONSOLE_READ_NOREMOVE),
  627. !(a->Flags & CONSOLE_READ_NOWAIT),
  628. FALSE,
  629. Console,
  630. HandleData,
  631. m,
  632. DirectReadWaitRoutine,
  633. &DirectReadData,
  634. sizeof(DirectReadData),
  635. FALSE
  636. );
  637. if (Status == CONSOLE_STATUS_WAIT) {
  638. *ReplyStatus = CsrReplyPending;
  639. } else if (!a->Unicode) {
  640. TranslateInputToOem(Console,
  641. Buffer,
  642. a->NumRecords
  643. );
  644. }
  645. #endif
  646. }
  647. UnlockConsole(Console);
  648. return Status;
  649. }
  650. ULONG
  651. SrvWriteConsoleInput(
  652. IN OUT PCSR_API_MSG m,
  653. IN OUT PCSR_REPLY_STATUS ReplyStatus
  654. )
  655. {
  656. PCONSOLE_WRITECONSOLEINPUT_MSG a = (PCONSOLE_WRITECONSOLEINPUT_MSG)&m->u.ApiMessageData;
  657. PCONSOLE_INFORMATION Console;
  658. PHANDLE_DATA HandleData;
  659. NTSTATUS Status;
  660. PINPUT_RECORD Buffer;
  661. Status = ApiPreamble(a->ConsoleHandle,
  662. &Console
  663. );
  664. if (!NT_SUCCESS(Status)) {
  665. return Status;
  666. }
  667. Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
  668. a->InputHandle,
  669. CONSOLE_INPUT_HANDLE,
  670. GENERIC_WRITE,
  671. &HandleData
  672. );
  673. if (!NT_SUCCESS(Status)) {
  674. a->NumRecords = 0;
  675. } else {
  676. if (a->NumRecords <= INPUT_RECORD_BUFFER_SIZE) {
  677. Buffer = a->Record;
  678. } else {
  679. Buffer = a->BufPtr;
  680. if (!CsrValidateMessageBuffer(m, &a->BufPtr, a->NumRecords, sizeof(*Buffer))) {
  681. UnlockConsole(Console);
  682. return STATUS_INVALID_PARAMETER;
  683. }
  684. }
  685. if (!a->Unicode) {
  686. #if defined(FE_SB)
  687. a->NumRecords = TranslateInputToUnicode(Console,
  688. Buffer,
  689. a->NumRecords,
  690. &HandleData->Buffer.InputBuffer->WriteConInpDbcsLeadByte[0]
  691. );
  692. #else
  693. TranslateInputToUnicode(Console,
  694. Buffer,
  695. a->NumRecords
  696. );
  697. #endif
  698. }
  699. if (a->Append) {
  700. a->NumRecords = WriteInputBuffer(Console,
  701. HandleData->Buffer.InputBuffer,
  702. Buffer,
  703. a->NumRecords
  704. );
  705. } else {
  706. a->NumRecords = PrependInputBuffer(Console,
  707. HandleData->Buffer.InputBuffer,
  708. Buffer,
  709. a->NumRecords
  710. );
  711. }
  712. }
  713. UnlockConsole(Console);
  714. return((ULONG) Status);
  715. UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
  716. }
  717. NTSTATUS
  718. SB_TranslateOutputToOem
  719. (
  720. IN PCONSOLE_INFORMATION Console,
  721. IN OUT PCHAR_INFO OutputBuffer,
  722. IN COORD Size
  723. )
  724. // this is used when the app reads oem from the output buffer
  725. // the app wants real OEM characters. We have real Unicode or UnicodeOem.
  726. {
  727. SHORT i,j;
  728. UINT Codepage;
  729. DBGCHARS(("SB_TranslateOutputToOem(Console=%lx, OutputBuffer=%lx)\n",
  730. Console, OutputBuffer));
  731. j = Size.X * Size.Y;
  732. if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) &&
  733. ((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) {
  734. #if defined(FE_SB)
  735. if (CONSOLE_IS_DBCS_ENABLED() &&
  736. Console->OutputCP != WINDOWSCP ) {
  737. Codepage = USACP;
  738. }
  739. else
  740. #endif
  741. // we have UnicodeOem characters
  742. Codepage = WINDOWSCP;
  743. } else {
  744. // we have real Unicode characters
  745. Codepage = Console->OutputCP; // BUG FIX by KazuM Jun.2.97
  746. }
  747. for (i=0;i<j;i++,OutputBuffer++) {
  748. OutputBuffer->Char.AsciiChar = WcharToChar(Codepage,
  749. OutputBuffer->Char.UnicodeChar);
  750. }
  751. return STATUS_SUCCESS;
  752. }
  753. #if defined(FE_SB)
  754. NTSTATUS
  755. FE_TranslateOutputToOem(
  756. IN PCONSOLE_INFORMATION Console,
  757. IN OUT PCHAR_INFO OutputBuffer,
  758. IN COORD Size
  759. )
  760. // this is used when the app reads oem from the output buffer
  761. // the app wants real OEM characters. We have real Unicode or UnicodeOem.
  762. {
  763. SHORT i,j;
  764. UINT Codepage;
  765. PCHAR_INFO TmpBuffer,SaveBuffer;
  766. CHAR AsciiDbcs[2];
  767. ULONG NumBytes;
  768. DBGCHARS(("FE_TranslateOutputToOem(Console=%lx, OutputBuffer=%lx)\n",
  769. Console, OutputBuffer));
  770. SaveBuffer = TmpBuffer =
  771. ConsoleHeapAlloc(TMP_DBCS_TAG, Size.X * Size.Y * sizeof(CHAR_INFO) * 2);
  772. if (TmpBuffer == NULL) {
  773. return STATUS_NO_MEMORY;
  774. }
  775. if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) &&
  776. ((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) {
  777. if (CONSOLE_IS_DBCS_ENABLED() &&
  778. Console->OutputCP != WINDOWSCP ) {
  779. Codepage = USACP;
  780. }
  781. else
  782. // we have UnicodeOem characters
  783. Codepage = WINDOWSCP;
  784. } else {
  785. // we have real Unicode characters
  786. Codepage = Console->OutputCP;
  787. }
  788. memcpy(TmpBuffer,OutputBuffer,Size.X * Size.Y * sizeof(CHAR_INFO));
  789. for (i=0; i < Size.Y; i++) {
  790. for (j=0; j < Size.X; j++) {
  791. if (TmpBuffer->Attributes & COMMON_LVB_LEADING_BYTE) {
  792. if (j < Size.X-1) { // -1 is safe DBCS in buffer
  793. j++;
  794. NumBytes = sizeof(AsciiDbcs);
  795. NumBytes = ConvertOutputToOem(Codepage,
  796. &TmpBuffer->Char.UnicodeChar,
  797. 1,
  798. &AsciiDbcs[0],
  799. NumBytes);
  800. OutputBuffer->Char.AsciiChar = AsciiDbcs[0];
  801. OutputBuffer->Attributes = TmpBuffer->Attributes;
  802. OutputBuffer++;
  803. TmpBuffer++;
  804. OutputBuffer->Char.AsciiChar = AsciiDbcs[1];
  805. OutputBuffer->Attributes = TmpBuffer->Attributes;
  806. OutputBuffer++;
  807. TmpBuffer++;
  808. }
  809. else {
  810. OutputBuffer->Char.AsciiChar = ' ';
  811. OutputBuffer->Attributes = TmpBuffer->Attributes & ~COMMON_LVB_SBCSDBCS;
  812. OutputBuffer++;
  813. TmpBuffer++;
  814. }
  815. }
  816. else if (!(TmpBuffer->Attributes & COMMON_LVB_SBCSDBCS)){
  817. ConvertOutputToOem(Codepage,
  818. &TmpBuffer->Char.UnicodeChar,
  819. 1,
  820. &OutputBuffer->Char.AsciiChar,
  821. 1);
  822. OutputBuffer->Attributes = TmpBuffer->Attributes;
  823. OutputBuffer++;
  824. TmpBuffer++;
  825. }
  826. }
  827. }
  828. ConsoleHeapFree(SaveBuffer);
  829. return STATUS_SUCCESS;
  830. }
  831. #endif
  832. NTSTATUS
  833. SB_TranslateOutputToOemUnicode
  834. (
  835. IN PCONSOLE_INFORMATION Console,
  836. IN OUT PCHAR_INFO OutputBuffer,
  837. IN COORD Size
  838. )
  839. // this is used when the app reads unicode from the output buffer
  840. {
  841. SHORT i,j;
  842. DBGCHARS(("SB_TranslateOutputToOemUnicode\n"));
  843. j = Size.X * Size.Y;
  844. for (i=0;i<j;i++,OutputBuffer++) {
  845. FalseUnicodeToRealUnicode(&OutputBuffer->Char.UnicodeChar,
  846. 1,
  847. Console->OutputCP
  848. );
  849. }
  850. return STATUS_SUCCESS;
  851. }
  852. #if defined(FE_SB)
  853. NTSTATUS
  854. FE_TranslateOutputToOemUnicode(
  855. IN PCONSOLE_INFORMATION Console,
  856. IN OUT PCHAR_INFO OutputBuffer,
  857. IN COORD Size,
  858. IN BOOL fRemoveDbcsMark
  859. )
  860. // this is used when the app reads unicode from the output buffer
  861. {
  862. SHORT i,j;
  863. DBGCHARS(("FE_TranslateOutputToOemUnicode\n"));
  864. j = Size.X * Size.Y;
  865. if (fRemoveDbcsMark)
  866. RemoveDbcsMarkCell(OutputBuffer,OutputBuffer,j);
  867. for (i=0;i<j;i++,OutputBuffer++) {
  868. FalseUnicodeToRealUnicode(&OutputBuffer->Char.UnicodeChar,
  869. 1,
  870. Console->OutputCP
  871. );
  872. }
  873. return STATUS_SUCCESS;
  874. }
  875. #endif
  876. NTSTATUS
  877. SB_TranslateOutputToUnicode
  878. (
  879. IN PCONSOLE_INFORMATION Console,
  880. IN OUT PCHAR_INFO OutputBuffer,
  881. IN COORD Size
  882. )
  883. // this is used when the app writes oem to the output buffer
  884. // we want UnicodeOem or Unicode in the buffer, depending on font & fullscreen
  885. {
  886. SHORT i,j;
  887. UINT Codepage;
  888. DBGCHARS(("SB_TranslateOutputToUnicode %lx %lx (%lx,%lx)\n",
  889. Console, OutputBuffer, Size.X, Size.Y));
  890. j = Size.X * Size.Y;
  891. if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) &&
  892. ((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) {
  893. #if defined(FE_SB)
  894. if (CONSOLE_IS_DBCS_ENABLED() &&
  895. (Console->OutputCP != WINDOWSCP) ) {
  896. Codepage = USACP;
  897. }
  898. else
  899. #endif
  900. // we want UnicodeOem characters
  901. Codepage = WINDOWSCP;
  902. } else {
  903. // we want real Unicode characters
  904. Codepage = Console->OutputCP; // BUG FIX by KazuM Jun.2.97
  905. }
  906. for (i = 0; i < j; i++, OutputBuffer++) {
  907. #if defined(FE_SB)
  908. OutputBuffer->Char.UnicodeChar = SB_CharToWchar(
  909. Codepage, OutputBuffer->Char.AsciiChar);
  910. #else
  911. OutputBuffer->Char.UnicodeChar = CharToWchar(
  912. Codepage, OutputBuffer->Char.AsciiChar);
  913. #endif
  914. }
  915. return STATUS_SUCCESS;
  916. }
  917. #if defined(FE_SB)
  918. NTSTATUS
  919. FE_TranslateOutputToUnicode(
  920. IN PCONSOLE_INFORMATION Console,
  921. IN OUT PCHAR_INFO OutputBuffer,
  922. IN COORD Size
  923. )
  924. // this is used when the app writes oem to the output buffer
  925. // we want UnicodeOem or Unicode in the buffer, depending on font & fullscreen
  926. {
  927. SHORT i,j;
  928. UINT Codepage;
  929. CHAR AsciiDbcs[2];
  930. WCHAR UnicodeDbcs[2];
  931. DBGCHARS(("FE_TranslateOutputToUnicode %lx %lx (%lx,%lx)\n",
  932. Console, OutputBuffer, Size.X, Size.Y));
  933. if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) &&
  934. ((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) {
  935. if (CONSOLE_IS_DBCS_ENABLED() &&
  936. (Console->OutputCP != WINDOWSCP) ) {
  937. Codepage = USACP;
  938. }
  939. else
  940. // we want UnicodeOem characters
  941. Codepage = WINDOWSCP;
  942. } else {
  943. // we want real Unicode characters
  944. Codepage = Console->OutputCP;
  945. }
  946. for (i=0; i < Size.Y; i++) {
  947. for (j=0; j < Size.X; j++) {
  948. OutputBuffer->Attributes &= ~COMMON_LVB_SBCSDBCS;
  949. if (IsDBCSLeadByteConsole(OutputBuffer->Char.AsciiChar,&Console->OutputCPInfo)) {
  950. if (j < Size.X-1) { // -1 is safe DBCS in buffer
  951. j++;
  952. AsciiDbcs[0] = OutputBuffer->Char.AsciiChar;
  953. AsciiDbcs[1] = (OutputBuffer+1)->Char.AsciiChar;
  954. ConvertOutputToUnicode(Codepage,
  955. &AsciiDbcs[0],
  956. 2,
  957. &UnicodeDbcs[0],
  958. 2);
  959. OutputBuffer->Char.UnicodeChar = UnicodeDbcs[0];
  960. OutputBuffer->Attributes |= COMMON_LVB_LEADING_BYTE;
  961. OutputBuffer++;
  962. OutputBuffer->Char.UnicodeChar = UNICODE_DBCS_PADDING;
  963. OutputBuffer->Attributes &= ~COMMON_LVB_SBCSDBCS;
  964. OutputBuffer->Attributes |= COMMON_LVB_TRAILING_BYTE;
  965. OutputBuffer++;
  966. }
  967. else {
  968. OutputBuffer->Char.UnicodeChar = UNICODE_SPACE;
  969. OutputBuffer++;
  970. }
  971. }
  972. else {
  973. CHAR c;
  974. c=OutputBuffer->Char.AsciiChar;
  975. ConvertOutputToUnicode(Codepage,
  976. &c,
  977. 1,
  978. &OutputBuffer->Char.UnicodeChar,
  979. 1);
  980. OutputBuffer++;
  981. }
  982. }
  983. }
  984. return STATUS_SUCCESS;
  985. }
  986. #endif
  987. NTSTATUS
  988. SB_TranslateOutputToAnsiUnicode (
  989. IN PCONSOLE_INFORMATION Console,
  990. IN OUT PCHAR_INFO OutputBuffer,
  991. IN COORD Size
  992. )
  993. // this is used when the app writes unicode to the output buffer
  994. {
  995. SHORT i,j;
  996. DBGCHARS(("TranslateOutputToAnsiUnicode\n"));
  997. j = Size.X * Size.Y;
  998. for (i=0;i<j;i++,OutputBuffer++) {
  999. RealUnicodeToFalseUnicode(&OutputBuffer->Char.UnicodeChar,
  1000. 1,
  1001. Console->OutputCP
  1002. );
  1003. }
  1004. return STATUS_SUCCESS;
  1005. }
  1006. NTSTATUS
  1007. FE_TranslateOutputToAnsiUnicodeInternal(
  1008. IN PCONSOLE_INFORMATION Console,
  1009. IN OUT PCHAR_INFO OutputBuffer,
  1010. IN COORD Size,
  1011. IN OUT PCHAR_INFO OutputBufferR,
  1012. IN BOOL fRealUnicodeToFalseUnicode
  1013. )
  1014. // this is used when the app writes unicode to the output buffer
  1015. {
  1016. SHORT i,j;
  1017. DBGCHARS(("TranslateOutputToAnsiUnicode\n"));
  1018. for (i=0; i < Size.Y; i++) {
  1019. for (j=0; j < Size.X; j++) {
  1020. WCHAR wch = OutputBuffer->Char.UnicodeChar;
  1021. if (fRealUnicodeToFalseUnicode) {
  1022. RealUnicodeToFalseUnicode(&OutputBuffer->Char.UnicodeChar,
  1023. 1,
  1024. Console->OutputCP
  1025. );
  1026. }
  1027. if (OutputBufferR) {
  1028. OutputBufferR->Attributes = OutputBuffer->Attributes & ~COMMON_LVB_SBCSDBCS;
  1029. if (IsConsoleFullWidth(Console->hDC,
  1030. Console->OutputCP,OutputBuffer->Char.UnicodeChar)) {
  1031. if (j == Size.X-1){
  1032. OutputBufferR->Char.UnicodeChar = UNICODE_SPACE;
  1033. }
  1034. else{
  1035. OutputBufferR->Char.UnicodeChar = OutputBuffer->Char.UnicodeChar;
  1036. OutputBufferR->Attributes |= COMMON_LVB_LEADING_BYTE;
  1037. OutputBufferR++;
  1038. OutputBufferR->Char.UnicodeChar = UNICODE_DBCS_PADDING;
  1039. OutputBufferR->Attributes = OutputBuffer->Attributes & ~COMMON_LVB_SBCSDBCS;
  1040. OutputBufferR->Attributes |= COMMON_LVB_TRAILING_BYTE;
  1041. }
  1042. }
  1043. else{
  1044. OutputBufferR->Char.UnicodeChar = OutputBuffer->Char.UnicodeChar;
  1045. }
  1046. OutputBufferR++;
  1047. }
  1048. if (IsConsoleFullWidth(Console->hDC,
  1049. Console->OutputCP,
  1050. wch)) {
  1051. if (j != Size.X-1){
  1052. j++;
  1053. }
  1054. }
  1055. OutputBuffer++;
  1056. }
  1057. }
  1058. return STATUS_SUCCESS;
  1059. }
  1060. NTSTATUS
  1061. FE_TranslateOutputToAnsiUnicode(
  1062. IN PCONSOLE_INFORMATION Console,
  1063. IN OUT PCHAR_INFO OutputBuffer,
  1064. IN COORD Size,
  1065. IN OUT PCHAR_INFO OutputBufferR
  1066. )
  1067. // this is used when the app writes unicode to the output buffer
  1068. {
  1069. return FE_TranslateOutputToAnsiUnicodeInternal(Console,
  1070. OutputBuffer,
  1071. Size,
  1072. OutputBufferR,
  1073. TRUE
  1074. );
  1075. }
  1076. NTSTATUS
  1077. TranslateOutputToPaddingUnicode(
  1078. IN PCONSOLE_INFORMATION Console,
  1079. IN OUT PCHAR_INFO OutputBuffer,
  1080. IN COORD Size,
  1081. IN OUT PCHAR_INFO OutputBufferR
  1082. )
  1083. {
  1084. return FE_TranslateOutputToAnsiUnicodeInternal(Console,
  1085. OutputBuffer,
  1086. Size,
  1087. OutputBufferR,
  1088. FALSE
  1089. );
  1090. }
  1091. ULONG
  1092. SrvReadConsoleOutput(
  1093. IN OUT PCSR_API_MSG m,
  1094. IN OUT PCSR_REPLY_STATUS ReplyStatus
  1095. )
  1096. {
  1097. PCONSOLE_READCONSOLEOUTPUT_MSG a = (PCONSOLE_READCONSOLEOUTPUT_MSG)&m->u.ApiMessageData;
  1098. PCONSOLE_INFORMATION Console;
  1099. PHANDLE_DATA HandleData;
  1100. NTSTATUS Status;
  1101. PCHAR_INFO Buffer;
  1102. DBGOUTPUT(("SrvReadConsoleOutput\n"));
  1103. Status = ApiPreamble(a->ConsoleHandle,
  1104. &Console
  1105. );
  1106. if (!NT_SUCCESS(Status)) {
  1107. return Status;
  1108. }
  1109. Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
  1110. a->OutputHandle,
  1111. CONSOLE_OUTPUT_HANDLE,
  1112. GENERIC_READ,
  1113. &HandleData
  1114. );
  1115. if (!NT_SUCCESS(Status)) {
  1116. //
  1117. // a region of zero size is indicated by the right and bottom
  1118. // coordinates being less than the left and top.
  1119. //
  1120. a->CharRegion.Right = (USHORT) (a->CharRegion.Left-1);
  1121. a->CharRegion.Bottom = (USHORT) (a->CharRegion.Top-1);
  1122. }
  1123. else {
  1124. COORD BufferSize;
  1125. BufferSize.X = (SHORT)(a->CharRegion.Right - a->CharRegion.Left + 1);
  1126. BufferSize.Y = (SHORT)(a->CharRegion.Bottom - a->CharRegion.Top + 1);
  1127. if ((BufferSize.X == 1) && (BufferSize.Y == 1)) {
  1128. Buffer = &a->Char;
  1129. }
  1130. else {
  1131. Buffer = a->BufPtr;
  1132. if (!CsrValidateMessageBuffer(m, &a->BufPtr, BufferSize.X * BufferSize.Y, sizeof(*Buffer))) {
  1133. UnlockConsole(Console);
  1134. return STATUS_INVALID_PARAMETER;
  1135. }
  1136. }
  1137. Status = ReadScreenBuffer(HandleData->Buffer.ScreenBuffer,
  1138. Buffer,
  1139. &a->CharRegion
  1140. );
  1141. if (!a->Unicode) {
  1142. TranslateOutputToOem(Console,
  1143. Buffer,
  1144. BufferSize
  1145. );
  1146. } else if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) &&
  1147. !(Console->FullScreenFlags & CONSOLE_FULLSCREEN)) {
  1148. TranslateOutputToOemUnicode(Console,
  1149. Buffer,
  1150. BufferSize
  1151. #if defined(FE_SB)
  1152. ,
  1153. TRUE
  1154. #endif
  1155. );
  1156. }
  1157. }
  1158. UnlockConsole(Console);
  1159. return Status;
  1160. UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
  1161. }
  1162. ULONG
  1163. SrvWriteConsoleOutput(
  1164. IN OUT PCSR_API_MSG m,
  1165. IN OUT PCSR_REPLY_STATUS ReplyStatus
  1166. )
  1167. {
  1168. PCONSOLE_WRITECONSOLEOUTPUT_MSG a = (PCONSOLE_WRITECONSOLEOUTPUT_MSG)&m->u.ApiMessageData;
  1169. PSCREEN_INFORMATION ScreenBufferInformation;
  1170. PCONSOLE_INFORMATION Console;
  1171. PHANDLE_DATA HandleData;
  1172. NTSTATUS Status;
  1173. PCHAR_INFO Buffer;
  1174. #if defined(FE_SB)
  1175. PCHAR_INFO TransBuffer = NULL;
  1176. #endif
  1177. DBGOUTPUT(("SrvWriteConsoleOutput\n"));
  1178. Status = ApiPreamble(a->ConsoleHandle,
  1179. &Console
  1180. );
  1181. if (!NT_SUCCESS(Status)) {
  1182. return Status;
  1183. }
  1184. Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
  1185. a->OutputHandle,
  1186. CONSOLE_OUTPUT_HANDLE,
  1187. GENERIC_WRITE,
  1188. &HandleData
  1189. );
  1190. if (!NT_SUCCESS(Status)) {
  1191. //
  1192. // a region of zero size is indicated by the right and bottom
  1193. // coordinates being less than the left and top.
  1194. //
  1195. a->CharRegion.Right = (USHORT) (a->CharRegion.Left-1);
  1196. a->CharRegion.Bottom = (USHORT) (a->CharRegion.Top-1);
  1197. } else {
  1198. COORD BufferSize;
  1199. ULONG NumBytes;
  1200. BufferSize.X = (SHORT)(a->CharRegion.Right - a->CharRegion.Left + 1);
  1201. BufferSize.Y = (SHORT)(a->CharRegion.Bottom - a->CharRegion.Top + 1);
  1202. NumBytes = BufferSize.X * BufferSize.Y * sizeof(*Buffer);
  1203. if ((BufferSize.X == 1) && (BufferSize.Y == 1)) {
  1204. Buffer = &a->Char;
  1205. } else if (a->ReadVM) {
  1206. Buffer = ConsoleHeapAlloc(TMP_TAG, NumBytes);
  1207. if (Buffer == NULL) {
  1208. UnlockConsole(Console);
  1209. return (ULONG)STATUS_NO_MEMORY;
  1210. }
  1211. Status = NtReadVirtualMemory(CONSOLE_CLIENTPROCESSHANDLE(),
  1212. a->BufPtr,
  1213. Buffer,
  1214. NumBytes,
  1215. NULL
  1216. );
  1217. if (!NT_SUCCESS(Status)) {
  1218. ConsoleHeapFree(Buffer);
  1219. UnlockConsole(Console);
  1220. return (ULONG)STATUS_NO_MEMORY;
  1221. }
  1222. } else {
  1223. Buffer = a->BufPtr;
  1224. if (!CsrValidateMessageBuffer(m, &a->BufPtr, NumBytes, sizeof(BYTE))) {
  1225. UnlockConsole(Console);
  1226. return STATUS_INVALID_PARAMETER;
  1227. }
  1228. }
  1229. ScreenBufferInformation = HandleData->Buffer.ScreenBuffer;
  1230. if (!a->Unicode) {
  1231. TranslateOutputToUnicode(Console,
  1232. Buffer,
  1233. BufferSize
  1234. );
  1235. #if defined(FE_SB)
  1236. Status = WriteScreenBuffer(ScreenBufferInformation,
  1237. Buffer,
  1238. &a->CharRegion
  1239. );
  1240. #endif
  1241. } else if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) &&
  1242. ((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) {
  1243. #if defined(FE_SB)
  1244. if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) {
  1245. TransBuffer = ConsoleHeapAlloc(TMP_DBCS_TAG, (BufferSize.Y * BufferSize.X) * 2 * sizeof(CHAR_INFO));
  1246. if (TransBuffer == NULL) {
  1247. UnlockConsole(Console);
  1248. return (ULONG)STATUS_NO_MEMORY;
  1249. }
  1250. FE_TranslateOutputToAnsiUnicode(Console,
  1251. Buffer,
  1252. BufferSize,
  1253. &TransBuffer[0]
  1254. );
  1255. Status = WriteScreenBuffer(ScreenBufferInformation,
  1256. &TransBuffer[0],
  1257. &a->CharRegion
  1258. );
  1259. ConsoleHeapFree(TransBuffer);
  1260. } else {
  1261. SB_TranslateOutputToAnsiUnicode(Console,
  1262. Buffer,
  1263. BufferSize
  1264. );
  1265. Status = WriteScreenBuffer(ScreenBufferInformation,
  1266. Buffer,
  1267. &a->CharRegion
  1268. );
  1269. }
  1270. #else
  1271. TranslateOutputToAnsiUnicode(Console,
  1272. Buffer,
  1273. BufferSize
  1274. );
  1275. #endif
  1276. }
  1277. #if defined(FE_SB)
  1278. else
  1279. #endif
  1280. Status = WriteScreenBuffer(ScreenBufferInformation,
  1281. Buffer,
  1282. &a->CharRegion
  1283. );
  1284. if (a->ReadVM) {
  1285. ConsoleHeapFree(Buffer);
  1286. }
  1287. if (NT_SUCCESS(Status)) {
  1288. //
  1289. // cause screen to be updated
  1290. //
  1291. #if defined(FE_SB)
  1292. if (CONSOLE_IS_DBCS_OUTPUTCP(Console) &&
  1293. Console->Flags & CONSOLE_JUST_VDM_UNREGISTERED ){
  1294. int MouseRec;
  1295. MouseRec = Console->InputBuffer.InputMode;
  1296. Console->InputBuffer.InputMode &= ~ENABLE_MOUSE_INPUT;
  1297. Console->CurrentScreenBuffer->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT;
  1298. WriteToScreen(ScreenBufferInformation,&a->CharRegion );
  1299. Console->CurrentScreenBuffer->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT;
  1300. Console->InputBuffer.InputMode = MouseRec;
  1301. }
  1302. else
  1303. #endif
  1304. WriteToScreen(ScreenBufferInformation,
  1305. &a->CharRegion
  1306. );
  1307. }
  1308. }
  1309. UnlockConsole(Console);
  1310. return Status;
  1311. UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
  1312. }
  1313. ULONG
  1314. SrvReadConsoleOutputString(
  1315. IN OUT PCSR_API_MSG m,
  1316. IN OUT PCSR_REPLY_STATUS ReplyStatus
  1317. )
  1318. {
  1319. NTSTATUS Status;
  1320. PCONSOLE_INFORMATION Console;
  1321. PHANDLE_DATA HandleData;
  1322. PVOID Buffer;
  1323. PCONSOLE_READCONSOLEOUTPUTSTRING_MSG a = (PCONSOLE_READCONSOLEOUTPUTSTRING_MSG)&m->u.ApiMessageData;
  1324. ULONG nSize;
  1325. Status = ApiPreamble(a->ConsoleHandle,
  1326. &Console
  1327. );
  1328. if (!NT_SUCCESS(Status)) {
  1329. return Status;
  1330. }
  1331. Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
  1332. a->OutputHandle,
  1333. CONSOLE_OUTPUT_HANDLE,
  1334. GENERIC_READ,
  1335. &HandleData
  1336. );
  1337. if (!NT_SUCCESS(Status)) {
  1338. //
  1339. // a region of zero size is indicated by the right and bottom
  1340. // coordinates being less than the left and top.
  1341. //
  1342. a->NumRecords = 0;
  1343. } else {
  1344. if (a->StringType == CONSOLE_ASCII)
  1345. nSize = sizeof(CHAR);
  1346. else
  1347. nSize = sizeof(WORD);
  1348. if ((a->NumRecords*nSize) > sizeof(a->String)) {
  1349. Buffer = a->BufPtr;
  1350. if (!CsrValidateMessageBuffer(m, &a->BufPtr, a->NumRecords, nSize)) {
  1351. UnlockConsole(Console);
  1352. return STATUS_INVALID_PARAMETER;
  1353. }
  1354. }
  1355. else {
  1356. Buffer = a->String;
  1357. }
  1358. Status = ReadOutputString(HandleData->Buffer.ScreenBuffer,
  1359. Buffer,
  1360. a->ReadCoord,
  1361. a->StringType,
  1362. &a->NumRecords
  1363. );
  1364. }
  1365. UnlockConsole(Console);
  1366. return Status;
  1367. UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
  1368. }
  1369. ULONG
  1370. SrvWriteConsoleOutputString(
  1371. IN OUT PCSR_API_MSG m,
  1372. IN OUT PCSR_REPLY_STATUS ReplyStatus
  1373. )
  1374. {
  1375. PCONSOLE_WRITECONSOLEOUTPUTSTRING_MSG a = (PCONSOLE_WRITECONSOLEOUTPUTSTRING_MSG)&m->u.ApiMessageData;
  1376. NTSTATUS Status;
  1377. PCONSOLE_INFORMATION Console;
  1378. PHANDLE_DATA HandleData;
  1379. PVOID Buffer;
  1380. ULONG nSize;
  1381. Status = ApiPreamble(a->ConsoleHandle,
  1382. &Console
  1383. );
  1384. if (!NT_SUCCESS(Status)) {
  1385. return Status;
  1386. }
  1387. Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
  1388. a->OutputHandle,
  1389. CONSOLE_OUTPUT_HANDLE,
  1390. GENERIC_WRITE,
  1391. &HandleData
  1392. );
  1393. if (!NT_SUCCESS(Status)) {
  1394. a->NumRecords = 0;
  1395. } else {
  1396. if (a->WriteCoord.X < 0 ||
  1397. a->WriteCoord.Y < 0) {
  1398. Status = STATUS_INVALID_PARAMETER;
  1399. } else {
  1400. if (a->StringType == CONSOLE_ASCII)
  1401. nSize = sizeof(CHAR);
  1402. else
  1403. nSize = sizeof(WORD);
  1404. if ((a->NumRecords*nSize) > sizeof(a->String)) {
  1405. Buffer = a->BufPtr;
  1406. if (!CsrValidateMessageBuffer(m, &a->BufPtr, a->NumRecords, nSize)) {
  1407. UnlockConsole(Console);
  1408. return STATUS_INVALID_PARAMETER;
  1409. }
  1410. }
  1411. else {
  1412. Buffer = a->String;
  1413. }
  1414. Status = WriteOutputString(HandleData->Buffer.ScreenBuffer,
  1415. Buffer,
  1416. a->WriteCoord,
  1417. a->StringType,
  1418. &a->NumRecords,
  1419. NULL
  1420. );
  1421. }
  1422. }
  1423. UnlockConsole(Console);
  1424. return Status;
  1425. UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
  1426. }
  1427. ULONG
  1428. SrvFillConsoleOutput(
  1429. IN OUT PCSR_API_MSG m,
  1430. IN OUT PCSR_REPLY_STATUS ReplyStatus
  1431. )
  1432. {
  1433. PCONSOLE_FILLCONSOLEOUTPUT_MSG a = (PCONSOLE_FILLCONSOLEOUTPUT_MSG)&m->u.ApiMessageData;
  1434. NTSTATUS Status;
  1435. PCONSOLE_INFORMATION Console;
  1436. PHANDLE_DATA HandleData;
  1437. Status = ApiPreamble(a->ConsoleHandle,
  1438. &Console
  1439. );
  1440. if (!NT_SUCCESS(Status)) {
  1441. return Status;
  1442. }
  1443. Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(),
  1444. a->OutputHandle,
  1445. CONSOLE_OUTPUT_HANDLE,
  1446. GENERIC_WRITE,
  1447. &HandleData
  1448. );
  1449. if (!NT_SUCCESS(Status)) {
  1450. a->Length = 0;
  1451. } else {
  1452. Status = FillOutput(HandleData->Buffer.ScreenBuffer,
  1453. a->Element,
  1454. a->WriteCoord,
  1455. a->ElementType,
  1456. &a->Length
  1457. );
  1458. }
  1459. UnlockConsole(Console);
  1460. return Status;
  1461. UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
  1462. }
  1463. ULONG
  1464. SrvCreateConsoleScreenBuffer(
  1465. IN OUT PCSR_API_MSG m,
  1466. IN OUT PCSR_REPLY_STATUS ReplyStatus
  1467. )
  1468. /*++
  1469. Routine Description:
  1470. This routine creates a screen buffer and returns a handle to it.
  1471. Arguments:
  1472. ApiMessageData - Points to parameter structure.
  1473. Return Value:
  1474. --*/
  1475. {
  1476. PCONSOLE_CREATESCREENBUFFER_MSG a = (PCONSOLE_CREATESCREENBUFFER_MSG)&m->u.ApiMessageData;
  1477. NTSTATUS Status;
  1478. PCONSOLE_INFORMATION Console;
  1479. HANDLE Handle;
  1480. PHANDLE_DATA HandleData;
  1481. PCONSOLE_SHARE_ACCESS ShareAccess;
  1482. CHAR_INFO Fill;
  1483. COORD WindowSize;
  1484. PSCREEN_INFORMATION ScreenInfo;
  1485. PCONSOLE_PER_PROCESS_DATA ProcessData;
  1486. ULONG HandleType;
  1487. int FontIndex;
  1488. DBGOUTPUT(("SrvCreateConsoleScreenBuffer\n"));
  1489. /*
  1490. * Verify that the Flags value is legit, or malicious code could make us
  1491. * fault. Windows Bug #209416.
  1492. */
  1493. if (a->Flags != CONSOLE_TEXTMODE_BUFFER &&
  1494. a->Flags != CONSOLE_GRAPHICS_BUFFER) {
  1495. return STATUS_INVALID_PARAMETER;
  1496. }
  1497. Status = ApiPreamble(a->ConsoleHandle,
  1498. &Console
  1499. );
  1500. if (!NT_SUCCESS(Status)) {
  1501. return Status;
  1502. }
  1503. if (a->Flags & CONSOLE_GRAPHICS_BUFFER) {
  1504. if (!CsrValidateMessageBuffer(m, &a->GraphicsBufferInfo.lpBitMapInfo, a->GraphicsBufferInfo.dwBitMapInfoLength, sizeof(BYTE))) {
  1505. UnlockConsole(Console);
  1506. return STATUS_INVALID_PARAMETER;
  1507. }
  1508. }
  1509. try {
  1510. Handle = INVALID_HANDLE_VALUE;
  1511. ProcessData = CONSOLE_PERPROCESSDATA();
  1512. HandleType = (a->Flags & CONSOLE_GRAPHICS_BUFFER) ?
  1513. CONSOLE_GRAPHICS_OUTPUT_HANDLE : CONSOLE_OUTPUT_HANDLE;
  1514. if (a->InheritHandle)
  1515. HandleType |= CONSOLE_INHERITABLE;
  1516. Status = AllocateIoHandle(ProcessData,
  1517. HandleType,
  1518. &Handle
  1519. );
  1520. if (!NT_SUCCESS(Status)) {
  1521. leave;
  1522. }
  1523. Status = DereferenceIoHandleNoCheck(ProcessData,
  1524. Handle,
  1525. &HandleData
  1526. );
  1527. ASSERT (NT_SUCCESS(Status));
  1528. if (!NT_SUCCESS(Status)) {
  1529. leave;
  1530. }
  1531. //
  1532. // create new screen buffer
  1533. //
  1534. Fill.Char.UnicodeChar = (WCHAR)' ';
  1535. Fill.Attributes = Console->CurrentScreenBuffer->Attributes;
  1536. WindowSize.X = (SHORT)CONSOLE_WINDOW_SIZE_X(Console->CurrentScreenBuffer);
  1537. WindowSize.Y = (SHORT)CONSOLE_WINDOW_SIZE_Y(Console->CurrentScreenBuffer);
  1538. FontIndex = FindCreateFont(CON_FAMILY(Console),
  1539. CON_FACENAME(Console),
  1540. CON_FONTSIZE(Console),
  1541. CON_FONTWEIGHT(Console),
  1542. CON_FONTCODEPAGE(Console)
  1543. );
  1544. Status = CreateScreenBuffer(&ScreenInfo,WindowSize,
  1545. FontIndex,
  1546. WindowSize,
  1547. Fill,Fill,Console,
  1548. a->Flags,&a->GraphicsBufferInfo,
  1549. &a->lpBitmap,&a->hMutex,
  1550. CURSOR_SMALL_SIZE,
  1551. NULL);
  1552. if (!NT_SUCCESS(Status)) {
  1553. leave;
  1554. }
  1555. InitializeOutputHandle(HandleData,ScreenInfo);
  1556. ShareAccess = &ScreenInfo->ShareAccess;
  1557. Status = ConsoleAddShare(a->DesiredAccess,
  1558. a->ShareMode,
  1559. ShareAccess,
  1560. HandleData
  1561. );
  1562. if (!NT_SUCCESS(Status)) {
  1563. HandleData->Buffer.ScreenBuffer->RefCount--;
  1564. FreeScreenBuffer(ScreenInfo);
  1565. leave;
  1566. }
  1567. InsertScreenBuffer(Console, ScreenInfo);
  1568. a->Handle = INDEX_TO_HANDLE(Handle);
  1569. } finally {
  1570. if (!NT_SUCCESS(Status) && Handle != INVALID_HANDLE_VALUE) {
  1571. FreeIoHandle(ProcessData,
  1572. Handle
  1573. );
  1574. }
  1575. UnlockConsole(Console);
  1576. }
  1577. return Status;
  1578. UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message
  1579. }