-
January 15th, 2014, 02:58 PM
#16
Re: How to refresh logon screensaver parameter changes?
Originally Posted by dc_2000
Thanks. It's a nice article. But unfortunately like one of the commenters noted there:
See this post for a practical sample.
Best regards,
Igor
-
January 15th, 2014, 05:12 PM
#17
Re: How to refresh logon screensaver parameter changes?
@VictorN: LocalSystemSID is indeed S-1-5-18, which is the user SID that my local service is running under. I need to run my test process in a user account with SID S-1-5-19.
@Igor Vartanov: It's an interesting idea. But you see, in your example you had notepad.exe already running in one user session, so you could reuse it's token. In my case I don't have a process to use for that approach...
-
January 15th, 2014, 06:02 PM
#18
Re: How to refresh logon screensaver parameter changes?
Originally Posted by Igor Vartanov
See this post for a practical sample.
Igor, you gave me an idea. I logged off all users and checked all running processes. As it shows here:
Windows Logon is the only interactive process, that is LogonUI.exe:
Shall I try to get its token & run my process with it using your approach?
-
January 16th, 2014, 04:00 AM
#19
Re: How to refresh logon screensaver parameter changes?
I think the best candidate for the case of real interactive user is explorer.exe, or whatever exe is registered as a shell. Or you can adopt the method from the article (afraid it's Vista/7/8 only).
In case there is no interactive session at all, the suggested SystemParametersInfo API won't work I guess. Besides, I'm not sure whether screensaver timeout matters in this case.
Best regards,
Igor
-
January 16th, 2014, 04:30 AM
#20
Re: How to refresh logon screensaver parameter changes?
Originally Posted by Igor Vartanov
See this post for a practical sample.
Igor Vartanov, I'd like to thank you for suggesting your solution. Using it I was able to resolve this issue!
Here's how:
1. Use Igor's code from here and the following method to obtain the user token for the "LogonUI.exe" process:
Code:
HANDLE hToken = NULL;
DWORD pid = GetProcessTokenByName(_T("LogonUI.exe"), &hToken);
His GetProcessTokenByName is a bit an overkill for my needs, so you can strip out anything past the 'hToken' part. Or, you can use WTSEnumerateProcesses API to retrieve process names in a faster fashion and use hProc=OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, process_ID); and OpenProcessToken(hProc, TOKEN_ALL_ACCESS, &hToken) to obtain the desired token for a matched process (by its name.)
One correction I want to point out for the Igor's method. Do not use CString().CompareNoCase() and stick with CompareString() API instead. It handles international case-insensitive comparison in a correct way, which CString does not.
Also you may want to consider checking that there's no interactive users logged on to the console. For that use WTSEnumerateSessions() API and then call WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, session_ID, WTSUserName, , ); for each session returned and check that the obtained user name has length 0. This will mean that the user session is not interactive. Otherwise, stop and don't continue.
2. Once you have a token use it in a call to CreateProcessAsUser() to run a small console exe process (see item 3.) You can use Igor's ExecThread method, or something similar to this:
Code:
//INFO: Error handling is omitted
// hToken = obtained from the 'LogonUI.exe' process using the method described above
HANDLE hToken2;
::DuplicateHandle(::GetCurrentProcess(), hUserToken, ::GetCurrentProcess(), &hToken2, 0, FALSE, DUPLICATE_SAME_ACCESS);
LPVOID pEnvBlock;
CreateEnvironmentBlock(&pEnvBlock, hToken2, FALSE);
STARTUPINFO si = {0};
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = _T("winsta0\\default");
PROCESS_INFORMATION pi = {0};
ImpersonateLoggedOnUser(hToken2);
bResult = CreateProcessAsUser(
hToken2, // client's access token
pStrExeFilePath, // file to execute
pBuffCmdLine[0] != 0 ? pBuffCmdLine : NULL, // command line
NULL, // pointer to process SECURITY_ATTRIBUTES
NULL, // pointer to thread SECURITY_ATTRIBUTES
FALSE, // handles are not inheritable
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, // creation flags
pEnvBlock, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
);
RevertToSelf();
DWORD dwResWait = ::WaitForSingleObject(pi.hProcess, 5 * 1000);
if(dwResWait == WAIT_OBJECT_0)
{
//Get return code with results from my test exe
DWORD dwExitCode;
GetExitCodeProcess(pi.hProcess, &dwExitCode);
//Analyze the 'dwExitCode' to be 1000 for success, otherwise an error
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
DestroyEnvironmentBlock(pEnvBlock);
//Close both tokens
CloseHandle(hToken2);
CloseHandle(hToken);
3. The console exe process should simply read the value from the 'HKEY_USERS\.DEFAULT\Control Panel\Desktop\ScreenSaveTimeOut' registry and apply it as such:
Code:
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
int nExitCode = 0;
int nValueForTimeout = readIntFromRegistry_I_will_let_you_do_it(HKEY_USERS, L".DEFAULT\\Control Panel\\Desktop", L"ScreenSaveTimeOut");
if(SystemParametersInfo(SPI_SETSCREENSAVETIMEOUT, nValueForTimeout, 0, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE))
{
//Success
nExitCode = 1000;
}
else
{
//Error
nExitCode = 0xdead;
}
return nExitCode;
}
Important thing is to create this console exe as a simple Win32 process, and statically link it to the CRT (with /MT switch.) This will make it depend on as few dlls as possible!
4. And the last step is to check the return code 'dwExitCode' from the method in item 2 to be equal to '1000'. If it is, then we're in luck.
And voila, it works! I tested it on Windows XP SP3, Vista, 7, 8. (I don't have Windows 8.1, but I'm assuming it'd work as well.)
So thanks everyone who pitched it!
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|