VirtualStore in Win Vista/7/8
Those who have used Windows Vista/7/8 may have had this experience: after modifying a file on the C drive with a 32-bit program (such as cygwin), when you look at it from the Windows Explorer, it’s still the version before the modification! Does the file system have different views for different programs? You’re right, since Vista introduced UAC and VirtualStore, don’t trust the changes made by 32-bit programs in the C drive.
After Windows Vista introduced stronger security mechanisms, some important system directories are not modifiable by everyone. These directories include the C drive root directory, Program Files, Program Files (x86), Windows, and the registry’s HKEY_LOCAL_MACHINE, etc. But some old applications still assume these directories are writable, and if the system API simply returns access denied, these programs can’t run.
Therefore, Vista provides VirtualStore. For 32-bit programs running without administrator privileges, as long as there are write operations to these directories, the modified or added files will be copied to this user’s VirtualStore. The file at this path seen by the 32-bit program running under this user’s identity is the corresponding file in VirtualStore, and it knows nothing about any modifications to the file at the original path.
I wrote this blog because a classmate encountered a problem editing the OpenVPN configuration file in cygwin, so let’s use this as an example.
- Edit C:\Program Files\OpenVPN\config\boj.ovpn in 32-bit cygwin (if it prompts read-only, you can force save in vim with :w!)
- Go to Windows Explorer and find that the above file has not changed (just look at the last modified time)
- In Windows Explorer or cygwin, you can find the modified virtual file at C:\Users\boj\AppData\Local\VirtualStore\Program Files\OpenVPN\config\boj.ovpn
- Modify C:\Program Files\OpenVPN\config\boj.ovpn in Windows Explorer, and you can’t see this modification in cygwin, indicating that the two “branches” of the file system have formed.
- Delete C:\Users\boj\AppData\Local\VirtualStore\Program Files\OpenVPN\config\boj.ovpn in Windows Explorer or cygwin, and the file seen in cygwin becomes the version modified in step 4.
If I am a 32-bit application (for example, a program compiled in cygwin) and want to know whether the modification to a file has taken effect, I can judge whether %localappdata%\VirtualStore<path-to-file> exists. (It is recommended to use environment variables like %localappdata% instead of absolute paths to improve compatibility)
Similarly, modifications to the registry key HKEY_LOCAL_MACHINE\Software\Example will be redirected to HKEY_CURRENT_USER\Software\Classes\VirtualStore\MACHINE\Software\Example.
However, it is best for newly written applications not to hard-code paths to system directories. It is recommended to follow the API specifications and call SHGetKnownFolderPath with the following parameters to get the path to store application data.
- FOLDERID_ProgramData – Shared by all users on the local computer;
- FOLDERID_LocalAppData – Current user, and only on the local computer (such as browser cache);
- FOLDERID_RoamingAppData – Current user, and migrates with the user (such as preference settings), for example, if the user logs in with a domain, these data are stored on the Active Directory server.
I hope this article can solve the confusion of cygwin users about ineffective file modifications.