1 /* 2 * PROJECT: ReactOS VT100 emulator 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: drivers/base/green/screen.c 5 * PURPOSE: IRP_MJ_PNP operations 6 * PROGRAMMERS: Copyright 2005 Eric Kohl (ekohl@abo.rhein-zeitung.de) 7 * Copyright 2005 Art Yerkes 8 * Copyright 2005-2006 Herv� Poussineau (hpoussin@reactos.org) 9 */ 10 11 #include "green.h" 12 13 #define NDEBUG 14 #include <debug.h> 15 16 #define ESC ((UCHAR)0x1b) 17 18 /* Force a move of the cursor on each printer char. 19 * Very useful for debug, but it is very slow... 20 */ 21 //#define FORCE_POSITION 22 23 /* UCHAR is promoted to int when passed through '...', 24 * so we get int with va_arg and cast them back to UCHAR. 25 */ 26 static VOID 27 AddToSendBuffer( 28 IN PSCREEN_DEVICE_EXTENSION DeviceExtension, 29 IN ULONG NumberOfChars, 30 ... /* IN int */) 31 { 32 PIRP Irp; 33 IO_STATUS_BLOCK ioStatus; 34 va_list args; 35 PDEVICE_OBJECT SerialDevice; 36 ULONG SizeLeft; 37 int CurrentInt; 38 UCHAR CurrentChar; 39 NTSTATUS Status; 40 LARGE_INTEGER ZeroOffset; 41 42 ZeroOffset.QuadPart = 0; 43 44 SizeLeft = sizeof(DeviceExtension->SendBuffer) - DeviceExtension->SendBufferPosition; 45 if (SizeLeft < NumberOfChars * 2 || NumberOfChars == 0) 46 { 47 SerialDevice = ((PGREEN_DEVICE_EXTENSION)DeviceExtension->Green->DeviceExtension)->Serial; 48 Irp = IoBuildSynchronousFsdRequest( 49 IRP_MJ_WRITE, 50 SerialDevice, 51 DeviceExtension->SendBuffer, DeviceExtension->SendBufferPosition, 52 &ZeroOffset, 53 NULL, /* Event */ 54 &ioStatus); 55 if (!Irp) 56 { 57 DPRINT1("IoBuildSynchronousFsdRequest() failed. Unable to flush output buffer\n"); 58 return; 59 } 60 61 Status = IoCallDriver(SerialDevice, Irp); 62 63 if (!NT_SUCCESS(Status) && Status != STATUS_PENDING) 64 { 65 DPRINT1("IoCallDriver() failed. Status = 0x%08lx\n", Status); 66 return; 67 } 68 DeviceExtension->SendBufferPosition = 0; 69 SizeLeft = sizeof(DeviceExtension->SendBuffer); 70 } 71 72 va_start(args, NumberOfChars); 73 while (NumberOfChars-- > 0) 74 { 75 CurrentInt = va_arg(args, int); 76 77 if (CurrentInt > 0) 78 { 79 CurrentChar = (UCHAR)CurrentInt; 80 81 /* Why 0xff chars are printed on a 'dir' ? */ 82 if (CurrentChar == 0xff) CurrentChar = ' '; 83 84 DeviceExtension->SendBuffer[DeviceExtension->SendBufferPosition++] = CurrentChar; 85 SizeLeft--; 86 } 87 else if (CurrentInt == 0) 88 { 89 DeviceExtension->SendBuffer[DeviceExtension->SendBufferPosition++] = '0'; 90 SizeLeft--; 91 } 92 else 93 { 94 CurrentInt = -CurrentInt; 95 ASSERT(CurrentInt < 100); 96 if (CurrentInt >= 10) 97 { 98 DeviceExtension->SendBuffer[DeviceExtension->SendBufferPosition++] = 99 (CurrentInt / 10) % 10 + '0'; 100 SizeLeft--; 101 } 102 DeviceExtension->SendBuffer[DeviceExtension->SendBufferPosition++] = 103 CurrentInt % 10 + '0'; 104 SizeLeft--; 105 } 106 } 107 va_end(args); 108 } 109 110 NTSTATUS 111 ScreenAddDevice( 112 IN PDRIVER_OBJECT DriverObject, 113 IN PDEVICE_OBJECT Pdo) 114 { 115 /* We want to be an upper filter of Blue, if it is existing. 116 * We also *have to* create a Fdo on top of the given Pdo. 117 * Hence, we have 2 cases: 118 * - Blue doesn't exist -> Create a unique Fdo (named Blue) at 119 * the top of the given Pdo 120 * - Blue does exist -> Create a Fdo at the top of the existing 121 * DO, and create a "pass to Green" FDO at the top of the Pdo 122 */ 123 PDEVICE_OBJECT Fdo = NULL; 124 PDEVICE_OBJECT PassThroughFdo = NULL; 125 PDEVICE_OBJECT LowerDevice = NULL; 126 PDEVICE_OBJECT PreviousBlue = NULL; 127 PSCREEN_DEVICE_EXTENSION DeviceExtension = NULL; 128 UNICODE_STRING BlueScreenName = RTL_CONSTANT_STRING(L"\\Device\\BlueScreen"); 129 NTSTATUS Status; 130 131 DPRINT("ScreenInitialize() called\n"); 132 133 /* Try to create a unique Fdo */ 134 Status = IoCreateDevice( 135 DriverObject, 136 sizeof(SCREEN_DEVICE_EXTENSION), 137 &BlueScreenName, 138 FILE_DEVICE_SCREEN, 139 FILE_DEVICE_SECURE_OPEN, 140 TRUE, 141 &Fdo); 142 143 if (Status == STATUS_OBJECT_NAME_COLLISION) 144 { 145 DPRINT("Attaching to old blue\n"); 146 147 /* Suggested by hpoussin .. Hide previous blue device 148 * This makes us able to coexist with blue, and install 149 * when loaded */ 150 Status = IoCreateDevice( 151 DriverObject, 152 sizeof(SCREEN_DEVICE_EXTENSION), 153 NULL, 154 FILE_DEVICE_SCREEN, 155 FILE_DEVICE_SECURE_OPEN, 156 TRUE, 157 &Fdo); 158 if (!NT_SUCCESS(Status)) 159 { 160 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status); 161 goto cleanup; 162 } 163 164 /* Initialize some fields, as IoAttachDevice will trigger the 165 * sending of IRP_MJ_CLEANUP/IRP_MJ_CLOSE. We have to know where to 166 * dispatch these IRPs... */ 167 ((PSCREEN_DEVICE_EXTENSION)Fdo->DeviceExtension)->Common.Type = ScreenPDO; 168 Status = IoAttachDevice( 169 Fdo, 170 &BlueScreenName, 171 &LowerDevice); 172 if (!NT_SUCCESS(Status)) 173 { 174 DPRINT("IoAttachDevice() failed with status 0x%08lx\n", Status); 175 goto cleanup; 176 } 177 PreviousBlue = LowerDevice; 178 179 /* Attach a faked FDO to PDO */ 180 Status = IoCreateDevice( 181 DriverObject, 182 sizeof(COMMON_FDO_DEVICE_EXTENSION), 183 NULL, 184 FILE_DEVICE_SCREEN, 185 FILE_DEVICE_SECURE_OPEN, 186 TRUE, 187 &PassThroughFdo); 188 if (!NT_SUCCESS(Status)) 189 { 190 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status); 191 goto cleanup; 192 } 193 ((PCOMMON_FDO_DEVICE_EXTENSION)PassThroughFdo->DeviceExtension)->Type = PassThroughFDO; 194 ((PCOMMON_FDO_DEVICE_EXTENSION)PassThroughFdo->DeviceExtension)->LowerDevice = Fdo; 195 PassThroughFdo->StackSize = Fdo->StackSize + 1; 196 } 197 else if (NT_SUCCESS(Status)) 198 { 199 /* Attach the named Fdo on top of Pdo */ 200 LowerDevice = IoAttachDeviceToDeviceStack(Fdo, Pdo); 201 } 202 else 203 { 204 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status); 205 return Status; 206 } 207 208 /* We definately have a device object. PreviousBlue may or may 209 * not be null */ 210 DeviceExtension = (PSCREEN_DEVICE_EXTENSION)Fdo->DeviceExtension; 211 RtlZeroMemory(DeviceExtension, sizeof(SCREEN_DEVICE_EXTENSION)); 212 DeviceExtension->Common.Type = ScreenFDO; 213 DeviceExtension->Common.LowerDevice = LowerDevice; 214 DeviceExtension->Green = ((PGREEN_DRIVER_EXTENSION)IoGetDriverObjectExtension(DriverObject, DriverObject))->GreenMainDO; 215 ((PGREEN_DEVICE_EXTENSION)DeviceExtension->Green->DeviceExtension)->ScreenFdo = Fdo; 216 DeviceExtension->PreviousBlue = PreviousBlue; 217 IoAttachDeviceToDeviceStack(PassThroughFdo ? PassThroughFdo : Fdo, Pdo); 218 219 /* initialize screen */ 220 DeviceExtension->Columns = 80; 221 DeviceExtension->Rows = 25; 222 DeviceExtension->ScanLines = 16; 223 DeviceExtension->VideoMemory = (PUCHAR)ExAllocatePool( 224 PagedPool, 225 2 * DeviceExtension->Columns * DeviceExtension->Rows * sizeof(UCHAR)); 226 if (!DeviceExtension->VideoMemory) 227 { 228 DPRINT("ExAllocatePool() failed\n"); 229 Status = STATUS_INSUFFICIENT_RESOURCES; 230 goto cleanup; 231 } 232 DeviceExtension->TabWidth = 8; 233 234 /* more initialization */ 235 DeviceExtension->Mode = ENABLE_PROCESSED_OUTPUT | 236 ENABLE_WRAP_AT_EOL_OUTPUT; 237 238 /* initialize screen at next write */ 239 AddToSendBuffer(DeviceExtension, 2, ESC, 'c'); /* reset device */ 240 AddToSendBuffer(DeviceExtension, 4, ESC, '[', '7', 'l'); /* disable line wrap */ 241 AddToSendBuffer(DeviceExtension, 4, ESC, '[', '3', 'g'); /* clear all tabs */ 242 243 Fdo->Flags |= DO_POWER_PAGABLE; 244 Fdo->Flags &= ~DO_DEVICE_INITIALIZING; 245 246 Status = STATUS_SUCCESS; 247 248 cleanup: 249 if (!NT_SUCCESS(Status)) 250 { 251 if (DeviceExtension) 252 ExFreePool(DeviceExtension->VideoMemory); 253 if (LowerDevice) 254 IoDetachDevice(LowerDevice); 255 if (Fdo) 256 IoDeleteDevice(Fdo); 257 if (PassThroughFdo) 258 IoDeleteDevice(PassThroughFdo); 259 } 260 261 return Status; 262 } 263 264 NTSTATUS 265 ScreenWrite( 266 IN PDEVICE_OBJECT DeviceObject, 267 IN PIRP Irp) 268 { 269 PIO_STACK_LOCATION Stack; 270 PUCHAR Buffer; 271 PSCREEN_DEVICE_EXTENSION DeviceExtension; 272 PDEVICE_OBJECT SerialDevice; 273 PUCHAR VideoMemory; /* FIXME: is it useful? */ 274 ULONG VideoMemorySize; /* FIXME: is it useful? */ 275 276 ULONG Columns, Rows; 277 ULONG CursorX, CursorY; 278 ULONG i, j; 279 DBG_UNREFERENCED_LOCAL_VARIABLE(VideoMemory); 280 DBG_UNREFERENCED_LOCAL_VARIABLE(VideoMemorySize); 281 282 DPRINT("ScreenWrite() called\n"); 283 284 Stack = IoGetCurrentIrpStackLocation (Irp); 285 Buffer = Irp->UserBuffer; 286 DeviceExtension = (PSCREEN_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 287 VideoMemory = DeviceExtension->VideoMemory; 288 289 SerialDevice = ((PGREEN_DEVICE_EXTENSION)DeviceExtension->Green->DeviceExtension)->Serial; 290 if (!SerialDevice) 291 { 292 DPRINT1("Calling blue\n"); 293 IoSkipCurrentIrpStackLocation(Irp); 294 return IoCallDriver(DeviceExtension->PreviousBlue, Irp); 295 } 296 297 Columns = DeviceExtension->Columns; 298 Rows = DeviceExtension->Rows; 299 CursorX = (DeviceExtension->LogicalOffset / 2) % Columns + 1; 300 CursorY = (DeviceExtension->LogicalOffset / 2) / Columns + 1; 301 VideoMemorySize = Columns * Rows * 2 * sizeof(UCHAR); 302 303 if (!(DeviceExtension->Mode & ENABLE_PROCESSED_OUTPUT)) 304 { 305 /* raw output mode */ 306 Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 307 IoCompleteRequest (Irp, IO_NO_INCREMENT); 308 309 return STATUS_NOT_SUPPORTED; 310 } 311 else 312 { 313 for (i = 0; i < Stack->Parameters.Write.Length; i++, Buffer++) 314 { 315 switch (*Buffer) 316 { 317 case '\b': 318 { 319 if (CursorX > 1) 320 { 321 CursorX--; 322 AddToSendBuffer(DeviceExtension, 6, ESC, '[', -(int)CursorY, ';', -(int)CursorX, 'H'); 323 AddToSendBuffer(DeviceExtension, 1, ' '); 324 AddToSendBuffer(DeviceExtension, 6, ESC, '[', -(int)CursorY, ';', -(int)CursorX, 'H'); 325 } 326 else if (CursorY > 1) 327 { 328 CursorX = Columns; 329 CursorY--; 330 AddToSendBuffer(DeviceExtension, 6, ESC, '[', -(int)CursorY, ';', -(int)CursorX, 'H'); 331 } 332 break; 333 } 334 case '\n': 335 { 336 CursorY++; 337 CursorX = 1; 338 AddToSendBuffer(DeviceExtension, 1, '\n'); 339 AddToSendBuffer(DeviceExtension, 6, ESC, '[', -(int)CursorY, ';', '1', 'H'); 340 break; 341 } 342 case '\r': 343 { 344 if (CursorX > 1) 345 { 346 AddToSendBuffer(DeviceExtension, 4, ESC, '[', -(int)(CursorX-1), 'D'); 347 CursorX = 1; 348 } 349 break; 350 } 351 case '\t': 352 { 353 ULONG Offset = DeviceExtension->TabWidth - (CursorX % DeviceExtension->TabWidth); 354 for (j = 0; j < Offset; j++) 355 { 356 #ifdef FORCE_POSITION 357 AddToSendBuffer(DeviceExtension, 6, ESC, '[', -(int)CursorY, ';', -(int)CursorX, 'H'); 358 #endif 359 AddToSendBuffer(DeviceExtension, 1, ' '); 360 CursorX++; 361 if (CursorX > Columns) 362 { 363 CursorX = 1; 364 CursorY++; 365 } 366 } 367 break; 368 } 369 default: 370 { 371 #ifdef FORCE_POSITION 372 AddToSendBuffer(DeviceExtension, 6, ESC, '[', -(int)CursorY, ';', -(int)CursorX, 'H'); 373 #endif 374 AddToSendBuffer(DeviceExtension, 1, *Buffer); 375 CursorX++; 376 if (CursorX > Columns) 377 { 378 CursorX = 1; 379 DPRINT("Y: %lu -> %lu\n", CursorY, CursorY + 1); 380 CursorY++; 381 AddToSendBuffer(DeviceExtension, 6, ESC, '[', -(int)CursorY, ';', '1', 'H'); 382 383 } 384 } 385 } 386 if (CursorY >= Rows) 387 { 388 DPRINT("Y: %lu -> %lu\n", CursorY, CursorY - 1); 389 CursorY--; 390 AddToSendBuffer(DeviceExtension, 6, ESC, '[', -(int)1, ';', -(int)(Rows), 'r'); 391 AddToSendBuffer(DeviceExtension, 2, ESC, 'D'); 392 AddToSendBuffer(DeviceExtension, 6, ESC, '[', -(int)CursorY, ';', -(int)CursorX, 'H'); 393 } 394 } 395 } 396 397 DeviceExtension->LogicalOffset = ((CursorX-1) + (CursorY-1) * Columns) * 2; 398 399 /* flush output buffer */ 400 AddToSendBuffer(DeviceExtension, 0); 401 402 /* Call lower driver */ 403 IoSkipCurrentIrpStackLocation(Irp); 404 return IoCallDriver(DeviceExtension->Common.LowerDevice, Irp); 405 } 406 407 NTSTATUS 408 ScreenDeviceControl( 409 IN PDEVICE_OBJECT DeviceObject, 410 IN PIRP Irp) 411 { 412 PIO_STACK_LOCATION Stack; 413 PSCREEN_DEVICE_EXTENSION DeviceExtension; 414 PDEVICE_OBJECT SerialDevice; 415 NTSTATUS Status; 416 417 Stack = IoGetCurrentIrpStackLocation(Irp); 418 DeviceExtension = (PSCREEN_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 419 SerialDevice = ((PGREEN_DEVICE_EXTENSION)DeviceExtension->Green->DeviceExtension)->Serial; 420 if (!SerialDevice) 421 { 422 DPRINT1("Calling blue\n"); 423 IoSkipCurrentIrpStackLocation(Irp); 424 return IoCallDriver(DeviceExtension->PreviousBlue, Irp); 425 } 426 427 switch (Stack->Parameters.DeviceIoControl.IoControlCode) 428 { 429 #if 0 430 case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO: 431 { 432 PCONSOLE_SCREEN_BUFFER_INFO pcsbi; 433 DPRINT("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO\n"); 434 435 pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer; 436 437 pcsbi->dwSize.X = DeviceExtension->Columns; 438 pcsbi->dwSize.Y = DeviceExtension->Rows; 439 440 pcsbi->dwCursorPosition.X = (SHORT)(DeviceExtension->LogicalOffset % DeviceExtension->Columns); 441 pcsbi->dwCursorPosition.Y = (SHORT)(DeviceExtension->LogicalOffset / DeviceExtension->Columns); 442 443 pcsbi->wAttributes = DeviceExtension->CharAttribute; 444 445 pcsbi->srWindow.Left = 1; 446 pcsbi->srWindow.Right = DeviceExtension->Columns; 447 pcsbi->srWindow.Top = 1; 448 pcsbi->srWindow.Bottom = DeviceExtension->Rows; 449 450 pcsbi->dwMaximumWindowSize.X = DeviceExtension->Columns; 451 pcsbi->dwMaximumWindowSize.Y = DeviceExtension->Rows; 452 453 Irp->IoStatus.Information = sizeof(CONSOLE_SCREEN_BUFFER_INFO); 454 Status = STATUS_SUCCESS; 455 break; 456 } 457 case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO: 458 { 459 PCONSOLE_SCREEN_BUFFER_INFO pcsbi; 460 DPRINT("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO\n"); 461 462 pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer; 463 /* FIXME: remove */ { pcsbi->dwCursorPosition.X++; } 464 /* FIXME: remove */ { pcsbi->dwCursorPosition.Y++; } 465 ASSERT(pcsbi->dwCursorPosition.X >= 1); 466 ASSERT(pcsbi->dwCursorPosition.Y >= 1); 467 ASSERT(pcsbi->dwCursorPosition.X <= DeviceExtension->Columns); 468 ASSERT(pcsbi->dwCursorPosition.Y <= DeviceExtension->Rows); 469 470 DeviceExtension->LogicalOffset = ( 471 (pcsbi->dwCursorPosition.Y-1) * DeviceExtension->Columns + 472 (pcsbi->dwCursorPosition.X-1)) * 2; 473 AddToSendBuffer(DeviceExtension, 6, ESC, '[', 474 -(int)pcsbi->dwCursorPosition.Y, ';', 475 -(int)pcsbi->dwCursorPosition.X, 'H'); 476 477 /* flush buffer */ 478 AddToSendBuffer(DeviceExtension, 0); 479 480 DeviceExtension->CharAttribute = pcsbi->wAttributes; 481 482 Irp->IoStatus.Information = 0; 483 Status = STATUS_SUCCESS; 484 break; 485 } 486 case IOCTL_CONSOLE_GET_CURSOR_INFO: 487 { 488 PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer; 489 DPRINT("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_GET_CURSOR_INFO\n"); 490 491 pcci->dwSize = 1; 492 pcci->bVisible = TRUE; 493 494 Irp->IoStatus.Information = sizeof (CONSOLE_CURSOR_INFO); 495 Status = STATUS_SUCCESS; 496 break; 497 } 498 case IOCTL_CONSOLE_GET_MODE: 499 { 500 PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer; 501 DPRINT("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_GET_MODE\n"); 502 503 pcm->dwMode = DeviceExtension->Mode; 504 505 Irp->IoStatus.Information = sizeof(CONSOLE_MODE); 506 Status = STATUS_SUCCESS; 507 break; 508 } 509 case IOCTL_CONSOLE_SET_MODE: 510 { 511 PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer; 512 DPRINT("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_SET_MODE\n"); 513 514 DeviceExtension->Mode = pcm->dwMode; 515 516 Irp->IoStatus.Information = 0; 517 Status = STATUS_SUCCESS; 518 break; 519 } 520 case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE: 521 { 522 DPRINT1("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE\n"); 523 Status = STATUS_NOT_IMPLEMENTED; /* FIXME: IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE */ 524 break; 525 } 526 case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE: 527 { 528 DPRINT1("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE\n"); 529 Status = STATUS_NOT_IMPLEMENTED; /* FIXME: IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE */ 530 break; 531 } 532 case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE: 533 { 534 DPRINT1("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE\n"); 535 Status = STATUS_NOT_IMPLEMENTED; /* FIXME: IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE */ 536 break; 537 } 538 case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE: 539 { 540 DPRINT("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE\n"); 541 542 DeviceExtension->CharAttribute = (WORD)*(PWORD)Irp->AssociatedIrp.SystemBuffer; 543 Irp->IoStatus.Information = 0; 544 Status = STATUS_SUCCESS; 545 break; 546 } 547 case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER: 548 { 549 DPRINT1("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER\n"); 550 Status = STATUS_NOT_IMPLEMENTED; /* FIXME:IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER */ 551 break; 552 } 553 case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER: 554 { 555 DPRINT1("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_READ_OUTPUT_CHARACTER\n"); 556 Status = STATUS_NOT_IMPLEMENTED; /* FIXME: IOCTL_CONSOLE_READ_OUTPUT_CHARACTER */ 557 break; 558 } 559 case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER: 560 { 561 DPRINT1("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER\n"); 562 Status = STATUS_NOT_IMPLEMENTED; /* FIXME: IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER */ 563 break; 564 } 565 case IOCTL_CONSOLE_DRAW: 566 { 567 PCONSOLE_DRAW ConsoleDraw; 568 PUCHAR Video; 569 ULONG x, y; 570 BOOLEAN DoOptimization = FALSE; 571 DPRINT("IRP_MJ_DEVICE_CONTROL / IOCTL_CONSOLE_DRAW\n"); 572 573 ConsoleDraw = (PCONSOLE_DRAW)MmGetSystemAddressForMdl(Irp->MdlAddress); 574 /* FIXME: remove */ { ConsoleDraw->X++; ConsoleDraw->CursorX++; } 575 /* FIXME: remove */ { ConsoleDraw->Y++; ConsoleDraw->CursorY++; } 576 DPRINT1("%lu %lu %lu %lu\n", 577 ConsoleDraw->X, ConsoleDraw->Y, 578 ConsoleDraw->SizeX, ConsoleDraw->SizeY); 579 ASSERT(ConsoleDraw->X >= 1); 580 ASSERT(ConsoleDraw->Y >= 1); 581 ASSERT(ConsoleDraw->X <= DeviceExtension->Columns); 582 ASSERT(ConsoleDraw->Y <= DeviceExtension->Rows); 583 ASSERT(ConsoleDraw->X + ConsoleDraw->SizeX >= 1); 584 ASSERT(ConsoleDraw->Y + ConsoleDraw->SizeY >= 1); 585 ASSERT(ConsoleDraw->X + ConsoleDraw->SizeX - 1 <= DeviceExtension->Columns); 586 ASSERT(ConsoleDraw->Y + ConsoleDraw->SizeY - 1 <= DeviceExtension->Rows); 587 ASSERT(ConsoleDraw->CursorX >= 1); 588 ASSERT(ConsoleDraw->CursorY >= 1); 589 ASSERT(ConsoleDraw->CursorX <= DeviceExtension->Columns); 590 ASSERT(ConsoleDraw->CursorY <= DeviceExtension->Rows); 591 592 #if 0 593 if (ConsoleDraw->X == 1 594 && ConsoleDraw->Y == 1 595 && ConsoleDraw->SizeX == DeviceExtension->Columns 596 && ConsoleDraw->SizeY == DeviceExtension->Rows) 597 { 598 /* search if we need to clear all screen */ 599 DoOptimization = TRUE; 600 Video = (PUCHAR)(ConsoleDraw + 1); 601 x = 0; 602 while (DoOptimization && x < DeviceExtension->Columns * DeviceExtension->Rows) 603 { 604 if (Video[x++] != ' ') 605 { 606 DoOptimization = FALSE; 607 } 608 /*if (Video[x++] != DeviceExtension->CharAttribute) DoOptimization = FALSE; */ 609 } 610 if (DoOptimization) 611 { 612 AddToSendBuffer(DeviceExtension, 4, ESC, '[', '2', 'J'); 613 } 614 } 615 #endif 616 /* add here more optimizations if needed */ 617 618 if (!DoOptimization) 619 { 620 for (y = 0; y < ConsoleDraw->SizeY; y++) 621 { 622 AddToSendBuffer(DeviceExtension, 6, ESC, '[', 623 -(int)(ConsoleDraw->Y + y), ';', 624 -(int)(ConsoleDraw->X), 'H'); 625 Video = (PUCHAR)(ConsoleDraw + 1); 626 Video = &Video[((ConsoleDraw->Y + y) * /*DeviceExtension->Columns +*/ ConsoleDraw->X) * 2]; 627 for (x = 0; x < ConsoleDraw->SizeX; x++) 628 { 629 AddToSendBuffer(DeviceExtension, 1, Video[x * 2]); 630 } 631 } 632 } 633 634 DeviceExtension->LogicalOffset = ( 635 (ConsoleDraw->CursorY-1) * DeviceExtension->Columns + 636 (ConsoleDraw->CursorX-1)) * 2; 637 AddToSendBuffer(DeviceExtension, 6, ESC, '[', 638 -(int)(ConsoleDraw->CursorY), ';', 639 -(int)(ConsoleDraw->CursorX), 'H'); 640 641 /* flush buffer */ 642 AddToSendBuffer(DeviceExtension, 0); 643 644 Irp->IoStatus.Information = 0; 645 Status = STATUS_SUCCESS; 646 break; 647 } 648 #endif 649 default: 650 { 651 DPRINT1("IRP_MJ_DEVICE_CONTROL / unknown ioctl code 0x%lx\n", 652 Stack->Parameters.DeviceIoControl.IoControlCode); 653 /* Call lower driver */ 654 IoSkipCurrentIrpStackLocation(Irp); 655 return IoCallDriver(DeviceExtension->Common.LowerDevice, Irp); 656 } 657 } 658 659 if (!NT_SUCCESS(Status)) 660 { 661 /* Don't call blue (if any), as we encountered an error */ 662 Irp->IoStatus.Status = Status; 663 IoCompleteRequest(Irp, IO_NO_INCREMENT); 664 return Status; 665 } 666 else 667 { 668 /* Call lower driver */ 669 IoSkipCurrentIrpStackLocation(Irp); 670 return IoCallDriver(DeviceExtension->Common.LowerDevice, Irp); 671 } 672 } 673