-
Notifications
You must be signed in to change notification settings - Fork 3
Fixup: FileRedirectionFixup
The FileRedirectionFixup (FRF for short) is a workhorse fixup library that intercepts a wide variety of Windows API calls that involve the Windows file system and may need help under MSIX.
The general causes of issues resulting in needing the FRF include:
- Files that are part of the package under either the 'VFS\AppData' or 'VFS\LocalAppData' folders are not seen by the application. On Windows 10 versions prior to 2004 (20H1) this would also happen to package files under 'VFS\AppDataCommon'. This issue usually occurs when the application attempts to use the normal path that the application would use when natively installed. Unlike other VFS folders in the package, these folders are not correctly layered and the application will not see the files in the package without FRF assistance.
- Files in other VFS folders of the package that the application needs to open for modify. The FRF can assist with this.
- Files in non VFS folders of the package that the application needs to open for modify. In addition to solving this issue by using the FRF, Microsoft introduced a new AppXManifest option to solve this also.
- Accesses that may work improperly due to other redirection. The FRF will apply Reverse VFS and Reverse Redirection logic when necessary.
When the FRF is used, as files are accessed by the application, an evaluation will be made as to if there is a source for the file inside the package and cause a Copy-on-Access to be made into the MsixWritablePackageRoot folder of the user's LocalAppData folder for this package (if there isn't one already present). It will then complete the call by using redirection to this copy instead.
The FRF intercepts calls to Open and Find folders and files, however, it does not need to intercept the read/write/close associated with that file access and the intercepted call returns a handle to the application which is then used for those operations, ensuring that the activity will also affect the redirected file without additional interceptions.
The FRF currently targets the following Windows API Calls:
API | API | API | API | API |
---|---|---|---|---|
CopyFile | CopyFileEx | CopyFile2 | CreateDirectory | CreateDirectoryEx |
CreateFile | CreateFile2 | CreateHardLink | CreateSymbolicLink | DeleteFile |
GetFileAttributes | GetFileAttributesEx | FindNextFile | FindFirstFileEx | FindNextFile |
FindClose | GetPrivateProfileInt | GetPrivateProfileSection | GetPrivateProfileSectionNames | GetPrivateProfileString |
GetPrivateProfileStruct | MoveFile | MoveFileEx | ReadDirectoryChangesW | RemoveDirectory |
ReplaceFile | SearchPath | SetFileAttributes | GetCurrentDirectory | SetCurrentDirectory |
WritePrivateProfileString | WritePrivateProfileStruct |
Note 1: ReadDirectoryChangesW is an intercept that logs only at this time. Applications call this function with a handle to a directory to monitor changes made under that directory. In most cases, the app would have received a handle to the redirected directory, which is the folder where any changes would be made. There is concern that it is possible for the app to receive a handle from the package, so this logging, which occurs in a minimal form in the release build, will alert you that this function is being used. Testing using the debug build will display the file path associated with this handle. If a handle to a wrong path is discovered, additional work to the fixup may be warranted (Please log an issue to this GitHub repository if you find one).
Note 2: Applications may use posix interfaces to the file system. Each of the functions we have analyzed so far seem to call APIs supported by the FRF. Thus at this time these functions are not being intercepted, If you find an app needing additional support due to posix interfaces, please add an issue to this GitHub repository. The Posix functions under consideration are in ucrtbase.dll, with interfaces such as OpenFile.
When Microsoft originally wrote the FRF, they assumed that an application might have just a single file or two that needs the fixup. Therefore, they created an overly complicated configuration that allows you to target just that one or two things. Our experience with running older applications in MSIX is that they tend to have a lot of different file issues and attempting to identify and target precision configurations is overly tedious as it is a serial process to find each and every process.
So in most cases we instead just configure the FRF to cover all of the general cases that we tend to run into without trying to identify them all individually. Such a blanket remediation technique has a historical precedent in Microsoft App-V where it worked well. While this blanket general configuration will look complicated in the following example, it is fortunately boilerplate text that may be used in just about any application that uses the FRF.
"processes": [
{
"executable": "^PsfLauncher.*",
"fixups": []
},
{
"executable": ".*",
"fixups": [
{
"dll": "VFS\\ProgramFilesX64\\FileZilla FTP Client\\FileRedirectionFixup.dll",
"config": {
"redirectedPaths": {
"packageRelative": [
{
"base": "",
"patterns": [
".*\\.[eE][xX][eE]$",
".*\\.[dD][lL][lL]$",
".*\\.[tT][lL][bB]$",
".*\\.[oO][cC][xX]$",
".*\\.[cC][oO][mM]$",
".*\\.[fF][oO][nN]$",
".*\\.[tT][tT][cC]$",
".*\\.[tT][tT][fF]$",
".*\\.[zZ][iI][pP].*"
],
"isExclusion": true
},
{
"base": "",
"patterns": [
".*"
]
}
],
"packageDriveRelative": [],
"knownFolders": [
{
"id": "LocalAppData",
"relativePaths": [
{
"base": "",
"patterns": [
".*"
]
}
]
},
{
"id": "RoamingAppData",
"relativePaths": [
{
"base": "",
"patterns": [
".*"
]
}
]
},
{
"id": "ProgramFilesX86",
"relativePaths": [
{
"base": "",
"patterns": [
".*"
]
}
]
},
{
"id": "ProgramFilesCommonX86",
"relativePaths": [
{
"base": "",
"patterns": [
".*"
]
}
]
},
{
"id": "ProgramFilesX64",
"relativePaths": [
{
"base": "",
"patterns": [
".*"
]
}
]
},
{
"id": "ProgramFilesCommonX64",
"relativePaths": [
{
"base": "",
"patterns": [
".*"
]
}
]
},
{
"id": "SystemX86",
"relativePaths": [
{
"base": "",
"patterns": [
".*"
]
}
]
},
{
"id": "System",
"relativePaths": [
{
"base": "",
"patterns": [
".*"
]
}
]
},
{
"id": "Windows",
"relativePaths": [
{
"base": "",
"patterns": [
".*"
]
}
]
},
{
"id": "ProgramData",
"relativePaths": [
{
"base": "",
"patterns": [
".*"
]
}
]
}
]
}
}
}
]
}
]
A summary of the processes section of the above example is:
- A process entry for any PsfLauncher process such that it effectly exempts those processes for fixup dlls.
- A process entry for any other process running in the container that has the FRF configured for injection.
- The FRF confiration has a field called
redirectedPaths
that has three sub-fields that contain arrays of specific configuration. These subfields take effect in calls depending on how the application specified a requested file path: > *packageRelative
is for calls using relative pathing from the package root folder or a working directory folder. > *packageDriveRelative
is for calls using non-package paths from the drive letter (C:) that the package volume is on. This type is rarely used and is currently covered as an unrequested default case afterknownFolders
matching has been exhausted. > *knownFolders
is for calls made using paths of known locations (often documented in developer docs as KnownFolderIDs). These known folders are identified often with the names used in VFS folders, however additional GUIDs are also referenced instead of by name.- The
packageRelative
entry includes an exclusion entry for typical file types that we want to exempt from copy-on-access. These are generally binary components that should not be modified ever.- The
knownFolders
entry includes exclusion entries for folder locations we typically do not want to redirect, such as the Desktop folder.
The MSIX, and/or the FRF use the following known list of VFS Path Names and KnownFolderIDs:
Known VFS names in MSIX | FolderId\extra | Typical path on x64 System |
---|---|---|
AppVSystem32Catroot2 | FOLDERID_System\catroot2 | C:\Windows\System32\catroot2 |
AppVSystem32Catroot | FOLDERID_System\catroot | C:\Windows\SysWOW64\catroot |
AppVSystem32DriversEtc | FOLDERID_System\drivers\etc | C:\Windows\System32\Drivers\etc |
AppVSystemreDriverstore | FOLDERID_System\driverstore | C:\Windows\System32\DriverStore |
AppVSystem32Logfiles | FOLDERID_System\logfiles | C:\Windows\System32\LogFiles |
AppVSystem32Spool | FOLDERID_System\spool | C:\Windows\System32\Spool |
SystemX86 | FOLDERID_SystemX86 | C:\Windows\SysWOW64 |
ProgramFilesCommonX86 | FOLDERID_ProgramFilesCommonX86 | C:\Program Files (x86)\Common Files |
ProgramFilesX86 | FOLDERID_ProgramFilesX86 | C:\Program Files (x86) |
SystemX64 | FOLDERID_System | C:\Windows\System32 |
ProgramFilesCommonX64 | FOLDERID_ProgramFilesX64 | C:\Program Files\Common Files |
System | FOLDERID_System | C:\Windows\System32 |
Fonts | FOLDERID_Fonts | C:\Windows\Fonts |
Windows | FOLDERID_Windows | C:\Windows |
Common AppData | FOLDERID_ProgramData | C:\ProgramData |
Local AppData | FOLDERID_LocalAppData | C:\Users\UserName\AppData\Local |
AppData | FOLDERID_RoamingAppData | C:\Users\UserName\AppData\Roaming |
Common Desktop | FOLDERID_PublicDesktop | C:\ProgramData\Desktop |
Common Programs | FOLDERID_CommonPrograms | C:\ProgramData\Microsoft\Windows\Start Menu\Programs |
LOCALAPPDATALOW | FOLDERID_LocalAppDataLow | C:\Users\UserName\AppData\LocalLow |
B4BFCC3A-DB2C-424C-B029-7FE99A87C641 | C:\Users\UserName\Desktop | |
FDD39AD0-238F-46AF-ADB4-6C85480369C7 | C:\Users\UserName\Documents | |
56784854-C6CB-462B-8169-88E350ACB882 | C:\Users\UserName\Contacts | |
374DE290-123F-4565-9164-39C4925E467B | C:\Users\UserName\Downloads | |
1777F761-68AD-4D8A-87BD-30B759FA33DD | C:\Users\UserName\Favorites | |
4BD8D571-6D19-48D3-BE97-422220080E43 | C:\Users\UserName\Music | |
31C0DD25-9439-4F12-BF41-7FF4EDA38722 | C:\Users\UserName\3D Objects | |
2C36C0AA-5812-4B87-BFD0-4CD0DFB19B39 | ?? "OriginalImages" | |
69D2CF90-FC33-4FB7-9A0C-EBB0F0FCB43C | ?? "PhotoAlumns" | |
33E28130-4E1E-4676-835A-98395C3BC3BB | C:\Users\UserName\Pictures | |
DE92C1C7-837F-4F69-A3BB-86E631204A23 | C:\Users\UserName\PlayLists | |
AE50C081-EBD2-438A-8655-8A092E34987A | C:\Users\UserName\Recent | |
BD85E001-112E-431E-983B-7B15AC09FFF1 | C:\Users\UserName\RecordedTV | |
A63293E8-664E-48DB-A079-DF759E0509F7 | C:\Users\UserName\Templates | |
18989B1D-99B5-455B-841C-AB7C74E4DDFC | C:\Users\UserName\Videos | |
Other GUIDs | Other... | |
AppVPackageDrive | C:\ |
More information on the FileRedirectionFixup may be found in the FileRedirectionFixup Developer Documentation page.