|
|
// Copyright (c) 1995, Microsoft Corporation, all rights reserved
//
// terminal.c
// Remote Access Common Dialog APIs
// Terminal dialogs
//
// 08/28/95 Steve Cobb
#include "rasdlgp.h"
#include "rasscrpt.h"
#define WM_EOLFROMDEVICE (WM_USER+999)
#define SECS_ReceiveTimeout 1
#define SIZE_ReceiveBuf 1024
#define SIZE_SendBuf 1
//----------------------------------------------------------------------------
// Help maps
//----------------------------------------------------------------------------
static DWORD g_adwItHelp[] = { CID_IT_EB_Screen, HID_IT_EB_Screen, CID_IT_ST_IpAddress, HID_IT_CC_IpAddress, CID_IT_CC_IpAddress, HID_IT_CC_IpAddress, IDOK, HID_IT_PB_Done, 0, 0 };
//----------------------------------------------------------------------------
// Local datatypes (alphabetically)
//----------------------------------------------------------------------------
// Interactive terminal dialog argument block.
//
typedef struct _ITARGS { DWORD sidTitle; TCHAR* pszIpAddress; HRASCONN hrasconn; PBENTRY* pEntry; RASDIALPARAMS* pRdp; } ITARGS;
// Interactive terminal dialog context block.
//
typedef struct _ITINFO { // Caller's arguments to the dialog.
//
ITARGS* pArgs;
// Handle of this dialog and some of it's controls.
//
HWND hwndDlg; HWND hwndEbScreen; HWND hwndCcIpAddress; HWND hwndPbBogus;
// Set when waiting for the thread to terminate.
//
BOOL fAbortReceiveLoop;
// Original dialog and screen edit box window proc.
//
WNDPROC pOldWndProc; WNDPROC pOldEbScreenWndProc;
// buffers for RasScriptSend/RasScriptReceive.
//
BYTE pbyteReceiveBuf[SIZE_ReceiveBuf]; BYTE pbyteSendBuf[SIZE_SendBuf];
// handle to active script on this connection
//
HANDLE hscript;
// Screen edit box font and brush.
//
HFONT hfontEbScreen; HBRUSH hbrEbScreen; } ITINFO;
//----------------------------------------------------------------------------
// Local prototypes (alphabetically)
//----------------------------------------------------------------------------
INT_PTR CALLBACK ItDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam );
BOOL ItCommand( IN ITINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl );
LRESULT APIENTRY ItEbScreenWndProc( HWND hwnd, UINT unMsg, WPARAM wParam, LPARAM lParam );
BOOL ItInit( IN HWND hwndDlg, IN ITARGS* pArgs );
BOOL ItRasApiComplete( IN ITINFO* pInfo );
DWORD ItReceiveMonitorThread( LPVOID pThreadArg );
VOID ItTerm( IN HWND hwndDlg );
VOID ItViewScriptLog( IN HWND hwndOwner );
LRESULT APIENTRY ItWndProc( HWND hwnd, UINT unMsg, WPARAM wParam, LPARAM lParam );
//----------------------------------------------------------------------------
// Terminal dialog
// Listed alphabetically following stub API and dialog proc
//----------------------------------------------------------------------------
BOOL TerminalDlg( IN PBENTRY* pEntry, IN RASDIALPARAMS* pRdp, IN HWND hwndOwner, IN HRASCONN hrasconn, IN DWORD sidTitle, IN OUT TCHAR* pszIpAddress )
// Pops-up the Terminal dialog. 'HwndOwner' is the window owning the
// dialog. 'Hrasconn' is the RAS connection handle to talk on.
// 'SidTitle' is ID of the string displayed as the window caption.
// 'PszIpAddress' is caller's buffer of at least 16 characters containing
// the initial IP address on entry and the edited IP address on exit. If
// 'pszIpAddress' is empty, no IP address field is displayed.
//
// Returns true if user pressed OK and succeeded, false if he pressed
// Cancel or encountered an error.
//
{ INT_PTR nStatus; INT nDlg; ITARGS args;
TRACE( "TerminalDlg" );
if (pszIpAddress && pszIpAddress[ 0 ]) {
InitCommonControls(); IpAddrInit( g_hinstDll, SID_PopupTitle, SID_BadIpAddrRange );
nDlg = DID_IT_SlipTerminal; } else { nDlg = DID_IT_Terminal; }
args.pszIpAddress = pszIpAddress; args.sidTitle = sidTitle; args.hrasconn = hrasconn; args.pEntry = pEntry; args.pRdp = pRdp;
nStatus = DialogBoxParam( g_hinstDll, MAKEINTRESOURCE( nDlg ), hwndOwner, ItDlgProc, (LPARAM )&args );
if (nStatus == -1) { TRACE1("TerminalDlg: GLE=%d", GetLastError()); ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL ); nStatus = FALSE; }
return (nStatus) ? TRUE : FALSE; }
INT_PTR CALLBACK ItDlgProc( IN HWND hwnd, IN UINT unMsg, IN WPARAM wparam, IN LPARAM lparam )
// DialogProc callback for the Interactive Terminal dialog. Parameters
// and return value are as described for standard windows 'DialogProc's.
//
{ #if 0
TRACE4( "ItDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif
switch (unMsg) { case WM_INITDIALOG: { return ItInit( hwnd, (ITARGS* )lparam ); }
case WM_HELP: case WM_CONTEXTMENU: { ContextHelp( g_adwItHelp, hwnd, unMsg, wparam, lparam ); break; }
case WM_COMMAND: { ITINFO* pInfo = (ITINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT(pInfo);
return ItCommand( pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam ); }
case WM_RASAPICOMPLETE: { ITINFO* pInfo = (ITINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT(pInfo);
// The notification code from the scripting-thread is in 'lparam'
//
switch (lparam) { case SCRIPTCODE_Done: { EndDialog(hwnd, TRUE); return TRUE; }
case SCRIPTCODE_Halted: { MSGARGS msg;
// The script has halted programmatically, for instance
// because of an explicit "halt" command. Show a popup
// indicating things have stopped, but don't dismiss the
// dialog.
//
ZeroMemory(&msg, sizeof(msg)); msg.dwFlags = MB_OK | MB_ICONINFORMATION; MsgDlg( hwnd, SID_OP_ScriptHalted, &msg ); return TRUE; }
case SCRIPTCODE_HaltedOnError: { MSGARGS msg; INT nResponse;
// There was an execution-error in the script; show a
// popup asking if the user wants to view the errors, and
// if the user clicks 'Yes' invoke Notepad on the file
// %windir%\system32\ras\script.log. Since this is an
// error condition, dismiss the dialog.
//
ZeroMemory(&msg, sizeof(msg)); msg.dwFlags = MB_YESNO | MB_ICONQUESTION; nResponse = MsgDlg( hwnd, SID_OP_ScriptHaltedOnError, &msg );
if (nResponse == IDYES) { ItViewScriptLog( hwnd ); }
EndDialog(hwnd, FALSE); return TRUE; }
case SCRIPTCODE_KeyboardEnable: { // Allow keyboard input in the edit-box.
//
EnableWindow(pInfo->hwndEbScreen, TRUE); return TRUE; }
case SCRIPTCODE_KeyboardDisable: { // Disallow keyboard input in the edit-box; if the
// edit-box currently has the focus, we first set the
// focus to the 'Done' button.
//
if (GetFocus() == pInfo->hwndEbScreen) { SetFocus( GetDlgItem (hwnd, IDOK ) ); }
EnableWindow( pInfo->hwndEbScreen, FALSE ); return TRUE; }
case SCRIPTCODE_IpAddressSet: { DWORD dwErr; CHAR szAddress[ RAS_MaxIpAddress + 1 ];
// The script is notifying us that the IP address has been
// changed programmatically.
//
// Get the new IP address.
//
dwErr = RasScriptGetIpAddress( pInfo->hscript, szAddress );
if (dwErr == NO_ERROR) { TCHAR* psz;
// Save the new IP address.
//
psz = StrDupTFromA(szAddress);
if (NULL != psz) { // Whistler bug 224074 use only lstrcpyn's to
// prevent maliciousness
//
lstrcpyn( pInfo->pArgs->pszIpAddress, psz, TERM_IpAddress); Free0(psz); }
// Display it in the IP-address edit-box
//
if (pInfo->hwndCcIpAddress) { SetWindowText( pInfo->hwndCcIpAddress, pInfo->pArgs->pszIpAddress ); } }
return TRUE; }
case SCRIPTCODE_InputNotify: { // Handle input-notification.
//
return ItRasApiComplete( pInfo ); }
return TRUE; } }
case WM_DESTROY: { ItTerm( hwnd ); break; } }
return FALSE; }
BOOL ItCommand( IN ITINFO* pInfo, IN WORD wNotification, IN WORD wId, IN HWND hwndCtrl )
// Called on WM_COMMAND. 'PInfo' is the dialog context. 'WNotification'
// is the notification code of the command. 'wId' is the control/menu
// identifier of the command. 'HwndCtrl' is the control window handle of
// the command.
//
// Returns true if processed message, false otherwise.
//
{ TRACE3( "ItCommand(n=%d,i=%d,c=$%x)", (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
switch (wId) { case CID_IT_EB_Screen: {
// Turn off the default button whenever the terminal window
// has the focus. Pressing [Return] in the terminal acts like
// a normal terminal.
//
Button_MakeDefault( pInfo->hwndDlg, pInfo->hwndPbBogus );
// Don't select the entire string on entry.
//
Edit_SetSel( pInfo->hwndEbScreen, (UINT )-1, 0 );
break; }
case IDOK: { TRACE("OK pressed");
if (pInfo->pArgs->pszIpAddress) { GetWindowText( pInfo->hwndCcIpAddress, pInfo->pArgs->pszIpAddress, 16 ); }
EndDialog( pInfo->hwndDlg, TRUE ); return TRUE; }
case IDCANCEL: TRACE("Cancel pressed"); EndDialog( pInfo->hwndDlg, FALSE ); return TRUE; }
return FALSE; }
LRESULT APIENTRY ItEbScreenWndProc( HWND hwnd, UINT unMsg, WPARAM wParam, LPARAM lParam )
// Subclassed terminal edit box window procedure.
//
// Return value depends on message type.
//
{ ITINFO* pInfo; BOOL fSend; BOOL fSendTab;
fSend = fSendTab = FALSE;
if (unMsg == WM_EOLFROMDEVICE) { // An end-of-line in the device input was received. Send a linefeed
// character to the window.
//
wParam = '\n'; unMsg = WM_CHAR; } else { BOOL fCtrlKeyDown = (GetKeyState( VK_CONTROL ) < 0); BOOL fShiftKeyDown = (GetKeyState( VK_SHIFT ) < 0);
if (unMsg == WM_KEYDOWN) { // The key was pressed by the user.
//
if (wParam == VK_RETURN && !fCtrlKeyDown && !fShiftKeyDown) { // Enter key pressed without Shift or Ctrl is discarded. This
// prevents Enter from being interpreted as "press default
// button" when pressed in the edit box.
//
return 0; }
if (fCtrlKeyDown && wParam == VK_TAB) { fSend = TRUE; fSendTab = TRUE; } } else if (unMsg == WM_CHAR) { // The character was typed by the user.
//
if (wParam == VK_TAB) { // Ignore tabs...Windows sends this message when Tab (leave
// field) is pressed but not when Ctrl+Tab (insert a TAB
// character) is pressed...weird.
//
return 0; }
fSend = TRUE; } }
pInfo = (ITINFO* )GetWindowLongPtr( GetParent( hwnd ), DWLP_USER ); ASSERT(pInfo);
if (fSend) { DWORD dwErr;
pInfo->pbyteSendBuf[ 0 ] = (BYTE )wParam; dwErr = RasScriptSend( pInfo->hscript, pInfo->pbyteSendBuf, SIZE_SendBuf); if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_RasPortSend, dwErr, NULL ); }
if (!fSendTab) { return 0; } }
// Call the previous window procedure for everything else.
//
return CallWindowProc( pInfo->pOldEbScreenWndProc, hwnd, unMsg, wParam, lParam ); }
BOOL ItInit( IN HWND hwndDlg, IN ITARGS* pArgs )
// Called on WM_INITDIALOG. 'hwndDlg' is the handle of the phonebook
// dialog window. 'pEntry' is caller's entry as passed to the stub API.
//
// Return false if focus was set, true otherwise, i.e. as defined for
// WM_INITDIALOG.
//
{ DWORD dwErr; ITINFO* pInfo; WORD wReceiveSize; WORD wSendSize; WORD wSize; DWORD dwThreadId;
TRACE( "ItInit" );
// Allocate the dialog context block. Initialize minimally for proper
// cleanup, then attach to the dialog window.
//
{ pInfo = Malloc( sizeof(*pInfo) ); if (!pInfo) { ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL ); EndDialog( hwndDlg, FALSE ); return TRUE; }
ZeroMemory( pInfo, sizeof(*pInfo) ); pInfo->pArgs = pArgs; pInfo->hwndDlg = hwndDlg;
SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo ); TRACE( "Context set" ); }
pInfo->hwndEbScreen = GetDlgItem( hwndDlg, CID_IT_EB_Screen ); ASSERT( pInfo->hwndEbScreen ); pInfo->hwndPbBogus = GetDlgItem( hwndDlg, CID_IT_PB_BogusButton ); ASSERT( pInfo->hwndPbBogus ); if (pArgs->pszIpAddress && pArgs->pszIpAddress[0]) { pInfo->hwndCcIpAddress = GetDlgItem( hwndDlg, CID_IT_CC_IpAddress ); ASSERT( pInfo->hwndCcIpAddress );
if (*pArgs->pszIpAddress) { SetWindowText( pInfo->hwndCcIpAddress, pArgs->pszIpAddress ); } else { SetWindowText( pInfo->hwndCcIpAddress, TEXT("0.0.0.0") ); } }
// Set the dialog title.
//
{ TCHAR* psz = PszFromId( g_hinstDll, pArgs->sidTitle ); if (psz) { SetWindowText( hwndDlg, psz ); Free( psz ); } }
// Subclass the dialog and screen edit box.
//
pInfo->pOldWndProc = (WNDPROC )SetWindowLongPtr( pInfo->hwndDlg, GWLP_WNDPROC, (ULONG_PTR )ItWndProc ); pInfo->pOldEbScreenWndProc = (WNDPROC )SetWindowLongPtr( pInfo->hwndEbScreen, GWLP_WNDPROC, (ULONG_PTR )ItEbScreenWndProc );
// Prepare for special TTY-ish painting.
//
pInfo->hfontEbScreen = SetFont( pInfo->hwndEbScreen, TEXT("Courier New"), FIXED_PITCH | FF_MODERN, 9, FALSE, FALSE, FALSE, FALSE );
pInfo->hbrEbScreen = (HBRUSH )GetStockObject( BLACK_BRUSH );
// Initialize script-processing/data-receipt
//
{ CHAR* pszUserName; CHAR* pszPassword;
pszUserName = StrDupAFromT( pInfo->pArgs->pRdp->szUserName );
// Whistler bug 254385 encode password when not being used
// Assumed password was encoded by DpInteractive() -or- DwTerminalDlg()
//
DecodePassword( pInfo->pArgs->pRdp->szPassword ); pszPassword = StrDupAFromT( pInfo->pArgs->pRdp->szPassword ); EncodePassword( pInfo->pArgs->pRdp->szPassword );
// Initialize the script. The script DLL is 'delayload' hence the
// exception handling.
//
__try { dwErr = RasScriptInit( pInfo->pArgs->hrasconn, pInfo->pArgs->pEntry, pszUserName, pszPassword, RASSCRIPT_NotifyOnInput | RASSCRIPT_HwndNotify, (HANDLE)hwndDlg, &pInfo->hscript ); TRACE1( "RasScriptInit(e=%d)", dwErr ); } __except( EXCEPTION_EXECUTE_HANDLER ) { ErrorDlg( hwndDlg, SID_OP_LoadDlg, STATUS_PROCEDURE_NOT_FOUND, NULL ); EndDialog( hwndDlg, FALSE ); return TRUE; }
Free0( pszUserName );
// Whistler bug 254385 encode password when not being used
// Whistler bug 275526 NetVBL BVT Break: Routing BVT broken
//
if (pszPassword) { ZeroMemory( pszPassword, strlen(pszPassword) + 1 ); Free( pszPassword ); }
// See whether anything went wrong in the script-initialization
//
if (dwErr == ERROR_SCRIPT_SYNTAX) { MSGARGS msg; INT nResponse;
// There was a syntax error in the script; show a popup asking if
// the user wants to view the errors, and if so bring up Notepad
// on %windir%\system32\ras\script.log.
//
// Center the dialog on our parent rather than on the dialog,
// since the dialog is not yet visible.
//
ZeroMemory(&msg, sizeof(msg)); msg.dwFlags = MB_YESNO | MB_ICONQUESTION; nResponse = MsgDlg( GetParent( hwndDlg ), SID_ConfirmViewScriptLog, &msg );
if (nResponse == IDYES) { ItViewScriptLog( hwndDlg ); }
// Terminate the dialog. This hangs up the connection.
//
EndDialog( hwndDlg, FALSE );
return TRUE; } else if (dwErr != 0) { ErrorDlg( hwndDlg, SID_OP_LoadDlg, dwErr, NULL ); EndDialog( hwndDlg, FALSE ); return TRUE; } }
// Center dialog on the owner window, and hide the owner window which is
// currently assumed to be the dial progress dialog.
//
CenterWindow( hwndDlg, GetParent( hwndDlg ) ); SetOffDesktop( GetParent( hwndDlg ), SOD_MoveOff, NULL );
// Add context help button to title bar.
//
AddContextHelpButton( hwndDlg );
// Set initial focus to the screen.
//
SetFocus( pInfo->hwndEbScreen ); return FALSE; }
BOOL ItRasApiComplete( IN ITINFO* pInfo )
// Called on WM_RASAPICOMPLETE, i.e. an asynchronous RasPortReceive
// completed. 'PInfo' is the dialog context block.
//
// Returns true if processed the message, false otherwise.
//
{ DWORD dwErr; DWORD dwSize = SIZE_ReceiveBuf; RASMAN_INFO info;
TRACE( "RasScriptReceive" ); dwErr = RasScriptReceive( pInfo->hscript, pInfo->pbyteReceiveBuf, &dwSize); TRACE1( "RasScriptReceive=%d",dwErr ); if (dwErr != 0) { ErrorDlg( pInfo->hwndDlg, SID_OP_RasGetInfo, dwErr, NULL ); EndDialog( pInfo->hwndDlg, FALSE ); return TRUE; }
info.RI_BytesReceived = (WORD )dwSize;
// Send the device talk to the terminal edit box.
//
if (info.RI_BytesReceived > 0) { CHAR szBuf[ SIZE_ReceiveBuf + 1 ]; CHAR* pch = szBuf; WORD i;
TRACE1( "Read %d", info.RI_BytesReceived );
for (i = 0; i < info.RI_BytesReceived; ++i) { CHAR ch = pInfo->pbyteReceiveBuf[ i ];
// Formatting: Converts CRs to LFs (there seems to be no VK_ for
// LF) and throws away LFs. This prevents the user from exiting
// the dialog when they press Enter (CR) in the terminal screen.
// LF looks like CRLF in the edit box. Also, throw away TABs
// because otherwise they change focus to the next control.
//
if (ch == VK_RETURN) { // Must send whenever end-of-line is encountered because
// EM_REPLACESEL doesn't handle VK_RETURN characters well
// (prints garbage).
//
*pch = '\0';
// Turn off current selection, if any, and replace the null
// selection with the current buffer. This has the effect of
// adding the buffer at the caret. Finally, send the EOL to
// the window which (unlike EM_REPLACESEL) handles it
// correctly.
//
Edit_SetSel( pInfo->hwndEbScreen, (UINT )-1, 0 ); SendMessageA( pInfo->hwndEbScreen, EM_REPLACESEL, (WPARAM )0, (LPARAM )szBuf ); SendMessage( pInfo->hwndEbScreen, WM_EOLFROMDEVICE, 0, 0 );
// Start afresh on the output buffer.
//
pch = szBuf; continue; } else if (ch == '\n' || ch == VK_TAB) { continue; }
*pch++ = ch; }
*pch = '\0';
if (pch != szBuf) { // Send the last remnant of the line.
//
Edit_SetSel( pInfo->hwndEbScreen, (UINT )-1, 0 ); SendMessageA( pInfo->hwndEbScreen, EM_REPLACESEL, (WPARAM )0, (LPARAM )szBuf ); } }
return TRUE; }
VOID ItTerm( IN HWND hwndDlg )
// Called on WM_DESTROY. 'HwndDlg' is that handle of the dialog window.
//
{ ITINFO* pInfo = (ITINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER );
TRACE( "ItTerm" );
if (pInfo) { // Close RAS script resources
//
if (pInfo->hscript) { TRACE( "Stop script processing" );
// Shutdown script processing
//
TRACE( "RasScriptTerm" ); RasScriptTerm( pInfo->hscript ); TRACE( "RasScriptTerm done" ); }
// De-activate WndProc hooks.
//
if (pInfo->pOldEbScreenWndProc) { SetWindowLongPtr( pInfo->hwndEbScreen, GWLP_WNDPROC, (ULONG_PTR )pInfo->pOldEbScreenWndProc ); } if (pInfo->pOldWndProc) { SetWindowLongPtr( pInfo->hwndDlg, GWLP_WNDPROC, (ULONG_PTR )pInfo->pOldWndProc ); }
if (pInfo->hfontEbScreen) { DeleteObject( (HGDIOBJ )pInfo->hfontEbScreen ); }
SetOffDesktop( GetParent( hwndDlg ), SOD_MoveBackFree, NULL );
Free( pInfo ); } }
VOID ItViewScriptLog( IN HWND hwndOwner )
// Starts notepad.exe on the script log file, script.log. 'HwndOwner' is
// the window to center any error popup on.
//
{ DWORD dwSize; TCHAR szCmd[ (MAX_PATH * 2) + 50 + 1 ]; TCHAR* pszCmd; STARTUPINFO si; PROCESS_INFORMATION pi; BOOL f;
// Format the command-line string invoking Notepad on the script-log; note
// the double-quotes around the script-log's path, which are needed since
// RASSCRIPT_LOG is %windir%\system32\ras\script.log and so the expanded
// result may contain spaces.
//
wsprintf( szCmd, TEXT("notepad.exe \"%s\""), TEXT(RASSCRIPT_LOG) );
// Get the size of the expanded command-line
//
dwSize = ExpandEnvironmentStrings(szCmd, NULL, 0);
// Allocate enough space for the expanded command-line
//
pszCmd = Malloc( (dwSize + 1) * sizeof(TCHAR) ); if (!pszCmd) { ErrorDlg( hwndOwner, SID_OP_LoadScriptLog, GetLastError(), NULL ); return; }
// Expand the command-line into the allocated space
//
ExpandEnvironmentStrings(szCmd, pszCmd, dwSize);
// Initialize the startup-info structure
//
ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si);
// Launch Notepad on the script-log.
//
f = CreateProcess( NULL, pszCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi ); Free(pszCmd);
if (f) { CloseHandle( pi.hThread ); CloseHandle( pi.hProcess ); } else { ErrorDlg( hwndOwner, SID_OP_LoadScriptLog, GetLastError(), NULL ); } }
LRESULT APIENTRY ItWndProc( HWND hwnd, UINT unMsg, WPARAM wParam, LPARAM lParam )
// Subclassed dialog window procedure.
//
// Return value depends on message type.
//
{ ITINFO* pInfo = (ITINFO* )GetWindowLongPtr( hwnd, DWLP_USER ); ASSERT(pInfo);
#if 0
TRACE4( "ItWndProc(h=$%x,m=$%x,w=$%x,l=$%x)", (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam ); #endif
switch (unMsg) { case WM_CTLCOLOREDIT: { // Set terminal screen colors to TTY-ish green on black.
//
if (pInfo->hbrEbScreen) { SetBkColor( (HDC )wParam, RGB( 0, 0, 0 ) ); SetTextColor( (HDC )wParam, RGB( 2, 208, 44 ) ); return (LRESULT )pInfo->hbrEbScreen; } break; } }
// Call the previous window procedure for everything else.
//
return CallWindowProc( pInfo->pOldWndProc, hwnd, unMsg, wParam, lParam ); }
|