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