mirror of
https://github.com/reactos/reactos.git
synced 2024-11-24 12:03:31 +08:00
[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:
parent
5077e400d5
commit
14599b0a37
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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) */
|
||||
|
Loading…
Reference in New Issue
Block a user