((Vista || Win7) && UAC && virtualization) && (T3D.exe || webPlugin) == pain
by Guy Allard · in Torque 3D Professional · 01/20/2011 (10:09 am) · 15 replies
I'm looking desperately for some ideas here to help get a product out of the door.
We have a game designed to be played in a browser, with the web page that it's contained in providing extra community functions and advertising. Naturally, we're using the web plugin.
When the web plugin is installed to the default directory of c:\program files on a users machine, the game is unable to save any data due to UAC. This includes compiled shaders, prefs and (importantly for us) streamed updates.
Normally, programs such as T3D which use the legacy method of writing files into a subdirectory of their installation directory have that data redirected by vista or win7 to their 'virtualStore' which is located in AppData under their user directory. This doesn't happen with the web plugin. This also doesn't happen with the default project settings for the .exe, although changing the manifest for the .exe to disable UAC results in the .exe using the virtualStore.
However, changing the manifest settings for the web plugins does not help.
As our intended customers are casual gamers, we cannot be expecting people to disable UAC just to play the game.
In a perfect world, windows would like programs to be installed in program files, but for their data to be stored in userdir\AppData. However, this is not possible with T3D as it restricts the saving of files to within the same directory tree that the executable is in.
If the web plugin is installed outside of program files, in a directory within the users home directory, then it should be able to save data. However, now we are facing windows Data Execution Prevention stopping the plugin from running because we now have something being executed in a location that windows considers is only for data. I know, 'you can get the user to disable DEP' I hear you say, but again, that's not something that we should be expecting people to do. Also, I can only seem to find options to disable DEP for .exe's, and not for .dll's.
The last option is to install to the root c: drive, but on many systems windows will make the resulting directory read only, so again we are unable to save anything. Also, that practice has been discouraged for the last decade, so we don't really want to go there.
If anyone has successfully overcome these problems, could you give me some idea of how you did it? Any help would be met with grovelling appreciation and maybe even manly hugs.
We have a game designed to be played in a browser, with the web page that it's contained in providing extra community functions and advertising. Naturally, we're using the web plugin.
When the web plugin is installed to the default directory of c:\program files on a users machine, the game is unable to save any data due to UAC. This includes compiled shaders, prefs and (importantly for us) streamed updates.
Normally, programs such as T3D which use the legacy method of writing files into a subdirectory of their installation directory have that data redirected by vista or win7 to their 'virtualStore' which is located in AppData under their user directory. This doesn't happen with the web plugin. This also doesn't happen with the default project settings for the .exe, although changing the manifest for the .exe to disable UAC results in the .exe using the virtualStore.
However, changing the manifest settings for the web plugins does not help.
As our intended customers are casual gamers, we cannot be expecting people to disable UAC just to play the game.
In a perfect world, windows would like programs to be installed in program files, but for their data to be stored in userdir\AppData. However, this is not possible with T3D as it restricts the saving of files to within the same directory tree that the executable is in.
If the web plugin is installed outside of program files, in a directory within the users home directory, then it should be able to save data. However, now we are facing windows Data Execution Prevention stopping the plugin from running because we now have something being executed in a location that windows considers is only for data. I know, 'you can get the user to disable DEP' I hear you say, but again, that's not something that we should be expecting people to do. Also, I can only seem to find options to disable DEP for .exe's, and not for .dll's.
The last option is to install to the root c: drive, but on many systems windows will make the resulting directory read only, so again we are unable to save anything. Also, that practice has been discouraged for the last decade, so we don't really want to go there.
If anyone has successfully overcome these problems, could you give me some idea of how you did it? Any help would be met with grovelling appreciation and maybe even manly hugs.
About the author
Recent Threads
#2
01/20/2011 (10:46 am)
I did manage to change the manifest so that it worked with the .exe, but made no difference to the web plugin.
#3
First, make your installer run as user. In the NSIS script, add:
Now, if you try to run the installer, it will fail miserably because it can no longer write to Program Files, nor to the HKLM registry area. The next step is to fix that.
Change the install dir in the NSIS script to install your game in $LOCALAPPDATA:
Now replace all instances of "HKLM" to "HKCU" in the code that writes/erases to/from the registry NSIS script. You can also remove the Wow3264 references, they are not necessary. Writing to Software\\MozillaPlugins is enough to register a NPAPI plugin that works on all non-IE browsers, example:
There is one more thing: the IE plugin still needs admin rights to register. I looked into it and found this code change fixes the issue. In IEWebGamePlugin.cpp, find the functions DllRegisterServer() and DllUnregisterServer() and make them look like this:
With these steps you'll be able to both play *and* install your game without UAC elevation.
01/20/2011 (11:32 am)
I have dealt with that recently. We ditched the Toolbox installer creator and wrote our own NSIS script instead (using the Toolbox NSIS script as a template). I cannot post the script here as is, but here are some relevant info:First, make your installer run as user. In the NSIS script, add:
RequestExecutionLevel user
Now, if you try to run the installer, it will fail miserably because it can no longer write to Program Files, nor to the HKLM registry area. The next step is to fix that.
Change the install dir in the NSIS script to install your game in $LOCALAPPDATA:
InstallDir "$LOCALAPPDATA\YourCompany\YourProduct"This will allow your game to have full write access to its install location, without UAC elevation. So you can download files and stuff there if you want. The downside is that the game will installed for the current user only, but both Chrome and Unity install like this, so it isn't much of a problem unless your game is huge.
Now replace all instances of "HKLM" to "HKCU" in the code that writes/erases to/from the registry NSIS script. You can also remove the Wow3264 references, they are not necessary. Writing to Software\\MozillaPlugins is enough to register a NPAPI plugin that works on all non-IE browsers, example:
WriteRegStr HKCU "SOFTWARE\MozillaPlugins@MyCompany/MyPlugin" "Path" "$INSTDIR\NP myGame plugin.dll"
There is one more thing: the IE plugin still needs admin rights to register. I looked into it and found this code change fixes the issue. In IEWebGamePlugin.cpp, find the functions DllRegisterServer() and DllUnregisterServer() and make them look like this:
// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer(void)
{
// registers object, typelib and all interfaces in typelib
AtlSetPerUserRegistration(true);
HRESULT hr = _AtlModule.DllRegisterServer();
return hr;
}
// DllUnregisterServer - Removes entries from the system registry
STDAPI DllUnregisterServer(void)
{
AtlSetPerUserRegistration(true);
HRESULT hr = _AtlModule.DllUnregisterServer();
return hr;
}With these steps you'll be able to both play *and* install your game without UAC elevation.
#4
01/20/2011 (11:56 am)
Ah, I haven't faced DEP yet. If you have problems using $LOCALAPPDATA, try installing to $APPDATA\LocalLow instead. Chrome, Unity and a few others actually install there, so I assume it's DEP-safe. You should also buy code signing certificates and sign your installer, EXE and both the game and plugin DLLs. This is required in order for the IE plugin to run without so many warnings.
#5
There's some really usefull information there. It looks like you've also dealt with most of the issues we're facing.
We've found that the DEP can be circumvented by getting the user to add our domain to their trusted sites, but I'd prefer it if they didn't have to do that, so will try your suggestion of putting things in LocalLow.
01/20/2011 (1:23 pm)
Ah, Manoel, thanks.There's some really usefull information there. It looks like you've also dealt with most of the issues we're facing.
We've found that the DEP can be circumvented by getting the user to add our domain to their trusted sites, but I'd prefer it if they didn't have to do that, so will try your suggestion of putting things in LocalLow.
#6
01/20/2011 (2:06 pm)
Check if you can install Unity 3D in the same machine. If it install and works, you should be able to do the same somehow. I believe DEP should allow your binaries to run if they are digitally signed. In more strict setups, you won't even be able to run the setup if it isn't signed.
#7
I got around that by creating a small C++ application which uses ShellExecuteEx() to launch the DirectX setup instead (since ShellExecuteEx() will prompt for elevation if necessary) and have my NSIS setup execute it if getDXVersion fails.
01/20/2011 (2:10 pm)
Ah, I almost forgot: you won't be able to run the DirectX web updater from a user-level NSIS setup (it won't request UAC elevation and will fail). I got around that by creating a small C++ application which uses ShellExecuteEx() to launch the DirectX setup instead (since ShellExecuteEx() will prompt for elevation if necessary) and have my NSIS setup execute it if getDXVersion fails.
#8
EDIT: Found this link also http://nsis.sourceforge.net/CreateIn...o_%26_function
01/20/2011 (8:37 pm)
How would you go about getting a custom desktop icon to appear rather than the browser looking icon?EDIT: Found this link also http://nsis.sourceforge.net/CreateIn...o_%26_function
#9
nsis.sourceforge.net/Docs/Chapter4.html#4.9.3.4
01/21/2011 (6:41 am)
@Scot: NSIS CreateShortcut command allows you to specify custom icons for shortcuts:nsis.sourceforge.net/Docs/Chapter4.html#4.9.3.4
#10
01/21/2011 (10:27 am)
Thanks Manoel, I tried out your suggestions today and so far things seem to be working well.
#11
Also, you said: "I got around that by creating a small C++ application which uses ShellExecuteEx() to launch the DirectX setup instead (since ShellExecuteEx() will prompt for elevation if necessary) and have my NSIS setup execute it if getDXVersion fails. "
The C++ app starts getD3DXver? Or starts DXwebsetup?
Thanks!
01/21/2011 (5:59 pm)
@Manoel, when I use this $APPDATALocalLow it actually puts it in AppData/Roaming/LocalLow for some reason. Does it matter? What's the Roaming folder for?Also, you said: "I got around that by creating a small C++ application which uses ShellExecuteEx() to launch the DirectX setup instead (since ShellExecuteEx() will prompt for elevation if necessary) and have my NSIS setup execute it if getDXVersion fails. "
The C++ app starts getD3DXver? Or starts DXwebsetup?
Thanks!
#12
01/22/2011 (7:18 am)
@Scot: my bad, $APPDATA returns "AppData/Roaming". The correct way to reach LocalLow should be $PROFILE\\AppData\\LocalLow. However, I don't know how it will behave in XP.Quote:Also, you said: "I got around that by creating a small C++ application which uses ShellExecuteEx() to launch the DirectX setup instead (since ShellExecuteEx() will prompt for elevation if necessary) and have my NSIS setup execute it if getDXVersion fails. "NSIS calls getD3DXver. If it fails, I call my C++ app that calls DXwebsetup. Both getD3DXver and my app are run at user-level.
The C++ app starts getD3DXver? Or starts DXwebsetup?
#13
seems to work fine!
EDIT: whoops, it won't uninstall from LocalLow, says it can't find a temp directory...going back to roaming\localLow
01/23/2011 (3:56 pm)
Thanks Manoel, in XP that setting installs to C:\Documents and Settings\UserName\appdata\locaLow just fyi...seems to work fine!
EDIT: whoops, it won't uninstall from LocalLow, says it can't find a temp directory...going back to roaming\localLow
#14
Same problems here, made the changes as Manoel posted and they work great.
IE won't run the plugin from the users directory if internet protection mode = ON. We get the generic
"Could not load game library: Please make sure you have the latest DirectX installed"
which is triggered as LoadLibrary won't load the DLL and the code assumes any failure is down to directX when its not
Now if we sign the dll's they load but we then get a series of error dialogs in the browser
Failed to load main.cs
Failed to initalize game, shutting down
The plugin could not be initalized (internal intialization error)
It appears signing loads the DLL's but then when you need to load the scripts/assets you hit a block
Thoughts?
06/27/2011 (3:43 am)
Sorry to reopen an oldish threadSame problems here, made the changes as Manoel posted and they work great.
IE won't run the plugin from the users directory if internet protection mode = ON. We get the generic
"Could not load game library: Please make sure you have the latest DirectX installed"
which is triggered as LoadLibrary won't load the DLL and the code assumes any failure is down to directX when its not
Now if we sign the dll's they load but we then get a series of error dialogs in the browser
Failed to load main.cs
Failed to initalize game, shutting down
The plugin could not be initalized (internal intialization error)
It appears signing loads the DLL's but then when you need to load the scripts/assets you hit a block
Thoughts?
#15
In protected mode, IE runs in "low integrity" mode. That's one level lower than user-mode and is far more restricted. The main restriction is that it cannot write to anywhere outside $PROFILE/AppData/LocalLow. This means your game must be installed in a folder in there, otherwise all write-based operations will fail.
07/01/2011 (11:53 am)
Ah, I had completely forgot the IE problems.In protected mode, IE runs in "low integrity" mode. That's one level lower than user-mode and is far more restricted. The main restriction is that it cannot write to anywhere outside $PROFILE/AppData/LocalLow. This means your game must be installed in a folder in there, otherwise all write-based operations will fail.
Associate Steve Acaster
[YorkshireRifles.com]