本文介绍了尝试显示我的屏幕保护程序的配置窗口(从高强制完整性级别运行的GUI应用程序)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

我有一个自带屏幕保护程序的旧项目。项目的GUI应用程序有一个选项配置屏保,应该会出现我的屏幕保护程序配置窗口(通常从控制面板 - >显示 - >个性化 - >屏幕保护程序 - >设置。)



要显示配置窗口,需要使用 / c 参数调用屏幕保护程序或,这似乎是为什么屏保的配置窗口没有显示的原因。如果我运行我的GUI应用程序的常规中等完整性级别或 S-1-16-8192 ,配置窗口显示确定。



否则,我可以看到我的屏幕保护程序方法被调用,但是当我从它返回TRUE,从未被调用。



由于引入了完整性级别以防止进程以较低级别向具有较高级别的进程发送消息,显然,屏幕保护程序配置机制尝试向我的GUI应用程序发送一些消息(无论什么未记录的原因),并失败,然后默默失败...



所以这是最新的。我会欣赏任何输入,从谁知道如何解决这个(除了降低我的GUI应用程序的完整性级别,我显然不想这样做。)

解决方案

God damn Microsoft (对不起,我只是浪费了整天的时间试图修复它。)



对于谁遇到这种情况,结果是一个人需要这样调用:

其中N是父窗口的窗口句柄,表示为整数。通过检查通过控制面板显示的配置窗口的命令行找到它(使用



在我的例子中,由于我的GUI进程以更高的完整性级别运行,所以执行以下操作就足够了:

  HWND hWndToUse = :: GetDesktopWindow(); 
:: StringCbPrintf(buff,sizeof(buff),L\%s\\mysvr.scr\/ c:%d,buffSysFldr,(int)hWndToUse);

就是这样!


I have an old project that comes with its own screensaver. The GUI application for the project has an option to "Configure screensaver" that should bring up my screensaver configuration window (that you would normally get from a Control Panel -> Display -> Personalization -> Screensaver -> Settings.)

To display the configuration window, one needs to call the screensaver process with the /c parameter as described here. The screensaver itself is placed into the system directory, i.e. "C:\Windows\System32".

So to emulate this from my (32-bit) GUI application I do the following:

//Error checks are omitted for brevity
BOOL bResult = FALSE;

TCHAR buffSysFldr[MAX_PATH];
buffSysFldr[0] = 0;
::GetSystemDirectory(buffSysFldr, SIZEOF(buffSysFldr));

//Make the path, which basically becomes:
//  "C:\Windows\System32\mysvr.scr" /c
TCHAR buff[MAX_PATH];
buff[0] = 0;
::StringCbPrintf(buff, sizeof(buff), L"\"%s\\mysvr.scr\" /c", buffSysFldr);

STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
ZeroMemory(&si,sizeof(si));
ZeroMemory(&pi,sizeof(pi));
si.cb = sizeof(si);

PVOID OldValue;
Wow64DisableWow64FsRedirection(&OldValue);

//And run it
if(CreateProcess(NULL, buff, NULL, NULL, FALSE,
    NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
    NULL, NULL, &si, &pi))
{
    //Success
    bResult = TRUE;
}

Wow64RevertWow64FsRedirection(OldValue);

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

When I deploy it to the Windows 7 machine, the code above returns bResult = TRUE but my screensaver's configuration window is never shown.

I tried it on both 32-bit and 64-bit Windows 7 thinking that Wow64 redirection has something to do with it, but it still didn't change the outcome.

Any idea why this doesn't work?

PS. When I copy and paste that command into a command prompt it runs just fine and displays my configuration window w/o a problem:

EDIT: After further review, it turns out that the issue seems to be connected to the fact that my GUI applications runs with High Mandatory Integrity Level, or S-1-16-12288, which seems to be the reason why the screensaver's configuration window is not shown. If I run my GUI app with its regular Medium integrity level, or S-1-16-8192, the configuration window shows OK.

Otherwise, I can see that my screensaver's RegisterDialogClasses method is called OK, but then when I return TRUE from it, ScreenSaverConfigureDialog is never called.

Since integrity level was introduced to prevent processes with lower levels to send messages to processes with higher levels, evidently the screensaver configuration mechanism tries to send some messages to my GUI app (for whatever undocumented reason) and fails and then silently fails as well ...

So this is the latest. I'll appreciate any input on this from whoever knows how to solve this (apart from lowering the integrity level of my GUI app, that I obviously don't want to do.)

解决方案

God damn Microsoft documentation (sorry, I just wasted the whole day today trying to fix it.)

For whoever else runs into this -- it turns out one needs to call it as such:

where N is a window handle of the parent window expressed as an integer. Found it out by checking command line of the configuration window displayed via Control Panel (did it using Process Explorer.)

In my case, since my GUI process runs with higher integrity level, doing the following will suffice:

HWND hWndToUse = ::GetDesktopWindow();
::StringCbPrintf(buff, sizeof(buff), L"\"%s\\mysvr.scr\" /c:%d", buffSysFldr, (int)hWndToUse);

And that's it!

这篇关于尝试显示我的屏幕保护程序的配置窗口(从高强制完整性级别运行的GUI应用程序)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-07 01:57