diff --git a/dll/win32/shell32/precomp.h b/dll/win32/shell32/precomp.h index 84bb7e49dc5..9ae77f4b794 100644 --- a/dll/win32/shell32/precomp.h +++ b/dll/win32/shell32/precomp.h @@ -45,6 +45,19 @@ #undef ShellExecute #include +/* + * 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 #include diff --git a/dll/win32/shell32/shell32.spec b/dll/win32/shell32/shell32.spec index f24256761af..110ac17c69c 100644 --- a/dll/win32/shell32/shell32.spec +++ b/dll/win32/shell32/shell32.spec @@ -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) diff --git a/dll/win32/shell32/wine/shellord.c b/dll/win32/shell32/wine/shellord.c index 8cbdb2a4da4..ab0969a157b 100644 --- a/dll/win32/shell32/wine/shellord.c +++ b/dll/win32/shell32/wine/shellord.c @@ -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 } /************************************************************************* diff --git a/dll/win32/shlwapi/ordinal.c b/dll/win32/shlwapi/ordinal.c index 431ec51d2e1..b8b93a60372 100644 --- a/dll/win32/shlwapi/ordinal.c +++ b/dll/win32/shlwapi/ordinal.c @@ -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); diff --git a/sdk/include/psdk/shellapi.h b/sdk/include/psdk/shellapi.h index b4a5ecb4f78..77e3fc5b62c 100644 --- a/sdk/include/psdk/shellapi.h +++ b/sdk/include/psdk/shellapi.h @@ -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, diff --git a/sdk/include/reactos/shlwapi_undoc.h b/sdk/include/reactos/shlwapi_undoc.h index 08af85972d7..a56ed24ed9d 100644 --- a/sdk/include/reactos/shlwapi_undoc.h +++ b/sdk/include/reactos/shlwapi_undoc.h @@ -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) */