[SHELL32][SHELL32_APITEST][SDK] Implement SHGetUnreadMailCountW (#7622)

Implementing missing features...
JIRA issue: CORE-19278
- Modify shell32.spec.
- Move function definition from stubs.cpp into utils.cpp.
- Add SHELL_ReadSingleUnreadMailCount helper function.
- Add prototype to <shellapi.h>.
This commit is contained in:
Katayama Hirofumi MZ 2025-01-20 09:51:27 +09:00 committed by GitHub
parent 157e18b215
commit 84607161b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 211 additions and 17 deletions

View file

@ -317,7 +317,7 @@
317 stdcall SHGetSpecialFolderLocation(long long ptr)
318 stdcall SHGetSpecialFolderPathA(long ptr long long)
319 stdcall SHGetSpecialFolderPathW(long ptr long long)
320 stdcall SHGetUnreadMailCountW (long wstr long ptr wstr long)
320 stdcall SHGetUnreadMailCountW(ptr wstr ptr ptr ptr long)
321 stdcall SHHelpShortcuts_RunDLL(long long long long) SHHelpShortcuts_RunDLLA
322 stdcall SHHelpShortcuts_RunDLLA(long long long long)
323 stdcall SHHelpShortcuts_RunDLLW(long long long long)

View file

@ -14,22 +14,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(shell);
/*
* Unimplemented
*/
EXTERN_C HRESULT
WINAPI
SHGetUnreadMailCountW(HKEY hKeyUser,
LPCWSTR pszMailAddress,
DWORD *pdwCount,
FILETIME *pFileTime,
LPWSTR pszShellExecuteCommand,
int cchShellExecuteCommand)
{
FIXME("SHGetUnreadMailCountW() stub\n");
return E_FAIL;
}
/*
* Unimplemented
*/

View file

@ -878,6 +878,123 @@ SHCreatePropertyBag(_In_ REFIID riid, _Out_ void **ppvObj)
return SHCreatePropertyBagOnMemory(STGM_READWRITE, riid, ppvObj);
}
// The helper function for SHGetUnreadMailCountW
static DWORD
SHELL_ReadSingleUnreadMailCount(
_In_ HKEY hKey,
_Out_opt_ PDWORD pdwCount,
_Out_opt_ PFILETIME pFileTime,
_Out_writes_opt_(cchShellExecuteCommand) LPWSTR pszShellExecuteCommand,
_In_ INT cchShellExecuteCommand)
{
DWORD dwType, dwCount, cbSize = sizeof(dwCount);
DWORD error = SHQueryValueExW(hKey, L"MessageCount", 0, &dwType, &dwCount, &cbSize);
if (error)
return error;
if (pdwCount && dwType == REG_DWORD)
*pdwCount = dwCount;
FILETIME FileTime;
cbSize = sizeof(FileTime);
error = SHQueryValueExW(hKey, L"TimeStamp", 0, &dwType, &FileTime, &cbSize);
if (error)
return error;
if (pFileTime && dwType == REG_BINARY)
*pFileTime = FileTime;
WCHAR szName[2 * MAX_PATH];
cbSize = sizeof(szName);
error = SHQueryValueExW(hKey, L"Application", 0, &dwType, szName, &cbSize);
if (error)
return error;
if (pszShellExecuteCommand && dwType == REG_SZ &&
FAILED(StringCchCopyW(pszShellExecuteCommand, cchShellExecuteCommand, szName)))
{
return ERROR_INSUFFICIENT_BUFFER;
}
return ERROR_SUCCESS;
}
/*************************************************************************
* SHGetUnreadMailCountW [SHELL32.320]
*
* @see https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shgetunreadmailcountw
*/
EXTERN_C
HRESULT WINAPI
SHGetUnreadMailCountW(
_In_opt_ HKEY hKeyUser,
_In_opt_ LPCWSTR pszMailAddress,
_Out_opt_ PDWORD pdwCount,
_Inout_opt_ PFILETIME pFileTime,
_Out_writes_opt_(cchShellExecuteCommand) LPWSTR pszShellExecuteCommand,
_In_ INT cchShellExecuteCommand)
{
LSTATUS error;
HKEY hKey;
if (!hKeyUser)
hKeyUser = HKEY_CURRENT_USER;
if (pszMailAddress)
{
CStringW strKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\UnreadMail";
strKey += L'\\';
strKey += pszMailAddress;
error = RegOpenKeyExW(hKeyUser, strKey, 0, KEY_QUERY_VALUE, &hKey);
if (error)
return HRESULT_FROM_WIN32(error);
error = SHELL_ReadSingleUnreadMailCount(hKey, pdwCount, pFileTime,
pszShellExecuteCommand, cchShellExecuteCommand);
}
else
{
if (pszShellExecuteCommand || cchShellExecuteCommand)
return E_INVALIDARG;
*pdwCount = 0;
error = RegOpenKeyExW(hKeyUser, L"Software\\Microsoft\\Windows\\CurrentVersion\\UnreadMail",
0, KEY_ENUMERATE_SUB_KEYS, &hKey);
if (error)
return HRESULT_FROM_WIN32(error);
for (DWORD dwIndex = 0; !error; ++dwIndex)
{
WCHAR Name[2 * MAX_PATH];
DWORD cchName = _countof(Name);
FILETIME LastWritten;
error = RegEnumKeyExW(hKey, dwIndex, Name, &cchName, NULL, NULL, NULL, &LastWritten);
if (error)
break;
HKEY hSubKey;
error = RegOpenKeyExW(hKey, Name, 0, KEY_QUERY_VALUE, &hSubKey);
if (error)
break;
FILETIME FileTime;
DWORD dwCount;
error = SHELL_ReadSingleUnreadMailCount(hSubKey, &dwCount, &FileTime, NULL, 0);
if (!error && (!pFileTime || CompareFileTime(&FileTime, pFileTime) >= 0))
*pdwCount += dwCount;
RegCloseKey(hSubKey);
}
if (error == ERROR_NO_MORE_ITEMS)
error = ERROR_SUCCESS;
}
RegCloseKey(hKey);
return error ? HRESULT_FROM_WIN32(error) : S_OK;
}
/*************************************************************************
* SHSetUnreadMailCountW [SHELL32.336]
*

View file

@ -31,6 +31,7 @@ list(APPEND SOURCE
SHCreateDataObject.cpp
SHCreateFileDataObject.cpp
SHCreateFileExtractIconW.cpp
SHGetUnreadMailCountW.cpp
SHParseDisplayName.cpp
SHRestricted.cpp
SHShouldShowWizards.cpp

View file

@ -0,0 +1,81 @@
/*
* PROJECT: ReactOS API tests
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Test for SHGetUnreadMailCountW
* COPYRIGHT: Copyright 2025 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/
#include "shelltest.h"
static VOID SetUnreadMailInfo(PDWORD pdwDisposition)
{
HKEY hKey;
LSTATUS error = RegCreateKeyExW(
HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\UnreadMail\\example.com",
0, NULL, 0, KEY_WRITE, NULL, &hKey, pdwDisposition);
ok_long(error, ERROR_SUCCESS);
DWORD dwCount = 1;
error = SHSetValueW(hKey, NULL, L"MessageCount", REG_DWORD, &dwCount, sizeof(dwCount));
ok_long(error, ERROR_SUCCESS);
FILETIME FileTime;
GetSystemTimeAsFileTime(&FileTime);
error = SHSetValueW(hKey, NULL, L"TimeStamp", REG_BINARY, &FileTime, sizeof(FileTime));
ok_long(error, ERROR_SUCCESS);
LPCWSTR pszApp = L"MyMailerApp";
DWORD cbValue = (lstrlenW(pszApp) + 1) * sizeof(WCHAR);
error = SHSetValueW(hKey, NULL, L"Application", REG_SZ, pszApp, cbValue);
ok_long(error, ERROR_SUCCESS);
RegCloseKey(hKey);
}
START_TEST(SHGetUnreadMailCountW)
{
HRESULT hr;
DWORD dwDisposition;
SetUnreadMailInfo(&dwDisposition);
hr = SHGetUnreadMailCountW(NULL, L"example.com", NULL, NULL, NULL, 0);
ok_hex(hr, S_OK);
FILETIME FileTime;
ZeroMemory(&FileTime, sizeof(FileTime));
hr = SHGetUnreadMailCountW(HKEY_CURRENT_USER, L"example.com", NULL, &FileTime, NULL, 0);
ok_hex(hr, S_OK);
ok(FileTime.dwHighDateTime != 0, "FileTime.dwHighDateTime was zero\n");
DWORD dwCount = 0;
ZeroMemory(&FileTime, sizeof(FileTime));
hr = SHGetUnreadMailCountW(NULL, NULL, &dwCount, &FileTime, NULL, 0);
ok_hex(hr, S_OK);
ok_long(dwCount, 1);
ok_long(FileTime.dwHighDateTime, 0);
dwCount = 0;
hr = SHGetUnreadMailCountW(NULL, L"example.com", &dwCount, NULL, NULL, 0);
ok_hex(hr, S_OK);
ok_long(dwCount, 1);
hr = SHGetUnreadMailCountW(NULL, NULL, &dwCount, NULL, NULL, 0);
ok_hex(hr, S_OK);
WCHAR szAppName[MAX_PATH];
dwCount = 0;
hr = SHGetUnreadMailCountW(NULL, NULL, &dwCount, NULL, szAppName, _countof(szAppName));
ok_hex(hr, E_INVALIDARG);
ok_long(dwCount, 0);
hr = SHGetUnreadMailCountW(NULL, L"example.com", NULL, NULL, szAppName, _countof(szAppName));
ok_hex(hr, S_OK);
ok_wstr(szAppName, L"MyMailerApp");
if (dwDisposition == REG_CREATED_NEW_KEY)
{
RegDeleteKeyW(HKEY_CURRENT_USER,
L"Software\\Microsoft\\Windows\\CurrentVersion\\UnreadMail\\example.com");
}
}

View file

@ -44,6 +44,7 @@ extern void func_ShellHook(void);
extern void func_ShellState(void);
extern void func_SHGetAttributesFromDataObject(void);
extern void func_SHGetFileInfo(void);
extern void func_SHGetUnreadMailCountW(void);
extern void func_SHGetUserDisplayName(void);
extern void func_SHLimitInputEdit(void);
extern void func_SHParseDisplayName(void);
@ -96,6 +97,7 @@ const struct test winetest_testlist[] =
{ "ShellState", func_ShellState },
{ "SHGetAttributesFromDataObject", func_SHGetAttributesFromDataObject },
{ "SHGetFileInfo", func_SHGetFileInfo },
{ "SHGetUnreadMailCountW", func_SHGetUnreadMailCountW },
{ "SHGetUserDisplayName", func_SHGetUserDisplayName },
{ "SHLimitInputEdit", func_SHLimitInputEdit },
{ "SHParseDisplayName", func_SHParseDisplayName },

View file

@ -659,6 +659,15 @@ SHEnumerateUnreadMailAccountsW(
_Out_writes_(cchMailAddress) PWSTR pszMailAddress,
_In_ INT cchMailAddress);
HRESULT WINAPI
SHGetUnreadMailCountW(
_In_opt_ HKEY hKeyUser,
_In_opt_ LPCWSTR pszMailAddress,
_Out_opt_ PDWORD pdwCount,
_Inout_opt_ PFILETIME pFileTime,
_Out_writes_opt_(cchShellExecuteCommand) LPWSTR pszShellExecuteCommand,
_In_ INT cchShellExecuteCommand);
#ifdef UNICODE
#define NOTIFYICONDATA_V1_SIZE NOTIFYICONDATAW_V1_SIZE
#define NOTIFYICONDATA_V2_SIZE NOTIFYICONDATAW_V2_SIZE