Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenconoutput.c
Go to the documentation of this file.
00001 /* 00002 * reactos/subsys/csrss/win32csr/conio.c 00003 * 00004 * Console I/O functions 00005 * 00006 * ReactOS Operating System 00007 */ 00008 00009 /* INCLUDES ******************************************************************/ 00010 00011 #define NDEBUG 00012 #include "w32csr.h" 00013 #include <debug.h> 00014 00015 /* GLOBALS *******************************************************************/ 00016 00017 #define ConioInitRect(Rect, top, left, bottom, right) \ 00018 ((Rect)->Top) = top; \ 00019 ((Rect)->Left) = left; \ 00020 ((Rect)->Bottom) = bottom; \ 00021 ((Rect)->Right) = right 00022 00023 #define ConioIsRectEmpty(Rect) \ 00024 (((Rect)->Left > (Rect)->Right) || ((Rect)->Top > (Rect)->Bottom)) 00025 00026 #define ConsoleUnicodeCharToAnsiChar(Console, dChar, sWChar) \ 00027 WideCharToMultiByte((Console)->OutputCodePage, 0, (sWChar), 1, (dChar), 1, NULL, NULL) 00028 00029 #define ConsoleAnsiCharToUnicodeChar(Console, dWChar, sChar) \ 00030 MultiByteToWideChar((Console)->OutputCodePage, 0, (sChar), 1, (dWChar), 1) 00031 00032 /* FUNCTIONS *****************************************************************/ 00033 00034 PBYTE FASTCALL 00035 ConioCoordToPointer(PCSRSS_SCREEN_BUFFER Buff, ULONG X, ULONG Y) 00036 { 00037 return &Buff->Buffer[2 * (((Y + Buff->VirtualY) % Buff->MaxY) * Buff->MaxX + X)]; 00038 } 00039 00040 static VOID FASTCALL 00041 ClearLineBuffer(PCSRSS_SCREEN_BUFFER Buff) 00042 { 00043 PBYTE Ptr = ConioCoordToPointer(Buff, 0, Buff->CurrentY); 00044 UINT Pos; 00045 00046 for (Pos = 0; Pos < Buff->MaxX; Pos++) 00047 { 00048 /* Fill the cell */ 00049 *Ptr++ = ' '; 00050 *Ptr++ = Buff->DefaultAttrib; 00051 } 00052 } 00053 00054 NTSTATUS FASTCALL 00055 CsrInitConsoleScreenBuffer(PCSRSS_CONSOLE Console, 00056 PCSRSS_SCREEN_BUFFER Buffer) 00057 { 00058 DPRINT("CsrInitConsoleScreenBuffer Size X %d Size Y %d\n", Buffer->MaxX, Buffer->MaxY); 00059 00060 Buffer->Header.Type = CONIO_SCREEN_BUFFER_MAGIC; 00061 Buffer->Header.Console = Console; 00062 Buffer->Header.HandleCount = 0; 00063 Buffer->ShowX = 0; 00064 Buffer->ShowY = 0; 00065 Buffer->VirtualY = 0; 00066 Buffer->Buffer = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY, Buffer->MaxX * Buffer->MaxY * 2); 00067 if (NULL == Buffer->Buffer) 00068 { 00069 return STATUS_INSUFFICIENT_RESOURCES; 00070 } 00071 ConioInitScreenBuffer(Console, Buffer); 00072 /* initialize buffer to be empty with default attributes */ 00073 for (Buffer->CurrentY = 0 ; Buffer->CurrentY < Buffer->MaxY; Buffer->CurrentY++) 00074 { 00075 ClearLineBuffer(Buffer); 00076 } 00077 Buffer->Mode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; 00078 Buffer->CurrentX = 0; 00079 Buffer->CurrentY = 0; 00080 00081 InsertHeadList(&Console->BufferList, &Buffer->ListEntry); 00082 return STATUS_SUCCESS; 00083 } 00084 00085 static VOID FASTCALL 00086 ConioNextLine(PCSRSS_SCREEN_BUFFER Buff, SMALL_RECT *UpdateRect, UINT *ScrolledLines) 00087 { 00088 /* If we hit bottom, slide the viewable screen */ 00089 if (++Buff->CurrentY == Buff->MaxY) 00090 { 00091 Buff->CurrentY--; 00092 if (++Buff->VirtualY == Buff->MaxY) 00093 { 00094 Buff->VirtualY = 0; 00095 } 00096 (*ScrolledLines)++; 00097 ClearLineBuffer(Buff); 00098 if (UpdateRect->Top != 0) 00099 { 00100 UpdateRect->Top--; 00101 } 00102 } 00103 UpdateRect->Left = 0; 00104 UpdateRect->Right = Buff->MaxX - 1; 00105 UpdateRect->Bottom = Buff->CurrentY; 00106 } 00107 00108 NTSTATUS FASTCALL 00109 ConioWriteConsole(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff, 00110 CHAR *Buffer, DWORD Length, BOOL Attrib) 00111 { 00112 UINT i; 00113 PBYTE Ptr; 00114 SMALL_RECT UpdateRect; 00115 LONG CursorStartX, CursorStartY; 00116 UINT ScrolledLines; 00117 00118 CursorStartX = Buff->CurrentX; 00119 CursorStartY = Buff->CurrentY; 00120 UpdateRect.Left = Buff->MaxX; 00121 UpdateRect.Top = Buff->CurrentY; 00122 UpdateRect.Right = -1; 00123 UpdateRect.Bottom = Buff->CurrentY; 00124 ScrolledLines = 0; 00125 00126 for (i = 0; i < Length; i++) 00127 { 00128 if (Buff->Mode & ENABLE_PROCESSED_OUTPUT) 00129 { 00130 /* --- LF --- */ 00131 if (Buffer[i] == '\n') 00132 { 00133 Buff->CurrentX = 0; 00134 ConioNextLine(Buff, &UpdateRect, &ScrolledLines); 00135 continue; 00136 } 00137 /* --- BS --- */ 00138 else if (Buffer[i] == '\b') 00139 { 00140 /* Only handle BS if we're not on the first pos of the first line */ 00141 if (0 != Buff->CurrentX || 0 != Buff->CurrentY) 00142 { 00143 if (0 == Buff->CurrentX) 00144 { 00145 /* slide virtual position up */ 00146 Buff->CurrentX = Buff->MaxX - 1; 00147 Buff->CurrentY--; 00148 UpdateRect.Top = min(UpdateRect.Top, (LONG)Buff->CurrentY); 00149 } 00150 else 00151 { 00152 Buff->CurrentX--; 00153 } 00154 Ptr = ConioCoordToPointer(Buff, Buff->CurrentX, Buff->CurrentY); 00155 Ptr[0] = ' '; 00156 Ptr[1] = Buff->DefaultAttrib; 00157 UpdateRect.Left = min(UpdateRect.Left, (LONG) Buff->CurrentX); 00158 UpdateRect.Right = max(UpdateRect.Right, (LONG) Buff->CurrentX); 00159 } 00160 continue; 00161 } 00162 /* --- CR --- */ 00163 else if (Buffer[i] == '\r') 00164 { 00165 Buff->CurrentX = 0; 00166 UpdateRect.Left = min(UpdateRect.Left, (LONG) Buff->CurrentX); 00167 UpdateRect.Right = max(UpdateRect.Right, (LONG) Buff->CurrentX); 00168 continue; 00169 } 00170 /* --- TAB --- */ 00171 else if (Buffer[i] == '\t') 00172 { 00173 UINT EndX; 00174 00175 UpdateRect.Left = min(UpdateRect.Left, (LONG)Buff->CurrentX); 00176 EndX = (Buff->CurrentX + 8) & ~7; 00177 if (EndX > Buff->MaxX) 00178 { 00179 EndX = Buff->MaxX; 00180 } 00181 Ptr = ConioCoordToPointer(Buff, Buff->CurrentX, Buff->CurrentY); 00182 while (Buff->CurrentX < EndX) 00183 { 00184 *Ptr++ = ' '; 00185 *Ptr++ = Buff->DefaultAttrib; 00186 Buff->CurrentX++; 00187 } 00188 UpdateRect.Right = max(UpdateRect.Right, (LONG) Buff->CurrentX - 1); 00189 if (Buff->CurrentX == Buff->MaxX) 00190 { 00191 if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT) 00192 { 00193 Buff->CurrentX = 0; 00194 ConioNextLine(Buff, &UpdateRect, &ScrolledLines); 00195 } 00196 else 00197 { 00198 Buff->CurrentX--; 00199 } 00200 } 00201 continue; 00202 } 00203 } 00204 UpdateRect.Left = min(UpdateRect.Left, (LONG)Buff->CurrentX); 00205 UpdateRect.Right = max(UpdateRect.Right, (LONG) Buff->CurrentX); 00206 Ptr = ConioCoordToPointer(Buff, Buff->CurrentX, Buff->CurrentY); 00207 Ptr[0] = Buffer[i]; 00208 if (Attrib) 00209 { 00210 Ptr[1] = Buff->DefaultAttrib; 00211 } 00212 Buff->CurrentX++; 00213 if (Buff->CurrentX == Buff->MaxX) 00214 { 00215 if (Buff->Mode & ENABLE_WRAP_AT_EOL_OUTPUT) 00216 { 00217 Buff->CurrentX = 0; 00218 ConioNextLine(Buff, &UpdateRect, &ScrolledLines); 00219 } 00220 else 00221 { 00222 Buff->CurrentX = CursorStartX; 00223 } 00224 } 00225 } 00226 00227 if (! ConioIsRectEmpty(&UpdateRect) && Buff == Console->ActiveBuffer) 00228 { 00229 ConioWriteStream(Console, &UpdateRect, CursorStartX, CursorStartY, ScrolledLines, 00230 Buffer, Length); 00231 } 00232 00233 return STATUS_SUCCESS; 00234 } 00235 00236 __inline BOOLEAN ConioGetIntersection( 00237 SMALL_RECT *Intersection, 00238 SMALL_RECT *Rect1, 00239 SMALL_RECT *Rect2) 00240 { 00241 if (ConioIsRectEmpty(Rect1) || 00242 (ConioIsRectEmpty(Rect2)) || 00243 (Rect1->Top > Rect2->Bottom) || 00244 (Rect1->Left > Rect2->Right) || 00245 (Rect1->Bottom < Rect2->Top) || 00246 (Rect1->Right < Rect2->Left)) 00247 { 00248 /* The rectangles do not intersect */ 00249 ConioInitRect(Intersection, 0, -1, 0, -1); 00250 return FALSE; 00251 } 00252 00253 ConioInitRect(Intersection, 00254 max(Rect1->Top, Rect2->Top), 00255 max(Rect1->Left, Rect2->Left), 00256 min(Rect1->Bottom, Rect2->Bottom), 00257 min(Rect1->Right, Rect2->Right)); 00258 00259 return TRUE; 00260 } 00261 00262 __inline BOOLEAN ConioGetUnion( 00263 SMALL_RECT *Union, 00264 SMALL_RECT *Rect1, 00265 SMALL_RECT *Rect2) 00266 { 00267 if (ConioIsRectEmpty(Rect1)) 00268 { 00269 if (ConioIsRectEmpty(Rect2)) 00270 { 00271 ConioInitRect(Union, 0, -1, 0, -1); 00272 return FALSE; 00273 } 00274 else 00275 { 00276 *Union = *Rect2; 00277 } 00278 } 00279 else if (ConioIsRectEmpty(Rect2)) 00280 { 00281 *Union = *Rect1; 00282 } 00283 else 00284 { 00285 ConioInitRect(Union, 00286 min(Rect1->Top, Rect2->Top), 00287 min(Rect1->Left, Rect2->Left), 00288 max(Rect1->Bottom, Rect2->Bottom), 00289 max(Rect1->Right, Rect2->Right)); 00290 } 00291 00292 return TRUE; 00293 } 00294 00295 /* Move from one rectangle to another. We must be careful about the order that 00296 * this is done, to avoid overwriting parts of the source before they are moved. */ 00297 static VOID FASTCALL 00298 ConioMoveRegion(PCSRSS_SCREEN_BUFFER ScreenBuffer, 00299 SMALL_RECT *SrcRegion, 00300 SMALL_RECT *DstRegion, 00301 SMALL_RECT *ClipRegion, 00302 WORD Fill) 00303 { 00304 int Width = ConioRectWidth(SrcRegion); 00305 int Height = ConioRectHeight(SrcRegion); 00306 int SX, SY; 00307 int DX, DY; 00308 int XDelta, YDelta; 00309 int i, j; 00310 00311 SY = SrcRegion->Top; 00312 DY = DstRegion->Top; 00313 YDelta = 1; 00314 if (SY < DY) 00315 { 00316 /* Moving down: work from bottom up */ 00317 SY = SrcRegion->Bottom; 00318 DY = DstRegion->Bottom; 00319 YDelta = -1; 00320 } 00321 for (i = 0; i < Height; i++) 00322 { 00323 PWORD SRow = (PWORD)ConioCoordToPointer(ScreenBuffer, 0, SY); 00324 PWORD DRow = (PWORD)ConioCoordToPointer(ScreenBuffer, 0, DY); 00325 00326 SX = SrcRegion->Left; 00327 DX = DstRegion->Left; 00328 XDelta = 1; 00329 if (SX < DX) 00330 { 00331 /* Moving right: work from right to left */ 00332 SX = SrcRegion->Right; 00333 DX = DstRegion->Right; 00334 XDelta = -1; 00335 } 00336 for (j = 0; j < Width; j++) 00337 { 00338 WORD Cell = SRow[SX]; 00339 if (SX >= ClipRegion->Left && SX <= ClipRegion->Right 00340 && SY >= ClipRegion->Top && SY <= ClipRegion->Bottom) 00341 { 00342 SRow[SX] = Fill; 00343 } 00344 if (DX >= ClipRegion->Left && DX <= ClipRegion->Right 00345 && DY >= ClipRegion->Top && DY <= ClipRegion->Bottom) 00346 { 00347 DRow[DX] = Cell; 00348 } 00349 SX += XDelta; 00350 DX += XDelta; 00351 } 00352 SY += YDelta; 00353 DY += YDelta; 00354 } 00355 } 00356 00357 CSR_API(CsrWriteConsole) 00358 { 00359 NTSTATUS Status; 00360 PCHAR Buffer; 00361 PCSRSS_SCREEN_BUFFER Buff; 00362 PCSRSS_CONSOLE Console; 00363 DWORD Written = 0; 00364 ULONG Length; 00365 ULONG CharSize = (Request->Data.WriteConsoleRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR)); 00366 00367 DPRINT("CsrWriteConsole\n"); 00368 00369 if (Request->Header.u1.s1.TotalLength 00370 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE) 00371 + (Request->Data.WriteConsoleRequest.NrCharactersToWrite * CharSize)) 00372 { 00373 DPRINT1("Invalid request size\n"); 00374 return STATUS_INVALID_PARAMETER; 00375 } 00376 00377 Status = ConioLockScreenBuffer(ProcessData, Request->Data.WriteConsoleRequest.ConsoleHandle, &Buff, GENERIC_WRITE); 00378 if (! NT_SUCCESS(Status)) 00379 { 00380 return Status; 00381 } 00382 Console = Buff->Header.Console; 00383 00384 if (Console->UnpauseEvent) 00385 { 00386 Status = NtDuplicateObject(GetCurrentProcess(), Console->UnpauseEvent, 00387 ProcessData->ProcessHandle, &Request->Data.WriteConsoleRequest.UnpauseEvent, 00388 SYNCHRONIZE, 0, 0); 00389 ConioUnlockScreenBuffer(Buff); 00390 return NT_SUCCESS(Status) ? STATUS_PENDING : Status; 00391 } 00392 00393 if(Request->Data.WriteConsoleRequest.Unicode) 00394 { 00395 Length = WideCharToMultiByte(Console->OutputCodePage, 0, 00396 (PWCHAR)Request->Data.WriteConsoleRequest.Buffer, 00397 Request->Data.WriteConsoleRequest.NrCharactersToWrite, 00398 NULL, 0, NULL, NULL); 00399 Buffer = RtlAllocateHeap(GetProcessHeap(), 0, Length); 00400 if (Buffer) 00401 { 00402 WideCharToMultiByte(Console->OutputCodePage, 0, 00403 (PWCHAR)Request->Data.WriteConsoleRequest.Buffer, 00404 Request->Data.WriteConsoleRequest.NrCharactersToWrite, 00405 Buffer, Length, NULL, NULL); 00406 } 00407 else 00408 { 00409 Status = STATUS_NO_MEMORY; 00410 } 00411 } 00412 else 00413 { 00414 Buffer = (PCHAR)Request->Data.WriteConsoleRequest.Buffer; 00415 } 00416 00417 if (Buffer) 00418 { 00419 if (NT_SUCCESS(Status)) 00420 { 00421 Status = ConioWriteConsole(Console, Buff, Buffer, 00422 Request->Data.WriteConsoleRequest.NrCharactersToWrite, TRUE); 00423 if (NT_SUCCESS(Status)) 00424 { 00425 Written = Request->Data.WriteConsoleRequest.NrCharactersToWrite; 00426 } 00427 } 00428 if (Request->Data.WriteConsoleRequest.Unicode) 00429 { 00430 RtlFreeHeap(GetProcessHeap(), 0, Buffer); 00431 } 00432 } 00433 ConioUnlockScreenBuffer(Buff); 00434 00435 Request->Data.WriteConsoleRequest.NrCharactersWritten = Written; 00436 00437 return Status; 00438 } 00439 00440 VOID WINAPI 00441 ConioDeleteScreenBuffer(PCSRSS_SCREEN_BUFFER Buffer) 00442 { 00443 PCSRSS_CONSOLE Console = Buffer->Header.Console; 00444 00445 RemoveEntryList(&Buffer->ListEntry); 00446 if (Buffer == Console->ActiveBuffer) 00447 { 00448 /* Deleted active buffer; switch to most recently created */ 00449 Console->ActiveBuffer = NULL; 00450 if (!IsListEmpty(&Console->BufferList)) 00451 { 00452 Console->ActiveBuffer = CONTAINING_RECORD(Console->BufferList.Flink, CSRSS_SCREEN_BUFFER, ListEntry); 00453 ConioDrawConsole(Console); 00454 } 00455 } 00456 00457 HeapFree(Win32CsrApiHeap, 0, Buffer->Buffer); 00458 HeapFree(Win32CsrApiHeap, 0, Buffer); 00459 } 00460 00461 VOID FASTCALL 00462 ConioDrawConsole(PCSRSS_CONSOLE Console) 00463 { 00464 SMALL_RECT Region; 00465 00466 ConioInitRect(&Region, 0, 0, Console->Size.Y - 1, Console->Size.X - 1); 00467 00468 ConioDrawRegion(Console, &Region); 00469 } 00470 00471 CSR_API(CsrGetScreenBufferInfo) 00472 { 00473 NTSTATUS Status; 00474 PCSRSS_CONSOLE Console; 00475 PCSRSS_SCREEN_BUFFER Buff; 00476 PCONSOLE_SCREEN_BUFFER_INFO pInfo; 00477 00478 DPRINT("CsrGetScreenBufferInfo\n"); 00479 00480 Status = ConioLockScreenBuffer(ProcessData, Request->Data.ScreenBufferInfoRequest.ConsoleHandle, &Buff, GENERIC_READ); 00481 if (! NT_SUCCESS(Status)) 00482 { 00483 return Status; 00484 } 00485 Console = Buff->Header.Console; 00486 pInfo = &Request->Data.ScreenBufferInfoRequest.Info; 00487 pInfo->dwSize.X = Buff->MaxX; 00488 pInfo->dwSize.Y = Buff->MaxY; 00489 pInfo->dwCursorPosition.X = Buff->CurrentX; 00490 pInfo->dwCursorPosition.Y = Buff->CurrentY; 00491 pInfo->wAttributes = Buff->DefaultAttrib; 00492 pInfo->srWindow.Left = Buff->ShowX; 00493 pInfo->srWindow.Right = Buff->ShowX + Console->Size.X - 1; 00494 pInfo->srWindow.Top = Buff->ShowY; 00495 pInfo->srWindow.Bottom = Buff->ShowY + Console->Size.Y - 1; 00496 pInfo->dwMaximumWindowSize.X = Buff->MaxX; 00497 pInfo->dwMaximumWindowSize.Y = Buff->MaxY; 00498 ConioUnlockScreenBuffer(Buff); 00499 00500 return STATUS_SUCCESS; 00501 } 00502 00503 CSR_API(CsrSetCursor) 00504 { 00505 NTSTATUS Status; 00506 PCSRSS_CONSOLE Console; 00507 PCSRSS_SCREEN_BUFFER Buff; 00508 LONG OldCursorX, OldCursorY; 00509 LONG NewCursorX, NewCursorY; 00510 00511 DPRINT("CsrSetCursor\n"); 00512 00513 Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff, GENERIC_WRITE); 00514 if (! NT_SUCCESS(Status)) 00515 { 00516 return Status; 00517 } 00518 Console = Buff->Header.Console; 00519 00520 NewCursorX = Request->Data.SetCursorRequest.Position.X; 00521 NewCursorY = Request->Data.SetCursorRequest.Position.Y; 00522 if (NewCursorX < 0 || NewCursorX >= Buff->MaxX || 00523 NewCursorY < 0 || NewCursorY >= Buff->MaxY) 00524 { 00525 ConioUnlockScreenBuffer(Buff); 00526 return STATUS_INVALID_PARAMETER; 00527 } 00528 OldCursorX = Buff->CurrentX; 00529 OldCursorY = Buff->CurrentY; 00530 Buff->CurrentX = NewCursorX; 00531 Buff->CurrentY = NewCursorY; 00532 if (Buff == Console->ActiveBuffer) 00533 { 00534 if (! ConioSetScreenInfo(Console, Buff, OldCursorX, OldCursorY)) 00535 { 00536 ConioUnlockScreenBuffer(Buff); 00537 return STATUS_UNSUCCESSFUL; 00538 } 00539 } 00540 00541 ConioUnlockScreenBuffer(Buff); 00542 00543 return STATUS_SUCCESS; 00544 } 00545 00546 static VOID FASTCALL 00547 ConioComputeUpdateRect(PCSRSS_SCREEN_BUFFER Buff, SMALL_RECT *UpdateRect, COORD *Start, UINT Length) 00548 { 00549 if (Buff->MaxX <= Start->X + Length) 00550 { 00551 UpdateRect->Left = 0; 00552 } 00553 else 00554 { 00555 UpdateRect->Left = Start->X; 00556 } 00557 if (Buff->MaxX <= Start->X + Length) 00558 { 00559 UpdateRect->Right = Buff->MaxX - 1; 00560 } 00561 else 00562 { 00563 UpdateRect->Right = Start->X + Length - 1; 00564 } 00565 UpdateRect->Top = Start->Y; 00566 UpdateRect->Bottom = Start->Y+ (Start->X + Length - 1) / Buff->MaxX; 00567 if (Buff->MaxY <= UpdateRect->Bottom) 00568 { 00569 UpdateRect->Bottom = Buff->MaxY - 1; 00570 } 00571 } 00572 00573 CSR_API(CsrWriteConsoleOutputChar) 00574 { 00575 NTSTATUS Status; 00576 PCHAR String, tmpString = NULL; 00577 PBYTE Buffer; 00578 PCSRSS_CONSOLE Console; 00579 PCSRSS_SCREEN_BUFFER Buff; 00580 DWORD X, Y, Length, CharSize, Written = 0; 00581 SMALL_RECT UpdateRect; 00582 00583 DPRINT("CsrWriteConsoleOutputChar\n"); 00584 00585 CharSize = (Request->Data.WriteConsoleOutputCharRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR)); 00586 00587 if (Request->Header.u1.s1.TotalLength 00588 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_CHAR) 00589 + (Request->Data.WriteConsoleOutputCharRequest.Length * CharSize)) 00590 { 00591 DPRINT1("Invalid request size\n"); 00592 return STATUS_INVALID_PARAMETER; 00593 } 00594 00595 Status = ConioLockScreenBuffer(ProcessData, 00596 Request->Data.WriteConsoleOutputCharRequest.ConsoleHandle, 00597 &Buff, 00598 GENERIC_WRITE); 00599 if (NT_SUCCESS(Status)) 00600 { 00601 Console = Buff->Header.Console; 00602 if(Request->Data.WriteConsoleOutputCharRequest.Unicode) 00603 { 00604 Length = WideCharToMultiByte(Console->OutputCodePage, 0, 00605 (PWCHAR)Request->Data.WriteConsoleOutputCharRequest.String, 00606 Request->Data.WriteConsoleOutputCharRequest.Length, 00607 NULL, 0, NULL, NULL); 00608 tmpString = String = RtlAllocateHeap(GetProcessHeap(), 0, Length); 00609 if (String) 00610 { 00611 WideCharToMultiByte(Console->OutputCodePage, 0, 00612 (PWCHAR)Request->Data.WriteConsoleOutputCharRequest.String, 00613 Request->Data.WriteConsoleOutputCharRequest.Length, 00614 String, Length, NULL, NULL); 00615 } 00616 else 00617 { 00618 Status = STATUS_NO_MEMORY; 00619 } 00620 } 00621 else 00622 { 00623 String = (PCHAR)Request->Data.WriteConsoleOutputCharRequest.String; 00624 } 00625 00626 if (String) 00627 { 00628 if (NT_SUCCESS(Status)) 00629 { 00630 X = Request->Data.WriteConsoleOutputCharRequest.Coord.X; 00631 Y = (Request->Data.WriteConsoleOutputCharRequest.Coord.Y + Buff->VirtualY) % Buff->MaxY; 00632 Length = Request->Data.WriteConsoleOutputCharRequest.Length; 00633 Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)]; 00634 while (Length--) 00635 { 00636 *Buffer = *String++; 00637 Written++; 00638 Buffer += 2; 00639 if (++X == Buff->MaxX) 00640 { 00641 if (++Y == Buff->MaxY) 00642 { 00643 Y = 0; 00644 Buffer = Buff->Buffer; 00645 } 00646 X = 0; 00647 } 00648 } 00649 if (Buff == Console->ActiveBuffer) 00650 { 00651 ConioComputeUpdateRect(Buff, &UpdateRect, &Request->Data.WriteConsoleOutputCharRequest.Coord, 00652 Request->Data.WriteConsoleOutputCharRequest.Length); 00653 ConioDrawRegion(Console, &UpdateRect); 00654 } 00655 00656 Request->Data.WriteConsoleOutputCharRequest.EndCoord.X = X; 00657 Request->Data.WriteConsoleOutputCharRequest.EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY; 00658 00659 } 00660 if (Request->Data.WriteConsoleRequest.Unicode) 00661 { 00662 RtlFreeHeap(GetProcessHeap(), 0, tmpString); 00663 } 00664 } 00665 ConioUnlockScreenBuffer(Buff); 00666 } 00667 Request->Data.WriteConsoleOutputCharRequest.NrCharactersWritten = Written; 00668 return Status; 00669 } 00670 00671 CSR_API(CsrFillOutputChar) 00672 { 00673 NTSTATUS Status; 00674 PCSRSS_CONSOLE Console; 00675 PCSRSS_SCREEN_BUFFER Buff; 00676 DWORD X, Y, Length, Written = 0; 00677 CHAR Char; 00678 PBYTE Buffer; 00679 SMALL_RECT UpdateRect; 00680 00681 DPRINT("CsrFillOutputChar\n"); 00682 00683 Status = ConioLockScreenBuffer(ProcessData, Request->Data.FillOutputRequest.ConsoleHandle, &Buff, GENERIC_WRITE); 00684 if (! NT_SUCCESS(Status)) 00685 { 00686 return Status; 00687 } 00688 Console = Buff->Header.Console; 00689 00690 X = Request->Data.FillOutputRequest.Position.X; 00691 Y = (Request->Data.FillOutputRequest.Position.Y + Buff->VirtualY) % Buff->MaxY; 00692 Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X)]; 00693 if(Request->Data.FillOutputRequest.Unicode) 00694 ConsoleUnicodeCharToAnsiChar(Console, &Char, &Request->Data.FillOutputRequest.Char.UnicodeChar); 00695 else 00696 Char = Request->Data.FillOutputRequest.Char.AsciiChar; 00697 Length = Request->Data.FillOutputRequest.Length; 00698 while (Length--) 00699 { 00700 *Buffer = Char; 00701 Buffer += 2; 00702 Written++; 00703 if (++X == Buff->MaxX) 00704 { 00705 if (++Y == Buff->MaxY) 00706 { 00707 Y = 0; 00708 Buffer = Buff->Buffer; 00709 } 00710 X = 0; 00711 } 00712 } 00713 00714 if (Buff == Console->ActiveBuffer) 00715 { 00716 ConioComputeUpdateRect(Buff, &UpdateRect, &Request->Data.FillOutputRequest.Position, 00717 Request->Data.FillOutputRequest.Length); 00718 ConioDrawRegion(Console, &UpdateRect); 00719 } 00720 00721 ConioUnlockScreenBuffer(Buff); 00722 Length = Request->Data.FillOutputRequest.Length; 00723 Request->Data.FillOutputRequest.NrCharactersWritten = Length; 00724 return STATUS_SUCCESS; 00725 } 00726 00727 CSR_API(CsrWriteConsoleOutputAttrib) 00728 { 00729 PCSRSS_CONSOLE Console; 00730 PCSRSS_SCREEN_BUFFER Buff; 00731 PUCHAR Buffer; 00732 PWORD Attribute; 00733 int X, Y, Length; 00734 NTSTATUS Status; 00735 SMALL_RECT UpdateRect; 00736 00737 DPRINT("CsrWriteConsoleOutputAttrib\n"); 00738 00739 if (Request->Header.u1.s1.TotalLength 00740 < CSR_API_MESSAGE_HEADER_SIZE(CSRSS_WRITE_CONSOLE_OUTPUT_ATTRIB) 00741 + Request->Data.WriteConsoleOutputAttribRequest.Length * sizeof(WORD)) 00742 { 00743 DPRINT1("Invalid request size\n"); 00744 return STATUS_INVALID_PARAMETER; 00745 } 00746 00747 Status = ConioLockScreenBuffer(ProcessData, 00748 Request->Data.WriteConsoleOutputAttribRequest.ConsoleHandle, 00749 &Buff, 00750 GENERIC_WRITE); 00751 if (! NT_SUCCESS(Status)) 00752 { 00753 return Status; 00754 } 00755 Console = Buff->Header.Console; 00756 00757 X = Request->Data.WriteConsoleOutputAttribRequest.Coord.X; 00758 Y = (Request->Data.WriteConsoleOutputAttribRequest.Coord.Y + Buff->VirtualY) % Buff->MaxY; 00759 Length = Request->Data.WriteConsoleOutputAttribRequest.Length; 00760 Buffer = &Buff->Buffer[2 * (Y * Buff->MaxX + X) + 1]; 00761 Attribute = Request->Data.WriteConsoleOutputAttribRequest.Attribute; 00762 while (Length--) 00763 { 00764 *Buffer = (UCHAR)(*Attribute++); 00765 Buffer += 2; 00766 if (++X == Buff->MaxX) 00767 { 00768 if (++Y == Buff->MaxY) 00769 { 00770 Y = 0; 00771 Buffer = Buff->Buffer + 1; 00772 } 00773 X = 0; 00774 } 00775 } 00776 00777 if (Buff == Console->ActiveBuffer) 00778 { 00779 ConioComputeUpdateRect(Buff, &UpdateRect, &Request->Data.WriteConsoleOutputAttribRequest.Coord, 00780 Request->Data.WriteConsoleOutputAttribRequest.Length); 00781 ConioDrawRegion(Console, &UpdateRect); 00782 } 00783 00784 Request->Data.WriteConsoleOutputAttribRequest.EndCoord.X = X; 00785 Request->Data.WriteConsoleOutputAttribRequest.EndCoord.Y = (Y + Buff->MaxY - Buff->VirtualY) % Buff->MaxY; 00786 00787 ConioUnlockScreenBuffer(Buff); 00788 00789 return STATUS_SUCCESS; 00790 } 00791 00792 CSR_API(CsrFillOutputAttrib) 00793 { 00794 PCSRSS_SCREEN_BUFFER Buff; 00795 PUCHAR Buffer; 00796 NTSTATUS Status; 00797 int X, Y, Length; 00798 UCHAR Attr; 00799 SMALL_RECT UpdateRect; 00800 PCSRSS_CONSOLE Console; 00801 00802 DPRINT("CsrFillOutputAttrib\n"); 00803 00804 Status = ConioLockScreenBuffer(ProcessData, Request->Data.FillOutputAttribRequest.ConsoleHandle, &Buff, GENERIC_WRITE); 00805 if (! NT_SUCCESS(Status)) 00806 { 00807 return Status; 00808 } 00809 Console = Buff->Header.Console; 00810 00811 X = Request->Data.FillOutputAttribRequest.Coord.X; 00812 Y = (Request->Data.FillOutputAttribRequest.Coord.Y + Buff->VirtualY) % Buff->MaxY; 00813 Length = Request->Data.FillOutputAttribRequest.Length; 00814 Attr = Request->Data.FillOutputAttribRequest.Attribute; 00815 Buffer = &Buff->Buffer[(Y * Buff->MaxX * 2) + (X * 2) + 1]; 00816 while (Length--) 00817 { 00818 *Buffer = Attr; 00819 Buffer += 2; 00820 if (++X == Buff->MaxX) 00821 { 00822 if (++Y == Buff->MaxY) 00823 { 00824 Y = 0; 00825 Buffer = Buff->Buffer + 1; 00826 } 00827 X = 0; 00828 } 00829 } 00830 00831 if (Buff == Console->ActiveBuffer) 00832 { 00833 ConioComputeUpdateRect(Buff, &UpdateRect, &Request->Data.FillOutputAttribRequest.Coord, 00834 Request->Data.FillOutputAttribRequest.Length); 00835 ConioDrawRegion(Console, &UpdateRect); 00836 } 00837 00838 ConioUnlockScreenBuffer(Buff); 00839 00840 return STATUS_SUCCESS; 00841 } 00842 00843 DWORD FASTCALL 00844 ConioEffectiveCursorSize(PCSRSS_CONSOLE Console, DWORD Scale) 00845 { 00846 DWORD Size = (Console->ActiveBuffer->CursorInfo.dwSize * Scale + 99) / 100; 00847 /* If line input in progress, perhaps adjust for insert toggle */ 00848 if (Console->LineBuffer && !Console->LineComplete && Console->LineInsertToggle) 00849 return (Size * 2 <= Scale) ? (Size * 2) : (Size / 2); 00850 return Size; 00851 } 00852 00853 CSR_API(CsrGetCursorInfo) 00854 { 00855 PCSRSS_SCREEN_BUFFER Buff; 00856 NTSTATUS Status; 00857 00858 DPRINT("CsrGetCursorInfo\n"); 00859 00860 Status = ConioLockScreenBuffer(ProcessData, Request->Data.GetCursorInfoRequest.ConsoleHandle, &Buff, GENERIC_READ); 00861 if (! NT_SUCCESS(Status)) 00862 { 00863 return Status; 00864 } 00865 Request->Data.GetCursorInfoRequest.Info.bVisible = Buff->CursorInfo.bVisible; 00866 Request->Data.GetCursorInfoRequest.Info.dwSize = Buff->CursorInfo.dwSize; 00867 ConioUnlockScreenBuffer(Buff); 00868 00869 return STATUS_SUCCESS; 00870 } 00871 00872 CSR_API(CsrSetCursorInfo) 00873 { 00874 PCSRSS_CONSOLE Console; 00875 PCSRSS_SCREEN_BUFFER Buff; 00876 DWORD Size; 00877 BOOL Visible; 00878 NTSTATUS Status; 00879 00880 DPRINT("CsrSetCursorInfo\n"); 00881 00882 Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorInfoRequest.ConsoleHandle, &Buff, GENERIC_WRITE); 00883 if (! NT_SUCCESS(Status)) 00884 { 00885 return Status; 00886 } 00887 Console = Buff->Header.Console; 00888 00889 Size = Request->Data.SetCursorInfoRequest.Info.dwSize; 00890 Visible = Request->Data.SetCursorInfoRequest.Info.bVisible; 00891 if (Size < 1) 00892 { 00893 Size = 1; 00894 } 00895 if (100 < Size) 00896 { 00897 Size = 100; 00898 } 00899 00900 if (Size != Buff->CursorInfo.dwSize 00901 || (Visible && ! Buff->CursorInfo.bVisible) || (! Visible && Buff->CursorInfo.bVisible)) 00902 { 00903 Buff->CursorInfo.dwSize = Size; 00904 Buff->CursorInfo.bVisible = Visible; 00905 00906 if (! ConioSetCursorInfo(Console, Buff)) 00907 { 00908 ConioUnlockScreenBuffer(Buff); 00909 return STATUS_UNSUCCESSFUL; 00910 } 00911 } 00912 00913 ConioUnlockScreenBuffer(Buff); 00914 00915 return STATUS_SUCCESS; 00916 } 00917 00918 CSR_API(CsrSetTextAttrib) 00919 { 00920 NTSTATUS Status; 00921 PCSRSS_CONSOLE Console; 00922 PCSRSS_SCREEN_BUFFER Buff; 00923 00924 DPRINT("CsrSetTextAttrib\n"); 00925 00926 Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetCursorRequest.ConsoleHandle, &Buff, GENERIC_WRITE); 00927 if (! NT_SUCCESS(Status)) 00928 { 00929 return Status; 00930 } 00931 Console = Buff->Header.Console; 00932 00933 Buff->DefaultAttrib = Request->Data.SetAttribRequest.Attrib; 00934 if (Buff == Console->ActiveBuffer) 00935 { 00936 if (! ConioUpdateScreenInfo(Console, Buff)) 00937 { 00938 ConioUnlockScreenBuffer(Buff); 00939 return STATUS_UNSUCCESSFUL; 00940 } 00941 } 00942 00943 ConioUnlockScreenBuffer(Buff); 00944 00945 return STATUS_SUCCESS; 00946 } 00947 00948 CSR_API(CsrCreateScreenBuffer) 00949 { 00950 PCSRSS_CONSOLE Console; 00951 PCSRSS_SCREEN_BUFFER Buff; 00952 NTSTATUS Status; 00953 00954 DPRINT("CsrCreateScreenBuffer\n"); 00955 00956 RtlEnterCriticalSection(&ProcessData->HandleTableLock); 00957 Status = ConioConsoleFromProcessData(ProcessData, &Console); 00958 if (! NT_SUCCESS(Status)) 00959 { 00960 return Status; 00961 } 00962 00963 Buff = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY, sizeof(CSRSS_SCREEN_BUFFER)); 00964 00965 if (Buff != NULL) 00966 { 00967 if (Console->ActiveBuffer) 00968 { 00969 Buff->MaxX = Console->ActiveBuffer->MaxX; 00970 Buff->MaxY = Console->ActiveBuffer->MaxY; 00971 Buff->CursorInfo.bVisible = Console->ActiveBuffer->CursorInfo.bVisible; 00972 Buff->CursorInfo.dwSize = Console->ActiveBuffer->CursorInfo.dwSize; 00973 } 00974 else 00975 { 00976 Buff->CursorInfo.bVisible = TRUE; 00977 Buff->CursorInfo.dwSize = CSR_DEFAULT_CURSOR_SIZE; 00978 } 00979 00980 if (Buff->MaxX == 0) 00981 { 00982 Buff->MaxX = 80; 00983 } 00984 00985 if (Buff->MaxY == 0) 00986 { 00987 Buff->MaxY = 25; 00988 } 00989 00990 Status = CsrInitConsoleScreenBuffer(Console, Buff); 00991 if (NT_SUCCESS(Status)) 00992 { 00993 Status = Win32CsrInsertObject(ProcessData, 00994 &Request->Data.CreateScreenBufferRequest.OutputHandle, 00995 &Buff->Header, 00996 Request->Data.CreateScreenBufferRequest.Access, 00997 Request->Data.CreateScreenBufferRequest.Inheritable, 00998 Request->Data.CreateScreenBufferRequest.ShareMode); 00999 } 01000 } 01001 else 01002 { 01003 Status = STATUS_INSUFFICIENT_RESOURCES; 01004 } 01005 01006 ConioUnlockConsole(Console); 01007 RtlLeaveCriticalSection(&ProcessData->HandleTableLock); 01008 return Status; 01009 } 01010 01011 CSR_API(CsrSetScreenBuffer) 01012 { 01013 NTSTATUS Status; 01014 PCSRSS_CONSOLE Console; 01015 PCSRSS_SCREEN_BUFFER Buff; 01016 01017 DPRINT("CsrSetScreenBuffer\n"); 01018 01019 Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetScreenBufferRequest.OutputHandle, &Buff, GENERIC_WRITE); 01020 if (! NT_SUCCESS(Status)) 01021 { 01022 return Status; 01023 } 01024 Console = Buff->Header.Console; 01025 01026 if (Buff == Console->ActiveBuffer) 01027 { 01028 ConioUnlockScreenBuffer(Buff); 01029 return STATUS_SUCCESS; 01030 } 01031 01032 /* If old buffer has no handles, it's now unreferenced */ 01033 if (Console->ActiveBuffer->Header.HandleCount == 0) 01034 { 01035 ConioDeleteScreenBuffer(Console->ActiveBuffer); 01036 } 01037 /* tie console to new buffer */ 01038 Console->ActiveBuffer = Buff; 01039 /* Redraw the console */ 01040 ConioDrawConsole(Console); 01041 01042 ConioUnlockScreenBuffer(Buff); 01043 01044 return STATUS_SUCCESS; 01045 } 01046 01047 CSR_API(CsrWriteConsoleOutput) 01048 { 01049 SHORT i, X, Y, SizeX, SizeY; 01050 PCSRSS_CONSOLE Console; 01051 PCSRSS_SCREEN_BUFFER Buff; 01052 SMALL_RECT ScreenBuffer; 01053 CHAR_INFO* CurCharInfo; 01054 SMALL_RECT WriteRegion; 01055 CHAR_INFO* CharInfo; 01056 COORD BufferCoord; 01057 COORD BufferSize; 01058 NTSTATUS Status; 01059 PBYTE Ptr; 01060 01061 DPRINT("CsrWriteConsoleOutput\n"); 01062 01063 Status = ConioLockScreenBuffer(ProcessData, 01064 Request->Data.WriteConsoleOutputRequest.ConsoleHandle, 01065 &Buff, 01066 GENERIC_WRITE); 01067 if (! NT_SUCCESS(Status)) 01068 { 01069 return Status; 01070 } 01071 Console = Buff->Header.Console; 01072 01073 BufferSize = Request->Data.WriteConsoleOutputRequest.BufferSize; 01074 BufferCoord = Request->Data.WriteConsoleOutputRequest.BufferCoord; 01075 CharInfo = Request->Data.WriteConsoleOutputRequest.CharInfo; 01076 if (!Win32CsrValidateBuffer(ProcessData, CharInfo, 01077 BufferSize.X * BufferSize.Y, sizeof(CHAR_INFO))) 01078 { 01079 ConioUnlockScreenBuffer(Buff); 01080 return STATUS_ACCESS_VIOLATION; 01081 } 01082 WriteRegion = Request->Data.WriteConsoleOutputRequest.WriteRegion; 01083 01084 SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&WriteRegion)); 01085 SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&WriteRegion)); 01086 WriteRegion.Bottom = WriteRegion.Top + SizeY - 1; 01087 WriteRegion.Right = WriteRegion.Left + SizeX - 1; 01088 01089 /* Make sure WriteRegion is inside the screen buffer */ 01090 ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1); 01091 if (! ConioGetIntersection(&WriteRegion, &ScreenBuffer, &WriteRegion)) 01092 { 01093 ConioUnlockScreenBuffer(Buff); 01094 01095 /* It is okay to have a WriteRegion completely outside the screen buffer. 01096 No data is written then. */ 01097 return STATUS_SUCCESS; 01098 } 01099 01100 for (i = 0, Y = WriteRegion.Top; Y <= WriteRegion.Bottom; i++, Y++) 01101 { 01102 CurCharInfo = CharInfo + (i + BufferCoord.Y) * BufferSize.X + BufferCoord.X; 01103 Ptr = ConioCoordToPointer(Buff, WriteRegion.Left, Y); 01104 for (X = WriteRegion.Left; X <= WriteRegion.Right; X++) 01105 { 01106 CHAR AsciiChar; 01107 if (Request->Data.WriteConsoleOutputRequest.Unicode) 01108 { 01109 ConsoleUnicodeCharToAnsiChar(Console, &AsciiChar, &CurCharInfo->Char.UnicodeChar); 01110 } 01111 else 01112 { 01113 AsciiChar = CurCharInfo->Char.AsciiChar; 01114 } 01115 *Ptr++ = AsciiChar; 01116 *Ptr++ = CurCharInfo->Attributes; 01117 CurCharInfo++; 01118 } 01119 } 01120 01121 ConioDrawRegion(Console, &WriteRegion); 01122 01123 ConioUnlockScreenBuffer(Buff); 01124 01125 Request->Data.WriteConsoleOutputRequest.WriteRegion.Right = WriteRegion.Left + SizeX - 1; 01126 Request->Data.WriteConsoleOutputRequest.WriteRegion.Bottom = WriteRegion.Top + SizeY - 1; 01127 Request->Data.WriteConsoleOutputRequest.WriteRegion.Left = WriteRegion.Left; 01128 Request->Data.WriteConsoleOutputRequest.WriteRegion.Top = WriteRegion.Top; 01129 01130 return STATUS_SUCCESS; 01131 } 01132 01133 CSR_API(CsrScrollConsoleScreenBuffer) 01134 { 01135 PCSRSS_CONSOLE Console; 01136 PCSRSS_SCREEN_BUFFER Buff; 01137 SMALL_RECT ScreenBuffer; 01138 SMALL_RECT SrcRegion; 01139 SMALL_RECT DstRegion; 01140 SMALL_RECT UpdateRegion; 01141 SMALL_RECT ScrollRectangle; 01142 SMALL_RECT ClipRectangle; 01143 NTSTATUS Status; 01144 HANDLE ConsoleHandle; 01145 BOOLEAN UseClipRectangle; 01146 COORD DestinationOrigin; 01147 CHAR_INFO Fill; 01148 CHAR FillChar; 01149 01150 DPRINT("CsrScrollConsoleScreenBuffer\n"); 01151 01152 ConsoleHandle = Request->Data.ScrollConsoleScreenBufferRequest.ConsoleHandle; 01153 UseClipRectangle = Request->Data.ScrollConsoleScreenBufferRequest.UseClipRectangle; 01154 DestinationOrigin = Request->Data.ScrollConsoleScreenBufferRequest.DestinationOrigin; 01155 Fill = Request->Data.ScrollConsoleScreenBufferRequest.Fill; 01156 01157 Status = ConioLockScreenBuffer(ProcessData, ConsoleHandle, &Buff, GENERIC_WRITE); 01158 if (! NT_SUCCESS(Status)) 01159 { 01160 return Status; 01161 } 01162 Console = Buff->Header.Console; 01163 01164 ScrollRectangle = Request->Data.ScrollConsoleScreenBufferRequest.ScrollRectangle; 01165 01166 /* Make sure source rectangle is inside the screen buffer */ 01167 ConioInitRect(&ScreenBuffer, 0, 0, Buff->MaxY - 1, Buff->MaxX - 1); 01168 if (! ConioGetIntersection(&SrcRegion, &ScreenBuffer, &ScrollRectangle)) 01169 { 01170 ConioUnlockScreenBuffer(Buff); 01171 return STATUS_SUCCESS; 01172 } 01173 01174 /* If the source was clipped on the left or top, adjust the destination accordingly */ 01175 if (ScrollRectangle.Left < 0) 01176 { 01177 DestinationOrigin.X -= ScrollRectangle.Left; 01178 } 01179 if (ScrollRectangle.Top < 0) 01180 { 01181 DestinationOrigin.Y -= ScrollRectangle.Top; 01182 } 01183 01184 if (UseClipRectangle) 01185 { 01186 ClipRectangle = Request->Data.ScrollConsoleScreenBufferRequest.ClipRectangle; 01187 if (!ConioGetIntersection(&ClipRectangle, &ClipRectangle, &ScreenBuffer)) 01188 { 01189 ConioUnlockScreenBuffer(Buff); 01190 return STATUS_SUCCESS; 01191 } 01192 } 01193 else 01194 { 01195 ClipRectangle = ScreenBuffer; 01196 } 01197 01198 ConioInitRect(&DstRegion, 01199 DestinationOrigin.Y, 01200 DestinationOrigin.X, 01201 DestinationOrigin.Y + ConioRectHeight(&SrcRegion) - 1, 01202 DestinationOrigin.X + ConioRectWidth(&SrcRegion) - 1); 01203 01204 if (Request->Data.ScrollConsoleScreenBufferRequest.Unicode) 01205 ConsoleUnicodeCharToAnsiChar(Console, &FillChar, &Fill.Char.UnicodeChar); 01206 else 01207 FillChar = Fill.Char.AsciiChar; 01208 01209 ConioMoveRegion(Buff, &SrcRegion, &DstRegion, &ClipRectangle, Fill.Attributes << 8 | (BYTE)FillChar); 01210 01211 if (Buff == Console->ActiveBuffer) 01212 { 01213 ConioGetUnion(&UpdateRegion, &SrcRegion, &DstRegion); 01214 if (ConioGetIntersection(&UpdateRegion, &UpdateRegion, &ClipRectangle)) 01215 { 01216 /* Draw update region */ 01217 ConioDrawRegion(Console, &UpdateRegion); 01218 } 01219 } 01220 01221 ConioUnlockScreenBuffer(Buff); 01222 01223 return STATUS_SUCCESS; 01224 } 01225 01226 CSR_API(CsrReadConsoleOutputChar) 01227 { 01228 NTSTATUS Status; 01229 PCSRSS_CONSOLE Console; 01230 PCSRSS_SCREEN_BUFFER Buff; 01231 DWORD Xpos, Ypos; 01232 PCHAR ReadBuffer; 01233 DWORD i; 01234 ULONG CharSize; 01235 CHAR Char; 01236 01237 DPRINT("CsrReadConsoleOutputChar\n"); 01238 01239 ReadBuffer = Request->Data.ReadConsoleOutputCharRequest.String; 01240 01241 CharSize = (Request->Data.ReadConsoleOutputCharRequest.Unicode ? sizeof(WCHAR) : sizeof(CHAR)); 01242 01243 Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputCharRequest.ConsoleHandle, &Buff, GENERIC_READ); 01244 if (! NT_SUCCESS(Status)) 01245 { 01246 return Status; 01247 } 01248 Console = Buff->Header.Console; 01249 01250 Xpos = Request->Data.ReadConsoleOutputCharRequest.ReadCoord.X; 01251 Ypos = (Request->Data.ReadConsoleOutputCharRequest.ReadCoord.Y + Buff->VirtualY) % Buff->MaxY; 01252 01253 for (i = 0; i < Request->Data.ReadConsoleOutputCharRequest.NumCharsToRead; ++i) 01254 { 01255 Char = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX)]; 01256 01257 if(Request->Data.ReadConsoleOutputCharRequest.Unicode) 01258 { 01259 ConsoleAnsiCharToUnicodeChar(Console, (WCHAR*)ReadBuffer, &Char); 01260 ReadBuffer += sizeof(WCHAR); 01261 } 01262 else 01263 *(ReadBuffer++) = Char; 01264 01265 Xpos++; 01266 01267 if (Xpos == Buff->MaxX) 01268 { 01269 Xpos = 0; 01270 Ypos++; 01271 01272 if (Ypos == Buff->MaxY) 01273 { 01274 Ypos = 0; 01275 } 01276 } 01277 } 01278 01279 *ReadBuffer = 0; 01280 Request->Data.ReadConsoleOutputCharRequest.EndCoord.X = Xpos; 01281 Request->Data.ReadConsoleOutputCharRequest.EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY; 01282 01283 ConioUnlockScreenBuffer(Buff); 01284 01285 Request->Data.ReadConsoleOutputCharRequest.CharsRead = (DWORD)((ULONG_PTR)ReadBuffer - (ULONG_PTR)Request->Data.ReadConsoleOutputCharRequest.String) / CharSize; 01286 if (Request->Data.ReadConsoleOutputCharRequest.CharsRead * CharSize + CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_CHAR) > sizeof(CSR_API_MESSAGE)) 01287 { 01288 DPRINT1("Length won't fit in message\n"); 01289 return STATUS_BUFFER_TOO_SMALL; 01290 } 01291 01292 return STATUS_SUCCESS; 01293 } 01294 01295 01296 CSR_API(CsrReadConsoleOutputAttrib) 01297 { 01298 NTSTATUS Status; 01299 PCSRSS_SCREEN_BUFFER Buff; 01300 DWORD Xpos, Ypos; 01301 PWORD ReadBuffer; 01302 DWORD i; 01303 DWORD CurrentLength; 01304 01305 DPRINT("CsrReadConsoleOutputAttrib\n"); 01306 01307 ReadBuffer = Request->Data.ReadConsoleOutputAttribRequest.Attribute; 01308 01309 Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputAttribRequest.ConsoleHandle, &Buff, GENERIC_READ); 01310 if (! NT_SUCCESS(Status)) 01311 { 01312 return Status; 01313 } 01314 01315 Xpos = Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.X; 01316 Ypos = (Request->Data.ReadConsoleOutputAttribRequest.ReadCoord.Y + Buff->VirtualY) % Buff->MaxY; 01317 01318 for (i = 0; i < Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead; ++i) 01319 { 01320 *ReadBuffer = Buff->Buffer[(Xpos * 2) + (Ypos * 2 * Buff->MaxX) + 1]; 01321 01322 ReadBuffer++; 01323 Xpos++; 01324 01325 if (Xpos == Buff->MaxX) 01326 { 01327 Xpos = 0; 01328 Ypos++; 01329 01330 if (Ypos == Buff->MaxY) 01331 { 01332 Ypos = 0; 01333 } 01334 } 01335 } 01336 01337 *ReadBuffer = 0; 01338 01339 Request->Data.ReadConsoleOutputAttribRequest.EndCoord.X = Xpos; 01340 Request->Data.ReadConsoleOutputAttribRequest.EndCoord.Y = (Ypos - Buff->VirtualY + Buff->MaxY) % Buff->MaxY; 01341 01342 ConioUnlockScreenBuffer(Buff); 01343 01344 CurrentLength = CSR_API_MESSAGE_HEADER_SIZE(CSRSS_READ_CONSOLE_OUTPUT_ATTRIB) 01345 + Request->Data.ReadConsoleOutputAttribRequest.NumAttrsToRead * sizeof(WORD); 01346 if (CurrentLength > sizeof(CSR_API_MESSAGE)) 01347 { 01348 DPRINT1("Length won't fit in message\n"); 01349 return STATUS_BUFFER_TOO_SMALL; 01350 } 01351 01352 return STATUS_SUCCESS; 01353 } 01354 01355 CSR_API(CsrReadConsoleOutput) 01356 { 01357 PCHAR_INFO CharInfo; 01358 PCHAR_INFO CurCharInfo; 01359 PCSRSS_SCREEN_BUFFER Buff; 01360 DWORD SizeX, SizeY; 01361 NTSTATUS Status; 01362 COORD BufferSize; 01363 COORD BufferCoord; 01364 SMALL_RECT ReadRegion; 01365 SMALL_RECT ScreenRect; 01366 DWORD i; 01367 PBYTE Ptr; 01368 LONG X, Y; 01369 UINT CodePage; 01370 01371 DPRINT("CsrReadConsoleOutput\n"); 01372 01373 Status = ConioLockScreenBuffer(ProcessData, Request->Data.ReadConsoleOutputRequest.ConsoleHandle, &Buff, GENERIC_READ); 01374 if (! NT_SUCCESS(Status)) 01375 { 01376 return Status; 01377 } 01378 01379 CharInfo = Request->Data.ReadConsoleOutputRequest.CharInfo; 01380 ReadRegion = Request->Data.ReadConsoleOutputRequest.ReadRegion; 01381 BufferSize = Request->Data.ReadConsoleOutputRequest.BufferSize; 01382 BufferCoord = Request->Data.ReadConsoleOutputRequest.BufferCoord; 01383 01384 /* FIXME: Is this correct? */ 01385 CodePage = ProcessData->Console->OutputCodePage; 01386 01387 if (!Win32CsrValidateBuffer(ProcessData, CharInfo, 01388 BufferSize.X * BufferSize.Y, sizeof(CHAR_INFO))) 01389 { 01390 ConioUnlockScreenBuffer(Buff); 01391 return STATUS_ACCESS_VIOLATION; 01392 } 01393 01394 SizeY = min(BufferSize.Y - BufferCoord.Y, ConioRectHeight(&ReadRegion)); 01395 SizeX = min(BufferSize.X - BufferCoord.X, ConioRectWidth(&ReadRegion)); 01396 ReadRegion.Bottom = ReadRegion.Top + SizeY; 01397 ReadRegion.Right = ReadRegion.Left + SizeX; 01398 01399 ConioInitRect(&ScreenRect, 0, 0, Buff->MaxY, Buff->MaxX); 01400 if (! ConioGetIntersection(&ReadRegion, &ScreenRect, &ReadRegion)) 01401 { 01402 ConioUnlockScreenBuffer(Buff); 01403 return STATUS_SUCCESS; 01404 } 01405 01406 for (i = 0, Y = ReadRegion.Top; Y < ReadRegion.Bottom; ++i, ++Y) 01407 { 01408 CurCharInfo = CharInfo + (i * BufferSize.X); 01409 01410 Ptr = ConioCoordToPointer(Buff, ReadRegion.Left, Y); 01411 for (X = ReadRegion.Left; X < ReadRegion.Right; ++X) 01412 { 01413 if (Request->Data.ReadConsoleOutputRequest.Unicode) 01414 { 01415 MultiByteToWideChar(CodePage, 0, 01416 (PCHAR)Ptr++, 1, 01417 &CurCharInfo->Char.UnicodeChar, 1); 01418 } 01419 else 01420 { 01421 CurCharInfo->Char.AsciiChar = *Ptr++; 01422 } 01423 CurCharInfo->Attributes = *Ptr++; 01424 ++CurCharInfo; 01425 } 01426 } 01427 01428 ConioUnlockScreenBuffer(Buff); 01429 01430 Request->Data.ReadConsoleOutputRequest.ReadRegion.Right = ReadRegion.Left + SizeX - 1; 01431 Request->Data.ReadConsoleOutputRequest.ReadRegion.Bottom = ReadRegion.Top + SizeY - 1; 01432 Request->Data.ReadConsoleOutputRequest.ReadRegion.Left = ReadRegion.Left; 01433 Request->Data.ReadConsoleOutputRequest.ReadRegion.Top = ReadRegion.Top; 01434 01435 return STATUS_SUCCESS; 01436 } 01437 01438 CSR_API(CsrSetScreenBufferSize) 01439 { 01440 NTSTATUS Status; 01441 PCSRSS_CONSOLE Console; 01442 PCSRSS_SCREEN_BUFFER Buff; 01443 01444 Status = ConioLockScreenBuffer(ProcessData, Request->Data.SetScreenBufferSize.OutputHandle, &Buff, GENERIC_WRITE); 01445 if (!NT_SUCCESS(Status)) 01446 { 01447 return Status; 01448 } 01449 Console = Buff->Header.Console; 01450 01451 Status = ConioResizeBuffer(Console, Buff, Request->Data.SetScreenBufferSize.Size); 01452 ConioUnlockScreenBuffer(Buff); 01453 01454 return Status; 01455 } 01456 01457 /* EOF */ Generated on Mon May 28 2012 04:38:41 for ReactOS by
1.7.6.1
|