Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Bring window from elevated process to front in Vista

396 views
Skip to first unread message

Steph

unread,
Feb 26, 2008, 9:34:00 AM2/26/08
to
Hi,

I'm writing a task switching application and am having difficulty in giving
a window belonging to an elevated process the focus.

The code I usually use:

WINDOWPLACEMENT lpwndpl;
lpwndpl.length = sizeof(WINDOWPLACEMENT);
::GetWindowPlacement( hwndAppWindow, &lpwndpl);
::BringWindowToTop (hwndAppWindow);
if (lpwndpl.showCmd == SW_SHOWMINIMIZED)
{
::ShowWindow (hwndAppWindow, SW_RESTORE);
}
::SetFocus (hwndAppWindow);

is returning "Access is denied" for BringWindowToTop, ShowWindow and
SetFocus. (hwndAppWindow is returned by FindWindow)

I've tried calling AllowSetForegroundWindow(ASFW_ANY) in both the task
switch app and the elevated app without success, and the dialogs of both
programs have the Set Foreground property set to True, but still it fails. I
also tried using SetWindowPos which also returns an "Access is denied" error.

Can someone please tell me if it's possible to do this, and give me some
pointers?

Note that the above code works for windows of non-elevated apps.

I'm using VS2008 and Windows Vista.

Thanks,
Steph

Tom Serface

unread,
Feb 26, 2008, 10:12:16 AM2/26/08
to
Try calling SetForegroundWindow() first then BringWindowToTop();

Tom

"Steph" <st...@newsgroups.nospam> wrote in message
news:9B64EE13-5148-4E62...@microsoft.com...

David Ching

unread,
Feb 26, 2008, 1:04:12 PM2/26/08
to
"Steph" <st...@newsgroups.nospam> wrote in message
news:9B64EE13-5148-4E62...@microsoft.com...

If Windows Vista has UAC (User Access Control) enabled (it is by default),
then Windows prevents a non-elevated app from manipulating the Windows of an
elevated app. In order to do so, your app needs to be elevated itself. For
your app to elevate, the user must accept this (the screen darkens and a
dialog asking for the Admin password or, if an Admin is logged in, a simple
OK button click). This is a royal pain. The only way around it that I have
heard is if you put your app into the Windows Scheduler, which can start the
app as elevated without further approval.

-- David


Ajay Kalra

unread,
Feb 26, 2008, 3:54:12 PM2/26/08
to

Where is Win3.1 when you need it?

--
Ajay


Jeffrey Tan[MSFT]

unread,
Feb 26, 2008, 10:36:39 PM2/26/08
to
Hi Steph,

This behavior is by the security enhancement of Vista UIPI(User Interface
Privilege Isolation) which can be seen as a part of Vista UAC(User Account
Control).

On Vista, only elevated application/process will run under the full
administrator security context, while most of the normal processes run
under a splitted normal user security context to minimize the attack
surface. However, since these high right processes and normal right
processes run on the same UI desktop, it is possible for the low right
hacky process to send message to the high right processes.(For legacy
reason, Windows GUI system did not have per-process or per-window security
constraint) This is called shatter attack.

