ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

guiconsole.c
Go to the documentation of this file.
00001 /* $Id: guiconsole.c 55620 2012-02-15 22:15:33Z ion $
00002  *
00003  * COPYRIGHT:       See COPYING in the top level directory
00004  * PROJECT:         ReactOS system libraries
00005  * FILE:            subsys/csrss/win32csr/guiconsole.c
00006  * PURPOSE:         Implementation of gui-mode consoles
00007  */
00008 
00009 /* INCLUDES ******************************************************************/
00010 
00011 #define NDEBUG
00012 #include "w32csr.h"
00013 #include <debug.h>
00014 
00015 /* Not defined in any header file */
00016 extern VOID WINAPI PrivateCsrssManualGuiCheck(LONG Check);
00017 
00018 /* GLOBALS *******************************************************************/
00019 
00020 typedef struct GUI_CONSOLE_DATA_TAG
00021 {
00022     HFONT Font;
00023     unsigned CharWidth;
00024     unsigned CharHeight;
00025     BOOL CursorBlinkOn;
00026     BOOL ForceCursorOff;
00027     CRITICAL_SECTION Lock;
00028     HMODULE ConsoleLibrary;
00029     HANDLE hGuiInitEvent;
00030     WCHAR FontName[LF_FACESIZE];
00031     DWORD FontSize;
00032     DWORD FontWeight;
00033     DWORD FullScreen;
00034     DWORD QuickEdit;
00035     DWORD InsertMode;
00036     DWORD WindowPosition;
00037     DWORD UseRasterFonts;
00038     COLORREF ScreenText;
00039     COLORREF ScreenBackground;
00040     COLORREF PopupBackground;
00041     COLORREF PopupText;
00042     COLORREF Colors[16];
00043     WCHAR szProcessName[MAX_PATH];
00044     BOOL WindowSizeLock;
00045     POINT OldCursor;
00046 } GUI_CONSOLE_DATA, *PGUI_CONSOLE_DATA;
00047 
00048 #ifndef WM_APP
00049 #define WM_APP 0x8000
00050 #endif
00051 #define PM_CREATE_CONSOLE  (WM_APP + 1)
00052 #define PM_DESTROY_CONSOLE (WM_APP + 2)
00053 
00054 #define CURSOR_BLINK_TIME 500
00055 #define DEFAULT_ATTRIB (FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED)
00056 
00057 static BOOL ConsInitialized = FALSE;
00058 static HWND NotifyWnd;
00059 
00060 typedef struct _GUICONSOLE_MENUITEM
00061 {
00062     UINT uID;
00063     const struct _GUICONSOLE_MENUITEM *SubMenu;
00064     WORD wCmdID;
00065 } GUICONSOLE_MENUITEM, *PGUICONSOLE_MENUITEM;
00066 
00067 static const GUICONSOLE_MENUITEM GuiConsoleEditMenuItems[] =
00068 {
00069     { IDS_MARK, NULL, ID_SYSTEM_EDIT_MARK },
00070     { IDS_COPY, NULL, ID_SYSTEM_EDIT_COPY },
00071     { IDS_PASTE, NULL, ID_SYSTEM_EDIT_PASTE },
00072     { IDS_SELECTALL, NULL, ID_SYSTEM_EDIT_SELECTALL },
00073     { IDS_SCROLL, NULL, ID_SYSTEM_EDIT_SCROLL },
00074     { IDS_FIND, NULL, ID_SYSTEM_EDIT_FIND },
00075 
00076     { 0, NULL, 0 } /* End of list */
00077 };
00078 
00079 static const GUICONSOLE_MENUITEM GuiConsoleMainMenuItems[] =
00080 {
00081     { (UINT)-1, NULL, 0 }, /* Separator */
00082     { IDS_EDIT, GuiConsoleEditMenuItems, 0 },
00083     { IDS_DEFAULTS, NULL, ID_SYSTEM_DEFAULTS },
00084     { IDS_PROPERTIES, NULL, ID_SYSTEM_PROPERTIES },
00085 
00086     { 0, NULL, 0 } /* End of list */
00087 };
00088 
00089 static const COLORREF s_Colors[] =
00090 {
00091     RGB(0, 0, 0),
00092     RGB(0, 0, 128),
00093     RGB(0, 128, 0),
00094     RGB(0, 128, 128),
00095     RGB(128, 0, 0),
00096     RGB(128, 0, 128),
00097     RGB(128, 128, 0),
00098     RGB(192, 192, 192),
00099     RGB(128, 128, 128),
00100     RGB(0, 0, 255),
00101     RGB(0, 255, 0),
00102     RGB(0, 255, 255),
00103     RGB(255, 0, 0),
00104     RGB(255, 0, 255),
00105     RGB(255, 255, 0),
00106     RGB(255, 255, 255)
00107 };
00108 
00109 #define GuiConsoleRGBFromAttribute(GuiData, Attribute) ((GuiData)->Colors[(Attribute) & 0xF])
00110 
00111 /* FUNCTIONS *****************************************************************/
00112 
00113 static VOID
00114 GuiConsoleAppendMenuItems(HMENU hMenu,
00115                           const GUICONSOLE_MENUITEM *Items)
00116 {
00117     UINT i = 0;
00118     WCHAR szMenuString[255];
00119     HMENU hSubMenu;
00120     HINSTANCE hInst = GetModuleHandleW(L"win32csr");
00121 
00122     do
00123     {
00124         if (Items[i].uID != (UINT)-1)
00125         {
00126             if (LoadStringW(hInst,
00127                             Items[i].uID,
00128                             szMenuString,
00129                             sizeof(szMenuString) / sizeof(szMenuString[0])) > 0)
00130             {
00131                 if (Items[i].SubMenu != NULL)
00132                 {
00133                     hSubMenu = CreatePopupMenu();
00134                     if (hSubMenu != NULL)
00135                     {
00136                         GuiConsoleAppendMenuItems(hSubMenu,
00137                                                   Items[i].SubMenu);
00138 
00139                         if (!AppendMenuW(hMenu,
00140                                          MF_STRING | MF_POPUP,
00141                                          (UINT_PTR)hSubMenu,
00142                                          szMenuString))
00143                         {
00144                             DestroyMenu(hSubMenu);
00145                         }
00146                     }
00147                 }
00148                 else
00149                 {
00150                     AppendMenuW(hMenu,
00151                                 MF_STRING,
00152                                 Items[i].wCmdID,
00153                                 szMenuString);
00154                 }
00155             }
00156         }
00157         else
00158         {
00159             AppendMenuW(hMenu,
00160                         MF_SEPARATOR,
00161                         0,
00162                         NULL);
00163         }
00164         i++;
00165     } while(!(Items[i].uID == 0 && Items[i].SubMenu == NULL && Items[i].wCmdID == 0));
00166 }
00167 
00168 static VOID
00169 GuiConsoleCreateSysMenu(PCSRSS_CONSOLE Console)
00170 {
00171     HMENU hMenu;
00172     hMenu = GetSystemMenu(Console->hWindow,
00173                           FALSE);
00174     if (hMenu != NULL)
00175     {
00176         GuiConsoleAppendMenuItems(hMenu,
00177                                   GuiConsoleMainMenuItems);
00178         DrawMenuBar(Console->hWindow);
00179     }
00180 }
00181 
00182 static VOID
00183 GuiConsoleGetDataPointers(HWND hWnd, PCSRSS_CONSOLE *Console, PGUI_CONSOLE_DATA *GuiData)
00184 {
00185     *Console = (PCSRSS_CONSOLE) GetWindowLongPtrW(hWnd, GWL_USERDATA);
00186     *GuiData = (NULL == *Console ? NULL : (*Console)->PrivateData);
00187 }
00188 
00189 static BOOL
00190 GuiConsoleOpenUserRegistryPathPerProcessId(DWORD ProcessId, PHANDLE hProcHandle, PHKEY hResult, REGSAM samDesired)
00191 {
00192     HANDLE hProcessToken = NULL;
00193     HANDLE hProcess;
00194 
00195     BYTE Buffer[256];
00196     DWORD Length = 0;
00197     UNICODE_STRING SidName;
00198     LONG res;
00199     PTOKEN_USER TokUser;
00200 
00201     hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | READ_CONTROL, FALSE, ProcessId);
00202     if (!hProcess)
00203     {
00204         DPRINT("Error: OpenProcess failed(0x%x)\n", GetLastError());
00205         return FALSE;
00206     }
00207 
00208     if (!OpenProcessToken(hProcess, TOKEN_QUERY, &hProcessToken))
00209     {
00210         DPRINT("Error: OpenProcessToken failed(0x%x)\n", GetLastError());
00211         CloseHandle(hProcess);
00212         return FALSE;
00213     }
00214 
00215     if (!GetTokenInformation(hProcessToken, TokenUser, (PVOID)Buffer, sizeof(Buffer), &Length))
00216     {
00217         DPRINT("Error: GetTokenInformation failed(0x%x)\n",GetLastError());
00218         CloseHandle(hProcessToken);
00219         CloseHandle(hProcess);
00220         return FALSE;
00221     }
00222 
00223     TokUser = ((PTOKEN_USER)Buffer)->User.Sid;
00224     if (!NT_SUCCESS(RtlConvertSidToUnicodeString(&SidName, TokUser, TRUE)))
00225     {
00226         DPRINT("Error: RtlConvertSidToUnicodeString failed(0x%x)\n", GetLastError());
00227         CloseHandle(hProcessToken);
00228         CloseHandle(hProcess);
00229         return FALSE;
00230     }
00231 
00232     res = RegOpenKeyExW(HKEY_USERS, SidName.Buffer, 0, samDesired, hResult);
00233     RtlFreeUnicodeString(&SidName);
00234 
00235     CloseHandle(hProcessToken);
00236     if (res != ERROR_SUCCESS)
00237     {
00238         CloseHandle(hProcess);
00239         return FALSE;
00240     }
00241 
00242     if (hProcHandle)
00243         *hProcHandle = hProcess;
00244     else
00245         CloseHandle(hProcess);
00246 
00247     return TRUE;
00248 }
00249 
00250 static BOOL
00251 GuiConsoleOpenUserSettings(PGUI_CONSOLE_DATA GuiData, DWORD ProcessId, PHKEY hSubKey, REGSAM samDesired, BOOL bCreate)
00252 {
00253     WCHAR szProcessName[MAX_PATH];
00254     WCHAR szBuffer[MAX_PATH];
00255     UINT fLength, wLength;
00256     DWORD dwBitmask, dwLength;
00257     WCHAR CurDrive[] = { 'A',':', 0 };
00258     HANDLE hProcess;
00259     HKEY hKey;
00260     WCHAR * ptr;
00261 
00262     /*
00263      * console properties are stored under
00264      * HKCU\Console\*
00265      *
00266      * There are 3 ways to store console properties
00267      *
00268      *  1. use console title as subkey name
00269      *    i.e. cmd.exe
00270      *
00271      *  2. use application name as subkey name
00272      *
00273      *  3. use unexpanded path to console application.
00274      *     i.e. %SystemRoot%_system32_cmd.exe
00275      */
00276 
00277     DPRINT("GuiConsoleOpenUserSettings entered\n");
00278 
00279     if (!GuiConsoleOpenUserRegistryPathPerProcessId(ProcessId, &hProcess, &hKey, samDesired))
00280     {
00281         DPRINT("GuiConsoleOpenUserRegistryPathPerProcessId failed\n");
00282         return FALSE;
00283     }
00284 
00285     /* FIXME we do not getting the process name so no menu will be loading, why ?*/
00286     fLength = GetProcessImageFileNameW(hProcess, szProcessName, sizeof(GuiData->szProcessName) / sizeof(WCHAR));
00287     CloseHandle(hProcess);
00288 
00289     //DPRINT1("szProcessName3 : %S\n",szProcessName);
00290 
00291     if (!fLength)
00292     {
00293         DPRINT("GetProcessImageFileNameW failed(0x%x)ProcessId %d\n", GetLastError(), ProcessId);
00294         return FALSE;
00295     }
00296     /*
00297      * try the process name as path
00298      */
00299 
00300     ptr = wcsrchr(szProcessName, L'\\');
00301     wcscpy(GuiData->szProcessName, ptr);
00302 
00303     swprintf(szBuffer, L"Console%s",ptr);
00304     DPRINT("#1 Path : %S\n", szBuffer);
00305 
00306     if (bCreate)
00307     {
00308         if (RegCreateKeyW(hKey, szBuffer, hSubKey) == ERROR_SUCCESS)
00309         {
00310             RegCloseKey(hKey);
00311             return TRUE;
00312         }
00313         RegCloseKey(hKey);
00314         return FALSE;
00315     }
00316 
00317     if (RegOpenKeyExW(hKey, szBuffer, 0, samDesired, hSubKey) == ERROR_SUCCESS)
00318     {
00319         RegCloseKey(hKey);
00320         return TRUE;
00321     }
00322 
00323     /*
00324      * try the "Shortcut to processname" as path
00325      * FIXME: detect wheter the process was started as a shortcut
00326      */
00327 
00328     swprintf(szBuffer, L"Console\\Shortcut to %S", ptr);
00329     DPRINT("#2 Path : %S\n", szBuffer);
00330     if (RegOpenKeyExW(hKey, szBuffer, 0, samDesired, hSubKey) == ERROR_SUCCESS)
00331     {
00332         swprintf(GuiData->szProcessName, L"Shortcut to %S", ptr);
00333         RegCloseKey(hKey);
00334         return TRUE;
00335     }
00336 
00337     /*
00338      * if the path contains \\Device\\HarddiskVolume1\... remove it
00339      */
00340 
00341     if (szProcessName[0] == L'\\')
00342     {
00343         dwBitmask = GetLogicalDrives();
00344         while(dwBitmask)
00345         {
00346             if (dwBitmask & 0x1)
00347             {
00348                 dwLength = QueryDosDeviceW(CurDrive, szBuffer, MAX_PATH);
00349                 if (dwLength)
00350                 {
00351                     if (!memcmp(szBuffer, szProcessName, (dwLength-2)*sizeof(WCHAR)))
00352                     {
00353                         wcscpy(szProcessName, CurDrive);
00354                         RtlMoveMemory(&szProcessName[2], &szProcessName[dwLength-1], fLength - dwLength -1);
00355                         break;
00356                     }
00357                 }
00358             }
00359             dwBitmask = (dwBitmask >> 1);
00360             CurDrive[0]++;
00361         }
00362     }
00363 
00364     /*
00365      * last attempt: check whether the file is under %SystemRoot%
00366      * and use path like Console\%SystemRoot%_dir_dir2_file.exe
00367      */
00368 
00369     wLength = GetWindowsDirectoryW(szBuffer, MAX_PATH);
00370     if (wLength)
00371     {
00372         if (!wcsncmp(szProcessName, szBuffer, wLength))
00373         {
00374             /* replace slashes by underscores */
00375             while((ptr = wcschr(szProcessName, L'\\')))
00376                 ptr[0] = L'_';
00377 
00378             swprintf(szBuffer, L"Console\\%%SystemRoot%%%S", &szProcessName[wLength]);
00379             DPRINT("#3 Path : %S\n", szBuffer);
00380             if (RegOpenKeyExW(hKey, szBuffer, 0, samDesired, hSubKey) == ERROR_SUCCESS)
00381             {
00382                 swprintf(GuiData->szProcessName, L"%%SystemRoot%%%S", &szProcessName[wLength]);
00383                 RegCloseKey(hKey);
00384                 return TRUE;
00385             }
00386         }
00387     }
00388     RegCloseKey(hKey);
00389     return FALSE;
00390 }
00391 
00392 static VOID
00393 GuiConsoleWriteUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData)
00394 {
00395     HKEY hKey;
00396     PCSR_PROCESS ProcessData;
00397 
00398     if (Console->ProcessList.Flink == &Console->ProcessList)
00399     {
00400         DPRINT("GuiConsoleWriteUserSettings: No Process!!!\n");
00401         return;
00402     }
00403     ProcessData = CONTAINING_RECORD(Console->ProcessList.Flink, CSR_PROCESS, ConsoleLink);
00404     if (!GuiConsoleOpenUserSettings(GuiData, PtrToUlong(ProcessData->ClientId.UniqueProcess), &hKey, KEY_READ | KEY_WRITE, TRUE))
00405     {
00406         return;
00407     }
00408 
00409     if (Console->ActiveBuffer->CursorInfo.dwSize <= 1)
00410     {
00411         RegDeleteKeyW(hKey, L"CursorSize");
00412     }
00413     else
00414     {
00415         RegSetValueExW(hKey, L"CursorSize", 0, REG_DWORD, (const BYTE *)&Console->ActiveBuffer->CursorInfo.dwSize, sizeof(DWORD));
00416     }
00417 
00418     if (Console->NumberOfHistoryBuffers == 5)
00419     {
00420         RegDeleteKeyW(hKey, L"NumberOfHistoryBuffers");
00421     }
00422     else
00423     {
00424         DWORD Temp = Console->NumberOfHistoryBuffers;
00425         RegSetValueExW(hKey, L"NumberOfHistoryBuffers", 0, REG_DWORD, (const BYTE *)&Temp, sizeof(DWORD));
00426     }
00427 
00428     if (Console->HistoryBufferSize == 50)
00429     {
00430         RegDeleteKeyW(hKey, L"HistoryBufferSize");
00431     }
00432     else
00433     {
00434         DWORD Temp = Console->HistoryBufferSize;
00435         RegSetValueExW(hKey, L"HistoryBufferSize", 0, REG_DWORD, (const BYTE *)&Temp, sizeof(DWORD));
00436     }
00437 
00438     if (GuiData->FullScreen == FALSE)
00439     {
00440         RegDeleteKeyW(hKey, L"FullScreen");
00441     }
00442     else
00443     {
00444         RegSetValueExW(hKey, L"FullScreen", 0, REG_DWORD, (const BYTE *)&GuiData->FullScreen, sizeof(DWORD));
00445     }
00446 
00447     if ( GuiData->QuickEdit == FALSE)
00448     {
00449         RegDeleteKeyW(hKey, L"QuickEdit");
00450     }
00451     else
00452     {
00453         RegSetValueExW(hKey, L"QuickEdit", 0, REG_DWORD, (const BYTE *)&GuiData->QuickEdit, sizeof(DWORD));
00454     }
00455 
00456     if (GuiData->InsertMode == TRUE)
00457     {
00458         RegDeleteKeyW(hKey, L"InsertMode");
00459     }
00460     else
00461     {
00462         RegSetValueExW(hKey, L"InsertMode", 0, REG_DWORD, (const BYTE *)&GuiData->InsertMode, sizeof(DWORD));
00463     }
00464 
00465     if (Console->HistoryNoDup == FALSE)
00466     {
00467         RegDeleteKeyW(hKey, L"HistoryNoDup");
00468     }
00469     else
00470     {
00471         DWORD Temp = Console->HistoryNoDup;
00472         RegSetValueExW(hKey, L"HistoryNoDup", 0, REG_DWORD, (const BYTE *)&Temp, sizeof(DWORD));
00473     }
00474 
00475     if (GuiData->ScreenText == RGB(192, 192, 192))
00476     {
00477         /*
00478          * MS uses console attributes instead of real color
00479          */
00480         RegDeleteKeyW(hKey, L"ScreenText");
00481     }
00482     else
00483     {
00484         RegSetValueExW(hKey, L"ScreenText", 0, REG_DWORD, (const BYTE *)&GuiData->ScreenText, sizeof(COLORREF));
00485     }
00486 
00487     if (GuiData->ScreenBackground == RGB(0, 0, 0))
00488     {
00489         RegDeleteKeyW(hKey, L"ScreenBackground");
00490     }
00491     else
00492     {
00493         RegSetValueExW(hKey, L"ScreenBackground", 0, REG_DWORD, (const BYTE *)&GuiData->ScreenBackground, sizeof(COLORREF));
00494     }
00495 
00496     RegCloseKey(hKey);
00497 }
00498 
00499 static void
00500 GuiConsoleReadUserSettings(HKEY hKey, PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PCSRSS_SCREEN_BUFFER Buffer)
00501 {
00502     DWORD dwNumSubKeys = 0;
00503     DWORD dwIndex;
00504     DWORD dwValueName;
00505     DWORD dwValue;
00506     DWORD dwType;
00507     WCHAR szValueName[MAX_PATH];
00508     WCHAR szValue[LF_FACESIZE] = L"\0";
00509     DWORD Value;
00510 
00511     if (RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwNumSubKeys, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
00512     {
00513         DPRINT("GuiConsoleReadUserSettings: RegQueryInfoKey failed\n");
00514         return;
00515     }
00516 
00517     DPRINT("GuiConsoleReadUserSettings entered dwNumSubKeys %d\n", dwNumSubKeys);
00518 
00519     for (dwIndex = 0; dwIndex < dwNumSubKeys; dwIndex++)
00520     {
00521         dwValue = sizeof(Value);
00522         dwValueName = MAX_PATH;
00523 
00524         if (RegEnumValueW(hKey, dwIndex, szValueName, &dwValueName, NULL, &dwType, (BYTE*)&Value, &dwValue) != ERROR_SUCCESS)
00525         {
00526             if (dwType == REG_SZ)
00527             {
00528                 /*
00529                  * retry in case of string value
00530                  */
00531                 dwValue = sizeof(szValue);
00532                 dwValueName = LF_FACESIZE;
00533                 if (RegEnumValueW(hKey, dwIndex, szValueName, &dwValueName, NULL, NULL, (BYTE*)szValue, &dwValue) != ERROR_SUCCESS)
00534                     break;
00535             }
00536             else
00537                 break;
00538         }
00539         if (!wcscmp(szValueName, L"CursorSize"))
00540         {
00541             if (Value == 0x32)
00542             {
00543                 Buffer->CursorInfo.dwSize = Value;
00544             }
00545             else if (Value == 0x64)
00546             {
00547                 Buffer->CursorInfo.dwSize = Value;
00548             }
00549         }
00550         else if (!wcscmp(szValueName, L"ScreenText"))
00551         {
00552             GuiData->ScreenText = Value;
00553         }
00554         else if (!wcscmp(szValueName, L"ScreenBackground"))
00555         {
00556             GuiData->ScreenBackground = Value;
00557         }
00558         else if (!wcscmp(szValueName, L"FaceName"))
00559         {
00560             wcscpy(GuiData->FontName, szValue);
00561         }
00562         else if (!wcscmp(szValueName, L"FontSize"))
00563         {
00564             GuiData->FontSize = Value;
00565         }
00566         else if (!wcscmp(szValueName, L"FontWeight"))
00567         {
00568             GuiData->FontWeight = Value;
00569         }
00570         else if (!wcscmp(szValueName, L"HistoryNoDup"))
00571         {
00572             Console->HistoryNoDup = Value;
00573         }
00574         else if (!wcscmp(szValueName, L"WindowSize"))
00575         {
00576             Console->Size.X = LOWORD(Value);
00577             Console->Size.Y = HIWORD(Value);
00578         }
00579         else if (!wcscmp(szValueName, L"ScreenBufferSize"))
00580         {
00581             if(Buffer)
00582             {
00583                 Buffer->MaxX = LOWORD(Value);
00584                 Buffer->MaxY = HIWORD(Value);
00585             }
00586         }
00587         else if (!wcscmp(szValueName, L"FullScreen"))
00588         {
00589             GuiData->FullScreen = Value;
00590         }
00591         else if (!wcscmp(szValueName, L"QuickEdit"))
00592         {
00593             GuiData->QuickEdit = Value;
00594         }
00595         else if (!wcscmp(szValueName, L"InsertMode"))
00596         {
00597             GuiData->InsertMode = Value;
00598         }
00599     }
00600 }
00601 static VOID
00602 GuiConsoleUseDefaults(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PCSRSS_SCREEN_BUFFER Buffer)
00603 {
00604     /*
00605      * init guidata with default properties
00606      */
00607 
00608     wcscpy(GuiData->FontName, L"DejaVu Sans Mono");
00609     GuiData->FontSize = 0x0008000C; // font is 8x12
00610     GuiData->FontWeight = FW_NORMAL;
00611     GuiData->FullScreen = FALSE;
00612     GuiData->QuickEdit = FALSE;
00613     GuiData->InsertMode = TRUE;
00614     GuiData->ScreenText = RGB(192, 192, 192);
00615     GuiData->ScreenBackground = RGB(0, 0, 0);
00616     GuiData->PopupText = RGB(128, 0, 128);
00617     GuiData->PopupBackground = RGB(255, 255, 255);
00618     GuiData->WindowPosition = UINT_MAX;
00619     GuiData->UseRasterFonts = TRUE;
00620     memcpy(GuiData->Colors, s_Colors, sizeof(s_Colors));
00621 
00622     Console->HistoryBufferSize = 50;
00623     Console->NumberOfHistoryBuffers = 5;
00624     Console->HistoryNoDup = FALSE;
00625     Console->Size.X = 80;
00626     Console->Size.Y = 25;
00627 
00628     if (Buffer)
00629     {
00630         Buffer->MaxX = 80;
00631         Buffer->MaxY = 300;
00632         Buffer->CursorInfo.bVisible = TRUE;
00633         Buffer->CursorInfo.dwSize = CSR_DEFAULT_CURSOR_SIZE;
00634     }
00635 }
00636 
00637 VOID
00638 FASTCALL
00639 GuiConsoleInitScrollbar(PCSRSS_CONSOLE Console, HWND hwnd)
00640 {
00641     SCROLLINFO sInfo;
00642     PGUI_CONSOLE_DATA GuiData = Console->PrivateData;
00643 
00644     DWORD Width = Console->Size.X * GuiData->CharWidth + 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
00645     DWORD Height = Console->Size.Y * GuiData->CharHeight + 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
00646 
00647     /* set scrollbar sizes */
00648     sInfo.cbSize = sizeof(SCROLLINFO);
00649     sInfo.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
00650     sInfo.nMin = 0;
00651     if (Console->ActiveBuffer->MaxY > Console->Size.Y)
00652     {
00653         sInfo.nMax = Console->ActiveBuffer->MaxY - 1;
00654         sInfo.nPage = Console->Size.Y;
00655         sInfo.nPos = Console->ActiveBuffer->ShowY;
00656         SetScrollInfo(hwnd, SB_VERT, &sInfo, TRUE);
00657         Width += GetSystemMetrics(SM_CXVSCROLL);
00658         ShowScrollBar(hwnd, SB_VERT, TRUE);
00659     }
00660     else
00661     {
00662         ShowScrollBar(hwnd, SB_VERT, FALSE);
00663     }
00664 
00665     if (Console->ActiveBuffer->MaxX > Console->Size.X)
00666     {
00667         sInfo.nMax = Console->ActiveBuffer->MaxX - 1;
00668         sInfo.nPage = Console->Size.X;
00669         sInfo.nPos = Console->ActiveBuffer->ShowX;
00670         SetScrollInfo(hwnd, SB_HORZ, &sInfo, TRUE);
00671         Height += GetSystemMetrics(SM_CYHSCROLL);
00672         ShowScrollBar(hwnd, SB_HORZ, TRUE);
00673 
00674     }
00675     else
00676     {
00677         ShowScrollBar(hwnd, SB_HORZ, FALSE);
00678     }
00679 
00680     SetWindowPos(hwnd, NULL, 0, 0, Width, Height,
00681                  SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
00682 }
00683 
00684 static BOOL
00685 GuiConsoleHandleNcCreate(HWND hWnd, CREATESTRUCTW *Create)
00686 {
00687     PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) Create->lpCreateParams;
00688     PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)Console->PrivateData;
00689     HDC Dc;
00690     HFONT OldFont;
00691     TEXTMETRICW Metrics;
00692     SIZE CharSize;
00693     PCSR_PROCESS ProcessData;
00694     HKEY hKey;
00695 
00696     Console->hWindow = hWnd;
00697 
00698     if (NULL == GuiData)
00699     {
00700         DPRINT1("GuiConsoleNcCreate: HeapAlloc failed\n");
00701         return FALSE;
00702     }
00703 
00704     GuiConsoleUseDefaults(Console, GuiData, Console->ActiveBuffer);
00705     if (Console->ProcessList.Flink != &Console->ProcessList)
00706     {
00707         ProcessData = CONTAINING_RECORD(Console->ProcessList.Flink, CSR_PROCESS, ConsoleLink);
00708         if (GuiConsoleOpenUserSettings(GuiData, PtrToUlong(ProcessData->ClientId.UniqueProcess), &hKey, KEY_READ, FALSE))
00709         {
00710             GuiConsoleReadUserSettings(hKey, Console, GuiData, Console->ActiveBuffer);
00711             RegCloseKey(hKey);
00712         }
00713     }
00714 
00715     InitializeCriticalSection(&GuiData->Lock);
00716 
00717     GuiData->Font = CreateFontW(LOWORD(GuiData->FontSize),
00718                                 0, //HIWORD(GuiData->FontSize),
00719                                 0,
00720                                 TA_BASELINE,
00721                                 GuiData->FontWeight,
00722                                 FALSE,
00723                                 FALSE,
00724                                 FALSE,
00725                                 OEM_CHARSET,
00726                                 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
00727                                 NONANTIALIASED_QUALITY, FIXED_PITCH | FF_DONTCARE,
00728                                 GuiData->FontName);
00729     if (NULL == GuiData->Font)
00730     {
00731         DPRINT1("GuiConsoleNcCreate: CreateFont failed\n");
00732         DeleteCriticalSection(&GuiData->Lock);
00733         HeapFree(Win32CsrApiHeap, 0, GuiData);
00734         return FALSE;
00735     }
00736     Dc = GetDC(hWnd);
00737     if (NULL == Dc)
00738     {
00739         DPRINT1("GuiConsoleNcCreate: GetDC failed\n");
00740         DeleteObject(GuiData->Font);
00741         DeleteCriticalSection(&GuiData->Lock);
00742         HeapFree(Win32CsrApiHeap, 0, GuiData);
00743         return FALSE;
00744     }
00745     OldFont = SelectObject(Dc, GuiData->Font);
00746     if (NULL == OldFont)
00747     {
00748         DPRINT1("GuiConsoleNcCreate: SelectObject failed\n");
00749         ReleaseDC(hWnd, Dc);
00750         DeleteObject(GuiData->Font);
00751         DeleteCriticalSection(&GuiData->Lock);
00752         HeapFree(Win32CsrApiHeap, 0, GuiData);
00753         return FALSE;
00754     }
00755     if (! GetTextMetricsW(Dc, &Metrics))
00756     {
00757         DPRINT1("GuiConsoleNcCreate: GetTextMetrics failed\n");
00758         SelectObject(Dc, OldFont);
00759         ReleaseDC(hWnd, Dc);
00760         DeleteObject(GuiData->Font);
00761         DeleteCriticalSection(&GuiData->Lock);
00762         HeapFree(Win32CsrApiHeap, 0, GuiData);
00763         return FALSE;
00764     }
00765     GuiData->CharWidth = Metrics.tmMaxCharWidth;
00766     GuiData->CharHeight = Metrics.tmHeight + Metrics.tmExternalLeading;
00767 
00768     /* Measure real char width more precisely if possible. */
00769     if (GetTextExtentPoint32W(Dc, L"R", 1, &CharSize))
00770         GuiData->CharWidth = CharSize.cx;
00771 
00772     SelectObject(Dc, OldFont);
00773 
00774     ReleaseDC(hWnd, Dc);
00775     GuiData->CursorBlinkOn = TRUE;
00776     GuiData->ForceCursorOff = FALSE;
00777 
00778     DPRINT("Console %p GuiData %p\n", Console, GuiData);
00779     Console->PrivateData = GuiData;
00780     SetWindowLongPtrW(hWnd, GWL_USERDATA, (DWORD_PTR) Console);
00781 
00782     SetTimer(hWnd, CONGUI_UPDATE_TIMER, CONGUI_UPDATE_TIME, NULL);
00783     GuiConsoleCreateSysMenu(Console);
00784 
00785     GuiData->WindowSizeLock = TRUE;
00786     GuiConsoleInitScrollbar(Console, hWnd);
00787     GuiData->WindowSizeLock = FALSE;
00788 
00789     SetEvent(GuiData->hGuiInitEvent);
00790 
00791     return (BOOL) DefWindowProcW(hWnd, WM_NCCREATE, 0, (LPARAM) Create);
00792 }
00793 
00794 static VOID
00795 SmallRectToRect(PCSRSS_CONSOLE Console, PRECT Rect, PSMALL_RECT SmallRect)
00796 {
00797     PCSRSS_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
00798     PGUI_CONSOLE_DATA GuiData = Console->PrivateData;
00799     Rect->left   = (SmallRect->Left       - Buffer->ShowX) * GuiData->CharWidth;
00800     Rect->top    = (SmallRect->Top        - Buffer->ShowY) * GuiData->CharHeight;
00801     Rect->right  = (SmallRect->Right  + 1 - Buffer->ShowX) * GuiData->CharWidth;
00802     Rect->bottom = (SmallRect->Bottom + 1 - Buffer->ShowY) * GuiData->CharHeight;
00803 }
00804 
00805 static VOID
00806 GuiConsoleUpdateSelection(PCSRSS_CONSOLE Console, PCOORD coord)
00807 {
00808     RECT oldRect, newRect;
00809     HWND hWnd = Console->hWindow;
00810 
00811     SmallRectToRect(Console, &oldRect, &Console->Selection.srSelection);
00812 
00813     if(coord != NULL)
00814     {
00815         SMALL_RECT rc;
00816         /* exchange left/top with right/bottom if required */
00817         rc.Left   = min(Console->Selection.dwSelectionAnchor.X, coord->X);
00818         rc.Top    = min(Console->Selection.dwSelectionAnchor.Y, coord->Y);
00819         rc.Right  = max(Console->Selection.dwSelectionAnchor.X, coord->X);
00820         rc.Bottom = max(Console->Selection.dwSelectionAnchor.Y, coord->Y);
00821 
00822         SmallRectToRect(Console, &newRect, &rc);
00823 
00824         if (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
00825         {
00826             if (memcmp(&rc, &Console->Selection.srSelection, sizeof(SMALL_RECT)) != 0)
00827             {
00828                 HRGN rgn1, rgn2;
00829 
00830                 /* calculate the region that needs to be updated */
00831                 if((rgn1 = CreateRectRgnIndirect(&oldRect)))
00832                 {
00833                     if((rgn2 = CreateRectRgnIndirect(&newRect)))
00834                     {
00835                         if(CombineRgn(rgn1, rgn2, rgn1, RGN_XOR) != ERROR)
00836                         {
00837                             InvalidateRgn(hWnd, rgn1, FALSE);
00838                         }
00839 
00840                         DeleteObject(rgn2);
00841                     }
00842                     DeleteObject(rgn1);
00843                 }
00844             }
00845         }
00846         else
00847         {
00848             InvalidateRect(hWnd, &newRect, FALSE);
00849         }
00850         Console->Selection.dwFlags |= CONSOLE_SELECTION_NOT_EMPTY;
00851         Console->Selection.srSelection = rc;
00852         ConioPause(Console, PAUSED_FROM_SELECTION);
00853     }
00854     else
00855     {
00856         /* clear the selection */
00857         if (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
00858         {
00859             InvalidateRect(hWnd, &oldRect, FALSE);
00860         }
00861         Console->Selection.dwFlags = CONSOLE_NO_SELECTION;
00862         ConioUnpause(Console, PAUSED_FROM_SELECTION);
00863     }
00864 }
00865 
00866 
00867 static VOID
00868 GuiConsolePaint(PCSRSS_CONSOLE Console,
00869                 PGUI_CONSOLE_DATA GuiData,
00870                 HDC hDC,
00871                 PRECT rc)
00872 {
00873     PCSRSS_SCREEN_BUFFER Buff;
00874     ULONG TopLine, BottomLine, LeftChar, RightChar;
00875     ULONG Line, Char, Start;
00876     PBYTE From;
00877     PWCHAR To;
00878     BYTE LastAttribute, Attribute;
00879     ULONG CursorX, CursorY, CursorHeight;
00880     HBRUSH CursorBrush, OldBrush;
00881     HFONT OldFont;
00882 
00883     Buff = Console->ActiveBuffer;
00884 
00885     EnterCriticalSection(&Buff->Header.Console->Lock);
00886 
00887     TopLine = rc->top / GuiData->CharHeight + Buff->ShowY;
00888     BottomLine = (rc->bottom + (GuiData->CharHeight - 1)) / GuiData->CharHeight - 1 + Buff->ShowY;
00889     LeftChar = rc->left / GuiData->CharWidth + Buff->ShowX;
00890     RightChar = (rc->right + (GuiData->CharWidth - 1)) / GuiData->CharWidth - 1 + Buff->ShowX;
00891     LastAttribute = ConioCoordToPointer(Buff, LeftChar, TopLine)[1];
00892 
00893     SetTextColor(hDC, GuiConsoleRGBFromAttribute(GuiData, LastAttribute));
00894     SetBkColor(hDC, GuiConsoleRGBFromAttribute(GuiData, LastAttribute >> 4));
00895 
00896     if (BottomLine >= Buff->MaxY) BottomLine = Buff->MaxY - 1;
00897     if (RightChar >= Buff->MaxX) RightChar = Buff->MaxX - 1;
00898 
00899     OldFont = SelectObject(hDC,
00900                            GuiData->Font);
00901 
00902     for (Line = TopLine; Line <= BottomLine; Line++)
00903     {
00904         WCHAR LineBuffer[80];
00905         From = ConioCoordToPointer(Buff, LeftChar, Line);
00906         Start = LeftChar;
00907         To = LineBuffer;
00908 
00909         for (Char = LeftChar; Char <= RightChar; Char++)
00910         {
00911             if (*(From + 1) != LastAttribute || (Char - Start == sizeof(LineBuffer) / sizeof(WCHAR)))
00912             {
00913                 TextOutW(hDC,
00914                          (Start - Buff->ShowX) * GuiData->CharWidth,
00915                          (Line - Buff->ShowY) * GuiData->CharHeight,
00916                          LineBuffer,
00917                          Char - Start);
00918                 Start = Char;
00919                 To = LineBuffer;
00920                 Attribute = *(From + 1);
00921                 if (Attribute != LastAttribute)
00922                 {
00923                     SetTextColor(hDC, GuiConsoleRGBFromAttribute(GuiData, Attribute));
00924                     SetBkColor(hDC, GuiConsoleRGBFromAttribute(GuiData, Attribute >> 4));
00925                     LastAttribute = Attribute;
00926                 }
00927             }
00928 
00929             MultiByteToWideChar(Console->OutputCodePage,
00930                                 0,
00931                                 (PCHAR)From,
00932                                 1,
00933                                 To,
00934                                 1);
00935             To++;
00936             From += 2;
00937         }
00938 
00939         TextOutW(hDC,
00940                  (Start - Buff->ShowX) * GuiData->CharWidth,
00941                  (Line - Buff->ShowY) * GuiData->CharHeight,
00942                  LineBuffer,
00943                  RightChar - Start + 1);
00944     }
00945 
00946     if (Buff->CursorInfo.bVisible && GuiData->CursorBlinkOn &&
00947             !GuiData->ForceCursorOff)
00948     {
00949         CursorX = Buff->CurrentX;
00950         CursorY = Buff->CurrentY;
00951         if (LeftChar <= CursorX && CursorX <= RightChar &&
00952                 TopLine <= CursorY && CursorY <= BottomLine)
00953         {
00954             CursorHeight = ConioEffectiveCursorSize(Console, GuiData->CharHeight);
00955             From = ConioCoordToPointer(Buff, Buff->CurrentX, Buff->CurrentY) + 1;
00956 
00957             if (*From != DEFAULT_ATTRIB)
00958             {
00959                 CursorBrush = CreateSolidBrush(GuiConsoleRGBFromAttribute(GuiData, *From));
00960             }
00961             else
00962             {
00963                 CursorBrush = CreateSolidBrush(GuiData->ScreenText);
00964             }
00965 
00966             OldBrush = SelectObject(hDC,
00967                                     CursorBrush);
00968             PatBlt(hDC,
00969                    (CursorX - Buff->ShowX) * GuiData->CharWidth,
00970                    (CursorY - Buff->ShowY) * GuiData->CharHeight + (GuiData->CharHeight - CursorHeight),
00971                    GuiData->CharWidth,
00972                    CursorHeight,
00973                    PATCOPY);
00974             SelectObject(hDC,
00975                          OldBrush);
00976             DeleteObject(CursorBrush);
00977         }
00978     }
00979 
00980     LeaveCriticalSection(&Buff->Header.Console->Lock);
00981 
00982     SelectObject(hDC,
00983                  OldFont);
00984 }
00985 
00986 static VOID
00987 GuiConsoleHandlePaint(HWND hWnd, HDC hDCPaint)
00988 {
00989     HDC hDC;
00990     PAINTSTRUCT ps;
00991     PCSRSS_CONSOLE Console;
00992     PGUI_CONSOLE_DATA GuiData;
00993 
00994     hDC = BeginPaint(hWnd, &ps);
00995     if (hDC != NULL &&
00996             ps.rcPaint.left < ps.rcPaint.right &&
00997             ps.rcPaint.top < ps.rcPaint.bottom)
00998     {
00999         GuiConsoleGetDataPointers(hWnd,
01000                                   &Console,
01001                                   &GuiData);
01002         if (Console != NULL && GuiData != NULL &&
01003                 Console->ActiveBuffer != NULL)
01004         {
01005             if (Console->ActiveBuffer->Buffer != NULL)
01006             {
01007                 EnterCriticalSection(&GuiData->Lock);
01008 
01009                 GuiConsolePaint(Console,
01010                                 GuiData,
01011                                 hDC,
01012                                 &ps.rcPaint);
01013 
01014                 if (Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY)
01015                 {
01016                     RECT rc;
01017                     SmallRectToRect(Console, &rc, &Console->Selection.srSelection);
01018 
01019                     /* invert the selection */
01020                     if (IntersectRect(&rc,
01021                                       &ps.rcPaint,
01022                                       &rc))
01023                     {
01024                         PatBlt(hDC,
01025                                rc.left,
01026                                rc.top,
01027                                rc.right - rc.left,
01028                                rc.bottom - rc.top,
01029                                DSTINVERT);
01030                     }
01031                 }
01032 
01033                 LeaveCriticalSection(&GuiData->Lock);
01034             }
01035         }
01036 
01037     }
01038     EndPaint(hWnd, &ps);
01039 }
01040 
01041 static VOID
01042 GuiConsoleHandleKey(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
01043 {
01044     PCSRSS_CONSOLE Console;
01045     PGUI_CONSOLE_DATA GuiData;
01046     MSG Message;
01047 
01048     GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
01049     Message.hwnd = hWnd;
01050     Message.message = msg;
01051     Message.wParam = wParam;
01052     Message.lParam = lParam;
01053 
01054     if(msg == WM_CHAR || msg == WM_SYSKEYDOWN)
01055     {
01056         /* clear the selection */
01057         GuiConsoleUpdateSelection(Console, NULL);
01058     }
01059 
01060     ConioProcessKey(&Message, Console, FALSE);
01061 }
01062 
01063 static VOID WINAPI
01064 GuiDrawRegion(PCSRSS_CONSOLE Console, SMALL_RECT *Region)
01065 {
01066     RECT RegionRect;
01067     SmallRectToRect(Console, &RegionRect, Region);
01068     InvalidateRect(Console->hWindow, &RegionRect, FALSE);
01069 }
01070 
01071 static VOID
01072 GuiInvalidateCell(PCSRSS_CONSOLE Console, UINT x, UINT y)
01073 {
01074     SMALL_RECT CellRect = { x, y, x, y };
01075     GuiDrawRegion(Console, &CellRect);
01076 }
01077 
01078 static VOID WINAPI
01079 GuiWriteStream(PCSRSS_CONSOLE Console, SMALL_RECT *Region, LONG CursorStartX, LONG CursorStartY,
01080                UINT ScrolledLines, CHAR *Buffer, UINT Length)
01081 {
01082     PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA) Console->PrivateData;
01083     PCSRSS_SCREEN_BUFFER Buff = Console->ActiveBuffer;
01084     LONG CursorEndX, CursorEndY;
01085     RECT ScrollRect;
01086 
01087     if (NULL == Console->hWindow || NULL == GuiData)
01088     {
01089         return;
01090     }
01091 
01092     if (0 != ScrolledLines)
01093     {
01094         ScrollRect.left = 0;
01095         ScrollRect.top = 0;
01096         ScrollRect.right = Console->Size.X * GuiData->CharWidth;
01097         ScrollRect.bottom = Region->Top * GuiData->CharHeight;
01098 
01099         ScrollWindowEx(Console->hWindow,
01100                        0,
01101                        -(ScrolledLines * GuiData->CharHeight),
01102                        &ScrollRect,
01103                        NULL,
01104                        NULL,
01105                        NULL,
01106                        SW_INVALIDATE);
01107     }
01108 
01109     GuiDrawRegion(Console, Region);
01110 
01111     if (CursorStartX < Region->Left || Region->Right < CursorStartX
01112             || CursorStartY < Region->Top || Region->Bottom < CursorStartY)
01113     {
01114         GuiInvalidateCell(Console, CursorStartX, CursorStartY);
01115     }
01116 
01117     CursorEndX = Buff->CurrentX;
01118     CursorEndY = Buff->CurrentY;
01119     if ((CursorEndX < Region->Left || Region->Right < CursorEndX
01120             || CursorEndY < Region->Top || Region->Bottom < CursorEndY)
01121             && (CursorEndX != CursorStartX || CursorEndY != CursorStartY))
01122     {
01123         GuiInvalidateCell(Console, CursorEndX, CursorEndY);
01124     }
01125 
01126     // Set up the update timer (very short interval) - this is a "hack" for getting the OS to
01127     // repaint the window without having it just freeze up and stay on the screen permanently.
01128     GuiData->CursorBlinkOn = TRUE;
01129     SetTimer(Console->hWindow, CONGUI_UPDATE_TIMER, CONGUI_UPDATE_TIME, NULL);
01130 }
01131 
01132 static BOOL WINAPI
01133 GuiSetCursorInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff)
01134 {
01135     if (Console->ActiveBuffer == Buff)
01136     {
01137         GuiInvalidateCell(Console, Buff->CurrentX, Buff->CurrentY);
01138     }
01139 
01140     return TRUE;
01141 }
01142 
01143 static BOOL WINAPI
01144 GuiSetScreenInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff, UINT OldCursorX, UINT OldCursorY)
01145 {
01146     if (Console->ActiveBuffer == Buff)
01147     {
01148         /* Redraw char at old position (removes cursor) */
01149         GuiInvalidateCell(Console, OldCursorX, OldCursorY);
01150         /* Redraw char at new position (shows cursor) */
01151         GuiInvalidateCell(Console, Buff->CurrentX, Buff->CurrentY);
01152     }
01153 
01154     return TRUE;
01155 }
01156 
01157 static BOOL WINAPI
01158 GuiUpdateScreenInfo(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buff)
01159 {
01160     PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA) Console->PrivateData;
01161 
01162     if (Console->ActiveBuffer == Buff)
01163     {
01164         GuiData->ScreenText = GuiConsoleRGBFromAttribute(GuiData, Buff->DefaultAttrib);
01165         GuiData->ScreenBackground = GuiConsoleRGBFromAttribute(GuiData, Buff->DefaultAttrib >> 4);
01166     }
01167 
01168     return TRUE;
01169 }
01170 
01171 static VOID
01172 GuiConsoleHandleTimer(HWND hWnd)
01173 {
01174     PCSRSS_CONSOLE Console;
01175     PGUI_CONSOLE_DATA GuiData;
01176     PCSRSS_SCREEN_BUFFER Buff;
01177 
01178     SetTimer(hWnd, CONGUI_UPDATE_TIMER, CURSOR_BLINK_TIME, NULL);
01179 
01180     GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
01181 
01182     Buff = Console->ActiveBuffer;
01183     GuiInvalidateCell(Console, Buff->CurrentX, Buff->CurrentY);
01184     GuiData->CursorBlinkOn = ! GuiData->CursorBlinkOn;
01185 
01186     if((GuiData->OldCursor.x != Buff->CurrentX) || (GuiData->OldCursor.y != Buff->CurrentY))
01187     {
01188         SCROLLINFO xScroll;
01189         int OldScrollX = -1, OldScrollY = -1;
01190         int NewScrollX = -1, NewScrollY = -1;
01191 
01192         xScroll.cbSize = sizeof(SCROLLINFO);
01193         xScroll.fMask = SIF_POS;
01194         // Capture the original position of the scroll bars and save them.
01195         if(GetScrollInfo(hWnd, SB_HORZ, &xScroll))OldScrollX = xScroll.nPos;
01196         if(GetScrollInfo(hWnd, SB_VERT, &xScroll))OldScrollY = xScroll.nPos;
01197 
01198         // If we successfully got the info for the horizontal scrollbar
01199         if(OldScrollX >= 0)
01200         {
01201             if((Buff->CurrentX < Buff->ShowX)||(Buff->CurrentX >= (Buff->ShowX + Console->Size.X)))
01202             {
01203                 // Handle the horizontal scroll bar
01204                 if(Buff->CurrentX >= Console->Size.X) NewScrollX = Buff->CurrentX - Console->Size.X + 1;
01205                 else NewScrollX = 0;
01206             }
01207             else
01208             {
01209                 NewScrollX = OldScrollX;
01210             }
01211         }
01212         // If we successfully got the info for the vertical scrollbar
01213         if(OldScrollY >= 0)
01214         {
01215             if((Buff->CurrentY < Buff->ShowY) || (Buff->CurrentY >= (Buff->ShowY + Console->Size.Y)))
01216             {
01217                 // Handle the vertical scroll bar
01218                 if(Buff->CurrentY >= Console->Size.Y) NewScrollY = Buff->CurrentY - Console->Size.Y + 1;
01219                 else NewScrollY = 0;
01220             }
01221             else
01222             {
01223                 NewScrollY = OldScrollY;
01224             }
01225         }
01226 
01227         // Adjust scroll bars and refresh the window if the cursor has moved outside the visible area
01228         // NOTE: OldScroll# and NewScroll# will both be -1 (initial value) if the info for the respective scrollbar
01229         //       was not obtained successfully in the previous steps. This means their difference is 0 (no scrolling)
01230         //       and their associated scrollbar is left alone.
01231         if((OldScrollX != NewScrollX) || (OldScrollY != NewScrollY))
01232         {
01233             Buff->ShowX = NewScrollX;
01234             Buff->ShowY = NewScrollY;
01235             ScrollWindowEx(hWnd,
01236                            (OldScrollX - NewScrollX) * GuiData->CharWidth,
01237                            (OldScrollY - NewScrollY) * GuiData->CharHeight,
01238                            NULL,
01239                            NULL,
01240                            NULL,
01241                            NULL,
01242                            SW_INVALIDATE);
01243             if(NewScrollX >= 0)
01244             {
01245                 xScroll.nPos = NewScrollX;
01246                 SetScrollInfo(hWnd, SB_HORZ, &xScroll, TRUE);
01247             }
01248             if(NewScrollY >= 0)
01249             {
01250                 xScroll.nPos = NewScrollY;
01251                 SetScrollInfo(hWnd, SB_VERT, &xScroll, TRUE);
01252             }
01253             UpdateWindow(hWnd);
01254             GuiData->OldCursor.x = Buff->CurrentX;
01255             GuiData->OldCursor.y = Buff->CurrentY;
01256         }
01257     }
01258 }
01259 
01260 static VOID
01261 GuiConsoleHandleClose(HWND hWnd)
01262 {
01263     PCSRSS_CONSOLE Console;
01264     PGUI_CONSOLE_DATA GuiData;
01265     PLIST_ENTRY current_entry;
01266     PCSR_PROCESS current;
01267 
01268     GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
01269 
01270     EnterCriticalSection(&Console->Lock);
01271 
01272     current_entry = Console->ProcessList.Flink;
01273     while (current_entry != &Console->ProcessList)
01274     {
01275         current = CONTAINING_RECORD(current_entry, CSR_PROCESS, ConsoleLink);
01276         current_entry = current_entry->Flink;
01277 
01278         /* FIXME: Windows will wait up to 5 seconds for the thread to exit.
01279          * We shouldn't wait here, though, since the console lock is entered.
01280          * A copy of the thread list probably needs to be made. */
01281         ConioConsoleCtrlEvent(CTRL_CLOSE_EVENT, current);
01282     }
01283 
01284     LeaveCriticalSection(&Console->Lock);
01285 }
01286 
01287 static VOID
01288 GuiConsoleHandleNcDestroy(HWND hWnd)
01289 {
01290     PCSRSS_CONSOLE Console;
01291     PGUI_CONSOLE_DATA GuiData;
01292 
01293 
01294     GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
01295     KillTimer(hWnd, 1);
01296     Console->PrivateData = NULL;
01297     DeleteCriticalSection(&GuiData->Lock);
01298     GetSystemMenu(hWnd, TRUE);
01299     if (GuiData->ConsoleLibrary)
01300         FreeLibrary(GuiData->ConsoleLibrary);
01301 
01302     HeapFree(Win32CsrApiHeap, 0, GuiData);
01303 }
01304 
01305 static COORD
01306 PointToCoord(PCSRSS_CONSOLE Console, LPARAM lParam)
01307 {
01308     PCSRSS_SCREEN_BUFFER Buffer = Console->ActiveBuffer;
01309     PGUI_CONSOLE_DATA GuiData = Console->PrivateData;
01310     COORD Coord;
01311     Coord.X = Buffer->ShowX + ((short)LOWORD(lParam) / (int)GuiData->CharWidth);
01312     Coord.Y = Buffer->ShowY + ((short)HIWORD(lParam) / (int)GuiData->CharHeight);
01313 
01314     /* Clip coordinate to ensure it's inside buffer */
01315     if (Coord.X < 0)                  Coord.X = 0;
01316     else if (Coord.X >= Buffer->MaxX) Coord.X = Buffer->MaxX - 1;
01317     if (Coord.Y < 0)                  Coord.Y = 0;
01318     else if (Coord.Y >= Buffer->MaxY) Coord.Y = Buffer->MaxY - 1;
01319     return Coord;
01320 }
01321 
01322 static VOID
01323 GuiConsoleLeftMouseDown(HWND hWnd, LPARAM lParam)
01324 {
01325     PCSRSS_CONSOLE Console;
01326     PGUI_CONSOLE_DATA GuiData;
01327 
01328     GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
01329     if (Console == NULL || GuiData == NULL) return;
01330 
01331     Console->Selection.dwSelectionAnchor = PointToCoord(Console, lParam);
01332 
01333     SetCapture(hWnd);
01334 
01335     Console->Selection.dwFlags |= CONSOLE_SELECTION_IN_PROGRESS | CONSOLE_MOUSE_SELECTION | CONSOLE_MOUSE_DOWN;
01336 
01337     GuiConsoleUpdateSelection(Console, &Console->Selection.dwSelectionAnchor);
01338 }
01339 
01340 static VOID
01341 GuiConsoleLeftMouseUp(HWND hWnd, LPARAM lParam)
01342 {
01343     PCSRSS_CONSOLE Console;
01344     PGUI_CONSOLE_DATA GuiData;
01345     COORD c;
01346 
01347     GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
01348     if (Console == NULL || GuiData == NULL) return;
01349     if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) return;
01350 
01351     c = PointToCoord(Console, lParam);
01352 
01353     Console->Selection.dwFlags &= ~CONSOLE_MOUSE_DOWN;
01354 
01355     GuiConsoleUpdateSelection(Console, &c);
01356 
01357     ReleaseCapture();
01358 }
01359 
01360 static VOID
01361 GuiConsoleMouseMove(HWND hWnd, WPARAM wParam, LPARAM lParam)
01362 {
01363     PCSRSS_CONSOLE Console;
01364     PGUI_CONSOLE_DATA GuiData;
01365     COORD c;
01366 
01367     if (!(wParam & MK_LBUTTON)) return;
01368 
01369     GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
01370     if (Console == NULL || GuiData == NULL) return;
01371     if (!(Console->Selection.dwFlags & CONSOLE_MOUSE_DOWN)) return;
01372 
01373     c = PointToCoord(Console, lParam); /* TODO: Scroll buffer to bring c into view */
01374 
01375     GuiConsoleUpdateSelection(Console, &c);
01376 }
01377 
01378 static VOID
01379 GuiConsoleCopy(HWND hWnd, PCSRSS_CONSOLE Console)
01380 {
01381     if (OpenClipboard(hWnd) == TRUE)
01382     {
01383         HANDLE hData;
01384         PBYTE ptr;
01385         LPSTR data, dstPos;
01386         ULONG selWidth, selHeight;
01387         ULONG xPos, yPos, size;
01388 
01389         selWidth = Console->Selection.srSelection.Right - Console->Selection.srSelection.Left + 1;
01390         selHeight = Console->Selection.srSelection.Bottom - Console->Selection.srSelection.Top + 1;
01391         DPRINT("Selection is (%d|%d) to (%d|%d)\n",
01392                Console->Selection.srSelection.Left,
01393                Console->Selection.srSelection.Top,
01394                Console->Selection.srSelection.Right,
01395                Console->Selection.srSelection.Bottom);
01396 
01397         /* Basic size for one line and termination */
01398         size = selWidth + 1;
01399         if (selHeight > 0)
01400         {
01401             /* Multiple line selections have to get \r\n appended */
01402             size += ((selWidth + 2) * (selHeight - 1));
01403         }
01404 
01405         /* Allocate memory, it will be passed to the system and may not be freed here */
01406         hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, size);
01407         if (hData == NULL)
01408         {
01409             CloseClipboard();
01410             return;
01411         }
01412         data = GlobalLock(hData);
01413         if (data == NULL)
01414         {
01415             CloseClipboard();
01416             return;
01417         }
01418 
01419         DPRINT("Copying %dx%d selection\n", selWidth, selHeight);
01420         dstPos = data;
01421 
01422         for (yPos = 0; yPos < selHeight; yPos++)
01423         {
01424             ptr = ConioCoordToPointer(Console->ActiveBuffer, 
01425                                       Console->Selection.srSelection.Left,
01426                                       yPos + Console->Selection.srSelection.Top);
01427             /* Copy only the characters, leave attributes alone */
01428             for (xPos = 0; xPos < selWidth; xPos++)
01429             {
01430                 dstPos[xPos] = ptr[xPos * 2];
01431             }
01432             dstPos += selWidth;
01433             if (yPos != (selHeight - 1))
01434             {
01435                 strcat(data, "\r\n");
01436                 dstPos += 2;
01437             }
01438         }
01439 
01440         DPRINT("Setting data <%s> to clipboard\n", data);
01441         GlobalUnlock(hData);
01442 
01443         EmptyClipboard();
01444         SetClipboardData(CF_TEXT, hData);
01445         CloseClipboard();
01446     }
01447 }
01448 
01449 static VOID
01450 GuiConsolePaste(HWND hWnd, PCSRSS_CONSOLE Console)
01451 {
01452     if (OpenClipboard(hWnd) == TRUE)
01453     {
01454         HANDLE hData;
01455         LPSTR str;
01456         size_t len;
01457 
01458         hData = GetClipboardData(CF_TEXT);
01459         if (hData == NULL)
01460         {
01461             CloseClipboard();
01462             return;
01463         }
01464 
01465         str = GlobalLock(hData);
01466         if (str == NULL)
01467         {
01468             CloseClipboard();
01469             return;
01470         }
01471         DPRINT("Got data <%s> from clipboard\n", str);
01472         len = strlen(str);
01473 
01474         ConioWriteConsole(Console, Console->ActiveBuffer, str, len, TRUE);
01475 
01476         GlobalUnlock(hData);
01477         CloseClipboard();
01478     }
01479 }
01480 
01481 static VOID
01482 GuiConsoleRightMouseDown(HWND hWnd)
01483 {
01484     PCSRSS_CONSOLE Console;
01485     PGUI_CONSOLE_DATA GuiData;
01486 
01487     GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
01488     if (Console == NULL || GuiData == NULL) return;
01489 
01490     if (!(Console->Selection.dwFlags & CONSOLE_SELECTION_NOT_EMPTY))
01491     {
01492         GuiConsolePaste(hWnd, Console);
01493     }
01494     else
01495     {
01496         GuiConsoleCopy(hWnd, Console);
01497 
01498         /* Clear the selection */
01499         GuiConsoleUpdateSelection(Console, NULL);
01500     }
01501 
01502 }
01503 
01504 
01505 static VOID
01506 GuiConsoleShowConsoleProperties(HWND hWnd, BOOL Defaults, PGUI_CONSOLE_DATA GuiData)
01507 {
01508     PCSRSS_CONSOLE Console;
01509     APPLET_PROC CPLFunc;
01510     TCHAR szBuffer[MAX_PATH];
01511     ConsoleInfo SharedInfo;
01512 
01513     DPRINT("GuiConsoleShowConsoleProperties entered\n");
01514 
01515     GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
01516 
01517     if (GuiData == NULL)
01518     {
01519         DPRINT("GuiConsoleGetDataPointers failed\n");
01520         return;
01521     }
01522 
01523     if (GuiData->ConsoleLibrary == NULL)
01524     {
01525         GetWindowsDirectory(szBuffer,MAX_PATH);
01526         _tcscat(szBuffer, _T("\\system32\\console.dll"));
01527         GuiData->ConsoleLibrary = LoadLibrary(szBuffer);
01528 
01529         if (GuiData->ConsoleLibrary == NULL)
01530         {
01531             DPRINT1("failed to load console.dll");
01532             return;
01533         }
01534     }
01535 
01536     CPLFunc = (APPLET_PROC) GetProcAddress(GuiData->ConsoleLibrary, _T("CPlApplet"));
01537     if (!CPLFunc)
01538     {
01539         DPRINT("Error: Console.dll misses CPlApplet export\n");
01540         return;
01541     }
01542 
01543     /* setup struct */
01544     SharedInfo.InsertMode = GuiData->InsertMode;
01545     SharedInfo.HistoryBufferSize = Console->HistoryBufferSize;
01546     SharedInfo.NumberOfHistoryBuffers = Console->NumberOfHistoryBuffers;
01547     SharedInfo.ScreenText = GuiData->ScreenText;
01548     SharedInfo.ScreenBackground = GuiData->ScreenBackground;
01549     SharedInfo.PopupText = GuiData->PopupText;
01550     SharedInfo.PopupBackground = GuiData->PopupBackground;
01551     SharedInfo.WindowSize = (DWORD)MAKELONG(Console->Size.X, Console->Size.Y);
01552     SharedInfo.WindowPosition = GuiData->WindowPosition;
01553     SharedInfo.ScreenBuffer = (DWORD)MAKELONG(Console->ActiveBuffer->MaxX, Console->ActiveBuffer->MaxY);
01554     SharedInfo.UseRasterFonts = GuiData->UseRasterFonts;
01555     SharedInfo.FontSize = (DWORD)GuiData->FontSize;
01556     SharedInfo.FontWeight = GuiData->FontWeight;
01557     SharedInfo.CursorSize = Console->ActiveBuffer->CursorInfo.dwSize;
01558     SharedInfo.HistoryNoDup = Console->HistoryNoDup;
01559     SharedInfo.FullScreen = GuiData->FullScreen;
01560     SharedInfo.QuickEdit = GuiData->QuickEdit;
01561     memcpy(&SharedInfo.Colors[0], GuiData->Colors, sizeof(s_Colors));
01562 
01563     if (!CPLFunc(hWnd, CPL_INIT, 0, 0))
01564     {
01565         DPRINT("Error: failed to initialize console.dll\n");
01566         return;
01567     }
01568 
01569     if (CPLFunc(hWnd, CPL_GETCOUNT, 0, 0) != 1)
01570     {
01571         DPRINT("Error: console.dll returned unexpected CPL count\n");
01572         return;
01573     }
01574 
01575     CPLFunc(hWnd, CPL_DBLCLK, (LPARAM)&SharedInfo, Defaults);
01576 }
01577 static LRESULT
01578 GuiConsoleHandleSysMenuCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
01579 {
01580     LRESULT Ret = TRUE;
01581     PCSRSS_CONSOLE Console;
01582     PGUI_CONSOLE_DATA GuiData;
01583     COORD bottomRight = { 0, 0 };
01584 
01585     GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
01586 
01587     switch(wParam)
01588     {
01589     case ID_SYSTEM_EDIT_MARK:
01590         DPRINT1("Marking not handled yet\n");
01591         break;
01592 
01593     case ID_SYSTEM_EDIT_COPY:
01594         GuiConsoleCopy(hWnd, Console);
01595         break;
01596 
01597     case ID_SYSTEM_EDIT_PASTE:
01598         GuiConsolePaste(hWnd, Console);
01599         break;
01600 
01601     case ID_SYSTEM_EDIT_SELECTALL:
01602         bottomRight.X = Console->Size.X - 1;
01603         bottomRight.Y = Console->Size.Y - 1;
01604         GuiConsoleUpdateSelection(Console, &bottomRight);
01605         break;
01606 
01607     case ID_SYSTEM_EDIT_SCROLL:
01608         DPRINT1("Scrolling is not handled yet\n");
01609         break;
01610 
01611     case ID_SYSTEM_EDIT_FIND:
01612         DPRINT1("Finding is not handled yet\n");
01613         break;
01614 
01615     case ID_SYSTEM_DEFAULTS:
01616         GuiConsoleShowConsoleProperties(hWnd, TRUE, GuiData);
01617         break;
01618 
01619     case ID_SYSTEM_PROPERTIES:
01620         GuiConsoleShowConsoleProperties(hWnd, FALSE, GuiData);
01621         break;
01622 
01623     default:
01624         Ret = DefWindowProcW(hWnd, WM_SYSCOMMAND, wParam, lParam);
01625         break;
01626     }
01627     return Ret;
01628 }
01629 
01630 static VOID
01631 GuiConsoleGetMinMaxInfo(HWND hWnd, PMINMAXINFO minMaxInfo)
01632 {
01633     PCSRSS_CONSOLE Console;
01634     PGUI_CONSOLE_DATA GuiData;
01635     DWORD windx, windy;
01636 
01637     GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
01638     if((Console == NULL)|| (GuiData == NULL)) return;
01639 
01640     windx = CONGUI_MIN_WIDTH * GuiData->CharWidth + 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
01641     windy = CONGUI_MIN_HEIGHT * GuiData->CharHeight + 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
01642 
01643     minMaxInfo->ptMinTrackSize.x = windx;
01644     minMaxInfo->ptMinTrackSize.y = windy;
01645 
01646     windx = (Console->ActiveBuffer->MaxX) * GuiData->CharWidth + 2 * (GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXEDGE));
01647     windy = (Console->ActiveBuffer->MaxY) * GuiData->CharHeight + 2 * (GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYEDGE)) + GetSystemMetrics(SM_CYCAPTION);
01648 
01649     if(Console->Size.X < Console->ActiveBuffer->MaxX) windy += GetSystemMetrics(SM_CYHSCROLL);    // window currently has a horizontal scrollbar
01650     if(Console->Size.Y < Console->ActiveBuffer->MaxY) windx += GetSystemMetrics(SM_CXVSCROLL);    // window currently has a vertical scrollbar
01651 
01652     minMaxInfo->ptMaxTrackSize.x = windx;
01653     minMaxInfo->ptMaxTrackSize.y = windy;
01654 }
01655 static VOID
01656 GuiConsoleResize(HWND hWnd, WPARAM wParam, LPARAM lParam)
01657 {
01658     PCSRSS_CONSOLE Console;
01659     PGUI_CONSOLE_DATA GuiData;
01660     GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
01661     if((Console == NULL) || (GuiData == NULL)) return;
01662 
01663     if ((GuiData->WindowSizeLock == FALSE) && (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED || wParam == SIZE_MINIMIZED))
01664     {
01665         PCSRSS_SCREEN_BUFFER Buff = Console->ActiveBuffer;
01666         DWORD windx, windy, charx, chary;
01667 
01668         GuiData->WindowSizeLock = TRUE;
01669 
01670         windx = LOWORD(lParam);
01671         windy = HIWORD(lParam);
01672 
01673         // Compensate for existing scroll bars (because lParam values do not accommodate scroll bar)
01674         if(Console->Size.X < Buff->MaxX) windy += GetSystemMetrics(SM_CYHSCROLL);    // window currently has a horizontal scrollbar
01675         if(Console->Size.Y < Buff->MaxY) windx += GetSystemMetrics(SM_CXVSCROLL);    // window currently has a vertical scrollbar
01676 
01677         charx = windx / GuiData->CharWidth;
01678         chary = windy / GuiData->CharHeight;
01679 
01680         // Character alignment (round size up or down)
01681         if((windx % GuiData->CharWidth) >= (GuiData->CharWidth / 2)) ++charx;
01682         if((windy % GuiData->CharHeight) >= (GuiData->CharHeight / 2)) ++chary;
01683 
01684         // Compensate for added scroll bars in new window
01685         if(charx < Buff->MaxX)windy -= GetSystemMetrics(SM_CYHSCROLL);    // new window will have a horizontal scroll bar
01686         if(chary < Buff->MaxY)windx -= GetSystemMetrics(SM_CXVSCROLL);    // new window will have a vertical scroll bar
01687 
01688         charx = windx / GuiData->CharWidth;
01689         chary = windy / GuiData->CharHeight;
01690 
01691         // Character alignment (round size up or down)
01692         if((windx % GuiData->CharWidth) >= (GuiData->CharWidth / 2)) ++charx;
01693         if((windy % GuiData->CharHeight) >= (GuiData->CharHeight / 2)) ++chary;
01694 
01695         // Resize window
01696         if((charx != Console->Size.X) || (chary != Console->Size.Y))
01697         {
01698             Console->Size.X = (charx <= Buff->MaxX) ? charx : Buff->MaxX;
01699             Console->Size.Y = (chary <= Buff->MaxY) ? chary : Buff->MaxY;
01700         }
01701 
01702         GuiConsoleInitScrollbar(Console, hWnd);
01703 
01704         // Adjust the start of the visible area if we are attempting to show nonexistent areas
01705         if((Buff->MaxX - Buff->ShowX) < Console->Size.X) Buff->ShowX = Buff->MaxX - Console->Size.X;
01706         if((Buff->MaxY - Buff->ShowY) < Console->Size.Y) Buff->ShowY = Buff->MaxY - Console->Size.Y;
01707         InvalidateRect(hWnd, NULL, TRUE);
01708 
01709         GuiData->WindowSizeLock = FALSE;
01710     }
01711 }
01712 
01713 VOID
01714 FASTCALL
01715 GuiConsoleHandleScrollbarMenu()
01716 {
01717     HMENU hMenu;
01718 
01719     hMenu = CreatePopupMenu();
01720     if (hMenu == NULL)
01721     {
01722         DPRINT("CreatePopupMenu failed\n");
01723         return;
01724     }
01725     //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLHERE);
01726     //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
01727     //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLTOP);
01728     //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLBOTTOM);
01729     //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
01730     //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_UP);
01731     //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLPAGE_DOWN);
01732     //InsertItem(hMenu, MFT_SEPARATOR, MIIM_FTYPE, 0, NULL, -1);
01733     //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLUP);
01734     //InsertItem(hMenu, MIIM_STRING, MIIM_ID | MIIM_FTYPE | MIIM_STRING, 0, NULL, IDS_SCROLLDOWN);
01735 
01736 }
01737 
01738 static NTSTATUS WINAPI
01739 GuiResizeBuffer(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER ScreenBuffer, COORD Size)
01740 {
01741     BYTE * Buffer;
01742     DWORD Offset = 0;
01743     BYTE * OldPtr;
01744     USHORT CurrentY;
01745     BYTE * OldBuffer;
01746 #if HAVE_WMEMSET
01747     USHORT value = MAKEWORD(' ', ScreenBuffer->DefaultAttrib);
01748 #endif
01749     DWORD diff;
01750     DWORD i;
01751 
01752     /* Buffer size is not allowed to be smaller than window size */
01753     if (Size.X < Console->Size.X || Size.Y < Console->Size.Y)
01754         return STATUS_INVALID_PARAMETER;
01755 
01756     if (Size.X == ScreenBuffer->MaxX && Size.Y == ScreenBuffer->MaxY)
01757         return STATUS_SUCCESS;
01758 
01759     Buffer = HeapAlloc(Win32CsrApiHeap, 0, Size.X * Size.Y * 2);
01760     if (!Buffer)
01761         return STATUS_NO_MEMORY;
01762 
01763     DPRINT1("Resizing (%d,%d) to (%d,%d)\n", ScreenBuffer->MaxX, ScreenBuffer->MaxY, Size.X, Size.Y);
01764     OldBuffer = ScreenBuffer->Buffer;
01765 
01766     for (CurrentY = 0; CurrentY < ScreenBuffer->MaxY && CurrentY < Size.Y; CurrentY++)
01767     {
01768         OldPtr = ConioCoordToPointer(ScreenBuffer, 0, CurrentY);
01769         if (Size.X <= ScreenBuffer->MaxX)
01770         {
01771             /* reduce size */
01772             RtlCopyMemory(&Buffer[Offset], OldPtr, Size.X * 2);
01773             Offset += (Size.X * 2);
01774         }
01775         else
01776         {
01777             /* enlarge size */
01778             RtlCopyMemory(&Buffer[Offset], OldPtr, ScreenBuffer->MaxX * 2);
01779             Offset += (ScreenBuffer->MaxX * 2);
01780 
01781             diff = Size.X - ScreenBuffer->MaxX;
01782             /* zero new part of it */
01783 #if HAVE_WMEMSET
01784             wmemset((WCHAR*)&Buffer[Offset], value, diff);
01785 #else
01786             for (i = 0; i < diff; i++)
01787             {
01788                 Buffer[Offset++] = ' ';
01789                 Buffer[Offset++] = ScreenBuffer->DefaultAttrib;
01790             }
01791 #endif
01792         }
01793     }
01794 
01795     if (Size.Y > ScreenBuffer->MaxY)
01796     {
01797         diff = Size.X * (Size.Y - ScreenBuffer->MaxY);
01798 #if HAVE_WMEMSET
01799         wmemset((WCHAR*)&Buffer[Offset], value, diff);
01800 #else
01801         for (i = 0; i < diff; i++)
01802         {
01803             Buffer[Offset++] = ' ';
01804             Buffer[Offset++] = ScreenBuffer->DefaultAttrib;
01805         }
01806 #endif
01807     }
01808 
01809     (void)InterlockedExchangePointer((PVOID volatile  *)&ScreenBuffer->Buffer, Buffer);
01810     HeapFree(Win32CsrApiHeap, 0, OldBuffer);
01811     ScreenBuffer->MaxX = Size.X;
01812     ScreenBuffer->MaxY = Size.Y;
01813     ScreenBuffer->VirtualY = 0;
01814 
01815     /* Ensure cursor and window are within buffer */
01816     if (ScreenBuffer->CurrentX >= Size.X)
01817         ScreenBuffer->CurrentX = Size.X - 1;
01818     if (ScreenBuffer->CurrentY >= Size.Y)
01819         ScreenBuffer->CurrentY = Size.Y - 1;
01820     if (ScreenBuffer->ShowX > Size.X - Console->Size.X)
01821         ScreenBuffer->ShowX = Size.X - Console->Size.X;
01822     if (ScreenBuffer->ShowY > Size.Y - Console->Size.Y)
01823         ScreenBuffer->ShowY = Size.Y - Console->Size.Y;
01824 
01825     /* TODO: Should update scrollbar, but can't use anything that
01826      * calls SendMessage or it could cause deadlock */
01827 
01828     return STATUS_SUCCESS;
01829 }
01830 
01831 static VOID
01832 GuiApplyUserSettings(PCSRSS_CONSOLE Console, PGUI_CONSOLE_DATA GuiData, PConsoleInfo pConInfo)
01833 {
01834     DWORD windx, windy;
01835     PCSRSS_SCREEN_BUFFER ActiveBuffer = Console->ActiveBuffer;
01836     COORD BufSize;
01837     BOOL SizeChanged = FALSE;
01838 
01839     EnterCriticalSection(&Console->Lock);
01840 
01841     /* apply text / background color */
01842     GuiData->ScreenText = pConInfo->ScreenText;
01843     GuiData->ScreenBackground = pConInfo->ScreenBackground;
01844 
01845     /* apply cursor size */
01846     ActiveBuffer->CursorInfo.dwSize = min(max(pConInfo->CursorSize, 1), 100);
01847 
01848     windx = LOWORD(pConInfo->WindowSize);
01849     windy = HIWORD(pConInfo->WindowSize);
01850 
01851     if (windx != Console->Size.X || windy != Console->Size.Y)
01852     {
01853         /* resize window */
01854         Console->Size.X = windx;
01855         Console->Size.Y = windy;
01856         SizeChanged = TRUE;
01857     }
01858 
01859     BufSize.X = LOWORD(pConInfo->ScreenBuffer);
01860     BufSize.Y = HIWORD(pConInfo->ScreenBuffer);
01861     if (BufSize.X != ActiveBuffer->MaxX || BufSize.Y != ActiveBuffer->MaxY)
01862     {
01863         if (NT_SUCCESS(GuiResizeBuffer(Console, ActiveBuffer, BufSize)))
01864             SizeChanged = TRUE;
01865     }
01866 
01867     if (SizeChanged)
01868     {
01869         GuiData->WindowSizeLock = TRUE;
01870         GuiConsoleInitScrollbar(Console, pConInfo->hConsoleWindow);
01871         GuiData->WindowSizeLock = FALSE;
01872     }
01873 
01874     LeaveCriticalSection(&Console->Lock);
01875     InvalidateRect(pConInfo->hConsoleWindow, NULL, TRUE);
01876 }
01877 
01878 static
01879 LRESULT
01880 GuiConsoleHandleScroll(HWND hwnd, UINT uMsg, WPARAM wParam)
01881 {
01882     PCSRSS_CONSOLE Console;
01883     PCSRSS_SCREEN_BUFFER Buff;
01884     PGUI_CONSOLE_DATA GuiData;
01885     SCROLLINFO sInfo;
01886     int fnBar;
01887     int old_pos, Maximum;
01888     PUSHORT pShowXY;
01889 
01890     GuiConsoleGetDataPointers(hwnd, &Console, &GuiData);
01891     if (Console == NULL || GuiData == NULL)
01892         return FALSE;
01893     Buff = Console->ActiveBuffer;
01894 
01895     if (uMsg == WM_HSCROLL)
01896     {
01897         fnBar = SB_HORZ;
01898         Maximum = Buff->MaxX - Console->Size.X;
01899         pShowXY = &Buff->ShowX;
01900     }
01901     else
01902     {
01903         fnBar = SB_VERT;
01904         Maximum = Buff->MaxY - Console->Size.Y;
01905         pShowXY = &Buff->ShowY;
01906     }
01907 
01908     /* set scrollbar sizes */
01909     sInfo.cbSize = sizeof(SCROLLINFO);
01910     sInfo.fMask = SIF_RANGE | SIF_POS | SIF_PAGE | SIF_TRACKPOS;
01911 
01912     if (!GetScrollInfo(hwnd, fnBar, &sInfo))
01913     {
01914         return FALSE;
01915     }
01916 
01917     old_pos = sInfo.nPos;
01918 
01919     switch(LOWORD(wParam))
01920     {
01921     case SB_LINELEFT:
01922         sInfo.nPos -= 1;
01923         break;
01924 
01925     case SB_LINERIGHT:
01926         sInfo.nPos += 1;
01927         break;
01928 
01929     case SB_PAGELEFT:
01930         sInfo.nPos -= sInfo.nPage;
01931         break;
01932 
01933     case SB_PAGERIGHT:
01934         sInfo.nPos += sInfo.nPage;
01935         break;
01936 
01937     case SB_THUMBTRACK:
01938         sInfo.nPos = sInfo.nTrackPos;
01939         ConioPause(Console, PAUSED_FROM_SCROLLBAR);
01940         break;
01941 
01942     case SB_THUMBPOSITION:
01943         ConioUnpause(Console, PAUSED_FROM_SCROLLBAR);
01944         break;
01945 
01946     case SB_TOP:
01947         sInfo.nPos = sInfo.nMin;
01948         break;
01949 
01950     case SB_BOTTOM:
01951         sInfo.nPos = sInfo.nMax;
01952         break;
01953 
01954     default:
01955         break;
01956     }
01957 
01958     sInfo.nPos = max(sInfo.nPos, 0);
01959     sInfo.nPos = min(sInfo.nPos, Maximum);
01960 
01961     if (old_pos != sInfo.nPos)
01962     {
01963         USHORT OldX = Buff->ShowX;
01964         USHORT OldY = Buff->ShowY;
01965         *pShowXY = sInfo.nPos;
01966 
01967         ScrollWindowEx(hwnd,
01968                        (OldX - Buff->ShowX) * GuiData->CharWidth,
01969                        (OldY - Buff->ShowY) * GuiData->CharHeight,
01970                        NULL,
01971                        NULL,
01972                        NULL,
01973                        NULL,
01974                        SW_INVALIDATE);
01975 
01976         sInfo.fMask = SIF_POS;
01977         SetScrollInfo(hwnd, fnBar, &sInfo, TRUE);
01978 
01979         UpdateWindow(hwnd);
01980     }
01981     return 0;
01982 }
01983 
01984 static LRESULT CALLBACK
01985 GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
01986 {
01987     LRESULT Result = 0;
01988     PGUI_CONSOLE_DATA GuiData = NULL;
01989     PCSRSS_CONSOLE Console = NULL;
01990 
01991     GuiConsoleGetDataPointers(hWnd, &Console, &GuiData);
01992 
01993     switch(msg)
01994     {
01995     case WM_NCCREATE:
01996         Result = (LRESULT) GuiConsoleHandleNcCreate(hWnd, (CREATESTRUCTW *) lParam);
01997         break;
01998     case WM_PAINT:
01999         GuiConsoleHandlePaint(hWnd, (HDC)wParam);
02000         break;
02001     case WM_KEYDOWN:
02002     case WM_KEYUP:
02003     case WM_SYSKEYDOWN:
02004     case WM_SYSKEYUP:
02005     case WM_CHAR:
02006         GuiConsoleHandleKey(hWnd, msg, wParam, lParam);
02007         break;
02008     case WM_TIMER:
02009         GuiConsoleHandleTimer(hWnd);
02010         break;
02011     case WM_CLOSE:
02012         GuiConsoleHandleClose(hWnd);
02013         break;
02014     case WM_NCDESTROY:
02015         GuiConsoleHandleNcDestroy(hWnd);
02016         break;
02017     case WM_LBUTTONDOWN:
02018         GuiConsoleLeftMouseDown(hWnd, lParam);
02019         break;
02020     case WM_LBUTTONUP:
02021         GuiConsoleLeftMouseUp(hWnd, lParam);
02022         break;
02023     case WM_RBUTTONDOWN:
02024         GuiConsoleRightMouseDown(hWnd);
02025         break;
02026     case WM_MOUSEMOVE:
02027         GuiConsoleMouseMove(hWnd, wParam, lParam);
02028         break;
02029     case WM_SYSCOMMAND:
02030         Result = GuiConsoleHandleSysMenuCommand(hWnd, wParam, lParam);
02031         break;
02032     case WM_HSCROLL:
02033     case WM_VSCROLL:
02034         Result = GuiConsoleHandleScroll(hWnd, msg, wParam);
02035         break;
02036     case WM_GETMINMAXINFO:
02037         GuiConsoleGetMinMaxInfo(hWnd, (PMINMAXINFO)lParam);
02038         break;
02039     case WM_SIZE:
02040         GuiConsoleResize(hWnd, wParam, lParam);
02041         break;
02042     case PM_APPLY_CONSOLE_INFO:
02043         GuiApplyUserSettings(Console, GuiData, (PConsoleInfo)wParam);
02044         if (lParam)
02045         {
02046             GuiConsoleWriteUserSettings(Console, GuiData);
02047         }
02048         break;
02049     default:
02050         Result = DefWindowProcW(hWnd, msg, wParam, lParam);
02051         break;
02052     }
02053 
02054     return Result;
02055 }
02056 
02057 static LRESULT CALLBACK
02058 GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
02059 {
02060     HWND NewWindow;
02061     LONG WindowCount;
02062     MSG Msg;
02063     PWCHAR Buffer, Title;
02064     PCSRSS_CONSOLE Console = (PCSRSS_CONSOLE) lParam;
02065 
02066 
02067 
02068     switch(msg)
02069     {
02070     case WM_CREATE:
02071         SetWindowLongW(hWnd, GWL_USERDATA, 0);
02072         return 0;
02073     case PM_CREATE_CONSOLE:
02074         Buffer = HeapAlloc(Win32CsrApiHeap, 0,
02075                            Console->Title.Length + sizeof(WCHAR));
02076         if (NULL != Buffer)
02077         {
02078             memcpy(Buffer, Console->Title.Buffer, Console->Title.Length);
02079             Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0';
02080             Title = Buffer;
02081         }
02082         else
02083         {
02084             Title = L"";
02085         }
02086         NewWindow = CreateWindowExW(WS_EX_CLIENTEDGE,
02087                                     L"ConsoleWindowClass",
02088                                     Title,
02089                                     WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
02090                                     CW_USEDEFAULT,
02091                                     CW_USEDEFAULT,
02092                                     CW_USEDEFAULT,
02093                                     CW_USEDEFAULT,
02094                                     NULL,
02095                                     NULL,
02096                                     (HINSTANCE) GetModuleHandleW(NULL),
02097                                     (PVOID) Console);
02098         if (NULL != Buffer)
02099         {
02100             HeapFree(Win32CsrApiHeap, 0, Buffer);
02101         }
02102         if (NULL != NewWindow)
02103         {
02104             SetWindowLongW(hWnd, GWL_USERDATA, GetWindowLongW(hWnd, GWL_USERDATA) + 1);
02105             ShowWindow(NewWindow, (int)wParam);
02106         }
02107         return (LRESULT) NewWindow;
02108     case PM_DESTROY_CONSOLE:
02109         /* Window creation is done using a PostMessage(), so it's possible that the
02110          * window that we want to destroy doesn't exist yet. So first empty the message
02111          * queue */
02112         while(PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE))
02113         {
02114             TranslateMessage(&Msg);
02115             DispatchMessageW(&Msg);
02116         }
02117         DestroyWindow(Console->hWindow);
02118         Console->hWindow = NULL;
02119         WindowCount = GetWindowLongW(hWnd, GWL_USERDATA);
02120         WindowCount--;
02121         SetWindowLongW(hWnd, GWL_USERDATA, WindowCount);
02122         if (0 == WindowCount)
02123         {
02124             NotifyWnd = NULL;
02125             DestroyWindow(hWnd);
02126             PrivateCsrssManualGuiCheck(-1);
02127             PostQuitMessage(0);
02128         }
02129         return 0;
02130     default:
02131         return DefWindowProcW(hWnd, msg, wParam, lParam);
02132     }
02133 }
02134 
02135 static DWORD WINAPI
02136 GuiConsoleGuiThread(PVOID Data)
02137 {
02138     MSG msg;
02139     PHANDLE GraphicsStartupEvent = (PHANDLE) Data;
02140 
02141     NotifyWnd = CreateWindowW(L"Win32CsrCreateNotify",
02142                               L"",
02143                               WS_OVERLAPPEDWINDOW,
02144                               CW_USEDEFAULT,
02145                               CW_USEDEFAULT,
02146                               CW_USEDEFAULT,
02147                               CW_USEDEFAULT,
02148                               NULL,
02149                               NULL,
02150                               (HINSTANCE) GetModuleHandleW(NULL),
02151                               NULL);
02152     if (NULL == NotifyWnd)
02153     {
02154         PrivateCsrssManualGuiCheck(-1);
02155         SetEvent(*GraphicsStartupEvent);
02156         return 1;
02157     }
02158 
02159     SetEvent(*GraphicsStartupEvent);
02160 
02161     while(GetMessageW(&msg, NULL, 0, 0))
02162     {
02163         TranslateMessage(&msg);
02164         DispatchMessageW(&msg);
02165     }
02166 
02167     return 1;
02168 }
02169 
02170 static BOOL
02171 GuiInit(VOID)
02172 {
02173     WNDCLASSEXW wc;
02174 
02175     if (NULL == NotifyWnd)
02176     {
02177         PrivateCsrssManualGuiCheck(+1);
02178     }
02179 
02180     wc.cbSize = sizeof(WNDCLASSEXW);
02181     wc.lpszClassName = L"Win32CsrCreateNotify";
02182     wc.lpfnWndProc = GuiConsoleNotifyWndProc;
02183     wc.style = 0;
02184     wc.hInstance = (HINSTANCE) GetModuleHandleW(NULL);
02185     wc.hIcon = NULL;
02186     wc.hCursor = NULL;
02187     wc.hbrBackground = NULL;
02188     wc.lpszMenuName = NULL;
02189     wc.cbClsExtra = 0;
02190     wc.cbWndExtra = 0;
02191     wc.hIconSm = NULL;
02192     if (RegisterClassExW(&wc) == 0)
02193     {
02194         DPRINT1("Failed to register notify wndproc\n");
02195         return FALSE;
02196     }
02197 
02198     wc.cbSize = sizeof(WNDCLASSEXW);
02199     wc.lpszClassName = L"ConsoleWindowClass";
02200     wc.lpfnWndProc = GuiConsoleWndProc;
02201     wc.style = 0;
02202     wc.hInstance = (HINSTANCE) GetModuleHandleW(NULL);
02203     wc.hIcon = LoadIconW(GetModuleHandleW(L"win32csr"), MAKEINTRESOURCEW(1));
02204     wc.hCursor = LoadCursorW(NULL, (LPCWSTR) IDC_ARROW);
02205     wc.hbrBackground = CreateSolidBrush(RGB(0,0,0));
02206     wc.lpszMenuName = NULL;
02207     wc.cbClsExtra = 0;
02208     wc.cbWndExtra = 0;
02209     wc.hIconSm = LoadImageW(GetModuleHandleW(L"win32csr"), MAKEINTRESOURCEW(1), IMAGE_ICON,
02210                             GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
02211                             LR_SHARED);
02212     if (RegisterClassExW(&wc) == 0)
02213     {
02214         DPRINT1("Failed to register console wndproc\n");
02215         return FALSE;
02216     }
02217 
02218     return TRUE;
02219 }
02220 
02221 static VOID WINAPI
02222 GuiInitScreenBuffer(PCSRSS_CONSOLE Console, PCSRSS_SCREEN_BUFFER Buffer)
02223 {
02224     Buffer->DefaultAttrib = DEFAULT_ATTRIB;
02225 }
02226 
02227 static BOOL WINAPI
02228 GuiChangeTitle(PCSRSS_CONSOLE Console)
02229 {
02230     PWCHAR Buffer, Title;
02231 
02232     Buffer = HeapAlloc(Win32CsrApiHeap, 0,
02233                        Console->Title.Length + sizeof(WCHAR));
02234     if (NULL != Buffer)
02235     {
02236         memcpy(Buffer, Console->Title.Buffer, Console->Title.Length);
02237         Buffer[Console->Title.Length / sizeof(WCHAR)] = L'\0';
02238         Title = Buffer;
02239     }
02240     else
02241     {
02242         Title = L"";
02243     }
02244 
02245     SendMessageW(Console->hWindow, WM_SETTEXT, 0, (LPARAM) Title);
02246 
02247     if (NULL != Buffer)
02248     {
02249         HeapFree(Win32CsrApiHeap, 0, Buffer);
02250     }
02251 
02252     return TRUE;
02253 }
02254 
02255 static BOOL WINAPI
02256 GuiChangeIcon(PCSRSS_CONSOLE Console, HICON hWindowIcon)
02257 {
02258     SendMessageW(Console->hWindow, WM_SETICON, ICON_BIG, (LPARAM)hWindowIcon);
02259     SendMessageW(Console->hWindow, WM_SETICON, ICON_SMALL, (LPARAM)hWindowIcon);
02260 
02261     return TRUE;
02262 }
02263 
02264 static VOID WINAPI
02265 GuiCleanupConsole(PCSRSS_CONSOLE Console)
02266 {
02267     SendMessageW(NotifyWnd, PM_DESTROY_CONSOLE, 0, (LPARAM) Console);
02268 }
02269 
02270 static CSRSS_CONSOLE_VTBL GuiVtbl =
02271 {
02272     GuiInitScreenBuffer,
02273     GuiWriteStream,
02274     GuiDrawRegion,
02275     GuiSetCursorInfo,
02276     GuiSetScreenInfo,
02277     GuiUpdateScreenInfo,
02278     GuiChangeTitle,
02279     GuiCleanupConsole,
02280     GuiChangeIcon,
02281     GuiResizeBuffer,
02282 };
02283 
02284 NTSTATUS FASTCALL
02285 GuiInitConsole(PCSRSS_CONSOLE Console, int ShowCmd)
02286 {
02287     HANDLE GraphicsStartupEvent;
02288     HANDLE ThreadHandle;
02289     PGUI_CONSOLE_DATA GuiData;
02290 
02291     if (! ConsInitialized)
02292     {
02293         ConsInitialized = TRUE;
02294         if (! GuiInit())
02295         {
02296             ConsInitialized = FALSE;
02297             return STATUS_UNSUCCESSFUL;
02298         }
02299     }
02300 
02301     Console->Vtbl = &GuiVtbl;
02302     if (NULL == NotifyWnd)
02303     {
02304         GraphicsStartupEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
02305         if (NULL == GraphicsStartupEvent)
02306         {
02307             return STATUS_UNSUCCESSFUL;
02308         }
02309 
02310         ThreadHandle = CreateThread(NULL,
02311                                     0,
02312                                     GuiConsoleGuiThread,
02313                                     (PVOID) &GraphicsStartupEvent,
02314                                     0,
02315                                     NULL);
02316         if (NULL == ThreadHandle)
02317         {
02318             CloseHandle(GraphicsStartupEvent);
02319             DPRINT1("Win32Csr: Failed to create graphics console thread. Expect problems\n");
02320             return STATUS_UNSUCCESSFUL;
02321         }
02322         SetThreadPriority(ThreadHandle, THREAD_PRIORITY_HIGHEST);
02323         CloseHandle(ThreadHandle);
02324 
02325         WaitForSingleObject(GraphicsStartupEvent, INFINITE);
02326         CloseHandle(GraphicsStartupEvent);
02327 
02328         if (NULL == NotifyWnd)
02329         {
02330             DPRINT1("Win32Csr: Failed to create notification window.\n");
02331             return STATUS_UNSUCCESSFUL;
02332         }
02333     }
02334     GuiData = HeapAlloc(Win32CsrApiHeap, HEAP_ZERO_MEMORY,
02335                         sizeof(GUI_CONSOLE_DATA));
02336     if (!GuiData)
02337     {
02338         DPRINT1("Win32Csr: Failed to create GUI_CONSOLE_DATA\n");
02339         return STATUS_UNSUCCESSFUL;
02340     }
02341 
02342     Console->PrivateData = (PVOID) GuiData;
02343     /*
02344      * we need to wait untill the GUI has been fully initialized
02345      * to retrieve custom settings i.e. WindowSize etc..
02346      * Ideally we could use SendNotifyMessage for this but its not
02347      * yet implemented.
02348      *
02349      */
02350     GuiData->hGuiInitEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
02351     /* create console */
02352     PostMessageW(NotifyWnd, PM_CREATE_CONSOLE, ShowCmd, (LPARAM) Console);
02353 
02354     /* wait untill initialization has finished */
02355     WaitForSingleObject(GuiData->hGuiInitEvent, INFINITE);
02356     DPRINT("received event Console %p GuiData %p X %d Y %d\n", Console, Console->PrivateData, Console->Size.X, Console->Size.Y);
02357     CloseHandle(GuiData->hGuiInitEvent);
02358     GuiData->hGuiInitEvent = NULL;
02359 
02360     return STATUS_SUCCESS;
02361 }
02362 
02363 /* EOF */

Generated on Sat May 26 2012 04:37:33 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.