ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

conoutput.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.