Admittedly most people never find the need to write a Winlogon Notification DLL. However, if you were tempted to: stop. Microsoft no longer supports them in LongHorny. Yes, they had a good run beginning with Windows 2000, continuing into Windows XP and Windows 2003 server. But, like many things where Microsoft just up and decides that "those darn developers out there crash our crap too much" they've pulled the plug on Winlogon Notification DLL's. Apparently too many people didn't free their pointers or something and caused Winlogon crashes. GINA's have been pulled too, but I imagine the GINA's of the world will unite in protest - maybe even the Regina's too.
So, if you want to acheive the same results that you used to be able to do with a Winlogon Notification DLL what's a poor developer to do? Never fear, some more difficult code is here! Instead of simply running a CreateProcess with the lpDesktop parameter of the StartupInformation structure set to "Winsta0\Default" like you could in the Notification DLL, you now have to create a service. The service must be setup to handle SERVICE_ACCEPT_SESSIONCHANGE and has a callback to get notified of logons, logoffs, etc. Now, due to some further changes in Windows, services can't easily put things on the user desktop. Simple things like what SMS does - deliver packages to the user desktop running as Local System are now more difficult because if you just launch them on WinSta0\Default they will run on the "services" session and not on the user console.
So how do you get them onto the user desktop?
Well, to quote Microsoft: "It becomes more difficult if you want to start LocalSystem code on the user’s “Default” desktop. That’s actually something that we would strongly discourage because of things like shatter attacks. So if you are calling CreateProcess and specify Winsta0\Default as the desktop, that won’t work as is from a service. It is still possible to do this, but as mentioned, that approach is strongly discouraged for security reasons..". It's always funny to then tell them, but you sell a product called SMS that does this. Anyway, since I still need that functionality I need to write this service. Besides isn't William Shatner getting too old to attack things anymore?
Can we get there from here?
It turns out that you need to do things like create a Security Descriptor (which is no simple task for VB.Net people like me), Duplicate the token, modify the token to be associated with a different session, and then call CreateProcessAsUser using your newly minted token (no, not a fake video game token; just a fake Windows token). All this uses some of the obtuse security API's that most people hope that they never even have to read about, let alone understand. So, I've done that (read about it, don't understand it). The good news is that it doesn't crash. The bad news is that it doesn't do much of anything at all. When debugging it under Vista, it shows "True" for the result codes of all of the calls. In fact, I even get a PID back in the ProcessInformation structure after the call to CreateProcessAsUser. The only problem is that the app never starts, even though I get thread handles, process handles, PID, etc. and a true result code. Boy this was simple before! Now its quite complicated. I'll let you know if I ever get this working. So far this has left me wondering if a shatter attack is what happens to your monitor when you get frustrated writing code for Windows.