Recommended installation folders

Many applications that used to write into their own installation folder under C:\Program Files have run into problems when Windows Vista came out. Under Windows Vista and later, it appears that C:\Program Files and its subfolders are read-only, whereas they used to be writable.

Here is the news: This isn't Windows Vista or Windows 7; it has been this way in all Windows NT versions since NT 3.1 back in 1993, and including NT4, 2000, and XP. The only reason most people (and developers) didn't notice this, is that the default login account had Administrator privileges and could therefore write under Program Files.

What changed in Vista is that Microsoft introduced "split" access tokens for Administrators. From Vista onwards, Administrator-level accounts run with a double access token: the usual Admin token with many privileges, but also a normal, much more restricted access token. When an Administrator account logs in under Vista or later, the effective token is the restricted one; only after the UAC prompt for elevated privileges is the full Admin token used, and then only for the current process (and its descendants). The result is that the effective rights of Administrator users are now the same as those of restricted users, which also implies read-only access under Program Files.

Bearing that in mind, the recommended installation locations for application files have always been as follows.

Program files and read-only data files for 32-bit applications

In subfolders of the 32-bit version of C:\Program Files:

InstallMate folder Target System\Program Files (32-bit)\...etc...
XP path (32-bit system) C:\Program Files\...etc...
XP path (64-bit system) C:\Program Files (x86)\...etc...
Vista/7 path (32-bit system) C:\Program Files\...etc...
Vista/7 path (64-bit system) C:\Program Files (x86)\...etc...
Symbolic path <ProgramFilesFolder>\...etc...
In your 32-bit code SHGetFolderPath(CSIDL_PROGRAM_FILES)\...etc...
In your 64-bit code SHGetFolderPath(CSIDL_PROGRAM_FILESX86)\...etc...

Program files and read-only data files for 64-bit applications

In subfolders of the 64-bit version of C:\Program Files:

InstallMate folder Target System\Program Files (64-bit)\...etc...
XP path (32-bit system) n/a
XP path (64-bit system) C:\Program Files\...etc...
Vista/7 path (32-bit system) n/a
Vista/7 path (64-bit system) C:\Program Files\...etc...
Symbolic path <ProgramFiles64Folder>\...etc...
In your 32-bit code n/a
In your 64-bit code SHGetFolderPath(CSIDL_PROGRAM_FILES)\...etc...

Program files and read-only data files for native applications

In subfolders of the native version of C:\Program Files:

InstallMate folder Target System\Program Files (native)\...etc...
XP path (32-bit system) C:\Program Files\...etc...
XP path (64-bit system) C:\Program Files\...etc...
Vista/7 path (32-bit system) C:\Program Files\...etc...
Vista/7 path (64-bit system) C:\Program Files\...etc...
Symbolic path <ProgramFilesXFolder>\...etc...
In your code SHGetFolderPath(CSIDL_PROGRAM_FILES)\...etc...

System-wide, user-visible read/write files

Under Users\Public\Public Documents or equivalent:

Note: All users can create and write new files and read existing files, but standard Users cannot change, rename, or delete files, unless they were created under their own account.

InstallMate folder Target System\Users\Public\Public Documents
XP path C:\Documents and Settings\All Users\Shared Documents
Vista/7 path C:\Users\Public\Public Documents
Symbolic path <CommonDocumentsFolder>
In your code SHGetFolderPath(CSIDL_COMMON_DOCUMENTS)

System-wide, user-hidden read/write files

Under ProgramData\Company\Product:

Note: All users can create and write new files and read existing files, but standard Users cannot change, rename, or delete files, unless they were created under their own account.

InstallMate folder Target System\ProgramData\<Publisher>\<ProductName>
XP path C:\Documents and Settings\All Users\Application Data\Company\Product
Vista/7 path C:\ProgramData\Company\Product
Symbolic path <CommonAppDataFolder>\<Publisher>\<ProductName> or <CommonProductAppDataFolder>
In your code SHGetFolderPath(CSIDL_COMMON_APPDATA)\Company\Product

Per-user visible read/write files

Under <UserName>\[My ]Documents (for example, Word documents, Excel spreadsheets, etc.):

InstallMate folder Target System\Users\Current User\My Documents
XP path C:\Documents and Settings\<UserName>\Documents
Vista/7 path C:\Users\<UserName>\My Documents
Symbolic path <PersonalFolder>
In your code SHGetFolderPath(CSIDL_PERSONAL)

Per-user hidden read/write files

Under <UserName>\AppData\Company\Product (for example browser caches, email storage, per-user settings):

InstallMate folder Target System\Users\Current User\AppData (Roaming)\<Publisher>\<ProductName>
XP path C:\Documents and Settings\<UserName>\Application Data\Company\Product
Vista/7 path C:\Users\<UserName>\AppData\Roaming\Company\Product
Symbolic path <AppDataFolder>\<Publisher>\<ProductName> or <ProductAppDataFolder>
In your code SHGetFolderPath(CSIDL_APPDATA)\Company\Product

Note: The <AppDataFolder> used in the table above refers to the roaming application data folder, i.e., the folder that "moves" with the user between computers if the user's account is set up for roaming. This is the folder that you should normally use if you install user-specific application data.

The non-roaming per-user equivalent is the <LocalAppDataFolder>, which does not move with the user to different computers:

InstallMate folder Target System\Users\Current User\AppData (Local)\...etc...
XP path C:\Documents and Settings\<UserName>\Application Data\Local Settings\...etc...
Vista/7 path C:\Users\<UserName>\AppData\Local\...etc...
Symbolic path <LocalAppDataFolder>\...etc...
In your code SHGetFolderPath(CSIDL_LOCAL_APPDATA)\...etc...

In general, you should use the roaming folder <AppDataFolder> for installation purposes. Only use the local version <LocalAppDataFolder> for files that are absolutely meant to be local to the computer. For example, each user's Temp folder appears under <LocalAppDataFolder>.

Physical locations

The exact folder names have changed a bit over time, but the above categories have been present in one form or another since NT 3.1 in 1993. Any naming changes are dealt with by the installer if you use the Symbolic path variables indicated above. See:

Note: Windows 95/98/Me are different and only approximate the NT model. Moreover, those Windows versions have no concept of security and allow access to all aspects of the system. That's what most users and developers grew up with.

How to apply this to your application

So, what you should do depends on your application model and you should ask yourself the following questions:

  1. If the target computer is shared by different users (i.e., different login accounts), do you need to keep the read/write files of one user separate from all other users? For example, if you were deploying Microsoft Word, then the answer would be Yes -- you don't want user A to have access to user B's private correspondence.
  2. Must the user be able to select the files in question, for example through a File > Open... or a File Save As... command, or are they more or less hidden implementation details of your application? For example, Microsoft Word document files are user-visible, but Internet Explorer's cache and cookies are not, at least not in the sense that they must be accessible through File > Open... or something like that. Most email clients also use hidden per-user files to store all the mail boxes.

You then get a matrix like this for read/write files:

 
User separation?
No
Yes
User-visible? No
CSIDL_COMMON_APPDATA <CommonAppDataFolder> *
CSIDL_APPDATA <AppDataFolder>
Yes
CSIDL_COMMON_DOCUMENTS <CommonDocumentsFolder> *
CSIDL_PERSONAL <PersonalFolder>

*All users can create and write new files, and read existing files, but standard Users cannot change, rename, or delete files, unless they were created under their own account. Writing, renaming, or deleting non-owned files requires Power User or Administrator rights on Windows XP and earlier, or elevated rights on Windows Vista and later.

As a slight variation, some applications start with read-only files that may have to be modified for each user. This may be an Access database or perhaps user preferences. In that case, the usual approach is copy-on-write: The application starts with the system-wide read-only template (for example, under C:\Program Files), but as soon as a user modifies it, the modified copy is written to the user's Application Data area.

Internally, the application then uses this kind of logic:

if (user's Application Data\Company\Product\TheFile exists)
    then use that file;
    else use the global read-only file; 

If you do this correctly, then you don't need to tweak any folder access rights and your application will also be Windows Logo compliant.

See also:

Information on the Microsoft MSDN web site: