We have a program with manifest attached and option "level="requireAdministrator". After program launched under standard user(not as admin), its elevating to admin user and from that moment SHGetFolderPath(0,CSIDL_LOCAL_APPDATA,0,SHGFP_TYPE_CURRENT,@buf)) returns admin local directory but not user's where it was originally started. Of course we could pass standard user token as third parameter to SHGetFolderPath but how we can get it in elevated program? Is there any way to do it?
Of course because of this problem we have another question. How to start another program with ShellExecute not as admin in elevated program? Of course we could use CreateProcessWithTokenW but still the problem with token exists(how to get this token). Right now we looking for IShellDispatch2 interface and try to start application not as administrator using explorer, but something tells me that this is wrong way.
I know that we have to start program as standard user then using com objects elevate only parts of code which should be executed with admin's rights. But still, the main question is with token.
Also there was an idea to make manifest with "level="asInvoker" and start first program as standard user, detect all local user paths and pass it as parameters to ShellExecuteEx with runas and SEE_MASK_NOCLOSEPROCESS options and run the same program but as admin. After the elevated program will exit we can execute any program from not elevated program not as admin. Is this right way?
Maybe a little late, but your alternative option is the right way to go. Once the program is elevated, there is no reliable way of starting yet another program but without the elevation, or even know what user started it, if it was done with different credentials.
The general solution to all those problems is to split the program in 2 different processes (which may be implemented in 1 or 2 different .EXEs, as you like). The "main" program, the one that the user runs, runs without elevation, manifested as
asInvoker
, and it in turn launches the second "worker" process, manifested asrequireAdministrator
. The main one can pass the data from the original user to the second by means of command line, unnamed pipes, window messages or any other form of IPC while the worker process does all the admin-only stuff. Possibly you may want to notify back to the main process when it's time to spawn another non-elevated program.