Skip to content

Commit

Permalink
Better file sizes in Explorer details v1.4 (#1217)
Browse files Browse the repository at this point in the history
* Added an option to mix files and folders when sorting by size.
  • Loading branch information
m417z authored Nov 8, 2024
1 parent 404f046 commit 8a97216
Showing 1 changed file with 113 additions and 46 deletions.
159 changes: 113 additions & 46 deletions mods/explorer-details-better-file-sizes.wh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// @id explorer-details-better-file-sizes
// @name Better file sizes in Explorer details
// @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)
// @version 1.3
// @version 1.4
// @author m417z
// @github https://github.com/m417z
// @twitter https://twitter.com/m417z
Expand Down Expand Up @@ -63,6 +63,13 @@ have them calculated manually. Since calculating folder sizes can be slow, it's
not enabled by default, and there's an option to enable it only while holding
the Shift key.
## Mix files and folders when sorting by size
When sorting by size, files end up in one separate chunk, and folders in
another. That's the default Explorer behavior, which also applies when sorting
by other columns. This option changes sorting by size to disable this
separation.
## Use MB/GB for large files
Explorer always shows file sizes in KBs in details, make it use MB/GB when
Expand Down Expand Up @@ -98,6 +105,10 @@ KiB?](https://devblogs.microsoft.com/oldnewthing/20090611-00/?p=17933).
- everything: Enabled via "Everything" integration
- always: Enabled, calculated manually (can be slow)
- withShiftKey: Enabled, calculated manually while holding the Shift key
- sortSizesMixFolders: true
$name: Mix files and folders when sorting by size
$description: >-
By default, folders are kept separately from files when sorting
- disableKbOnlySizes: true
$name: Use MB/GB for large files
$description: >-
Expand All @@ -120,6 +131,7 @@ KiB?](https://devblogs.microsoft.com/oldnewthing/20090611-00/?p=17933).

#include <initguid.h>

#include <comutil.h>
#include <propsys.h>
#include <shlobj.h>
#include <shobjidl.h>
Expand All @@ -135,6 +147,7 @@ enum class CalculateFolderSizes {

struct {
CalculateFolderSizes calculateFolderSizes;
bool sortSizesMixFolders;
bool disableKbOnlySizes;
bool useIecTerms;
} g_settings;
Expand All @@ -157,55 +170,12 @@ auto hookRefCountScope() {
#pragma region everything_sdk
// clang-format off

// Version 1.5

#define FT_NOMOREFIELDS 0
#define FT_NUMERIC_32 1
#define FT_NUMERIC_64 2
#define FT_NUMERIC_FLOATING 3
#define FT_DATE 4
#define FT_TIME 5
#define FT_BOOLEAN 6
#define FT_MULTIPLECHOICE 7
#define FT_STRING 8
#define FT_FULLTEXT 9
#define FT_DATETIME 10
#define FT_STRINGW 11

#define FT_NOSUCHFIELD -1 // Error, invalid field number given
#define FT_FILEERROR -2 // File i/o error
#define FT_FIELDEMPTY -3 // Field valid, but empty
#define FT_NOTSUPPORTED -5 // Function not supported

typedef struct {
int size;
DWORD PluginInterfaceVersionLow;
DWORD PluginInterfaceVersionHi;
char DefaultIniName[MAX_PATH];
} ContentDefaultParamStruct;

int __stdcall ContentGetDetectString(LPSTR DetectString, int maxlen);
int __stdcall ContentGetSupportedField(int FieldIndex, LPSTR FieldName, [[maybe_unused]] LPSTR Units, [[maybe_unused]] int maxlen);
int __stdcall ContentGetValueW(LPWSTR FileName, int FieldIndex, [[maybe_unused]] int UnitIndex, LPVOID FieldValue, [[maybe_unused]] int maxlen, [[maybe_unused]] int flags);

void __stdcall ContentSetDefaultParams([[maybe_unused]] ContentDefaultParamStruct *dps);
int __stdcall ContentGetSupportedFieldFlags(int FieldIndex);

// Severely reduced Everything_IPC.h, Copyright (C) 2022 David Carpenter (this file only) https://www.voidtools.com/Everything-SDK.zip

#define EVERYTHING_WM_IPC (WM_USER)

#define EVERYTHING_IPC_GET_MAJOR_VERSION 0
#define EVERYTHING_IPC_GET_MINOR_VERSION 1
#define EVERYTHING_IPC_GET_REVISION 2
#define EVERYTHING_IPC_GET_BUILD_NUMBER 3
// Severely reduced Everything_IPC.h, Copyright (C) 2022 David Carpenter
// https://www.voidtools.com/Everything-SDK.zip

#define EVERYTHING_IPC_WNDCLASSW L"EVERYTHING_TASKBAR_NOTIFICATION"
#define EVERYTHING_IPC_WNDCLASSW_15A L"EVERYTHING_TASKBAR_NOTIFICATION_(1.5a)"

#define EVERYTHING_IPC_IS_FILE_INFO_INDEXED 411
#define EVERYTHING_IPC_FILE_INFO_FOLDER_SIZE 2

#define EVERYTHING_IPC_MATCHCASE 0x00000001
#define EVERYTHING_IPC_MATCHDIACRITICS 0x00000010
#define EVERYTHING_IPC_COPYDATA_QUERY2W 18
Expand Down Expand Up @@ -718,6 +688,71 @@ HRESULT WINAPI CFSFolder__GetSize_Hook(void* pCFSFolder,
return S_OK;
}

using CFSFolder_MapColumnToSCID_t = HRESULT(WINAPI*)(void* pCFSFolder,
int column,
PROPERTYKEY* scid);
CFSFolder_MapColumnToSCID_t CFSFolder_MapColumnToSCID_Original;

using CFSFolder_GetDetailsEx_t = HRESULT(WINAPI*)(void* pCFSFolder,
const ITEMID_CHILD* itemid,
const PROPERTYKEY* scid,
VARIANT* value);
CFSFolder_GetDetailsEx_t CFSFolder_GetDetailsEx_Original;

using CFSFolder_CompareIDs_t =
HRESULT(WINAPI*)(void* pCFSFolder,
int column,
const ITEMIDLIST_RELATIVE* itemid1,
const ITEMIDLIST_RELATIVE* itemid2);
CFSFolder_CompareIDs_t CFSFolder_CompareIDs_Original;
HRESULT WINAPI CFSFolder_CompareIDs_Hook(void* pCFSFolder,
int column,
const ITEMIDLIST_RELATIVE* itemid1,
const ITEMIDLIST_RELATIVE* itemid2) {
auto hookScope = hookRefCountScope();

auto original = [=]() {
return CFSFolder_CompareIDs_Original(pCFSFolder, column, itemid1,
itemid2);
};

if (!itemid1 || !itemid2 || !g_settings.sortSizesMixFolders) {
return original();
}

PROPERTYKEY columnSCID;
if (FAILED(CFSFolder_MapColumnToSCID_Original(pCFSFolder, column,
&columnSCID)) ||
!IsEqualPropertyKey(columnSCID, kPKEY_Size)) {
return original();
}

_variant_t value1;
if (FAILED(CFSFolder_GetDetailsEx_Original(pCFSFolder, itemid1, &columnSCID,
value1.GetAddress())) ||
value1.vt != VT_UI8) {
return original();
}

_variant_t value2;
if (FAILED(CFSFolder_GetDetailsEx_Original(pCFSFolder, itemid2, &columnSCID,
value2.GetAddress())) ||
value2.vt != VT_UI8) {
return original();
}

ULONGLONG size1 = value1.ullVal;
ULONGLONG size2 = value2.ullVal;

if (size1 > size2) {
return 1;
} else if (size1 < size2) {
return 0xFFFF;
} else {
return 0;
}
}

using PSFormatForDisplayAlloc_t = decltype(&PSFormatForDisplayAlloc);
PSFormatForDisplayAlloc_t PSFormatForDisplayAlloc_Original;
HRESULT WINAPI PSFormatForDisplayAlloc_Hook(const PROPERTYKEY& key,
Expand Down Expand Up @@ -809,6 +844,37 @@ bool HookWindowsStorageSymbols() {
&CFSFolder__GetSize_Original,
CFSFolder__GetSize_Hook,
},
{
{
#ifdef _WIN64
LR"(public: virtual long __cdecl CFSFolder::MapColumnToSCID(unsigned int,struct _tagpropertykey *))",
#else
LR"(public: virtual long __stdcall CFSFolder::MapColumnToSCID(unsigned int,struct _tagpropertykey *))",
#endif
},
&CFSFolder_MapColumnToSCID_Original,
},
{
{
#ifdef _WIN64
LR"(public: virtual long __cdecl CFSFolder::GetDetailsEx(struct _ITEMID_CHILD const __unaligned *,struct _tagpropertykey const *,struct tagVARIANT *))",
#else
LR"(public: virtual long __stdcall CFSFolder::GetDetailsEx(struct _ITEMID_CHILD const *,struct _tagpropertykey const *,struct tagVARIANT *))",
#endif
},
&CFSFolder_GetDetailsEx_Original,
},
{
{
#ifdef _WIN64
LR"(public: virtual long __cdecl CFSFolder::CompareIDs(__int64,struct _ITEMIDLIST_RELATIVE const __unaligned *,struct _ITEMIDLIST_RELATIVE const __unaligned *))",
#else
LR"(public: virtual long __stdcall CFSFolder::CompareIDs(long,struct _ITEMIDLIST_RELATIVE const *,struct _ITEMIDLIST_RELATIVE const *))",
#endif
},
&CFSFolder_CompareIDs_Original,
CFSFolder_CompareIDs_Hook,
},
};

return HookSymbols(windowsStorageModule, windowsStorageHooks,
Expand All @@ -827,6 +893,7 @@ void LoadSettings() {
}
Wh_FreeStringSetting(calculateFolderSizes);

g_settings.sortSizesMixFolders = Wh_GetIntSetting(L"sortSizesMixFolders");
g_settings.disableKbOnlySizes = Wh_GetIntSetting(L"disableKbOnlySizes");
g_settings.useIecTerms = Wh_GetIntSetting(L"useIecTerms");
}
Expand Down

0 comments on commit 8a97216

Please sign in to comment.