50

As pointed out in Writing config file in C:\Program Files (x86)\MyApp\myapp.cfg, vs. Administrator privilege, it is not a good idea to write a config file in C:\Program Files (x86)\MyApp\myapp.cfg.

Instead of this, my software now saves its data in a subdir of %ALLUSERSPROFILE% (ex : C:\ProgramData\MyApp\myapp.cfg on Win7)

[I use myfile = open(filename, 'a') in Python to do this.]

I now encounter an issue about this file :

  • I installed the software with User A, and ran it, then the file C:\ProgramData\MyApp\myapp.cfg was written.
  • Then, I changed user to User B, and ran my software again : now an error is displayed : User 2 has no right to write in C:\ProgramData\MyApp\myapp.cfg (Permission denied).

Why? Isn't %ALLUSERSPROFILE% a place that can be written by all users? How to solve this problem ?

Community
  • 1
  • 1
Basj
  • 41,386
  • 99
  • 383
  • 673
  • 4
    To reiterate one of David's points which may have gotten lost in the following discussion, make sure that this is what you really should be doing before doing it. It's pretty rare for it to make sense for an application to share configuration data between users. Usually each user should have their own distinct configuration file. (What if Fred and George share a computer, and Fred wants your app to have a blue background but George wants it to have a red one?) – Harry Johnston Mar 01 '14 at 11:05

2 Answers2

53

No, C:\ProgramData, aka FOLDERID_ProgramData, has restricted security settings. Standard users can create files there. But these files are, by default, secured so that only the user that created the file can subsequently modify the file.

The recommended solution is for your installer to create a sub directory of C:\ProgramData for your shared storage. And that sub directory must be given a permissive ACL by the installation program. That is what grants the desired access to all standard users.

I do wonder whether you really need shared writeable data. Normally I'd expect to see shared configuration be something that is specified at install time and modified infrequently by administrators. Most configuration data tends to be per user.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Thank you. I will ask the `InnoSetup installer` to create a `C:\ProgramData\MySoftware` directory that has **shared access by all users** with read/write permission (do you know how to do this? I'll search anyway). – Basj Feb 28 '14 at 23:49
  • 2
    More generally, is there a way for creating a file (when I do `f = open(filename, 'a')` in Python) that will have full read/write access by **all other users** ? – Basj Feb 28 '14 at 23:50
  • I know nothing of Inno. I use WiX and msi. When you create a file it inherits the security settings of its container. Get the directory secured right, and everything flows. If you don't secure the container permissively, then you need admin rights to create the file. – David Heffernan Feb 28 '14 at 23:50
  • Oh thanks. About adding **full privilege** to a file (read/write access by all users) when `User A` creates it (with `f = open(...)`) , is there a way to do this, in your opinion @DavidHeffernan ? – Basj Feb 28 '14 at 23:52
  • I answered that in my previous comments. You need admin rights in order to create a file in the scenario you describe. To avoid that, make a sub directory with permissive rights. If you could skip this step, then the security would be pointless. – David Heffernan Mar 01 '14 at 00:00
  • @Basj: there is no way to tell `open()` in Python to grant access to other users. The user that creates the file owns the file. I don't whether Python has any functionality at all to grant access to other users. But in Win32 API terms, you can grant access rights with [`CreateFile()`](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx), [`SetFileSecurity()`](http://msdn.microsoft.com/en-us/library/windows/desktop/aa379577.aspx), or [`SetNamedSecurityInfo()`](http://msdn.microsoft.com/en-us/library/windows/desktop/aa379579.aspx). – Remy Lebeau Mar 01 '14 at 01:34
  • @Basj: You would typically specify user access rights to `CreateFile()` at the time the file is created. – Remy Lebeau Mar 01 '14 at 01:36
  • @Basj - IS have a few built-in grant types like 'full' 'modify', search for '[DIRS] section'. – Sertac Akyuz Mar 01 '14 at 03:08
  • 1
    @Remy That would fail though because you'd need admin rights. Which is why you need the installer to do the work. – David Heffernan Mar 01 '14 at 08:54
  • @DavidHeffernan: I think you misunderstand what I said. When an app creates a file, the file is owned by the user that is running the app. If the app has rights to create the file, it certainly has rights to specify security for the file, like who else can access the file. You do not need admin rights to do that. `CreateFile()` can set a security descriptor at the time a file is created. `SetFileSecurity()` and `SetNamedSecurityInfo()` can set a security descriptor on an existing file, if the calling user has rights to change the file's security (such as if the user owns the file). – Remy Lebeau Mar 01 '14 at 10:01
  • @Remy But the app does not have rights to create the file in `C:\ProgramData\MyApp` unless a permissive ACL is applied to that directory. – David Heffernan Mar 01 '14 at 10:02
  • @DavidHeffernan: Whether or not the app has permission to create the file at all was addressed in your answer, and Basj acknowledged that before starting this whole comment chain. I'm addressing Basj's subsequent question about granting access to other users when creating a file, assuming the folder allows the file to be created. Please keep up. – Remy Lebeau Mar 01 '14 at 10:08
  • 1
    @RemyLebeau Am I not keeping up? If the permissive ACL has been applied, then that's enough. At that point files can be created in the directory. Why do you think that they cannot? I routinely create files without specifying any security settings on the new object. Also, "Please keep up" is pretty rude. I think it would be better if you could avoid that and stick to the facts. – David Heffernan Mar 01 '14 at 10:10
  • 7
    @DavidHeffernan: actually your initial premise is wrong; on Windows 7, at least, the default permissions for `ProgramData` do allow any user to write to it; specifically, to create new files and folders. However, only the user who creates any given file has permission by default to write to it. – Harry Johnston Mar 01 '14 at 10:59
  • 3
    To be more precise, by "any user" I mean members of the built-in Users group. Permissions on `ProgramData` are `c:\ProgramData NT AUTHORITY\SYSTEM:(OI)(CI)(F) BUILTIN\Administrators:(OI)(CI)(F) CREATOR OWNER:(OI)(CI)(IO)(F) BUILTIN\Users:(OI)(CI)(RX) BUILTIN\Users:(CI)(WD,AD,WEA,WA)` – Harry Johnston Mar 01 '14 at 11:02
  • 1
    @Harry Thanks. I've obviously not fully grasped the permissions on this folder. I'll correct the answer. – David Heffernan Mar 01 '14 at 11:11
  • 1
    Is this "recommended solution" of changing permissions on a ProgramData subfolder documented anywhere? Also, is this still considered a best practice in 2022, with things like Controlled Folder Access in Microsoft Defender locking folders down? – Dan Korn Jul 14 '22 at 20:12
8

I'd like to add onto this as I was having issues writing to C:\ProgramData as well. My issue ended up being that my directory/files within C:\ProgramData were written by an administrator. When my app ran under a normal user it was unable to write there so Windows automatically used C:\Users\fooface\AppData\Local\VirtualStore\ProgramData instead. I found the path it was writing to by using process monitor on my application. After seeing this I deleted the files out of C:\ProgramData and ran my app again and it wrote there as expected.

Hope this helps someone.

Wolf
  • 9,679
  • 7
  • 62
  • 108
Daniel Caban
  • 111
  • 1
  • 3
  • Isn't there a need to remove as well the files created under `C:\Users\fooface\AppData\Local\VirtualStore\ProgramData` to return to normal function? – Wolf Mar 12 '21 at 10:12
  • ...the question [*How to prevent file redirection to VirtualStore for read/write files?*](https://stackoverflow.com/q/18059015/2932052) suggests that the virtual-store files are transparently used also at reading access... – Wolf Mar 12 '21 at 10:23