To minimize this shatter attack, Vista introduced the UIPI which does not
allow low right process to send message to the high right processes. That's
why your application will fail to call these User32 APIs. Note: it is
possible to establish the trust relationship by calling
ChangeWindowMessageFilter() in the high right process(which says, yes, this
low right process is a good guy, let's allow it to send message to me).
However, in your scenario, since you have no control over all the high
right processes, this is not a doable solution for you. Please see the link
below for more details:
http://blogs.msdn.com/vishalsi/archive/2006/11/30/what-is-user-interface-pri
vilege-isolation-uipi-on-vista.aspx

The only solution should be running your process under elevated
Administrator token. Actually, this kind of system level task switching
application really needs Admin right to get it work done, since its
behavior affects all the processes/applications on the system.

Finally, you may still meet some problem while dealing with System
Integrity Level GUI window, however, this seldom occurs on Vista.

Hope this helps.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.

Jeffrey Tan[MSFT]

unread,
Feb 26, 2008, 10:41:53 PM2/26/08
to
Oh, also, please note that although you did not send message explicitly in
your code, these are all User32 APIs for inter-process operations, so they
are also under the control of UIPI. Thanks.

Joseph M. Newcomer

unread,
Mar 1, 2008, 9:29:01 PM3/1/08
to
Having checked the link, it does *not* say "the low right process is a good guy". It says
"ANY process that sends this message is a good guy" which is quite a different statement.

Since SetForegroundWindow and BringWindowToTop are not actually messages, it is not clear
what the impact of this filter would be on operations like that.
joe

Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

Jeffrey Tan[MSFT]

unread,
Mar 2, 2008, 9:09:02 PM3/2/08
to
Hi Joseph,

Yes, ChangeWindowMessageFilter() only helps with the Windows Messages, so
it may not be a resolution for the OP. Anyway, since we are writting an
administration task switch program, we definitely need Administrator right
to perform all the work.

Thanks.

Joseph M. Newcomer

unread,
Mar 3, 2008, 3:46:42 AM3/3/08
to
I have not read the specs myself, but the client I had recently said that they had to
implement their product entirely at ..._MEDIUM_RID level, since they could not get a
Windows Vista Logo if they required elevated integrity level to do anything. It took me
three weeks of research (on my own) and three weeks of coding (paid) to create a solution
for their problem that did not require elevated integrity level to solve the problem.

Since not all users will be able to get an elevated integrity level (lacking both admin
privileges and an admin password), it may simply be infeasible to write a "task switching
application" that requires admn rights, and consequently it may be infeasible to even
consider this as a project that is capable of doing task switching to elevated processes.

Every once in a while, a programmer undertakes to write a piece of code that superficially
looks useful but which is impossible to implement; some years ago, the favorite task
seemed to involve wanting to do IN and OUT instructions from user space and the question
usually started out "I don't see how to get interrupts after I start the I/O operation..."
This question has a lot of that flavor. "I want to do something which is forbidden by the
operating system, so why doesn't my code work?"

What surprises me is that FindWindow can even return a window handle of an elevated
process. This looks like a security oversight.
joe

Steph

unread,
Mar 3, 2008, 11:41:02 AM3/3/08
to
Thank you all for your help and advice.

It does indeed look as though I may have to run my application with admin
rights to do this properly, as I do not have control over all the
applications it will be managing.

That said, Toms suggestion of using SetForegroundWindow does actually work
for elevated processes, though if I try to use it for non-elevated it makes
them permanently topmost which is not desirable. I do realise that I may not
be able to rely on this behaviour persisting in future versions of Windows.

My code now goes along the lines of

if (::BringWindowToTop(a_hwndApp) == FALSE)
{
// if access denied it's probably an elevated process
if (GetLastError() == ERROR_ACCESS_DENIED)
{
blnSuccess = ::SetForegroundWindow(a_hwndApp);
}

}
else
{
// bring to front as before
}


Thanks once again,
Steph

Joseph M. Newcomer

unread,
Mar 3, 2008, 12:36:37 PM3/3/08
to
See below...

On Mon, 3 Mar 2008 08:41:02 -0800, Steph <st...@newsgroups.nospam> wrote:

>Thank you all for your help and advice.
>
>It does indeed look as though I may have to run my application with admin
>rights to do this properly, as I do not have control over all the
>applications it will be managing.
>
>That said, Toms suggestion of using SetForegroundWindow does actually work
>for elevated processes, though if I try to use it for non-elevated it makes
>them permanently topmost which is not desirable. I do realise that I may not
>be able to rely on this behaviour persisting in future versions of Windows.
>
>My code now goes along the lines of
>
>if (::BringWindowToTop(a_hwndApp) == FALSE)

****
VERY POOR programming style. Comparing any BOOL-returning value or expression to a
boolean constant is a Really Bad Idea. The correct way to write this would be
if(!::BringWindowToTop(a_hwndApp))
I have no idea where the educational failure is that suggests that writing == FALSE or ==
TRUE for a boolean expression makes sense. You might as well write
if( (a > 0) == FALSE)
which is just as foolish as a way to write
if(a <= 0)
****


>{
> // if access denied it's probably an elevated process
> if (GetLastError() == ERROR_ACCESS_DENIED)
> {
> blnSuccess = ::SetForegroundWindow(a_hwndApp);
> }
>
>}
>else
>{
> // bring to front as before
>}
>
>
>Thanks once again,
>Steph

Jeffrey Tan[MSFT]

unread,
Mar 4, 2008, 9:11:57 PM3/4/08
to
Hi Steph,

Thanks for your feedback.

Oh, I am not aware that BringWindowToTop API will be limited by UIPI while
SetForegroundWindow() does not. I will try to send an email to the Windows
security to consult this behavior. I hope they can provide some definite
answer for it.

I will get back to you as soon as I got anything interesting. Thanks.

Jeffrey Tan[MSFT]

unread,
Mar 4, 2008, 9:24:53 PM3/4/08
to
Hi Joseph,

Yes, security enhancement is really a trade-off. It introduces some
inconvenient but minimizes the attack surface.

I also find the document for UIPI very incomplete. I am currently sending
an email to the UIPI team to find a complete list of Window Manager
functions that are contrained by UIPI. I do not know if I can get a such
list.

Joseph M. Newcomer

unread,
Mar 4, 2008, 10:09:40 PM3/4/08
to
Not only do we deserve such a list, but if they *can't* produce such a list, it indicates
a failure in both design and in management.
joe

Joseph M. Newcomer

unread,
Mar 4, 2008, 11:32:55 PM3/4/08
to
I like the improved security. It is much better than the crap we had in the past. Now if
only I could figure out what I need to do to protect the file system and Registry against
"lower integrity" processes...but I don't have time to look that up right now...
joe

Jeffrey Tan[MSFT]

unread,
Mar 5, 2008, 10:00:27 PM3/5/08
to
Hi Joseph ,

For the FindWindow() function issue, UIPI distinguishes between find / get
/ read type of operations and set / write / manipulate type of operations.
The latter are (typically) blocked up-IL policy. The former are not and the
reasoning for this is:
a) These operations do not typically constitute a vulnerability. You can
"find" the handle to an elevated window; what can you then do with it?
You'll find that UIPI prevents you from doing almost anything with that
handle that could be described as controlling that window or it's process.
b) Blocking these operations would have a huge app-compat impact and you'd
eventually have a bunch of applications running elevated simply because
they need to do something relatively harmless like "find" an elevated
window.

