diff --git a/dll/win32/shell32/CDefView.cpp b/dll/win32/shell32/CDefView.cpp index ebcfa7670904c..708ce00e060d0 100644 --- a/dll/win32/shell32/CDefView.cpp +++ b/dll/win32/shell32/CDefView.cpp @@ -36,6 +36,7 @@ #include "precomp.h" +#include #include #include @@ -153,6 +154,7 @@ class CDefView : SFVM_CUSTOMVIEWINFO_DATA m_viewinfo_data; HICON m_hMyComputerIcon; + HANDLE m_hUpdateStatusbarThread; private: HRESULT _MergeToolbar(); @@ -171,6 +173,8 @@ class CDefView : HRESULT IncludeObject(PCUITEMID_CHILD pidl); HRESULT OnDefaultCommand(); HRESULT OnStateChange(UINT uFlags); + static unsigned __stdcall _UpdateStatusbarProc(void *args); + void UpdateStatusbarWorker(HANDLE hThread); void UpdateStatusbar(); void CheckToolbar(); BOOL CreateList(); @@ -428,7 +432,9 @@ CDefView::CDefView() : m_cScrollDelay(0), m_isEditing(FALSE), m_isParentFolderSpecial(FALSE), - m_Destroyed(FALSE) + m_Destroyed(FALSE), + m_hMyComputerIcon(::LoadIconW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_COMPUTER_DESKTOP))), + m_hUpdateStatusbarThread(NULL) { ZeroMemory(&m_FolderSettings, sizeof(m_FolderSettings)); ZeroMemory(&m_sortInfo, sizeof(m_sortInfo)); @@ -437,8 +443,6 @@ CDefView::CDefView() : m_viewinfo_data.clrText = GetSysColor(COLOR_WINDOWTEXT); m_viewinfo_data.clrTextBack = GetSysColor(COLOR_WINDOW); m_viewinfo_data.hbmBack = NULL; - - m_hMyComputerIcon = LoadIconW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_COMPUTER_DESKTOP)); } CDefView::~CDefView() @@ -539,10 +543,9 @@ void CDefView::CheckToolbar() } } -void CDefView::UpdateStatusbar() +void CDefView::UpdateStatusbarWorker(HANDLE hThread) { - WCHAR szFormat[MAX_PATH] = {0}; - WCHAR szPartText[MAX_PATH] = {0}; + WCHAR szFormat[MAX_PATH], szPartText[MAX_PATH]; UINT cSelectedItems; cSelectedItems = m_ListView.GetSelectedCount(); @@ -571,12 +574,13 @@ void CDefView::UpdateStatusbar() /* If we have something selected then only count selected file sizes. */ if (cSelectedItems) - { uFileFlags = LVNI_SELECTED; - } while ((nItem = m_ListView.GetNextItem(nItem, uFileFlags)) >= 0) { + if (hThread != m_hUpdateStatusbarThread) + return; + PCUITEMID_CHILD pidl = _PidlByItem(nItem); uTotalFileSize += _ILGetFileSize(pidl, NULL, 0); @@ -589,18 +593,14 @@ void CDefView::UpdateStatusbar() /* Don't show the file size text if there is 0 bytes in the folder * OR we only have folders selected. */ + szPartText[0] = UNICODE_NULL; if ((cSelectedItems && !bIsOnlyFoldersSelected) || uTotalFileSize) - { StrFormatByteSizeW(uTotalFileSize, szPartText, _countof(szPartText)); - } - else - { - *szPartText = 0; - } m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 1, (LPARAM)szPartText, &lResult); /* If we are in a Recycle Bin folder then show no text for the location part. */ + szPartText[0] = UNICODE_NULL; if (!_ILIsBitBucket(m_pidlParent)) { LoadStringW(shell32_hInstance, IDS_MYCOMPUTER, szPartText, _countof(szPartText)); @@ -612,6 +612,38 @@ void CDefView::UpdateStatusbar() } } +unsigned __stdcall CDefView::_UpdateStatusbarProc(void *args) +{ + CDefView* pView = static_cast(args); + pView->UpdateStatusbarWorker(pView->m_hUpdateStatusbarThread); + pView->Release(); + return 0; +} + +void CDefView::UpdateStatusbar() +{ + HANDLE hOldThread = m_hUpdateStatusbarThread; + + AddRef(); + + // We have to initialize m_hUpdateStatusbarThread before the target thread begins. + // So, we use CREATE_SUSPENDED. + HANDLE hNewThread = reinterpret_cast(_beginthreadex(NULL, 0, _UpdateStatusbarProc, + this, CREATE_SUSPENDED, NULL)); + if (hNewThread) + { + m_hUpdateStatusbarThread = hNewThread; + ::ResumeThread(hNewThread); + + if (hOldThread) + ::CloseHandle(hOldThread); + } + else + { + Release(); + } +} + /********************************************************** * * ##### helperfunctions for initializing the view ##### @@ -2582,6 +2614,17 @@ HRESULT WINAPI CDefView::DestroyViewWindow() { TRACE("(%p)\n", this); + if (m_hUpdateStatusbarThread) + { + HANDLE hOldThread = m_hUpdateStatusbarThread; + + // Assigning NULL to m_hUpdateStatusbarThread will terminate the target thread immediately + m_hUpdateStatusbarThread = NULL; + ::WaitForSingleObject(hOldThread, INFINITE); + + ::CloseHandle(hOldThread); + } + /* Make absolutely sure all our UI is cleaned up */ UIActivate(SVUIA_DEACTIVATE);