Skip to content

Commit 3379f54

Browse files
authored
Better file sizes in Explorer details v1.5.1 (#4462)
* Fixed the IEC terms option not working in some cases. * Fixed slow file list loading with mapped network drives. * Excluded msedgewebview2.exe to work around a reported incompatibility with Bitdefender which could cause the Start menu search to load indefinitely. * Excluded Windhawk as an additional safety measure to allow disabling the mod if it's stuck on init.
1 parent b804f7b commit 3379f54

1 file changed

Lines changed: 98 additions & 28 deletions

File tree

mods/explorer-details-better-file-sizes.wh.cpp

Lines changed: 98 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// ==WindhawkMod==
22
// @id explorer-details-better-file-sizes
33
// @name Better file sizes in Explorer details
4-
// @description Optional improvements: show folder sizes, use MB/GB for large files (by default, all sizes are shown in KBs), use IEC terms (such as KiB instead of KB)
5-
// @version 1.5
4+
// @description Enhances file size display in Explorer details with folder sizes, human-readable units (MB/GB), and optional IEC notation (KiB/MiB)
5+
// @version 1.5.1
66
// @author m417z
77
// @github https://github.com/m417z
88
// @twitter https://twitter.com/m417z
@@ -15,6 +15,9 @@
1515
// @exclude SearchHost.exe
1616
// @exclude ShellExperienceHost.exe
1717
// @exclude StartMenuExperienceHost.exe
18+
// @exclude msedgewebview2.exe
19+
// @exclude windhawk.exe
20+
// @exclude *\UI\VSCodium.exe
1821
// @compilerOptions -lole32 -loleaut32 -lpropsys
1922
// ==/WindhawkMod==
2023

@@ -65,7 +68,7 @@ To show folder sizes via "Everything" integration:
6568
6669
* "Everything" must be running for the integration to work.
6770
* Both "Everything" 1.4 and [1.5
68-
Alpha](https://www.voidtools.com/forum/viewtopic.php?t=9787) are supported.
71+
Beta](https://www.voidtools.com/forum/viewtopic.php?t=9787) are supported.
6972
With version 1.5.0.1384a or newer, the mod uses the new [Everything
7073
SDK3](https://www.voidtools.com/forum/viewtopic.php?t=15853), which results in
7174
a much faster folder size query (can be around 20x faster).
@@ -1201,8 +1204,24 @@ std::mutex g_everything4Wh_ThreadMutex;
12011204
std::atomic<HANDLE> g_everything4Wh_Thread;
12021205
HANDLE g_everything4Wh_ThreadReadyEvent;
12031206

1204-
bool IsUncPath(PCWSTR folderPath) {
1205-
return folderPath[0] == L'\\' && folderPath[1] == L'\\';
1207+
bool IsNetworkPath(PCWSTR folderPath) {
1208+
// UNC path, e.g. \\server\share.
1209+
if (folderPath[0] == L'\\' && folderPath[1] == L'\\') {
1210+
return true;
1211+
}
1212+
1213+
// Mapped network drive, e.g. Z:\. GetDriveType reads the drive type from
1214+
// the local mount table without hitting the network, so it's cheap.
1215+
if (((folderPath[0] >= L'A' && folderPath[0] <= L'Z') ||
1216+
(folderPath[0] >= L'a' && folderPath[0] <= L'z')) &&
1217+
folderPath[1] == L':' && folderPath[2] == L'\\') {
1218+
WCHAR root[] = {folderPath[0], L':', L'\\', L'\0'};
1219+
if (GetDriveType(root) == DRIVE_REMOTE) {
1220+
return true;
1221+
}
1222+
}
1223+
1224+
return false;
12061225
}
12071226

12081227
bool IsReparse(PCWSTR folderPath) {
@@ -1770,11 +1789,12 @@ HRESULT WINAPI CFSFolder__GetSize_Hook(void* pCFSFolder,
17701789
// the link itself. Subfolders of reparse points aren't indexed,
17711790
// so ES_QUERY_NO_INDEX is returned in this case.
17721791
//
1773-
// Avoid resolving UNC folders which are not indexed as it can
1774-
// be slow, and will be done for all folders if the UNC host
1775-
// isn't indexed.
1792+
// Avoid resolving network folders (UNC paths and mapped network
1793+
// drives) which are not indexed as it can be slow, and will be
1794+
// done for all folders if the network host isn't indexed.
17761795
if (result == ES_QUERY_ZERO_SIZE_REPARSE_POINT ||
1777-
(result == ES_QUERY_NO_INDEX && !IsUncPath(path.c_str()))) {
1796+
(result == ES_QUERY_NO_INDEX &&
1797+
!IsNetworkPath(path.c_str()))) {
17781798
Wh_Log(L"Resolving path due to status: %s",
17791799
g_gsQueryStatus[result]);
17801800

@@ -2402,6 +2422,45 @@ HRESULT WINAPI PSFormatForDisplay_Hook(const PROPERTYKEY& propkey,
24022422
cchText);
24032423
}
24042424

2425+
using PSStrFormatByteSizeW_t = void*(WINAPI*)(ULONGLONG size,
2426+
LPWSTR pwszText,
2427+
DWORD cchText);
2428+
PSStrFormatByteSizeW_t PSStrFormatByteSizeW_Original;
2429+
void* WINAPI PSStrFormatByteSizeW_Hook(ULONGLONG size,
2430+
LPWSTR pwszText,
2431+
DWORD cchText) {
2432+
Wh_Log(L">");
2433+
2434+
void* ret = PSStrFormatByteSizeW_Original(size, pwszText, cchText);
2435+
2436+
if (!pwszText || cchText == 0) {
2437+
return ret;
2438+
}
2439+
2440+
int len = wcslen(pwszText);
2441+
if (len < 2 || pwszText[len - 1] != 'B') {
2442+
return ret;
2443+
}
2444+
2445+
WCHAR sizeUnit = pwszText[len - 2];
2446+
if (sizeUnit != 'K' && sizeUnit != 'M' && sizeUnit != 'G' &&
2447+
sizeUnit != 'T' && sizeUnit != 'P' && sizeUnit != 'E') {
2448+
return ret;
2449+
}
2450+
2451+
if (cchText >= (size_t)len + 2) {
2452+
pwszText[len - 1] = 'i';
2453+
pwszText[len] = 'B';
2454+
pwszText[len + 1] = '\0';
2455+
2456+
Wh_Log(L"Appended 'i' to size unit, new string: %s", pwszText);
2457+
} else {
2458+
Wh_Log(L"Not enough space to append 'i'");
2459+
}
2460+
2461+
return ret;
2462+
}
2463+
24052464
using PSStrFormatKBSizeW_t = void*(WINAPI*)(ULONGLONG size,
24062465
LPWSTR pwszText,
24072466
DWORD cchText);
@@ -2418,14 +2477,19 @@ void* WINAPI PSStrFormatKBSizeW_Hook(ULONGLONG size,
24182477
}
24192478

24202479
int len = wcslen(pwszText);
2421-
if (len < 2 || (size_t)len + 1 > cchText - 1 || pwszText[len - 2] != 'K' ||
2422-
pwszText[len - 1] != 'B') {
2480+
if (len < 2 || pwszText[len - 2] != 'K' || pwszText[len - 1] != 'B') {
24232481
return ret;
24242482
}
24252483

2426-
pwszText[len - 1] = 'i';
2427-
pwszText[len] = 'B';
2428-
pwszText[len + 1] = '\0';
2484+
if (cchText >= (size_t)len + 2) {
2485+
pwszText[len - 1] = 'i';
2486+
pwszText[len] = 'B';
2487+
pwszText[len + 1] = '\0';
2488+
2489+
Wh_Log(L"Appended 'i' to size unit, new string: %s", pwszText);
2490+
} else {
2491+
Wh_Log(L"Not enough space to append 'i'");
2492+
}
24292493

24302494
return ret;
24312495
}
@@ -2464,17 +2528,20 @@ int WINAPI LoadStringW_Hook(HINSTANCE hInstance,
24642528

24652529
Wh_Log(L"> Overriding string %u: %s", uID, lpBuffer);
24662530

2467-
size_t originalStringLen = p - lpBuffer;
2531+
size_t stringLen = p - lpBuffer;
24682532

2469-
// Override "B" to "iB".
2470-
p[-1] = 'i';
2471-
2472-
if ((size_t)cchBufferMax >= originalStringLen + 2) {
2533+
if ((size_t)cchBufferMax >= stringLen + 2) {
2534+
p[-1] = 'i';
24732535
p[0] = 'B';
24742536
p[1] = '\0';
2537+
stringLen++;
2538+
2539+
Wh_Log(L"Appended 'i' to size unit, new string: %s", lpBuffer);
2540+
} else {
2541+
Wh_Log(L"Not enough space to append 'i'");
24752542
}
24762543

2477-
return wcslen(lpBuffer);
2544+
return stringLen;
24782545
}
24792546

24802547
bool HookWindowsStorageSymbols() {
@@ -2668,7 +2735,6 @@ bool Init(HMODULE module) {
26682735

26692736
void** ppCxaThrow = FindImportPtr(module, "libc++.dll", "__cxa_throw");
26702737
if (!ppCxaThrow) {
2671-
wsprintf(errorMsg, L"No __cxa_throw");
26722738
return false;
26732739
}
26742740

@@ -2873,13 +2939,17 @@ BOOL Wh_ModInit() {
28732939

28742940
g_propsysModule = propsysModule;
28752941

2876-
if (!g_settings.disableKbOnlySizes) {
2877-
auto pPSStrFormatKBSizeW =
2878-
(PSStrFormatKBSizeW_t)GetProcAddress(propsysModule, (PCSTR)422);
2879-
WindhawkUtils::Wh_SetFunctionHookT(pPSStrFormatKBSizeW,
2880-
PSStrFormatKBSizeW_Hook,
2881-
&PSStrFormatKBSizeW_Original);
2882-
}
2942+
auto pPSStrFormatByteSizeW =
2943+
(PSStrFormatByteSizeW_t)GetProcAddress(propsysModule, (PCSTR)421);
2944+
WindhawkUtils::Wh_SetFunctionHookT(pPSStrFormatByteSizeW,
2945+
PSStrFormatByteSizeW_Hook,
2946+
&PSStrFormatByteSizeW_Original);
2947+
2948+
auto pPSStrFormatKBSizeW =
2949+
(PSStrFormatKBSizeW_t)GetProcAddress(propsysModule, (PCSTR)422);
2950+
WindhawkUtils::Wh_SetFunctionHookT(pPSStrFormatKBSizeW,
2951+
PSStrFormatKBSizeW_Hook,
2952+
&PSStrFormatKBSizeW_Original);
28832953

28842954
HMODULE kernelBaseModule = GetModuleHandle(L"kernelbase.dll");
28852955
HMODULE kernel32Module = GetModuleHandle(L"kernel32.dll");

0 commit comments

Comments
 (0)