Starting from an unknown version of Windows 10, programs can no longer access dehydrated (online-only, placeholder) files with CreateFile(Ex)
normally.
Consider the following excerpt:
// By default (if the program does not have a manifest, so it runs in Windows Vista mode),
// RtlQueryProcessPlaceholderCompatibilityMode returns PHCM_DISGUISE_PLACEHOLDER, and
// RtlQueryThreadPlaceholderCompatibilityMode returns PHCM_APPLICATION_DEFAULT.
FILE *fp = fopen("C:\\Users\\testuser\\OneDrive\\test.txt", "rb");
if (!fp)
{
fputs("fopen failed.\n", stderr);
}
else
{
if (fgetc(fp) == -1)
{
fputs("fgetc failed.\n", stderr);
}
else
{
fputs("Succeeded.\n", stderr);
}
fclose(fp);
}
And the following excerpt:
Get-Content -LiteralPath 'C:\Users\testuser\OneDrive\test.txt'
- Windows 10 build 18363.1500, 64-bit, Education.
- OneDrive version 2021 build 21.062.0328.0001 (32 bit).
- We are connected to the Internet.
- The user syncs personal OneDrive at
C:\Users\testuser\OneDrive
, and has a filetest.txt
available at this root. This file is dehydrated (online-only, placeholder) before each case is tested.
If the code excerpts are running as a non-administrator (including an administrator in admin-approval mode of UAC; unelevated):
- The C program fails with
fgetc failed
. - The PowerShell script fails with permission denied.
If the code excerpts are running as an administrator (elevated):
- The C program succeeds.
- The PowerShell script succeeds. (IMPORTANT: after running the C program, the file should be dehydrated before the PowerShell script is run; otherwise, the case for PowerShell will be in the wrong configuration that the file is already hydrated.)
Both programs will just do fine. This held in some early version of Windows 10 (say version 1709).
This makes a lot of applications fail to run when it tries to programmatically access files stored on OneDrive. Some typical scenarios:
- The user saves a document to OneDrive, and the application provides a list of recently opened documents, which when clicked causes the application to programmatically open the file. Most applications are not aware of placeholders and expect the files to be automatically hydrated whenever needed. If the user has dehydrated a file and tries to open it from the list of recently opened documents in the application, then the application will fail.
- The application asks the user to choose a folder, after which it processes files inside the folder. The access to files inside the picked folder is programmatic. If the folder resides in OneDrive and some of the files are dehydrated, the application will fail.
- Continuing the above example, the application operates a sparse subset of files inside the chosen folder (depending on the file name). When used on a OneDrive folder, it is expected that only the touched files are hydrated as necessary. This bug makes such operation impossible.
It seems that the shell handles this OK, so if the application asks the user to choose a file (not a folder) using common file dialog, it will run fine, as the common file dialog (shell) will hydrate the file upon selection.
- Cloud Filter API
- Compatibility with applications that use reparse points
- Evidence that
CreateFile(Ex)
worked in earlier versions of Windows 10:
@GeeLaw - Thanks a lot for bringing the issue to our attention.
I tried to reproduce the issue but couldn't succeed. Hence I have not been able to debug it so far. If you have one of these machines where you saw the issue, could you please confirm the following: