I'm currently using ShellExecute "open" to open a URL in the user's browser, but running into a bit of trouble in Win7 and Vista because the program runs elevated as a service.
When ShellExecute opens the browser, it seems to read the "Local Admin" profile instead of the user's. So for example, if the user at the keyboard has Firefox as his default browser, it may open IE (which is the admin's default).
I know that the "runas" verb can be used to elevate, but how do you do it the other way around? Is there a way to open a URL in the default browser on a standard user's desktop from a service?
ShellExecute will execute the program in the context of the same session and same user as the process you are running.
If you'd like to use a different session or user token you can use the CreateProcessAsUser Win32 API.
There are several ways to obtain a user token, for example you can call the Win32 API:
LogonUser if you know the username and password
WTSQueryUserToken for any given session ID.
OpenProcessToken if you have another process handle
After a while of testing, the best way to determine the default browser is the following:
NOTE: It is strange but it's true...
It has nothing to say that an application is the default application for
some file type or web protocol like 'http'. What matters to determine the default
web browser is just what is registered in the start menu entry (see reg key below).
So forget all the HKCR\http, HKCU\Software\Classes\http, HKLM\Software\Classes\http and their friends.
read from "HKEY_CURRENT_USER\Software\Clients\StartMenuInternet"
read command line from "HKEY_LOCAL_MACHINE\Software\Clients\StartMenuInternet\\shell\open\command"
truncate the command line after ".exe"
Of course you need to impersonate as the logged on user first.
If this solution does not work (like with w2k), use the handler for the http protocol.
To actually start the default browser from a service we use an extra process which is within the service using the logged on user-context. This process starts the above commandline (using ShellExecute on platforms >= Vista). Be sure to use same integrity level (medium) as a default user (else IE won't work because it uses DDE).
HTH.
Aaron Margosis has a seven-step native code example at http://blogs.msdn.com/aaron_margosis/archive/2009/06/06/faq-how-do-i-start-a-program-as-the-desktop-user-from-an-elevated-app.aspx. Won't help you from your service if that is what you have - I agree your service shouldn't be trying to launch an app as the logged in user, especially since there might not be one.
Related
I use psexec to run my app,
Some of the tasks my app does should have a logged on user,
so I want to check (from the app, not the server which runs the psexec)
if there is a user which currently logged on. I couldn't find any api which retrieve this. My code is in c++.
Any idea to check it?
use LsaEnumerateLogonSessions + LsaGetLogonSessionData
Found a solution to this issue
I enumerate the registry keys (using RegEnumKeyEx) under HKEY_USERS.
If there is a key different from the default ones (".DEFAULT","S-1-5-18","S-1-5-19","S-1-5-20") it means that at least on user is logged on
I am working in an application. In this user enter his email id to get the some application setting.
After some time he will get mail with settings embedded and an apply button. Once user click on that we need to set the setting (in some file or registry).
Desktop application will read the setting(File / Registry) once it is launched.
This is the requirement. My question is,
How to call Win32/MFC application on clicking apply button with setting parameter.
You cannot arbitrarily execute something in an email message for obvious reasons.
The closest integration you could get would be to pass the configuration data as an argument to a custom URL handler in an HTML anchor; your mileage would likely vary wildly depending on browser/email client/webmail service so this is a bad idea.
Far better to simply send the configuration as an attachment with a file extension associated with your application and tell the user to open it, your app reads the config file and your done.
I am currently working on a project that interacts with a COM object. In my code I call the following:
CoInitialize(NULL); //Initialize COM system
HRESULT hr = spSSCProt.CreateInstance(("SSCProt.SSCprotector"));
This should get me the object I need. If this fails, it is presumably because the COM Server does not have the COM object registered using regsvr32. All is fine and well, I have the following code to handle that:
/if its not, lets try to register it ourselves...create the command
CHAR cmdBuf[BUFSIZE];
GetCurrentDirectory(BUFSIZE,cmdBuf);
string cmd("regsvr32 -s \"");
cmd += cmdBuf;
cmd += "\\stixDlls\\SSCProt.dll\"";
//attempt to register it
system(cmd.c_str());
The problem arises if the user is not an admin. They wont be able to execute the section of code the registers the COM server. Most of my users will probably not be admins.
Any ideas on how I can register the com server if they are not an admin.
Thanks
The whole point of Windows protection is to prevent you from doing things like that. How is Windows supposed to know you're not a virus trying to install some malware?
Your only hope is to start up another program which requests administrator privileges via its manifest. At that point Windows will ask for the administrator password.
If possible, the best place to do COM registration is during the installation process, which is usually being run under admin privileges. If that's not possible, there's another standard way: most home users on Vista and Win7 do have admin privileges - it's just not enabled by default. To enable those privileges you should request elevation through the (in)famous UAC.
I am attempting to add a temporary IP address to a NIC using AddIPAddress when logged in as a non-admin user. The MSDN documentation for AddIPAddress states that ERROR_INVALID_HANDLE is returned as as error if the function is called by a non-admin user.
Given that I have preceeded the call to AddIPAddress with API calls to LogonUser() and ImpersonateLoggedOnUser(). Now my application thinks it's logged in as an Admin, but AddIPAddress still fails with ERROR_INVALID_HANDLE.
MSDN also states that..
"Note Group policies, enterprise policies, and other restrictions on the network may prevent these functions from completing successfully. Ensure that the application has the necessary network permissions before attempting to use these functions."
Is it possible to call AddIPAddress using impersonation? if so how? I'm guessing I need to change the permissions mentioned above but I am at a loss as to what to chnage in this area.
Any help would be appreciated!
Additonal: I've also drawn a blank while attempting to call out to netsh (again logged in as a normal user) using CreateProcessAsUser using a handle to an impersonated admin user to launch the process. Always returns errors indicating insufficent priviledges.
If you are using windows Vista you may need to elevate privileges.
In Vista by default UAC is enabled. This makes it so that even as an administrator you are using a limited user token unless you explicitly elevate. When you do this the user is presented with a dialog to allow or deny the request.
For more information on this see Windows Vista Application Development Requirements for User Account Control Compatibility.
You may want to try using CheckTokenMembership to verify you are properly elevated after you log on as admin. I would suspect you are getting the limited user token and thus failing requests for privileged resources.
Best of luck.
How can I launch a URL in a NEW window using C++ (Windows only)?
The straight-forward approach seems to open a new tab in an existing browser window. (Or, if tabbed browsing is disabled, the new URL hijacks the existing browser window).
This is for a (large) desktop app, using MFC and Qt.
I've used this for showing locally generated html in the default browser, in my case filename is something like "c:\temp\page.html", perhaps replacing filename with the URL might work??
ShellExecute(NULL,"open",filename,NULL,NULL,SW_SHOWNORMAL);
Updated:
http://support.microsoft.com/kb/224816
How ShellExecute Determines Whether to Start a New Instance
When ShellExecute looks through the registry, it looks for the shell\open subkey. If the shell\open\ddeexec key is defined, then a Dynamic Data Exchange (DDE) message with the specified application IExplore and the topic WWW_OpenURL is broadcast to all top-level windows on the desktop. The first application to respond to this message is the application that goes to the requested URL. If no application responds to this DDE message, then ShellExecute uses the information that is contained in the shell\open\command subkey to start the application. It then re-broadcasts the DDE message to go to the requested URL.
So it looks like you have no control over opening a new window. Whatever browser currently running can handle opening it in whatever way they want.
This is controlled by windows. The only way to explicitly tell it to open in a new browser window is to spawn the browser explicitly and give it the url.
Here's a link to some code that will open a URL in a new browser. The code looks up the default application for handling an HTML document and then explicitly opens that application with a ShellExecute call.
You can't in general. The user's browser is free to do whatever the user wants it to do.
One way to achieve your desired effect might be to embed a particular browser in a window of your own (say, the IE ActiveX control) and have that render your URL.