[SHELL32][SHLWAPI] Forward shell32.ShellMessageBoxW directly to shlwapi.ShellMessageBoxWrapW. (#3179)

This makes ShellMessageBoxW use the correct implementation where the
text buffer size is dynamic, instead of having a too small hardcoded
size.

Fixes CORE-17271.
See also PR #3172 by Kyle Katarn, supplemented with some ideas from
Mark Jansen.

However we cannot straightforwardly implement ShellMessageBoxA around
ShellMessageBoxW, by converting some parameters from ANSI to UNICODE,
because there may be some variadic ANSI strings, associated with '%s'
printf-like formatters inside the format string, that would also need
to be converted; however there is no way for us to find these and perform
the conversion ourselves.
Therefore, we re-implement ShellMessageBoxA by doing a copy-paste ANSI
adaptation of the shlwapi.ShellMessageBoxWrapW function.

Note that, on Vista+ onwards, shlwapi implements both ShellMessageBoxA/W,
and shell32 directly forwards these exports to shlwapi, thus avoiding
these workarounds.

[PSDK] Explicily use WINAPIV for the variadic ShellMessageBoxA/W functions.

[INCLUDE/REACTOS] Add ShellMessageBoxWrapW in shlwapi_undoc.h .
This commit is contained in:
Hermès Bélusca-Maïto 2020-09-13 18:21:29 +02:00
parent 5077e400d5
commit 14599b0a37
No known key found for this signature in database
GPG Key ID: 3B2539C65E7B93D0
6 changed files with 132 additions and 4 deletions

View File

@ -45,6 +45,19 @@
#undef ShellExecute
#include <undocshell.h>
/*
* For versions < Vista+, redefine ShellMessageBoxW to ShellMessageBoxWrapW
* (this is needed to avoid a linker error). On Vista+ onwards, shell32.ShellMessageBoxW
* redirects to shlwapi.ShellMessageBoxW so the #define should not be needed.
*
* However our shell32 is built with _WIN32_WINNT set to 0x600 (Vista+),
* yet its exports (especially regarding ShellMessageBoxA/W) are Win2003
* compatible. So the #define is still needed, and the check be disabled.
*/
// #if (_WIN32_WINNT < 0x0600)
#define ShellMessageBoxW ShellMessageBoxWrapW
// #endif
#include <browseui_undoc.h>
#include <shellutils.h>

View File

@ -178,7 +178,7 @@
179 stdcall SHGetNewLinkInfoA(str str ptr long long)
180 stdcall SHGetNewLinkInfoW(wstr wstr ptr long long)
181 stdcall -noname RegisterShellHook(long long)
182 varargs ShellMessageBoxW(long long wstr wstr long)
182 varargs ShellMessageBoxW(long long wstr wstr long) shlwapi.ShellMessageBoxWrapW
183 varargs ShellMessageBoxA(long long str str long)
184 stdcall -noname ArrangeWindows(long long long long long)
185 stdcall -noname SHHandleDiskFull(ptr long)

View File

@ -331,12 +331,28 @@ BOOL WINAPI RegisterShellHook(
*
* See ShellMessageBoxA.
*
*/
#ifdef __REACTOS__
/*
* shell32.ShellMessageBoxW directly redirects to shlwapi.ShellMessageBoxWrapW,
* while shell32.ShellMessageBoxA is a copy-paste ANSI adaptation of the
* shlwapi.ShellMessageBoxWrapW function.
*
* From Vista+ onwards, all the implementation of ShellMessageBoxA/W that
* were existing in shell32 has been completely moved to shlwapi, so that
* shell32.ShellMessageBoxA and shell32.ShellMessageBoxW are redirections
* to the corresponding shlwapi functions.
*
*/
#else // !__REACTOS__
/*
* NOTE:
* shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
* because we can't forward to it in the .spec file since it's exported by
* ordinal. If you change the implementation here please update the code in
* shlwapi as well.
*/
// Wine version, broken.
int ShellMessageBoxW(
HINSTANCE hInstance,
HWND hWnd,
@ -358,12 +374,12 @@ int ShellMessageBoxW(
hInstance,hWnd,lpText,lpCaption,uType);
if (IS_INTRESOURCE(lpCaption))
LoadStringW(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
LoadStringW(hInstance, LOWORD(lpCaption), szTitle, ARRAY_SIZE(szTitle));
else
pszTitle = lpCaption;
if (IS_INTRESOURCE(lpText))
LoadStringW(hInstance, LOWORD(lpText), szText, sizeof(szText)/sizeof(szText[0]));
LoadStringW(hInstance, LOWORD(lpText), szText, ARRAY_SIZE(szText));
else
pszText = lpText;
@ -376,6 +392,7 @@ int ShellMessageBoxW(
LocalFree(pszTemp);
return ret;
}
#endif
/*************************************************************************
* ShellMessageBoxA [SHELL32.183]
@ -395,6 +412,18 @@ int ShellMessageBoxW(
* NOTES
* Exported by ordinal
*/
#ifdef __REACTOS__
/*
* Note that we cannot straightforwardly implement ShellMessageBoxA around
* ShellMessageBoxW, by converting some parameters from ANSI to UNICODE,
* because there may be some variadic ANSI strings, associated with '%s'
* printf-like formatters inside the format string, that would also need
* to be converted; however there is no way for us to find these and perform
* the conversion ourselves.
* Therefore, we re-implement ShellMessageBoxA by doing a copy-paste ANSI
* adaptation of the shlwapi.ShellMessageBoxWrapW function.
*/
#endif
int ShellMessageBoxA(
HINSTANCE hInstance,
HWND hWnd,
@ -403,6 +432,62 @@ int ShellMessageBoxA(
UINT uType,
...)
{
#ifdef __REACTOS__
CHAR *szText = NULL, szTitle[100];
LPCSTR pszText, pszTitle = szTitle;
LPSTR pszTemp;
__ms_va_list args;
int ret;
__ms_va_start(args, uType);
TRACE("(%p,%p,%p,%p,%08x)\n", hInstance, hWnd, lpText, lpCaption, uType);
if (IS_INTRESOURCE(lpCaption))
LoadStringA(hInstance, LOWORD(lpCaption), szTitle, ARRAY_SIZE(szTitle));
else
pszTitle = lpCaption;
if (IS_INTRESOURCE(lpText))
{
/* Retrieve the length of the Unicode string and obtain the maximum
* possible length for the corresponding ANSI string (not counting
* any possible NULL-terminator). */
const WCHAR *ptr;
UINT len = LoadStringW(hInstance, LOWORD(lpText), (LPWSTR)&ptr, 0);
len = WideCharToMultiByte(CP_ACP, 0, ptr, len,
NULL, 0, NULL, NULL);
if (len)
{
szText = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(CHAR));
if (szText) LoadStringA(hInstance, LOWORD(lpText), szText, len + 1);
}
pszText = szText;
if (!pszText) {
WARN("Failed to load id %d\n", LOWORD(lpText));
__ms_va_end(args);
return 0;
}
}
else
pszText = lpText;
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
pszText, 0, 0, (LPSTR)&pszTemp, 0, &args);
__ms_va_end(args);
ret = MessageBoxA(hWnd, pszTemp, pszTitle, uType | MB_SETFOREGROUND);
HeapFree(GetProcessHeap(), 0, szText);
LocalFree(pszTemp);
return ret;
#else // __REACTOS__
// Wine version, broken.
char szText[100],szTitle[100];
LPCSTR pszText = szText, pszTitle = szTitle;
LPSTR pszTemp;
@ -433,6 +518,7 @@ int ShellMessageBoxA(
ret = MessageBoxA(hWnd,pszTemp,pszTitle,uType);
LocalFree(pszTemp);
return ret;
#endif
}
/*************************************************************************

View File

@ -4803,11 +4803,25 @@ DWORD WINAPI GetUIVersion(void)
*
* See shell32.ShellMessageBoxW
*
#ifndef __REACTOS__
*
* NOTE:
* shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
* because we can't forward to it in the .spec file since it's exported by
* ordinal. If you change the implementation here please update the code in
* shell32 as well.
*
#else // __REACTOS__
*
* From Vista+ onwards, all the implementation of ShellMessageBoxA/W that
* were existing in shell32 has been completely moved to shlwapi, so that
* shell32.ShellMessageBoxA and shell32.ShellMessageBoxW are redirections
* to the corresponding shlwapi functions.
*
* For Win2003 compatibility, if you change the implementation here please
* update the code of ShellMessageBoxA in shell32 as well.
*
#endif
*/
INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText,
LPCWSTR lpCaption, UINT uType, ...)
@ -4823,7 +4837,7 @@ INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText,
TRACE("(%p,%p,%p,%p,%08x)\n", hInstance, hWnd, lpText, lpCaption, uType);
if (IS_INTRESOURCE(lpCaption))
LoadStringW(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
LoadStringW(hInstance, LOWORD(lpCaption), szTitle, ARRAY_SIZE(szTitle));
else
pszTitle = lpCaption;
@ -4852,6 +4866,9 @@ INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText,
__ms_va_end(args);
#ifdef __REACTOS__
uType |= MB_SETFOREGROUND;
#endif
ret = MessageBoxW(hWnd, pszTemp, pszTitle, uType);
HeapFree(GetProcessHeap(), 0, szText);

View File

@ -511,6 +511,7 @@ ShellAboutW(
_In_opt_ HICON hIcon);
int
WINAPIV
ShellMessageBoxA(
_In_opt_ HINSTANCE hAppInst,
_In_opt_ HWND hWnd,
@ -520,6 +521,7 @@ ShellMessageBoxA(
...);
int
WINAPIV
ShellMessageBoxW(
_In_opt_ HINSTANCE hAppInst,
_In_opt_ HWND hWnd,

View File

@ -120,6 +120,16 @@ INT WINAPI SHUnicodeToAnsi(LPCWSTR lpSrcStr, LPSTR lpDstStr, INT iLen);
PVOID WINAPI SHLockSharedEx(HANDLE hData, DWORD dwProcessId, BOOL bWriteAccess);
int
WINAPIV
ShellMessageBoxWrapW(
_In_opt_ HINSTANCE hAppInst,
_In_opt_ HWND hWnd,
_In_ LPCWSTR lpcText,
_In_opt_ LPCWSTR lpcTitle,
_In_ UINT fuStyle,
...);
#ifdef __cplusplus
} /* extern "C" */
#endif /* defined(__cplusplus) */