Archive: Shortcuts on Vista


Shortcuts on Vista
What is the proper way to create shortcuts on Windows Vista ?
If I set 'RequestExecutionLevel admin', install is running as administrator and shortcuts are created for administrator not the currently logged in user.
If RequestExecutionLevel is set to user, then shortcuts are properly created, but you can't write to Program Files, write unistall registry key...

How can I create shortcuts for current user (SetShellVarContext is set to current) ?

Thanks

Alex

**********************************************************
[edit] 08/05/07 - DrO
Please refer to http://nsis.sourceforge.net/UAC_plug-in for information and plugin regarding this thread


I could reproduce this with "Standart User" account :( UAC not only elevates execution level, but changes user as well... Even desktop links created for UAC requested admin account.


I think this is a serious problem which should be handled by NSIS. Of course we could build wrapped installers where some are running as user and some as admin. But this will be some very basic problem with Vista in general.

Problems:
1. Registry: HKCU
2. User profile directory (shortcuts and more)
3. "Run ... now" on finish page (this is a small issue in XP too if the installer is run as admin there). This might be a problem for other (custom) ShellExec's, too.

Can NSIS change its execution level at runtime? Does anybody know what Vista does here?

I think the best solution would be to run as admin in general when RequestExecutionLevel admin is set but to make special handling for HKCU / shortcuts.

Could NSIS detect what user was active before elevating?


No NSIS could not detect this, vista elevates before the actual process is started


I'm developing a plugin that hopefully will help to deal with these Vista problems, its still "in Beta" so don't blame me if it doesnt work or blows up in your face (or all over your HD)

Checkout UAC_RealWorldExample (Known issue: Does not print to instfiles page log or any kind of success feedback when elevated)


http://stashbox.org/13537/UAC%20v0.0.5b.zip

IMHO The shortcut problem is not really a problem, when using RequestExecutionLevel admin it is a "All users" install, if you want to use RequestExecutionLevel user, you should write the uninstall entry in HKCU and install your files in $LOCALAPPDATA


I agree: short cut is no real problem, I think I will just disable the possibility to install them for "current user". I know of current user installs but this is not an option for most of my installers here.

I use HKCU to store some settings for the user who installs the application. E.g. the license text can be stored as "seen" for the use who read it during install. Other users will get it on first application start. And I store language settings and more for the installing user.

Thanks for the new plugin, is there some short documentation how the functions work (other than the examples)?

As far as I can see this works like:

- start in user mode
- elevate to admin mode (with error/retry handling)

Can I un-elevate (back to user mode)?
If yes, I guess re-elevating (elevating for the 2nd time) would require additional password entry.

It seems the current process is changed at run-time. What does change on elevation? Username? access rights? "current user" profile (NSIS vars?)

What about my Exec problem? Currently I would like to run the installer as admin (could be done by requestlevel user and elevating in .oninit) but make the run caused by the finish page checkbox ("run now ...") to run the app as original user.


The SAFER plug-in should solve the Exec problem. But if the user is switched and not elevated, you won't get the original user.


There are no docs at this time, the exported functions have a little bit of text if you look in uac.cpp

You cant un-elevate once you have elevated (Well you could call UAC::Exec on yourself but that would be the same as a "current user" install)


This plugin should solve the Exec problem, use Process Explorer (Sysinternals/MS), turn on the User and Intergrity level columns and run the realworld example as a normal user elevating with a different admin account


What changes after elevation depends on whether UAC is on or off.

UAC on and the user is an admin (Split token):
Nothing really changes
UAC::IsAdmin returns 1 after elevation and 0 before
UAC::SupportsUAC returns 1
UAC::GetElevationType returns 3 before successfull elevation with RunElevated and 2 after

UAC off and the user is an admin:
Nothing really changes
UAC::IsAdmin returns 1
UAC::SupportsUAC returns 0
UAC::GetElevationType returns 1

User not member of admin group:
Everything changes (Username/Profile/HKCU part of registry)
UAC::IsAdmin returns 0 before elevation and 1 after
UAC::SupportsUAC return depends on whether UAC is on/off
UAC::GetElevationType again depends on UAC on/off
(NOTE: Vista seems totally broken in this configuration (IF UAC IS OFF), try right clicking on a .exe and choose "Run as administrator", nothing happens, in this case the plugin uses its own custom RunAs dialog)


on pre vista systems UAC::GetElevationType always returns 0

the UAC plugin can allow you to run in "current user" mode, if $0 == 1223 after UAC::RunElevated the user clicked cancel in the UAC/RunAs dialog (This is all up to the creator of the installer)

The SAFER plugin doesnt work very well on Vista, MS broke the SAFER api on this OS (It still works but the process will still run @ High integrity level)

Note: This is all from memory, i might have missed something


Thanks a lot, Anders.

Some questions:
Can you explain Exec a bit more? How does this work? Does this run the process with the original user (calling the installer)? How does UAC::Exec behave on Non-UAC-systems?

Does this help with RunAs (WinXP) or is RunAs with XP always independent from the original user (I guess this is the case, so maybe the "run now" on the finish page is bad for XP when RunAs (possibly) is used).

I'm trying to understand this (before testing/verifying).

You wrote: "in this case the plugin uses its own custom RunAs dialog"
What do you mean with this? How is the "run as dialog" correlated to NSIS here?


Run process explorer, you can see two instances(processes) of your setup, one running as the user that started the setup and one running at high integrity level (and possibly as another user if the original user was not a member of the admin group) When you use UAC::Exec/ExecWait/ShellExec/ShellExecWait the 2nd elevated process will send a message to the original process telling it to start a process (uses WM_COPYDATA)

Running as admin on pre vista or admin with UAC off on vista will only use one process and UAC::Exec just calls CreateProcess without any trickery

EDIT: on win2000/xp it somewhat emulates the vista elevation, UAC::Exec will start a process as the original user
I guess you could use the SAFER plugin on xp so the process spawned at the finish page does not run as admin even if the real user is admin


UAC::RunElevated just does ShellExecute on itself using the runas verb (The documented way to get the uac dialog on vista) this also works on Win2k/XP except you get the old school runas ofcourse. If a non-admin user on vista with UAC off is detected, using runas with ShellExecute will not work at all so UAC::RunElevated uses its own dialog that emulates the pre vista runas instead


Thanks Anders, I will try your plugin.


New version: http://stashbox.org/13698/UAC%20v0.0.5c.zip

IsAdmin can now handle a restricted token on <NT6, no other changes


New version: http://stashbox.org/15549/UAC%20v0.0.5d.zip

Fixed a bug in IsAdmin, please update


@Anders: You call UAC::Unload in .oninstfailed/.oninstsuccess.
Is this necessary?

I use Quit in many places in my scripts (to abort the installer immediately) and this will not run those callbacks, so UAC::Unload will not run. Is it safe to Quit without "UAC::Unload"?


Additional question: Does UAC::Unload harm if UAC plugin wasn't used/loaded before?


It will not crash if you dont call unload, but it will probably leave uac.dll in $pluginsdir so you will leave stuff behind in the users $temp dir. The only thing UAC::Unload does is to call FreeLibrary on itself so you should probably call it if possible. If you call Quit before you call any UAC function you dont need to unload (IsAdmin,SupportsUAC and GetElevationType is safe to use without unload, RunElevated and ExecCodeSegment is not)


I could not try it myself (yet), what about error level return values? I use "set error level" within my script and the outer process should return those error level value, too (if set).


Ah, found it:

RunElevate returns
"r2 is the ExitCode of the elevated fork process (The NSIS errlvl is also set to the ExitCode)"


The plugin seems to work. Thanks, Anders!

UAC::GetElevationType and UAC::SupportsUAC return "0" for XP. But RunElevated supports RunAs dialog (nice feature). It would be nice to have functions UAC::GetRunAsType and UAC::SupportsRunAs so one can show some message to the user before the RunAs dialog is shown. Seems that at least SupportsRunAs is already implemented (but not exported to NSIS).


UAC::GetElevationType and UAC::SupportsUAC return 0 on XP and below because those are Vista specific.

I think RunAs is supported on all NT systems (And it is not needed on 9x) atleast it works on w2k and up. I don't have a NT4 box to test on so im not sure. What would UAC::GetRunAsType do, tell you what kind of runas dialog you would get (Does it really matter)?

I like the idea of the messagebox before elevation (Even tho users will get used to the elevation on Vista), I could probably create something like UAC::SupportsRunAs


GetRunAsType could return "1" if this is the inner process. I currently check myself for "/UAC:" in CMDLINE. I have to do this because the MessageBox I show will appear twice if I show it always before RunElevated.

I don't really know whether GetElevationType will really return the state of "inner" or "outer" process (imagine outer user IS admin, even with UAC -- could be caused by automatic install scripts). So maybe GetRunAsType could be something like "IsInnerProcess"...

I simulate SupportsRunAs for now by checking the OS major version against "5". AFAIK NT4 does not have something like RunAs (at least "runas.exe" is only available with 2k/XP).


You dont really need to know if you are the inner process or not, if IsAdmin returns 1 you are either already admin or the elevation has been performed


NT4 users should install and use the SU command from the NT Resource Kit.


@Anders: I need to know. It is helpful anyway to know this, but if I don't detect this (inner process yes/no), I will show the warning message twice if the user logs in as non-admin in RunAs dialog (try for yourself; it took me some minutes to detect what was going on there).


ah ok, just look for "/UAC" then utill I can get a new version out


Downloaded your pluggin today to try to fix some exec problems i've been having in vista. I ended up making an function to install files in restricted areas and calling it to run in ellivated mode, but it didn't work, instead producing an error when the installer tried to write to the secured area.


Post code here for help.

UAC plugin works fine for me. One important thing to know is that the whole installer will run elevated (or not), so you cannot have a single function run elevated and the rest unelevated (you would have to do this manually).


Hello,

I am trying to make an installer which runs with "RequestExecutionLevel user".

During the installation process the user can select whether he just wants to execute or install the software. If he wants to install the software I use UAC::RunElevated to restart the installer with all necessary tokens. This works fine if the current user is an admin.
When I try it with an ordinary user the RunAs Dialog is dispalyed but the second program is not executed.

RunElevated returns a value of 6 which is (to my knowledge) the error code for a missing handle.

Any ideas what is happening there?


Could you post some example script with this problem?


Hello Anders,

Thank you for your reply.
Unfortunately a code snippet will not be of much help.
I only call UAC::RunElevated when logged in as a domain user in Win Vista.

But the thing gets even stranger: I tested the installer from my desktop. When I copy the same installer to some other folder (e.g. \programms) UAC::RunElevated runs perfectly (RunAs Dialog is being displayed and the installer is restarted with the correct privileges). Btw: It also does not work when I run it under \users.
Maybe it is some kind of special virtualization with Vista.
Any ideas what is causing this?


I have no idea whats going on, and I don't have a domain setup to test with (I don't even have a Vista install to test on ATM)


FYI:
I did some further research (trial and error...).
The error has nothing to do with whether the user is in a domain or not.
It just seems that CreateProcessWithLogonW does not work when the installer is in a user related folder (e.g. Desktop, Documents, etc.). If I copy the installer to some other place (e.g. Programms, Public, etc.) the installer works just fine.
I added some messageboxes to the uac.dll but CreateProcessWithLogonW did not give me any errors.


Originally posted by MarcOfChaos
But the thing gets even stranger: I tested the installer from my desktop. When I copy the same installer to some other folder (e.g. \programms) UAC::RunElevated runs perfectly (RunAs Dialog is being displayed and the installer is restarted with the correct privileges). Btw: It also does not work when I run it under \users.
Maybe it is some kind of special virtualization with Vista.
Any ideas what is causing this?
I just tested it on my Vista machine.

I ran my installer on a limited Vista user account. If I ran it from a non-user folder, I got the Run As dialog. I put in the Administrator name and password, which Windows accepted. But my NSIS/UAC plugin code reported that admin access is required.

When I moved it to the users desktop folder, I received the error 6 as you mentioned. :(

Please describe your exact setup (Vista SKU, UAC on or off, type of user, exact directory it fails in)

Try this debug build: http://stashbox.org/19884/UAC.dll and watch the (unhelpful?) debug output with DebugView ( http://www.microsoft.com/technet/sys...debugview.mspx )

Are you sure the problem is with CreateProcessWithLogonW? you could comment out #define FEAT_CUSTOMRUNASDLG in uac.h to disable that code, but in my experience, Vista does nothing if you call ShellExecute(0,"runas") if the current user is not in the admin group and UAC is off (thats why I had to call CreateProcessWithLogonW in the first place)


Anders,

Your reply seemed to be directed at MarcOfChaos, but with your blessings, I'd like to help do what I can on this problem as well. I would really like to get this plugin working. Prior to receiving said blessings, I'm going to help anyways. :)

