https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7d44c1cb0729b37d7657585f3740c68030e755d8

commit 7d44c1cb0729b37d7657585f3740c68030e755d8
Author:     Kyle Katarn <[email protected]>
AuthorDate: Thu Sep 10 20:48:40 2020 +0200
Commit:     GitHub <[email protected]>
CommitDate: Thu Sep 10 20:48:40 2020 +0200

    [SHELL32] Show "size on disk" in file/folder properties (#3107)
    
    
    
    Co-authored-by: Katayama Hirofumi MZ <[email protected]>
    Co-authored-by: Hermès BÉLUSCA - MAÏTO <[email protected]>
    Co-authored-by: Adam Stachowicz <[email protected]>
---
 dll/win32/shell32/dialogs/filedefext.cpp | 118 +++++++++++++++++++++++++------
 dll/win32/shell32/dialogs/filedefext.h   |   4 +-
 2 files changed, 97 insertions(+), 25 deletions(-)

diff --git a/dll/win32/shell32/dialogs/filedefext.cpp 
b/dll/win32/shell32/dialogs/filedefext.cpp
index f4b587dae1e..edcb44ff1b4 100644
--- a/dll/win32/shell32/dialogs/filedefext.cpp
+++ b/dll/win32/shell32/dialogs/filedefext.cpp
@@ -21,10 +21,64 @@
 
 #include "precomp.h"
 
+#define NTOS_MODE_USER
+#include <ndk/iofuncs.h>
+#include <ndk/obfuncs.h>
+
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 
 EXTERN_C BOOL PathIsExeW(LPCWSTR lpszPath);
 
+BOOL GetPhysicalFileSize(LPCWSTR PathBuffer, PULARGE_INTEGER Size)
+{
+    UNICODE_STRING FileName;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    IO_STATUS_BLOCK IoStatusBlock;
+    HANDLE FileHandle;
+    FILE_STANDARD_INFORMATION FileInfo;
+    NTSTATUS Status;
+    
+    if (!RtlDosPathNameToNtPathName_U(PathBuffer, &FileName, NULL, NULL))
+    {
+        ERR("RtlDosPathNameToNtPathName_U failed\n");
+        return FALSE;
+    }
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &FileName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status = NtOpenFile(&FileHandle,
+                        FILE_READ_ATTRIBUTES | SYNCHRONIZE,
+                        &ObjectAttributes,
+                        &IoStatusBlock,
+                        FILE_SHARE_READ,
+                        FILE_SYNCHRONOUS_IO_NONALERT);
+    RtlFreeUnicodeString(&FileName);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("NtOpenFile failed for %S (Status 0x%08lx)\n", PathBuffer, Status);
+        return FALSE;
+    }
+
+    /* Query the file size */
+    Status = NtQueryInformationFile(FileHandle,
+                                    &IoStatusBlock,
+                                    &FileInfo,
+                                    sizeof(FileInfo),
+                                    FileStandardInformation);
+    NtClose(FileHandle);
+    if (!NT_SUCCESS(Status))
+    {
+        ERR("NtQueryInformationFile failed for %S (Status: %08lX)\n", 
PathBuffer, Status);
+        return FALSE;
+    }
+    
+    Size->QuadPart = FileInfo.AllocationSize.QuadPart;
+    return TRUE;
+}
+
 BOOL CFileVersionInfo::Load(LPCWSTR pwszPath)
 {
     ULONG cbInfo = GetFileVersionInfoSizeW(pwszPath, NULL);
@@ -552,7 +606,17 @@ CFileDefExt::InitFileAttr(HWND hwndDlg)
             FileSize.u.LowPart = FileInfo.nFileSizeLow;
             FileSize.u.HighPart = FileInfo.nFileSizeHigh;
             if (SH_FormatFileSizeWithBytes(&FileSize, wszBuf, 
_countof(wszBuf)))
+            {
                 SetDlgItemTextW(hwndDlg, 14011, wszBuf);
+                
+                // Compute file on disk. If fails, use logical size
+                if (GetPhysicalFileSize(m_wszPath, &FileSize))
+                    SH_FormatFileSizeWithBytes(&FileSize, wszBuf, 
_countof(wszBuf));
+                else
+                    ERR("Unreliable size on disk\n");
+
+                SetDlgItemTextW(hwndDlg, 14012, wszBuf);
+            }
         }
     }
 
@@ -562,8 +626,7 @@ CFileDefExt::InitFileAttr(HWND hwndDlg)
 
         _CountFolderAndFilesData *data = 
static_cast<_CountFolderAndFilesData*>(HeapAlloc(GetProcessHeap(), 0, 
sizeof(_CountFolderAndFilesData)));
         data->This = this;
