move from branch
[reactos.git] / reactos / subsystems / win32 / csrss / win32csr / guiconsole.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: subsys/csrss/win32csr/guiconsole.c
6 * PURPOSE: Implementation of gui-mode consoles
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "w32csr.h"
12
13 #define NDEBUG
14 #include <debug.h>
15
16 /* Not defined in any header file */
17 extern VOID STDCALL PrivateCsrssManualGuiCheck(LONG Check);
18
19 /* GLOBALS *******************************************************************/
20
21 typedef struct GUI_CONSOLE_DATA_TAG
22 {
23 HFONT Font;
24 unsigned CharWidth;
25 unsigned CharHeight;
26 PWCHAR LineBuffer;
27 BOOL CursorBlinkOn;
28 BOOL ForceCursorOff;
29 CRITICAL_SECTION Lock;
30 RECT Selection;
31 POINT SelectionStart;
32 BOOL MouseDown;
33 HMODULE ConsoleLibrary;
34 HANDLE hGuiInitEvent;
35 HWND hVScrollBar;
36 HWND hHScrollBar;
37 WCHAR FontName[LF_FACESIZE];
38 DWORD FontSize;
39 DWORD FontWeight;
40 DWORD HistoryNoDup;
41 DWORD FullScreen;
42 DWORD QuickEdit;
43 DWORD InsertMode;
44 DWORD NumberOfHistoryBuffers;
45 DWORD HistoryBufferSize;
46 DWORD WindowPosition;
47 DWORD ScreenBufferSize;
48 DWORD UseRasterFonts;
49 COLORREF ScreenText;
50 COLORREF ScreenBackground;
51 COLORREF PopupBackground;
52 COLORREF PopupText;
53 COLORREF Colors[16];
54 WCHAR szProcessName[MAX_PATH];
55 } GUI_CONSOLE_DATA, *PGUI_CONSOLE_DATA;
56
57 #ifndef WM_APP
58 #define WM_APP 0x8000
59 #endif
60 #define PM_CREATE_CONSOLE (WM_APP + 1)
61 #define PM_DESTROY_CONSOLE (WM_APP + 2)
62
63 #define CURSOR_BLINK_TIME 500
64 #define DEFAULT_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY)
65
66 static BOOL ConsInitialized = FALSE;
67 static HWND NotifyWnd;
68
69 typedef struct _GUICONSOLE_MENUITEM
70 {
71 UINT uID;
72 const struct _GUICONSOLE_MENUITEM *SubMenu;
73 WORD wCmdID;
74 } GUICONSOLE_MENUITEM, *PGUICONSOLE_MENUITEM;
75
76 static const GUICONSOLE_MENUITEM GuiConsoleEditMenuItems[] =
77 {
78 { IDS_MARK, NULL, ID_SYSTEM_EDIT_MARK },
79 { IDS_COPY, NULL, ID_SYSTEM_EDIT_COPY },
80 { IDS_PASTE, NULL, ID_SYSTEM_EDIT_PASTE },
81 { IDS_SELECTALL, NULL, ID_SYSTEM_EDIT_SELECTALL },
82 { IDS_SCROLL, NULL, ID_SYSTEM_EDIT_SCROLL },
83 { IDS_FIND, NULL, ID_SYSTEM_EDIT_FIND },
84
85 { 0, NULL, 0 } /* End of list */
86 };
87
88 static const GUICONSOLE_MENUITEM GuiConsoleMainMenuItems[] =
89 {
90 { (UINT)-1, NULL, 0 }, /* Separator */
91 { IDS_EDIT, GuiConsoleEditMenuItems, 0 },
92 { IDS_DEFAULTS, NULL, ID_SYSTEM_DEFAULTS },
93 { IDS_PROPERTIES, NULL, ID_SYSTEM_PROPERTIES },
94
95 { 0, NULL, 0 } /* End of list */
96 };
97
98 static const COLORREF s_Colors[] =
99 {
100 RGB(0, 0, 0),
101 RGB(0, 0, 128),
102 RGB(0, 128, 0),
103 RGB(0, 128, 128),
104 RGB(128, 0, 0),
105 RGB(128, 0, 128),
106 RGB(128, 128, 0),
107 RGB(192, 192, 192),
108 RGB(128, 128, 128),
109 RGB(0, 0, 255),
110 RGB(0, 255, 0),
111 RGB(0, 255, 255),
112 RGB(255, 0, 0),
113 RGB(255, 0, 255),
114 RGB(255, 255, 0),
115 RGB(255, 255, 255)
116 };
117
118 /* FUNCTIONS *****************************************************************/
119
120 static VOID FASTCALL
121 GuiConsoleAppendMenuItems(HMENU hMenu,
122 const GUICONSOLE_MENUITEM *Items)
123 {
124 UINT i;
125 WCHAR szMenuString[255];
126 HMENU hSubMenu;
127
128 for (i = 0; Items[i].uID != 0; i++)
129 {
130 if (Items[i].uID != (UINT)-1)
131 {
132 if (LoadStringW(Win32CsrDllHandle,
133 Items[i].uID,
134 szMenuString,
135 sizeof(szMenuString) / sizeof(szMenuString[0])) > 0)
136 {
137 if (Items[i].SubMenu != NULL)
138 {
139 hSubMenu = CreatePopupMenu();
140 if (hSubMenu != NULL)
141 {
142 GuiConsoleAppendMenuItems(hSubMenu,
143 Items[i].SubMenu);
144
145 if (!AppendMenuW(hMenu,
146 MF_STRING | MF_POPUP,
147 (UINT_PTR)hSubMenu,
148 szMenuString))
149 {
150 DestroyMenu(hSubMenu);
151 }
152 }
153 }
154 else
155 {
156 AppendMenuW(hMenu,
157 MF_STRING,
158 Items[i].wCmdID,
159 szMenuString);
160 }
161 }
162 }
163 else
164 {
165 AppendMenuW(hMenu,
166 MF_SEPARATOR,
167 0,
168 NULL);
169 }
170 }
171 }
172
173 static VOID FASTCALL
174 GuiConsoleCreateSysMenu(PCSRSS_CONSOLE Console)
175 {
176 HMENU hMenu;
177
178 hMenu = GetSystemMenu(Console->hWindow,
179 FALSE);
180 if (hMenu != NULL)
181 {
182 GuiConsoleAppendMenuItems(hMenu,
183 GuiConsoleMainMenuItems);
184 }
185 }
186
187 static VOID FASTCALL
188 GuiConsoleGetDataPointers(HWND hWnd, PCSRSS_CONSOLE *Console, PGUI_CONSOLE_DATA *GuiData)
189 {
190 *Console = (PCSRSS_CONSOLE) GetWindowLongPtrW(hWnd, GWL_USERDATA);
191 *GuiData = (NULL == *Console ? NULL : (*Console)->PrivateData);
192 }
193
194 static BOOL FASTCALL
195 GuiConsoleOpenUserRegistryPathPerProcessId(DWORD ProcessId, PHANDLE hProcHandle, PHKEY hResult, REGSAM samDesired)
196 {
197 HANDLE hProcessToken = NULL;
198 HANDLE hProcess;
199
200 BYTE Buffer[256];
201 DWORD Length = 0;
202 UNICODE_STRING SidName;
203 LONG res;
204 PTOKEN_USER TokUser;
205
206 hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | READ_CONTROL, FALSE, ProcessId);
207 if (!hProcess)
208 {
209 DPRINT("Error: OpenProcess failed(0x%x)\n", GetLastError());
210 return FALSE;
211 }
212
213 if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hProcessToken))
214 {
215 DPRINT("Error: OpenProcessToken failed(0x%x)\n", GetLastError());
216 CloseHandle(hProcess);
217 return FALSE;
218 }
219
220 if (!GetTokenInformation(hProcessToken, TokenUser, (PVOID)Buffer, sizeof(Buffer), &Length))
221 {
222 DPRINT("Error: GetTokenInformation failed(0x%x)\n",GetLastError());
223 CloseHandle(hProcess);
224 CloseHandle(hProcessToken);
225 return FALSE;
226 }
227
228 TokUser = ((PTOKEN_USER)Buffer)->User.Sid;
229 if (!NT_SUCCESS(RtlConvertSidToUnicodeString(&SidName, TokUser, TRUE)))
230 {
231 DPRINT("Error: RtlConvertSidToUnicodeString failed(0x%x)\n", GetLastError());
232 return FALSE;
233 }
234
235 res = RegOpenKeyExW(HKEY_USERS, SidName.Buffer, 0, samDesired, hResult);
236 RtlFreeUnicodeString(&SidName);
237
238 CloseHandle(hProcessToken);
239 if (hProcHandle)
240 *hProcHandle = hProcess;
241 else
242 CloseHandle(hProcess);
243
244 if (res != ERROR_SUCCESS)
245 return FALSE;
246 else
247 return TRUE;
248 }
249
250 static BOOL FASTCALL
251 GuiConsoleOpenUserSettings(PGUI_CONSOLE_DATA GuiData, DWORD ProcessId, PHKEY hSubKey, REGSAM samDesired, BOOL bCreate)
252 {
253 WCHAR szProcessName[MAX_PATH];
254 WCHAR szBuffer[MAX_PATH];
255 UINT fLength, wLength;
256 DWORD dwBitmask, dwLength;
257 WCHAR CurDrive[] = { 'A',':', 0 };
258 HANDLE hProcess;
259 HKEY hKey;
260 WCHAR * ptr;
261
262 /*
263 * console properties are stored under
264 * HKCU\Console\*
265 *
266 * There are 3 ways to store console properties
267 *
268 * 1. use console title as subkey name
269 * i.e. cmd.exe
270 *
271 * 2. use application name as subkey name
272 *
273 * 3. use unexpanded path to console application.
274 * i.e. %SystemRoot%_system32_cmd.exe
275 */
276
277 DPRINT("GuiConsoleOpenUserSettings entered\n");
278
279 if (!GuiConsoleOpenUserRegistryPathPerProcessId(ProcessId, &hProcess, &hKey, samDesired))
280 {
281 DPRINT("GuiConsoleOpenUserRegistryPathPerProcessId failed\n");
282 return FALSE;
283 }
284
285 fLength = GetProcessImageFileNameW(hProcess, szProcessName, sizeof(GuiData->szProcessName) / sizeof(WCHAR));
286 CloseHandle(hProcess);
287
288 if (!fLength)
289 {
290 DPRINT("GetProcessImageFileNameW failed(0x%x)ProcessId %d\n", GetLastError(),hProcess);
291 return FALSE;
292 }
293 /*
294 * try the process name as path
295 */
296
297 ptr = wcsrchr(szProcessName, L'\\');
298 wcscpy(GuiData->szProcessName, ptr);
299
300 swprintf(szBuffer, L"Console%s",ptr);
301 DPRINT("#1 Path : %S\n", szBuffer);
302
303 if (bCreate)
304 {
305 if (RegCreateKeyW(hKey, szBuffer, hSubKey) == ERROR_SUCCESS)
306 {
307 RegCloseKey(hKey);
308 return TRUE;
309 }
310 RegCloseKey(hKey);
311 return FALSE;
312 }
313
314 if (RegOpenKeyExW(hKey, szBuffer, 0, samDesired, hSubKey) == ERROR_SUCCESS)
315 {
316 RegCloseKey(hKey);
317 return TRUE;
318 }
319
320 /*
321 * try the "Shortcut to processname" as path
322 * FIXME: detect wheter the process was started as a shortcut
323 */
324
325 swprintf(szBuffer, L"Console\\Shortcut to %S", ptr);
326 DPRINT("#2 Path : %S\n", szBuffer);
327 if (RegOpenKeyExW(hKey, szBuffer, 0, samDesired, hSubKey) == ERROR_SUCCESS)
328 {
329 swprintf(GuiData->szProcessName, L"Shortcut to %S", ptr);
330 RegCloseKey(hKey);
331 return TRUE;
332 }
333
334 /*
335 * if the path contains \\Device\\HarddiskVolume1\... remove it
336 */
337
338 if (szProcessName[0] == L'\\')
339 {
340 dwBitmask = GetLogicalDrives();
341 while(dwBitmask)
342 {
343 if (dwBitmask & 0x1)
344 {
345 dwLength = QueryDosDeviceW(CurDrive, szBuffer, MAX_PATH);
346 if (dwLength)
347 {
348 if (!memcmp(szBuffer, szProcessName, (dwLength-2)*sizeof(WCHAR)))
349 {
350 wcscpy(szProcessName, CurDrive);
351 RtlMoveMemory(&szProcessName[2], &szProcessName[dwLength-1], fLength - dwLength -1);
352 break;
353 }
354 }
355 }
356 dwBitmask = (dwBitmask >> 1);
357 CurDrive[0]++;
358 }
359 }
360
361 /*
362 * last attempt: check whether the file is under %SystemRoot%
363 * and use path like Console\%SystemRoot%_dir_dir2_file.exe
364 */
365
366 wLength = GetWindowsDirectoryW(szBuffer, MAX_PATH);
367 if (wLength)
368 {
369 if (!wcsncmp(szProcessName, szBuffer, wLength))
370 {
371 /* replace slashes by underscores */
372 while((ptr = wcschr(szProcessName, L'\\')))
373 ptr[0] = L'_';
374
375 swprintf(szBuffer, L"Console\\\%SystemRoot\%%S", &szProcessName[wLength]);
376 DPRINT("#3 Path : %S\n", szBuffer);
377 if (RegOpenKeyExW(hKey, szBuffer, 0, samDesired, hSubKey) == ERROR_SUCCESS)
378 {
379 swprintf(GuiData->szProcessName, L"\%SystemRoot\%%S", &szProcessName[wLength]);
380 RegCloseKey(hKey);
381 return TRUE;
382 }
383 }
384 }
385 RegCloseKey(hKey);
386 return FALSE;
387 }
388
389 static VOID
390 GuiConsoleWriteUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData)
391 {
392 HKEY hKey;
393 PCSRSS_PROCESS_DATA ProcessData;
394
395 if (Console->ProcessList.Flink == &Console->ProcessList)
396 {
397 DPRINT("GuiConsoleWriteUserSettings: No Process!!!\n");
398 return;
399 }
400 ProcessData = CONTAINING_RECORD(Console->ProcessList.Flink, CSRSS_PROCESS_DATA, ProcessEntry);
401 if (!GuiConsoleOpenUserSettings(GuiData, PtrToUlong(ProcessData->ProcessId), &hKey, KEY_READ | KEY_WRITE, TRUE))
402 {
403 return;
404 }
405
406 if (Console->ActiveBuffer->CursorInfo.dwSize <= 1)
407 {
408 RegDeleteKeyW(hKey, L"CursorSize");
409 }
410 else
411 {
412 RegSetValueExW(hKey, L"CursorSize", 0, REG_DWORD, (const BYTE *)&Console->ActiveBuffer->CursorInfo.dwSize, sizeof(DWORD));
413 }
414
415 if (GuiData->NumberOfHistoryBuffers == 5)
416 {
417 RegDeleteKeyW(hKey, L"NumberOfHistoryBuffers");
418 }
419 else
420 {
421 RegSetValueExW(hKey, L"NumberOfHistoryBuffers", 0, REG_DWORD, (const BYTE *)&GuiData->NumberOfHistoryBuffers, sizeof(DWORD));
422 }
423
424 if (GuiData->HistoryBufferSize == 50)
425 {
426 RegDeleteKeyW(hKey, L"HistoryBufferSize");
427 }
428 else
429 {
430 RegSetValueExW(hKey, L"HistoryBufferSize", 0, REG_DWORD, (const BYTE *)&GuiData->HistoryBufferSize, sizeof(DWORD));
431 }
432
433 if (GuiData->FullScreen == FALSE)
434 {
435 RegDeleteKeyW(hKey, L"FullScreen");
436 }
437 else
438 {
439 RegSetValueExW(hKey, L"FullScreen", 0, REG_DWORD, (const BYTE *)&GuiData->FullScreen, sizeof(DWORD));
440 }
441
442 if ( GuiData->QuickEdit == FALSE)
443 {
444 RegDeleteKeyW(hKey, L"QuickEdit");
445 }
446 else
447 {
448 RegSetValueExW(hKey, L"QuickEdit", 0, REG_DWORD, (const BYTE *)&GuiData->QuickEdit, sizeof(DWORD));
449 }
450
451 if (GuiData->InsertMode == TRUE)
452 {
453 RegDeleteKeyW(hKey, L"InsertMode");
454 }
455 else
456 {
457 RegSetValueExW(hKey, L"InsertMode", 0, REG_DWORD, (const BYTE *)&GuiData->InsertMode, sizeof(DWORD));
458 }
459
460 if (GuiData->HistoryNoDup == FALSE)
461 {
462 RegDeleteKeyW(hKey, L"HistoryNoDup");
463 }
464 else
465 {
466 RegSetValueExW(hKey, L"HistoryNoDup", 0, REG_DWORD, (const BYTE *)&GuiData->HistoryNoDup, sizeof(DWORD));
467 }
468
469 if (GuiData->ScreenText == RGB(192, 192, 192))
470 {
471 /*
472 * MS uses console attributes instead of real color
473 */
474 RegDeleteKeyW(hKey, L"ScreenText");
475 }
476 else
477 {
478 RegSetValueExW(hKey, L"ScreenText", 0, REG_DWORD, (const BYTE *)&GuiData->ScreenText, sizeof(COLORREF));
479 }
480
481 if (GuiData->ScreenBackground == RGB(0, 0, 0))
482 {
483 RegDeleteKeyW(hKey, L"ScreenBackground");
484 }
485 else
486 {
487 RegSetValueExW(hKey, L"ScreenBackground", 0, REG_DWORD, (const BYTE *)&GuiData->ScreenBackground, sizeof(COLORREF));
488 }
489
490 RegCloseKey(hKey);
491 }
492
493 static void FASTCALL
494 GuiConsoleReadUserSettings(HKEY hKey, PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PCSRSS_SCREEN_BUFFER Buffer)
495 {
496 DWORD dwNumSubKeys = 0;
497 DWORD dwIndex;
498 DWORD dwValueName;
499 DWORD dwValue;
500 DWORD dwType;
501 WCHAR szValueName[MAX_PATH];
502 WCHAR szValue[MAX_PATH];
503 DWORD Value;
504
505 if (RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwNumSubKeys, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
506 {
507 DPRINT("GuiConsoleReadUserSettings: RegQueryInfoKey failed\n");
508 return;
509 }
510
511 DPRINT("GuiConsoleReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys);
512
513 for (dwIndex = 0; dwIndex < dwNumSubKeys; dwIndex++)
514 {
515 dwValue = sizeof(Value);
516 dwValueName = MAX_PATH;
517
518 if (RegEnumValueW(hKey, dwIndex, szValueName, &dwValueName, NULL, &dwType, (BYTE*)&Value, &dwValue) != ERROR_SUCCESS)
519 {
520 if (dwType == REG_SZ)
521 {
522 /*
523 * retry in case of string value
524 */
525 dwValue = sizeof(szValue);
526 dwValueName = MAX_PATH;
527 if (RegEnumValueW(hKey, dwIndex, szValueName, &dwValueName, NULL, NULL, (BYTE*)szValue, &dwValue) != ERROR_SUCCESS)
528 break;
529 }
530 else
531 break;
532 }
533 if (!wcscmp(szValueName, L"CursorSize"))
534 {
535 if (Value == 0x32)
536 {
537 Buffer->CursorInfo.dwSize = Value;
538 }
539 else if (Value == 0x64)
540 {
541 Buffer->CursorInfo.dwSize = Value;
542 }
543 }
544 else if (!wcscmp(szValueName, L"ScreenText"))
545 {
546 GuiData->ScreenText = Value;
547 }
548 else if (!wcscmp(szValueName, L"ScreenBackground"))
549 {
550 GuiData->ScreenBackground = Value;
551 }
552 else if (!wcscmp(szValueName, L"FaceName"))
553 {
554 wcscpy(GuiData->FontName, szValue);
555 }
556 else if (!wcscmp(szValueName, L"FontSize"))
557 {
558 GuiData->FontSize = Value;
559 }
560 else if (!wcscmp(szValueName, L"FontWeight"))
561 {
562 GuiData->FontWeight = Value;
563 }
564 else if (!wcscmp(szValueName, L"HistoryNoDup"))
565 {
566 GuiData->HistoryNoDup = Value;
567 }
568 else if (!wcscmp(szValueName, L"WindowSize"))
569 {
570 Console->Size.X = LOWORD(Value);
571 Console->Size.Y = HIWORD(Value);
572 }
573 else if (!wcscmp(szValueName, L"ScreenBufferSize"))
574 {
575 if(Buffer)
576 {
577 Buffer->MaxX = LOWORD(Value);
578 Buffer->MaxY = HIWORD(Value);
579 }
580 }
581 else if (!wcscmp(szValueName, L"FullScreen"))
582 {
583 GuiData->FullScreen = Value;
584 }
585 else if (!wcscmp(szValueName, L"QuickEdit"))
586 {
587 GuiData->QuickEdit = Value;
588 }
589 else if (!wcscmp(szValueName, L"InsertMode"))
590 {
591 GuiData->InsertMode = Value;
592 }
593 }
594 }
595 static VOID FASTCALL
596 GuiConsoleUseDefaults(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PCSRSS_SCREEN_BUFFER Buffer)
597 {
598 /*
599 * init guidata with default properties
600 */
601
602 wcscpy(GuiData->FontName, L"Bitstream Vera Sans Mono");
603 GuiData->FontSize = 0x0008000C; // font is 8x12
604 GuiData->FontWeight = FW_NORMAL;
605 GuiData->HistoryNoDup = FALSE;
606 GuiData->FullScreen = FALSE;
607 GuiData->QuickEdit = FALSE;
608 GuiData->InsertMode = TRUE;
609 GuiData->HistoryBufferSize = 50;
610 GuiData->NumberOfHistoryBuffers = 5;
611 GuiData->ScreenText = RGB(192, 192, 192);
612 GuiData->ScreenBackground = RGB(0, 0, 0);
613 GuiData->PopupText = RGB(128, 0, 128);
614 GuiData->PopupBackground = RGB(255, 255, 255);
615 GuiData->WindowPosition = UINT_MAX;
616 GuiData->ScreenBufferSize = MAKELONG(80, 300); //FIXME
617 GuiData->UseRasterFonts = TRUE;
618 memcpy(GuiData->Colors, s_Colors, sizeof(s_Colors));
619
620 Console->Size.X = 80;
621 Console->Size.Y = 25;
622
623 if (Buffer)
624 {
625 Buffer->MaxX = 80;
626 Buffer->MaxY = 25;
627 Buffer->CursorInfo.bVisible = TRUE;
628 Buffer->CursorInfo.dwSize = 5;
629 }
630 }
631
632
633
634 static BOOL FASTCALL
635 GuiConsoleHandleNcCreate(HWND hWnd, CREATESTRUCTW *Create)
636 {
637 RECT Rect;
638 PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) Create->lpCreateParams;
639 PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)Console->PrivateData;
640 HDC Dc;
641 HFONT OldFont;
642 TEXTMETRICW Metrics;
643 PCSRSS_PROCESS_DATA ProcessData;
644 HKEY hKey;
645
646 Console->hWindow = hWnd;
647
648 if (NULL == GuiData)
649 {
650 DPRINT1("GuiConsoleNcCreate: HeapAlloc failed\n");
651 return FALSE;
652 }
653
654 GuiConsoleUseDefaults(Console, GuiData, Console->ActiveBuffer);
655 if (Console->ProcessList.Flink != &Console->ProcessList)
656 {
657 ProcessData = CONTAINING_RECORD(Console->ProcessList.Flink, CSRSS_PROCESS_DATA, ProcessEntry);
658 if (GuiConsoleOpenUserSettings(GuiData, PtrToUlong(ProcessData->ProcessId), &hKey, KEY_READ, FALSE))
659 {
660 GuiConsoleReadUserSettings(hKey, Console, GuiData, Console->ActiveBuffer);
661 RegCloseKey(hKey);
662 }
663 }
664
665 InitializeCriticalSection(&GuiData->Lock);
666
667 GuiData->LineBuffer = (PWCHAR)HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY,
668 Console->Size.X * sizeof(WCHAR));
669
670 GuiData->Font = CreateFontW(LOWORD(GuiData->FontSize),
671 0, //HIWORD(GuiData->FontSize),
672 0,
673 TA_BASELINE,
674 GuiData->FontWeight,
675 FALSE,
676 FALSE,
677 FALSE,
678 OEM_CHARSET,
679 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
680 NONANTIALIASED_QUALITY, FIXED_PITCH | FF_DONTCARE,
681 GuiData->FontName);
682 if (NULL == GuiData->Font)
683 {
684 DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
685 DeleteCriticalSection(&GuiData->Lock);
686 HeapFree(Win32CsrApiHeap, 0, GuiData);
687 return FALSE;
688 }
689 Dc = GetDC(hWnd);
690 if (NULL == Dc)
691 {
692 DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
693 DeleteObject(GuiData->Font);
694 DeleteCriticalSection(&GuiData->Lock);
695 HeapFree(Win32CsrApiHeap, 0, GuiData);
696 return FALSE;
697 }
698 OldFont = SelectObject(Dc, GuiData->Font);
699 if (NULL == OldFont)
700 {
701 DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
702 ReleaseDC(hWnd, Dc);
703 DeleteObject(GuiData->Font);
704 DeleteCriticalSection(&GuiData->Lock);
705 HeapFree(Win32CsrApiHeap, 0, GuiData);
706 return FALSE;
707 }
708 if (! GetTextMetricsW(Dc, &Metrics))
709 {
710 DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
711 SelectObject(Dc, OldFont);
712 ReleaseDC(hWnd, Dc);
713 DeleteObject(GuiData->Font);
714 DeleteCriticalSection(&GuiData->Lock);
715 HeapFree(Win32CsrApiHeap, 0, GuiData);
716 return FALSE;
717 }
718 GuiData->CharWidth = Metrics.tmMaxCharWidth;
719 GuiData->CharHeight = Metrics.tmHeight + Metrics.tmExternalLeading;
720 SelectObject(Dc, OldFont);
721
722 ReleaseDC(hWnd, Dc);
723 GuiData->CursorBlinkOn = TRUE;
724 GuiData->ForceCursorOff = FALSE;
725
726 GuiData->Selection.left = -1;
727 DPRINT("Console %p GuiData %p\n", Console, GuiData);
728 Console->PrivateData = GuiData;
729 SetWindowLongPtrW(hWnd, GWL_USERDATA, (DWORD_PTR) Console);
730
731 GetWindowRect(hWnd, &Rect);
732 Rect.right = Rect.left + Console->Size.X * GuiData->CharWidth +
733 2 * GetSystemMetrics(SM_CXFIXEDFRAME);
734 Rect.bottom = Rect.top + Console->Size.Y * GuiData->CharHeight +
735 2 * GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYCAPTION);
736 MoveWindow(hWnd, Rect.left, Rect.top, Rect.right - Rect.left,
737 Rect.bottom - Rect.top, FALSE);
738
739 SetTimer(hWnd, 1, CURSOR_BLINK_TIME, NULL);
740 GuiConsoleCreateSysMenu(Console);
741 SetEvent(GuiData->hGuiInitEvent);
742
743 return (BOOL) DefWindowProcW(hWnd, WM_NCCREATE, 0, (LPARAM) Create);
744 }
745
746 static COLORREF FASTCALL
747 GuiConsoleRGBFromAttribute(BYTE Attribute)
748 {
749 int Red = (Attribute & 0x04 ? (Attribute & 0x08 ? 0xff : 0x80) : 0x00);
750 int Green = (Attribute & 0x02 ? (Attribute & 0x08 ? 0xff : 0x80) : 0x00);
751 int Blue = (Attribute & 0x01 ? (Attribute & 0x08 ? 0xff : 0x80) : 0x00);
752
753 return RGB(Red, Green, Blue);
754 }
755
756 static VOID FASTCALL
757 GuiConsoleSetTextColors(HDC Dc, BYTE Attribute, PCSRSS_SCREEN_BUFFER Buff, COLORREF TextColor, COLORREF BkColor)
758 {
759 if (Attribute != Buff->DefaultAttrib)
760 {
761 SetTextColor(Dc, GuiConsoleRGBFromAttribute(Attribute & 0x0f));
762 SetBkColor(Dc, GuiConsoleRGBFromAttribute((Attribute & 0xf0) >> 4));
763 }
764 else
765 {
766 SetTextColor(Dc, TextColor);
767 SetBkColor(Dc, BkColor);
768 }
769 }
770
771 static VOID FASTCALL
772 GuiConsoleGetLogicalCursorPos(PCSRSS_SCREEN_BUFFER Buff, ULONG *CursorX, ULONG *CursorY)
773 {
774 *CursorX = Buff->CurrentX;
775 if (Buff->CurrentY < Buff->ShowY)
776 {
777 *CursorY = Buff->MaxY - Buff->ShowY + Buff->CurrentY;
778 }
779 else
780 {
781 *CursorY = Buff->CurrentY - Buff->ShowY;
782 }
783 }
784
785
786 static VOID FASTCALL
787 GuiConsoleUpdateSelection(HWND hWnd, PRECT rc, PGUI_CONSOLE_DATA GuiData)
788 {
789 RECT oldRect = GuiData->Selection;
790
791 if(rc != NULL)
792 {
793 RECT changeRect = *rc;
794
795 GuiData->Selection = *rc;
796
797 changeRect.left *= GuiData->CharWidth;
798 changeRect.top *= GuiData->CharHeight;
799 changeRect.right *= GuiData->CharWidth;
800 changeRect.bottom *= GuiData->CharHeight;
801
802 if(rc->left != oldRect.left ||
803 rc->top != oldRect.top ||
804 rc->right != oldRect.right ||
805 rc->bottom != oldRect.bottom)
806 {
807 if(oldRect.left != -1)
808 {
809 HRGN rgn1, rgn2;
810
811 oldRect.left *= GuiData->CharWidth;
812 oldRect.top *= GuiData->CharHeight;
813 oldRect.right *= GuiData->CharWidth;
814 oldRect.bottom *= GuiData->CharHeight;
815
816 /* calculate the region that needs to be updated */
817 if((rgn1 = CreateRectRgnIndirect(&oldRect)))
818 {
819 if((rgn2 = CreateRectRgnIndirect(&changeRect)))
820 {
821 if(CombineRgn(rgn1, rgn2, rgn1, RGN_XOR) != ERROR)
822 {
823 InvalidateRgn(hWnd, rgn1, FALSE);
824 }
825
826 DeleteObject(rgn2);
827 }
828 DeleteObject(rgn1);
829 }
830 }
831 else
832 {
833 InvalidateRect(hWnd, &changeRect, FALSE);
834 }
835 }
836 }
837 else if(oldRect.left != -1)
838 {
839 /* clear the selection */
840 GuiData->Selection.left = -1;
841 oldRect.left *= GuiData->CharWidth;
842 oldRect.top *= GuiData->CharHeight;
843 oldRect.right *= GuiData->CharWidth;
844 oldRect.bottom *= GuiData->CharHeight;
845 InvalidateRect(hWnd, &oldRect, FALSE);
846 }
847 }
848
849
850 static VOID FASTCALL
851 GuiConsolePaint(PCSRSS_CONSOLE Console,
852 PGUI_CONSOLE_DATA GuiData,
853 HDC hDC,
854 PRECT rc)
855 {
856 PCSRSS_SCREEN_BUFFER Buff;
857 ULONG TopLine, BottomLine, LeftChar, RightChar;
858 ULONG Line, Char, Start;
859 PBYTE From;
860 PWCHAR To;
861 BYTE LastAttribute, Attribute;
862 ULONG CursorX, CursorY, CursorHeight;
863 HBRUSH CursorBrush, OldBrush;
864 HFONT OldFont;
865
866 Buff = Console->ActiveBuffer;
867
868 TopLine = rc->top / GuiData->CharHeight;
869 BottomLine = (rc->bottom + (GuiData->CharHeight - 1)) / GuiData->CharHeight - 1;
870 LeftChar = rc->left / GuiData->CharWidth;
871 RightChar = (rc->right + (GuiData->CharWidth - 1)) / GuiData->CharWidth - 1;
872 LastAttribute = Buff->Buffer[(TopLine * Buff->MaxX + LeftChar) * 2 + 1];
873
874 GuiConsoleSetTextColors(hDC,
875 LastAttribute,
876 Buff,
877 GuiData->ScreenText,
878 GuiData->ScreenBackground);
879
880 EnterCriticalSection(&Buff->Header.Lock);
881
882 OldFont = SelectObject(hDC,
883 GuiData->Font);
884
885 for (Line = TopLine; Line <= BottomLine; Line++)
886 {
887 if (Line + Buff->ShowY < Buff->MaxY)
888 {
889 From = Buff->Buffer + ((Line + Buff->ShowY) * Buff->MaxX + LeftChar) * 2;
890 }
891 else
892 {
893 From = Buff->Buffer +
894 ((Line - (Buff->MaxY - Buff->ShowY)) * Buff->MaxX + LeftChar) * 2;
895 }
896 Start = LeftChar;
897 To = GuiData->LineBuffer;
898
899 for (Char = LeftChar; Char <= RightChar; Char++)
900 {
901 if (*(From + 1) != LastAttribute)
902 {
903 TextOutW(hDC,
904 Start * GuiData->CharWidth,
905 Line * GuiData->CharHeight,
906 GuiData->LineBuffer,
907 Char - Start);
908 Start = Char;
909 To = GuiData->LineBuffer;
910 Attribute = *(From + 1);
911 if (Attribute != LastAttribute)
912 {
913 GuiConsoleSetTextColors(hDC,
914 Attribute,
915 Buff,
916 GuiData->ScreenText,
917 GuiData->ScreenBackground);
918 LastAttribute = Attribute;
919 }
920 }
921
922 MultiByteToWideChar(Console->OutputCodePage,
923 0,
924 (PCHAR)From,
925 1,
926 To,
927 1);
928 To++;
929 From += 2;
930 }
931
932 TextOutW(hDC,
933 Start * GuiData->CharWidth,
934 Line * GuiData->CharHeight,
935 GuiData->LineBuffer,
936 RightChar - Start + 1);
937 }
938
939 if (Buff->CursorInfo.bVisible && GuiData->CursorBlinkOn &&
940 !GuiData->ForceCursorOff)
941 {
942 GuiConsoleGetLogicalCursorPos(Buff,
943 &CursorX,
944 &CursorY);
945 if (LeftChar <= CursorX && CursorX <= RightChar &&
946 TopLine <= CursorY && CursorY <= BottomLine)
947 {
948 CursorHeight = (GuiData->CharHeight * Buff->CursorInfo.dwSize) / 100;
949 if (CursorHeight < 1)
950 {
951 CursorHeight = 1;
952 }
953 From = Buff->Buffer + (Buff->CurrentY * Buff->MaxX + Buff->CurrentX) * 2 + 1;
954
955 if (*From != DEFAULT_ATTRIB)
956 {
957 CursorBrush = CreateSolidBrush(GuiConsoleRGBFromAttribute(*From));
958 }
959 else
960 {
961 CursorBrush = CreateSolidBrush(GuiData->ScreenText);
962 }
963
964 OldBrush = SelectObject(hDC,
965 CursorBrush);
966 PatBlt(hDC,
967 CursorX * GuiData->CharWidth,
968 CursorY * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
969 GuiData->CharWidth,
970 CursorHeight,
971 PATCOPY);
972 SelectObject(hDC,
973 OldBrush);
974 DeleteObject(CursorBrush);
975 }
976 }
977
978 LeaveCriticalSection(&Buff->Header.Lock);
979
980 SelectObject(hDC,
981 OldFont);
982 }
983
984 static VOID FASTCALL
985 GuiConsoleHandlePaint(HWND hWnd, HDC hDCPaint)
986 {
987 HDC hDC;
988 PAINTSTRUCT ps;
989 PCSRSS_CONSOLE Console;
990 PGUI_CONSOLE_DATA GuiData;
991
992 hDC = BeginPaint(hWnd, &ps);
993 if (hDC != NULL &&
994 ps.rcPaint.left < ps.rcPaint.right &&
995 ps.rcPaint.top < ps.rcPaint.bottom)
996 {
997 GuiConsoleGetDataPointers(hWnd,
998 &Console,
999 &GuiData);
1000 if (Console != NULL && GuiData != NULL &&
1001 Console->ActiveBuffer != NULL)
1002 {
1003 if (Console->ActiveBuffer->Buffer != NULL)
1004 {
1005 EnterCriticalSection(&GuiData->Lock);
1006
1007 GuiConsolePaint(Console,
1008 GuiData,
1009 hDC,
1010 &ps.rcPaint);
1011
1012 if (GuiData->Selection.left != -1)
1013 {
1014 RECT rc = GuiData->Selection;
1015
1016 rc.left *= GuiData->CharWidth;
1017 rc.top *= GuiData->CharHeight;
1018 rc.right *= GuiData->CharWidth;
1019 rc.bottom *= GuiData->CharHeight;
1020
1021 /* invert the selection */
1022 if (IntersectRect(&rc,
1023 &ps.rcPaint,
1024 &rc))
1025 {
1026 PatBlt(hDC,
1027 rc.left,
1028 rc.top,
1029 rc.right - rc.left,
1030 rc.bottom - rc.top,
1031 DSTINVERT);
1032 }
1033 }
1034
1035 LeaveCriticalSection(&GuiData->Lock);
1036 }
1037 }
1038
1039 EndPaint(hWnd, &ps);
1040 }
1041 }
1042
1043 static VOID FASTCALL
1044 GuiConsoleHandleKey(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
1045 {
1046 PCSRSS_CONSOLE Console;
1047 PGUI_CONSOLE_DATA GuiData;
1048 MSG Message;
1049
1050 GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
1051 Message.hwnd = hWnd;
1052 Message.message = msg;
1053 Message.wParam = wParam;
1054 Message.lParam = lParam;
1055
1056 if(msg == WM_CHAR || msg == WM_SYSKEYDOWN)
1057 {
1058 /* clear the selection */
1059 GuiConsoleUpdateSelection(hWnd, NULL, GuiData);
1060 }
1061
1062 ConioProcessKey(&Message, Console, FALSE);
1063 }
1064
1065 static VOID FASTCALL
1066 GuiIntDrawRegion(PGUI_CONSOLE_DATA GuiData, HWND Wnd, RECT *Region)
1067 {
1068 RECT RegionRect;
1069
1070 RegionRect.left = Region->left * GuiData->CharWidth;
1071 RegionRect.top = Region->top * GuiData->CharHeight;
1072 RegionRect.right = (Region->right + 1) * GuiData->CharWidth;
1073 RegionRect.bottom = (Region->bottom + 1) * GuiData->CharHeight;
1074
1075 InvalidateRect(Wnd, &RegionRect, FALSE);
1076 }
1077
1078 static VOID STDCALL
1079 GuiDrawRegion(PCSRSS_CONSOLE Console, RECT *Region)
1080 {
1081 PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA) Console->PrivateData;
1082
1083 if (NULL != Console->hWindow && NULL != GuiData)
1084 {
1085 GuiIntDrawRegion(GuiData, Console->hWindow, Region);
1086 }
1087 }
1088
1089 static VOID FASTCALL
1090 GuiInvalidateCell(PGUI_CONSOLE_DATA GuiData, HWND Wnd, UINT x, UINT y)
1091 {
1092 RECT CellRect;
1093
1094 CellRect.left = x;
1095 CellRect.top = y;
1096 CellRect.right = x;
1097 CellRect.bottom = y;
1098
1099 GuiIntDrawRegion(GuiData, Wnd, &CellRect);
1100 }
1101
1102 static VOID STDCALL
1103 GuiWriteStream(PCSRSS_CONSOLE Console, RECT *Region, LONG CursorStartX, LONG CursorStartY,
1104 UINT ScrolledLines, CHAR *Buffer, UINT Length)
1105 {
1106 PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA) Console->PrivateData;
1107 PCSRSS_SCREEN_BUFFER Buff = Console->ActiveBuffer;
1108 LONG CursorEndX, CursorEndY;
1109 RECT ScrollRect;
1110
1111 if (NULL == Console->hWindow || NULL == GuiData)
1112 {
1113 return;
1114 }
1115
1116 if (0 != ScrolledLines)
1117 {
1118 ScrollRect.left = 0;
1119 ScrollRect.top = 0;
1120 ScrollRect.right = Console->Size.X * GuiData->CharWidth;
1121 ScrollRect.bottom = Region->top * GuiData->CharHeight;
1122
1123 if (GuiData->Selection.left != -1)
1124 {
1125 /* scroll the selection */
1126 if (GuiData->Selection.top > ScrolledLines)
1127 {
1128 GuiData->Selection.top -= ScrolledLines;
1129 GuiData->Selection.bottom -= ScrolledLines;
1130 }
1131 else if (GuiData->Selection.bottom < ScrolledLines)
1132 {
1133 GuiData->Selection.left = -1;
1134 }
1135 else
1136 {
1137 GuiData->Selection.top = 0;
1138 GuiData->Selection.bottom -= ScrolledLines;
1139 }
1140 }
1141
1142 ScrollWindowEx(Console->hWindow,
1143 0,
1144 -(ScrolledLines * GuiData->CharHeight),
1145 &ScrollRect,
1146 NULL,
1147 NULL,
1148 NULL,
1149 SW_INVALIDATE);
1150 }
1151
1152 GuiIntDrawRegion(GuiData, Console->hWindow, Region);
1153
1154 if (CursorStartX < Region->left || Region->right < CursorStartX
1155 || CursorStartY < Region->top || Region->bottom < CursorStartY)
1156 {
1157 GuiInvalidateCell(GuiData, Console->hWindow, CursorStartX, CursorStartY);
1158 }
1159
1160 ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY,
1161 &CursorEndX, &CursorEndY);
1162 if ((CursorEndX < Region->left || Region->right < CursorEndX
1163 || CursorEndY < Region->top || Region->bottom < CursorEndY)
1164 && (CursorEndX != CursorStartX || CursorEndY != CursorStartY))
1165 {
1166 GuiInvalidateCell(GuiData, Console->hWindow, CursorEndX, CursorEndY);
1167 }
1168 }
1169
1170 static BOOL STDCALL
1171 GuiSetCursorInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff)
1172 {
1173 RECT UpdateRect;
1174
1175 if (Console->ActiveBuffer == Buff)
1176 {
1177 ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY,
1178 &UpdateRect.left, &UpdateRect.top);
1179 UpdateRect.right = UpdateRect.left;
1180 UpdateRect.bottom = UpdateRect.top;
1181 ConioDrawRegion(Console, &UpdateRect);
1182 }
1183
1184 return TRUE;
1185 }
1186
1187 static BOOL STDCALL
1188 GuiSetScreenInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff, UINT OldCursorX, UINT OldCursorY)
1189 {
1190 RECT UpdateRect;
1191
1192 if (Console->ActiveBuffer == Buff)
1193 {
1194 /* Redraw char at old position (removes cursor) */
1195 UpdateRect.left = OldCursorX;
1196 UpdateRect.top = OldCursorY;
1197 UpdateRect.right = OldCursorX;
1198 UpdateRect.bottom = OldCursorY;
1199 ConioDrawRegion(Console, &UpdateRect);
1200 /* Redraw char at new position (shows cursor) */
1201 ConioPhysicalToLogical(Buff, Buff->CurrentX, Buff->CurrentY,
1202 &(UpdateRect.left), &(UpdateRect.top));
1203 UpdateRect.right = UpdateRect.left;
1204 UpdateRect.bottom = UpdateRect.top;
1205 ConioDrawRegion(Console, &UpdateRect);
1206 }
1207
1208 return TRUE;
1209 }
1210
1211 static VOID FASTCALL
1212 GuiConsoleHandleTimer(HWND hWnd)
1213 {
1214 PCSRSS_CONSOLE Console;
1215 PGUI_CONSOLE_DATA GuiData;
1216 RECT CursorRect;
1217 ULONG CursorX, CursorY;
1218
1219 GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
1220 GuiData->CursorBlinkOn = ! GuiData->CursorBlinkOn;
1221
1222 GuiConsoleGetLogicalCursorPos(Console->ActiveBuffer, &CursorX, &CursorY);
1223 CursorRect.left = CursorX;
1224 CursorRect.top = CursorY;
1225 CursorRect.right = CursorX;
1226 CursorRect.bottom = CursorY;
1227 GuiDrawRegion(Console, &CursorRect);
1228 }
1229
1230 static VOID FASTCALL
1231 GuiConsoleHandleClose(HWND hWnd)
1232 {
1233 PCSRSS_CONSOLE Console;
1234 PGUI_CONSOLE_DATA GuiData;
1235 PLIST_ENTRY current_entry;
1236 PCSRSS_PROCESS_DATA current;
1237
1238 GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
1239
1240 EnterCriticalSection(&Console->Header.Lock);
1241
1242 current_entry = Console->ProcessList.Flink;
1243 while (current_entry != &Console->ProcessList)
1244 {
1245 current = CONTAINING_RECORD(current_entry, CSRSS_PROCESS_DATA, ProcessEntry);
1246 current_entry = current_entry->Flink;
1247
1248 ConioConsoleCtrlEvent(CTRL_CLOSE_EVENT, current);
1249 }
1250
1251 LeaveCriticalSection(&Console->Header.Lock);
1252 }
1253
1254 static VOID FASTCALL
1255 GuiConsoleHandleNcDestroy(HWND hWnd)
1256 {
1257 PCSRSS_CONSOLE Console;
1258 PGUI_CONSOLE_DATA GuiData;
1259
1260
1261 GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
1262 KillTimer(hWnd, 1);
1263 Console->PrivateData = NULL;
1264 DeleteCriticalSection(&GuiData->Lock);
1265 GetSystemMenu(hWnd, TRUE);
1266 if (GuiData->ConsoleLibrary)
1267 FreeLibrary(GuiData->ConsoleLibrary);
1268
1269 HeapFree(Win32CsrApiHeap, 0, GuiData);
1270 }
1271
1272 static VOID FASTCALL
1273 GuiConsoleLeftMouseDown(HWND hWnd, LPARAM lParam)
1274 {
1275 PCSRSS_CONSOLE Console;
1276 PGUI_CONSOLE_DATA GuiData;
1277 POINTS pt;
1278 RECT rc;
1279
1280 GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
1281 if (Console == NULL || GuiData == NULL) return;
1282
1283 pt = MAKEPOINTS(lParam);
1284
1285 rc.left = pt.x / GuiData->CharWidth;
1286 rc.top = pt.y / GuiData->CharHeight;
1287 rc.right = rc.left + 1;
1288 rc.bottom = rc.top + 1;
1289
1290 GuiData->SelectionStart.x = rc.left;
1291 GuiData->SelectionStart.y = rc.top;
1292
1293 SetCapture(hWnd);
1294
1295 GuiData->MouseDown = TRUE;
1296
1297 GuiConsoleUpdateSelection(hWnd, &rc, GuiData);
1298 }
1299
1300 static VOID FASTCALL
1301 GuiConsoleLeftMouseUp(HWND hWnd, LPARAM lParam)
1302 {
1303 PCSRSS_CONSOLE Console;
1304 PGUI_CONSOLE_DATA GuiData;
1305 RECT rc;
1306 POINTS pt;
1307
1308 GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
1309 if (Console == NULL || GuiData == NULL) return;
1310 if (GuiData->Selection.left == -1 || !GuiData->MouseDown) return;
1311
1312 pt = MAKEPOINTS(lParam);
1313
1314 rc.left = GuiData->SelectionStart.x;
1315 rc.top = GuiData->SelectionStart.y;
1316 rc.right = (pt.x >= 0 ? (pt.x / GuiData->CharWidth) + 1 : 0);
1317 rc.bottom = (pt.y >= 0 ? (pt.y / GuiData->CharHeight) + 1 : 0);
1318
1319 /* exchange left/top with right/bottom if required */
1320 if(rc.left >= rc.right)
1321 {
1322 LONG tmp;
1323 tmp = rc.left;
1324 rc.left = max(rc.right - 1, 0);
1325 rc.right = tmp + 1;
1326 }
1327 if(rc.top >= rc.bottom)
1328 {
1329 LONG tmp;
1330 tmp = rc.top;
1331 rc.top = max(rc.bottom - 1, 0);
1332 rc.bottom = tmp + 1;
1333 }
1334
1335 GuiData->MouseDown = FALSE;
1336
1337 GuiConsoleUpdateSelection(hWnd, &rc, GuiData);
1338
1339 ReleaseCapture();
1340 }
1341
1342 static VOID FASTCALL
1343 GuiConsoleMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam)
1344 {
1345 PCSRSS_CONSOLE Console;
1346 PGUI_CONSOLE_DATA GuiData;
1347 RECT rc;
1348 POINTS pt;
1349
1350 if (!(wParam & MK_LBUTTON)) return;
1351
1352 GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
1353 if (Console == NULL || GuiData == NULL || !GuiData->MouseDown) return;
1354
1355 pt = MAKEPOINTS(lParam);
1356
1357 rc.left = GuiData->SelectionStart.x;
1358 rc.top = GuiData->SelectionStart.y;
1359 rc.right = (pt.x >= 0 ? (pt.x / GuiData->CharWidth) + 1 : 0);
1360 if (Console->Size.X < rc.right)
1361 {
1362 rc.right = Console->Size.X;
1363 }
1364 rc.bottom = (pt.y >= 0 ? (pt.y / GuiData->CharHeight) + 1 : 0);
1365 if (Console->Size.Y < rc.bottom)
1366 {
1367 rc.bottom = Console->Size.Y;
1368 }
1369
1370 /* exchange left/top with right/bottom if required */
1371 if(rc.left >= rc.right)
1372 {
1373 LONG tmp;
1374 tmp = rc.left;
1375 rc.left = max(rc.right - 1, 0);
1376 rc.right = tmp + 1;
1377 }
1378 if(rc.top >= rc.bottom)
1379 {
1380 LONG tmp;
1381 tmp = rc.top;
1382 rc.top = max(rc.bottom - 1, 0);
1383 rc.bottom = tmp + 1;
1384 }
1385
1386 GuiConsoleUpdateSelection(hWnd, &rc, GuiData);
1387 }
1388
1389 static VOID FASTCALL
1390 GuiConsoleRightMouseDown(HWND hWnd)
1391 {
1392 PCSRSS_CONSOLE Console;
1393 PGUI_CONSOLE_DATA GuiData;
1394
1395 GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
1396 if (Console == NULL || GuiData == NULL) return;
1397
1398 if (GuiData->Selection.left == -1)
1399 {
1400 /* FIXME - paste text from clipboard */
1401 }
1402 else
1403 {
1404 /* FIXME - copy selection to clipboard */
1405
1406 GuiConsoleUpdateSelection(hWnd, NULL, GuiData);
1407 }
1408
1409 }
1410
1411
1412 static VOID
1413 GuiConsoleShowConsoleProperties(HWND hWnd, BOOL Defaults, PGUI_CONSOLE_DATA GuiData)
1414 {
1415 PCSRSS_CONSOLE Console;
1416 APPLET_PROC CPLFunc;
1417 TCHAR szBuffer[MAX_PATH];
1418 ConsoleInfo SharedInfo;
1419
1420 DPRINT("GuiConsoleShowConsoleProperties entered\n");
1421
1422 GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
1423
1424 if (GuiData == NULL)
1425 {
1426 DPRINT("GuiConsoleGetDataPointers failed\n");
1427 return;
1428 }
1429
1430 if (GuiData->ConsoleLibrary == NULL)
1431 {
1432 GetWindowsDirectory(szBuffer,MAX_PATH);
1433 _tcscat(szBuffer, _T("\\system32\\console.dll"));
1434 GuiData->ConsoleLibrary = LoadLibrary(szBuffer);
1435
1436 if (GuiData->ConsoleLibrary == NULL)
1437 {
1438 DPRINT1("failed to load console.dll");
1439 return;
1440 }
1441 }
1442
1443 CPLFunc = (APPLET_PROC) GetProcAddress(GuiData->ConsoleLibrary, _T("CPlApplet"));
1444 if (!CPLFunc)
1445 {
1446 DPRINT("Error: Console.dll misses CPlApplet export\n");
1447 return;
1448 }
1449
1450 /* setup struct */
1451 SharedInfo.InsertMode = GuiData->InsertMode;
1452 SharedInfo.HistoryBufferSize = GuiData->HistoryBufferSize;
1453 SharedInfo.NumberOfHistoryBuffers = GuiData->NumberOfHistoryBuffers;
1454 SharedInfo.ScreenText = GuiData->ScreenText;
1455 SharedInfo.ScreenBackground = GuiData->ScreenBackground;
1456 SharedInfo.PopupText = GuiData->PopupText;
1457 SharedInfo.PopupBackground = GuiData->PopupBackground;
1458 SharedInfo.WindowSize = (DWORD)MAKELONG(Console->Size.X, Console->Size.Y);
1459 SharedInfo.WindowPosition = GuiData->WindowPosition;
1460 SharedInfo.ScreenBuffer = GuiData->ScreenBufferSize;
1461 SharedInfo.UseRasterFonts = GuiData->UseRasterFonts;
1462 SharedInfo.FontSize = (DWORD)GuiData->FontSize;
1463 SharedInfo.FontWeight = GuiData->FontWeight;
1464 SharedInfo.CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
1465 SharedInfo.HistoryNoDup = GuiData->HistoryNoDup;
1466 SharedInfo.FullScreen = GuiData->FullScreen;
1467 SharedInfo.QuickEdit = GuiData->QuickEdit;
1468 memcpy(&SharedInfo.Colors[0], GuiData->Colors, sizeof(s_Colors));
1469
1470 if (!CPLFunc(hWnd, CPL_INIT, 0, 0))
1471 {
1472 DPRINT("Error: failed to initialize console.dll\n");
1473 return;
1474 }
1475
1476 if (CPLFunc(hWnd, CPL_GETCOUNT, 0, 0) != 1)
1477 {
1478 DPRINT("Error: console.dll returned unexpected CPL count\n");
1479 return;
1480 }
1481
1482 CPLFunc(hWnd, CPL_DBLCLK, (LPARAM)&SharedInfo, Defaults);
1483 }
1484 static BOOL FASTCALL
1485 GuiConsoleHandleSysMenuCommand(HWND hWnd, WPARAM wParam, PGUI_CONSOLE_DATA GuiData)
1486 {
1487 BOOL Ret = TRUE;
1488
1489 switch(wParam)
1490 {
1491 case ID_SYSTEM_EDIT_MARK:
1492 case ID_SYSTEM_EDIT_COPY:
1493 case ID_SYSTEM_EDIT_PASTE:
1494 case ID_SYSTEM_EDIT_SELECTALL:
1495 case ID_SYSTEM_EDIT_SCROLL:
1496 case ID_SYSTEM_EDIT_FIND:
1497 break;
1498
1499 case ID_SYSTEM_DEFAULTS:
1500 GuiConsoleShowConsoleProperties(hWnd, TRUE, GuiData);
1501 break;
1502
1503 case ID_SYSTEM_PROPERTIES:
1504 GuiConsoleShowConsoleProperties(hWnd, FALSE, GuiData);
1505 break;
1506
1507 default:
1508 Ret = FALSE;
1509 break;
1510 }
1511
1512 return Ret;
1513 }
1514
1515 static VOID FASTCALL
1516 GuiConsoleResize(HWND hWnd, WPARAM wParam, LPARAM lParam)
1517 {
1518 PCSRSS_CONSOLE Console;
1519 PGUI_CONSOLE_DATA GuiData;
1520
1521 GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
1522 if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED || wParam == SIZE_MINIMIZED)
1523 {
1524 DPRINT1("GuiConsoleResize X %d Y %d\n", LOWORD(lParam), HIWORD(lParam));
1525 }
1526 }
1527
1528 VOID FASTCALL
1529 GuiConsoleCreateScrollBar(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, HWND NewWindow)
1530 {
1531 HMENU hMenu;
1532 HWND hVScrollBar;
1533 HWND hHScrollBar;
1534 SCROLLINFO sInfo;
1535
1536 hMenu = CreatePopupMenu();
1537 if (hMenu == NULL)
1538 {
1539 DPRINT("CreatePopupMenu failed\n");
1540 return;
1541 }
1542
1543 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLHERE);
1544 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1545 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLTOP);
1546 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLBOTTOM);
1547 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1548 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_UP);
1549 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_DOWN);
1550 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1551 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLUP);
1552 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLDOWN);
1553
1554 hVScrollBar = CreateWindowExW(0L,
1555 L"ScrollBar",
1556 (LPWSTR)NULL,
1557 WS_CHILD | WS_VSCROLL,
1558 0,
1559 0,
1560 200,
1561 50,
1562 NewWindow,
1563 NULL, //hMenu,
1564 GetModuleHandleW(NULL),
1565 (LPVOID)GuiData);
1566
1567 if (hVScrollBar)
1568 {
1569
1570 /* set scrollbar sizes */
1571 sInfo.cbSize = sizeof(SCROLLINFO);
1572 sInfo.fMask = SIF_RANGE | SIF_POS;
1573 sInfo.nMin = 0;
1574 sInfo.nMax = Console->ActiveBuffer->MaxY;
1575 sInfo.nPos = 0;
1576 SetScrollInfo(hVScrollBar, SB_CTL, &sInfo, TRUE);
1577 ShowScrollBar(NewWindow, SB_CTL, TRUE);
1578 GuiData->hVScrollBar = hVScrollBar;
1579 }
1580
1581 if (Console->ActiveBuffer->MaxX > Console->Size.X)
1582 {
1583 hHScrollBar = CreateWindowExW(0L,
1584 L"ScrollBar",
1585 (LPWSTR)NULL,
1586 WS_CHILD | WS_HSCROLL,
1587 0,
1588 0,
1589 200,
1590 CW_USEDEFAULT,
1591 NewWindow,
1592 hMenu,
1593 GetModuleHandleW(NULL),
1594 (LPVOID)GuiData);
1595 if (hHScrollBar)
1596 {
1597 sInfo.nMax = Console->ActiveBuffer->MaxX;
1598 SetScrollInfo(hHScrollBar, SB_CTL, &sInfo, TRUE);
1599 GuiData->hHScrollBar = hHScrollBar;
1600 }
1601 }
1602 }
1603
1604 static VOID FASTCALL
1605 GuiApplyUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PConsoleInfo pConInfo)
1606 {
1607 DWORD windx, windy;
1608 RECT rect;
1609
1610 /* apply text / background color */
1611 GuiData->ScreenText = pConInfo->ScreenText;
1612 GuiData->ScreenBackground = pConInfo->ScreenBackground;
1613
1614 /* apply cursor size */
1615 Console->ActiveBuffer->CursorInfo.dwSize = max(min(pConInfo->CursorSize, 1), 100);
1616
1617 windx = LOWORD(pConInfo->ScreenBuffer);
1618 windy = HIWORD(pConInfo->ScreenBuffer);
1619
1620 if (windx != Console->ActiveBuffer->MaxX || windy != Console->ActiveBuffer->MaxY)
1621 {
1622 //
1623 // TODO
1624 // resize screen buffer
1625
1626
1627 // Console->ActiveBuffer->MaxX = windx;
1628 // Console->ActiveBuffer->MaxY = windy;
1629 }
1630
1631 windx = LOWORD(pConInfo->WindowSize);
1632 windy = HIWORD(pConInfo->WindowSize);
1633
1634 if (windx != Console->Size.X || windy != Console->Size.Y)
1635 {
1636 /* resize window */
1637 Console->Size.X = windx;
1638 Console->Size.Y = windy;
1639
1640 GetWindowRect(pConInfo->hConsoleWindow, &rect);
1641
1642 rect.right = rect.left + Console->Size.X * GuiData->CharWidth + 2 * GetSystemMetrics(SM_CXFIXEDFRAME);
1643 rect.bottom = rect.top + Console->Size.Y * GuiData->CharHeight + 2 * GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CYCAPTION);
1644
1645 MoveWindow(pConInfo->hConsoleWindow, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, FALSE);
1646
1647 if (Console->Size.X < Console->ActiveBuffer->MaxX)
1648 {
1649 /* show scrollbar when window becomes smaller than active screen buffer */
1650 //ShowScrollBar(GuiData->hHScrollBar, SB_CTL, TRUE);
1651 }
1652 else
1653 {
1654 /* hide scrollbar */
1655 //ShowScrollBar(GuiData->hHScrollBar, SB_CTL, FALSE);
1656 }
1657 }
1658 /* repaint window */
1659 InvalidateRect(pConInfo->hConsoleWindow, NULL, TRUE);
1660 }
1661
1662 static LRESULT CALLBACK
1663 GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
1664 {
1665 LRESULT Result = 0;
1666 PGUI_CONSOLE_DATA GuiData = NULL;
1667 PCSRSS_CONSOLE Console = NULL;
1668
1669 GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
1670
1671 switch(msg)
1672 {
1673 case WM_NCCREATE:
1674 Result = (LRESULT) GuiConsoleHandleNcCreate(hWnd, (CREATESTRUCTW *) lParam);
1675 break;
1676 case WM_PAINT:
1677 GuiConsoleHandlePaint(hWnd, (HDC)wParam);
1678 break;
1679 case WM_KEYDOWN:
1680 case WM_KEYUP:
1681 case WM_SYSKEYDOWN:
1682 case WM_SYSKEYUP:
1683 case WM_CHAR:
1684 GuiConsoleHandleKey(hWnd, msg, wParam, lParam);
1685 break;
1686 case WM_TIMER:
1687 GuiConsoleHandleTimer(hWnd);
1688 break;
1689 case WM_CLOSE:
1690 GuiConsoleHandleClose(hWnd);
1691 break;
1692 case WM_NCDESTROY:
1693 GuiConsoleHandleNcDestroy(hWnd);
1694 break;
1695 case WM_LBUTTONDOWN:
1696 GuiConsoleLeftMouseDown(hWnd, lParam);
1697 break;
1698 case WM_LBUTTONUP:
1699 GuiConsoleLeftMouseUp(hWnd, lParam);
1700 break;
1701 case WM_RBUTTONDOWN:
1702 GuiConsoleRightMouseDown(hWnd);
1703 break;
1704 case WM_MOUSEMOVE:
1705 GuiConsoleMouseMove(hWnd, wParam, lParam);
1706 break;
1707 case WM_SYSCOMMAND:
1708 if (!GuiConsoleHandleSysMenuCommand(hWnd, wParam, GuiData))
1709 Result = DefWindowProcW(hWnd, msg, wParam, lParam);
1710 break;
1711 case WM_SIZE:
1712 GuiConsoleResize(hWnd, wParam, lParam);
1713 break;
1714 case PM_APPLY_CONSOLE_INFO:
1715 GuiApplyUserSettings(Console, GuiData, (PConsoleInfo)wParam);
1716 if (lParam)
1717 {
1718 GuiConsoleWriteUserSettings(Console, GuiData);
1719 }
1720 break;
1721 default:
1722 Result = DefWindowProcW(hWnd, msg, wParam, lParam);
1723 break;
1724 }
1725
1726 return Result;
1727 }
1728
1729 static LRESULT CALLBACK
1730 GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
1731 {
1732 HWND NewWindow;
1733 LONG WindowCount;
1734 MSG Msg;
1735 PWCHAR Buffer, Title;
1736 PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) lParam;
1737
1738
1739
1740 switch(msg)
1741 {
1742 case WM_CREATE:
1743 SetWindowLongW(hWnd, GWL_USERDATA, 0);
1744 return 0;
1745 case PM_CREATE_CONSOLE:
1746 Buffer = HeapAlloc(Win32CsrApiHeap, 0,
1747 Console->Title.Length + sizeof(WCHAR));
1748 if (NULL != Buffer)
1749 {
1750 memcpy(Buffer, Console->Title.Buffer, Console->Title.Length);
1751 Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0';
1752 Title = Buffer;
1753 }
1754 else
1755 {
1756 Title = L"";
1757 }
1758 NewWindow = CreateWindowW(L"ConsoleWindowClass",
1759 Title,
1760 WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, //WS_OVERLAPPEDWINDOW
1761 CW_USEDEFAULT,
1762 CW_USEDEFAULT,
1763 CW_USEDEFAULT,
1764 CW_USEDEFAULT,
1765 NULL,
1766 NULL,
1767 (HINSTANCE) GetModuleHandleW(NULL),
1768 (PVOID) Console);
1769 if (NULL != Buffer)
1770 {
1771 HeapFree(Win32CsrApiHeap, 0, Buffer);
1772 }
1773 if (NULL != NewWindow)
1774 {
1775 // scrollbar support
1776 //GuiConsoleCreateScrollBar(Console, (PGUI_CONSOLE_DATA)Console->PrivateData, NewWindow);
1777 SetWindowLongW(hWnd, GWL_USERDATA, GetWindowLongW(hWnd, GWL_USERDATA) + 1);
1778 ShowWindow(NewWindow, SW_SHOW);
1779 }
1780 return (LRESULT) NewWindow;
1781 case PM_DESTROY_CONSOLE:
1782 /* Window creation is done using a PostMessage(), so it's possible that the
1783 * window that we want to destroy doesn't exist yet. So first empty the message
1784 * queue */
1785 while(PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE))
1786 {
1787 TranslateMessage(&Msg);
1788 DispatchMessageW(&Msg);
1789 }
1790 DestroyWindow(Console->hWindow);
1791 Console->hWindow = NULL;
1792 WindowCount = GetWindowLongW(hWnd, GWL_USERDATA);
1793 WindowCount--;
1794 SetWindowLongW(hWnd, GWL_USERDATA, WindowCount);
1795 if (0 == WindowCount)
1796 {
1797 NotifyWnd = NULL;
1798 DestroyWindow(hWnd);
1799 PrivateCsrssManualGuiCheck(-1);
1800 PostQuitMessage(0);
1801 }
1802 return 0;
1803 default:
1804 return DefWindowProcW(hWnd, msg, wParam, lParam);
1805 }
1806 }
1807
1808 static DWORD STDCALL
1809 GuiConsoleGuiThread(PVOID Data)
1810 {
1811 MSG msg;
1812 PHANDLE GraphicsStartupEvent = (PHANDLE) Data;
1813
1814 NotifyWnd = CreateWindowW(L"Win32CsrCreateNotify",
1815 L"",
1816 WS_OVERLAPPEDWINDOW,
1817 CW_USEDEFAULT,
1818 CW_USEDEFAULT,
1819 CW_USEDEFAULT,
1820 CW_USEDEFAULT,
1821 NULL,
1822 NULL,
1823 (HINSTANCE) GetModuleHandleW(NULL),
1824 NULL);
1825 if (NULL == NotifyWnd)
1826 {
1827 PrivateCsrssManualGuiCheck(-1);
1828 SetEvent(*GraphicsStartupEvent);
1829 return 1;
1830 }
1831
1832 SetEvent(*GraphicsStartupEvent);
1833
1834 while(GetMessageW(&msg, NULL, 0, 0))
1835 {
1836 TranslateMessage(&msg);
1837 DispatchMessageW(&msg);
1838 }
1839
1840 return 1;
1841 }
1842
1843 static BOOL FASTCALL
1844 GuiInit(VOID)
1845 {
1846 WNDCLASSEXW wc;
1847
1848 if (NULL == NotifyWnd)
1849 {
1850 PrivateCsrssManualGuiCheck(+1);
1851 }
1852
1853 wc.cbSize = sizeof(WNDCLASSEXW);
1854 wc.lpszClassName = L"Win32CsrCreateNotify";
1855 wc.lpfnWndProc = GuiConsoleNotifyWndProc;
1856 wc.style = 0;
1857 wc.hInstance = (HINSTANCE) GetModuleHandleW(NULL);
1858 wc.hIcon = NULL;
1859 wc.hCursor = NULL;
1860 wc.hbrBackground = NULL;
1861 wc.lpszMenuName = NULL;
1862 wc.cbClsExtra = 0;
1863 wc.cbWndExtra = 0;
1864 wc.hIconSm = NULL;
1865 if (RegisterClassExW(&wc) == 0)
1866 {
1867 DPRINT1("Failed to register notify wndproc\n");
1868 return FALSE;
1869 }
1870
1871 wc.cbSize = sizeof(WNDCLASSEXW);
1872 wc.lpszClassName = L"ConsoleWindowClass";
1873 wc.lpfnWndProc = GuiConsoleWndProc;
1874 wc.style = 0;
1875 wc.hInstance = (HINSTANCE) GetModuleHandleW(NULL);
1876 wc.hIcon = LoadIconW(Win32CsrDllHandle, MAKEINTRESOURCEW(1));
1877 wc.hCursor = LoadCursorW(NULL, (LPCWSTR) IDC_ARROW);
1878 wc.hbrBackground = NULL;
1879 wc.lpszMenuName = NULL;
1880 wc.cbClsExtra = 0;
1881 wc.cbWndExtra = 0;
1882 wc.hIconSm = LoadImageW(Win32CsrDllHandle, MAKEINTRESOURCEW(1), IMAGE_ICON,
1883 GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
1884 LR_SHARED);
1885 if (RegisterClassExW(&wc) == 0)
1886 {
1887 DPRINT1("Failed to register console wndproc\n");
1888 return FALSE;
1889 }
1890
1891 return TRUE;
1892 }
1893
1894 static VOID STDCALL
1895 GuiInitScreenBuffer(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buffer)
1896 {
1897 Buffer->DefaultAttrib = DEFAULT_ATTRIB;
1898 }
1899
1900 static BOOL STDCALL
1901 GuiChangeTitle(PCSRSS_CONSOLE Console)
1902 {
1903 PWCHAR Buffer, Title;
1904
1905 Buffer = HeapAlloc(Win32CsrApiHeap, 0,
1906 Console->Title.Length + sizeof(WCHAR));
1907 if (NULL != Buffer)
1908 {
1909 memcpy(Buffer, Console->Title.Buffer, Console->Title.Length);
1910 Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0';
1911 Title = Buffer;
1912 }
1913 else
1914 {
1915 Title = L"";
1916 }
1917 SendMessageW(Console->hWindow, WM_SETTEXT, 0, (LPARAM) Title);
1918 if (NULL != Buffer)
1919 {
1920 HeapFree(Win32CsrApiHeap, 0, Buffer);
1921 }
1922
1923 return TRUE;
1924 }
1925
1926 static BOOL STDCALL
1927 GuiChangeIcon(PCSRSS_CONSOLE Console)
1928 {
1929 SendMessageW(Console->hWindow, WM_SETICON, ICON_BIG, (LPARAM)Console->hWindowIcon);
1930 SendMessageW(Console->hWindow, WM_SETICON, ICON_SMALL, (LPARAM)Console->hWindowIcon);
1931
1932 return TRUE;
1933 }
1934
1935 static VOID STDCALL
1936 GuiCleanupConsole(PCSRSS_CONSOLE Console)
1937 {
1938 SendMessageW(NotifyWnd, PM_DESTROY_CONSOLE, 0, (LPARAM) Console);
1939 }
1940
1941 static CSRSS_CONSOLE_VTBL GuiVtbl =
1942 {
1943 GuiInitScreenBuffer,
1944 GuiWriteStream,
1945 GuiDrawRegion,
1946 GuiSetCursorInfo,
1947 GuiSetScreenInfo,
1948 GuiChangeTitle,
1949 GuiCleanupConsole,
1950 GuiChangeIcon
1951 };
1952
1953 NTSTATUS FASTCALL
1954 GuiInitConsole(PCSRSS_CONSOLE Console)
1955 {
1956 HANDLE GraphicsStartupEvent;
1957 HANDLE ThreadHandle;
1958 PGUI_CONSOLE_DATA GuiData;
1959
1960 if (! ConsInitialized)
1961 {
1962 ConsInitialized = TRUE;
1963 if (! GuiInit())
1964 {
1965 ConsInitialized = FALSE;
1966 return STATUS_UNSUCCESSFUL;
1967 }
1968 }
1969
1970 Console->Vtbl = &GuiVtbl;
1971 if (NULL == NotifyWnd)
1972 {
1973 GraphicsStartupEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
1974 if (NULL == GraphicsStartupEvent)
1975 {
1976 return STATUS_UNSUCCESSFUL;
1977 }
1978
1979 ThreadHandle = CreateThread(NULL,
1980 0,
1981 GuiConsoleGuiThread,
1982 (PVOID) &GraphicsStartupEvent,
1983 0,
1984 NULL);
1985 if (NULL == ThreadHandle)
1986 {
1987 NtClose(GraphicsStartupEvent);
1988 DPRINT1("Win32Csr: Failed to create graphics console thread. Expect problems\n");
1989 return STATUS_UNSUCCESSFUL;
1990 }
1991 SetThreadPriority(ThreadHandle, THREAD_PRIORITY_HIGHEST);
1992 CloseHandle(ThreadHandle);
1993
1994 WaitForSingleObject(GraphicsStartupEvent, INFINITE);
1995 CloseHandle(GraphicsStartupEvent);
1996
1997 if (NULL == NotifyWnd)
1998 {
1999 DPRINT1("Win32Csr: Failed to create notification window.\n");
2000 return STATUS_UNSUCCESSFUL;
2001 }
2002 }
2003 GuiData = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY,
2004 sizeof(GUI_CONSOLE_DATA));
2005 if (!GuiData)
2006 {
2007 DPRINT1("Win32Csr: Failed to create GUI_CONSOLE_DATA\n");
2008 return STATUS_UNSUCCESSFUL;
2009 }
2010
2011 Console->PrivateData = (PVOID) GuiData;
2012 /*
2013 * we need to wait untill the GUI has been fully initialized
2014 * to retrieve custom settings i.e. WindowSize etc..
2015 * Ideally we could use SendNotifyMessage for this but its not
2016 * yet implemented.
2017 *
2018 */
2019 GuiData->hGuiInitEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
2020 /* create console */
2021 PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, 0, (LPARAM) Console);
2022
2023 /* wait untill initialization has finished */
2024 WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE);
2025 DPRINT1("received event Console %p GuiData %p X %d Y %d\n", Console, Console->PrivateData, Console->Size.X, Console->Size.Y);
2026 CloseHandle(GuiData->hGuiInitEvent);
2027 GuiData->hGuiInitEvent = NULL;
2028
2029 return STATUS_SUCCESS;
2030 }
2031
2032 /* EOF */