From 2da2fba042f013e5a21b9abe39d5709e95db81f6 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Sun, 19 Jan 2025 21:26:19 +0900 Subject: [PATCH] [SHELL32][SHELL32_APITEST][SDK] Implement SHSetUnreadMailCountW (#7620) Implementing missing features... JIRA issue: CORE-19278 - Move function definition from stubs.cpp into utils.cpp. - Add prototype to . --- dll/win32/shell32/stubs.cpp | 13 ----- dll/win32/shell32/utils.cpp | 58 +++++++++++++++++++ .../rostests/apitests/shell32/CMakeLists.txt | 1 + .../shell32/SHSetUnreadMailCountW.cpp | 58 +++++++++++++++++++ modules/rostests/apitests/shell32/testlist.c | 2 + sdk/include/psdk/shellapi.h | 6 ++ 6 files changed, 125 insertions(+), 13 deletions(-) create mode 100644 modules/rostests/apitests/shell32/SHSetUnreadMailCountW.cpp diff --git a/dll/win32/shell32/stubs.cpp b/dll/win32/shell32/stubs.cpp index 5fec3d1e342..70918f6f18a 100644 --- a/dll/win32/shell32/stubs.cpp +++ b/dll/win32/shell32/stubs.cpp @@ -30,19 +30,6 @@ SHGetUnreadMailCountW(HKEY hKeyUser, return E_FAIL; } -/* - * Unimplemented - */ -EXTERN_C HRESULT -WINAPI -SHSetUnreadMailCountW(LPCWSTR pszMailAddress, - DWORD dwCount, - LPCWSTR pszShellExecuteCommand) -{ - FIXME("SHSetUnreadMailCountW() stub\n"); - return E_FAIL; -} - /* * Unimplemented */ diff --git a/dll/win32/shell32/utils.cpp b/dll/win32/shell32/utils.cpp index c1761021e18..575dadaa338 100644 --- a/dll/win32/shell32/utils.cpp +++ b/dll/win32/shell32/utils.cpp @@ -796,6 +796,64 @@ SHCreatePropertyBag(_In_ REFIID riid, _Out_ void **ppvObj) return SHCreatePropertyBagOnMemory(STGM_READWRITE, riid, ppvObj); } +/************************************************************************* + * SHSetUnreadMailCountW [SHELL32.336] + * + * @see https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shsetunreadmailcountw + */ +EXTERN_C +HRESULT WINAPI +SHSetUnreadMailCountW( + _In_ PCWSTR pszMailAddress, + _In_ DWORD dwCount, + _In_ PCWSTR pszShellExecuteCommand) +{ + CString strKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\UnreadMail"; + strKey += L'\\'; + strKey += pszMailAddress; + + HKEY hKey; + DWORD dwDisposition; + LSTATUS error = RegCreateKeyExW(HKEY_CURRENT_USER, strKey, 0, NULL, 0, KEY_SET_VALUE, NULL, + &hKey, &dwDisposition); + if (error) + return HRESULT_FROM_WIN32(error); + + error = RegSetValueExW(hKey, L"MessageCount", 0, REG_DWORD, (PBYTE)&dwCount, sizeof(dwCount)); + if (error) + { + RegCloseKey(hKey); + return HRESULT_FROM_WIN32(error); + } + + FILETIME FileTime; + GetSystemTimeAsFileTime(&FileTime); + + error = RegSetValueExW(hKey, L"TimeStamp", 0, REG_BINARY, (PBYTE)&FileTime, sizeof(FileTime)); + if (error) + { + RegCloseKey(hKey); + return HRESULT_FROM_WIN32(error); + } + + WCHAR szBuff[2 * MAX_PATH]; + if (!PathUnExpandEnvStringsW(pszShellExecuteCommand, szBuff, _countof(szBuff))) + { + HRESULT hr = StringCchCopyW(szBuff, _countof(szBuff), pszShellExecuteCommand); + if (FAILED_UNEXPECTEDLY(hr)) + { + RegCloseKey(hKey); + return hr; + } + } + + DWORD cbValue = (lstrlenW(szBuff) + 1) * sizeof(WCHAR); + error = RegSetValueExW(hKey, L"Application", 0, REG_SZ, (PBYTE)szBuff, cbValue); + + RegCloseKey(hKey); + return (error ? HRESULT_FROM_WIN32(error) : S_OK); +} + /************************************************************************* * SheRemoveQuotesA (SHELL32.@) */ diff --git a/modules/rostests/apitests/shell32/CMakeLists.txt b/modules/rostests/apitests/shell32/CMakeLists.txt index 39f1092027e..7a7b523a68d 100644 --- a/modules/rostests/apitests/shell32/CMakeLists.txt +++ b/modules/rostests/apitests/shell32/CMakeLists.txt @@ -45,6 +45,7 @@ list(APPEND SOURCE SHGetAttributesFromDataObject.cpp SHGetUserDisplayName.cpp SHLimitInputEdit.cpp + SHSetUnreadMailCountW.cpp menu.cpp shelltest.cpp) diff --git a/modules/rostests/apitests/shell32/SHSetUnreadMailCountW.cpp b/modules/rostests/apitests/shell32/SHSetUnreadMailCountW.cpp new file mode 100644 index 00000000000..413ecb34335 --- /dev/null +++ b/modules/rostests/apitests/shell32/SHSetUnreadMailCountW.cpp @@ -0,0 +1,58 @@ +/* + * PROJECT: ReactOS API tests + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) + * PURPOSE: Test for SHSetUnreadMailCountW + * COPYRIGHT: Copyright 2025 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) + */ + +#include "shelltest.h" + +START_TEST(SHSetUnreadMailCountW) +{ + HKEY hKey; + LSTATUS error; + DWORD dwDisposition; + error = RegCreateKeyExW(HKEY_CURRENT_USER, + L"Software\\Microsoft\\Windows\\CurrentVersion\\UnreadMail\\example.com", + 0, NULL, 0, KEY_WRITE, NULL, &hKey, &dwDisposition); + ok_long(error, ERROR_SUCCESS); + RegCloseKey(hKey); + + HRESULT hr = SHSetUnreadMailCountW(L"example.com", 1, L"MyMailerApp"); + ok_hex(hr, S_OK); + + error = RegOpenKeyExW(HKEY_CURRENT_USER, + L"Software\\Microsoft\\Windows\\CurrentVersion\\UnreadMail\\example.com", + 0, + KEY_READ, + &hKey); + ok_long(error, ERROR_SUCCESS); + + DWORD dwValue, cbValue = sizeof(dwValue); + error = RegQueryValueExW(hKey, L"MessageCount", NULL, NULL, (PBYTE)&dwValue, &cbValue); + ok_long(error, ERROR_SUCCESS); + ok_long(dwValue, 1); + + FILETIME FileTime; + cbValue = sizeof(FileTime); + error = RegQueryValueExW(hKey, L"TimeStamp", NULL, NULL, (PBYTE)&FileTime, &cbValue); + ok_long(error, ERROR_SUCCESS); + ok(FileTime.dwHighDateTime != 0, "FileTime.dwHighDateTime was zero\n"); + + WCHAR szValue[MAX_PATH]; + cbValue = sizeof(szValue); + error = RegQueryValueExW(hKey, L"Application", NULL, NULL, (PBYTE)szValue, &cbValue); + ok_long(error, ERROR_SUCCESS); + ok_wstr(szValue, L"MyMailerApp"); + + RegCloseKey(hKey); + + hr = SHSetUnreadMailCountW(L"example.com", 0, L"MyMailerApp"); + ok_hex(hr, S_OK); + + if (dwDisposition == REG_CREATED_NEW_KEY) + { + RegDeleteKeyW(HKEY_CURRENT_USER, + L"Software\\Microsoft\\Windows\\CurrentVersion\\UnreadMail\\example.com"); + } +} diff --git a/modules/rostests/apitests/shell32/testlist.c b/modules/rostests/apitests/shell32/testlist.c index 134f01a7838..d98d529c6fb 100644 --- a/modules/rostests/apitests/shell32/testlist.c +++ b/modules/rostests/apitests/shell32/testlist.c @@ -49,6 +49,7 @@ extern void func_SHParseDisplayName(void); extern void func_SHShouldShowWizards(void); extern void func_SHSimpleIDListFromPath(void); extern void func_SHRestricted(void); +extern void func_SHSetUnreadMailCountW(void); const struct test winetest_testlist[] = { @@ -98,6 +99,7 @@ const struct test winetest_testlist[] = { "SHShouldShowWizards", func_SHShouldShowWizards }, { "SHSimpleIDListFromPath", func_SHSimpleIDListFromPath }, { "SHRestricted", func_SHRestricted }, + { "SHSetUnreadMailCountW", func_SHSetUnreadMailCountW }, { 0, 0 } }; diff --git a/sdk/include/psdk/shellapi.h b/sdk/include/psdk/shellapi.h index 479d27d228d..eeda59cfcfb 100644 --- a/sdk/include/psdk/shellapi.h +++ b/sdk/include/psdk/shellapi.h @@ -638,6 +638,12 @@ DoEnvironmentSubstW( _Inout_updates_(cchSrc) LPWSTR pszSrc, UINT cchSrc); +HRESULT WINAPI +SHSetUnreadMailCountW( + _In_ PCWSTR pszMailAddress, + _In_ DWORD dwCount, + _In_ PCWSTR pszShellExecuteCommand); + #if (_WIN32_IE >= 0x0601) BOOL WINAPI