Add Disable folder thumbnails mod - #5425
Conversation
|
Thanks for the pull request! This repository uses a two-stage review: an AI review that you run yourself, followed by a human review. To get started, comment See the pull request review process for the full details. |
|
/ai-review |
|
Something went wrong while preparing the AI review, so there is nothing to post this time. This is a problem on the reviewer's side, not with this pull request. Comment |
|
/ai-review |
Submission reviewNote: This review was done by Claude. Due to the amount of submissions, doing a fully manual review for each pull request is no longer feasible. Thank you for understanding. Remember: The AI reviewer can be wrong - it may misread code, flag correct code as broken, or suggest changes that make things worse. Treat its findings as suggestions to verify, not instructions to follow blindly. You're responsible for the code you submit, so if a finding doesn't hold up, say so instead of changing working code to satisfy it. Please address the following issues. The items in the collapsed sections are optional, so it's your call whether to address them. The classification logic itself is sound (the 1. Don't activate a COM object in When the mod is loaded at process startup, It also creates the exact hazard the pin in item 2 was added to paper over: the trailing All of this disappears with a plain symbol hook against the module that implements the thumbnail cache ( // windows.storage.dll
static const WindhawkUtils::SYMBOL_HOOK hooks[] = {
{
{L"public: virtual long __cdecl CLocalThumbnailCache::GetThumbnail(...)"},
&g_originalGetThumbnail,
GetThumbnail_Hook,
},
};
BOOL Wh_ModInit() {
HMODULE storage = GetModuleHandleW(L"windows.storage.dll");
if (!storage) {
return FALSE;
}
return WindhawkUtils::HookSymbols(storage, hooks, ARRAYSIZE(hooks));
}folder-thumbnail-style-switcher.wh.cpp#L978-L1035 is the same target module and shows the pattern. Note that mod hooks 2. BOOL pinned = GetModuleHandleExW(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_PIN, ...);A pin can never be undone. Once the mod has run, the module stays loaded for the lifetime of the process even after the user disables or uninstalls the mod — a mod's effects have to disappear when it's disabled. Pinning also makes the mod's own success depend on it: if With item 1 applied there is nothing to pin — 3. Substantial overlap with folder-thumbnail-style-switcher is about Explorer folder thumbnails, targets the same module, uses the same The functional difference is real (suppressing vs. restyling), so this isn't automatically a blocker — but please state in the PR why it should be standalone, and consider opening an issue/PR on that mod proposing a "None" style instead. 4. Verify the mod takes effect (and reverts) without an Explorer restart The README instructs users to enable the mod and then restart Explorer via Task Manager. That shouldn't be necessary:
Please check which it is. Note the restart instruction also has a reversibility angle — if enabling needs a restart, disabling presumably does too, and a mod's effect should come and go with the toggle. 5. Add a screenshot to the README The effect is purely visual (folder thumbnails replaced by plain folder icons). A before/after screenshot makes the mod's purpose immediately clear on windhawk.net. Only Optional improvements
Minor polish — none of this affects users, so it's your call.
Functionality notes
Non-critical observations and ideas about the feature behavior itself.
Next steps:
See the review process for details. |
|
/ready-for-reviewer |
|
New commits were pushed, so this pull request left the human review queue and is back to waiting-for-author. Comment |
Updated author information and added GitHub link.
|
/ai-review |
Submission reviewNote: This review was done by Claude. Due to the amount of submissions, doing a fully manual review for each pull request is no longer feasible. Thank you for understanding. Remember: The AI reviewer can be wrong - it may misread code, flag correct code as broken, or suggest changes that make things worse. Treat its findings as suggestions to verify, not instructions to follow blindly. You're responsible for the code you submit, so if a finding doesn't hold up, say so instead of changing working code to satisfy it. Please address the following issues. The items in the collapsed sections are optional, so it's your call whether to address them. The overall approach (intercept 1.
Use STA, as the merged mods that do the same vtable trick do — HRESULT initHr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);or, to leave the host's main-thread apartment completely untouched, resolve the vtable on a short-lived dedicated thread as Either way, it's worth sanity-checking that the resolved address really belongs to the expected module before hooking, so a proxy/interception by something else fails loudly instead of silently: WCHAR moduleName[MAX_PATH];
if (!GetModuleFileNameW(implementationModule, moduleName, ARRAYSIZE(moduleName)) ||
!PathMatchSpecW(moduleName, L"*\\windows.storage.dll")) {
Wh_Log(L"Unexpected GetThumbnail implementation module: %s", moduleName);
return FALSE;
}2. The shortcut branch does a full For every The shell already has a one-call API for this — IShellItem* targetItem = nullptr;
if (SUCCEEDED(item->BindToHandler(nullptr, BHID_LinkTargetItem, IID_PPV_ARGS(&targetItem)))) {
bool targetIsFolder = IsPlainFilesystemFolder(targetItem);
targetItem->Release();
return targetIsFolder;
}
return false;Better still, check whether target resolution is needed at all: the shell reports 3. The README has no screenshot. This is a mod with a purely visual effect, so a before/after screenshot of a folder view (thumbnails vs. plain icons) makes it much easier for users to tell what they're getting. Only Optional improvements
Minor polish — none of this affects users, so it's your call.
Functionality notes
Non-critical observations and ideas about the feature behavior itself.
Next steps:
See the review process for details. |
|
/ready-for-reviewer |
|
New commits were pushed, so this pull request left the human review queue and is back to waiting-for-author. Comment |
|
/ai-review |
|
This pull request has already had 3 AI reviews in the last 24 hours, which is the limit, so no review was posted this time. Comment |
|
@m417z I only had 2 reviews. Why it says I had 3? |
|
Because of the error 16 hours ago. I started a review for you. |
Submission reviewNote: This review was done by Claude. Due to the amount of submissions, doing a fully manual review for each pull request is no longer feasible. Thank you for understanding. Remember: The AI reviewer can be wrong - it may misread code, flag correct code as broken, or suggest changes that make things worse. Treat its findings as suggestions to verify, not instructions to follow blindly. You're responsible for the code you submit, so if a finding doesn't hold up, say so instead of changing working code to satisfy it. Please address the following issues. The items in the collapsed sections are optional, so it's your call whether to address them. The idea is useful and the filtering logic (excluding 1. This feature already exists as an option in Resource Redirect
The maintainer strongly prefers extending an existing mod over merging a near-duplicate. Please state in the PR description how this mod differs and why it should exist separately. The differences I can see are that yours also covers folder shortcuts and that it isn't tied to a large theming mod — those may well be enough, but it needs to be spelled out. If the delta really is just "the same thing, standalone", extending Resource Redirect (or the 2. Don't activate the COM object to find the hook target — hook the implementation by symbol
// thumbcache.dll, windows.storage.dll
WindhawkUtils::SYMBOL_HOOK symbolHooks[] = {
{{L"public: virtual long __cdecl CThumbnailCache::GetThumbnail(struct IShellItem *,unsigned int,enum WTS_FLAGS,struct ISharedBitmap * *,enum WTS_CACHEFLAGS *,struct WTS_THUMBNAILID *)"},
&g_getThumbnailOriginal, GetThumbnailHook, true},
{{L"public: virtual long __cdecl CThumbnailCacheAPI::GetThumbnail(struct IShellItem *,unsigned int,enum WTS_FLAGS,struct ISharedBitmap * *,enum WTS_CACHEFLAGS *,struct WTS_THUMBNAILID *)"},
&g_apiGetThumbnailOriginal, ApiGetThumbnailHook, true},
};Concrete gains over the current approach:
The one thing the current approach genuinely buys you is version-agnosticism (whatever the CLSID returns is what gets hooked). Hooking both symbols in both DLLs gives you the same coverage without the side effects. 3. BOOL pinned = GetModuleHandleExW(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN, ...);A pin can never be undone. The thumbnail-cache DLL stays mapped for the lifetime of the process even after the mod is disabled or uninstalled, in every process the mod injected into — and the mod has no Keeping the module alive while the hook is installed is a legitimate need (Windhawk restores the original bytes at unload, so the code must still be mapped). Take an ordinary reference and drop it in // An ordinary reference, not a pin: released in Wh_ModUninit, once hooks
// are already removed and the module is safe to let go.
HMODULE ref = nullptr;
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
reinterpret_cast<LPCWSTR>(module), &ref);and releases it in 4. Per the mod lifetime flow chart, Two things to do here:
5. The shortcut path can block for a long time on unreachable targets hr = SHCreateItemFromIDList(targetIdList, IID_PPV_ARGS(&targetItem));
if (SUCCEEDED(hr)) {
targetIsFolder = IsPlainFilesystemFolder(targetItem); // GetAttributes()Creating a shell item from the target IDList and querying You've already loaded the WCHAR targetPath[MAX_PATH];
WIN32_FIND_DATAW findData{};
if (SUCCEEDED(link->GetPath(targetPath, ARRAYSIZE(targetPath), &findData,
SLGP_RAWPATH))) {
targetIsFolder = (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
}That's cached data (it can be stale if the target changed type since the shortcut was made, which is a non-issue here), and it costs nothing beyond the 6. Add a screenshot to the README This is a purely visual mod and the README currently has no image. A before/after screenshot of a folder view with and without thumbnails makes the mod much easier to evaluate in the catalog. Images must be hosted on Optional improvements
Minor polish — none of this affects users, so it's your call.
Functionality notes
Non-critical observations and ideas about the feature behavior itself.
Next steps:
See the review process for details. |
This does not disable thumbnails completely. Still, an empty folder has a different icon from a folder with content. Thus, mods such as |
I don't think this is a good idea, this requires symbols download, which could be unavailable for a given build and creates a delay at the first start. |
|
/ready-for-reviewer |
|
This pull request was converted to a draft, so it left the human review queue and is back to waiting-for-author. Mark it as ready for review and comment |
|
/ready-for-reviewer |
Changelog
If this pull request updates an existing mod, describe the changes below:
Mod authorship
If this pull request introduces a new mod, please complete the section below.
This mod was created by:
Please select the options that best apply. Your selection does not affect the acceptance criteria, but it helps reviewers understand the context of the code and provide relevant feedback.