Jeffrey Tan[MSFT]

unread,
Mar 5, 2008, 10:02:25 PM3/5/08
to
Sorry, I still can not get a complete UIPI block API list yet. I assume
there is no public one available. Anyway, I have sent the concern to the
UIPI team. However, I have no influence over their decision.

Thanks for your understanding.

Jeffrey Tan[MSFT]

unread,
Mar 5, 2008, 10:05:26 PM3/5/08
to
Hi Steph,

Sorry for letting you wait.

I have discussed this with the UIPI team. BringWindowToTop maps directly to
a SetWindowPos, which requires the caller to have UIPI access to the
concerned HWND.

In the SetForegroundWindow case, we have an explicit exception allowing the
call to be made with no IL restrictions; it does, of course, have other
restrictions and checks in the course of its execution. However, I did not
get more details of the story yet. I suspect it may be leaved to allow the
shell to be able to bring up windows on taskbar actions, but I am not sure.

Hope it helps.

Joseph M. Newcomer

unread,
Mar 6, 2008, 3:25:11 AM3/6/08
to
My understanding was that ::IsWIndow was one of the APIs that would fail on an elevated
process HWND (it would always return FALSE)

Reading can violate security if, for example, an app has a filename in the caption; why
would a lower-integrity process be allowed to obtain the name of a file used by a
higher-integrity process? That sounds to me like a serious security hole. In that sense,
FindWIndow would not be "harmless".

In a rational world, the admin would be allowed to limit what APIs would apply. A minimum
set (e.g., writes) could be blocked, and others at the discretion of the admin.
joe

Jeffrey Tan[MSFT]

unread,
Mar 8, 2008, 1:55:12 AM3/8/08
to
Hi Joseph,

I have written a simple to test IsWindow() API. When I call IsWindow() from
a non-elevated token for an elevated notepad window handle, it will return
TRUE without any problem:

#include "stdafx.h"
#include <windows.h>
#include<assert.h>
int _tmain(int argc, _TCHAR* argv[])
{
HWND hElevatedWndHandle = FindWindow(L"Notepad", L"Untitled - Notepad");
assert(hElevatedWndHandle);
BOOL fIsWnd = IsWindow(hElevatedWndHandle);
assert(fIsWnd);
return 0;
}

Regarding your sample of reading window caption to expose file path, I
believe it is that application that does not have security in consideration
and exposes sensitive information in the window caption. For example, if a
developer displays the password in a normal edit control instead of the
password protected mode edit control, it is a security bug in their code.
Due to the legacy reason(window manager did not have security protection),
a lot of GUI application did not have security in mind. If we block the
read type of GUI operation, it will break many of the GUI applications.

Yes, engineering full security control/configuration into Window Manager is
a good idea, but we need some type of compatibility for pre-Vista OS before
re-writing the whole Window Manager for security. That why we still have
file/registry virtualization feature in Vista while introducing the UAC
feature.

Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
msd...@microsoft.com.

Joseph M. Newcomer

unread,
Mar 9, 2008, 12:03:56 AM3/9/08
to
See below...

On Sat, 08 Mar 2008 06:55:12 GMT, je...@online.microsoft.com ("Jeffrey Tan[MSFT]") wrote:

>Hi Joseph,
>
>I have written a simple to test IsWindow() API. When I call IsWindow() from
>a non-elevated token for an elevated notepad window handle, it will return
>TRUE without any problem:
>
>#include "stdafx.h"
>#include <windows.h>
>#include<assert.h>
>int _tmain(int argc, _TCHAR* argv[])
>{
> HWND hElevatedWndHandle = FindWindow(L"Notepad", L"Untitled - Notepad");
> assert(hElevatedWndHandle);
> BOOL fIsWnd = IsWindow(hElevatedWndHandle);
> assert(fIsWnd);
> return 0;
>}

***
Note that from

Vishal's Windows Application Compatibilty Awareness
http://blogs.msdn.com/vishalsi/archive/2006/11/30/what-is-user-interface-privilege-isolation-uipi-on-vista.aspx

- Perform a window handle validation of higher process privilege.
- SendMessage or PostMessage to higher privilege application windows. These application
programming interfaces (APIs) return success but silently drop the window message.

What does "Perform a window handle validation" mean? I thought it meant IsWindow. If it
does not, that article should be corrected. Or the concept "perform a window handle
validation" should be explained so we know what it means.

What does it mean to have "SendMessage return success". As I see it, if you have a
SendMessage that is *expected* to return a meaningful value, of which 0 is one possible
member, you cannot tell success from failure!

Perhaps this would be recommended practice? [Just a guess...]

SetLastError(ERROR_SUCCESS);
LRESULT result = SendMessage(hwndInOtherProcess, ...);
if(GetLastError() != ERROR_SUCCESS)
...failed
else
... success

And the article does not mention PostThreadMessage, SendMessageNotify,
SendMessageCallback, SendMessageTimeout, etc., etc. If it mentions one API by name, it
must mention all APIs by name, or say "SendMessage and other message-sending APIs" or
something like that.

****

>
>Regarding your sample of reading window caption to expose file path, I
>believe it is that application that does not have security in consideration
>and exposes sensitive information in the window caption.

****
It is not the domain of anyone but me to decide what constitutes "sensitive information".
I said that the filename may be sensitive information. I need no justification for that
statement other than the fact that I have deemed this to be sensitive information, for
whatever reasons I choose to call it sensitive. If I'm running with UIPI enabled, and I
don't want some browser attack (such as ActiveVirus code) to see that the user has opened
a certain file, then I would expect that GetWindowText should behave *as if* it were
obtained via WM_GETTEXT, which would be illegal.

If a program breaks, it is my decision whether I care about that program. The system
should feel free to return an empty string as window text if I do a GetWindowText to a
window owned by a higher-integrity process.
****


>For example, if a
>developer displays the password in a normal edit control instead of the
>password protected mode edit control, it is a security bug in their code.

****
OK, so you've said that if I call GetWindowText on a child window that hold the password,
it should work, and return the password? How else can I get the password in the program
that is asking for it?
****


>Due to the legacy reason(window manager did not have security protection),
>a lot of GUI application did not have security in mind. If we block the
>read type of GUI operation, it will break many of the GUI applications.

****
SHould it not be my decision to determine if I want some random program to run, as opposed
to making sure that some random program cannot see something from higher integrity level?
Default OOTB might be "compromise security because it doesn't matter, really" but I should
be able to say "Do not compromise security because it really does matter".

This is yet another example of presuming that Microsoft knows best what my security policy
should be, and I have no say in the matter. How can I control access if fundamental
mechanisms that say they do something don't actually do something because some program I
don't care about might break, while I actually *want* any program which I have not
explicitly authorized to get that information to break.
****


>
>Yes, engineering full security control/configuration into Window Manager is
>a good idea, but we need some type of compatibility for pre-Vista OS before
>re-writing the whole Window Manager for security. That why we still have
>file/registry virtualization feature in Vista while introducing the UAC
>feature.

****
Do you have a link to how I can protect my entire file system and registry, except for a
very few limited directories/keys, against a lower-integrity process? I haven't found
this yet, although I've looked a couple times.

Right now, I run all my email and web browsing through one machine, under an account
called 'email', which has very, very limited access to the machine state. It took me
weeks to tune the file system and Registry to allow only the critical directories and keys
to be accessible (I want to run IE as sandboxed as I can possibly make it. I want it to
come out and say "Internet Explorer wishes to write file <name>. Permit?" and have
options such as
Deny (default)
Permit once
Permit always for this file from http://www.flounder.com/mvp_tips.htm
Permit always for this file from the address http://www.flounder.com
Permit always for files in the directory c:\downloads from http://www.flounder.com
Permit always for sites in my Trusted domain
Permit always for sites in the Internet domain
etc.

Same thing for Registry keys. I want to know WHAT is being modified, and BY WHOM.

I don't want to hear that this might upset my mother (who is 88). She would take the
defaults OOTB. I want to set my own policies. And any page that wants to modify
permanent state on my machine (unless I am doing an explict download of a file) is
suspect, because no page should be modifying my machine state without my permission.

I want to create my own categories; the distinctions "Trusted", "Internet", etc. are
overly simplistic and are inadequate for practical security. I want to create my own
categories with my own security policies.

Any attempt to modify my machine state without my permission is a hostile attack. For
convenience, I may choose to allow specific sites to "log in" to my machine, in effect. In
a reasonable world, when it came to any kind of client-side scripting (JavaVirus,
ActiveVirus, VBVirus, etc.) each site would be treated as a unique "user" and I should be
able to use the standard ACLs to grant/deny access to each such "user". I see no reason I
should trust any site OOTB. Thus, scripting that is restricted to working on the display
(presenting information, responding to my input, etc.) is not modifying my permanent
machine state, and as such does not require limitation. As soon as it tries to touch my
file system or Registry, however, it needs to create a new "user" and I can set the
permissions according to my local concept of security.

Otherwise, Microsoft needs to have a policy that lets me wander about the buildings on the
Microsoft campus freely, using any computer I run across to access anything I feel like,
and let me plug my USB memory stick into any machine I want to, without restriction.
(After all, if that is the security policy you want to subject me to, you should use it
yourselves...just pretend I'm a fragment of JavaScript) [Note how silly it sounds when we
express it in terms of real-life, yet somehow that's what is seen as 'good security
policy' in computers. Go ahead, pull the other one...]

Other than the fact that this idea is about 15 years overdue, it is at least a start in
the right direction.
joe
****


>
>Thanks.
>
>Best regards,
>Jeffrey Tan
>Microsoft Online Community Support
>==================================================
>Delighting our customers is our #1 priority. We welcome your comments and
>suggestions about how we can improve the support we provide to you. Please
>feel free to let my manager know what you think of the level of service
>provided. You can send feedback directly to my manager at:
>msd...@microsoft.com.
>
>This posting is provided "AS IS" with no warranties, and confers no rights.

Jeffrey Tan[MSFT]

unread,
Mar 10, 2008, 3:30:52 AM3/10/08
to
Hi Joseph,

Oh, I do not have the best authority to answer all your questions, since I
am not in these security products groups.

Neither UIPI nor Vista UAC are perfect. Once all the processes are running
in the same desktop, there is no perfect security. There are still a lot of
potential attacks targeting UAC and UIPI, please refer to the blogs below
for some information:
http://theinvisiblethings.blogspot.com/2007/02/running-vista-every-day.html
http://www.authenticationworld.com/blog/2007/02/more_on_vista_uac_and_a_pote
nt.html

If you believe the document is not good for UIPI, my recommend is finding
the MSDN page and click the link of sending feedback to Microsoft. This
feedback will reach the MSDN document team who is in charge of that
technology.

As I know, Admin-mode UAC is also a compatibilty feature for the non-Admin
dream. Using the IL is the perfect solution to restrict security at the
process boundary, so do the Admin-mode UAC. Mark's blog below clarifies
this point:
"PsExec, User Account Control and Security Boundaries"
http://blogs.technet.com/markrussinovich/archive/2007/02/12/638372.aspx

With our token running under the non-elevated Admin token, we still have
the Admin account Sid in the token, which makes it hard to enforce the
securiy. The recommend practise is running the interactive account under a
real normal user account.

Steph

unread,
Mar 10, 2008, 12:28:01 PM3/10/08
to
Jeffery,

Thank you for investigating this matter. I'd be interested to hear if you do
get any more information.

Steph

Jeffrey Tan[MSFT]

unread,
Mar 11, 2008, 4:24:39 AM3/11/08
to
Hi Steph,

Thanks for your feedback.

I still did not get any further story or comment from the UIPI team yet. I
assume this may be internal reason/information which is not available to be
public(at least, I am not authorized to get it public). Thanks for your
understanding.

I find an internal document says that SetForegroundWindow will bypass IL
validation so your code works as expected.

Anyway, if you need further help, please feel free to post, thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and

0 new messages