I have had a longstanding itch - I finally scratched it. This small utility is the result, and I'm posting it here for a couple of reasons. First, maybe you have the same itch, and this is a solution. And second, while writing it, I used several simple utility classes I keep in my toolbox and you might find them useful too.
What is this nagging itch? It is the darn password edit controls that show asterisks or circles instead of the password you're typing. Oh yes, this is a "security" feature. Some bad guy might be looking over your shoulder to steal your passwords. Except, that of the 4 computers I use on a daily basis, nobody is ever, I mean, ever looking over my shoulder. They're on my desk in my home! But, I use strong passwords with punctuation marks and digits and all that good stuff—sometimes I can't really tell if I typed the password correctly.
So, this simple utility lives in the tray - oops, I mean the Taskbar Notification Area, and whenever I have a password field blocking my view, I can simply click on its icon and the password field will be changed to a normal text field. Problem solved!
This is really a quite vanilla old-style Win32 program. Still, I have used a few utility classes you might find useful yourself. I have a class that encapsulates sending a message (buffer of bytes) from one Windows program to another via WM_COPYDATA
, a general message pump, and a nice little work item dispatcher suitable for running work items in your message loop's idle time. All of them are small and simple, and you can read the code in a few minutes to figure out what they do and if they're suitable for your needs. If you find one useful, go ahead and use it!
The PasswordUnhider uses two different techniques to unhide (unmask) password fields.
First, some password fields are standard edit controls in an ordinary Win32 program, that have a password mask character set—either the control was created with the ES_PASSWORD
style, or it was sent an EM_SETPASSWORDCHAR
notification with a non-zero password character. The utility searches for these edit controls and send them an EM_SETPASSWORDCHAR
notification with a zero password character.
bool SetPasswordChar(HWND hWnd, wchar_t c)
{
::SendMessage(hWnd, EM_SETPASSWORDCHAR, c, 0);
DWORD err = ::GetLastError();
if (err != 0)
{
BOOL b = ::PostMessage(hWnd, EM_SETPASSWORDCHAR, c, 0);
if (!b)
{
err = ::GetLastError();
return false;
}
}
::InvalidateRect(hWnd, NULL, TRUE);
return true;
}
To find these controls, the utility enumerates the desktop windows (::EnumDesktopWindows
API), and then for each desktop window which is an application, it enumerates all child windows looking for password controls (using the ::EnumChildWindows
API).
To determine if a window is a password control—that is, an edit control with a password hiding character set—the utility sends the window an EM_GETPASSWORDCHAR
message and sees what kind of answer it gets. Only edit controls—or things that act like edit controls—will answer this notification (with maybe some exceptions). I can't look at the class name or window procedure because the application may be using edit controls that are superclassed or subclassed but still behave like password fields.
bool IsPasswordEditControl(HWND hWnd)
{
if (!::IsWindow(hWnd))
return false;
wchar_t szClass[128];
int n = ::GetClassName(hWnd, szClass, ARRAYSIZE(szClass));
for (unsigned int i = 0; i < s_notEditControlClasses.size(); i++)
if (s_notEditControlClasses[i] == szClass)
return false;
DWORD msgResult = 0;
LRESULT r = ::SendMessageTimeout(hWnd, EM_GETPASSWORDCHAR, 0, 0,
SMTO_ABORTIFHUNG | SMTO_NORMAL, MSG_TIMEOUT, &msgResult);
return (r != 0) && (msgResult != 0);
}
(I did find that a window with the class name "Acrobat IEHelper Object" returns a non-zero answer for EM_GETPASSWORDCHAR
—the exception mentioned above—so I also use a little array of exceptional class names to filter out these false positives. Right now, "Acrobat IEHelper Object" is the only class name in that array.)
Second, some password fields are INPUT
elements in web pages. In IE, these are not implemented with Win32 edit controls, so a different technique is used.
First, I find all of the browser (IE) windows by using the ShellWindows
COM object, which is a collection of all the browser windows. From each of those windows (represented as a COM object, not a window handle), the HTML document can be retrieved, and from each HTML document, the collection of all INPUT
elements can be retrieved. Then, each INPUT
element can be checked to see if it has an attribute "type
" with the value "password
".
Once a password type INPUT
element is found, it is necessary to change the type to "text
". Unfortunately, for security reasons, you can't just change the attribute value. Instead, the utility gets the outer HTML for the INPUT
element, does a text substitution of "type=text
" for "type=password
", creates a new INPUT
element that is the same as the original except for this attribute, and patches it into the tree in place of the original INPUT
element.
if (SUCCEEDED(hr))
{
hr = pElement->get_outerHTML(&bstrOuterHTML);
}
if (SUCCEEDED(hr))
{
outer = bstrOuterHTML;
wstring outerLower = MakeLower(outer);
iFind = Find(outerLower, wstring(L"type=password"));
hr = BOOL_TO_HR(iFind >= 0);
}
if (SUCCEEDED(hr))
{
outer.erase(iFind, _tcslen(L"type=password"));
outer.insert(iFind, L"type=text");
bstrNewElement = CComBSTR(outer.c_str());
hr = PTR_NON_NULL(pDoc2 = pDoc3_);
}
if (SUCCEEDED(hr))
{
hr = SUCCEEDED_AND_PTR_NON_NULL(pDoc2->createElement(bstrNewElement,
&pNewElement), pNewElement);
}
if (SUCCEEDED(hr))
{
hr = SUCCEEDED_AND_PTR_NON_NULL(pElement->get_parentElement(&pParent), pParent);
}
hr = SUCCEEDED_AND_PTR_NON_NULL(hr, pParentDOM = pParent);
hr = SUCCEEDED_AND_PTR_NON_NULL(hr, pElementDOM = pElement);
hr = SUCCEEDED_AND_PTR_NON_NULL(hr, pNewElementDOM = pNewElement);
if (SUCCEEDED(hr))
{
hr = pParentDOM->replaceChild(pNewElementDOM, pElementDOM, &pReplaceDOM);
}
(Unfortunately, when you do this, whatever text has been typed into that input element is lost. So: click the icon before typing your password into an HTML field.)
The original program did everything in one process: it ran the tray icon and, when commanded, searched for and changed password fields. I knew, even before I wrote the program, that it would take some time to search all the windows on the desktop looking for password fields, and also some time to search all browser windows looking for INPUT
elements. So, I wanted the user to have some feedback while this search was taking place. I wanted to blink the tray icon while this process was happening.
I didn't want to mess with multiple threads for such a simple utility, so I found my trusty idle-time work-item dispatcher and used it to split the password unhiding process into a lot of little work items. Looking at each window would be its own work item, as would looking at each INPUT
element. In this way, I thought I could run the work items during the application's idle time, and the system tray class would then be able to nicely and smoothly animate the tray icon via Windows timer messages.
But, it turned out the icon animation wasn't smooth at all. Some of the operations took quite a bit of time, for example, getting the ShellWindows
collection, and then processing each INPUT
element. It was understandable, because those operations were manipulating the web page's DOM cross-process.
So, I restructured the program so it runs in two processes now. The original process that the user starts puts up the tray icon and manages it, and that's it. When the user clicks to unhide password fields, the program launches a copy of itself in a new process, with command line parameters to tell it what to do, and to tell it how to communicate back to the original process.
The second process sends messages back to the original process for each password field that it unmasks. That way, the original process can put up notification balloons as feedback to the user.
(The work item stuff is all still there, even though the second process doesn't really need it, because it has no UI that it needs to keep responsive. It was working, and there was no reason to rip it out.)
(By the way, I know that it is a waste of resources to keep a process running a system tray icon, consuming a couple of megabytes of private data, and so on, but I don't care. I want those password fields unmasked on demand, and I'm willing to pay the price. It's not like this is some random utility some device manufacturer (mouse, or trackball, or video card) installed on my machine and decided to keep running all the time just in case some day I wanted to change the resolution on my screen—which I never do.)
CMessagePump
is a class that implements an application's main message pump. It runs until WM_QUIT
is received.
It is parameterizable as follows:
- It will handle multiple accelerator tables.
- It will handle a modeless dialog (for keyboard handling).
- It will test for and perform work when no messages are available ("idle work").
- It will callout for messages sent to the thread, rather than to a window.
Here is an example showing how to create a message pump, parameterize it, and then set it into operation:
auto_ptr<CMessagePump> s_msgPump(new CMessagePump(hInstance));
s_msgPump->AddAccelerators(::LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PASSWORD)))
.SetIdleWorkTest(pdispatcher, &CWorkItemDispatcher::HaveWork)
.SetIdleWorkFunction(pdispatcher, &CWorkItemDispatcher::DoWork);
ret = s_msgPump->DoMessagePump();
CWorkItemDispatcher
implements a queue of work items, executing one when requested.
Before getting into how to use it, one question is surely in your mind, so I'll answer it first: Eh, why the heck does the world need another work item dispatcher?
Well, it doesn't really. But, nevertheless, I like this one. It is very simple, so there is very little chance it can get in your way and misbehave. It is very easy to use, so work items can be built as classes if you need state, or you can just use any object you have lying around by implementing a suitable 0- or 1-parameter method on it, or you can use anything you can stuff into a std::tr1::function
—which gives you a lot of choice, and maximizes the chance that you don't have to go out of your way to create work items. Yet, simple as it is, it does implement priorities, and it also implements delayed work items that fire at a future time.
And, it integrates smoothly with CMessagePump
(or with any other message pump you have) to make a smoothly running Win32 application.
So, how to use it? First, let's talk about work items. There is an abstract class, IWorkItem
, from which all work items are derived.
class IWorkItem
{
public:
IWorkItem() {}
virtual ~IWorkItem() {}
virtual void DoWork(CWorkItemDispatcher* dispatcher) = 0;
};
Well, that's pretty standard. You derive from IWorkItem
, implement DoWork()
(and a constructor and destructor if you need to), and you're ready to go.
Alternatively, you can just provide a function to run. A class CWorkItemFactory
provides a bunch of static functions that create work items from your function or function-like thing.
class CWorkItemFactory
{
public:
static std::auto_ptr<IWorkItem> New(void (*)());
static std::auto_ptr<IWorkItem> New(std::tr1::function<void()>);
template<class T> static std::auto_ptr<IWorkItem> New(T&, void(T::*)());
template<class TP> static std::auto_ptr<IWorkItem> New(void (*)(TP), TP);
template<class TP> static std::auto_ptr<IWorkItem> New(std::tr1::function<void(TP)>, TP);
template<class T, class TP> static std::auto_ptr<IWorkItem> New(T&, void(T::*)(TP), TP);
...
The six New
functions come in two flavors: those which take a 0-parameter function, and those which take a 1-parameter function, and a parameter object to supply to it (when the work item is run).
Each of the two flavors has three varieties: one which takes a simple function, one which takes a std::tr1::function
, and one which takes an object and a method on that object.
So that covers a lot of possibilities on how to easily create a work item from some function or method you have lying around.
Enqueuing a work item is very easy. The dispatcher provides an AddWork()
method which takes a work item and a priority. When you enqueue the work item, the dispatcher takes over ownership of it. There is also an AddDelayedWork()
method which takes, in addition, a delay in milliseconds. The work item will be held in a separate queue until (at least) that many milliseconds have elapsed, and then it will be transferred to the regular queue (where it will be executed in priority order).
Finally, how is the work item dispatcher created and used? A factory method, CWorkItemDispatcher::StandardWorkItemDispatcherFactory()
, will return a dispatcher. The dispatcher has two useful methods for running work items:
virtual bool HaveWork() = 0;
virtual void DoWork() = 0;
These simple methods are just right for hooking up to a message pump, or in the main loop of a thread.
The work item dispatcher can be parameterized in two ways. First, you can choose whether or not you need to protect its work item queues with a lock or not. If you have a single threaded program, you don't need a lock. If you are going to enqueue work items from different threads, you need a lock. (All work items must be consumed from a single thread; that is, DoWork()
should always be called from the same thread.)
The other way to parameterize the work item dispatcher is to control how it can "kick" its controller—typically, the message pump—when it has new work items ready to run. The issue is that the message pump might want to go into a wait state when there is no work for it to do. Then, some other thread might add a work item, or the time might have arrived for a delayed message to run. The message pump must be awakened. You can control what Windows message is used to kick the message pump, and what window or thread the message should be sent to.
CCopyIPC
will copy a message—a buffer of bytes—from one process to another, via the Windows WM_COPYDATA
facility. Obviously, this means that the receiving process must be running a message loop.
The sender and the receiver both instantiate a CCopyIPC
object.
All the sender needs to do is call CCopyIPC::Send
with a buffer of bytes, or an object, and the handle of the window to which to send the message. The window handle is passed out-of-band. For the PasswordUnhider, I put it on the command line of the process that is launched to process the password fields.
class CCopyIPC
{
public:
...
result_t Send(HWND hWndReceiver, uint nBytes, const char* bytes);
template<class T>
result_t Send(HWND hWndReceiver, const T& data);
...
The receiver has a little more work. It has to handle the WM_COPYDATA
message in the message loop of the target window. CCopyIPC
supplies a suitable procedure that can be called with the wparam
and lparam
when the WM_COPYDATA
message is received.
LRESULT DoWMCopyData(WPARAM wParam, LPARAM lParam);
The receiver also has to supply a callback function to be called when the data comes in. The nice thing is that CCopyIPC
lets you supply the callback function in several forms.
First, the callback can get either a buffer of bytes, or an object. Second, the callback can be either a simple function, a function object, or a method.
...
CCopyIPC& SetDataCallback(void (*)(HWND, uint, const char*));
CCopyIPC& SetDataCallback(std::tr1::function<void(HWND, uint, const char*)>);
template<class T>
CCopyIPC& SetDataCallback(T& t, void (T::*)(HWND, uint, const char*));
template<class TD>
CCopyIPC& SetDataCallback(void (*)(HWND, const TD&));
template<class TD>
CCopyIPC& SetDataCallback(std::tr1::function<void(HWND, const TD&)>);
template<class T, class TD>
CCopyIPC& SetDataCallback(T& t, void (T::*)(HWND, const TD&));
...
};
I am currently satisfied with my click-to-unhide approach. Another option would be to continually monitor the system and go ahead and unhide password fields as they are created. It would seem more convenient for the user.
This approach would use Windows hooks for ordinary Win32 applications, for example, the CBT hook. Or a DLL injection approach could be used, for example, with Detours. For IE windows, you could use a BHO.
Unfortunately, solutions like this could create stability problems, and possibly performance issues as well. I decided that, for now, I didn't need the convenience of a 0-click solution.
One issue that came up is that in most cases, when sending EM_SETPASSWORDCHAR
to a window (in another process), SendMessage
would fail with ERROR_ACCESS_DENIED
, but PostMessage
would work. I'm not sure why this happens. If anyone could enlighten me in the comments, I would appreciate it.
This is just a simple utility that I wrote to meet my needs. I hope it meets your needs, but if it doesn't, ... I'm sorry.
In particular:
- I didn't test with Firefox or any other browser besides IE. In fact, I only tested with IE7.
- I only tested on Windows XP. Windows Vista has UIPI (User Interface Privilege Isolation) which may interfere with sending, between processes, the messages that change the password fields. And, the manipulation of HTML documents in another process might not work either, for that reason or other similar reasons.
- It probably won't work with password dialogs popped up by the OS itself—though I haven't tried it.
In all cases, I'd be interested to hear about the problem, and really interested to hear how you fixed it!
Those of you wishing to compile the utility yourself, or to use the utility classes I've described: I make use of TR1 facilities like function
, mem_fn
, bind
, and tuple
. This means, you need, at a minimum, Visual Studio 2008 SP1. Alternatively, you could use Boost's TR1 implementation (though I haven't tried it).
The system tray icon is managed by the excellent CSystemTray
class, written by Chris Maunder and described in his excellent article Adding Icons to the System Tray.
- Apr 9, 2009: Original article.