Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentuiconsole.c
Go to the documentation of this file.
00001 /* $Id: tuiconsole.c 47693 2010-06-08 06:38:14Z jmorlan $ 00002 * 00003 * COPYRIGHT: See COPYING in the top level directory 00004 * PROJECT: ReactOS system libraries 00005 * FILE: subsys/csrss/win32csr/tuiconsole.c 00006 * PURPOSE: Implementation of text-mode consoles 00007 */ 00008 00009 #define NDEBUG 00010 #include "w32csr.h" 00011 #include <debug.h> 00012 00013 CRITICAL_SECTION ActiveConsoleLock; 00014 static COORD PhysicalConsoleSize; 00015 static HANDLE ConsoleDeviceHandle; 00016 static PCSRSS_CONSOLE ActiveConsole; 00017 00018 static BOOL ConsInitialized = FALSE; 00019 00020 static LRESULT CALLBACK 00021 TuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 00022 { 00023 if (msg == WM_ACTIVATE) 00024 { 00025 if (LOWORD(wParam) != WA_INACTIVE) 00026 { 00027 SetFocus(hWnd); 00028 ConioDrawConsole(ActiveConsole); 00029 } 00030 } 00031 return DefWindowProcW(hWnd, msg, wParam, lParam); 00032 } 00033 00034 static BOOL FASTCALL 00035 TuiStartService(LPCWSTR lpServiceName) 00036 { 00037 SC_HANDLE hSCManager = NULL; 00038 SC_HANDLE hService = NULL; 00039 BOOL ret = FALSE; 00040 00041 hSCManager = OpenSCManagerW(NULL, NULL, 0); 00042 if (hSCManager == NULL) 00043 goto cleanup; 00044 00045 hService = OpenServiceW(hSCManager, lpServiceName, SERVICE_START); 00046 if (hService == NULL) 00047 goto cleanup; 00048 00049 ret = StartServiceW(hService, 0, NULL); 00050 if (!ret) 00051 goto cleanup; 00052 00053 ret = TRUE; 00054 00055 cleanup: 00056 if (hSCManager != NULL) 00057 CloseServiceHandle(hSCManager); 00058 if (hService != NULL) 00059 CloseServiceHandle(hService); 00060 return ret; 00061 } 00062 00063 static BOOL FASTCALL 00064 TuiInit(DWORD OemCP) 00065 { 00066 CONSOLE_SCREEN_BUFFER_INFO ScrInfo; 00067 DWORD BytesReturned; 00068 WNDCLASSEXW wc; 00069 USHORT TextAttribute = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; 00070 00071 TuiStartService(L"Blue"); 00072 00073 ConsoleDeviceHandle = CreateFileW(L"\\\\.\\BlueScreen", FILE_ALL_ACCESS, 0, NULL, 00074 OPEN_EXISTING, 0, NULL); 00075 if (INVALID_HANDLE_VALUE == ConsoleDeviceHandle) 00076 { 00077 DPRINT1("Failed to open BlueScreen.\n"); 00078 return FALSE; 00079 } 00080 00081 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_LOADFONT, 00082 &OemCP, sizeof(OemCP), NULL, 0, 00083 &BytesReturned, NULL)) 00084 { 00085 DPRINT1("Failed to load the font for codepage %d\n", OemCP); 00086 /* Let's suppose the font is good enough to continue */ 00087 } 00088 00089 if (!DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE, 00090 &TextAttribute, sizeof(TextAttribute), NULL, 0, 00091 &BytesReturned, NULL)) 00092 { 00093 DPRINT1("Failed to set text attribute\n"); 00094 } 00095 00096 ActiveConsole = NULL; 00097 InitializeCriticalSection(&ActiveConsoleLock); 00098 if (! DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO, 00099 NULL, 0, &ScrInfo, sizeof(ScrInfo), &BytesReturned, NULL)) 00100 { 00101 DPRINT1("Failed to get console info\n"); 00102 return FALSE; 00103 } 00104 PhysicalConsoleSize = ScrInfo.dwSize; 00105 00106 RtlZeroMemory(&wc, sizeof(WNDCLASSEXW)); 00107 wc.cbSize = sizeof(WNDCLASSEXW); 00108 wc.lpszClassName = L"TuiConsoleWindowClass"; 00109 wc.lpfnWndProc = TuiConsoleWndProc; 00110 wc.hInstance = (HINSTANCE) GetModuleHandleW(NULL); 00111 if (RegisterClassExW(&wc) == 0) 00112 { 00113 DPRINT1("Failed to register console wndproc\n"); 00114 return FALSE; 00115 } 00116 00117 return TRUE; 00118 } 00119 00120 static VOID WINAPI 00121 TuiInitScreenBuffer(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buffer) 00122 { 00123 Buffer->DefaultAttrib = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED; 00124 } 00125 00126 static void FASTCALL 00127 TuiCopyRect(char *Dest, PCSRSS_SCREEN_BUFFER Buff, SMALL_RECT *Region) 00128 { 00129 UINT SrcDelta, DestDelta; 00130 LONG i; 00131 PBYTE Src, SrcEnd; 00132 00133 Src = ConioCoordToPointer(Buff, Region->Left, Region->Top); 00134 SrcDelta = Buff->MaxX * 2; 00135 SrcEnd = Buff->Buffer + Buff->MaxY * Buff->MaxX * 2; 00136 DestDelta = ConioRectWidth(Region) * 2; 00137 for (i = Region->Top; i <= Region->Bottom; i++) 00138 { 00139 memcpy(Dest, Src, DestDelta); 00140 Src += SrcDelta; 00141 if (SrcEnd <= Src) 00142 { 00143 Src -= Buff->MaxY * Buff->MaxX * 2; 00144 } 00145 Dest += DestDelta; 00146 } 00147 } 00148 00149 static VOID WINAPI 00150 TuiDrawRegion(PCSRSS_CONSOLE Console, SMALL_RECT *Region) 00151 { 00152 DWORD BytesReturned; 00153 PCSRSS_SCREEN_BUFFER Buff = Console->ActiveBuffer; 00154 PCONSOLE_DRAW ConsoleDraw; 00155 UINT ConsoleDrawSize; 00156 00157 if (ActiveConsole != Console) 00158 { 00159 return; 00160 } 00161 00162 ConsoleDrawSize = sizeof(CONSOLE_DRAW) + 00163 (ConioRectWidth(Region) * ConioRectHeight(Region)) * 2; 00164 ConsoleDraw = HeapAlloc(Win32CsrApiHeap, 0, ConsoleDrawSize); 00165 if (NULL == ConsoleDraw) 00166 { 00167 DPRINT1("HeapAlloc failed\n"); 00168 return; 00169 } 00170 ConsoleDraw->X = Region->Left; 00171 ConsoleDraw->Y = Region->Top; 00172 ConsoleDraw->SizeX = ConioRectWidth(Region); 00173 ConsoleDraw->SizeY = ConioRectHeight(Region); 00174 ConsoleDraw->CursorX = Buff->CurrentX; 00175 ConsoleDraw->CursorY = Buff->CurrentY; 00176 00177 TuiCopyRect((char *) (ConsoleDraw + 1), Buff, Region); 00178 00179 if (! DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_DRAW, 00180 NULL, 0, ConsoleDraw, ConsoleDrawSize, &BytesReturned, NULL)) 00181 { 00182 DPRINT1("Failed to draw console\n"); 00183 HeapFree(Win32CsrApiHeap, 0, ConsoleDraw); 00184 return; 00185 } 00186 00187 HeapFree(Win32CsrApiHeap, 0, ConsoleDraw); 00188 } 00189 00190 static VOID WINAPI 00191 TuiWriteStream(PCSRSS_CONSOLE Console, SMALL_RECT *Region, LONG CursorStartX, LONG CursorStartY, 00192 UINT ScrolledLines, CHAR *Buffer, UINT Length) 00193 { 00194 DWORD BytesWritten; 00195 PCSRSS_SCREEN_BUFFER Buff = Console->ActiveBuffer; 00196 00197 if (ActiveConsole->ActiveBuffer != Buff) 00198 { 00199 return; 00200 } 00201 00202 if (! WriteFile(ConsoleDeviceHandle, Buffer, Length, &BytesWritten, NULL)) 00203 { 00204 DPRINT1("Error writing to BlueScreen\n"); 00205 } 00206 } 00207 00208 static BOOL WINAPI 00209 TuiSetCursorInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff) 00210 { 00211 CONSOLE_CURSOR_INFO Info; 00212 DWORD BytesReturned; 00213 00214 if (ActiveConsole->ActiveBuffer != Buff) 00215 { 00216 return TRUE; 00217 } 00218 00219 Info.dwSize = ConioEffectiveCursorSize(Console, 100); 00220 Info.bVisible = Buff->CursorInfo.bVisible; 00221 00222 if (! DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_CURSOR_INFO, 00223 &Info, sizeof(Info), NULL, 0, &BytesReturned, NULL)) 00224 { 00225 DPRINT1( "Failed to set cursor info\n" ); 00226 return FALSE; 00227 } 00228 00229 return TRUE; 00230 } 00231 00232 static BOOL WINAPI 00233 TuiSetScreenInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff, UINT OldCursorX, UINT OldCursorY) 00234 { 00235 CONSOLE_SCREEN_BUFFER_INFO Info; 00236 DWORD BytesReturned; 00237 00238 if (ActiveConsole->ActiveBuffer != Buff) 00239 { 00240 return TRUE; 00241 } 00242 00243 Info.dwCursorPosition.X = Buff->CurrentX; 00244 Info.dwCursorPosition.Y = Buff->CurrentY; 00245 Info.wAttributes = Buff->DefaultAttrib; 00246 00247 if (! DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO, 00248 &Info, sizeof(CONSOLE_SCREEN_BUFFER_INFO), NULL, 0, 00249 &BytesReturned, NULL)) 00250 { 00251 DPRINT1( "Failed to set cursor position\n" ); 00252 return FALSE; 00253 } 00254 00255 return TRUE; 00256 } 00257 00258 static BOOL WINAPI 00259 TuiUpdateScreenInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff) 00260 { 00261 return TRUE; 00262 } 00263 00264 static BOOL WINAPI 00265 TuiChangeTitle(PCSRSS_CONSOLE Console) 00266 { 00267 return TRUE; 00268 } 00269 00270 static VOID WINAPI 00271 TuiCleanupConsole(PCSRSS_CONSOLE Console) 00272 { 00273 DestroyWindow(Console->hWindow); 00274 00275 EnterCriticalSection(&ActiveConsoleLock); 00276 00277 /* Switch to next console */ 00278 if (ActiveConsole == Console) 00279 { 00280 ActiveConsole = Console->Next != Console ? Console->Next : NULL; 00281 } 00282 00283 if (Console->Next != Console) 00284 { 00285 Console->Prev->Next = Console->Next; 00286 Console->Next->Prev = Console->Prev; 00287 } 00288 LeaveCriticalSection(&ActiveConsoleLock); 00289 00290 if (NULL != ActiveConsole) 00291 { 00292 ConioDrawConsole(ActiveConsole); 00293 } 00294 } 00295 00296 static BOOL WINAPI 00297 TuiChangeIcon(PCSRSS_CONSOLE Console, HICON hWindowIcon) 00298 { 00299 return TRUE; 00300 } 00301 00302 static NTSTATUS WINAPI 00303 TuiResizeBuffer(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER ScreenBuffer, COORD Size) 00304 { 00305 UNIMPLEMENTED; 00306 return STATUS_NOT_IMPLEMENTED; 00307 } 00308 00309 DWORD WINAPI 00310 TuiConsoleThread (PVOID Data) 00311 { 00312 PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) Data; 00313 HWND NewWindow; 00314 MSG msg; 00315 00316 NewWindow = CreateWindowW(L"TuiConsoleWindowClass", 00317 Console->Title.Buffer, 00318 0, 00319 -32000, -32000, 0, 0, 00320 NULL, NULL, 00321 (HINSTANCE) GetModuleHandleW(NULL), 00322 (PVOID) Console); 00323 Console->hWindow = NewWindow; 00324 if (NULL == NewWindow) 00325 { 00326 DPRINT1("CSR: Unable to create console window\n"); 00327 return 1; 00328 } 00329 00330 SetForegroundWindow(Console->hWindow); 00331 00332 while (TRUE) 00333 { 00334 GetMessageW(&msg, 0, 0, 0); 00335 DispatchMessage(&msg); 00336 TranslateMessage(&msg); 00337 00338 if (msg.message == WM_CHAR || msg.message == WM_SYSCHAR || 00339 msg.message == WM_KEYDOWN || msg.message == WM_KEYUP || 00340 msg.message == WM_SYSKEYDOWN || msg.message == WM_SYSKEYUP) 00341 { 00342 ConioProcessKey(&msg, Console, TRUE); 00343 } 00344 } 00345 00346 return 0; 00347 } 00348 00349 static CSRSS_CONSOLE_VTBL TuiVtbl = 00350 { 00351 TuiInitScreenBuffer, 00352 TuiWriteStream, 00353 TuiDrawRegion, 00354 TuiSetCursorInfo, 00355 TuiSetScreenInfo, 00356 TuiUpdateScreenInfo, 00357 TuiChangeTitle, 00358 TuiCleanupConsole, 00359 TuiChangeIcon, 00360 TuiResizeBuffer, 00361 }; 00362 00363 NTSTATUS FASTCALL 00364 TuiInitConsole(PCSRSS_CONSOLE Console) 00365 { 00366 HANDLE ThreadHandle; 00367 00368 if (! ConsInitialized) 00369 { 00370 ConsInitialized = TRUE; 00371 if (! TuiInit(Console->CodePage)) 00372 { 00373 ConsInitialized = FALSE; 00374 return STATUS_UNSUCCESSFUL; 00375 } 00376 } 00377 00378 Console->Vtbl = &TuiVtbl; 00379 Console->hWindow = NULL; 00380 Console->Size = PhysicalConsoleSize; 00381 Console->ActiveBuffer->MaxX = PhysicalConsoleSize.X; 00382 Console->ActiveBuffer->MaxY = PhysicalConsoleSize.Y; 00383 00384 ThreadHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) TuiConsoleThread, 00385 Console, 0, NULL); 00386 if (NULL == ThreadHandle) 00387 { 00388 DPRINT1("CSR: Unable to create console thread\n"); 00389 return STATUS_UNSUCCESSFUL; 00390 } 00391 CloseHandle(ThreadHandle); 00392 00393 EnterCriticalSection(&ActiveConsoleLock); 00394 if (NULL != ActiveConsole) 00395 { 00396 Console->Prev = ActiveConsole; 00397 Console->Next = ActiveConsole->Next; 00398 ActiveConsole->Next->Prev = Console; 00399 ActiveConsole->Next = Console; 00400 } 00401 else 00402 { 00403 Console->Prev = Console; 00404 Console->Next = Console; 00405 } 00406 ActiveConsole = Console; 00407 LeaveCriticalSection(&ActiveConsoleLock); 00408 00409 return STATUS_SUCCESS; 00410 } 00411 00412 PCSRSS_CONSOLE FASTCALL 00413 TuiGetFocusConsole(VOID) 00414 { 00415 return ActiveConsole; 00416 } 00417 00418 BOOL FASTCALL 00419 TuiSwapConsole(int Next) 00420 { 00421 static PCSRSS_CONSOLE SwapConsole = NULL; /* console we are thinking about swapping with */ 00422 DWORD BytesReturned; 00423 ANSI_STRING Title; 00424 void * Buffer; 00425 COORD *pos; 00426 00427 if (0 != Next) 00428 { 00429 /* alt-tab, swap consoles */ 00430 /* move SwapConsole to next console, and print its title */ 00431 EnterCriticalSection(&ActiveConsoleLock); 00432 if (! SwapConsole) 00433 { 00434 SwapConsole = ActiveConsole; 00435 } 00436 00437 SwapConsole = (0 < Next ? SwapConsole->Next : SwapConsole->Prev); 00438 Title.MaximumLength = RtlUnicodeStringToAnsiSize(&SwapConsole->Title); 00439 Title.Length = 0; 00440 Buffer = HeapAlloc(Win32CsrApiHeap, 00441 0, 00442 sizeof(COORD) + Title.MaximumLength); 00443 pos = (COORD *)Buffer; 00444 Title.Buffer = (PVOID)((ULONG_PTR)Buffer + sizeof( COORD )); 00445 00446 RtlUnicodeStringToAnsiString(&Title, &SwapConsole->Title, FALSE); 00447 pos->Y = PhysicalConsoleSize.Y / 2; 00448 pos->X = (PhysicalConsoleSize.X - Title.Length) / 2; 00449 /* redraw the console to clear off old title */ 00450 ConioDrawConsole(ActiveConsole); 00451 if (! DeviceIoControl(ConsoleDeviceHandle, IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER, 00452 NULL, 0, Buffer, sizeof(COORD) + Title.Length, 00453 &BytesReturned, NULL)) 00454 { 00455 DPRINT1( "Error writing to console\n" ); 00456 } 00457 HeapFree(Win32CsrApiHeap, 0, Buffer); 00458 LeaveCriticalSection(&ActiveConsoleLock); 00459 00460 return TRUE; 00461 } 00462 else if (NULL != SwapConsole) 00463 { 00464 EnterCriticalSection(&ActiveConsoleLock); 00465 if (SwapConsole != ActiveConsole) 00466 { 00467 /* first remove swapconsole from the list */ 00468 SwapConsole->Prev->Next = SwapConsole->Next; 00469 SwapConsole->Next->Prev = SwapConsole->Prev; 00470 /* now insert before activeconsole */ 00471 SwapConsole->Next = ActiveConsole; 00472 SwapConsole->Prev = ActiveConsole->Prev; 00473 ActiveConsole->Prev->Next = SwapConsole; 00474 ActiveConsole->Prev = SwapConsole; 00475 } 00476 ActiveConsole = SwapConsole; 00477 SwapConsole = NULL; 00478 ConioDrawConsole(ActiveConsole); 00479 LeaveCriticalSection(&ActiveConsoleLock); 00480 return TRUE; 00481 } 00482 else 00483 { 00484 return FALSE; 00485 } 00486 } 00487 00488 /* EOF */ Generated on Sun May 27 2012 04:38:45 for ReactOS by
1.7.6.1
|