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