How do I set permissions on dynamically linked files? - file-permissions

I have an InstallScript installer that utilizes dynamic file links for several components. These components contain configuration files that standard users should be able to edit. We recently discovered that when these files are installed on Windows Server 08, the permissions are set to full access for the Administrators group, but only read & execute access for the Users group. The typical install location is C:\programName.
I've tried creating new files manually as an admin (right click - new text file) in the C:\programName directory, and they are generated with identical permissions. I'm assuming that this is just the standard permission setup for new files.
Is there any way, within InstallShield, to set the permissions for dynamically linked files or the directory containing them?
I've looked for permission settings in
Organization -> Components
Application Data -> Files and Folders
but I haven't found anything. The documentation on dynamic file links makes no mention of permissions.
We are using InstallShield 2010.

Generally these permissions are a good thing; they're inherited from their parent folders. Non-administrator users (including the limited access admin before accepting a UAC prompt) should be unable to modify files under Program Files or C: so I would suggest addressing this concern in your application (for instance by using each user's Documents folder). Since you don't talk about why you need it, it's hard to say with certainty if this applies to your case.
If it turns out it does make sense to address this in the installation instead of the application, you can use the SetObjectPermissions API to set permissions programmatically.

In "Files and Folders" page right-click the file or folder, select Properties and click the Permissions button. In the "Permissions" dialog you can then right-click in the Name(s) list and use the New context menu option to add a new permission.
If the option is not available for a file, you can try setting it on the parent folder.

Related

NSIS - Restrict permissions of $PLUGINSDIR

The $PLUGINSDIR folder created by NSIS inherits the parent folder's permissions. This means (at least on my system) full control for SYSTEM, Administrators and the user. I'd like to remove the write access for the user to protect the libraries, which are copied to the folder and then loaded during installation. Is it possible to do it somehow?
$pluginsdir is restricted (only BUILTIN\Administrators can write) when the installer runs elevated. This restriction was first added in v2.51 and v3.0 in 2016.
Use the Access control plug-in if you need a custom ACL.

UAC Manifest file in VS2005 not working

I have an add-in in Excel that needs to store some data in the HKEY_LOCAL_MACHINE registry. because of the UAC control in Windows Vista and earlier versions, I added a manifest file. But it is just not working. I even added the manifests in each of the projects of my solution. I have 5 projects in my solution (3 VB projects, 1 c++ and 1 deployment).
I am using VS2005. I added the manifest file to the project (with the requestedExecutionLevel set to "requireAdministrator" and embedded the manifest using mt.exe in a post-build command.
Even with that, I am still getting an access denied to the HKEY_LOCAL_MACHINE. The only thing that is working is when I start Excel as "Run as administrator".
Any clue what the problem might be? Thanks.
Manifests in DLL do not affect the execution level of the application, in this case it's excel.exe.
Here are the options you have:
to run Excel as administrator;
to modify the add-on to write to HKCU rather than HKLM.
If you need to store data available to other users, consider using ProgramData folder (CSIDL_COMMON_APPDATA or FOLDERID_ProgramData). Then your add-on creates a subdirectory inside ProgramData and modifies its permission so that this new directory is writable by anyone (by default, only the user account that created the folder has write permissions, other users can only read).
There are some other options:
You can write a service that your add-on will communicate to write data into HKLM but it's not.
You can create an elevated COM object which will write the data into HKLM.
Although users don't expect Excel to require elevation when run, therefore consider changing your logic so that your add-on does not require elevation at all.

Accessing C:\ drive on Windows 7

I have full admin privileges on my Windows 7 machine but when I run my application which creates a file on c:\ drive I get error code 5 (Access is denied). I know windows 7 doesn't allow creating files in protected areas like c drive and program files and file explorer brings up 'administrative' message box if I copy a file there from somewhere else after which it does allows but can my application obtain write level access?
In my application, user gets to pick the folder where they want to create the file so if they choose c:\ drive s/he will obviously get this error which is not desirable.
void CTestDlg::OnBnClickedButtonCreate()
{
CFile f;
CFileException e;
TCHAR* pszFileName = _T("c:\\test.txt"); // here i am hard coding path for simplicity.
if(!f.Open(pszFileName, CFile::modeCreate | CFile::modeWrite, &e))
{
TRACE(_T("File could not be opened %d\n"), e.m_cause);
}
}
As far as I have researched it seems I can't by-pass the UAC dialog which is fine but my application don't even present it (which is understandable as well) but what are my options?
I see my only option is to detect this in my own application if this is Windows 7 OS and than check for file path before creating the file and present a more user friendly message 'windows 7 doesn't like you to create file in this folder, choose a different folder or go back to xp'. Is this scheme the way to go on Windows 7? Is there any other way?
As Kolink noted, your application needs to run with administrator privileges. In order to do that automatically, embed a manifest as explained here.
EDIT: For VS2010: Project Properties > Configuration Properties > Linker > Manifest File Change the 'UAC Execution Level' to the desired value.
Either don't try to write to protected areas, or require that your application be run with permissions (right-click => Run as Administrator).
I know I don't like random files appearing in my root - I like my files organised.
If it's the user who provides the path, then you should inform them that the file cannot be saved to this location and ask to provide another name.
Usually the shell, GetSaveFileName function, checks whether the new file can be created in the selected directory before returning, see flag OFN_NOTESTFILECREATE in description of OPENFILENAME structure.
Another option is to handle such situation and to show UAC confirmation yourself. But this solution requires much more effort than it's really worth. You can't elevate the current process, so the operation of saving the file to a protected area has to be implemented in another process. At the same time your current process has the data to be saved, so you'll have to implement the communication between the two processes. Read Designing UAC Applications for Windows Vista for more information.

Getting Application Data folder for every user

In my application, every user has its own settings, that I save to a subdirectory in that user's Application Data directory. During uninstall, I want to delete those settings for every user on the computer. How can I do that in Inno Setup?
In other words, I need to get a list that contains Application Data directory for each user (not the shared Application Data directory), so that I can delete the MyAwesomeApp directory from there. Is there some way to do that?
You can't, due to the design of Windows.
The same design stops you accessing the profile folders too.
On top of this, it's accepted best practice to leave the user's data behind in case they want to reinstall it, roaming profiles, etc.
Assuming that your uninstaller runs with administrator priviledges, you can just get the User directory and then enumerate all the user directories there.
You can run an executable from Inno Setup written in whatever language you want. In it you can first get the current user's Application Data directory, using the SHGetSpecialFolderPath function. It would look something like this for Win7:
c:\Users\MyUser\AppData\Roaming\
You can use GetUserName to get the user's name (MyUser in this case), and find the parent directory and split the string to the parent directory "C:\Users\" and "AppData\Roaming\". You can then use FindFirstFile/FindNextFile to enumerate all users directories, and just append the second part "AppData\Roaming\" to them, and check if the file exists. By splitting the directory you get from SHGetSpecialFolderPath you ensure it would work both in XP (which would return something like C:\Documents and Settings\MyUser\Application Data") and in Win7. Basically you just replace MyUser with all the users' names in the string returned by SHGetSpecialFolderPath.
I have no idea if this avoids OS security or if it works with roaming users.

Windows 7 Security Policy: How Do I Allow My .NET App to Write to Drive "C:"?

My application is not supposed to perform any administrative tasks, so I want a normal User account to be able to run it. Only thing is, my application reads from and writes to a database file; if the user running Windows 7 (Or Vista) installs my app in drive C, the drive's default permission set configuration doesn't allow my app to write data.
How can I allow my app to write to C:, without requiring full administrative privileges?
If the database file exists at install time you can just grant the user write access to the file as part of the installation process (ordinary users do not have this permission by default). If the file needs to be created by the program the user running the program will need modify permissions on the c drive, which is not something that I would recommend.
I'd suggest storing your db file in Documents and Settings / App data / your app / directory. It exists specifically for this purpose. Writing to C:/Program Files is not so good practice. If that's possible in your case, that is.
You need to open UAC (User Account Access) and set security slider to the bottom. Then you can access drive C: as you did in windows XP.
I decided to modify directory permissions in the setup process, so I created an .exe file that changes the permissions of its start-up path, and gives all users access to that path. I simply included that .exe file in my deployment project, and created a Custom Action that would run the file in the Commit phase of installation.
Because the setup asks the user for administrative rights when it is being installed, my .exe also enjoys administrative privileges and can modify the permissions of the installation directory.
In my .exe, I used a Process instance to run the ACL utility shipped with Windows (icacls.exe) as follows:
ICACLS.EXE [TargetDir] /T /C /grant Users:F
(Make sure that [TargetDir] doesn't end with a "\" or the call will fail.)
This gives all users full control access to the target directory.
I could also write .NET code and change directory permissions manually, but I'm a little lazy!
You may however want to inspect your environment conditions thoroughly so that what you do wouldn't become a security hole in your environment; but this was suitable for me.
I hope this helps others who faced the same issue.
The user by default should have write permissions to drive C:, if not, then you will need to change the directory you read from and write to, to the executing directory (C:/Program Files/Your App/) rather than the root of C:
You can get this by
String Path = Path.GetDirectoryName(Application.ExecutablePath);

Resources