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
9 /* INCLUDES ******************************************************************/
15 /* Not defined in any header file */
16 extern VOID WINAPI
PrivateCsrssManualGuiCheck(LONG Check
);
18 /* GLOBALS *******************************************************************/
20 typedef struct GUI_CONSOLE_DATA_TAG
27 CRITICAL_SECTION Lock
;
28 HMODULE ConsoleLibrary
;
30 WCHAR FontName
[LF_FACESIZE
];
37 DWORD NumberOfHistoryBuffers
;
38 DWORD HistoryBufferSize
;
42 COLORREF ScreenBackground
;
43 COLORREF PopupBackground
;
46 WCHAR szProcessName
[MAX_PATH
];
49 } GUI_CONSOLE_DATA
, *PGUI_CONSOLE_DATA
;
54 #define PM_CREATE_CONSOLE (WM_APP + 1)
55 #define PM_DESTROY_CONSOLE (WM_APP + 2)
57 #define CURSOR_BLINK_TIME 500
58 #define DEFAULT_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
60 static BOOL ConsInitialized
= FALSE
;
61 static HWND NotifyWnd
;
63 typedef struct _GUICONSOLE_MENUITEM
66 const struct _GUICONSOLE_MENUITEM
*SubMenu
;
68 } GUICONSOLE_MENUITEM
, *PGUICONSOLE_MENUITEM
;
70 static const GUICONSOLE_MENUITEM GuiConsoleEditMenuItems
[] =
72 { IDS_MARK
, NULL
, ID_SYSTEM_EDIT_MARK
},
73 { IDS_COPY
, NULL
, ID_SYSTEM_EDIT_COPY
},
74 { IDS_PASTE
, NULL
, ID_SYSTEM_EDIT_PASTE
},
75 { IDS_SELECTALL
, NULL
, ID_SYSTEM_EDIT_SELECTALL
},
76 { IDS_SCROLL
, NULL
, ID_SYSTEM_EDIT_SCROLL
},
77 { IDS_FIND
, NULL
, ID_SYSTEM_EDIT_FIND
},
79 { 0, NULL
, 0 } /* End of list */
82 static const GUICONSOLE_MENUITEM GuiConsoleMainMenuItems
[] =
84 { (UINT
)-1, NULL
, 0 }, /* Separator */
85 { IDS_EDIT
, GuiConsoleEditMenuItems
, 0 },
86 { IDS_DEFAULTS
, NULL
, ID_SYSTEM_DEFAULTS
},
87 { IDS_PROPERTIES
, NULL
, ID_SYSTEM_PROPERTIES
},
89 { 0, NULL
, 0 } /* End of list */
92 static const COLORREF s_Colors
[] =
112 #define GuiConsoleRGBFromAttribute(GuiData, Attribute) ((GuiData)->Colors[(Attribute) & 0xF])
114 /* FUNCTIONS *****************************************************************/
117 GuiConsoleAppendMenuItems(HMENU hMenu
,
118 const GUICONSOLE_MENUITEM
*Items
)
121 WCHAR szMenuString
[255];
123 HINSTANCE hInst
= GetModuleHandleW(L
"win32csr");
127 if (Items
[i
].uID
!= (UINT
)-1)
129 if (LoadStringW(hInst
,
132 sizeof(szMenuString
) / sizeof(szMenuString
[0])) > 0)
134 if (Items
[i
].SubMenu
!= NULL
)
136 hSubMenu
= CreatePopupMenu();
137 if (hSubMenu
!= NULL
)
139 GuiConsoleAppendMenuItems(hSubMenu
,
142 if (!AppendMenuW(hMenu
,
143 MF_STRING
| MF_POPUP
,
147 DestroyMenu(hSubMenu
);
168 }while(!(Items
[i
].uID
== 0 && Items
[i
].SubMenu
== NULL
&& Items
[i
].wCmdID
== 0));
172 GuiConsoleCreateSysMenu(PCSRSS_CONSOLE Console
)
175 hMenu
= GetSystemMenu(Console
->hWindow
,
179 GuiConsoleAppendMenuItems(hMenu
,
180 GuiConsoleMainMenuItems
);
181 DrawMenuBar(Console
->hWindow
);
186 GuiConsoleGetDataPointers(HWND hWnd
, PCSRSS_CONSOLE
*Console
, PGUI_CONSOLE_DATA
*GuiData
)
188 *Console
= (PCSRSS_CONSOLE
) GetWindowLongPtrW(hWnd
, GWL_USERDATA
);
189 *GuiData
= (NULL
== *Console
? NULL
: (*Console
)->PrivateData
);
193 GuiConsoleOpenUserRegistryPathPerProcessId(DWORD ProcessId
, PHANDLE hProcHandle
, PHKEY hResult
, REGSAM samDesired
)
195 HANDLE hProcessToken
= NULL
;
200 UNICODE_STRING SidName
;
204 hProcess
= OpenProcess(PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
| READ_CONTROL
, FALSE
, ProcessId
);
207 DPRINT("Error: OpenProcess failed(0x%x)\n", GetLastError());
211 if (!OpenProcessToken(hProcess
, TOKEN_QUERY
, &hProcessToken
))
213 DPRINT("Error: OpenProcessToken failed(0x%x)\n", GetLastError());
214 CloseHandle(hProcess
);
218 if (!GetTokenInformation(hProcessToken
, TokenUser
, (PVOID
)Buffer
, sizeof(Buffer
), &Length
))
220 DPRINT("Error: GetTokenInformation failed(0x%x)\n",GetLastError());
221 CloseHandle(hProcess
);
222 CloseHandle(hProcessToken
);
226 TokUser
= ((PTOKEN_USER
)Buffer
)->User
.Sid
;
227 if (!NT_SUCCESS(RtlConvertSidToUnicodeString(&SidName
, TokUser
, TRUE
)))
229 DPRINT("Error: RtlConvertSidToUnicodeString failed(0x%x)\n", GetLastError());
233 res
= RegOpenKeyExW(HKEY_USERS
, SidName
.Buffer
, 0, samDesired
, hResult
);
234 RtlFreeUnicodeString(&SidName
);
236 CloseHandle(hProcessToken
);
238 *hProcHandle
= hProcess
;
240 CloseHandle(hProcess
);
242 if (res
!= ERROR_SUCCESS
)
249 GuiConsoleOpenUserSettings(PGUI_CONSOLE_DATA GuiData
, DWORD ProcessId
, PHKEY hSubKey
, REGSAM samDesired
, BOOL bCreate
)
251 WCHAR szProcessName
[MAX_PATH
];
252 WCHAR szBuffer
[MAX_PATH
];
253 UINT fLength
, wLength
;
254 DWORD dwBitmask
, dwLength
;
255 WCHAR CurDrive
[] = { 'A',':', 0 };
261 * console properties are stored under
264 * There are 3 ways to store console properties
266 * 1. use console title as subkey name
269 * 2. use application name as subkey name
271 * 3. use unexpanded path to console application.
272 * i.e. %SystemRoot%_system32_cmd.exe
275 DPRINT("GuiConsoleOpenUserSettings entered\n");
277 if (!GuiConsoleOpenUserRegistryPathPerProcessId(ProcessId
, &hProcess
, &hKey
, samDesired
))
279 DPRINT("GuiConsoleOpenUserRegistryPathPerProcessId failed\n");
283 /* FIXME we do not getting the process name so no menu will be loading, why ?*/
284 fLength
= GetProcessImageFileNameW(hProcess
, szProcessName
, sizeof(GuiData
->szProcessName
) / sizeof(WCHAR
));
285 CloseHandle(hProcess
);
287 //DPRINT1("szProcessName3 : %S\n",szProcessName);
291 DPRINT("GetProcessImageFileNameW failed(0x%x)ProcessId %d\n", GetLastError(),hProcess
);
295 * try the process name as path
298 ptr
= wcsrchr(szProcessName
, L
'\\');
299 wcscpy(GuiData
->szProcessName
, ptr
);
301 swprintf(szBuffer
, L
"Console%s",ptr
);
302 DPRINT("#1 Path : %S\n", szBuffer
);
306 if (RegCreateKeyW(hKey
, szBuffer
, hSubKey
) == ERROR_SUCCESS
)
315 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
322 * try the "Shortcut to processname" as path
323 * FIXME: detect wheter the process was started as a shortcut
326 swprintf(szBuffer
, L
"Console\\Shortcut to %S", ptr
);
327 DPRINT("#2 Path : %S\n", szBuffer
);
328 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
330 swprintf(GuiData
->szProcessName
, L
"Shortcut to %S", ptr
);
336 * if the path contains \\Device\\HarddiskVolume1\... remove it
339 if (szProcessName
[0] == L
'\\')
341 dwBitmask
= GetLogicalDrives();
346 dwLength
= QueryDosDeviceW(CurDrive
, szBuffer
, MAX_PATH
);
349 if (!memcmp(szBuffer
, szProcessName
, (dwLength
-2)*sizeof(WCHAR
)))
351 wcscpy(szProcessName
, CurDrive
);
352 RtlMoveMemory(&szProcessName
[2], &szProcessName
[dwLength
-1], fLength
- dwLength
-1);
357 dwBitmask
= (dwBitmask
>> 1);
363 * last attempt: check whether the file is under %SystemRoot%
364 * and use path like Console\%SystemRoot%_dir_dir2_file.exe
367 wLength
= GetWindowsDirectoryW(szBuffer
, MAX_PATH
);
370 if (!wcsncmp(szProcessName
, szBuffer
, wLength
))
372 /* replace slashes by underscores */
373 while((ptr
= wcschr(szProcessName
, L
'\\')))
376 swprintf(szBuffer
, L
"Console\\%%SystemRoot%%%S", &szProcessName
[wLength
]);
377 DPRINT("#3 Path : %S\n", szBuffer
);
378 if (RegOpenKeyExW(hKey
, szBuffer
, 0, samDesired
, hSubKey
) == ERROR_SUCCESS
)
380 swprintf(GuiData
->szProcessName
, L
"%%SystemRoot%%%S", &szProcessName
[wLength
]);
391 GuiConsoleWriteUserSettings(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
)
394 PCSRSS_PROCESS_DATA ProcessData
;
396 if (Console
->ProcessList
.Flink
== &Console
->ProcessList
)
398 DPRINT("GuiConsoleWriteUserSettings: No Process!!!\n");
401 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Flink
, CSRSS_PROCESS_DATA
, ProcessEntry
);
402 if (!GuiConsoleOpenUserSettings(GuiData
, PtrToUlong(ProcessData
->ProcessId
), &hKey
, KEY_READ
| KEY_WRITE
, TRUE
))
407 if (Console
->ActiveBuffer
->CursorInfo
.dwSize
<= 1)
409 RegDeleteKeyW(hKey
, L
"CursorSize");
413 RegSetValueExW(hKey
, L
"CursorSize", 0, REG_DWORD
, (const BYTE
*)&Console
->ActiveBuffer
->CursorInfo
.dwSize
, sizeof(DWORD
));
416 if (GuiData
->NumberOfHistoryBuffers
== 5)
418 RegDeleteKeyW(hKey
, L
"NumberOfHistoryBuffers");
422 RegSetValueExW(hKey
, L
"NumberOfHistoryBuffers", 0, REG_DWORD
, (const BYTE
*)&GuiData
->NumberOfHistoryBuffers
, sizeof(DWORD
));
425 if (GuiData
->HistoryBufferSize
== 50)
427 RegDeleteKeyW(hKey
, L
"HistoryBufferSize");
431 RegSetValueExW(hKey
, L
"HistoryBufferSize", 0, REG_DWORD
, (const BYTE
*)&GuiData
->HistoryBufferSize
, sizeof(DWORD
));
434 if (GuiData
->FullScreen
== FALSE
)
436 RegDeleteKeyW(hKey
, L
"FullScreen");
440 RegSetValueExW(hKey
, L
"FullScreen", 0, REG_DWORD
, (const BYTE
*)&GuiData
->FullScreen
, sizeof(DWORD
));
443 if ( GuiData
->QuickEdit
== FALSE
)
445 RegDeleteKeyW(hKey
, L
"QuickEdit");
449 RegSetValueExW(hKey
, L
"QuickEdit", 0, REG_DWORD
, (const BYTE
*)&GuiData
->QuickEdit
, sizeof(DWORD
));
452 if (GuiData
->InsertMode
== TRUE
)
454 RegDeleteKeyW(hKey
, L
"InsertMode");
458 RegSetValueExW(hKey
, L
"InsertMode", 0, REG_DWORD
, (const BYTE
*)&GuiData
->InsertMode
, sizeof(DWORD
));
461 if (GuiData
->HistoryNoDup
== FALSE
)
463 RegDeleteKeyW(hKey
, L
"HistoryNoDup");
467 RegSetValueExW(hKey
, L
"HistoryNoDup", 0, REG_DWORD
, (const BYTE
*)&GuiData
->HistoryNoDup
, sizeof(DWORD
));
470 if (GuiData
->ScreenText
== RGB(192, 192, 192))
473 * MS uses console attributes instead of real color
475 RegDeleteKeyW(hKey
, L
"ScreenText");
479 RegSetValueExW(hKey
, L
"ScreenText", 0, REG_DWORD
, (const BYTE
*)&GuiData
->ScreenText
, sizeof(COLORREF
));
482 if (GuiData
->ScreenBackground
== RGB(0, 0, 0))
484 RegDeleteKeyW(hKey
, L
"ScreenBackground");
488 RegSetValueExW(hKey
, L
"ScreenBackground", 0, REG_DWORD
, (const BYTE
*)&GuiData
->ScreenBackground
, sizeof(COLORREF
));
495 GuiConsoleReadUserSettings(HKEY hKey
, PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PCSRSS_SCREEN_BUFFER Buffer
)
497 DWORD dwNumSubKeys
= 0;
502 WCHAR szValueName
[MAX_PATH
];
503 WCHAR szValue
[LF_FACESIZE
] = L
"\0";
506 if (RegQueryInfoKey(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, &dwNumSubKeys
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
508 DPRINT("GuiConsoleReadUserSettings: RegQueryInfoKey failed\n");
512 DPRINT("GuiConsoleReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys
);
514 for (dwIndex
= 0; dwIndex
< dwNumSubKeys
; dwIndex
++)
516 dwValue
= sizeof(Value
);
517 dwValueName
= MAX_PATH
;
519 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, &dwType
, (BYTE
*)&Value
, &dwValue
) != ERROR_SUCCESS
)
521 if (dwType
== REG_SZ
)
524 * retry in case of string value
526 dwValue
= sizeof(szValue
);
527 dwValueName
= LF_FACESIZE
;
528 if (RegEnumValueW(hKey
, dwIndex
, szValueName
, &dwValueName
, NULL
, NULL
, (BYTE
*)szValue
, &dwValue
) != ERROR_SUCCESS
)
534 if (!wcscmp(szValueName
, L
"CursorSize"))
538 Buffer
->CursorInfo
.dwSize
= Value
;
540 else if (Value
== 0x64)
542 Buffer
->CursorInfo
.dwSize
= Value
;
545 else if (!wcscmp(szValueName
, L
"ScreenText"))
547 GuiData
->ScreenText
= Value
;
549 else if (!wcscmp(szValueName
, L
"ScreenBackground"))
551 GuiData
->ScreenBackground
= Value
;
553 else if (!wcscmp(szValueName
, L
"FaceName"))
555 wcscpy(GuiData
->FontName
, szValue
);
557 else if (!wcscmp(szValueName
, L
"FontSize"))
559 GuiData
->FontSize
= Value
;
561 else if (!wcscmp(szValueName
, L
"FontWeight"))
563 GuiData
->FontWeight
= Value
;
565 else if (!wcscmp(szValueName
, L
"HistoryNoDup"))
567 GuiData
->HistoryNoDup
= Value
;
569 else if (!wcscmp(szValueName
, L
"WindowSize"))
571 Console
->Size
.X
= LOWORD(Value
);
572 Console
->Size
.Y
= HIWORD(Value
);
574 else if (!wcscmp(szValueName
, L
"ScreenBufferSize"))
578 Buffer
->MaxX
= LOWORD(Value
);
579 Buffer
->MaxY
= HIWORD(Value
);
582 else if (!wcscmp(szValueName
, L
"FullScreen"))
584 GuiData
->FullScreen
= Value
;
586 else if (!wcscmp(szValueName
, L
"QuickEdit"))
588 GuiData
->QuickEdit
= Value
;
590 else if (!wcscmp(szValueName
, L
"InsertMode"))
592 GuiData
->InsertMode
= Value
;
597 GuiConsoleUseDefaults(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PCSRSS_SCREEN_BUFFER Buffer
)
600 * init guidata with default properties
603 wcscpy(GuiData
->FontName
, L
"DejaVu Sans Mono");
604 GuiData
->FontSize
= 0x0008000C; // font is 8x12
605 GuiData
->FontWeight
= FW_NORMAL
;
606 GuiData
->HistoryNoDup
= FALSE
;
607 GuiData
->FullScreen
= FALSE
;
608 GuiData
->QuickEdit
= FALSE
;
609 GuiData
->InsertMode
= TRUE
;
610 GuiData
->HistoryBufferSize
= 50;
611 GuiData
->NumberOfHistoryBuffers
= 5;
612 GuiData
->ScreenText
= RGB(192, 192, 192);
613 GuiData
->ScreenBackground
= RGB(0, 0, 0);
614 GuiData
->PopupText
= RGB(128, 0, 128);
615 GuiData
->PopupBackground
= RGB(255, 255, 255);
616 GuiData
->WindowPosition
= UINT_MAX
;
617 GuiData
->UseRasterFonts
= TRUE
;
618 memcpy(GuiData
->Colors
, s_Colors
, sizeof(s_Colors
));
620 Console
->Size
.X
= 80;
621 Console
->Size
.Y
= 25;
627 Buffer
->CursorInfo
.bVisible
= TRUE
;
628 Buffer
->CursorInfo
.dwSize
= CSR_DEFAULT_CURSOR_SIZE
;
634 GuiConsoleInitScrollbar(PCSRSS_CONSOLE Console
, HWND hwnd
)
637 PGUI_CONSOLE_DATA GuiData
= Console
->PrivateData
;
639 DWORD Width
= Console
->Size
.X
* GuiData
->CharWidth
+ 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
640 DWORD Height
= Console
->Size
.Y
* GuiData
->CharHeight
+ 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
642 /* set scrollbar sizes */
643 sInfo
.cbSize
= sizeof(SCROLLINFO
);
644 sInfo
.fMask
= SIF_RANGE
| SIF_PAGE
| SIF_POS
;
646 if (Console
->ActiveBuffer
->MaxY
> Console
->Size
.Y
)
648 sInfo
.nMax
= Console
->ActiveBuffer
->MaxY
- 1;
649 sInfo
.nPage
= Console
->Size
.Y
;
650 sInfo
.nPos
= Console
->ActiveBuffer
->ShowY
;
651 SetScrollInfo(hwnd
, SB_VERT
, &sInfo
, TRUE
);
652 Width
+= GetSystemMetrics(SM_CXVSCROLL
);
653 ShowScrollBar(hwnd
, SB_VERT
, TRUE
);
657 ShowScrollBar(hwnd
, SB_VERT
, FALSE
);
660 if (Console
->ActiveBuffer
->MaxX
> Console
->Size
.X
)
662 sInfo
.nMax
= Console
->ActiveBuffer
->MaxX
- 1;
663 sInfo
.nPage
= Console
->Size
.X
;
664 sInfo
.nPos
= Console
->ActiveBuffer
->ShowX
;
665 SetScrollInfo(hwnd
, SB_HORZ
, &sInfo
, TRUE
);
666 Height
+= GetSystemMetrics(SM_CYHSCROLL
);
667 ShowScrollBar(hwnd
, SB_HORZ
, TRUE
);
672 ShowScrollBar(hwnd
, SB_HORZ
, FALSE
);
675 SetWindowPos(hwnd
, NULL
, 0, 0, Width
, Height
,
676 SWP_NOZORDER
| SWP_NOMOVE
| SWP_NOACTIVATE
);
680 GuiConsoleHandleNcCreate(HWND hWnd
, CREATESTRUCTW
*Create
)
682 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) Create
->lpCreateParams
;
683 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
)Console
->PrivateData
;
688 PCSRSS_PROCESS_DATA ProcessData
;
691 Console
->hWindow
= hWnd
;
695 DPRINT1("GuiConsoleNcCreate: HeapAlloc failed\n");
699 GuiConsoleUseDefaults(Console
, GuiData
, Console
->ActiveBuffer
);
700 if (Console
->ProcessList
.Flink
!= &Console
->ProcessList
)
702 ProcessData
= CONTAINING_RECORD(Console
->ProcessList
.Flink
, CSRSS_PROCESS_DATA
, ProcessEntry
);
703 if (GuiConsoleOpenUserSettings(GuiData
, PtrToUlong(ProcessData
->ProcessId
), &hKey
, KEY_READ
, FALSE
))
705 GuiConsoleReadUserSettings(hKey
, Console
, GuiData
, Console
->ActiveBuffer
);
710 InitializeCriticalSection(&GuiData
->Lock
);
712 GuiData
->Font
= CreateFontW(LOWORD(GuiData
->FontSize
),
713 0, //HIWORD(GuiData->FontSize),
721 OUT_DEFAULT_PRECIS
, CLIP_DEFAULT_PRECIS
,
722 NONANTIALIASED_QUALITY
, FIXED_PITCH
| FF_DONTCARE
,
724 if (NULL
== GuiData
->Font
)
726 DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
727 DeleteCriticalSection(&GuiData
->Lock
);
728 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
734 DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
735 DeleteObject(GuiData
->Font
);
736 DeleteCriticalSection(&GuiData
->Lock
);
737 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
740 OldFont
= SelectObject(Dc
, GuiData
->Font
);
743 DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
745 DeleteObject(GuiData
->Font
);
746 DeleteCriticalSection(&GuiData
->Lock
);
747 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
750 if (! GetTextMetricsW(Dc
, &Metrics
))
752 DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
753 SelectObject(Dc
, OldFont
);
755 DeleteObject(GuiData
->Font
);
756 DeleteCriticalSection(&GuiData
->Lock
);
757 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
760 GuiData
->CharWidth
= Metrics
.tmMaxCharWidth
;
761 GuiData
->CharHeight
= Metrics
.tmHeight
+ Metrics
.tmExternalLeading
;
763 /* Measure real char width more precisely if possible. */
764 if (GetTextExtentPoint32W(Dc
, L
"R", 1, &CharSize
))
765 GuiData
->CharWidth
= CharSize
.cx
;
767 SelectObject(Dc
, OldFont
);
770 GuiData
->CursorBlinkOn
= TRUE
;
771 GuiData
->ForceCursorOff
= FALSE
;
773 DPRINT("Console %p GuiData %p\n", Console
, GuiData
);
774 Console
->PrivateData
= GuiData
;
775 SetWindowLongPtrW(hWnd
, GWL_USERDATA
, (DWORD_PTR
) Console
);
777 SetTimer(hWnd
, CONGUI_UPDATE_TIMER
, CONGUI_UPDATE_TIME
, NULL
);
778 GuiConsoleCreateSysMenu(Console
);
780 GuiData
->WindowSizeLock
= TRUE
;
781 GuiConsoleInitScrollbar(Console
, hWnd
);
782 GuiData
->WindowSizeLock
= FALSE
;
784 SetEvent(GuiData
->hGuiInitEvent
);
786 return (BOOL
) DefWindowProcW(hWnd
, WM_NCCREATE
, 0, (LPARAM
) Create
);
790 SmallRectToRect(PCSRSS_CONSOLE Console
, PRECT Rect
, PSMALL_RECT SmallRect
)
792 PCSRSS_SCREEN_BUFFER Buffer
= Console
->ActiveBuffer
;
793 PGUI_CONSOLE_DATA GuiData
= Console
->PrivateData
;
794 Rect
->left
= (SmallRect
->Left
- Buffer
->ShowX
) * GuiData
->CharWidth
;
795 Rect
->top
= (SmallRect
->Top
- Buffer
->ShowY
) * GuiData
->CharHeight
;
796 Rect
->right
= (SmallRect
->Right
+ 1 - Buffer
->ShowX
) * GuiData
->CharWidth
;
797 Rect
->bottom
= (SmallRect
->Bottom
+ 1 - Buffer
->ShowY
) * GuiData
->CharHeight
;
801 GuiConsoleUpdateSelection(PCSRSS_CONSOLE Console
, PCOORD coord
)
803 RECT oldRect
, newRect
;
804 HWND hWnd
= Console
->hWindow
;
806 SmallRectToRect(Console
, &oldRect
, &Console
->Selection
.srSelection
);
811 /* exchange left/top with right/bottom if required */
812 rc
.Left
= min(Console
->Selection
.dwSelectionAnchor
.X
, coord
->X
);
813 rc
.Top
= min(Console
->Selection
.dwSelectionAnchor
.Y
, coord
->Y
);
814 rc
.Right
= max(Console
->Selection
.dwSelectionAnchor
.X
, coord
->X
);
815 rc
.Bottom
= max(Console
->Selection
.dwSelectionAnchor
.Y
, coord
->Y
);
817 SmallRectToRect(Console
, &newRect
, &rc
);
819 if (Console
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
)
821 if (memcmp(&rc
, &Console
->Selection
.srSelection
, sizeof(SMALL_RECT
)) != 0)
825 /* calculate the region that needs to be updated */
826 if((rgn1
= CreateRectRgnIndirect(&oldRect
)))
828 if((rgn2
= CreateRectRgnIndirect(&newRect
)))
830 if(CombineRgn(rgn1
, rgn2
, rgn1
, RGN_XOR
) != ERROR
)
832 InvalidateRgn(hWnd
, rgn1
, FALSE
);
843 InvalidateRect(hWnd
, &newRect
, FALSE
);
845 Console
->Selection
.dwFlags
|= CONSOLE_SELECTION_NOT_EMPTY
;
846 Console
->Selection
.srSelection
= rc
;
850 /* clear the selection */
851 if (Console
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
)
853 InvalidateRect(hWnd
, &oldRect
, FALSE
);
855 Console
->Selection
.dwFlags
= CONSOLE_NO_SELECTION
;
861 GuiConsolePaint(PCSRSS_CONSOLE Console
,
862 PGUI_CONSOLE_DATA GuiData
,
866 PCSRSS_SCREEN_BUFFER Buff
;
867 ULONG TopLine
, BottomLine
, LeftChar
, RightChar
;
868 ULONG Line
, Char
, Start
;
871 BYTE LastAttribute
, Attribute
;
872 ULONG CursorX
, CursorY
, CursorHeight
;
873 HBRUSH CursorBrush
, OldBrush
;
876 Buff
= Console
->ActiveBuffer
;
878 EnterCriticalSection(&Buff
->Header
.Console
->Lock
);
880 TopLine
= rc
->top
/ GuiData
->CharHeight
+ Buff
->ShowY
;
881 BottomLine
= (rc
->bottom
+ (GuiData
->CharHeight
- 1)) / GuiData
->CharHeight
- 1 + Buff
->ShowY
;
882 LeftChar
= rc
->left
/ GuiData
->CharWidth
+ Buff
->ShowX
;
883 RightChar
= (rc
->right
+ (GuiData
->CharWidth
- 1)) / GuiData
->CharWidth
- 1 + Buff
->ShowX
;
884 LastAttribute
= ConioCoordToPointer(Buff
, LeftChar
, TopLine
)[1];
886 SetTextColor(hDC
, GuiConsoleRGBFromAttribute(GuiData
, LastAttribute
));
887 SetBkColor(hDC
, GuiConsoleRGBFromAttribute(GuiData
, LastAttribute
>> 4));
889 if (BottomLine
>= Buff
->MaxY
) BottomLine
= Buff
->MaxY
- 1;
890 if (RightChar
>= Buff
->MaxX
) RightChar
= Buff
->MaxX
- 1;
892 OldFont
= SelectObject(hDC
,
895 for (Line
= TopLine
; Line
<= BottomLine
; Line
++)
897 WCHAR LineBuffer
[80];
898 From
= ConioCoordToPointer(Buff
, LeftChar
, Line
);
902 for (Char
= LeftChar
; Char
<= RightChar
; Char
++)
904 if (*(From
+ 1) != LastAttribute
|| (Char
- Start
== sizeof(LineBuffer
) / sizeof(WCHAR
)))
907 (Start
- Buff
->ShowX
) * GuiData
->CharWidth
,
908 (Line
- Buff
->ShowY
) * GuiData
->CharHeight
,
913 Attribute
= *(From
+ 1);
914 if (Attribute
!= LastAttribute
)
916 SetTextColor(hDC
, GuiConsoleRGBFromAttribute(GuiData
, Attribute
));
917 SetBkColor(hDC
, GuiConsoleRGBFromAttribute(GuiData
, Attribute
>> 4));
918 LastAttribute
= Attribute
;
922 MultiByteToWideChar(Console
->OutputCodePage
,
933 (Start
- Buff
->ShowX
) * GuiData
->CharWidth
,
934 (Line
- Buff
->ShowY
) * GuiData
->CharHeight
,
936 RightChar
- Start
+ 1);
939 if (Buff
->CursorInfo
.bVisible
&& GuiData
->CursorBlinkOn
&&
940 !GuiData
->ForceCursorOff
)
942 CursorX
= Buff
->CurrentX
;
943 CursorY
= Buff
->CurrentY
;
944 if (LeftChar
<= CursorX
&& CursorX
<= RightChar
&&
945 TopLine
<= CursorY
&& CursorY
<= BottomLine
)
947 CursorHeight
= (GuiData
->CharHeight
* Buff
->CursorInfo
.dwSize
) / 100;
948 if (CursorHeight
< 1)
952 From
= ConioCoordToPointer(Buff
, Buff
->CurrentX
, Buff
->CurrentY
) + 1;
954 if (*From
!= DEFAULT_ATTRIB
)
956 CursorBrush
= CreateSolidBrush(GuiConsoleRGBFromAttribute(GuiData
, *From
));
960 CursorBrush
= CreateSolidBrush(GuiData
->ScreenText
);
963 OldBrush
= SelectObject(hDC
,
966 (CursorX
- Buff
->ShowX
) * GuiData
->CharWidth
,
967 (CursorY
- Buff
->ShowY
) * GuiData
->CharHeight
+ (GuiData
->CharHeight
- CursorHeight
),
973 DeleteObject(CursorBrush
);
977 LeaveCriticalSection(&Buff
->Header
.Console
->Lock
);
984 GuiConsoleHandlePaint(HWND hWnd
, HDC hDCPaint
)
988 PCSRSS_CONSOLE Console
;
989 PGUI_CONSOLE_DATA GuiData
;
991 hDC
= BeginPaint(hWnd
, &ps
);
993 ps
.rcPaint
.left
< ps
.rcPaint
.right
&&
994 ps
.rcPaint
.top
< ps
.rcPaint
.bottom
)
996 GuiConsoleGetDataPointers(hWnd
,
999 if (Console
!= NULL
&& GuiData
!= NULL
&&
1000 Console
->ActiveBuffer
!= NULL
)
1002 if (Console
->ActiveBuffer
->Buffer
!= NULL
)
1004 EnterCriticalSection(&GuiData
->Lock
);
1006 GuiConsolePaint(Console
,
1011 if (Console
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
)
1014 SmallRectToRect(Console
, &rc
, &Console
->Selection
.srSelection
);
1016 /* invert the selection */
1017 if (IntersectRect(&rc
,
1030 LeaveCriticalSection(&GuiData
->Lock
);
1035 EndPaint(hWnd
, &ps
);
1039 GuiConsoleHandleKey(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1041 PCSRSS_CONSOLE Console
;
1042 PGUI_CONSOLE_DATA GuiData
;
1045 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1046 Message
.hwnd
= hWnd
;
1047 Message
.message
= msg
;
1048 Message
.wParam
= wParam
;
1049 Message
.lParam
= lParam
;
1051 if(msg
== WM_CHAR
|| msg
== WM_SYSKEYDOWN
)
1053 /* clear the selection */
1054 GuiConsoleUpdateSelection(Console
, NULL
);
1057 ConioProcessKey(&Message
, Console
, FALSE
);
1061 GuiDrawRegion(PCSRSS_CONSOLE Console
, SMALL_RECT
*Region
)
1064 SmallRectToRect(Console
, &RegionRect
, Region
);
1065 InvalidateRect(Console
->hWindow
, &RegionRect
, FALSE
);
1069 GuiInvalidateCell(PCSRSS_CONSOLE Console
, UINT x
, UINT y
)
1071 SMALL_RECT CellRect
= { x
, y
, x
, y
};
1072 GuiDrawRegion(Console
, &CellRect
);
1076 GuiWriteStream(PCSRSS_CONSOLE Console
, SMALL_RECT
*Region
, LONG CursorStartX
, LONG CursorStartY
,
1077 UINT ScrolledLines
, CHAR
*Buffer
, UINT Length
)
1079 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
1080 PCSRSS_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
1081 LONG CursorEndX
, CursorEndY
;
1084 if (NULL
== Console
->hWindow
|| NULL
== GuiData
)
1089 if (0 != ScrolledLines
)
1091 ScrollRect
.left
= 0;
1093 ScrollRect
.right
= Console
->Size
.X
* GuiData
->CharWidth
;
1094 ScrollRect
.bottom
= Region
->Top
* GuiData
->CharHeight
;
1096 ScrollWindowEx(Console
->hWindow
,
1098 -(ScrolledLines
* GuiData
->CharHeight
),
1106 GuiDrawRegion(Console
, Region
);
1108 if (CursorStartX
< Region
->Left
|| Region
->Right
< CursorStartX
1109 || CursorStartY
< Region
->Top
|| Region
->Bottom
< CursorStartY
)
1111 GuiInvalidateCell(Console
, CursorStartX
, CursorStartY
);
1114 CursorEndX
= Buff
->CurrentX
;
1115 CursorEndY
= Buff
->CurrentY
;
1116 if ((CursorEndX
< Region
->Left
|| Region
->Right
< CursorEndX
1117 || CursorEndY
< Region
->Top
|| Region
->Bottom
< CursorEndY
)
1118 && (CursorEndX
!= CursorStartX
|| CursorEndY
!= CursorStartY
))
1120 GuiInvalidateCell(Console
, CursorEndX
, CursorEndY
);
1123 // Set up the update timer (very short interval) - this is a "hack" for getting the OS to
1124 // repaint the window without having it just freeze up and stay on the screen permanently.
1125 GuiData
->CursorBlinkOn
= TRUE
;
1126 SetTimer(Console
->hWindow
, CONGUI_UPDATE_TIMER
, CONGUI_UPDATE_TIME
, NULL
);
1130 GuiSetCursorInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
)
1132 if (Console
->ActiveBuffer
== Buff
)
1134 GuiInvalidateCell(Console
, Buff
->CurrentX
, Buff
->CurrentY
);
1141 GuiSetScreenInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
, UINT OldCursorX
, UINT OldCursorY
)
1143 if (Console
->ActiveBuffer
== Buff
)
1145 /* Redraw char at old position (removes cursor) */
1146 GuiInvalidateCell(Console
, OldCursorX
, OldCursorY
);
1147 /* Redraw char at new position (shows cursor) */
1148 GuiInvalidateCell(Console
, Buff
->CurrentX
, Buff
->CurrentY
);
1155 GuiUpdateScreenInfo(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buff
)
1157 PGUI_CONSOLE_DATA GuiData
= (PGUI_CONSOLE_DATA
) Console
->PrivateData
;
1159 if (Console
->ActiveBuffer
== Buff
)
1161 GuiData
->ScreenText
= GuiConsoleRGBFromAttribute(GuiData
, Buff
->DefaultAttrib
);
1162 GuiData
->ScreenBackground
= GuiConsoleRGBFromAttribute(GuiData
, Buff
->DefaultAttrib
>> 4);
1169 GuiConsoleHandleTimer(HWND hWnd
)
1171 PCSRSS_CONSOLE Console
;
1172 PGUI_CONSOLE_DATA GuiData
;
1173 PCSRSS_SCREEN_BUFFER Buff
;
1175 SetTimer(hWnd
, CONGUI_UPDATE_TIMER
, CURSOR_BLINK_TIME
, NULL
);
1177 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1179 Buff
= Console
->ActiveBuffer
;
1180 GuiInvalidateCell(Console
, Buff
->CurrentX
, Buff
->CurrentY
);
1181 GuiData
->CursorBlinkOn
= ! GuiData
->CursorBlinkOn
;
1183 if((GuiData
->OldCursor
.x
!= Buff
->CurrentX
) || (GuiData
->OldCursor
.y
!= Buff
->CurrentY
))
1186 int OldScrollX
= -1, OldScrollY
= -1;
1187 int NewScrollX
= -1, NewScrollY
= -1;
1189 xScroll
.cbSize
= sizeof(SCROLLINFO
);
1190 xScroll
.fMask
= SIF_POS
;
1191 // Capture the original position of the scroll bars and save them.
1192 if(GetScrollInfo(hWnd
, SB_HORZ
, &xScroll
))OldScrollX
= xScroll
.nPos
;
1193 if(GetScrollInfo(hWnd
, SB_VERT
, &xScroll
))OldScrollY
= xScroll
.nPos
;
1195 // If we successfully got the info for the horizontal scrollbar
1198 if((Buff
->CurrentX
< Buff
->ShowX
)||(Buff
->CurrentX
>= (Buff
->ShowX
+ Console
->Size
.X
)))
1200 // Handle the horizontal scroll bar
1201 if(Buff
->CurrentX
>= Console
->Size
.X
) NewScrollX
= Buff
->CurrentX
- Console
->Size
.X
+ 1;
1202 else NewScrollX
= 0;
1206 NewScrollX
= OldScrollX
;
1209 // If we successfully got the info for the vertical scrollbar
1212 if((Buff
->CurrentY
< Buff
->ShowY
) || (Buff
->CurrentY
>= (Buff
->ShowY
+ Console
->Size
.Y
)))
1214 // Handle the vertical scroll bar
1215 if(Buff
->CurrentY
>= Console
->Size
.Y
) NewScrollY
= Buff
->CurrentY
- Console
->Size
.Y
+ 1;
1216 else NewScrollY
= 0;
1220 NewScrollY
= OldScrollY
;
1224 // Adjust scroll bars and refresh the window if the cursor has moved outside the visible area
1225 // NOTE: OldScroll# and NewScroll# will both be -1 (initial value) if the info for the respective scrollbar
1226 // was not obtained successfully in the previous steps. This means their difference is 0 (no scrolling)
1227 // and their associated scrollbar is left alone.
1228 if((OldScrollX
!= NewScrollX
) || (OldScrollY
!= NewScrollY
))
1230 Buff
->ShowX
= NewScrollX
;
1231 Buff
->ShowY
= NewScrollY
;
1232 ScrollWindowEx(hWnd
,
1233 (OldScrollX
- NewScrollX
) * GuiData
->CharWidth
,
1234 (OldScrollY
- NewScrollY
) * GuiData
->CharHeight
,
1242 xScroll
.nPos
= NewScrollX
;
1243 SetScrollInfo(hWnd
, SB_HORZ
, &xScroll
, TRUE
);
1247 xScroll
.nPos
= NewScrollY
;
1248 SetScrollInfo(hWnd
, SB_VERT
, &xScroll
, TRUE
);
1251 GuiData
->OldCursor
.x
= Buff
->CurrentX
;
1252 GuiData
->OldCursor
.y
= Buff
->CurrentY
;
1258 GuiConsoleHandleClose(HWND hWnd
)
1260 PCSRSS_CONSOLE Console
;
1261 PGUI_CONSOLE_DATA GuiData
;
1262 PLIST_ENTRY current_entry
;
1263 PCSRSS_PROCESS_DATA current
;
1265 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1267 EnterCriticalSection(&Console
->Lock
);
1269 current_entry
= Console
->ProcessList
.Flink
;
1270 while (current_entry
!= &Console
->ProcessList
)
1272 current
= CONTAINING_RECORD(current_entry
, CSRSS_PROCESS_DATA
, ProcessEntry
);
1273 current_entry
= current_entry
->Flink
;
1275 /* FIXME: Windows will wait up to 5 seconds for the thread to exit.
1276 * We shouldn't wait here, though, since the console lock is entered.
1277 * A copy of the thread list probably needs to be made. */
1278 ConioConsoleCtrlEvent(CTRL_CLOSE_EVENT
, current
);
1281 LeaveCriticalSection(&Console
->Lock
);
1285 GuiConsoleHandleNcDestroy(HWND hWnd
)
1287 PCSRSS_CONSOLE Console
;
1288 PGUI_CONSOLE_DATA GuiData
;
1291 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1293 Console
->PrivateData
= NULL
;
1294 DeleteCriticalSection(&GuiData
->Lock
);
1295 GetSystemMenu(hWnd
, TRUE
);
1296 if (GuiData
->ConsoleLibrary
)
1297 FreeLibrary(GuiData
->ConsoleLibrary
);
1299 HeapFree(Win32CsrApiHeap
, 0, GuiData
);
1303 PointToCoord(PCSRSS_CONSOLE Console
, LPARAM lParam
)
1305 PCSRSS_SCREEN_BUFFER Buffer
= Console
->ActiveBuffer
;
1306 PGUI_CONSOLE_DATA GuiData
= Console
->PrivateData
;
1308 Coord
.X
= Buffer
->ShowX
+ ((short)LOWORD(lParam
) / (int)GuiData
->CharWidth
);
1309 Coord
.Y
= Buffer
->ShowY
+ ((short)HIWORD(lParam
) / (int)GuiData
->CharHeight
);
1311 /* Clip coordinate to ensure it's inside buffer */
1312 if (Coord
.X
< 0) Coord
.X
= 0;
1313 else if (Coord
.X
>= Buffer
->MaxX
) Coord
.X
= Buffer
->MaxX
- 1;
1314 if (Coord
.Y
< 0) Coord
.Y
= 0;
1315 else if (Coord
.Y
>= Buffer
->MaxY
) Coord
.Y
= Buffer
->MaxY
- 1;
1320 GuiConsoleLeftMouseDown(HWND hWnd
, LPARAM lParam
)
1322 PCSRSS_CONSOLE Console
;
1323 PGUI_CONSOLE_DATA GuiData
;
1325 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1326 if (Console
== NULL
|| GuiData
== NULL
) return;
1328 Console
->Selection
.dwSelectionAnchor
= PointToCoord(Console
, lParam
);
1332 Console
->Selection
.dwFlags
|= CONSOLE_SELECTION_IN_PROGRESS
| CONSOLE_MOUSE_SELECTION
| CONSOLE_MOUSE_DOWN
;
1334 GuiConsoleUpdateSelection(Console
, &Console
->Selection
.dwSelectionAnchor
);
1338 GuiConsoleLeftMouseUp(HWND hWnd
, LPARAM lParam
)
1340 PCSRSS_CONSOLE Console
;
1341 PGUI_CONSOLE_DATA GuiData
;
1344 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1345 if (Console
== NULL
|| GuiData
== NULL
) return;
1346 if (!(Console
->Selection
.dwFlags
& CONSOLE_MOUSE_DOWN
)) return;
1348 c
= PointToCoord(Console
, lParam
);
1350 Console
->Selection
.dwFlags
&= ~CONSOLE_MOUSE_DOWN
;
1352 GuiConsoleUpdateSelection(Console
, &c
);
1358 GuiConsoleMouseMove(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1360 PCSRSS_CONSOLE Console
;
1361 PGUI_CONSOLE_DATA GuiData
;
1364 if (!(wParam
& MK_LBUTTON
)) return;
1366 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1367 if (Console
== NULL
|| GuiData
== NULL
) return;
1368 if (!(Console
->Selection
.dwFlags
& CONSOLE_MOUSE_DOWN
)) return;
1370 c
= PointToCoord(Console
, lParam
); /* TODO: Scroll buffer to bring c into view */
1372 GuiConsoleUpdateSelection(Console
, &c
);
1376 GuiConsoleRightMouseDown(HWND hWnd
)
1378 PCSRSS_CONSOLE Console
;
1379 PGUI_CONSOLE_DATA GuiData
;
1381 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1382 if (Console
== NULL
|| GuiData
== NULL
) return;
1384 if (!(Console
->Selection
.dwFlags
& CONSOLE_SELECTION_NOT_EMPTY
))
1386 /* FIXME - paste text from clipboard */
1390 /* FIXME - copy selection to clipboard */
1392 GuiConsoleUpdateSelection(Console
, NULL
);
1399 GuiConsoleShowConsoleProperties(HWND hWnd
, BOOL Defaults
, PGUI_CONSOLE_DATA GuiData
)
1401 PCSRSS_CONSOLE Console
;
1402 APPLET_PROC CPLFunc
;
1403 TCHAR szBuffer
[MAX_PATH
];
1404 ConsoleInfo SharedInfo
;
1406 DPRINT("GuiConsoleShowConsoleProperties entered\n");
1408 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1410 if (GuiData
== NULL
)
1412 DPRINT("GuiConsoleGetDataPointers failed\n");
1416 if (GuiData
->ConsoleLibrary
== NULL
)
1418 GetWindowsDirectory(szBuffer
,MAX_PATH
);
1419 _tcscat(szBuffer
, _T("\\system32\\console.dll"));
1420 GuiData
->ConsoleLibrary
= LoadLibrary(szBuffer
);
1422 if (GuiData
->ConsoleLibrary
== NULL
)
1424 DPRINT1("failed to load console.dll");
1429 CPLFunc
= (APPLET_PROC
) GetProcAddress(GuiData
->ConsoleLibrary
, _T("CPlApplet"));
1432 DPRINT("Error: Console.dll misses CPlApplet export\n");
1437 SharedInfo
.InsertMode
= GuiData
->InsertMode
;
1438 SharedInfo
.HistoryBufferSize
= GuiData
->HistoryBufferSize
;
1439 SharedInfo
.NumberOfHistoryBuffers
= GuiData
->NumberOfHistoryBuffers
;
1440 SharedInfo
.ScreenText
= GuiData
->ScreenText
;
1441 SharedInfo
.ScreenBackground
= GuiData
->ScreenBackground
;
1442 SharedInfo
.PopupText
= GuiData
->PopupText
;
1443 SharedInfo
.PopupBackground
= GuiData
->PopupBackground
;
1444 SharedInfo
.WindowSize
= (DWORD
)MAKELONG(Console
->Size
.X
, Console
->Size
.Y
);
1445 SharedInfo
.WindowPosition
= GuiData
->WindowPosition
;
1446 SharedInfo
.ScreenBuffer
= (DWORD
)MAKELONG(Console
->ActiveBuffer
->MaxX
, Console
->ActiveBuffer
->MaxY
);
1447 SharedInfo
.UseRasterFonts
= GuiData
->UseRasterFonts
;
1448 SharedInfo
.FontSize
= (DWORD
)GuiData
->FontSize
;
1449 SharedInfo
.FontWeight
= GuiData
->FontWeight
;
1450 SharedInfo
.CursorSize
= Console
->ActiveBuffer
->CursorInfo
.dwSize
;
1451 SharedInfo
.HistoryNoDup
= GuiData
->HistoryNoDup
;
1452 SharedInfo
.FullScreen
= GuiData
->FullScreen
;
1453 SharedInfo
.QuickEdit
= GuiData
->QuickEdit
;
1454 memcpy(&SharedInfo
.Colors
[0], GuiData
->Colors
, sizeof(s_Colors
));
1456 if (!CPLFunc(hWnd
, CPL_INIT
, 0, 0))
1458 DPRINT("Error: failed to initialize console.dll\n");
1462 if (CPLFunc(hWnd
, CPL_GETCOUNT
, 0, 0) != 1)
1464 DPRINT("Error: console.dll returned unexpected CPL count\n");
1468 CPLFunc(hWnd
, CPL_DBLCLK
, (LPARAM
)&SharedInfo
, Defaults
);
1471 GuiConsoleHandleSysMenuCommand(HWND hWnd
, WPARAM wParam
, LPARAM lParam
, PGUI_CONSOLE_DATA GuiData
)
1477 case ID_SYSTEM_EDIT_MARK
:
1478 case ID_SYSTEM_EDIT_COPY
:
1479 case ID_SYSTEM_EDIT_PASTE
:
1480 case ID_SYSTEM_EDIT_SELECTALL
:
1481 case ID_SYSTEM_EDIT_SCROLL
:
1482 case ID_SYSTEM_EDIT_FIND
:
1485 case ID_SYSTEM_DEFAULTS
:
1486 GuiConsoleShowConsoleProperties(hWnd
, TRUE
, GuiData
);
1489 case ID_SYSTEM_PROPERTIES
:
1490 GuiConsoleShowConsoleProperties(hWnd
, FALSE
, GuiData
);
1494 Ret
= DefWindowProcW(hWnd
, WM_SYSCOMMAND
, wParam
, lParam
);
1501 GuiConsoleGetMinMaxInfo(HWND hWnd
, PMINMAXINFO minMaxInfo
)
1503 PCSRSS_CONSOLE Console
;
1504 PGUI_CONSOLE_DATA GuiData
;
1505 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1506 if((Console
== NULL
)|| (GuiData
== NULL
)) return;
1508 DWORD windx
= CONGUI_MIN_WIDTH
* GuiData
->CharWidth
+ 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
1509 DWORD windy
= CONGUI_MIN_HEIGHT
* GuiData
->CharHeight
+ 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
1511 minMaxInfo
->ptMinTrackSize
.x
= windx
;
1512 minMaxInfo
->ptMinTrackSize
.y
= windy
;
1514 windx
= (Console
->ActiveBuffer
->MaxX
) * GuiData
->CharWidth
+ 2 * (GetSystemMetrics(SM_CXFRAME
) + GetSystemMetrics(SM_CXEDGE
));
1515 windy
= (Console
->ActiveBuffer
->MaxY
) * GuiData
->CharHeight
+ 2 * (GetSystemMetrics(SM_CYFRAME
) + GetSystemMetrics(SM_CYEDGE
)) + GetSystemMetrics(SM_CYCAPTION
);
1517 if(Console
->Size
.X
< Console
->ActiveBuffer
->MaxX
) windy
+= GetSystemMetrics(SM_CYHSCROLL
); // window currently has a horizontal scrollbar
1518 if(Console
->Size
.Y
< Console
->ActiveBuffer
->MaxY
) windx
+= GetSystemMetrics(SM_CXVSCROLL
); // window currently has a vertical scrollbar
1520 minMaxInfo
->ptMaxTrackSize
.x
= windx
;
1521 minMaxInfo
->ptMaxTrackSize
.y
= windy
;
1524 GuiConsoleResize(HWND hWnd
, WPARAM wParam
, LPARAM lParam
)
1526 PCSRSS_CONSOLE Console
;
1527 PGUI_CONSOLE_DATA GuiData
;
1528 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1529 if((Console
== NULL
) || (GuiData
== NULL
)) return;
1531 if ((GuiData
->WindowSizeLock
== FALSE
) && (wParam
== SIZE_RESTORED
|| wParam
== SIZE_MAXIMIZED
|| wParam
== SIZE_MINIMIZED
))
1533 PCSRSS_SCREEN_BUFFER Buff
= Console
->ActiveBuffer
;
1535 GuiData
->WindowSizeLock
= TRUE
;
1537 DWORD windx
= LOWORD(lParam
);
1538 DWORD windy
= HIWORD(lParam
);
1540 // Compensate for existing scroll bars (because lParam values do not accommodate scroll bar)
1541 if(Console
->Size
.X
< Buff
->MaxX
) windy
+= GetSystemMetrics(SM_CYHSCROLL
); // window currently has a horizontal scrollbar
1542 if(Console
->Size
.Y
< Buff
->MaxY
) windx
+= GetSystemMetrics(SM_CXVSCROLL
); // window currently has a vertical scrollbar
1544 DWORD charx
= windx
/ GuiData
->CharWidth
;
1545 DWORD chary
= windy
/ GuiData
->CharHeight
;
1547 // Character alignment (round size up or down)
1548 if((windx
% GuiData
->CharWidth
) >= (GuiData
->CharWidth
/ 2)) ++charx
;
1549 if((windy
% GuiData
->CharHeight
) >= (GuiData
->CharHeight
/ 2)) ++chary
;
1551 // Compensate for added scroll bars in new window
1552 if(charx
< Buff
->MaxX
)windy
-= GetSystemMetrics(SM_CYHSCROLL
); // new window will have a horizontal scroll bar
1553 if(chary
< Buff
->MaxY
)windx
-= GetSystemMetrics(SM_CXVSCROLL
); // new window will have a vertical scroll bar
1555 charx
= windx
/ GuiData
->CharWidth
;
1556 chary
= windy
/ GuiData
->CharHeight
;
1558 // Character alignment (round size up or down)
1559 if((windx
% GuiData
->CharWidth
) >= (GuiData
->CharWidth
/ 2)) ++charx
;
1560 if((windy
% GuiData
->CharHeight
) >= (GuiData
->CharHeight
/ 2)) ++chary
;
1563 if((charx
!= Console
->Size
.X
) || (chary
!= Console
->Size
.Y
))
1565 Console
->Size
.X
= (charx
<= Buff
->MaxX
) ? charx
: Buff
->MaxX
;
1566 Console
->Size
.Y
= (chary
<= Buff
->MaxY
) ? chary
: Buff
->MaxY
;
1569 GuiConsoleInitScrollbar(Console
, hWnd
);
1571 // Adjust the start of the visible area if we are attempting to show nonexistent areas
1572 if((Buff
->MaxX
- Buff
->ShowX
) < Console
->Size
.X
) Buff
->ShowX
= Buff
->MaxX
- Console
->Size
.X
;
1573 if((Buff
->MaxY
- Buff
->ShowY
) < Console
->Size
.Y
) Buff
->ShowY
= Buff
->MaxY
- Console
->Size
.Y
;
1574 InvalidateRect(hWnd
, NULL
, TRUE
);
1576 GuiData
->WindowSizeLock
= FALSE
;
1582 GuiConsoleHandleScrollbarMenu()
1586 hMenu
= CreatePopupMenu();
1589 DPRINT("CreatePopupMenu failed\n");
1592 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLHERE);
1593 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1594 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLTOP);
1595 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLBOTTOM);
1596 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1597 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_UP);
1598 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_DOWN);
1599 //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
1600 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLUP);
1601 //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLDOWN);
1605 static NTSTATUS WINAPI
1606 GuiResizeBuffer(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER ScreenBuffer
, COORD Size
)
1614 USHORT value
= MAKEWORD(' ', ScreenBuffer
->DefaultAttrib
);
1619 /* Buffer size is not allowed to be smaller than window size */
1620 if (Size
.X
< Console
->Size
.X
|| Size
.Y
< Console
->Size
.Y
)
1621 return STATUS_INVALID_PARAMETER
;
1623 if (Size
.X
== ScreenBuffer
->MaxX
&& Size
.Y
== ScreenBuffer
->MaxY
)
1624 return STATUS_SUCCESS
;
1626 Buffer
= HeapAlloc(Win32CsrApiHeap
, 0, Size
.X
* Size
.Y
* 2);
1628 return STATUS_NO_MEMORY
;
1630 DPRINT1("Resizing (%d,%d) to (%d,%d)\n", ScreenBuffer
->MaxX
, ScreenBuffer
->MaxY
, Size
.X
, Size
.Y
);
1631 OldBuffer
= ScreenBuffer
->Buffer
;
1633 for (CurrentY
= 0; CurrentY
< ScreenBuffer
->MaxY
&& CurrentY
< Size
.Y
; CurrentY
++)
1635 OldPtr
= ConioCoordToPointer(ScreenBuffer
, 0, CurrentY
);
1636 if (Size
.X
<= ScreenBuffer
->MaxX
)
1639 RtlCopyMemory(&Buffer
[Offset
], OldPtr
, Size
.X
* 2);
1640 Offset
+= (Size
.X
* 2);
1645 RtlCopyMemory(&Buffer
[Offset
], OldPtr
, ScreenBuffer
->MaxX
* 2);
1646 Offset
+= (ScreenBuffer
->MaxX
* 2);
1648 diff
= Size
.X
- ScreenBuffer
->MaxX
;
1649 /* zero new part of it */
1651 wmemset((WCHAR
*)&Buffer
[Offset
], value
, diff
);
1653 for (i
= 0; i
< diff
; i
++)
1655 Buffer
[Offset
++] = ' ';
1656 Buffer
[Offset
++] = ScreenBuffer
->DefaultAttrib
;
1662 if (Size
.Y
> ScreenBuffer
->MaxY
)
1664 diff
= Size
.X
* (Size
.Y
- ScreenBuffer
->MaxY
);
1666 wmemset((WCHAR
*)&Buffer
[Offset
], value
, diff
);
1668 for (i
= 0; i
< diff
; i
++)
1670 Buffer
[Offset
++] = ' ';
1671 Buffer
[Offset
++] = ScreenBuffer
->DefaultAttrib
;
1676 (void)InterlockedExchangePointer((PVOID
volatile *)&ScreenBuffer
->Buffer
, Buffer
);
1677 HeapFree(Win32CsrApiHeap
, 0, OldBuffer
);
1678 ScreenBuffer
->MaxX
= Size
.X
;
1679 ScreenBuffer
->MaxY
= Size
.Y
;
1680 ScreenBuffer
->VirtualY
= 0;
1682 /* Ensure cursor and window are within buffer */
1683 if (ScreenBuffer
->CurrentX
>= Size
.X
)
1684 ScreenBuffer
->CurrentX
= Size
.X
- 1;
1685 if (ScreenBuffer
->CurrentY
>= Size
.Y
)
1686 ScreenBuffer
->CurrentY
= Size
.Y
- 1;
1687 if (ScreenBuffer
->ShowX
> Size
.X
- Console
->Size
.X
)
1688 ScreenBuffer
->ShowX
= Size
.X
- Console
->Size
.X
;
1689 if (ScreenBuffer
->ShowY
> Size
.Y
- Console
->Size
.Y
)
1690 ScreenBuffer
->ShowY
= Size
.Y
- Console
->Size
.Y
;
1692 /* TODO: Should update scrollbar, but can't use anything that
1693 * calls SendMessage or it could cause deadlock */
1695 return STATUS_SUCCESS
;
1699 GuiApplyUserSettings(PCSRSS_CONSOLE Console
, PGUI_CONSOLE_DATA GuiData
, PConsoleInfo pConInfo
)
1702 PCSRSS_SCREEN_BUFFER ActiveBuffer
= Console
->ActiveBuffer
;
1704 BOOL SizeChanged
= FALSE
;
1706 EnterCriticalSection(&Console
->Lock
);
1708 /* apply text / background color */
1709 GuiData
->ScreenText
= pConInfo
->ScreenText
;
1710 GuiData
->ScreenBackground
= pConInfo
->ScreenBackground
;
1712 /* apply cursor size */
1713 ActiveBuffer
->CursorInfo
.dwSize
= min(max(pConInfo
->CursorSize
, 1), 100);
1715 windx
= LOWORD(pConInfo
->WindowSize
);
1716 windy
= HIWORD(pConInfo
->WindowSize
);
1718 if (windx
!= Console
->Size
.X
|| windy
!= Console
->Size
.Y
)
1721 Console
->Size
.X
= windx
;
1722 Console
->Size
.Y
= windy
;
1726 BufSize
.X
= LOWORD(pConInfo
->ScreenBuffer
);
1727 BufSize
.Y
= HIWORD(pConInfo
->ScreenBuffer
);
1728 if (BufSize
.X
!= ActiveBuffer
->MaxX
|| BufSize
.Y
!= ActiveBuffer
->MaxY
)
1730 if (NT_SUCCESS(GuiResizeBuffer(Console
, ActiveBuffer
, BufSize
)))
1736 GuiData
->WindowSizeLock
= TRUE
;
1737 GuiConsoleInitScrollbar(Console
, pConInfo
->hConsoleWindow
);
1738 GuiData
->WindowSizeLock
= FALSE
;
1741 LeaveCriticalSection(&Console
->Lock
);
1742 InvalidateRect(pConInfo
->hConsoleWindow
, NULL
, TRUE
);
1747 GuiConsoleHandleScroll(HWND hwnd
, UINT uMsg
, WPARAM wParam
)
1749 PCSRSS_CONSOLE Console
;
1750 PCSRSS_SCREEN_BUFFER Buff
;
1751 PGUI_CONSOLE_DATA GuiData
;
1754 int old_pos
, Maximum
;
1757 GuiConsoleGetDataPointers(hwnd
, &Console
, &GuiData
);
1758 if (Console
== NULL
|| GuiData
== NULL
)
1760 Buff
= Console
->ActiveBuffer
;
1762 if (uMsg
== WM_HSCROLL
)
1765 Maximum
= Buff
->MaxX
- Console
->Size
.X
;
1766 pShowXY
= &Buff
->ShowX
;
1771 Maximum
= Buff
->MaxY
- Console
->Size
.Y
;
1772 pShowXY
= &Buff
->ShowY
;
1775 /* set scrollbar sizes */
1776 sInfo
.cbSize
= sizeof(SCROLLINFO
);
1777 sInfo
.fMask
= SIF_RANGE
| SIF_POS
| SIF_PAGE
| SIF_TRACKPOS
;
1779 if (!GetScrollInfo(hwnd
, fnBar
, &sInfo
))
1784 old_pos
= sInfo
.nPos
;
1786 switch(LOWORD(wParam
))
1797 sInfo
.nPos
-= sInfo
.nPage
;
1801 sInfo
.nPos
+= sInfo
.nPage
;
1805 sInfo
.nPos
= sInfo
.nTrackPos
;
1809 sInfo
.nPos
= sInfo
.nMin
;
1813 sInfo
.nPos
= sInfo
.nMax
;
1820 sInfo
.nPos
= max(sInfo
.nPos
, 0);
1821 sInfo
.nPos
= min(sInfo
.nPos
, Maximum
);
1823 if (old_pos
!= sInfo
.nPos
)
1825 USHORT OldX
= Buff
->ShowX
;
1826 USHORT OldY
= Buff
->ShowY
;
1827 *pShowXY
= sInfo
.nPos
;
1829 ScrollWindowEx(hwnd
,
1830 (OldX
- Buff
->ShowX
) * GuiData
->CharWidth
,
1831 (OldY
- Buff
->ShowY
) * GuiData
->CharHeight
,
1838 sInfo
.fMask
= SIF_POS
;
1839 SetScrollInfo(hwnd
, fnBar
, &sInfo
, TRUE
);
1846 static LRESULT CALLBACK
1847 GuiConsoleWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1850 PGUI_CONSOLE_DATA GuiData
= NULL
;
1851 PCSRSS_CONSOLE Console
= NULL
;
1853 GuiConsoleGetDataPointers(hWnd
, &Console
, &GuiData
);
1858 Result
= (LRESULT
) GuiConsoleHandleNcCreate(hWnd
, (CREATESTRUCTW
*) lParam
);
1861 GuiConsoleHandlePaint(hWnd
, (HDC
)wParam
);
1868 GuiConsoleHandleKey(hWnd
, msg
, wParam
, lParam
);
1871 GuiConsoleHandleTimer(hWnd
);
1874 GuiConsoleHandleClose(hWnd
);
1877 GuiConsoleHandleNcDestroy(hWnd
);
1879 case WM_LBUTTONDOWN
:
1880 GuiConsoleLeftMouseDown(hWnd
, lParam
);
1883 GuiConsoleLeftMouseUp(hWnd
, lParam
);
1885 case WM_RBUTTONDOWN
:
1886 GuiConsoleRightMouseDown(hWnd
);
1889 GuiConsoleMouseMove(hWnd
, wParam
, lParam
);
1892 Result
= GuiConsoleHandleSysMenuCommand(hWnd
, wParam
, lParam
, GuiData
);
1896 Result
= GuiConsoleHandleScroll(hWnd
, msg
, wParam
);
1898 case WM_GETMINMAXINFO
:
1899 GuiConsoleGetMinMaxInfo(hWnd
, (PMINMAXINFO
)lParam
);
1902 GuiConsoleResize(hWnd
, wParam
, lParam
);
1904 case PM_APPLY_CONSOLE_INFO
:
1905 GuiApplyUserSettings(Console
, GuiData
, (PConsoleInfo
)wParam
);
1908 GuiConsoleWriteUserSettings(Console
, GuiData
);
1912 Result
= DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
1919 static LRESULT CALLBACK
1920 GuiConsoleNotifyWndProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1925 PWCHAR Buffer
, Title
;
1926 PCSRSS_CONSOLE Console
= (PCSRSS_CONSOLE
) lParam
;
1933 SetWindowLongW(hWnd
, GWL_USERDATA
, 0);
1935 case PM_CREATE_CONSOLE
:
1936 Buffer
= HeapAlloc(Win32CsrApiHeap
, 0,
1937 Console
->Title
.Length
+ sizeof(WCHAR
));
1940 memcpy(Buffer
, Console
->Title
.Buffer
, Console
->Title
.Length
);
1941 Buffer
[Console
->Title
.Length
/ sizeof(WCHAR
)] = L
'\0';
1948 NewWindow
= CreateWindowExW(WS_EX_CLIENTEDGE
,
1949 L
"ConsoleWindowClass",
1951 WS_OVERLAPPEDWINDOW
| WS_HSCROLL
| WS_VSCROLL
,
1958 (HINSTANCE
) GetModuleHandleW(NULL
),
1962 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
1964 if (NULL
!= NewWindow
)
1966 SetWindowLongW(hWnd
, GWL_USERDATA
, GetWindowLongW(hWnd
, GWL_USERDATA
) + 1);
1969 ShowWindow(NewWindow
, SW_SHOW
);
1972 return (LRESULT
) NewWindow
;
1973 case PM_DESTROY_CONSOLE
:
1974 /* Window creation is done using a PostMessage(), so it's possible that the
1975 * window that we want to destroy doesn't exist yet. So first empty the message
1977 while(PeekMessageW(&Msg
, NULL
, 0, 0, PM_REMOVE
))
1979 TranslateMessage(&Msg
);
1980 DispatchMessageW(&Msg
);
1982 DestroyWindow(Console
->hWindow
);
1983 Console
->hWindow
= NULL
;
1984 WindowCount
= GetWindowLongW(hWnd
, GWL_USERDATA
);
1986 SetWindowLongW(hWnd
, GWL_USERDATA
, WindowCount
);
1987 if (0 == WindowCount
)
1990 DestroyWindow(hWnd
);
1991 PrivateCsrssManualGuiCheck(-1);
1996 return DefWindowProcW(hWnd
, msg
, wParam
, lParam
);
2001 GuiConsoleGuiThread(PVOID Data
)
2004 PHANDLE GraphicsStartupEvent
= (PHANDLE
) Data
;
2006 NotifyWnd
= CreateWindowW(L
"Win32CsrCreateNotify",
2008 WS_OVERLAPPEDWINDOW
,
2015 (HINSTANCE
) GetModuleHandleW(NULL
),
2017 if (NULL
== NotifyWnd
)
2019 PrivateCsrssManualGuiCheck(-1);
2020 SetEvent(*GraphicsStartupEvent
);
2024 SetEvent(*GraphicsStartupEvent
);
2026 while(GetMessageW(&msg
, NULL
, 0, 0))
2028 TranslateMessage(&msg
);
2029 DispatchMessageW(&msg
);
2040 if (NULL
== NotifyWnd
)
2042 PrivateCsrssManualGuiCheck(+1);
2045 wc
.cbSize
= sizeof(WNDCLASSEXW
);
2046 wc
.lpszClassName
= L
"Win32CsrCreateNotify";
2047 wc
.lpfnWndProc
= GuiConsoleNotifyWndProc
;
2049 wc
.hInstance
= (HINSTANCE
) GetModuleHandleW(NULL
);
2052 wc
.hbrBackground
= NULL
;
2053 wc
.lpszMenuName
= NULL
;
2057 if (RegisterClassExW(&wc
) == 0)
2059 DPRINT1("Failed to register notify wndproc\n");
2063 wc
.cbSize
= sizeof(WNDCLASSEXW
);
2064 wc
.lpszClassName
= L
"ConsoleWindowClass";
2065 wc
.lpfnWndProc
= GuiConsoleWndProc
;
2067 wc
.hInstance
= (HINSTANCE
) GetModuleHandleW(NULL
);
2068 wc
.hIcon
= LoadIconW(GetModuleHandleW(L
"win32csr"), MAKEINTRESOURCEW(1));
2069 wc
.hCursor
= LoadCursorW(NULL
, (LPCWSTR
) IDC_ARROW
);
2070 wc
.hbrBackground
= CreateSolidBrush(RGB(0,0,0));
2071 wc
.lpszMenuName
= NULL
;
2074 wc
.hIconSm
= LoadImageW(GetModuleHandleW(L
"win32csr"), MAKEINTRESOURCEW(1), IMAGE_ICON
,
2075 GetSystemMetrics(SM_CXSMICON
), GetSystemMetrics(SM_CYSMICON
),
2077 if (RegisterClassExW(&wc
) == 0)
2079 DPRINT1("Failed to register console wndproc\n");
2087 GuiInitScreenBuffer(PCSRSS_CONSOLE Console
, PCSRSS_SCREEN_BUFFER Buffer
)
2089 Buffer
->DefaultAttrib
= DEFAULT_ATTRIB
;
2093 GuiChangeTitle(PCSRSS_CONSOLE Console
)
2095 PWCHAR Buffer
, Title
;
2097 Buffer
= HeapAlloc(Win32CsrApiHeap
, 0,
2098 Console
->Title
.Length
+ sizeof(WCHAR
));
2101 memcpy(Buffer
, Console
->Title
.Buffer
, Console
->Title
.Length
);
2102 Buffer
[Console
->Title
.Length
/ sizeof(WCHAR
)] = L
'\0';
2110 SendMessageW(Console
->hWindow
, WM_SETTEXT
, 0, (LPARAM
) Title
);
2114 HeapFree(Win32CsrApiHeap
, 0, Buffer
);
2121 GuiChangeIcon(PCSRSS_CONSOLE Console
, HICON hWindowIcon
)
2123 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_BIG
, (LPARAM
)hWindowIcon
);
2124 SendMessageW(Console
->hWindow
, WM_SETICON
, ICON_SMALL
, (LPARAM
)hWindowIcon
);
2130 GuiCleanupConsole(PCSRSS_CONSOLE Console
)
2132 SendMessageW(NotifyWnd
, PM_DESTROY_CONSOLE
, 0, (LPARAM
) Console
);
2135 static CSRSS_CONSOLE_VTBL GuiVtbl
=
2137 GuiInitScreenBuffer
,
2142 GuiUpdateScreenInfo
,
2150 GuiInitConsole(PCSRSS_CONSOLE Console
, BOOL Visible
)
2152 HANDLE GraphicsStartupEvent
;
2153 HANDLE ThreadHandle
;
2154 PGUI_CONSOLE_DATA GuiData
;
2156 if (! ConsInitialized
)
2158 ConsInitialized
= TRUE
;
2161 ConsInitialized
= FALSE
;
2162 return STATUS_UNSUCCESSFUL
;
2166 Console
->Vtbl
= &GuiVtbl
;
2167 if (NULL
== NotifyWnd
)
2169 GraphicsStartupEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2170 if (NULL
== GraphicsStartupEvent
)
2172 return STATUS_UNSUCCESSFUL
;
2175 ThreadHandle
= CreateThread(NULL
,
2177 GuiConsoleGuiThread
,
2178 (PVOID
) &GraphicsStartupEvent
,
2181 if (NULL
== ThreadHandle
)
2183 NtClose(GraphicsStartupEvent
);
2184 DPRINT1("Win32Csr: Failed to create graphics console thread. Expect problems\n");
2185 return STATUS_UNSUCCESSFUL
;
2187 SetThreadPriority(ThreadHandle
, THREAD_PRIORITY_HIGHEST
);
2188 CloseHandle(ThreadHandle
);
2190 WaitForSingleObject(GraphicsStartupEvent
, INFINITE
);
2191 CloseHandle(GraphicsStartupEvent
);
2193 if (NULL
== NotifyWnd
)
2195 DPRINT1("Win32Csr: Failed to create notification window.\n");
2196 return STATUS_UNSUCCESSFUL
;
2199 GuiData
= HeapAlloc(Win32CsrApiHeap
, HEAP_ZERO_MEMORY
,
2200 sizeof(GUI_CONSOLE_DATA
));
2203 DPRINT1("Win32Csr: Failed to create GUI_CONSOLE_DATA\n");
2204 return STATUS_UNSUCCESSFUL
;
2207 Console
->PrivateData
= (PVOID
) GuiData
;
2209 * we need to wait untill the GUI has been fully initialized
2210 * to retrieve custom settings i.e. WindowSize etc..
2211 * Ideally we could use SendNotifyMessage for this but its not
2215 GuiData
->hGuiInitEvent
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2216 /* create console */
2217 PostMessageW(NotifyWnd
, PM_CREATE_CONSOLE
, Visible
, (LPARAM
) Console
);
2219 /* wait untill initialization has finished */
2220 WaitForSingleObject(GuiData
->hGuiInitEvent
, INFINITE
);
2221 DPRINT("received event Console %p GuiData %p X %d Y %d\n", Console
, Console
->PrivateData
, Console
->Size
.X
, Console
->Size
.Y
);
2222 CloseHandle(GuiData
->hGuiInitEvent
);
2223 GuiData
->hGuiInitEvent
= NULL
;
2225 return STATUS_SUCCESS
;