microsoft / microsoft/Windows-classic-samples
Shell does not fall back to the registered per-extension IThumbnailProvider when a cloud sync provider declines
Nobody has claimed this yet.
- Dominant language
- No language data
- Stars
- 5.7k
- Forks
- 3.3k
- PR merge metrics
- No merged PRs in 30d
Description
Filed here because the CloudMirror sample in this repository is what demonstrates the correct
delegation pattern, and the sample is what we used to reproduce the problem. If this belongs
elsewhere, please point us at the right place — we will refile.
Summary
For files that are dehydrated placeholders inside a Cloud Files API sync root, the shell routes
thumbnail generation to the sync root's registered ThumbnailProvider and never falls back to the
per-extension thumbnail handler, even when the sync provider explicitly returns
WTS_E_NOSTORAGEPROVIDERTHUMBNAILHANDLER (0x8004B207).
The practical result: a third-party file format can never show a thumbnail for a cloud-only file,
regardless of how correctly its IThumbnailProvider is registered — including registration through an
MSIX manifest (com:Extension + desktop2:ThumbnailHandler).
We hit this with .mdp, the native document format of MediBang Paint and FireAlpaca
(MediBang Inc.). MediBang Paint for Desktop is published on the Microsoft Store, so the format is
affected on a product Microsoft itself distributes. Our thumbnail handler is correct and works for
ordinary local files; it is simply never invoked once a file becomes a placeholder.
This is reproducible with Microsoft's own CloudMirror sample, modified by 15 lines (patch at the
end of this issue).
Reported by
MediBang Inc. — publisher of MediBang Paint for Desktop on the Microsoft Store
(MediBangInc.MediBangPaintforDesktop). .mdp is the native format of MediBang Paint and
FireAlpaca, used by a large drawing-app user base that stores work in OneDrive by default.
Environment
| OS | Windows 11 Pro 10.0.26200, 25H2, UBR 9168 |
| OneDrive | 26.150.0804.0011 (Personal) |
| Windows SDK | 10.0.26100.0 |
| Sample | microsoft/Windows-classic-samples — Samples/CloudMirror (main) |
Reproduction
- Register a thumbnail handler for
.mdp(MediBang Paint / FireAlpaca documents) via an MSIX package
(com:Extension/windows.comServer+desktop2:ThumbnailHandler).
Verified working for ordinary local files. - Build and install the CloudMirror sample, patched so that
ThumbnailProvider::GetThumbnail()returns a chosen HRESULT (patch at the end of this issue). - Place
.mdpfiles in the "server" folder and let CloudMirror create dehydrated placeholders
(FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS, attributes0x401620) in the sync root. - Query thumbnails with
IThumbnailCache::GetThumbnail(item, 96, WTS_EXTRACT)and inspect the
returnedHBITMAP. Use a fresh file name for each run — the thumbnail cache survives
registration changes, dehydration and provider restarts, and will otherwise mask the result.
Results
| # | What ThumbnailProvider::GetThumbnail() returns |
Observed |
|---|---|---|
| 1 | Stock sample: delegates via BHID_ThumbnailHandler on the source item |
Thumbnail rendered. Confirmed in Explorer with the cloud-only badge still present |
| 2 | WTS_E_EXTRACTIONPENDING (0x8004B205) |
No thumbnail. Caller receives 0x8004B205 on every retry; it never resolves |
| 3 | WTS_E_NOSTORAGEPROVIDERTHUMBNAILHANDLER (0x8004B207) |
No thumbnail. 0x8004B207 is returned verbatim to the caller. No fallback occurs |
Case 1 proves the shell can display thumbnails for dehydrated placeholders — the limitation is not
inherent to Files On-Demand.
Case 1 — .mdp thumbnails on cloud-only placeholders in the CloudMirror sync root. Note the
cloud-only badge on each item; nothing was hydrated.
Case 3 is the issue: a constant exists that names precisely this situation
("no storage provider thumbnail handler"), yet returning it produces no fallback behaviour.
Why this matters
OneDrive behaves like case 2. For extensions its service cannot render server-side, it returns
WTS_E_EXTRACTIONPENDING rather than a terminal error, and the request never completes.
The same .mdp files under OneDrive. The MSIX-registered thumbnail handler is never invoked, so
only the static file-type icon is shown. The .psd and .png files in the same folder do get
thumbnails — those are formats the OneDrive service renders on its own.
Because there is no fallback path, every third-party format owner is blocked:
| Vendor | Format | Status |
|---|---|---|
| Krita | .kra |
KDE Bug 479726 — open; maintainer: "I don't think we can fix this" |
| Blender | .blend |
blender#115282 — open |
| MediBang Inc. | .mdp (MediBang Paint / FireAlpaca) |
This report |
Note that .one (OneNote) is also affected on the machine used here — Microsoft's own format
shows no thumbnail while cloud-only. This is a plain observation on our test machine, not a claim
about OneNote's design.
Related, though not the same report: WindowsAppSDK #1874
("StorageFile.GetThumbnailAsync does not generate thumbnails for OneDrive files", 2021) covers a
different symptom — thumbnails not being generated on demand for formats OneDrive can render. It
carried the transfer-to-platform label for over two years and was closed in March 2024 with:
Super interesting, but not a WASDK issue. I've filed http://task.ms/49323440 for @RobertStPierre or @luedersj to look into.
We mention it only to note that thumbnail behaviour on placeholders has been raised before and
routed to an internal task with no public outcome. The problem described here — no fallback to the
per-extension handler — is distinct and, as far as we can find, has not been reported with a
reproduction.
Requests
1. (Defect) Do not leave WTS_E_EXTRACTIONPENDING outstanding for work that will never complete.
When the service is known not to support an extension, return a terminal error so callers stop
retrying. This alone does not restore thumbnails, but it removes wasted work.
2. (The actual fix) Let the shell fall back to the registered per-extension handler when the sync
provider declines. WTS_E_NOSTORAGEPROVIDERTHUMBNAILHANDLER already names this case. Honouring it
would unblock every format owner at once, with no change required from any third party.
As an alternative to (2), a documented opt-in whereby the sync provider hydrates a single file on
demand and delegates — the pattern the CloudMirror sample itself demonstrates — would also resolve it.
Patch
The full change to Samples/CloudMirror/CloudMirror/ThumbnailProvider.cpp. Nothing else in the
sample affects the result; a second small patch only replaces the folder-picker dialogs with
environment variables so the run is non-interactive.
@@ -55,6 +55,21 @@ IFACEMETHODIMP ThumbnailProvider::GetThumbnail(_In_ UINT width, _Out_ HBITMAP* bitmap, _Out_ WTS_ALPHATYPE* alphaType)
*bitmap = nullptr;
*alphaType = WTSAT_UNKNOWN;
+ // [EXPERIMENT] Override the return value via MBP_THUMB_MODE. Unset = stock sample behaviour.
+ // nostorage = return WTS_E_NOSTORAGEPROVIDERTHUMBNAILHANDLER (0x8004B207)
+ // pending = return WTS_E_EXTRACTIONPENDING (0x8004B205) (what OneDrive is observed to do)
+ // notimpl = return E_NOTIMPL
+ {
+ wchar_t mode[64] = {};
+ if (GetEnvironmentVariable(L"MBP_THUMB_MODE", mode, ARRAYSIZE(mode)) > 0)
+ {
+ if (_wcsicmp(mode, L"nostorage") == 0) { return HRESULT(0x8004B207L); }
+ if (_wcsicmp(mode, L"pending") == 0) { return HRESULT(0x8004B205L); }
+ if (_wcsicmp(mode, L"notimpl") == 0) { return E_NOTIMPL; }
+ }
+ }
+
try
{
winrt::com_ptr<IThumbnailProvider> thumbnailProviderSource;
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with Samples/CloudMirror/CloudMirror/ThumbnailProvider.cpp and the reproduction steps using MBP_THUMB_MODE, then query thumbnails through IThumbnailCache with fresh file names. Compare the three HRESULT cases and confirm whether the shell invokes the registered per-extension handler after WTS_E_NOSTORAGEPROVIDERTHUMBNAILHANDLER; done means the fallback works for dehydrated placeholders without changing the sample's delegation pattern.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- operating-systems
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100