Attached is a .zip file containng two log files generated from DebugView.

Setup:
Vista SKU - Vista Home Premium
UAC is on
User - A Standard User (I named my standard user account "Peon")

standarduser_regularfolder.LOG is an example of me trying to run your UAC_AdminOnly sample from my C:\download\nsis\ folder. I put in my info into a Run As dialog, it said it needed admin access, so I tried again, it said it needed admin access, so I clicked cancel, and received the NSIS script message that it's aborting.

standarduser_userfolder.LOG is an example of me trying to run your UAC_AdminOnly sample from my C:\Users\Peon folder. I put in my admin info into the Run As dialog. I then got 2 message boxes (if you want the message box info, let me know...it was something about line 53 and line 60 i think), then the NSIS script gave the error: "Unable to elevate , error 6"

One last thing. I went into the log files and changed my actual password to simply "password". I don't want you seeing my real password :P


Hm, when UAC is on, you are not supposed to get my runas dialog, but the normal vista elevation dialog. My detection for this must be messed up. Would be great if you could drop by the nsis irc channel so I could create some test builds for you

or try http://stashbox.org/19898/UAC.dll


Anders,

I'd be happy to test that out and jump int the IRC channels to help you out (I really appreciate the time you're putting into this).

But for now, I have to go. I've got tickets to the Utah Jazz vs. Golden State Warriors Game 1. :)

(Also, I just double checked to verify UAC was on. When I ran a normal NSIS installer on my standard user account, I did get a UAC dialog asking for an administrators password.

When I ran a NSIS installer with your UAC plugin under the same user account, I did get the Run As dialog.)


Hello,

Sorry for my late reply. I am currently a little busy (who is not? ;))
Find attached the logfiles and error messages of the 2 debug builds.

I tested on Win Vista Ultimate with activated UAC.
Just like helix400 I changed the passwords and usernames.


Hi Anders, I have three improvement suggestions:

1. The built-in RunAs-dialog for Vista is english only. This dialog should be "multi-language" (e.g. by loading text strings from some ini file in $PLUGINSDIR).

2. Currently we do not a RunAs-dialog which allows all users etc. We always want the user to login using an admin account. So the dialog might be changed: other texts, maybe a combo box where (local?) admin usernames are pre-filled etc. The "current user" setting (radio selection) seems quite useless here.

3. The XP/2000-RunAs-dialog is not optimal for installers because it has worse defaults. A good own dialog (see points 1 and 2) for Vista could be used for XP/2000, too. The dialog should mention the need for elevation (so we do not need a messagebox with explaining texts before).
We just need some text explaining why this dialog appeared and what the user is expected to do, a possibility to enter a username (Administrator account should be preselected) and a password input field.


Just an idea: I don't know whether the system RunAs-dialog in Windows 2000/XP supports other authentication methods than password. Think of a fingerprint reader...


Archive: Shortcuts on Vista


thanks everyone for testing, I will need to find a new way to detect if i need my runas dialog

Please report the output of this console app: http://stashbox.org/19958/TokenElevation.exe (Based on code from http://blogs.msdn.com/cjacks/archive...ows-Vista.aspx )


Hi,

Did some further research:
TokenElevationTypeDefault only means that the user does not have a split token. This should be true for 'nearly' every user that is not an administrator.
I also found a clue on how to determine whether UAC is enabled.
One could try to check in the registry whether the policy is enabled or not.
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA
Possible values: Enabled (1), Disabled(0)

Hope this helps...


Hi,

find attached the screenshots of the TokenElevation.exe.


I tested TokenElevation as well. I got different result when I ran the app from a regular folder with a standard user account. Screenshots are attached below.


Just an update for those following the thread. I worked with Anders more today. He got a version working where the UAC dialog pops up when it should (when UAC is turned on), and the Run As dialog pops up when it should (when UAC is turned off). In all situations, the test apps worked. There's still the issue of the installer window popping up behind active windows...he'll work on that later.


Ok, I created a wiki page @ http://nsis.sourceforge.net/UAC_plug-in , only done limited testing, but I hope its fixed, please report back


Sorry, but I got kind of lost as to how this plug-in helps to create shortcuts in the user's own start menu instead of the all users one. Can anyone give me a bit of guidance? Thanks.


It's more of an overall UAC thing, which has a nice side effect of solving the Vista user shortcuts problem.

The way this plugin works is the following:

