Winlogon Notification DLL -- Create Process as the user who logged in

2.9k views Asked by At

I have a requirement to run an app as a user unlocks his computer. This works swimmingly in Win 7 with regular task scheduler. For XP -- ive Created a C++ DLL to do this. This seems to work great, except that it does so under the system account (and thus doesnt show up ont he user's desktop).

I have 2 functions, the first WLEventLogon launches the process under the system acct,

The 2nd, (I havent done C++ in like 15 years so Im a tad rusty!) is most likely wildly incorrect. I'm trying to get a simple app to run on the user's account whenever he unlocks the system.

Below is my code -- the dll works and Ive tested the methods with rundll32 and using them in winlogon/notify

    // Here is the event handler for the Winlogon Logon event.
//__declspec( dllexport ) void WLEventLogon (PWLX_NOTIFICATION_INFO pInfo);

WINLOGINDLL_API void WLEventLogon (PWLX_NOTIFICATION_INFO pInfo)
{   

    const wchar_t* path =  L"C:\\path\\app.exe";


    ShellExecute(GetDesktopWindow(),L"open",path,NULL,NULL,SW_SHOWNORMAL);      
}


WINLOGINDLL_API void Test (PWLX_NOTIFICATION_INFO pInfo)
{   


STARTUPINFOW        lpStartupInfo;
PROCESS_INFORMATION lpProcessInfo;

ZeroMemory(&lpStartupInfo, sizeof(lpStartupInfo));
ZeroMemory(&lpProcessInfo, sizeof(lpProcessInfo));
lpStartupInfo.cb = sizeof(lpStartupInfo);
lpStartupInfo.dwFlags = STARTF_USESHOWWINDOW;
lpStartupInfo.wShowWindow = SW_SHOW;
CreateProcessAsUser(pInfo->hToken, L"C:\\path\\app.exe",L"test",NULL,NULL,FALSE,NULL,NULL,NULL,&lpStartupInfo,&lpProcessInfo);

   }

The 'test' function doesnt seem to be working at all -- My CreateProcessAsUser is most likely wildly wrong.

2

There are 2 answers

0
Remy Lebeau On BEST ANSWER

Did you make sure the hToken value is not NULL? If it is not, try using DuplicateTokenEx() to retreive the user's primary token, then pass that to CreateProcessAsUser().

WINLOGINDLL_API void Test (PWLX_NOTIFICATION_INFO pInfo)
{
    if( !pInfo->hToken )
        return;

    STARTUPINFOW        lpStartupInfo;
    PROCESS_INFORMATION lpProcessInfo;
    ZeroMemory(&lpStartupInfo, sizeof(lpStartupInfo));
    ZeroMemory(&lpProcessInfo, sizeof(lpProcessInfo));
    lpStartupInfo.cb = sizeof(lpStartupInfo);
    lpStartupInfo.dwFlags = STARTF_USESHOWWINDOW;
    lpStartupInfo.wShowWindow = SW_SHOW;

    HANDLE hUserToken;
    if( !DuplicateTokenEx(pInfo->hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hToken) )
        return;

    if( CreateProcessAsUser(hUserToken, ...) )
    {
        ...
    }

    CloseHandle(hUserToken);
}
0
Oleg On

You can just use Impersonate value set to 1 in the registration of the notification dll. (see documentation). It will make impersonation of the user.

I personally always prefer to set explicitly "WinSta0\\Default" as lpDesktop field of the STARTUPINFOW and use CreateProcess API instead of ShellExecute.

Moreover it is a little strange that the name of the function WLEventLogon and not something like WLEventLogon. Do you register the function name as Unlock value in the registry?