[EXPLORER][SHELL32][SHELL32_APITEST][SDK] AppBar Part 2 (#7946)

Follow-up of #7778.
JIRA issue: CORE-7237
- Rename APPBARDATA3264 structure
  as APPBARDATAINTEROP.
- Fix structures for WoW64.
- Use trace instead of DPRINT1.
- Add CAppBarManager::
  RecomputeAllWorkareas function.
- Fix WM_DISPLAYCHANGE handling
  to re-compute the work areas.
This commit is contained in:
Katayama Hirofumi MZ 2025-05-05 12:48:02 +09:00 committed by GitHub
parent 24c2e4433b
commit 7073bdfead
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 71 additions and 30 deletions

View file

@ -130,7 +130,7 @@ void CAppBarManager::OnAppBarQueryPos(_Inout_ PAPPBAR_COMMAND pData)
return;
}
PAPPBARDATA3264 pOutput = AppBar_LockOutput(pData);
PAPPBARDATAINTEROP pOutput = AppBar_LockOutput(pData);
if (!pOutput)
{
ERR("!pOutput: %d\n", pData->dwProcessId);
@ -187,7 +187,7 @@ void CAppBarManager::OnAppBarSetPos(_Inout_ PAPPBAR_COMMAND pData)
OnAppBarQueryPos(pData);
PAPPBARDATA3264 pOutput = AppBar_LockOutput(pData);
PAPPBARDATAINTEROP pOutput = AppBar_LockOutput(pData);
if (!pOutput)
return;
@ -425,6 +425,31 @@ CAppBarManager::RecomputeWorkArea(
return WORKAREA_SAME_AS_MONITOR;
}
BOOL CALLBACK
CAppBarManager::MonitorEnumProc(
_In_ HMONITOR hMonitor,
_In_ HDC hDC,
_In_ LPRECT prc,
_Inout_ LPARAM lParam)
{
CAppBarManager *pThis = (CAppBarManager *)lParam;
UNREFERENCED_PARAMETER(hDC);
RECT rcWorkArea;
if (pThis->RecomputeWorkArea(prc, hMonitor, &rcWorkArea) != WORKAREA_IS_NOT_MONITOR)
return TRUE;
HWND hwndDesktop = pThis->GetDesktopWnd();
::SystemParametersInfoW(SPI_SETWORKAREA, 0, &rcWorkArea, hwndDesktop ? SPIF_SENDCHANGE : 0);
pThis->RedrawDesktop(hwndDesktop, &rcWorkArea);
return TRUE;
}
void CAppBarManager::RecomputeAllWorkareas()
{
::EnumDisplayMonitors(NULL, NULL, CAppBarManager::MonitorEnumProc, (LPARAM)this);
}
PAPPBAR_COMMAND
CAppBarManager::GetAppBarMessage(_Inout_ PCOPYDATASTRUCT pCopyData)
{

View file

@ -15,14 +15,14 @@ typedef struct tagAPPBAR
RECT rc;
} APPBAR, *PAPPBAR;
static inline PAPPBARDATA3264
static inline PAPPBARDATAINTEROP
AppBar_LockOutput(_In_ PAPPBAR_COMMAND pData)
{
return (PAPPBARDATA3264)SHLockShared(UlongToHandle(pData->hOutput32), pData->dwProcessId);
return (PAPPBARDATAINTEROP)SHLockShared((HANDLE)pData->hOutput, pData->dwProcessId);
}
static inline VOID
AppBar_UnLockOutput(_Out_ PAPPBARDATA3264 pOutput)
AppBar_UnLockOutput(_Out_ PAPPBARDATAINTEROP pOutput)
{
SHUnlockShared(pOutput);
}
@ -77,6 +77,7 @@ protected:
_In_ const RECT *prcTray,
_In_ HMONITOR hMonitor,
_Out_ PRECT prcWorkArea);
void RecomputeAllWorkareas();
void StuckAppChange(
_In_opt_ HWND hwndTarget,
@ -93,4 +94,11 @@ protected:
virtual INT GetPosition() const = 0;
virtual const RECT* GetTrayRect() = 0;
virtual HWND GetDesktopWnd() const = 0;
static BOOL CALLBACK
MonitorEnumProc(
_In_ HMONITOR hMonitor,
_In_ HDC hDC,
_In_ LPRECT prc,
_Inout_ LPARAM lParam);
};

View file

@ -2492,6 +2492,9 @@ ChangePos:
LRESULT OnDisplayChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
/* Refresh workareas */
RecomputeAllWorkareas();
/* Load the saved tray window settings */
RegLoadSettings();

View file

