| 44 | ///////////////////////////////////////////////////////////////////////////// |
| 45 | |
| 46 | void CSecureEdit::OnUpdate() |
| 47 | { |
| 48 | LockZeroBuffer<WCHAR> wndBuf(MAX_PASSWORD_LEN + 1, true); |
| 49 | WCHAR *strWnd = wndBuf.m_buf; |
| 50 | LPWSTR lpWnd = NULL; |
| 51 | int iWndLen = 0, iDiff = 0; |
| 52 | int i = 0; |
| 53 | int inxLeft = -1, inxRight = -1; |
| 54 | int nLeft = -1, nRight = -1; |
| 55 | DWORD dwPos = 0; |
| 56 | LockZeroBuffer<WCHAR> newBuf(MAX_PASSWORD_LEN + 1, true); |
| 57 | WCHAR* strNew = newBuf.m_buf; |
| 58 | BOOL bHasChanged = FALSE; |
| 59 | LockZeroBuffer<WCHAR> dotsBuf(MAX_PASSWORD_LEN + 1, true); |
| 60 | WCHAR * strDots = dotsBuf.m_buf; |
| 61 | |
| 62 | // Get information about the new contents of the edit control |
| 63 | GetWindowText(strWnd, wndBuf.m_len-1); // The current window text (Windows has updated it already) |
| 64 | dwPos = GetSel() & 0xFFFF; // The current cursor position |
| 65 | iWndLen = lstrlen(strWnd); // The length of the hidden buffer |
| 66 | iDiff = iWndLen - m_nOldLen; // The difference between the new and the old |
| 67 | |
| 68 | // Scan buffer for non-password-chars (fast scan, using LockBuffer) |
| 69 | lpWnd = strWnd; |
| 70 | for(i = 0; i < iWndLen; i++) |
| 71 | { |
| 72 | if(lpWnd[i] != SE_PASSWORD_CHAR) // This is a new character! |
| 73 | { |
| 74 | if(inxLeft == -1) inxLeft = i; // Only allow one change |
| 75 | bHasChanged = TRUE; // We have found a new character |
| 76 | } |
| 77 | |
| 78 | // If we have found a new character and now find a password character |
| 79 | // again, this _must_ be the end of the new (clip-pasted?) string |
| 80 | if((lpWnd[i] == SE_PASSWORD_CHAR) && (bHasChanged == TRUE)) |
| 81 | if(inxRight == -1) inxRight = i - 1; // Change only once |
| 82 | } |
| 83 | |
| 84 | |
| 85 | if(iDiff < 0) // User has deleted one or more characters |
| 86 | { |
| 87 | iDiff = -iDiff; // Make positive, so we can handle indexes |
| 88 | |
| 89 | wcsncpy_s(strNew, MAX_PASSWORD_LEN+1, m_strRealText, dwPos); |
| 90 | wcsncat_s(strNew, MAX_PASSWORD_LEN+1, m_strRealText + wcslen(m_strRealText)-(m_nOldLen - dwPos - iDiff), _TRUNCATE); |
| 91 | wcscpy_s(m_strRealText, MAX_PASSWORD_LEN+1, strNew); |
| 92 | |
| 93 | for (i = 0; i < lstrlen(m_strRealText); i++) strDots[i] = SE_PASSWORD_CHAR; |
| 94 | |
| 95 | if(bHasChanged == FALSE) // If the encrypted buffer has not changed |
| 96 | { // execute this code only if no new code has been pasted (clipboard) |
| 97 | wcscpy_s(m_strOldText, MAX_PASSWORD_LEN+1, strNew); |
| 98 | m_nOldLen = (int)wcslen(strDots); |
| 99 | SetWindowText(strDots); |
| 100 | SetSel(dwPos, dwPos, FALSE); |
| 101 | } |
| 102 | } |
| 103 | if(bHasChanged == FALSE) return; // Everything is encrypted/hidden |
nothing calls this directly
no outgoing calls
no test coverage detected