So You Want To Set a Windows Journal Recording Hook on Vista? It’s Not Nearly as Easy as You Think!
Eons ago in Internet years, I wrote what proved to be a very popular tool, Tester, the latest edition appeared in my second book. With it you could record and playback UI automation scripts. While Tester wasn't perfect, the number of companies using it as their automation tool of choice was very gratifying. In fact, there were so many, I probably should have made a business out of updating and supporting the tool. At least it was very gratifying to know I'd produced something useful!
Since I rarely do any UI development, I don't need Tester that much myself. Today, I had a need so grabbed the code with the thought of giving it a quick dusting off so I could use it on Vista x64. After 20 minutes of some tweaks and adjustments to move the application to 64 bits, the real work started. My debug builds were always asserting because SetWindowsHookEx was returning false when my recorder application tried to set the WH_JOURNALRECORD journal recorder to record all the mouse and keystrokes. The last error value was access denied so I simply thought that I needed to run the recorder process with elevated rights. If only it were that easy, because I still got the access denied when running with high integrity as well.
It turns out lots of people were reporting the same issue, but all the reports were from way back in the Vista beta days. After several hours of searching I'd run across several articles where there were discussion about how the journal recording hook was used by key loggers and other nefarious programs so Microsoft was making changes in Vista to close that hole. While I was all in favor of closing the hole, how in the heck was I going to get my simple recorder application to work?
According to some of the forum reading it looked like people got journal recording working by turning off UAC. That was totally unacceptable to me as I have written before I like UAC. Anyway, turning off UAC just for journal recording was the easy way out and made me feel dirty. I dug in for battle and fired up the search engines hard. As I never found this information in one spot, I thought I'd put it here in case someone else wants to use a journal recording hook.
- Your program's manifest has to be set to requireAdministrator for the execution level. Because a journal recording hook falls into the accessibility portion of windows, the uiAccess must be set to true. Here's how you'll set those up in the Linker, Manifest File section of the property page:
- The output binary must be digitally signed with a valid certificate. Read about how and where you can get reasonably priced certificates here.
- You won't be able to run your application where you built it. This was the hardest item for me to figure out and it wasn't until I ran across a random forum entry that provided the missing clue. You must copy the binary that sets the recording hook into a directory under the C:\Program Files directory. That's the only acceptable place for accessibility applications to run. By copying the binary, you can run the application and get your hook set. Of course, if you are going to distribute your application, you'll need to have your installation put it in the C:\Program Files directory and not allow the user to change it.
- You won't be able to start your binary under the debugger even if it's properly located in the C:\Program Files and you've started the environment with elevated rights. Visual Studio will give you the following error:
Unfortunately, clicking on the Help button brings you to a "Information Not Found" page so it's a mystery. For you WinDBG users out there, the uiAccess set to true bothers WinDBG as well if you try to start the application from the debugger:
- To debug your journal recording application, you'll have to start it and attach the debugger. You'll want to make sure your application gives you a chance to attach before you start doing a lot of work.
Since this took three hours of my life to figure out I thought I'd share the solution in case someone else needed the information. While it would have been nice to have all this information in the journal recorder documentation, I'm really glad Microsoft shut down the security hole!