From fcbcaa10a76c6f5d5f972c842d1b8b1a5a23a30b Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Fri, 17 Jan 2025 09:33:52 +0900 Subject: [PATCH] [SHELL32][SHELL32_APITEST][SDK] Implement SHGetUserDisplayName (#7612) Implemementing missing features... JIRA issue: CORE-19278 - Add netapi32 and secur32 delay importing. - Move function definition from stubs.cpp into utils.cpp. - Include some security headers in utils.cpp. - Adapt to C++. - Add prototype to . --- dll/win32/shell32/CMakeLists.txt | 2 +- dll/win32/shell32/stubs.cpp | 12 ---- dll/win32/shell32/utils.cpp | 65 +++++++++++++++++++ .../rostests/apitests/shell32/CMakeLists.txt | 1 + .../apitests/shell32/SHGetUserDisplayName.cpp | 30 +++++++++ modules/rostests/apitests/shell32/testlist.c | 2 + sdk/include/psdk/secext.h | 11 +++- sdk/include/reactos/undocshell.h | 5 ++ 8 files changed, 114 insertions(+), 14 deletions(-) create mode 100644 modules/rostests/apitests/shell32/SHGetUserDisplayName.cpp diff --git a/dll/win32/shell32/CMakeLists.txt b/dll/win32/shell32/CMakeLists.txt index 258191318b6..81df5d528ab 100644 --- a/dll/win32/shell32/CMakeLists.txt +++ b/dll/win32/shell32/CMakeLists.txt @@ -120,7 +120,7 @@ set_source_files_properties(shell32.rc PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT set_module_type(shell32 win32dll UNICODE) target_link_libraries(shell32 shellmenu shelldesktop wine uuid recyclebin cpprt atl_classes oldnames) -add_delay_importlibs(shell32 powrprof shdocvw devmgr winspool.drv winmm mpr uxtheme ole32 oleaut32 userenv browseui version fmifs) +add_delay_importlibs(shell32 powrprof shdocvw devmgr winspool.drv winmm mpr uxtheme ole32 oleaut32 userenv browseui version fmifs netapi32 secur32) add_importlibs(shell32 advapi32 gdi32 user32 comctl32 comdlg32 shlwapi msvcrt kernel32 ntdll) add_dependencies(shell32 stdole2) # shell32_shldisp.tlb needs stdole2.tlb add_pch(shell32 precomp.h "${PCH_SKIP_SOURCE}") diff --git a/dll/win32/shell32/stubs.cpp b/dll/win32/shell32/stubs.cpp index 77e674e795f..fa022eb6c07 100644 --- a/dll/win32/shell32/stubs.cpp +++ b/dll/win32/shell32/stubs.cpp @@ -920,18 +920,6 @@ PathIsSlowW( return FALSE; } -/* - * Unimplemented - */ -EXTERN_C DWORD -WINAPI -SHGetUserDisplayName(LPWSTR lpName, PULONG puSize) -{ - FIXME("SHGetUserDisplayName() stub\n"); - wcscpy(lpName, L"UserName"); - return ERROR_SUCCESS; -} - /* * Unimplemented */ diff --git a/dll/win32/shell32/utils.cpp b/dll/win32/shell32/utils.cpp index 440d22f6460..21e97461c52 100644 --- a/dll/win32/shell32/utils.cpp +++ b/dll/win32/shell32/utils.cpp @@ -6,6 +6,10 @@ */ #include "precomp.h" +#include +#include +#include +#include WINE_DEFAULT_DEBUG_CHANNEL(shell); @@ -1485,3 +1489,64 @@ SHELL_CreateShell32DefaultExtractIcon(int IconIndex, REFIID riid, LPVOID *ppvOut initIcon->SetNormalIcon(swShell32Name, IconIndex); return initIcon->QueryInterface(riid, ppvOut); } + +/************************************************************************* + * SHGetUserDisplayName [SHELL32.241] + * + * @see https://undoc.airesoft.co.uk/shell32.dll/SHGetUserDisplayName.php + */ +EXTERN_C +HRESULT WINAPI +SHGetUserDisplayName( + _Out_writes_to_(*puSize, *puSize) PWSTR pName, + _Inout_ PULONG puSize) +{ + if (!pName || !puSize) + return E_INVALIDARG; + + if (GetUserNameExW(NameDisplay, pName, puSize)) + return S_OK; + + LONG error = GetLastError(); // for ERROR_NONE_MAPPED + HRESULT hr = HRESULT_FROM_WIN32(error); + + WCHAR UserName[MAX_PATH]; + DWORD cchUserName = _countof(UserName); + if (!GetUserNameW(UserName, &cchUserName)) + return HRESULT_FROM_WIN32(GetLastError()); + + // Was the user name not available in the specified format (NameDisplay)? + if (error == ERROR_NONE_MAPPED) + { + // Try to get the user name by using Network API + PUSER_INFO_2 UserInfo; + DWORD NetError = NetUserGetInfo(NULL, UserName, 2, (PBYTE*)&UserInfo); + if (NetError) + { + hr = HRESULT_FROM_WIN32(NetError); + } + else + { + if (UserInfo->usri2_full_name) + { + hr = StringCchCopyW(pName, *puSize, UserInfo->usri2_full_name); + if (SUCCEEDED(hr)) + { + // Include the NUL-terminator + *puSize = lstrlenW(UserInfo->usri2_full_name) + 1; + } + } + + NetApiBufferFree(UserInfo); + } + } + + if (FAILED(hr)) + { + hr = StringCchCopyW(pName, *puSize, UserName); + if (SUCCEEDED(hr)) + *puSize = cchUserName; + } + + return hr; +} diff --git a/modules/rostests/apitests/shell32/CMakeLists.txt b/modules/rostests/apitests/shell32/CMakeLists.txt index 2a90a0e009d..cad67b40a19 100644 --- a/modules/rostests/apitests/shell32/CMakeLists.txt +++ b/modules/rostests/apitests/shell32/CMakeLists.txt @@ -41,6 +41,7 @@ list(APPEND SOURCE ShellInfo.cpp ShellState.cpp SHGetAttributesFromDataObject.cpp + SHGetUserDisplayName.cpp SHLimitInputEdit.cpp menu.cpp shelltest.cpp) diff --git a/modules/rostests/apitests/shell32/SHGetUserDisplayName.cpp b/modules/rostests/apitests/shell32/SHGetUserDisplayName.cpp new file mode 100644 index 00000000000..ed2fcc37587 --- /dev/null +++ b/modules/rostests/apitests/shell32/SHGetUserDisplayName.cpp @@ -0,0 +1,30 @@ +/* + * PROJECT: ReactOS API tests + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) + * PURPOSE: Test for SHGetUserDisplayName + * COPYRIGHT: Copyright 2025 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) + */ + +#include "shelltest.h" +#include + +START_TEST(SHGetUserDisplayName) +{ + HRESULT hr; + WCHAR szBuf[MAX_PATH]; + ULONG cchBuf; + + hr = SHGetUserDisplayName(NULL, NULL); + ok_hex(hr, E_INVALIDARG); + + hr = SHGetUserDisplayName(szBuf, NULL); + ok_hex(hr, E_INVALIDARG); + + cchBuf = _countof(szBuf); + hr = SHGetUserDisplayName(NULL, &cchBuf); + ok_hex(hr, E_INVALIDARG); + + cchBuf = _countof(szBuf); + hr = SHGetUserDisplayName(szBuf, &cchBuf); + ok_hex(hr, S_OK); +} diff --git a/modules/rostests/apitests/shell32/testlist.c b/modules/rostests/apitests/shell32/testlist.c index ff06c5a5dc6..87f924f9f23 100644 --- a/modules/rostests/apitests/shell32/testlist.c +++ b/modules/rostests/apitests/shell32/testlist.c @@ -42,6 +42,7 @@ extern void func_ShellHook(void); extern void func_ShellState(void); extern void func_SHGetAttributesFromDataObject(void); extern void func_SHGetFileInfo(void); +extern void func_SHGetUserDisplayName(void); extern void func_SHLimitInputEdit(void); extern void func_SHParseDisplayName(void); extern void func_SHSimpleIDListFromPath(void); @@ -88,6 +89,7 @@ const struct test winetest_testlist[] = { "ShellState", func_ShellState }, { "SHGetAttributesFromDataObject", func_SHGetAttributesFromDataObject }, { "SHGetFileInfo", func_SHGetFileInfo }, + { "SHGetUserDisplayName", func_SHGetUserDisplayName }, { "SHLimitInputEdit", func_SHLimitInputEdit }, { "SHParseDisplayName", func_SHParseDisplayName }, { "SHSimpleIDListFromPath", func_SHSimpleIDListFromPath }, diff --git a/sdk/include/psdk/secext.h b/sdk/include/psdk/secext.h index b60399241ee..d9397113171 100644 --- a/sdk/include/psdk/secext.h +++ b/sdk/include/psdk/secext.h @@ -1,8 +1,13 @@ #ifndef _SECEXT_H #define _SECEXT_H +#ifdef __cplusplus +extern "C" { +#endif + #ifndef RC_INVOKED #if (_WIN32_WINNT >= 0x0500) + typedef enum { NameUnknown = 0, @@ -34,7 +39,11 @@ BOOLEAN WINAPI TranslateNameW(LPCWSTR,EXTENDED_NAME_FORMAT,EXTENDED_NAME_FORMAT, #define TranslateName TranslateNameA #endif - #endif /* ! RC_INVOKED */ #endif /* _WIN32_WINNT >= 0x0500 */ + +#ifdef __cplusplus +} // extern "C" +#endif + #endif /* ! _SECEXT_H */ diff --git a/sdk/include/reactos/undocshell.h b/sdk/include/reactos/undocshell.h index f5bd2cd7f2e..76e78372dd1 100644 --- a/sdk/include/reactos/undocshell.h +++ b/sdk/include/reactos/undocshell.h @@ -211,6 +211,11 @@ DWORD WINAPI SHNetConnectionDialog( BOOL WINAPI SHIsTempDisplayMode(VOID); +HRESULT WINAPI +SHGetUserDisplayName( + _Out_writes_to_(*puSize, *puSize) PWSTR pName, + _Inout_ PULONG puSize); + /**************************************************************************** * Cabinet Window Messages */