📄 csecureedit.cpp
字号:
//////////////////////////////////////////////////////////////////////////////
// CSecureEdit.cpp
//
// Implementation of class CSecureEdit.
//////////////////////////////////////////////////////////////////////////////
// $Id: CSecureEdit.cpp,v 1.7 1999/03/08 23:32:42 nryan Exp $
// Copyright (C) 1998 by Network Associates, Inc.
// All rights reserved.
#include "StdAfx.h"
#include <new.h>
#include "Required.h"
#include "UtilityFunctions.h"
#include "CSecureEdit.h"
#include "Globals.h"
////////////
// Constants
////////////
// Hide typing by default?
const PGPBoolean kDefaultCSecureEditHideTyping = TRUE;
///////////////////////////
// MFC specific definitions
///////////////////////////
// These defines are needed because ClassWizard is intelligent enough to
// realize I'm mapping to the same function but too dumb to outsmart the
// preprocessor.
#define DontClear DoNothing
#define DontCopy DoNothing
#define DontCut DoNothing
#define DontPaste DoNothing
#define DontUndo DoNothing
BEGIN_MESSAGE_MAP(CSecureEdit, CEdit)
//{{AFX_MSG_MAP(CSecureEdit)
ON_WM_KEYDOWN()
ON_WM_CHAR()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONDBLCLK()
ON_WM_MOUSEMOVE()
ON_CONTROL_REFLECT(EN_SETFOCUS, OnSetFocus)
ON_MESSAGE(WM_CLEAR, DontClear)
ON_MESSAGE(WM_COPY, DontCopy)
ON_MESSAGE(WM_CUT, DontCut)
ON_MESSAGE(WM_PASTE, DontPaste)
ON_MESSAGE(WM_UNDO, DontUndo)
ON_CONTROL_REFLECT(EN_KILLFOCUS, OnKillFocus)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////
// CSecureEdit public custom functions and non-default message handlers
///////////////////////////////////////////////////////////////////////
// The CSecureEdit default constructor.
CSecureEdit::CSecureEdit() : mLockedMem(sizeof(SecureString))
{
mCurCharPos = 0;
mCurNumSpaces = 0;
mHideTyping = kDefaultCSecureEditHideTyping;
mMaxSizeContents = kMaxStringSize;
// Pick from 1-3 random spaces to be used for each character.
srand((PGPUInt32) PGPdiskGetTicks());
for (PGPUInt32 i=0; i<kMaxStringSize; i++)
{
PGPUInt32 num = rand(); // rand roolz!
if (num < RAND_MAX/3)
mSpacesPerChar[i] = 1;
else if (num < RAND_MAX*2/3)
mSpacesPerChar[i] = 2;
else
mSpacesPerChar[i] = 3;
}
// Make sure our locked memory initialized correctly.
mInitErr = mLockedMem.mInitErr;
// Construct the secure string object.
if (mInitErr.IsntError())
{
mContents = new (mLockedMem.GetPtr()) SecureString; // <new.h>
mContents->ClearString();
}
}
// The CSecureEdit destructor destructs the SecureString we constructed in our
// locked memory.
CSecureEdit::~CSecureEdit()
{
if (mContents)
mContents->~SecureString(); // we used placement new
}
// ClearEditContents erases the contents of the edit box.
void
CSecureEdit::ClearEditContents()
{
mContents->ClearString();
SetWindowText(kEmptyString);
mCurCharPos = 0;
// Notify parent of the edit box change.
WPARAM wParam = (WPARAM) MakeLong(GetDlgCtrlID(), EN_CHANGE);
LPARAM lParam = (LPARAM) GetSafeHwnd();
GetParent()->PostMessage(WM_COMMAND, wParam, lParam);
}
// SetHideTypingPref shows or hides the text the user is typing. It returns
// the previous value of the preference.
PGPBoolean
CSecureEdit::SetHideTypingPref(PGPBoolean newHideValue)
{
CString text;
PGPBoolean oldHideValue = mHideTyping;
mHideTyping = newHideValue;
try
{
// If hiding the text, replace it with all spaces. If showing the
// text, extract the contents from mContents and set the edit box.
if (!oldHideValue && newHideValue)
{
FillEditBoxWithSpaces();
}
else if (oldHideValue && !newHideValue)
{
FillEditBoxWithContents();
}
}
catch (CMemoryException *ex)
{
ex->Delete();
}
return oldHideValue;
}
// SetMaxSizeContents sets the maximum size of the edit box. It returns the
// value of the old size. Nothing is changed if there is already this much
// or more text in the edit box.
PGPUInt32
CSecureEdit::SetMaxSizeContents(PGPUInt32 maxSize)
{
PGPUInt32 oldSize = mMaxSizeContents;
if (maxSize > mContents->GetLength())
mMaxSizeContents = maxSize;
return oldSize;
}
//////////////////////////////////////////////////////////////////////////
// CSecureEdit protected custom functions and non-default message handlers
//////////////////////////////////////////////////////////////////////////
// FillEditBoxWithContents fills the edit box with the actual string
// contents.
void
CSecureEdit::FillEditBoxWithContents()
{
pgpAssert(!mHideTyping);
try
{
CString text;
// Get real contents.
mContents->GetString(text.GetBuffer(kMaxStringSize),
kMaxStringSize);
text.ReleaseBuffer();
// Put the contents in the edit box.
SetWindowText(text);
SetSel(mCurCharPos, mCurCharPos);
// Notify parent of the edit box change.
NotifyParentOfEditChange();
}
catch (CMemoryException *ex)
{
ex->Delete();
}
}
// FillEditBoxWithSpaces fills the edit box with predetermined amount of
// spaces instead of characters.
void
CSecureEdit::FillEditBoxWithSpaces()
{
pgpAssert(mHideTyping);
try
{
CString spaces;
mCurNumSpaces = 0;
// Construct string of spaces.
for (PGPUInt32 i = 0; i < mContents->GetLength(); i++)
{
mCurNumSpaces += mSpacesPerChar[i];
}
pgpFillMemory(spaces.GetBuffer(mCurNumSpaces), mCurNumSpaces, ' ');
spaces.ReleaseBuffer(mCurNumSpaces);
// Put the spaces in the edit box.
SetWindowText(spaces);
SetSel(mCurNumSpaces, mCurNumSpaces);
// Notify parent of the edit box change.
NotifyParentOfEditChange();
}
catch (CMemoryException *ex)
{
ex->Delete();
}
}
LRESULT
CALLBACK
CSecureEdit::PGPdiskSecurityHookProc(INT iCode, WPARAM wParam, LPARAM lParam)
{
return 0;
}
void
CSecureEdit::InstallSecurityHooks()
{
PGPUInt32 dwPhraseThreadID = GetCurrentThreadId();
// These are just to prevent sniffers from seeing these messages.
mHhookKeyboard = SetWindowsHookEx (WH_KEYBOARD,
PGPdiskSecurityHookProc, NULL, dwPhraseThreadID);
mHhookCBT = SetWindowsHookEx(WH_CBT, PGPdiskSecurityHookProc, NULL,
dwPhraseThreadID);
mHhookGetMessage = SetWindowsHookEx(WH_GETMESSAGE,
PGPdiskSecurityHookProc, NULL, dwPhraseThreadID);
mHhookMsgFilter = SetWindowsHookEx(WH_MSGFILTER,
PGPdiskSecurityHookProc, NULL, dwPhraseThreadID);
}
void
CSecureEdit::UninstallSecurityHooks(void)
{
UnhookWindowsHookEx(mHhookMsgFilter);
UnhookWindowsHookEx(mHhookGetMessage);
UnhookWindowsHookEx(mHhookCBT);
UnhookWindowsHookEx(mHhookKeyboard);
}
// NotifyParentOfEditChange sends a message to the parent dialog telling it
// that the edit box contents have changed.
void
CSecureEdit::NotifyParentOfEditChange()
{
CWnd *pParent;
LPARAM lParam;
WPARAM wParam;
wParam = (WPARAM) MakeLong(GetDlgCtrlID(), EN_CHANGE);
lParam = (LPARAM) GetSafeHwnd();
pParent = GetParent();
pgpAssert(pParent);
if (pParent)
pParent->PostMessage(WM_COMMAND, wParam, lParam);
}
/////////////////////////////////////////////////
// CSecureEdit protected default message handlers
/////////////////////////////////////////////////
// DoNothing is a dummy message handler used to prevent certain "unsafe"
// messages from reaching the framework.
void
CSecureEdit::DoNothing(WPARAM wParam, LPARAM lParam)
{
}
// OnChar is overriden so we can implement our hidden typing routine.
// Instead of placing the character in the edit box, we place a space
// there instead and update only the secure mContents variable with the
// new character.
void
CSecureEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
PGPBoolean isPrintable;
isPrintable = (nChar >=32);
if (isPrintable) // printable character?
{
if (mContents->GetLength() == mMaxSizeContents) // overflow?
{
MessageBeep(MB_ICONHAND);
}
else
{
// Insert the new character in the contents.
mContents->InsertAt(mCurCharPos++, nChar);
// If hiding typing, fill the edit box with spaces, else show the
// real contents.
if (mHideTyping)
FillEditBoxWithSpaces();
else
FillEditBoxWithContents();
}
}
}
// OnLButtonDown is overidden so we can stop the user from making a selection
// or changing the position of the caret by clicking.
void
CSecureEdit::OnLButtonDown(UINT nFlags, CPoint point)
{
// Set us to have the focus!
SetFocus();
}
// OnLButtonDblClk is overidden so we can stop the user from making a
// selection.
void
CSecureEdit::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// Set us to have the focus!
SetFocus();
return;
}
// OnKeyDown is overriden so we can handle character deletion and selection.
void
CSecureEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
switch (nChar)
{
case VK_DELETE:
case VK_HOME:
case VK_END:
case VK_UP:
case VK_DOWN:
case VK_LEFT:
case VK_RIGHT:
case VK_NEXT:
case VK_PRIOR:
// Disallow caret movement.
break;
case VK_BACK:
// Delete the current character.
if (mCurCharPos > 0)
{
// Remove the character from the contents.
mContents->RemoveAt(--mCurCharPos);
// If hiding typing, fill the edit box with spaces, else show the
// real contents.
if (mHideTyping)
FillEditBoxWithSpaces();
else
FillEditBoxWithContents();
}
break;
default:
CEdit::OnKeyDown(nChar, nRepCnt, nFlags);
break;
}
}
// OnMouseMove is overidden so we can stop the user from making a selection.
void
CSecureEdit::OnMouseMove(UINT nFlags, CPoint point)
{
return;
}
// OnSetFocus is called when we are recieving the focus. Stop any text
// selections from being made.
void
CSecureEdit::OnSetFocus()
{
SetSel(-1, -1);
// Defeat sniffers.
InstallSecurityHooks();
}
void
CSecureEdit::OnKillFocus()
{
UninstallSecurityHooks();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -