Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

directio.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1985 - 1999, Microsoft Corporation 00004 00005 Module Name: 00006 00007 directio.c 00008 00009 Abstract: 00010 00011 This file implements the NT console direct I/O API 00012 00013 Author: 00014 00015 Therese Stowell (thereses) 6-Nov-1990 00016 00017 Revision History: 00018 00019 --*/ 00020 00021 #include "precomp.h" 00022 #pragma hdrstop 00023 00024 00025 #if defined(FE_SB) 00026 #define WWSB_FE 00027 #include "dispatch.h" // get the FE_ prototypes 00028 #undef WWSB_FE 00029 #pragma alloc_text(FE_TEXT, FE_TranslateInputToOem) 00030 #pragma alloc_text(FE_TEXT, FE_TranslateInputToUnicode) 00031 #pragma alloc_text(FE_TEXT, FE_TranslateOutputToOem) 00032 #pragma alloc_text(FE_TEXT, FE_TranslateOutputToOemUnicode) 00033 #pragma alloc_text(FE_TEXT, FE_TranslateOutputToUnicode) 00034 #pragma alloc_text(FE_TEXT, FE_TranslateOutputToAnsiUnicode) 00035 #endif 00036 00037 00038 #if defined(FE_SB) 00039 ULONG 00040 SB_TranslateInputToOem 00041 #else 00042 NTSTATUS 00043 TranslateInputToOem 00044 #endif 00045 ( 00046 IN PCONSOLE_INFORMATION Console, 00047 IN OUT PINPUT_RECORD InputRecords, 00048 IN ULONG NumRecords 00049 ) 00050 { 00051 ULONG i; 00052 00053 DBGCHARS(("TranslateInputToOem\n")); 00054 for (i=0;i<NumRecords;i++) { 00055 if (InputRecords[i].EventType == KEY_EVENT) { 00056 InputRecords[i].Event.KeyEvent.uChar.AsciiChar = WcharToChar( 00057 Console->CP, InputRecords[i].Event.KeyEvent.uChar.UnicodeChar); 00058 } 00059 } 00060 #if defined(FE_SB) 00061 return NumRecords; 00062 #else 00063 return STATUS_SUCCESS; 00064 #endif 00065 } 00066 00067 #if defined(FE_SB) 00068 ULONG 00069 FE_TranslateInputToOem( 00070 IN PCONSOLE_INFORMATION Console, 00071 IN OUT PINPUT_RECORD InputRecords, 00072 IN ULONG NumRecords, // in : ASCII byte count 00073 IN ULONG UnicodeLength, // in : Number of events (char count) 00074 OUT PINPUT_RECORD DbcsLeadInpRec 00075 ) 00076 { 00077 ULONG i,j; 00078 PINPUT_RECORD TmpInpRec; 00079 BYTE AsciiDbcs[2]; 00080 ULONG NumBytes; 00081 00082 ASSERT(NumRecords >= UnicodeLength); 00083 00084 TmpInpRec = ConsoleHeapAlloc(MAKE_TAG( TMP_DBCS_TAG ),NumRecords*sizeof(INPUT_RECORD)); 00085 if (TmpInpRec == NULL) 00086 return 0; 00087 00088 memcpy(TmpInpRec,InputRecords,NumRecords*sizeof(INPUT_RECORD)); 00089 AsciiDbcs[1] = 0; 00090 for (i=0,j=0; i<UnicodeLength; i++,j++) { 00091 if (TmpInpRec[i].EventType == KEY_EVENT) { 00092 if (IsConsoleFullWidth(Console->hDC, 00093 Console->CP,TmpInpRec[i].Event.KeyEvent.uChar.UnicodeChar)) { 00094 NumBytes = sizeof(AsciiDbcs); 00095 ConvertToOem(Console->CP, 00096 &TmpInpRec[i].Event.KeyEvent.uChar.UnicodeChar, 00097 1, 00098 &AsciiDbcs[0], 00099 NumBytes 00100 ); 00101 if (IsDBCSLeadByteConsole(AsciiDbcs[0],&Console->CPInfo)) { 00102 if (j < NumRecords-1) { // -1 is safe DBCS in buffer 00103 InputRecords[j] = TmpInpRec[i]; 00104 InputRecords[j].Event.KeyEvent.uChar.UnicodeChar = 0; 00105 InputRecords[j].Event.KeyEvent.uChar.AsciiChar = AsciiDbcs[0]; 00106 j++; 00107 InputRecords[j] = TmpInpRec[i]; 00108 InputRecords[j].Event.KeyEvent.uChar.UnicodeChar = 0; 00109 InputRecords[j].Event.KeyEvent.uChar.AsciiChar = AsciiDbcs[1]; 00110 AsciiDbcs[1] = 0; 00111 } 00112 else if (j == NumRecords-1) { 00113 InputRecords[j] = TmpInpRec[i]; 00114 InputRecords[j].Event.KeyEvent.uChar.UnicodeChar = 0; 00115 InputRecords[j].Event.KeyEvent.uChar.AsciiChar = AsciiDbcs[0]; 00116 j++; 00117 break; 00118 } 00119 else { 00120 AsciiDbcs[1] = 0; 00121 break; 00122 } 00123 } 00124 else { 00125 InputRecords[j] = TmpInpRec[i]; 00126 InputRecords[j].Event.KeyEvent.uChar.UnicodeChar = 0; 00127 InputRecords[j].Event.KeyEvent.uChar.AsciiChar = AsciiDbcs[0]; 00128 AsciiDbcs[1] = 0; 00129 } 00130 } 00131 else { 00132 InputRecords[j] = TmpInpRec[i]; 00133 ConvertToOem(Console->CP, 00134 &InputRecords[j].Event.KeyEvent.uChar.UnicodeChar, 00135 1, 00136 &InputRecords[j].Event.KeyEvent.uChar.AsciiChar, 00137 1 00138 ); 00139 } 00140 } 00141 } 00142 if (DbcsLeadInpRec) { 00143 if (AsciiDbcs[1]) { 00144 *DbcsLeadInpRec = TmpInpRec[i]; 00145 DbcsLeadInpRec->Event.KeyEvent.uChar.AsciiChar = AsciiDbcs[1]; 00146 } 00147 else { 00148 RtlZeroMemory(DbcsLeadInpRec,sizeof(INPUT_RECORD)); 00149 } 00150 } 00151 ConsoleHeapFree(TmpInpRec); 00152 return j; 00153 } 00154 #endif 00155 00156 00157 00158 #if defined(FE_SB) 00159 ULONG 00160 SB_TranslateInputToUnicode 00161 #else 00162 NTSTATUS 00163 TranslateInputToUnicode 00164 #endif 00165 ( 00166 IN PCONSOLE_INFORMATION Console, 00167 IN OUT PINPUT_RECORD InputRecords, 00168 IN ULONG NumRecords 00169 ) 00170 { 00171 ULONG i; 00172 DBGCHARS(("TranslateInputToUnicode\n")); 00173 for (i=0;i<NumRecords;i++) { 00174 if (InputRecords[i].EventType == KEY_EVENT) { 00175 #if defined(FE_SB) 00176 InputRecords[i].Event.KeyEvent.uChar.UnicodeChar = SB_CharToWchar( 00177 Console->CP, InputRecords[i].Event.KeyEvent.uChar.AsciiChar); 00178 #else 00179 InputRecords[i].Event.KeyEvent.uChar.UnicodeChar = CharToWchar( 00180 Console->CP, InputRecords[i].Event.KeyEvent.uChar.AsciiChar); 00181 #endif 00182 } 00183 } 00184 #if defined(FE_SB) 00185 return i; 00186 #else 00187 return STATUS_SUCCESS; 00188 #endif 00189 } 00190 00191 #if defined(FE_SB) 00192 ULONG 00193 FE_TranslateInputToUnicode( 00194 IN PCONSOLE_INFORMATION Console, 00195 IN OUT PINPUT_RECORD InputRecords, 00196 IN ULONG NumRecords, 00197 IN OUT PINPUT_RECORD DBCSLeadByte 00198 ) 00199 { 00200 ULONG i,j; 00201 INPUT_RECORD AsciiDbcs[2]; 00202 CHAR Strings[2]; 00203 WCHAR UnicodeDbcs[2]; 00204 PWCHAR Uni; 00205 ULONG NumBytes; 00206 00207 if (DBCSLeadByte->Event.KeyEvent.uChar.AsciiChar) { 00208 AsciiDbcs[0] = *DBCSLeadByte; 00209 Strings[0] = DBCSLeadByte->Event.KeyEvent.uChar.AsciiChar; 00210 } 00211 else{ 00212 RtlZeroMemory(AsciiDbcs,sizeof(AsciiDbcs)); 00213 } 00214 for (i=j=0; i<NumRecords; i++) { 00215 if (InputRecords[i].EventType == KEY_EVENT) { 00216 if (AsciiDbcs[0].Event.KeyEvent.uChar.AsciiChar) { 00217 AsciiDbcs[1] = InputRecords[i]; 00218 Strings[1] = InputRecords[i].Event.KeyEvent.uChar.AsciiChar; 00219 NumBytes = sizeof(Strings); 00220 NumBytes = ConvertInputToUnicode(Console->CP, 00221 &Strings[0], 00222 NumBytes, 00223 &UnicodeDbcs[0], 00224 NumBytes); 00225 Uni = &UnicodeDbcs[0]; 00226 while (NumBytes--) { 00227 InputRecords[j] = AsciiDbcs[0]; 00228 InputRecords[j].Event.KeyEvent.uChar.UnicodeChar = *Uni++; 00229 j++; 00230 } 00231 RtlZeroMemory(AsciiDbcs,sizeof(AsciiDbcs)); 00232 if (DBCSLeadByte->Event.KeyEvent.uChar.AsciiChar) 00233 RtlZeroMemory(DBCSLeadByte,sizeof(INPUT_RECORD)); 00234 } 00235 else if (IsDBCSLeadByteConsole(InputRecords[i].Event.KeyEvent.uChar.AsciiChar,&Console->CPInfo)) { 00236 if (i < NumRecords-1) { 00237 AsciiDbcs[0] = InputRecords[i]; 00238 Strings[0] = InputRecords[i].Event.KeyEvent.uChar.AsciiChar; 00239 } 00240 else { 00241 *DBCSLeadByte = InputRecords[i]; 00242 break; 00243 } 00244 } 00245 else { 00246 CHAR c; 00247 InputRecords[j] = InputRecords[i]; 00248 c = InputRecords[i].Event.KeyEvent.uChar.AsciiChar; 00249 ConvertInputToUnicode(Console->CP, 00250 &c, 00251 1, 00252 &InputRecords[j].Event.KeyEvent.uChar.UnicodeChar, 00253 1); 00254 j++; 00255 } 00256 } 00257 else { 00258 InputRecords[j++] = InputRecords[i]; 00259 } 00260 } 00261 return j; 00262 } 00263 #endif 00264 00265 00266 BOOLEAN 00267 DirectReadWaitRoutine( 00268 IN PLIST_ENTRY WaitQueue, 00269 IN PCSR_THREAD WaitingThread, 00270 IN PCSR_API_MSG WaitReplyMessage, 00271 IN PVOID WaitParameter, 00272 IN PVOID SatisfyParameter1, 00273 IN PVOID SatisfyParameter2, 00274 IN ULONG WaitFlags 00275 ) 00276 00277 /*++ 00278 00279 Routine Description: 00280 00281 This routine is called to complete a direct read that blocked in 00282 ReadInputBuffer. The context of the read was saved in the DirectReadData 00283 structure. This routine is called when events have been written to 00284 the input buffer. It is called in the context of the writing thread. 00285 00286 Arguments: 00287 00288 WaitQueue - Pointer to queue containing wait block. 00289 00290 WaitingThread - Pointer to waiting thread. 00291 00292 WaitReplyMessage - Pointer to reply message to return to dll when 00293 read is completed. 00294 00295 DirectReadData - Context of read. 00296 00297 SatisfyParameter1 - Unused. 00298 00299 SatisfyParameter2 - Unused. 00300 00301 WaitFlags - Flags indicating status of wait. 00302 00303 Return Value: 00304 00305 --*/ 00306 00307 { 00308 PCONSOLE_GETCONSOLEINPUT_MSG a; 00309 PINPUT_RECORD Buffer; 00310 NTSTATUS Status; 00311 PCONSOLE_INFORMATION Console; 00312 PDIRECT_READ_DATA DirectReadData; 00313 PHANDLE_DATA HandleData; 00314 BOOLEAN RetVal = TRUE; 00315 #if defined(FE_SB) 00316 BOOLEAN fAddDbcsLead = FALSE; 00317 PDWORD nLength; 00318 #endif 00319 00320 a = (PCONSOLE_GETCONSOLEINPUT_MSG)&WaitReplyMessage->u.ApiMessageData; 00321 DirectReadData = (PDIRECT_READ_DATA) WaitParameter; 00322 00323 Status = DereferenceIoHandleNoCheck(DirectReadData->ProcessData, 00324 DirectReadData->HandleIndex, 00325 &HandleData 00326 ); 00327 ASSERT (NT_SUCCESS(Status)); 00328 00329 // 00330 // see if this routine was called by CloseInputHandle. if it 00331 // was, see if this wait block corresponds to the dying handle. 00332 // if it doesn't, just return. 00333 // 00334 00335 if (SatisfyParameter1 != NULL && 00336 SatisfyParameter1 != HandleData) { 00337 return FALSE; 00338 } 00339 00340 // 00341 // if ctrl-c or ctrl-break was seen, ignore it. 00342 // 00343 00344 if ((ULONG_PTR)SatisfyParameter2 & (CONSOLE_CTRL_C_SEEN | CONSOLE_CTRL_BREAK_SEEN)) { 00345 return FALSE; 00346 } 00347 00348 Console = DirectReadData->Console; 00349 00350 #if defined(FE_SB) 00351 if (CONSOLE_IS_DBCS_CP(Console) && !a->Unicode) { 00352 if (HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte.Event.KeyEvent.uChar.AsciiChar) { 00353 if (a->NumRecords == 1) { 00354 Buffer = &a->Record[0]; 00355 *Buffer = HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte; 00356 if (!(a->Flags & CONSOLE_READ_NOREMOVE)) 00357 RtlZeroMemory(&HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte,sizeof(INPUT_RECORD)); 00358 return TRUE; 00359 } 00360 } 00361 } 00362 #endif 00363 00364 // 00365 // this routine should be called by a thread owning the same 00366 // lock on the same console as we're reading from. 00367 // 00368 00369 try { 00370 LockReadCount(HandleData); 00371 ASSERT(HandleData->InputReadData->ReadCount); 00372 HandleData->InputReadData->ReadCount -= 1; 00373 UnlockReadCount(HandleData); 00374 00375 // 00376 // see if called by CsrDestroyProcess or CsrDestroyThread 00377 // via CsrNotifyWaitBlock. if so, just decrement the ReadCount 00378 // and return. 00379 // 00380 00381 if (WaitFlags & CSR_PROCESS_TERMINATING) { 00382 Status = STATUS_THREAD_IS_TERMINATING; 00383 leave; 00384 } 00385 00386 // 00387 // We must see if we were woken up because the handle is being 00388 // closed. if so, we decrement the read count. if it goes to 00389 // zero, we wake up the close thread. otherwise, we wake up any 00390 // other thread waiting for data. 00391 // 00392 00393 if (HandleData->InputReadData->InputHandleFlags & HANDLE_CLOSING) { 00394 ASSERT (SatisfyParameter1 == HandleData); 00395 Status = STATUS_ALERTED; 00396 leave; 00397 } 00398 00399 // 00400 // if we get to here, this routine was called either by the input 00401 // thread or a write routine. both of these callers grab the 00402 // current console lock. 00403 // 00404 00405 // 00406 // this routine should be called by a thread owning the same 00407 // lock on the same console as we're reading from. 00408 // 00409 00410 ASSERT (ConsoleLocked(Console)); 00411 00412 // 00413 // if the read buffer is contained within the message, we need to 00414 // reset the buffer pointer because the message copied from the 00415 // stack to heap space when the wait block was created. 00416 // 00417 00418 if (a->NumRecords <= INPUT_RECORD_BUFFER_SIZE) { 00419 Buffer = a->Record; 00420 } else { 00421 Buffer = a->BufPtr; 00422 } 00423 #if defined(FE_SB) 00424 if (CONSOLE_IS_DBCS_CP(Console) ) { 00425 Console->ReadConInpNumBytesUnicode = a->NumRecords; 00426 if (!a->Unicode) { 00427 /* 00428 * ASCII : a->NumRecords is ASCII byte count 00429 */ 00430 if (HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte.Event.KeyEvent.uChar.AsciiChar) { 00431 /* 00432 * Saved DBCS Traling byte 00433 */ 00434 if (Console->ReadConInpNumBytesUnicode != 1) { 00435 Console->ReadConInpNumBytesUnicode--; 00436 Buffer++; 00437 fAddDbcsLead = TRUE; 00438 nLength = &Console->ReadConInpNumBytesUnicode; 00439 } 00440 else { 00441 ASSERT(Console->ReadConInpNumBytesUnicode==1); 00442 } 00443 } 00444 else { 00445 nLength = &Console->ReadConInpNumBytesUnicode; 00446 } 00447 } 00448 else { 00449 nLength = &a->NumRecords; 00450 } 00451 } 00452 else { 00453 nLength = &a->NumRecords; 00454 } 00455 Status = ReadInputBuffer(DirectReadData->InputInfo, 00456 Buffer, 00457 nLength, 00458 !!(a->Flags & CONSOLE_READ_NOREMOVE), 00459 !(a->Flags & CONSOLE_READ_NOWAIT), 00460 FALSE, 00461 Console, 00462 HandleData, 00463 WaitReplyMessage, 00464 DirectReadWaitRoutine, 00465 &DirectReadData, 00466 sizeof(DirectReadData), 00467 TRUE, 00468 a->Unicode 00469 ); 00470 #else 00471 Status = ReadInputBuffer(DirectReadData->InputInfo, 00472 Buffer, 00473 &a->NumRecords, 00474 !!(a->Flags & CONSOLE_READ_NOREMOVE), 00475 !(a->Flags & CONSOLE_READ_NOWAIT), 00476 FALSE, 00477 Console, 00478 HandleData, 00479 WaitReplyMessage, 00480 DirectReadWaitRoutine, 00481 &DirectReadData, 00482 sizeof(DirectReadData), 00483 TRUE 00484 ); 00485 #endif 00486 if (Status == CONSOLE_STATUS_WAIT) { 00487 RetVal = FALSE; 00488 } 00489 } finally { 00490 00491 // 00492 // if the read was completed (status != wait), free the direct read 00493 // data. 00494 // 00495 00496 if (Status != CONSOLE_STATUS_WAIT) { 00497 if (Status == STATUS_SUCCESS && !a->Unicode) { 00498 #if defined(FE_SB) 00499 if (CONSOLE_IS_DBCS_CP(Console) ) { 00500 if (fAddDbcsLead && 00501 HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte.Event.KeyEvent.uChar.AsciiChar) { 00502 a->NumRecords--; 00503 } 00504 a->NumRecords = FE_TranslateInputToOem( 00505 Console, 00506 Buffer, 00507 a->NumRecords, 00508 Console->ReadConInpNumBytesUnicode, 00509 a->Flags & CONSOLE_READ_NOREMOVE ? 00510 NULL : 00511 &HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte); 00512 if (fAddDbcsLead && 00513 HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte.Event.KeyEvent.uChar.AsciiChar) { 00514 *(Buffer-1) = HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte; 00515 if (!(a->Flags & CONSOLE_READ_NOREMOVE)) 00516 RtlZeroMemory(&HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte,sizeof(INPUT_RECORD)); 00517 a->NumRecords++; 00518 Buffer--; 00519 } 00520 } 00521 else { 00522 TranslateInputToOem(Console, 00523 Buffer, 00524 a->NumRecords, 00525 Console->ReadConInpNumBytesUnicode, 00526 a->Flags & CONSOLE_READ_NOREMOVE ? 00527 NULL : 00528 &HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte 00529 ); 00530 } 00531 #else 00532 TranslateInputToOem(Console, 00533 Buffer, 00534 a->NumRecords 00535 ); 00536 #endif 00537 } 00538 WaitReplyMessage->ReturnValue = Status; 00539 ConsoleHeapFree(DirectReadData); 00540 } 00541 } 00542 00543 return RetVal; 00544 00545 // 00546 // satisfy the unreferenced parameter warnings. 00547 // 00548 00549 UNREFERENCED_PARAMETER(WaitQueue); 00550 UNREFERENCED_PARAMETER(WaitingThread); 00551 UNREFERENCED_PARAMETER(SatisfyParameter2); 00552 } 00553 00554 00555 ULONG 00556 SrvGetConsoleInput( 00557 IN OUT PCSR_API_MSG m, 00558 IN OUT PCSR_REPLY_STATUS ReplyStatus 00559 ) 00560 00561 /*++ 00562 00563 Routine Description: 00564 00565 This routine reads or peeks input events. In both cases, the events 00566 are copied to the user's buffer. In the read case they are removed 00567 from the input buffer and in the peek case they are not. 00568 00569 Arguments: 00570 00571 m - message containing api parameters 00572 00573 ReplyStatus - Indicates whether to reply to the dll port. 00574 00575 Return Value: 00576 00577 --*/ 00578 00579 { 00580 PCONSOLE_GETCONSOLEINPUT_MSG a = (PCONSOLE_GETCONSOLEINPUT_MSG)&m->u.ApiMessageData; 00581 PCONSOLE_INFORMATION Console; 00582 PHANDLE_DATA HandleData; 00583 NTSTATUS Status; 00584 PINPUT_RECORD Buffer; 00585 DIRECT_READ_DATA DirectReadData; 00586 #ifdef FE_SB 00587 BOOLEAN fAddDbcsLead = FALSE; 00588 PDWORD nLength; 00589 #endif 00590 00591 if (a->Flags & ~CONSOLE_READ_VALID) { 00592 return (ULONG)STATUS_INVALID_PARAMETER; 00593 } 00594 00595 Status = ApiPreamble(a->ConsoleHandle, 00596 &Console 00597 ); 00598 if (!NT_SUCCESS(Status)) { 00599 return Status; 00600 } 00601 Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(), 00602 a->InputHandle, 00603 CONSOLE_INPUT_HANDLE, 00604 GENERIC_READ, 00605 &HandleData 00606 ); 00607 if (!NT_SUCCESS(Status)) { 00608 a->NumRecords = 0; 00609 } else { 00610 00611 if (a->NumRecords <= INPUT_RECORD_BUFFER_SIZE) { 00612 Buffer = a->Record; 00613 } else { 00614 Buffer = a->BufPtr; 00615 if (!CsrValidateMessageBuffer(m, &a->BufPtr, a->NumRecords, sizeof(*Buffer))) { 00616 UnlockConsole(Console); 00617 return STATUS_INVALID_PARAMETER; 00618 } 00619 } 00620 00621 // 00622 // if we're reading, wait for data. if we're peeking, don't. 00623 // 00624 00625 DirectReadData.InputInfo = HandleData->Buffer.InputBuffer; 00626 DirectReadData.Console = Console; 00627 DirectReadData.ProcessData = CONSOLE_PERPROCESSDATA(); 00628 DirectReadData.HandleIndex = HANDLE_TO_INDEX(a->InputHandle); 00629 #if defined(FE_SB) 00630 if (CONSOLE_IS_DBCS_CP(Console) ) { 00631 Console->ReadConInpNumBytesUnicode = a->NumRecords; 00632 if (!a->Unicode) { 00633 /* 00634 * ASCII : a->NumRecords is ASCII byte count 00635 */ 00636 if (HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte.Event.KeyEvent.uChar.AsciiChar) { 00637 /* 00638 * Saved DBCS Traling byte 00639 */ 00640 *Buffer = HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte; 00641 if (!(a->Flags & CONSOLE_READ_NOREMOVE)) 00642 RtlZeroMemory(&HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte,sizeof(INPUT_RECORD)); 00643 00644 if (Console->ReadConInpNumBytesUnicode == 1) { 00645 UnlockConsole(Console); 00646 return STATUS_SUCCESS; 00647 } 00648 else { 00649 Console->ReadConInpNumBytesUnicode--; 00650 Buffer++; 00651 fAddDbcsLead = TRUE; 00652 nLength = &Console->ReadConInpNumBytesUnicode; 00653 } 00654 } 00655 else { 00656 nLength = &Console->ReadConInpNumBytesUnicode; 00657 } 00658 } 00659 else { 00660 nLength = &a->NumRecords; 00661 } 00662 } 00663 else { 00664 nLength = &a->NumRecords; 00665 } 00666 Status = ReadInputBuffer(HandleData->Buffer.InputBuffer, 00667 Buffer, 00668 nLength, 00669 !!(a->Flags & CONSOLE_READ_NOREMOVE), 00670 !(a->Flags & CONSOLE_READ_NOWAIT), 00671 FALSE, 00672 Console, 00673 HandleData, 00674 m, 00675 DirectReadWaitRoutine, 00676 &DirectReadData, 00677 sizeof(DirectReadData), 00678 FALSE, 00679 a->Unicode 00680 ); 00681 if (Status == CONSOLE_STATUS_WAIT) { 00682 *ReplyStatus = CsrReplyPending; 00683 } else if (!a->Unicode) { 00684 a->NumRecords = TranslateInputToOem(Console, 00685 Buffer, 00686 fAddDbcsLead ? 00687 a->NumRecords-1 : 00688 a->NumRecords, 00689 Console->ReadConInpNumBytesUnicode, 00690 a->Flags & CONSOLE_READ_NOREMOVE ? 00691 NULL : 00692 &HandleData->Buffer.InputBuffer->ReadConInpDbcsLeadByte 00693 ); 00694 if (fAddDbcsLead) 00695 { 00696 a->NumRecords++; 00697 Buffer--; 00698 } 00699 } 00700 #else 00701 Status = ReadInputBuffer(HandleData->Buffer.InputBuffer, 00702 Buffer, 00703 &a->NumRecords, 00704 !!(a->Flags & CONSOLE_READ_NOREMOVE), 00705 !(a->Flags & CONSOLE_READ_NOWAIT), 00706 FALSE, 00707 Console, 00708 HandleData, 00709 m, 00710 DirectReadWaitRoutine, 00711 &DirectReadData, 00712 sizeof(DirectReadData), 00713 FALSE 00714 ); 00715 if (Status == CONSOLE_STATUS_WAIT) { 00716 *ReplyStatus = CsrReplyPending; 00717 } else if (!a->Unicode) { 00718 TranslateInputToOem(Console, 00719 Buffer, 00720 a->NumRecords 00721 ); 00722 } 00723 #endif 00724 } 00725 UnlockConsole(Console); 00726 return Status; 00727 } 00728 00729 ULONG 00730 SrvWriteConsoleInput( 00731 IN OUT PCSR_API_MSG m, 00732 IN OUT PCSR_REPLY_STATUS ReplyStatus 00733 ) 00734 { 00735 PCONSOLE_WRITECONSOLEINPUT_MSG a = (PCONSOLE_WRITECONSOLEINPUT_MSG)&m->u.ApiMessageData; 00736 PCONSOLE_INFORMATION Console; 00737 PHANDLE_DATA HandleData; 00738 NTSTATUS Status; 00739 PINPUT_RECORD Buffer; 00740 00741 Status = ApiPreamble(a->ConsoleHandle, 00742 &Console 00743 ); 00744 if (!NT_SUCCESS(Status)) { 00745 return Status; 00746 } 00747 Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(), 00748 a->InputHandle, 00749 CONSOLE_INPUT_HANDLE, 00750 GENERIC_WRITE, 00751 &HandleData 00752 ); 00753 if (!NT_SUCCESS(Status)) { 00754 a->NumRecords = 0; 00755 } else { 00756 if (a->NumRecords <= INPUT_RECORD_BUFFER_SIZE) { 00757 Buffer = a->Record; 00758 } else { 00759 Buffer = a->BufPtr; 00760 if (!CsrValidateMessageBuffer(m, &a->BufPtr, a->NumRecords, sizeof(*Buffer))) { 00761 UnlockConsole(Console); 00762 return STATUS_INVALID_PARAMETER; 00763 } 00764 } 00765 if (!a->Unicode) { 00766 #if defined(FE_SB) 00767 a->NumRecords = TranslateInputToUnicode(Console, 00768 Buffer, 00769 a->NumRecords, 00770 &HandleData->Buffer.InputBuffer->WriteConInpDbcsLeadByte[0] 00771 ); 00772 #else 00773 TranslateInputToUnicode(Console, 00774 Buffer, 00775 a->NumRecords 00776 ); 00777 #endif 00778 } 00779 if (a->Append) { 00780 a->NumRecords = WriteInputBuffer(Console, 00781 HandleData->Buffer.InputBuffer, 00782 Buffer, 00783 a->NumRecords 00784 ); 00785 } else { 00786 a->NumRecords = PrependInputBuffer(Console, 00787 HandleData->Buffer.InputBuffer, 00788 Buffer, 00789 a->NumRecords 00790 ); 00791 00792 } 00793 } 00794 UnlockConsole(Console); 00795 return((ULONG) Status); 00796 UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message 00797 } 00798 00799 NTSTATUS 00800 SB_TranslateOutputToOem 00801 ( 00802 IN PCONSOLE_INFORMATION Console, 00803 IN OUT PCHAR_INFO OutputBuffer, 00804 IN COORD Size 00805 ) 00806 // this is used when the app reads oem from the output buffer 00807 // the app wants real OEM characters. We have real Unicode or UnicodeOem. 00808 { 00809 SHORT i,j; 00810 UINT Codepage; 00811 DBGCHARS(("SB_TranslateOutputToOem(Console=%lx, OutputBuffer=%lx)\n", 00812 Console, OutputBuffer)); 00813 00814 j = Size.X * Size.Y; 00815 00816 if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) && 00817 ((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) { 00818 #if defined(FE_SB) 00819 if (CONSOLE_IS_DBCS_ENABLED() && 00820 Console->OutputCP != WINDOWSCP ) { 00821 Codepage = USACP; 00822 } 00823 else 00824 #endif 00825 // we have UnicodeOem characters 00826 Codepage = WINDOWSCP; 00827 } else { 00828 // we have real Unicode characters 00829 Codepage = Console->OutputCP; // BUG FIX by KazuM Jun.2.97 00830 } 00831 00832 for (i=0;i<j;i++,OutputBuffer++) { 00833 OutputBuffer->Char.AsciiChar = WcharToChar(Codepage, 00834 OutputBuffer->Char.UnicodeChar); 00835 } 00836 return STATUS_SUCCESS; 00837 } 00838 00839 #if defined(FE_SB) 00840 NTSTATUS 00841 FE_TranslateOutputToOem( 00842 IN PCONSOLE_INFORMATION Console, 00843 IN OUT PCHAR_INFO OutputBuffer, 00844 IN COORD Size 00845 ) 00846 // this is used when the app reads oem from the output buffer 00847 // the app wants real OEM characters. We have real Unicode or UnicodeOem. 00848 { 00849 SHORT i,j; 00850 UINT Codepage; 00851 PCHAR_INFO TmpBuffer,SaveBuffer; 00852 CHAR AsciiDbcs[2]; 00853 ULONG NumBytes; 00854 DBGCHARS(("FE_TranslateOutputToOem(Console=%lx, OutputBuffer=%lx)\n", 00855 Console, OutputBuffer)); 00856 00857 SaveBuffer = TmpBuffer = 00858 ConsoleHeapAlloc(MAKE_TAG( TMP_DBCS_TAG ), Size.X * Size.Y * sizeof(CHAR_INFO) * 2); 00859 if (TmpBuffer == NULL) { 00860 return STATUS_NO_MEMORY; 00861 } 00862 00863 if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) && 00864 ((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) { 00865 if (CONSOLE_IS_DBCS_ENABLED() && 00866 Console->OutputCP != WINDOWSCP ) { 00867 Codepage = USACP; 00868 } 00869 else 00870 // we have UnicodeOem characters 00871 Codepage = WINDOWSCP; 00872 } else { 00873 // we have real Unicode characters 00874 Codepage = Console->OutputCP; 00875 } 00876 00877 memcpy(TmpBuffer,OutputBuffer,Size.X * Size.Y * sizeof(CHAR_INFO)); 00878 for (i=0; i < Size.Y; i++) { 00879 for (j=0; j < Size.X; j++) { 00880 if (TmpBuffer->Attributes & COMMON_LVB_LEADING_BYTE) { 00881 if (j < Size.X-1) { // -1 is safe DBCS in buffer 00882 j++; 00883 NumBytes = sizeof(AsciiDbcs); 00884 NumBytes = ConvertOutputToOem(Codepage, 00885 &TmpBuffer->Char.UnicodeChar, 00886 1, 00887 &AsciiDbcs[0], 00888 NumBytes); 00889 OutputBuffer->Char.AsciiChar = AsciiDbcs[0]; 00890 OutputBuffer->Attributes = TmpBuffer->Attributes; 00891 OutputBuffer++; 00892 TmpBuffer++; 00893 OutputBuffer->Char.AsciiChar = AsciiDbcs[1]; 00894 OutputBuffer->Attributes = TmpBuffer->Attributes; 00895 OutputBuffer++; 00896 TmpBuffer++; 00897 } 00898 else { 00899 OutputBuffer->Char.AsciiChar = ' '; 00900 OutputBuffer->Attributes = TmpBuffer->Attributes & ~COMMON_LVB_SBCSDBCS; 00901 OutputBuffer++; 00902 TmpBuffer++; 00903 } 00904 } 00905 else if (!(TmpBuffer->Attributes & COMMON_LVB_SBCSDBCS)){ 00906 ConvertOutputToOem(Codepage, 00907 &TmpBuffer->Char.UnicodeChar, 00908 1, 00909 &OutputBuffer->Char.AsciiChar, 00910 1); 00911 OutputBuffer->Attributes = TmpBuffer->Attributes; 00912 OutputBuffer++; 00913 TmpBuffer++; 00914 } 00915 } 00916 } 00917 ConsoleHeapFree(SaveBuffer); 00918 return STATUS_SUCCESS; 00919 } 00920 #endif 00921 00922 NTSTATUS 00923 SB_TranslateOutputToOemUnicode 00924 ( 00925 IN PCONSOLE_INFORMATION Console, 00926 IN OUT PCHAR_INFO OutputBuffer, 00927 IN COORD Size 00928 ) 00929 // this is used when the app reads unicode from the output buffer 00930 { 00931 SHORT i,j; 00932 DBGCHARS(("SB_TranslateOutputToOemUnicode\n")); 00933 00934 j = Size.X * Size.Y; 00935 00936 for (i=0;i<j;i++,OutputBuffer++) { 00937 FalseUnicodeToRealUnicode(&OutputBuffer->Char.UnicodeChar, 00938 1, 00939 Console->OutputCP 00940 ); 00941 } 00942 return STATUS_SUCCESS; 00943 } 00944 00945 #if defined(FE_SB) 00946 NTSTATUS 00947 FE_TranslateOutputToOemUnicode( 00948 IN PCONSOLE_INFORMATION Console, 00949 IN OUT PCHAR_INFO OutputBuffer, 00950 IN COORD Size, 00951 IN BOOL fRemoveDbcsMark 00952 ) 00953 // this is used when the app reads unicode from the output buffer 00954 { 00955 SHORT i,j; 00956 DBGCHARS(("FE_TranslateOutputToOemUnicode\n")); 00957 00958 j = Size.X * Size.Y; 00959 00960 if (fRemoveDbcsMark) 00961 RemoveDbcsMarkCell(OutputBuffer,OutputBuffer,j); 00962 00963 for (i=0;i<j;i++,OutputBuffer++) { 00964 FalseUnicodeToRealUnicode(&OutputBuffer->Char.UnicodeChar, 00965 1, 00966 Console->OutputCP 00967 ); 00968 } 00969 return STATUS_SUCCESS; 00970 } 00971 #endif 00972 00973 00974 NTSTATUS 00975 SB_TranslateOutputToUnicode 00976 ( 00977 IN PCONSOLE_INFORMATION Console, 00978 IN OUT PCHAR_INFO OutputBuffer, 00979 IN COORD Size 00980 ) 00981 // this is used when the app writes oem to the output buffer 00982 // we want UnicodeOem or Unicode in the buffer, depending on font & fullscreen 00983 { 00984 SHORT i,j; 00985 UINT Codepage; 00986 DBGCHARS(("SB_TranslateOutputToUnicode %lx %lx (%lx,%lx)\n", 00987 Console, OutputBuffer, Size.X, Size.Y)); 00988 00989 j = Size.X * Size.Y; 00990 00991 if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) && 00992 ((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) { 00993 #if defined(FE_SB) 00994 if (CONSOLE_IS_DBCS_ENABLED() && 00995 (Console->OutputCP != WINDOWSCP) ) { 00996 Codepage = USACP; 00997 } 00998 else 00999 #endif 01000 // we want UnicodeOem characters 01001 Codepage = WINDOWSCP; 01002 } else { 01003 // we want real Unicode characters 01004 Codepage = Console->OutputCP; // BUG FIX by KazuM Jun.2.97 01005 } 01006 for (i = 0; i < j; i++, OutputBuffer++) { 01007 #if defined(FE_SB) 01008 OutputBuffer->Char.UnicodeChar = SB_CharToWchar( 01009 Codepage, OutputBuffer->Char.AsciiChar); 01010 #else 01011 OutputBuffer->Char.UnicodeChar = CharToWchar( 01012 Codepage, OutputBuffer->Char.AsciiChar); 01013 #endif 01014 } 01015 return STATUS_SUCCESS; 01016 } 01017 01018 #if defined(FE_SB) 01019 NTSTATUS 01020 FE_TranslateOutputToUnicode( 01021 IN PCONSOLE_INFORMATION Console, 01022 IN OUT PCHAR_INFO OutputBuffer, 01023 IN COORD Size 01024 ) 01025 // this is used when the app writes oem to the output buffer 01026 // we want UnicodeOem or Unicode in the buffer, depending on font & fullscreen 01027 { 01028 SHORT i,j; 01029 UINT Codepage; 01030 CHAR AsciiDbcs[2]; 01031 WCHAR UnicodeDbcs[2]; 01032 DBGCHARS(("FE_TranslateOutputToUnicode %lx %lx (%lx,%lx)\n", 01033 Console, OutputBuffer, Size.X, Size.Y)); 01034 01035 if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) && 01036 ((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) { 01037 if (CONSOLE_IS_DBCS_ENABLED() && 01038 (Console->OutputCP != WINDOWSCP) ) { 01039 Codepage = USACP; 01040 } 01041 else 01042 // we want UnicodeOem characters 01043 Codepage = WINDOWSCP; 01044 } else { 01045 // we want real Unicode characters 01046 Codepage = Console->OutputCP; 01047 } 01048 01049 for (i=0; i < Size.Y; i++) { 01050 for (j=0; j < Size.X; j++) { 01051 OutputBuffer->Attributes &= ~COMMON_LVB_SBCSDBCS; 01052 if (IsDBCSLeadByteConsole(OutputBuffer->Char.AsciiChar,&Console->OutputCPInfo)) { 01053 if (j < Size.X-1) { // -1 is safe DBCS in buffer 01054 j++; 01055 AsciiDbcs[0] = OutputBuffer->Char.AsciiChar; 01056 AsciiDbcs[1] = (OutputBuffer+1)->Char.AsciiChar; 01057 ConvertOutputToUnicode(Codepage, 01058 &AsciiDbcs[0], 01059 2, 01060 &UnicodeDbcs[0], 01061 2); 01062 OutputBuffer->Char.UnicodeChar = UnicodeDbcs[0]; 01063 OutputBuffer->Attributes |= COMMON_LVB_LEADING_BYTE; 01064 OutputBuffer++; 01065 OutputBuffer->Char.UnicodeChar = UNICODE_DBCS_PADDING; 01066 OutputBuffer->Attributes &= ~COMMON_LVB_SBCSDBCS; 01067 OutputBuffer->Attributes |= COMMON_LVB_TRAILING_BYTE; 01068 OutputBuffer++; 01069 } 01070 else { 01071 OutputBuffer->Char.UnicodeChar = UNICODE_SPACE; 01072 OutputBuffer++; 01073 } 01074 } 01075 else { 01076 CHAR c; 01077 c=OutputBuffer->Char.AsciiChar; 01078 ConvertOutputToUnicode(Codepage, 01079 &c, 01080 1, 01081 &OutputBuffer->Char.UnicodeChar, 01082 1); 01083 OutputBuffer++; 01084 } 01085 } 01086 } 01087 return STATUS_SUCCESS; 01088 } 01089 #endif 01090 01091 01092 NTSTATUS 01093 SB_TranslateOutputToAnsiUnicode ( 01094 IN PCONSOLE_INFORMATION Console, 01095 IN OUT PCHAR_INFO OutputBuffer, 01096 IN COORD Size 01097 ) 01098 // this is used when the app writes unicode to the output buffer 01099 { 01100 SHORT i,j; 01101 DBGCHARS(("TranslateOutputToAnsiUnicode\n")); 01102 01103 j = Size.X * Size.Y; 01104 01105 for (i=0;i<j;i++,OutputBuffer++) { 01106 RealUnicodeToFalseUnicode(&OutputBuffer->Char.UnicodeChar, 01107 1, 01108 Console->OutputCP 01109 ); 01110 } 01111 return STATUS_SUCCESS; 01112 } 01113 01114 NTSTATUS 01115 FE_TranslateOutputToAnsiUnicodeInternal( 01116 IN PCONSOLE_INFORMATION Console, 01117 IN OUT PCHAR_INFO OutputBuffer, 01118 IN COORD Size, 01119 IN OUT PCHAR_INFO OutputBufferR, 01120 IN BOOL fRealUnicodeToFalseUnicode 01121 ) 01122 // this is used when the app writes unicode to the output buffer 01123 { 01124 SHORT i,j; 01125 DBGCHARS(("TranslateOutputToAnsiUnicode\n")); 01126 01127 for (i=0; i < Size.Y; i++) { 01128 for (j=0; j < Size.X; j++) { 01129 WCHAR wch = OutputBuffer->Char.UnicodeChar; 01130 01131 if (fRealUnicodeToFalseUnicode) { 01132 RealUnicodeToFalseUnicode(&OutputBuffer->Char.UnicodeChar, 01133 1, 01134 Console->OutputCP 01135 ); 01136 } 01137 01138 if (OutputBufferR) { 01139 OutputBufferR->Attributes = OutputBuffer->Attributes & ~COMMON_LVB_SBCSDBCS; 01140 if (IsConsoleFullWidth(Console->hDC, 01141 Console->OutputCP,OutputBuffer->Char.UnicodeChar)) { 01142 if (j == Size.X-1){ 01143 OutputBufferR->Char.UnicodeChar = UNICODE_SPACE; 01144 } 01145 else{ 01146 OutputBufferR->Char.UnicodeChar = OutputBuffer->Char.UnicodeChar; 01147 OutputBufferR->Attributes |= COMMON_LVB_LEADING_BYTE; 01148 OutputBufferR++; 01149 OutputBufferR->Char.UnicodeChar = UNICODE_DBCS_PADDING; 01150 OutputBufferR->Attributes = OutputBuffer->Attributes & ~COMMON_LVB_SBCSDBCS; 01151 OutputBufferR->Attributes |= COMMON_LVB_TRAILING_BYTE; 01152 } 01153 } 01154 else{ 01155 OutputBufferR->Char.UnicodeChar = OutputBuffer->Char.UnicodeChar; 01156 } 01157 OutputBufferR++; 01158 } 01159 01160 if (IsConsoleFullWidth(Console->hDC, 01161 Console->OutputCP, 01162 wch)) { 01163 if (j != Size.X-1){ 01164 j++; 01165 } 01166 } 01167 OutputBuffer++; 01168 } 01169 } 01170 return STATUS_SUCCESS; 01171 } 01172 01173 NTSTATUS 01174 FE_TranslateOutputToAnsiUnicode( 01175 IN PCONSOLE_INFORMATION Console, 01176 IN OUT PCHAR_INFO OutputBuffer, 01177 IN COORD Size, 01178 IN OUT PCHAR_INFO OutputBufferR 01179 ) 01180 // this is used when the app writes unicode to the output buffer 01181 { 01182 return FE_TranslateOutputToAnsiUnicodeInternal(Console, 01183 OutputBuffer, 01184 Size, 01185 OutputBufferR, 01186 TRUE 01187 ); 01188 } 01189 01190 NTSTATUS 01191 TranslateOutputToPaddingUnicode( 01192 IN PCONSOLE_INFORMATION Console, 01193 IN OUT PCHAR_INFO OutputBuffer, 01194 IN COORD Size, 01195 IN OUT PCHAR_INFO OutputBufferR 01196 ) 01197 { 01198 return FE_TranslateOutputToAnsiUnicodeInternal(Console, 01199 OutputBuffer, 01200 Size, 01201 OutputBufferR, 01202 FALSE 01203 ); 01204 } 01205 01206 ULONG 01207 SrvReadConsoleOutput( 01208 IN OUT PCSR_API_MSG m, 01209 IN OUT PCSR_REPLY_STATUS ReplyStatus 01210 ) 01211 { 01212 PCONSOLE_READCONSOLEOUTPUT_MSG a = (PCONSOLE_READCONSOLEOUTPUT_MSG)&m->u.ApiMessageData; 01213 PCONSOLE_INFORMATION Console; 01214 PHANDLE_DATA HandleData; 01215 NTSTATUS Status; 01216 PCHAR_INFO Buffer; 01217 01218 DBGOUTPUT(("SrvReadConsoleOutput\n")); 01219 Status = ApiPreamble(a->ConsoleHandle, 01220 &Console 01221 ); 01222 if (!NT_SUCCESS(Status)) { 01223 return Status; 01224 } 01225 Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(), 01226 a->OutputHandle, 01227 CONSOLE_OUTPUT_HANDLE, 01228 GENERIC_READ, 01229 &HandleData 01230 ); 01231 if (!NT_SUCCESS(Status)) { 01232 // 01233 // a region of zero size is indicated by the right and bottom 01234 // coordinates being less than the left and top. 01235 // 01236 01237 a->CharRegion.Right = (USHORT) (a->CharRegion.Left-1); 01238 a->CharRegion.Bottom = (USHORT) (a->CharRegion.Top-1); 01239 } 01240 else { 01241 COORD BufferSize; 01242 01243 BufferSize.X = (SHORT)(a->CharRegion.Right - a->CharRegion.Left + 1); 01244 BufferSize.Y = (SHORT)(a->CharRegion.Bottom - a->CharRegion.Top + 1); 01245 01246 if ((BufferSize.X == 1) && (BufferSize.Y == 1)) { 01247 Buffer = &a->Char; 01248 } 01249 else { 01250 Buffer = a->BufPtr; 01251 if (!CsrValidateMessageBuffer(m, &a->BufPtr, BufferSize.X * BufferSize.Y, sizeof(*Buffer))) { 01252 UnlockConsole(Console); 01253 return STATUS_INVALID_PARAMETER; 01254 } 01255 } 01256 01257 Status = ReadScreenBuffer(HandleData->Buffer.ScreenBuffer, 01258 Buffer, 01259 &a->CharRegion 01260 ); 01261 if (!a->Unicode) { 01262 TranslateOutputToOem(Console, 01263 Buffer, 01264 BufferSize 01265 ); 01266 } else if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) && 01267 !(Console->FullScreenFlags & CONSOLE_FULLSCREEN)) { 01268 TranslateOutputToOemUnicode(Console, 01269 Buffer, 01270 BufferSize 01271 #if defined(FE_SB) 01272 , 01273 TRUE 01274 #endif 01275 ); 01276 } 01277 } 01278 UnlockConsole(Console); 01279 return Status; 01280 UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message 01281 } 01282 01283 ULONG 01284 SrvWriteConsoleOutput( 01285 IN OUT PCSR_API_MSG m, 01286 IN OUT PCSR_REPLY_STATUS ReplyStatus 01287 ) 01288 { 01289 PCONSOLE_WRITECONSOLEOUTPUT_MSG a = (PCONSOLE_WRITECONSOLEOUTPUT_MSG)&m->u.ApiMessageData; 01290 PSCREEN_INFORMATION ScreenBufferInformation; 01291 PCONSOLE_INFORMATION Console; 01292 PHANDLE_DATA HandleData; 01293 NTSTATUS Status; 01294 PCHAR_INFO Buffer; 01295 #if defined(FE_SB) 01296 PCHAR_INFO TransBuffer = NULL; 01297 #endif 01298 01299 DBGOUTPUT(("SrvWriteConsoleOutput\n")); 01300 Status = ApiPreamble(a->ConsoleHandle, 01301 &Console 01302 ); 01303 if (!NT_SUCCESS(Status)) { 01304 return Status; 01305 } 01306 Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(), 01307 a->OutputHandle, 01308 CONSOLE_OUTPUT_HANDLE, 01309 GENERIC_WRITE, 01310 &HandleData 01311 ); 01312 if (!NT_SUCCESS(Status)) { 01313 01314 // 01315 // a region of zero size is indicated by the right and bottom 01316 // coordinates being less than the left and top. 01317 // 01318 01319 a->CharRegion.Right = (USHORT) (a->CharRegion.Left-1); 01320 a->CharRegion.Bottom = (USHORT) (a->CharRegion.Top-1); 01321 } else { 01322 01323 COORD BufferSize; 01324 ULONG NumBytes; 01325 01326 BufferSize.X = (SHORT)(a->CharRegion.Right - a->CharRegion.Left + 1); 01327 BufferSize.Y = (SHORT)(a->CharRegion.Bottom - a->CharRegion.Top + 1); 01328 NumBytes = BufferSize.X * BufferSize.Y * sizeof(*Buffer); 01329 01330 if ((BufferSize.X == 1) && (BufferSize.Y == 1)) { 01331 Buffer = &a->Char; 01332 } else if (a->ReadVM) { 01333 Buffer = ConsoleHeapAlloc(MAKE_TAG( TMP_TAG ),NumBytes); 01334 if (Buffer == NULL) { 01335 UnlockConsole(Console); 01336 return (ULONG)STATUS_NO_MEMORY; 01337 } 01338 Status = NtReadVirtualMemory(CONSOLE_CLIENTPROCESSHANDLE(), 01339 a->BufPtr, 01340 Buffer, 01341 NumBytes, 01342 NULL 01343 ); 01344 if (!NT_SUCCESS(Status)) { 01345 ConsoleHeapFree(Buffer); 01346 UnlockConsole(Console); 01347 return (ULONG)STATUS_NO_MEMORY; 01348 } 01349 } else { 01350 Buffer = a->BufPtr; 01351 if (!CsrValidateMessageBuffer(m, &a->BufPtr, NumBytes, sizeof(BYTE))) { 01352 UnlockConsole(Console); 01353 return STATUS_INVALID_PARAMETER; 01354 } 01355 } 01356 ScreenBufferInformation = HandleData->Buffer.ScreenBuffer; 01357 01358 if (!a->Unicode) { 01359 TranslateOutputToUnicode(Console, 01360 Buffer, 01361 BufferSize 01362 ); 01363 #if defined(FE_SB) 01364 Status = WriteScreenBuffer(ScreenBufferInformation, 01365 Buffer, 01366 &a->CharRegion 01367 ); 01368 #endif 01369 } else if ((Console->CurrentScreenBuffer->Flags & CONSOLE_OEMFONT_DISPLAY) && 01370 ((Console->FullScreenFlags & CONSOLE_FULLSCREEN) == 0)) { 01371 #if defined(FE_SB) 01372 if (CONSOLE_IS_DBCS_OUTPUTCP(Console)) { 01373 TransBuffer = (PCHAR_INFO)ConsoleHeapAlloc(MAKE_TAG( TMP_DBCS_TAG ),(BufferSize.Y * BufferSize.X) * 2 * sizeof(CHAR_INFO)); 01374 if (TransBuffer == NULL) { 01375 UnlockConsole(Console); 01376 return (ULONG)STATUS_NO_MEMORY; 01377 } 01378 FE_TranslateOutputToAnsiUnicode(Console, 01379 Buffer, 01380 BufferSize, 01381 &TransBuffer[0] 01382 ); 01383 Status = WriteScreenBuffer(ScreenBufferInformation, 01384 &TransBuffer[0], 01385 &a->CharRegion 01386 ); 01387 ConsoleHeapFree(TransBuffer); 01388 } 01389 else { 01390 SB_TranslateOutputToAnsiUnicode(Console, 01391 Buffer, 01392 BufferSize 01393 ); 01394 Status = WriteScreenBuffer(ScreenBufferInformation, 01395 Buffer, 01396 &a->CharRegion 01397 ); 01398 } 01399 #else 01400 TranslateOutputToAnsiUnicode(Console, 01401 Buffer, 01402 BufferSize 01403 ); 01404 #endif 01405 } 01406 #if defined(FE_SB) 01407 else 01408 #endif 01409 Status = WriteScreenBuffer(ScreenBufferInformation, 01410 Buffer, 01411 &a->CharRegion 01412 ); 01413 01414 if (a->ReadVM) { 01415 ConsoleHeapFree(Buffer); 01416 } 01417 if (NT_SUCCESS(Status)) { 01418 01419 // 01420 // cause screen to be updated 01421 // 01422 01423 #if defined(FE_SB) 01424 if (CONSOLE_IS_DBCS_OUTPUTCP(Console) && 01425 Console->Flags & CONSOLE_JUST_VDM_UNREGISTERED ){ 01426 int MouseRec; 01427 MouseRec = Console->InputBuffer.InputMode; 01428 Console->InputBuffer.InputMode &= ~ENABLE_MOUSE_INPUT; 01429 Console->CurrentScreenBuffer->BufferInfo.TextInfo.Flags &= ~TEXT_VALID_HINT; 01430 WriteToScreen(ScreenBufferInformation,&a->CharRegion ); 01431 Console->CurrentScreenBuffer->BufferInfo.TextInfo.Flags |= TEXT_VALID_HINT; 01432 Console->InputBuffer.InputMode = MouseRec; 01433 } 01434 else 01435 #endif 01436 WriteToScreen(ScreenBufferInformation, 01437 &a->CharRegion 01438 ); 01439 } 01440 } 01441 UnlockConsole(Console); 01442 return Status; 01443 UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message 01444 } 01445 01446 01447 ULONG 01448 SrvReadConsoleOutputString( 01449 IN OUT PCSR_API_MSG m, 01450 IN OUT PCSR_REPLY_STATUS ReplyStatus 01451 ) 01452 { 01453 NTSTATUS Status; 01454 PCONSOLE_INFORMATION Console; 01455 PHANDLE_DATA HandleData; 01456 PVOID Buffer; 01457 PCONSOLE_READCONSOLEOUTPUTSTRING_MSG a = (PCONSOLE_READCONSOLEOUTPUTSTRING_MSG)&m->u.ApiMessageData; 01458 ULONG nSize; 01459 01460 Status = ApiPreamble(a->ConsoleHandle, 01461 &Console 01462 ); 01463 if (!NT_SUCCESS(Status)) { 01464 return Status; 01465 } 01466 Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(), 01467 a->OutputHandle, 01468 CONSOLE_OUTPUT_HANDLE, 01469 GENERIC_READ, 01470 &HandleData 01471 ); 01472 if (!NT_SUCCESS(Status)) { 01473 01474 // 01475 // a region of zero size is indicated by the right and bottom 01476 // coordinates being less than the left and top. 01477 // 01478 01479 a->NumRecords = 0; 01480 } else { 01481 if (a->StringType == CONSOLE_ASCII) 01482 nSize = sizeof(CHAR); 01483 else 01484 nSize = sizeof(WORD); 01485 if ((a->NumRecords*nSize) > sizeof(a->String)) { 01486 Buffer = a->BufPtr; 01487 if (!CsrValidateMessageBuffer(m, &a->BufPtr, a->NumRecords, nSize)) { 01488 UnlockConsole(Console); 01489 return STATUS_INVALID_PARAMETER; 01490 } 01491 } 01492 else { 01493 Buffer = a->String; 01494 } 01495 Status = ReadOutputString(HandleData->Buffer.ScreenBuffer, 01496 Buffer, 01497 a->ReadCoord, 01498 a->StringType, 01499 &a->NumRecords 01500 ); 01501 } 01502 UnlockConsole(Console); 01503 return Status; 01504 UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message 01505 } 01506 01507 ULONG 01508 SrvWriteConsoleOutputString( 01509 IN OUT PCSR_API_MSG m, 01510 IN OUT PCSR_REPLY_STATUS ReplyStatus 01511 ) 01512 { 01513 PCONSOLE_WRITECONSOLEOUTPUTSTRING_MSG a = (PCONSOLE_WRITECONSOLEOUTPUTSTRING_MSG)&m->u.ApiMessageData; 01514 NTSTATUS Status; 01515 PCONSOLE_INFORMATION Console; 01516 PHANDLE_DATA HandleData; 01517 PVOID Buffer; 01518 ULONG nSize; 01519 01520 Status = ApiPreamble(a->ConsoleHandle, 01521 &Console 01522 ); 01523 if (!NT_SUCCESS(Status)) { 01524 return Status; 01525 } 01526 Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(), 01527 a->OutputHandle, 01528 CONSOLE_OUTPUT_HANDLE, 01529 GENERIC_WRITE, 01530 &HandleData 01531 ); 01532 if (!NT_SUCCESS(Status)) { 01533 a->NumRecords = 0; 01534 } else { 01535 if (a->WriteCoord.X < 0 || 01536 a->WriteCoord.Y < 0) { 01537 Status = STATUS_INVALID_PARAMETER; 01538 } else { 01539 if (a->StringType == CONSOLE_ASCII) 01540 nSize = sizeof(CHAR); 01541 else 01542 nSize = sizeof(WORD); 01543 if ((a->NumRecords*nSize) > sizeof(a->String)) { 01544 Buffer = a->BufPtr; 01545 if (!CsrValidateMessageBuffer(m, &a->BufPtr, a->NumRecords, nSize)) { 01546 UnlockConsole(Console); 01547 return STATUS_INVALID_PARAMETER; 01548 } 01549 } 01550 else { 01551 Buffer = a->String; 01552 } 01553 Status = WriteOutputString(HandleData->Buffer.ScreenBuffer, 01554 Buffer, 01555 a->WriteCoord, 01556 a->StringType, 01557 &a->NumRecords, 01558 NULL 01559 ); 01560 } 01561 } 01562 UnlockConsole(Console); 01563 return Status; 01564 UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message 01565 } 01566 01567 ULONG 01568 SrvFillConsoleOutput( 01569 IN OUT PCSR_API_MSG m, 01570 IN OUT PCSR_REPLY_STATUS ReplyStatus 01571 ) 01572 { 01573 PCONSOLE_FILLCONSOLEOUTPUT_MSG a = (PCONSOLE_FILLCONSOLEOUTPUT_MSG)&m->u.ApiMessageData; 01574 NTSTATUS Status; 01575 PCONSOLE_INFORMATION Console; 01576 PHANDLE_DATA HandleData; 01577 01578 Status = ApiPreamble(a->ConsoleHandle, 01579 &Console 01580 ); 01581 if (!NT_SUCCESS(Status)) { 01582 return Status; 01583 } 01584 Status = DereferenceIoHandle(CONSOLE_PERPROCESSDATA(), 01585 a->OutputHandle, 01586 CONSOLE_OUTPUT_HANDLE, 01587 GENERIC_WRITE, 01588 &HandleData 01589 ); 01590 if (!NT_SUCCESS(Status)) { 01591 a->Length = 0; 01592 } else { 01593 Status = FillOutput(HandleData->Buffer.ScreenBuffer, 01594 a->Element, 01595 a->WriteCoord, 01596 a->ElementType, 01597 &a->Length 01598 ); 01599 } 01600 UnlockConsole(Console); 01601 return Status; 01602 UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message 01603 } 01604 01605 01606 ULONG 01607 SrvCreateConsoleScreenBuffer( 01608 IN OUT PCSR_API_MSG m, 01609 IN OUT PCSR_REPLY_STATUS ReplyStatus 01610 ) 01611 01612 /*++ 01613 01614 Routine Description: 01615 01616 This routine creates a screen buffer and returns a handle to it. 01617 01618 Arguments: 01619 01620 ApiMessageData - Points to parameter structure. 01621 01622 Return Value: 01623 01624 --*/ 01625 01626 { 01627 PCONSOLE_CREATESCREENBUFFER_MSG a = (PCONSOLE_CREATESCREENBUFFER_MSG)&m->u.ApiMessageData; 01628 NTSTATUS Status; 01629 PCONSOLE_INFORMATION Console; 01630 HANDLE Handle; 01631 PHANDLE_DATA HandleData; 01632 PCONSOLE_SHARE_ACCESS ShareAccess; 01633 CHAR_INFO Fill; 01634 COORD WindowSize; 01635 PSCREEN_INFORMATION ScreenInfo; 01636 PCONSOLE_PER_PROCESS_DATA ProcessData; 01637 ULONG HandleType; 01638 int FontIndex; 01639 01640 DBGOUTPUT(("SrvCreateConsoleScreenBuffer\n")); 01641 Status = ApiPreamble(a->ConsoleHandle, 01642 &Console 01643 ); 01644 if (!NT_SUCCESS(Status)) { 01645 return Status; 01646 } 01647 01648 if (a->Flags & CONSOLE_GRAPHICS_BUFFER) { 01649 if (!CsrValidateMessageBuffer(m, &a->GraphicsBufferInfo.lpBitMapInfo, a->GraphicsBufferInfo.dwBitMapInfoLength, sizeof(BYTE))) { 01650 UnlockConsole(Console); 01651 return STATUS_INVALID_PARAMETER; 01652 } 01653 } 01654 01655 try { 01656 Handle = (HANDLE) -1; 01657 ProcessData = CONSOLE_PERPROCESSDATA(); 01658 HandleType = (a->Flags & CONSOLE_GRAPHICS_BUFFER) ? 01659 CONSOLE_GRAPHICS_OUTPUT_HANDLE : CONSOLE_OUTPUT_HANDLE; 01660 if (a->InheritHandle) 01661 HandleType |= CONSOLE_INHERITABLE; 01662 Status = AllocateIoHandle(ProcessData, 01663 HandleType, 01664 &Handle 01665 ); 01666 if (!NT_SUCCESS(Status)) { 01667 leave; 01668 } 01669 Status = DereferenceIoHandleNoCheck(ProcessData, 01670 Handle, 01671 &HandleData 01672 ); 01673 ASSERT (NT_SUCCESS(Status)); 01674 if (!NT_SUCCESS(Status)) { 01675 leave; 01676 } 01677 01678 // 01679 // create new screen buffer 01680 // 01681 01682 Fill.Char.UnicodeChar = (WCHAR)' '; 01683 Fill.Attributes = Console->CurrentScreenBuffer->Attributes; 01684 WindowSize.X = (SHORT)CONSOLE_WINDOW_SIZE_X(Console->CurrentScreenBuffer); 01685 WindowSize.Y = (SHORT)CONSOLE_WINDOW_SIZE_Y(Console->CurrentScreenBuffer); 01686 FontIndex = FindCreateFont(CON_FAMILY(Console), 01687 CON_FACENAME(Console), 01688 CON_FONTSIZE(Console), 01689 CON_FONTWEIGHT(Console), 01690 CON_FONTCODEPAGE(Console) 01691 ); 01692 Status = CreateScreenBuffer(&ScreenInfo,WindowSize, 01693 FontIndex, 01694 WindowSize, 01695 Fill,Fill,Console, 01696 a->Flags,&a->GraphicsBufferInfo, 01697 &a->lpBitmap,&a->hMutex, 01698 CURSOR_SMALL_SIZE, 01699 NULL); 01700 if (!NT_SUCCESS(Status)) { 01701 leave; 01702 } 01703 InitializeOutputHandle(HandleData,ScreenInfo); 01704 ShareAccess = &ScreenInfo->ShareAccess; 01705 01706 Status = ConsoleAddShare(a->DesiredAccess, 01707 a->ShareMode, 01708 ShareAccess, 01709 HandleData 01710 ); 01711 if (!NT_SUCCESS(Status)) { 01712 HandleData->Buffer.ScreenBuffer->RefCount--; 01713 FreeScreenBuffer(ScreenInfo); 01714 leave; 01715 } 01716 InsertScreenBuffer(Console, ScreenInfo); 01717 a->Handle = INDEX_TO_HANDLE(Handle); 01718 } finally { 01719 if (!NT_SUCCESS(Status) && Handle != (HANDLE)-1) { 01720 FreeIoHandle(ProcessData, 01721 Handle 01722 ); 01723 } 01724 UnlockConsole(Console); 01725 } 01726 return Status; 01727 UNREFERENCED_PARAMETER(ReplyStatus); // get rid of unreferenced parameter warning message 01728 }

Generated on Sat May 15 19:39:45 2004 for test by doxygen 1.3.7