-        data->pwszBuf = static_cast<LPWSTR>(HeapAlloc(GetProcessHeap(), 0, 
sizeof(WCHAR) * MAX_PATH));
-        data->cchBufMax = MAX_PATH;
+        data->pwszBuf = static_cast<LPWSTR>(HeapAlloc(GetProcessHeap(), 
HEAP_ZERO_MEMORY, sizeof(WCHAR) * MAX_PATH));
         data->hwndDlg = hwndDlg;
         this->AddRef();
         StringCchCopyW(data->pwszBuf, MAX_PATH, m_wszPath);
@@ -574,6 +637,9 @@ CFileDefExt::InitFileAttr(HWND hwndDlg)
         if (SH_FormatFileSizeWithBytes(&m_DirSize, wszBuf, _countof(wszBuf)))
             SetDlgItemTextW(hwndDlg, 14011, wszBuf);
 
+        if (SH_FormatFileSizeWithBytes(&m_DirSizeOnDisc, wszBuf, 
_countof(wszBuf)))
+            SetDlgItemTextW(hwndDlg, 14012, wszBuf);
+
         /* Display files and folders count */
         WCHAR wszFormat[256];
         LoadStringW(shell32_hInstance, IDS_FILE_FOLDER, wszFormat, 
_countof(wszFormat));
@@ -1159,6 +1225,7 @@ CFileDefExt::CFileDefExt():
 {
     m_wszPath[0] = L'\0';
     m_DirSize.QuadPart = 0ull;
+    m_DirSizeOnDisc.QuadPart = 0ull;
 
     m_szFolderIconPath[0] = 0;
     m_nFolderIconIndex = 0;
@@ -1293,7 +1360,7 @@ CFileDefExt::_CountFolderAndFilesThreadProc(LPVOID 
lpParameter)
 {
     _CountFolderAndFilesData *data = 
static_cast<_CountFolderAndFilesData*>(lpParameter);
     DWORD ticks = 0;
-    data->This->CountFolderAndFiles(data->hwndDlg, data->pwszBuf, 
data->cchBufMax, &ticks);
+    data->This->CountFolderAndFiles(data->hwndDlg, data->pwszBuf, &ticks);
 
     //Release the CFileDefExt and data object holds in the copying thread.
     data->This->Release();
@@ -1304,25 +1371,19 @@ CFileDefExt::_CountFolderAndFilesThreadProc(LPVOID 
lpParameter)
 }
 
 BOOL
-CFileDefExt::CountFolderAndFiles(HWND hwndDlg, LPWSTR pwszBuf, UINT cchBufMax, 
DWORD *ticks)
+CFileDefExt::CountFolderAndFiles(HWND hwndDlg, LPCWSTR pwszBuf, DWORD *ticks)
 {
-    /* Find filename position */
-    UINT cchBuf = wcslen(pwszBuf);
-    WCHAR *pwszFilename = pwszBuf + cchBuf;
-    size_t cchFilenameMax = cchBufMax - cchBuf;
-    if (!cchFilenameMax)
-        return FALSE;
-    *(pwszFilename++) = '\\';
-    --cchFilenameMax;
-
-    /* Find all files, FIXME: shouldn't be "*"? */
-    StringCchCopyW(pwszFilename, cchFilenameMax, L"*");
+    CString sBuf = pwszBuf;
+    sBuf += L"\\" ;
+    CString sSearch = sBuf;
+    sSearch += L"*" ;
+    CString sFileName;
 
     WIN32_FIND_DATAW wfd;
-    HANDLE hFind = FindFirstFileW(pwszBuf, &wfd);
+    HANDLE hFind = FindFirstFileW(sSearch, &wfd);
     if (hFind == INVALID_HANDLE_VALUE)
     {
-        ERR("FindFirstFileW %ls failed\n", pwszBuf);
+        ERR("FindFirstFileW %ls failed\n", sSearch.GetString());
         return FALSE;
     }
 
@@ -1334,6 +1395,8 @@ CFileDefExt::CountFolderAndFiles(HWND hwndDlg, LPWSTR 
pwszBuf, UINT cchBufMax, D
 
     do
     {
+        sFileName = sBuf;
+        sFileName += wfd.cFileName;
         if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
         {
             /* Don't process "." and ".." items */
@@ -1342,8 +1405,7 @@ CFileDefExt::CountFolderAndFiles(HWND hwndDlg, LPWSTR 
pwszBuf, UINT cchBufMax, D
 
             ++m_cFolders;
 
-            StringCchCopyW(pwszFilename, cchFilenameMax, wfd.cFileName);
-            CountFolderAndFiles(hwndDlg, pwszBuf, cchBufMax, ticks);
+            CountFolderAndFiles(hwndDlg, sFileName, ticks);
         }
         else
         {
@@ -1353,19 +1415,26 @@ CFileDefExt::CountFolderAndFiles(HWND hwndDlg, LPWSTR 
pwszBuf, UINT cchBufMax, D
             FileSize.u.LowPart  = wfd.nFileSizeLow;
             FileSize.u.HighPart = wfd.nFileSizeHigh;
             m_DirSize.QuadPart += FileSize.QuadPart;
+            // Calculate size on disc
+            if (!GetPhysicalFileSize(sFileName.GetString(), &FileSize))
+                ERR("GetPhysicalFileSize failed for %ls\n", 
sFileName.GetString());
+            m_DirSizeOnDisc.QuadPart += FileSize.QuadPart;
         }
         if (GetTickCount() - *ticks > (DWORD) 300)
         {
             /* FIXME Using IsWindow is generally ill advised */
             if (IsWindow(hwndDlg))
             {
-                WCHAR wszBuf[MAX_PATH];
+                WCHAR wszBuf[100];
 
                 if (SH_FormatFileSizeWithBytes(&m_DirSize, wszBuf, 
_countof(wszBuf)))
                     SetDlgItemTextW(hwndDlg, 14011, wszBuf);
 
+                if (SH_FormatFileSizeWithBytes(&m_DirSizeOnDisc, wszBuf, 
_countof(wszBuf)))
+                    SetDlgItemTextW(hwndDlg, 14012, wszBuf);
+
                 /* Display files and folders count */
-                WCHAR wszFormat[256];
+                WCHAR wszFormat[100];
                 LoadStringW(shell32_hInstance, IDS_FILE_FOLDER, wszFormat, 
_countof(wszFormat));
                 StringCchPrintfW(wszBuf, _countof(wszBuf), wszFormat, 
m_cFiles, m_cFolders);
                 SetDlgItemTextW(hwndDlg, 14027, wszBuf);
@@ -1378,13 +1447,16 @@ CFileDefExt::CountFolderAndFiles(HWND hwndDlg, LPWSTR 
pwszBuf, UINT cchBufMax, D
 
     if (root && IsWindow(hwndDlg))
     {
-        WCHAR wszBuf[MAX_PATH];
+        WCHAR wszBuf[100];
 
         if (SH_FormatFileSizeWithBytes(&m_DirSize, wszBuf, _countof(wszBuf)))
             SetDlgItemTextW(hwndDlg, 14011, wszBuf);
 
+        if (SH_FormatFileSizeWithBytes(&m_DirSizeOnDisc, wszBuf, 
_countof(wszBuf)))
+            SetDlgItemTextW(hwndDlg, 14012, wszBuf);
+
         /* Display files and folders count */
-        WCHAR wszFormat[256];
+        WCHAR wszFormat[100];
         LoadStringW(shell32_hInstance, IDS_FILE_FOLDER, wszFormat, 
_countof(wszFormat));
         StringCchPrintfW(wszBuf, _countof(wszBuf), wszFormat, m_cFiles, 
m_cFolders);
         SetDlgItemTextW(hwndDlg, 14027, wszBuf);
diff --git a/dll/win32/shell32/dialogs/filedefext.h 
b/dll/win32/shell32/dialogs/filedefext.h
index ce56b84bff1..e093bec7689 100644
--- a/dll/win32/shell32/dialogs/filedefext.h
+++ b/dll/win32/shell32/dialogs/filedefext.h
@@ -75,7 +75,7 @@ private:
     static INT_PTR CALLBACK GeneralPageProc(HWND hwndDlg, UINT uMsg, WPARAM 
wParam, LPARAM lParam);
        static INT_PTR CALLBACK VersionPageProc(HWND hwndDlg, UINT uMsg, WPARAM 
wParam, LPARAM lParam);
        static INT_PTR CALLBACK FolderCustomizePageProc(HWND hwndDlg, UINT 
uMsg, WPARAM wParam, LPARAM lParam);
-       BOOL CountFolderAndFiles(HWND hwndDlg, LPWSTR pwszBuf, UINT cchBufMax, 
LPDWORD ticks);
+       BOOL CountFolderAndFiles(HWND hwndDlg, LPCWSTR pwszBuf, LPDWORD ticks);
 
        WCHAR m_wszPath[MAX_PATH];
        CFileVersionInfo m_VerInfo;
@@ -84,6 +84,7 @@ private:
        DWORD m_cFiles;
     DWORD m_cFolders;
     ULARGE_INTEGER m_DirSize;
+    ULARGE_INTEGER m_DirSizeOnDisc;
 
     static DWORD WINAPI _CountFolderAndFilesThreadProc(LPVOID lpParameter);
 
@@ -136,7 +137,6 @@ struct _CountFolderAndFilesData {
     CFileDefExt *This;
     HWND hwndDlg;
     LPWSTR pwszBuf;
-    UINT cchBufMax;
 };
 
 #endif /* _FILE_DEF_EXT_H_ */
\ No newline at end of file

Reply via email to