1) First, the NSIS script needs to say it wants user privileges, not admin privileges.
2) The NSIS installer launches, and quickly calls its .onInit code (no form has shown by this point yet). That code makes a new process and attempts to elevate it to admin mode. Anders calls the first process the outer process, and this second process the inner process.
3) If needed, a UAC or Run As dialog is shown. After that, the inner process should be elevated to admin access. Then this admin/inner process can display. This is the main installer app that users will see. At this time, two processes are running. One as a user, another as an admin.
4) Now that you have an admin process, you can continue to let your script do its thing. If you ever need to do something at a user level, you do it through the UAC plugin. For example, UAC::Exec can execute something with user privileges and not admin privileges.

With all this in place, you can do some system calls to create a shortcut as a user. Personally, I think the UAC plugin should have some extra features added on, such as UAC::CreateUserShortcut or something like that. But then, Anders has been working really hard on just getting the bugs worked out of the current plugin...I'm just happy he's providing a fairly clean solution compared to the really ugly alternatives out there in the Vista world.


I see... thanks for the nice, detailed overview. Now to figure out how to actually make those shortcuts using UAC::Exec...


You should not use UAC::Exec for that, use ExecCodeSegment

UAC_RealWorldExample.nsi does:

Function CreateShortcuts
CreateShortcut "$Desktop\${APPNAME}.lnk" "$Windir\Notepad.exe"
FunctionEnd

Section "Desktop Shortcut"
GetFunctionAddress $0 CreateShortcuts
UAC::ExecCodeSegment $0
SectionEnd

the CreateShortcuts function will execute as the original user (You get no feedback in the install log, hopefully I will implement some kind of DetailPrint that "works the other way")


So... just to make sure I'm understanding this correctly... basically we encapsulate the stuff we want to do as the original user in a function, then use UAC::ExecCodeSegment on the function address to execute the stuff?

Sounds pretty simple... thanks a lot!


yes, the only problem is that you get no output in the install log since its actually executing in a hidden installer


With Anders permission, I've added more documentation to the plug-in page at: http://nsis.sourceforge.net/UAC_plug-in

Some of it was based off comments mentioned in this thread. So if you find yourself saying "Hey, I said that!", it's because you did. :)


@Anders: I hope you consider my RunAs dialog ideas. Here's another feature request (which is quite obvious):

Allow communication from outer to inner installer. It would be nice if the ExecCodeSegment could return values. Either by allowing ExecCodeSegment the other way, too (outer calls inner => return values by a callback). Or by exchanging values internally using some UAC stack (UAC::Push, UAC::Pop, callable by both instances). Or something else.

The outer installer runs with user privileges, so it is a bit difficult to exchange information using some workaround (registry location). They both use different TMP (pluginsdir). Perhaps there is a possibility via windows API. I think about something like PeekMessage / PostThreadMessage (but those might interfere the GUI event handling...)


Yeah, I have already thought about adding stack support. The problem is, you can't send a message the other way without reducing the security of the admin instance

As for changes to the run-as dialog, those are way down on the list, you are only supposed to see that dialog if you are non admin with uac off. And I'm not sure if using my dialog is smart on 2k/xp, I don't know how much it changes if the machine has a custom GINA and stuff like that. Maybe I could implement some sort of show function callback and you could do whatever you want to my dialog

This thing was really just to support starting a process on the finish page, not sure how smart it is to add to much support for other stuff. Duplicating every NSIS api call to provide proper feedback is just too much work. The outer instance never gets past .onInit so there are no DetailPrints i can just "steal" from the listview either and there is no way to hook into the nsis calls as far as i know


Please make your RunAs dialog at least customizable (language strings). Is this an privileges problem? I guess the RunAs dialog is an outer process thing.

Regarding security issue (passing values from outer to inner): I think about two ways:

a) the inner process has admin privileges. We could use this to let the inner process read those values out of the process context / environment /... of the outer one.

Very simple solution: create a temp file and pass the file to the inner process as CMD. So both processes could use this file. Problem: The privileges of the inner process could be insufficient. The file could be encrypted by EFS and the admin user would not have the key. So file is not good...

b) is the inner process technically a child process of the outer one? Perhaps there is something in windows which allows limiting the communication to father-child.


http://support.microsoft.com/kb/95900/en

Perhaps Memory Mapped Files could help:
http://msdn2.microsoft.com/en-us/library/ms810613.aspx

I know you started UAC only for the Finish-Exec problem. And the current solution is quite nice. The "Passing parameters back" is not as important (for me). Anyway the plugin is great, thanks for your effort.


The biggest problem is not how to pass data back, its what to pass. Even if I added UAC::DetailPrint that works the other way, what strings would you pass back?


Originally posted by Anders
Yeah, I have already thought about adding stack support. The problem is, you can't send a message the other way without reducing the security of the admin instance
I stumbled on a new Vista API function that allows an admin process to register a type of message so that user-level process could send it messages of that type. Unfortunately, I can't remember the name of it now (my work computer probably has it in the browser history).

Also, in XP and 2000, can a user-level process send messages to an admin-level process? I was under the impression they could.

I don't know if this is any help for you, just chiming in with a thought.

I don't need UAC::DetailPrint. What I want is doing some processing for current user (not just Exec on finish):
Reading HKCU and writing HKCU, reading files from the user's profile/writing files (SetShellVarContext).

Doing actions (write) is possible using your UAC::ExecuteCodeSegment. But I cannot read values. I want to read a value (outer process), process it in the main installer (inner process), show it in the GUI, allow user options etc. and then do the action using UAC::ExecuteCodeSegment.

Reading those values using the inner process is no option because the files / keys could have privilege problems (or EFS encryption). So the original (outer) user account has to be used here.

At first I just want to pass some bool (yes/no), but in general it would be nice to at least allow int numbers and when possible strings.


* Check wiki for new version with basic language support. (See readme.txt and UAC_RealWorldExample.nsi)

Yes, on < Vista you can send messages to any window. I know I can use ChangeWindowMessageFilter to allow messages from the outer instance, but that would add possible security issues.

You can read the HKCU part of the registry from the inner instance unless the permissions on that key has done something to block admins (You would probably never see this in practice) You can probably do something with the access control plugin to make sure the inner instance can read from the outer instance's $pluginsdir.

I'm not sure if I want to add support for any kind of message passing from outer to inner, but you are free to fork the code ofcourse. The UAC plugin is all about support for all users type installers so why would you read user specific values?


Anders,

I've been playing around with your plug-in and my installer now works perfectly under a limited Vista account.

I did however notice a problem with the uninstaller; When I start the uninstaller the Vista elevation dialog pops up as expected, when I enter the correct info and click OK my uninstaller UI however doesn't pop up.
When I check the task manager I do see 2 uninstaller processes running, 1 as a normal user and 1 as an administrator.

After some investigation I noticed that this problem only occurs when my uninstaller uses the Modern UI. When I do not use the modern UI the uninstaller works as expected. Do you have any idea what's going on?
If you need any more info from me please let me know.


I noticed a similar issue with Vista (which seems to be a Vista bug) and solved the problem by calling

ShowWindow $HWNDPARENT "${SW_SHOW}"

in the show callback function of the first visible GUI page (welcome page).


Originally posted by stb
I noticed a similar issue with Vista (which seems to be a Vista bug) and solved the problem by calling

ShowWindow $HWNDPARENT "${SW_SHOW}"

in the show callback function of the first visible GUI page (welcome page).
Thanks, I have added a custom callback function to the uninstaller as you described and this fixed it. For me the problem only occurs for the uninstaller and not for the installer which to me seems kind of strange (what's the difference between installing and uninstalling for the OS?).
If anybody is interested I have added the following code to my script:


!define MUI_CUSTOMFUNCTION_UNGUIINIT un.GUIInit

Function un.GUIInit
ShowWindow $HWNDPARENT "${SW_SHOW}"
FunctionEnd

I noticed this in the installer with UAC disabled in Vista when self-executing the installer (copy in TEMP). This inner process (outer is finished because it doesn't wait) did not show any GUI Window (style was invisible). With XP SP2 this window was always visible.

Thanks for the hint to GUIINIT, I think that location is better.


Originally posted by stb
I noticed this in the installer with UAC disabled in Vista when self-executing the installer (copy in TEMP). This inner process (outer is finished because it doesn't wait) did not show any GUI Window (style was invisible). With XP SP2 this window was always visible.

Thanks for the hint to GUIINIT, I think that location is better.
I cannot reproduce what you describe above, what do you mean by "self-executing the installer (copy in TEMP)"?

Also for Anders I noticed another glitch.
On one of my test machines (actually a VMware machine) I have an administrator account without a password (I know this is unsafe ;)). With UAC disabled I get a nice run as dialog, I am however not able to use my administrator account because of the blank password.

First off, I am able to reproduce the invisible uninstaller window on XP Pro SP2. Will try to look into this at some point. For now, use the showwindow hack

Edit: I think i fixed it, please try with the latest version on the wiki


RichZ: Could you take a screenshot of the dialog? Do you get a error message?


Originally posted by Anders
First off, I am able to reproduce the invisible uninstaller window on XP Pro SP2. Will try to look into this at some point. For now, use the showwindow hack

Edit: I think i fixed it, please try with the latest version on the wiki


RichZ: Could you take a screenshot of the dialog? Do you get a error message?
I have attached a screenshot, it states that a possible reason can be because of a blank password, but I have not enforced such a policy.

I wanted a screenshot of the runas dialog and not the error but it doesnt really matter.

There is nothing i can do about this, CreateProcessWithLogonW fails with blank passwords by default. You can set limitblankpassworduse=0 in HKLM\SYSTEM\CurrentControlSet\Control\Lsa to override this


Originally posted by Anders
I wanted a screenshot of the runas dialog and not the error but it doesnt really matter.

There is nothing i can do about this, CreateProcessWithLogonW fails with blank passwords by default. You can set limitblankpassworduse=0 in HKLM\SYSTEM\CurrentControlSet\Control\Lsa to override this
Alright, thanks for the solution, not a big problem because a blank administrator password is not what you want anyway ;)

I will test your solution for the invisible dialog later on.

If you turn UAC on, will it elevate even if the admin password is blank?


Anders, I have checked the latest build (v0.0.6b) and the problem with the invisible dialogs is indeed fixed, thanks for the quick response. :up:


Originally posted by Anders
If you turn UAC on, will it elevate even if the admin password is blank?
Yes with UAC on there is no problem, it will elevate with an empty admin password.

Oh good, the UAC plugin is still improving. :)

Just to let you know Anders, we've deployed an installer containing it to several hundreds people so far. There haven't been any issues found by anyone yet.


source for UAC plugin not compiling
I am sure I am just being stupid here but I can't get the uac plugin source to compile (found here: http://nsis.sourceforge.net/UAC_plug-in)

TokenOrigin is not defined. Where is TokenOrigin defined?

Anyways TokenOrigin is being used in the UAC.h header file in this enum definition:
enum _TOKEN_INFORMATION_CLASS___VISTA {
TokenElevationType = (TokenOrigin+1),
TokenLinkedToken,
TokenElevation,
TokenHasRestrictions,
TokenAccessInformation,
TokenVirtualizationAllowed,
TokenVirtualizationEnabled,
TokenIntegrityLevel,
TokenUIAccess,
TokenMandatoryPolicy,
TokenLogonSid,
};

Thanks in advance for any help you can provide, and my apologies if this is the wrong place to post this.


in WinNT.h (You need a somewhat recent Platform sdk, mine is from 2003)

_TOKEN_INFORMATION_CLASS___VISTA is my fake enum since I don't have the latest Platform SDK installed


Anders, would you consider adding a method that created a process using CreateProcessWithTokenW using the desktop's token? This would allow an uninstaller to create a process that isn't elevated. I can provide the code to accomplish this and it seems that this would be a good plugin to add this to vs. creating a plugin that just did this.


Yeah, I would consider it (Depending on how you get this token, remember, the user could use a shell that is not explorer.exe etc.)


Something like this?

extern "C"
void __declspec(dllexport) LaunchWithTopMostWinToken(HWND hWndParent, int string_size,
char *variables, stack_t **stacktop,
extra_parameters *extra)
{
EXDLL_INIT();
{
char szCmdLine[MAX_PATH];

if (popstring(szCmdLine) == 0)
{
if (!pCreateProcessWithTokenW)
{
// CreateProcessWithTokenW is not present on WinXP or earlier
*(FARPROC *)&pCreateProcessWithTokenW =
GetProcAddress(GetModuleHandle("advapi32.dll"),
"CreateProcessWithTokenW");
if (!pCreateProcessWithTokenW)
{
pushstring(OUT_ERR);
return;
}
}
// use the token from the topmost window (highest in the z-order) to drop the privilege
HWND hwndTopMostWin = GetWindow(hWndParent, GW_HWNDFIRST);

DWORD dwProcessId;
GetWindowThreadProcessId(hwndTopMostWin, &dwProcessId);

HANDLE hProcessTopMostWin = OpenProcess(MAXIMUM_ALLOWED, FALSE, dwProcessId);
if (!hProcessTopMostWin)
{
pushstring(OUT_ERR);
return;
}

HANDLE hTokenTopMostWin;
BOOL ok = OpenProcessToken(hProcessTopMostWin, MAXIMUM_ALLOWED, &hTokenTopMostWin);
CloseHandle(hProcessTopMostWin);
if (!ok)
{
pushstring(OUT_ERR);
return;
}

HANDLE hNewToken;
ok = DuplicateTokenEx(hTokenTopMostWin,
MAXIMUM_ALLOWED,
NULL,
SecurityDelegation,
TokenPrimary,
&hNewToken);
CloseHandle(hTokenTopMostWin);
if (!ok)
{
pushstring(OUT_ERR);
return;
}

STARTUPINFOW si = {sizeof(si), 0};
PROCESS_INFORMATION pi = {0};

WCHAR wszCmdLine[MAX_PATH * 2];
MultiByteToWideChar(CP_ACP, 0, szCmdLine, lstrlen(szCmdLine) + 1,
wszCmdLine, sizeof(wszCmdLine) / sizeof(wszCmdLine[0]));

if (wszCmdLine)
{
ok = pCreateProcessWithTokenW(hNewToken,
0, // profile is already loaded
NULL,
wszCmdLine,
0, // No special process creation flags
NULL, // inherit my environment
NULL, // use my current directory
&si,
&pi);
}
CloseHandle(hNewToken);
if (ok)
{
pushstring(OUT_SUCCESS);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return;
}

}
pushstring(OUT_ERR);
}
}

Forgot pCreateProcessWithTokenW

BOOL (WINAPI *pCreateProcessWithTokenW)(HANDLE,
DWORD,
LPCWSTR,
LPWSTR,
DWORD,
LPVOID,
LPCWSTR,
LPSTARTUPINFOW,
LPPROCESS_INFORMATION);

Archive: Shortcuts on Vista


I'm sorry, but that is horrible, you just use some random window token. Can you get the token for GetDesktopWindow() or is that restricted somehow?

What about Win2000/XP ?


GetDesktopWindow didn't work and I didn't spend any time trying to figure out what was up with this. I'll look into what's going on.

Regarding Win2K/XP the comment:
// CreateProcessWithTokenW is not present on WinXP or earlier
so it returns an error allowing fallback to Exec, ExecShell, etc.


You can't fall back to Exec/ExecShell, you have the same problem on 2k/XP if you use runas


I understand a solution for the runas on systems without UAC or UAC is turned off would be a wonderful thing but that is highly unlikely from what I have read of other people's struggles with this (e.g. using task scheduler... I mean damn!). ;)

On the other hand being able to launch an app at the end of uninstall (e.g. option to open a web page) which is typically not elevated through runas (e.g. ARP or Programs and Features) though on Vista with UAC turned on is elevated would be a good thing. If a 100% solution were possible I'd certainly go for it but without that I am willing to settle for good vs. perfect since perfect isn't an option from what I have read on this scenario.

I'll probably just provide the option when the progman window is available to avoid using a random window and throw together a simple plugin to provide this when the target is Vista with UAC turned on.


ExecShell should open a http:// style URL without elevation no?

There is another problem, ARP is disabled untill all subprocesses finish, I created a hacky workaround for that @http://nsis.sourceforge.net/Escape_A...th_New_Process (Not tested on vista)


No, it regretfully inherits from the process that calls ShellExecute.

Thanks for the pointer on the workaround using JOB_OBJECT_LIMIT_BREAKAWAY_OK. That has been an annoyance for a long time.


UAC-Plugin - Multiple security warnings on Vista
Hi,

i have a problem with the UAC-plugin on vista.

After i clicked the button on my web page to download my installer, vista is poping up first a "File Download - Security Warning" with information about Name, Type and From. I think this i normal behavior.

After i confirm with clicking the "Run" button another security warning is poping up. This "Internet Explorer - Security warning" is asking if the software of a certain Name and Publisher is allowed to run. I think this is normal as well.
After i confirm "Run" i get a third security popup "Open File - Security Warning" which is asking if i want to run a file which is described with Name, Publisher, Type and where from. This file has the same name as my Installer except the installer name got a number suffix like Installer[2].exe and moreover it is stored under "c:\user\<account>\AppData\Microsoft\Wind...". Thats all what i can read from that path.
After i confirm the third installer and click on "Run" finally my installer window is coming up.

I dont think the third security warning should come up. It would only confuse the user.
Can you confirm such behavior? Is that normal?

Thank you for your help.

M.


This is probably not related to the UAC plugin

See http://forums.winamp.com/showthread....hreadid=278784


UAC-plugin security popups
Hi Anders,

before I included the UAC plugin in my script i only got the popup windows "File Download - Security Warning" for allowing to download and the "User Account Control" for running the installer. The disadvatage was that the installer window was not in focus after I confirmed the "User Account Control" window.

So by using the UAC-plugin my installer window is now in focus when it got started, but i have all the security warnings inbetween. ( "Internet Explorer - Security warning" and "Open File - Security Warning"). Havent had these security warnings without the UAC.

Therefore i was assuming the UAC raises such warnings.

M.


The UAC plugin will start the SAME exe one more time, so you might get another IE warning dialog, I don't know. Make sure you are have "RequestExecutionLevel user" in your script. If you can post a minimal sample script with this problem I might be able to look into it and see if I can come up with a fix


Sample script
Hi Anders,

I attached a simple script which is utilizing the UAC plug-in.
I signed the created installer before tested it.

The described problem with the multiple security warnings is not happening on Vista when you execute the installer direct from the hard drive.

It only happens on Vista when you run the installer out of a web page what means it gets downloaded and executed by IE7 and JavaScript without saving it to the hard drive.

I hope this will help you to figure out the problem.


Thank you very much for your help

M.


It still gets executed from the hard drive, just in the temporary internet files folder. I guess thats why you get the "c:\user\<account>\AppData\Microsoft\Wind..." path in the dialog, and the name installer[2].exe would indicate that this is the 2nd time you "ran it from a website". I'm not sure how any of this is related to UAC, other than the fact that you might get one extra warning from IE. It might be possible to check if $exedir is the temporary internet files folder and to copy your installer to $temp and then execute that.


Hi Anders,

I really think that the UAC-plugin makes it different in matter of security warnings.

For example if I run my simple test installer out of a web page without UAC-plugin i get the warnings:
- "File Download - Security Warning" download/run permission
- "User Account Control" elevate process

With UAC-plugin and basically the same test installer i get:
- "File Download - Security Warning" download/run permission
- "Internet Explorer - Security warning" run inst. as user
- "Open File - Security Warning" run installer as admin
- "User Account Control" elevate process

There must be a way that you can use the UAC-plugin with only the 2 security warnings as stated above.
Otherwise it could easily scare users away with so many warnings.

M.


nope, I don't think there is anything I can do. If you copy your installer out of temporary internet files and into $temp AND remove the "mark of the internet" (NTFS stream) you might be able to get rid of two warnings (you must do this before calling the uac plugin in .OnInit). Signing your installer might also help. This is a IE only issue that I don't really care about to be honest (you could also wrap your real installer inside a smaller one that just extracts the real thing to $pluginsdir/$temp and executes it)


plugin problems
When using the plugin the UAC dialog comes up minimized. This is bad because the user might miss it, even though it is flashing in the task bar. Once I click on the UAC icon I get the normal modal dialog with the desktop darkened.

Is this normal or am I doing something wrong?


unroar: which version of the UAC plugin are you using?


The comment in uac.cpp say it's version v0.0.6c - 20071014. I got the download from the wiki link.


When you say minimized, are you sure its not just BEHIND other open windows? If you drop by the NSIS IRC channel I might be able to provide you with some test builds


Latest version on the wiki should now fix the behind and/or minimized bugs (Hopefully) It also contains some other fixes, everyone should test the new build (It will probably be the last, the UAC plugin really needs a fresh start, I'm not sure when I'm up for doing that, if ever, you can still report bugs ofcourse and I will try to fix 'em)


hi i am a complete novice and need to use this plugin. where do i start? i have downloaded the zip file and extracted it, thats as far as i can get haha.


I guess you are better off not using it at all then if thats as far as you got on your own. You are probably better off using:

RequestExecutionLevel admin
SetShellVarContext all
and don't use the run checkbox on the finish page
If you need be admin on other NT versions aswell, you can use the UserInfo plugin that ships with NSIS to check in one of the init functions


Nice work on the UAC plug-in Anders ;). I have been using it for several months, allowing me to perform a post-install launch without propagating the high privileges of the installer to the child process.

Unfortunately, I have encountered a problem with the UNICODE build (built here /w VS2008). I am using it in conjunction with the UNICODE build of NSIS. I do not know which is at fault, but I suspect first the UAC plug-in.

I am getting a general failure in Windows x64 (unable to elevate). It appears to work in x32, though I have did have one user report of a failure to elevate for the x32 build -- leaving me unconfident.

I intend to so some debugging soon, but I figured I would ask here to see if anyone else has seen this, or if anyone is using this combination successfully for installations in Windows Vista+ x64.

Thanks!


Nevermind all.. My build of the UAC plug-in was bad. VS2008 had pulled in the CRT due to buffer security checks being enabled, and I had accidentally linked to the DLL version of it. This therefore caused a UAC.DLL load error on systems where the CRT DLLs weren't installed. Duh! Problem solved. I should have looked closer before posting here.

After removing the CRT dependency, all was well. My unicode build of the UAC plug-in ended up being 19KB, only 2KB larger than the official multi-byte distribution of it.

I can say now that the UAC plug-in definitely works great with the unicode build of NSIS ;).


when the next official release comes out (who know when that will be) it will ship with both versions so you don't have to recompile if you are not changing the source


Originally posted by Anders
when the next official release comes out (who know when that will be) it will ship with both versions so you don't have to recompile if you are not changing the source
Thanks Anders, I'm sure that will be helpful to many people -- and probably reduce the number of support requests you are bothered with, lol ;).

I attached a unicode build of Ander's UAC plugin to this post, in case it is helpful to anyone in the interim. This is version 0.0.11c.

I really appreciate your work on this plugin. Without it, I would have had to quit using NSIS.

Anders

Congratulations on the work you have done on the UAC plugin.

One strange problem I have encountered is as follows:
Windows 7 RC 1
A non-admin user
The install elevates and installs successfully using an admin user as the inner process. If I uninstall via Start Programs it elevates and works correctly. The paths are correctly identified via UAC as the outer user. However if I uninstall via the Control Panel (same nsi code and uninstall.exe) it elevates, but the install fails as the paths for the Data directory, the desktop icon and start menus are the inner (elevated admin) process and not the (outer) user.

If I run on XP both uninstall routes (Start menu and Control panel) elevate and work successfuly for a non-admin user.

I have worked on the problem for some time, but no luck.
Any help would be much appreciated.

It may well be a Windows 7 problem - I am about to submit as a problem to Microsoft. Any thoughts?

Paul


Vista and 7 will force the elevation for you IIRC (I'm sure this only happens when you put the uninstall info in HKLM)

You should stop creating stuff as the user and do a pure all users install (HKLM & SetShellVarContext all) if you don't want to deal with problems like this (Using the UAC plugin to launch a program during install is fine, anything else means your installer is broken and you will have issues like this)


Anders, you seem to be saying that NSIS + UAC plugin is broken if you try a user install. Do you really mean this, as it seem to me that the inconsistent behaviour on Windows 7 (uninstall.exe works via the start menu shortcuts, but fails through the Control Panel)is more likley a Windows bug? It's as though the windows 'executation context' of uninstall.exe, when launched via the Control Panel is different from that when done via the start menu. (I don't have a Vista system handy, so have not yet tried this on Vista.)


Well, it depends on what you mean by user install (In a real single user install, you would not call into the UAC plugin to perform operations since you are already running as the correct user and you will only write to HKCU and the users profile, not in HKLM or $programfiles)

I would not call this problem a windows bug even tho starting from a shortcut is not the same as starting from the control panel, since, if the uninstall info is in HKLM, you did a "all users" install and you will require admin rights to uninstall so windows just "helps you along"

So, if you run into this problem, it probably means you did a "mixed install" and this has never been correct (I know the UAC plugin really helps you do this, but it was not the original intent of the plugin, its only "supported" function is to run programs during install, not to create files or do any special action at all during uninstall)


Anders - thanks for such quick replies.
I take your point about the mixed install, which is not a good idea and I think I am guilty of doing this inadvertently. Also, the subtlety that the uninstall.exe was created with the correct paths (during the elevated install) had escaped me.
Thanks again, Paul


Hi, I am using the UAC plug-in, it works well for me. Just I have a requirement to suppress UAC if it is on, in order to let the installation process pure automatically, without any user interfere. Is it possiable through this UAC plug-in? If not, what should I do?

Thanks


june1212, please don't post the same question twice, it causes fragmentation of the answers.

--> Answered in http://forums.winamp.com/showthread....hreadid=313496


Hello over there,

I've a question regarding the UAC plugin and creating a Mutex to find out if the installation program is already running.

As far as I noticed the program is going to be run twice - in normal mode and in admin mode, if you confirm it. So if I create a mutex in onInit, it will be executed twice and then fail.

How do I prevent this?

Thank you for your great plugin!

The topic I posted my question first is:

Thread: CreateMutex Help Topic - Post #32
Post: Post #32 - Single Post View

Edit: Ok - I've a solution for my problem! Because we are going to check if there is an update required first before we execute the uac dialog I had to wrap it into those checks. And I create the mutex only if we have admin rights and the application can be installed. (see attachment)


I'm going nuts with the lack of documentation, and I can't find source code anywhere. Would it be possible to get a zip with the source uploaded to the wiki? http://nsis.sourceforge.net/UAC_plug-in

I'd be more than happy to add some documentation if I can get the source.


I have a question about using UAC plug-in.

I try to run setup from the non admin user and get "Run as" dialog box.
Then I fill 'user' field and 'password' field leave empty.
Then I get error something like "empty passwords are not allowed".

What could I do?


Originally posted by ivansobaka
I have a question about using UAC plug-in.

I try to run setup from the non admin user and get "Run as" dialog box.
Then I fill 'user' field and 'password' field leave empty.
Then I get error something like "empty passwords are not allowed".

What could I do?
This is a windows policy, probably Limit local account use of blank passwords to console logon only: http://technet.microsoft.com/en-us/l...8WS.10%29.aspx

Hello everyone,

thanks a lot for the great plugin! But I have troubles with UAC_AsUser_ExecShell / ExecShell - I want to execute an application as user but with administrative rights, because the launched application is storing some information in %APPDATA%.

- If I use ExecShell the information are stored in the administrators %APPDATA%

- If I user UAC_AsUser_ExecShell the information are stored in the users %APPDATA% BUT the application is not running in admin mode, so I can't changes files within my launched application.

Is there a way to run the application in admin mode but using the users scope variables?

Thank you very much!


Originally posted by klopfdreh
I want to execute an application as user but with administrative rights, because the launched application is storing some information in %APPDATA%.
This is not possible. Either it's running as admin, or it's running as user. It can never be both at the same time.

However, there is an easy solution to your problem: Use the UAC plugin to call a function as user (and make sure to use SYNCREGISTERS), and in that function copy the value of $APPDATA to a register:

Function SyncAppdata
setshellvarcontext current
StrCpy $0 $APPDATA
FunctionEnd

This way, you'll have the user's appdata path stored in $0, in the inner (admin) instance of your installer. Then, you can simply supply that user-appdata path as a commandline parameter to your application.


Edit: Here's two macros I created to do something similar, namely synching the contents of a variable, and synching the flags of sections, from outer to inner: http://pastebin.com/eM9MDUYL (Note that you shouldn't sync the $APPDATA variable using that syncvariable macro, because then the admin's $appdata will point to the wrong path. But you can modify it to suit your needs.)

Thanks a lot - Im going to evaluate that solution, soon.