@ -19,7 +19,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(appbar);
static UINT32
static HANDLE
AppBar_CopyIn(
_In_ const VOID *pvSrc,
_In_ SIZE_T dwSize,
@ -38,17 +38,16 @@ AppBar_CopyIn(
CopyMemory(pvDest, pvSrc, dwSize);
SHUnlockShared(pvDest);
return HandleToUlong(hMem);
return hMem;
}
static BOOL
AppBar_CopyOut(
_In_ UINT32 hOutput32,
_In_ HANDLE hOutput,
_Out_ PVOID pvDest,
_In_ SIZE_T cbDest,
_In_ DWORD dwProcessId)
{
HANDLE hOutput = UlongToHandle(hOutput32);
PVOID pvSrc = SHLockShared(hOutput, dwProcessId);
if (pvSrc)
{
@ -86,7 +85,7 @@ SHAppBarMessage(
cmd.abd.rc = pData->rc;
cmd.abd.lParam64 = pData->lParam;
cmd.dwMessage = dwMessage;
cmd.hOutput32 = 0;
cmd.hOutput = (APPBAR_OUTPUT)NULL;
cmd.dwProcessId = GetCurrentProcessId();
/* Make output data if necessary */
@ -95,8 +94,8 @@ SHAppBarMessage(
case ABM_QUERYPOS:
case ABM_SETPOS:
case ABM_GETTASKBARPOS:
cmd.hOutput32 = AppBar_CopyIn(&cmd.abd, sizeof(cmd.abd), cmd.dwProcessId);
if (!cmd.hOutput32)
cmd.hOutput = (APPBAR_OUTPUT)AppBar_CopyIn(&cmd.abd, sizeof(cmd.abd), cmd.dwProcessId);
if (!cmd.hOutput)
{
ERR("AppBar_CopyIn: %d\n", dwMessage);
return FALSE;
@ -111,9 +110,9 @@ SHAppBarMessage(
UINT_PTR ret = SendMessageW(hTrayWnd, WM_COPYDATA, (WPARAM)pData->hWnd, (LPARAM)&copyData);
/* Copy back output data */
if (cmd.hOutput32)
if (cmd.hOutput)
{
if (!AppBar_CopyOut(cmd.hOutput32, &cmd.abd, sizeof(cmd.abd), cmd.dwProcessId))
if (!AppBar_CopyOut((HANDLE)cmd.hOutput, &cmd.abd, sizeof(cmd.abd), cmd.dwProcessId))
{
ERR("AppBar_CopyOut: %d\n", dwMessage);
return FALSE;

View file

@ -10,9 +10,6 @@
#include <shlwapi.h>
#include <stdio.h>
#define NDEBUG
#include <debug.h>
/* Based on https://github.com/katahiromz/AppBarSample */
//#define VERBOSE
@ -469,9 +466,6 @@ protected:
case ABE_RIGHT:
rc.left = rc.right - m_cxWidth;
break;
default:
ASSERT(FALSE);
break;
}
APPBARDATA abd = { sizeof(abd) };
@ -688,7 +682,7 @@ protected:
AppBar_Register(hwnd);
AppBar_SetSide(hwnd, ABE_TOP);
DPRINT1("OnCreate(%p) done\n", hwnd);
trace("OnCreate(%p) done\n", hwnd);
return TRUE;
}
@ -984,7 +978,7 @@ public:
RECT rc1, rc2, rcWork;
DWORD dwTID = GetWindowThreadProcessId(s_hwnd1, NULL);
DPRINT1("DoAction\n");
trace("DoAction\n");
Sleep(INTERVAL);
GetWindowRect(s_hwnd1, &rc1);
@ -1136,7 +1130,7 @@ START_TEST(SHAppBarMessage)
return;
}
DPRINT1("SM_CMONITORS: %d\n", GetSystemMetrics(SM_CMONITORS));
trace("SM_CMONITORS: %d\n", GetSystemMetrics(SM_CMONITORS));
if (GetSystemMetrics(SM_CMONITORS) != 1)
{
skip("Multi-monitor not supported yet\n");
@ -1144,8 +1138,8 @@ START_TEST(SHAppBarMessage)
}
SystemParametersInfo(SPI_GETWORKAREA, 0, &s_rcWorkArea, FALSE);
DPRINT1("s_rcWorkArea: %d, %d, %d, %d\n",
s_rcWorkArea.left, s_rcWorkArea.top, s_rcWorkArea.right, s_rcWorkArea.bottom);
trace("s_rcWorkArea: %ld, %ld, %ld, %ld\n",
s_rcWorkArea.left, s_rcWorkArea.top, s_rcWorkArea.right, s_rcWorkArea.bottom);
HWND hwnd1 = Window::DoCreateMainWnd(hInstance, TEXT("Test1"), 80, 80,
WS_POPUP | WS_THICKFRAME | WS_CLIPCHILDREN);

View file

@ -1222,32 +1222,44 @@ typedef struct SFVM_CUSTOMVIEWINFO_DATA
#include <poppack.h>
#if defined(_WIN64) || defined(BUILD_WOW6432)
typedef UINT64 APPBAR_OUTPUT;
#else
typedef HANDLE APPBAR_OUTPUT;
#endif
/*
* Private structures for internal AppBar messaging.
* These structures can be sent from 32-bit shell32 to 64-bit Explorer.
* See also: https://learn.microsoft.com/en-us/windows/win32/winprog64/interprocess-communication
* > ... only the lower 32 bits are significant, so it is safe to truncate the handle
* See also: https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-duplicatehandle
* > DuplicateHandle can be used to duplicate a handle between a 32-bit process and a 64-bit process.
*/
#include <pshpack8.h>
typedef struct tagAPPBARDATA3264
typedef struct tagAPPBARDATAINTEROP
{
DWORD cbSize; /* == sizeof(APPBARDATA3264) */
DWORD cbSize; /* == sizeof(APPBARDATAINTEROP) */
UINT32 hWnd32;
UINT uCallbackMessage;
UINT uEdge;
RECT rc;
LONGLONG lParam64;
} APPBARDATA3264, *PAPPBARDATA3264;
} APPBARDATAINTEROP, *PAPPBARDATAINTEROP;
typedef struct tagAPPBAR_COMMAND
{
APPBARDATA3264 abd;
APPBARDATAINTEROP abd;
DWORD dwMessage;
UINT32 hOutput32; /* For shlwapi!SHAllocShared */
APPBAR_OUTPUT hOutput; /* For shlwapi!SHAllocShared */
DWORD dwProcessId;
} APPBAR_COMMAND, *PAPPBAR_COMMAND;
#include <poppack.h>
#if defined(_WIN64) || defined(BUILD_WOW6432)
C_ASSERT(sizeof(APPBAR_COMMAND) == 0x40);
#else
C_ASSERT(sizeof(APPBAR_COMMAND) == 0x38);
#endif
#ifdef __cplusplus
} /* extern "C" */