From aedba8441af6dbe3da9bee501ecd74dce851b5a1 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Wed, 20 Nov 2019 10:00:26 +0900 Subject: [PATCH] [SHELL32] Improve UI of drive formatting (#2048) - Add stub window (StubWindow32) to the drive formatting dialog to avoid locked. - Separate the thread of drive formatting. - Move CStubWindow32 codes. CORE-12756 --- dll/win32/shell32/dialogs/fprop.cpp | 11 -- dll/win32/shell32/folders/CDrivesFolder.cpp | 125 ++++++++++++++++++-- dll/win32/shell32/precomp.h | 11 ++ 3 files changed, 127 insertions(+), 20 deletions(-) diff --git a/dll/win32/shell32/dialogs/fprop.cpp b/dll/win32/shell32/dialogs/fprop.cpp index 108f7e03aff..3cab59b1f3b 100644 --- a/dll/win32/shell32/dialogs/fprop.cpp +++ b/dll/win32/shell32/dialogs/fprop.cpp @@ -67,17 +67,6 @@ LoadPropSheetHandlers(LPCWSTR pwszPath, PROPSHEETHEADERW *pHeader, UINT cMaxPage return cPages; } -// CStubWindow32 --- The owner window of file property sheets. -// This window hides taskbar button of property sheet. -class CStubWindow32 : public CWindowImpl -{ -public: - DECLARE_WND_CLASS_EX(_T("StubWindow32"), 0, COLOR_WINDOWTEXT) - - BEGIN_MSG_MAP(CStubWindow32) - END_MSG_MAP() -}; - /************************************************************************* * * SH_ShowPropertiesDialog diff --git a/dll/win32/shell32/folders/CDrivesFolder.cpp b/dll/win32/shell32/folders/CDrivesFolder.cpp index 35f6a7d735a..53c1b94dbaa 100644 --- a/dll/win32/shell32/folders/CDrivesFolder.cpp +++ b/dll/win32/shell32/folders/CDrivesFolder.cpp @@ -4,7 +4,7 @@ * Copyright 1997 Marcus Meissner * Copyright 1998, 1999, 2002 Juergen Schmied * Copyright 2009 Andrew Hill - * Copyright 2017-2018 Katayama Hirofumi MZ + * Copyright 2017-2019 Katayama Hirofumi MZ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,6 +22,7 @@ */ #include +#include WINE_DEFAULT_DEBUG_CHANNEL (shell); @@ -141,6 +142,119 @@ static BOOL DoEjectDrive(const WCHAR *physical, UINT nDriveType, INT *pnStringID return bResult; } +// A callback function for finding the stub windows. +static BOOL CALLBACK +EnumStubProc(HWND hwnd, LPARAM lParam) +{ + CSimpleArray *pStubs = reinterpret_cast *>(lParam); + + WCHAR szClass[64]; + GetClassNameW(hwnd, szClass, _countof(szClass)); + + if (lstrcmpiW(szClass, L"StubWindow32") == 0) + { + pStubs->Add(hwnd); + } + + return TRUE; +} + +// Another callback function to find the owned window of the stub window. +static BOOL CALLBACK +EnumStubProc2(HWND hwnd, LPARAM lParam) +{ + HWND *phwnd = reinterpret_cast(lParam); + + if (phwnd[0] == GetWindow(hwnd, GW_OWNER)) + { + phwnd[1] = hwnd; + return FALSE; + } + + return TRUE; +} + +// Parameters for format_drive_thread function below. +struct THREAD_PARAMS +{ + UINT nDriveNumber; +}; + +static unsigned __stdcall format_drive_thread(void *args) +{ + THREAD_PARAMS *params = (THREAD_PARAMS *)args; + UINT nDriveNumber = params->nDriveNumber; + LONG_PTR nProp = nDriveNumber | 0x7F00; + + // Search the stub windows that already exist. + CSimpleArray old_stubs; + EnumWindows(EnumStubProc, (LPARAM)&old_stubs); + + for (INT n = 0; n < old_stubs.GetSize(); ++n) + { + HWND hwndStub = old_stubs[n]; + + // The target stub window has the prop. + if (GetPropW(hwndStub, L"DriveNumber") == (HANDLE)nProp) + { + // Found. + HWND ahwnd[2]; + ahwnd[0] = hwndStub; + ahwnd[1] = NULL; + EnumWindows(EnumStubProc2, (LPARAM)ahwnd); + + // Activate. + BringWindowToTop(ahwnd[1]); + + delete params; + return 0; + } + } + + // Create a stub window. + DWORD style = WS_DISABLED | WS_CLIPSIBLINGS | WS_CAPTION; + DWORD exstyle = WS_EX_WINDOWEDGE | WS_EX_APPWINDOW; + CStubWindow32 stub; + if (!stub.Create(NULL, NULL, NULL, style, exstyle)) + { + ERR("StubWindow32 creation failed\n"); + delete params; + return 0; + } + + // Add prop to the target stub window. + SetPropW(stub, L"DriveNumber", (HANDLE)nProp); + + // Do format. + SHFormatDrive(stub, nDriveNumber, SHFMT_ID_DEFAULT, 0); + + // Clean up. + RemovePropW(stub, L"DriveNumber"); + stub.DestroyWindow(); + delete params; + + return 0; +} + +static HRESULT DoFormatDrive(HWND hwnd, UINT nDriveNumber) +{ + THREAD_PARAMS *params = new THREAD_PARAMS; + params->nDriveNumber = nDriveNumber; + + // Create thread to avoid locked. + unsigned tid; + HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, format_drive_thread, params, 0, &tid); + if (hThread == NULL) + { + delete params; + return E_FAIL; + } + + CloseHandle(hThread); + + return S_OK; +} + HRESULT CALLBACK DrivesContextMenuCallback(IShellFolder *psf, HWND hwnd, IDataObject *pdtobj, @@ -226,14 +340,7 @@ HRESULT CALLBACK DrivesContextMenuCallback(IShellFolder *psf, { if (wParam == CMDID_FORMAT) { - /* do format */ - DWORD dwRet = SHFormatDrive(hwnd, szDrive[0] - 'A', SHFMT_ID_DEFAULT, 0); - switch (dwRet) - { - case SHFMT_ERROR: case SHFMT_CANCEL: case SHFMT_NOFORMAT: - hr = E_FAIL; - break; - } + hr = DoFormatDrive(hwnd, szDrive[0] - 'A'); } else if (wParam == CMDID_EJECT) { diff --git a/dll/win32/shell32/precomp.h b/dll/win32/shell32/precomp.h index c58886e49ef..071a5c7b160 100644 --- a/dll/win32/shell32/precomp.h +++ b/dll/win32/shell32/precomp.h @@ -126,4 +126,15 @@ AddPropSheetPageCallback(HPROPSHEETPAGE hPage, LPARAM lParam) HRESULT WINAPI Shell_DefaultContextMenuCallBack(IShellFolder *psf, IDataObject *pdtobj); +// CStubWindow32 --- The owner window of file property sheets. +// This window hides taskbar button of property sheet. +class CStubWindow32 : public CWindowImpl +{ +public: + DECLARE_WND_CLASS_EX(_T("StubWindow32"), 0, COLOR_WINDOWTEXT) + + BEGIN_MSG_MAP(CStubWindow32) + END_MSG_MAP() +}; + #endif /* _PRECOMP_H__ */