mirror of
https://github.com/reactos/reactos.git
synced 2025-02-28 19:32:59 +00:00
[SHELL32][SHELL32_APITEST][SDK] SHGetComputerDisplayNameW (#7670)
Implementing missing features... JIRA issue: CORE-19278 - Modify shell32.spec. - Move function definition from stubs.cpp to utils.cpp. - Implement SHGetComputerDisplayNameW function. - Add prototype to <undocshell.h>.
This commit is contained in:
parent
1b5f6c2dc0
commit
84df40a128
7 changed files with 321 additions and 8 deletions
|
@ -460,7 +460,7 @@
|
|||
749 stdcall -noname -version=0x501-0x502 SHGetShellStyleHInstance()
|
||||
750 stdcall -noname SHGetAttributesFromDataObject(ptr long ptr ptr)
|
||||
751 stub -noname SHSimulateDropOnClsid
|
||||
752 stdcall -noname SHGetComputerDisplayNameW(long long long long)
|
||||
752 stdcall -noname SHGetComputerDisplayNameW(wstr long ptr long)
|
||||
753 stdcall -noname CheckStagingArea()
|
||||
754 stub -noname SHLimitInputEditWithFlags
|
||||
755 stdcall -noname PathIsEqualOrSubFolder(wstr wstr)
|
||||
|
|
|
@ -820,10 +820,3 @@ DWORD WINAPI CheckStagingArea(VOID)
|
|||
/* Called by native explorer */
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXTERN_C
|
||||
DWORD WINAPI SHGetComputerDisplayNameW(DWORD param1, DWORD param2, DWORD param3, DWORD param4)
|
||||
{
|
||||
FIXME("SHGetComputerDisplayNameW() stub\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <lmcons.h>
|
||||
#include <lmapibuf.h>
|
||||
#include <lmaccess.h>
|
||||
#include <lmserver.h>
|
||||
#include <secext.h>
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(shell);
|
||||
|
@ -1893,3 +1894,149 @@ SHGetUserDisplayName(
|
|||
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Skip leading backslashes
|
||||
static PCWSTR
|
||||
SHELL_SkipServerSlashes(
|
||||
_In_ PCWSTR pszPath)
|
||||
{
|
||||
PCWSTR pch;
|
||||
for (pch = pszPath; *pch == L'\\'; ++pch)
|
||||
;
|
||||
return pch;
|
||||
}
|
||||
|
||||
// The registry key for server computer descriptions cache
|
||||
#define COMPUTER_DESCRIPTIONS_KEY \
|
||||
L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComputerDescriptions"
|
||||
|
||||
// Get server computer description from cache
|
||||
static HRESULT
|
||||
SHELL_GetCachedComputerDescription(
|
||||
_Out_writes_z_(cchDescMax) PWSTR pszDesc,
|
||||
_In_ DWORD cchDescMax,
|
||||
_In_ PCWSTR pszServerName)
|
||||
{
|
||||
cchDescMax *= sizeof(WCHAR);
|
||||
DWORD error = SHGetValueW(HKEY_CURRENT_USER, COMPUTER_DESCRIPTIONS_KEY,
|
||||
SHELL_SkipServerSlashes(pszServerName), NULL, pszDesc, &cchDescMax);
|
||||
return HRESULT_FROM_WIN32(error);
|
||||
}
|
||||
|
||||
// Do cache a server computer description
|
||||
static VOID
|
||||
SHELL_CacheComputerDescription(
|
||||
_In_ PCWSTR pszServerName,
|
||||
_In_ PCWSTR pszDesc)
|
||||
{
|
||||
if (!pszDesc)
|
||||
return;
|
||||
|
||||
SIZE_T cbDesc = (wcslen(pszDesc) + 1) * sizeof(WCHAR);
|
||||
SHSetValueW(HKEY_CURRENT_USER, COMPUTER_DESCRIPTIONS_KEY,
|
||||
SHELL_SkipServerSlashes(pszServerName), REG_SZ, pszDesc, (DWORD)cbDesc);
|
||||
}
|
||||
|
||||
// Get real server computer description
|
||||
static HRESULT
|
||||
SHELL_GetComputerDescription(
|
||||
_Out_writes_z_(cchDescMax) PWSTR pszDesc,
|
||||
_In_ SIZE_T cchDescMax,
|
||||
_In_ PWSTR pszServerName)
|
||||
{
|
||||
PSERVER_INFO_101 bufptr;
|
||||
NET_API_STATUS error = NetServerGetInfo(pszServerName, 101, (PBYTE*)&bufptr);
|
||||
HRESULT hr = (error > 0) ? HRESULT_FROM_WIN32(error) : error;
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr;
|
||||
|
||||
PCWSTR comment = bufptr->sv101_comment;
|
||||
if (comment && comment[0])
|
||||
StringCchCopyW(pszDesc, cchDescMax, comment);
|
||||
else
|
||||
hr = E_FAIL;
|
||||
|
||||
NetApiBufferFree(bufptr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Build computer display name
|
||||
static HRESULT
|
||||
SHELL_BuildDisplayMachineName(
|
||||
_Out_writes_z_(cchNameMax) PWSTR pszName,
|
||||
_In_ DWORD cchNameMax,
|
||||
_In_ PCWSTR pszServerName,
|
||||
_In_ PCWSTR pszDescription)
|
||||
{
|
||||
if (!pszDescription || !*pszDescription)
|
||||
return E_FAIL;
|
||||
|
||||
PCWSTR pszFormat = (SHRestricted(REST_ALLOWCOMMENTTOGGLE) ? L"%2 (%1)" : L"%1 (%2)");
|
||||
PCWSTR args[] = { pszDescription , SHELL_SkipServerSlashes(pszServerName) };
|
||||
return (FormatMessageW(FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_STRING,
|
||||
pszFormat, 0, 0, pszName, cchNameMax, (va_list *)args) ? S_OK : E_FAIL);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* SHGetComputerDisplayNameW [SHELL32.752]
|
||||
*/
|
||||
EXTERN_C
|
||||
HRESULT WINAPI
|
||||
SHGetComputerDisplayNameW(
|
||||
_In_opt_ PWSTR pszServerName,
|
||||
_In_ DWORD dwFlags,
|
||||
_Out_writes_z_(cchNameMax) PWSTR pszName,
|
||||
_In_ DWORD cchNameMax)
|
||||
{
|
||||
WCHAR szDesc[256], szCompName[MAX_COMPUTERNAME_LENGTH + 1];
|
||||
|
||||
// If no server name is specified, retrieve the local computer name
|
||||
if (!pszServerName)
|
||||
{
|
||||
// Use computer name as server name
|
||||
DWORD cchCompName = _countof(szCompName);
|
||||
if (!GetComputerNameW(szCompName, &cchCompName))
|
||||
return E_FAIL;
|
||||
pszServerName = szCompName;
|
||||
|
||||
// Don't use the cache for the local machine
|
||||
dwFlags |= SHGCDN_NOCACHE;
|
||||
}
|
||||
|
||||
// Get computer description from cache if necessary
|
||||
HRESULT hr = E_FAIL;
|
||||
if (!(dwFlags & SHGCDN_NOCACHE))
|
||||
hr = SHELL_GetCachedComputerDescription(szDesc, _countof(szDesc), pszServerName);
|
||||
|
||||
// Actually retrieve the computer description if it is not in the cache
|
||||
if (FAILED(hr))
|
||||
{
|
||||
hr = SHELL_GetComputerDescription(szDesc, _countof(szDesc), pszServerName);
|
||||
if (FAILED(hr))
|
||||
szDesc[0] = UNICODE_NULL;
|
||||
|
||||
// Cache the description if necessary
|
||||
if (!(dwFlags & SHGCDN_NOCACHE))
|
||||
SHELL_CacheComputerDescription(pszServerName, szDesc);
|
||||
}
|
||||
|
||||
// If getting the computer description failed, store the server name only
|
||||
if (FAILED(hr) || !szDesc[0])
|
||||
{
|
||||
if (dwFlags & SHGCDN_NOSERVERNAME)
|
||||
return hr; // Bail out if no server name is requested
|
||||
|
||||
StringCchCopyW(pszName, cchNameMax, SHELL_SkipServerSlashes(pszServerName));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// If no server name is requested, store the description only
|
||||
if (dwFlags & SHGCDN_NOSERVERNAME)
|
||||
{
|
||||
StringCchCopyW(pszName, cchNameMax, szDesc);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Build a string like "Description (SERVERNAME)"
|
||||
return SHELL_BuildDisplayMachineName(pszName, cchNameMax, pszServerName, szDesc);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ list(APPEND SOURCE
|
|||
SHCreateDataObject.cpp
|
||||
SHCreateFileDataObject.cpp
|
||||
SHCreateFileExtractIconW.cpp
|
||||
SHGetComputerDisplayNameW.cpp
|
||||
SHGetUnreadMailCountW.cpp
|
||||
SHIsBadInterfacePtr.cpp
|
||||
SHParseDisplayName.cpp
|
||||
|
|
159
modules/rostests/apitests/shell32/SHGetComputerDisplayNameW.cpp
Normal file
159
modules/rostests/apitests/shell32/SHGetComputerDisplayNameW.cpp
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* PROJECT: ReactOS API Tests
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Tests for SHGetComputerDisplayNameW
|
||||
* COPYRIGHT: Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#include "shelltest.h"
|
||||
#include <lmserver.h>
|
||||
#include <undocshell.h>
|
||||
#include <strsafe.h>
|
||||
#include <versionhelpers.h>
|
||||
|
||||
typedef HRESULT (WINAPI *FN_SHGetComputerDisplayNameW)(PWSTR, DWORD, PWSTR, DWORD);
|
||||
typedef NET_API_STATUS (WINAPI *FN_NetServerGetInfo)(LPWSTR, DWORD, PBYTE*);
|
||||
typedef NET_API_STATUS (WINAPI *FN_NetApiBufferFree)(PVOID);
|
||||
|
||||
static FN_SHGetComputerDisplayNameW s_pSHGetComputerDisplayNameW = NULL;
|
||||
static FN_NetServerGetInfo s_pNetServerGetInfo = NULL;
|
||||
static FN_NetApiBufferFree s_pNetApiBufferFree = NULL;
|
||||
|
||||
#define COMPUTER_DESCRIPTIONS_KEY \
|
||||
L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ComputerDescriptions"
|
||||
|
||||
static PCWSTR
|
||||
SHELL_SkipServerSlashes(
|
||||
_In_ PCWSTR pszPath)
|
||||
{
|
||||
PCWSTR pch;
|
||||
for (pch = pszPath; *pch == L'\\'; ++pch)
|
||||
;
|
||||
return pch;
|
||||
}
|
||||
|
||||
static VOID
|
||||
SHELL_CacheComputerDescription(
|
||||
_In_ PCWSTR pszServerName,
|
||||
_In_ PCWSTR pszDesc)
|
||||
{
|
||||
if (!pszDesc)
|
||||
return;
|
||||
|
||||
SIZE_T cbDesc = (wcslen(pszDesc) + 1) * sizeof(WCHAR);
|
||||
SHSetValueW(HKEY_CURRENT_USER, COMPUTER_DESCRIPTIONS_KEY,
|
||||
SHELL_SkipServerSlashes(pszServerName), REG_SZ, pszDesc, (DWORD)cbDesc);
|
||||
}
|
||||
|
||||
static HRESULT
|
||||
SHELL_GetCachedComputerDescription(
|
||||
_Out_writes_z_(cchDescMax) PWSTR pszDesc,
|
||||
_In_ DWORD cchDescMax,
|
||||
_In_ PCWSTR pszServerName)
|
||||
{
|
||||
cchDescMax *= sizeof(WCHAR);
|
||||
DWORD error = SHGetValueW(HKEY_CURRENT_USER, COMPUTER_DESCRIPTIONS_KEY,
|
||||
SHELL_SkipServerSlashes(pszServerName), NULL, pszDesc, &cchDescMax);
|
||||
return HRESULT_FROM_WIN32(error);
|
||||
}
|
||||
|
||||
static HRESULT
|
||||
SHELL_BuildDisplayMachineName(
|
||||
_Out_writes_z_(cchNameMax) PWSTR pszName,
|
||||
_In_ DWORD cchNameMax,
|
||||
_In_ PCWSTR pszServerName,
|
||||
_In_ PCWSTR pszDescription)
|
||||
{
|
||||
if (!pszDescription || !*pszDescription)
|
||||
return E_FAIL;
|
||||
|
||||
PCWSTR pszFormat = (SHRestricted(REST_ALLOWCOMMENTTOGGLE) ? L"%2 (%1)" : L"%1 (%2)");
|
||||
PCWSTR args[] = { pszDescription , SHELL_SkipServerSlashes(pszServerName) };
|
||||
return (FormatMessageW(FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_STRING,
|
||||
pszFormat, 0, 0, pszName, cchNameMax, (va_list *)args) ? S_OK : E_FAIL);
|
||||
}
|
||||
|
||||
static VOID
|
||||
TEST_SHGetComputerDisplayNameW(VOID)
|
||||
{
|
||||
WCHAR szCompName[MAX_COMPUTERNAME_LENGTH + 1], szDesc[256], szDisplayName[MAX_PATH];
|
||||
WCHAR szName[MAX_PATH], szServerName[] = L"DummyServerName";
|
||||
|
||||
DWORD cchCompName = _countof(szCompName);
|
||||
BOOL ret = GetComputerNameW(szCompName, &cchCompName);
|
||||
ok_int(ret, TRUE);
|
||||
trace("%s\n", wine_dbgstr_w(szCompName));
|
||||
|
||||
SHELL_CacheComputerDescription(szServerName, L"DummyDescription");
|
||||
|
||||
HRESULT hr = SHELL_GetCachedComputerDescription(szDesc, _countof(szDesc), szServerName);
|
||||
if (FAILED(hr))
|
||||
szDesc[0] = UNICODE_NULL;
|
||||
trace("%s\n", wine_dbgstr_w(szDesc));
|
||||
|
||||
StringCchCopyW(szDisplayName, _countof(szDisplayName), L"@");
|
||||
hr = s_pSHGetComputerDisplayNameW(NULL, SHGCDN_NOCACHE, szDisplayName, _countof(szDisplayName));
|
||||
ok_hex(hr, S_OK);
|
||||
trace("%s\n", wine_dbgstr_w(szDisplayName));
|
||||
ok_wstr(szDisplayName, szCompName);
|
||||
|
||||
StringCchCopyW(szDisplayName, _countof(szDisplayName), L"@");
|
||||
hr = s_pSHGetComputerDisplayNameW(szServerName, 0, szDisplayName, _countof(szDisplayName));
|
||||
ok_hex(hr, S_OK);
|
||||
trace("%s\n", wine_dbgstr_w(szServerName));
|
||||
ok_wstr(szServerName, L"DummyServerName");
|
||||
|
||||
hr = SHELL_BuildDisplayMachineName(szName, _countof(szName), szServerName, szDesc);
|
||||
ok_hex(hr, S_OK);
|
||||
|
||||
trace("%s\n", wine_dbgstr_w(szDisplayName));
|
||||
trace("%s\n", wine_dbgstr_w(szName));
|
||||
ok_wstr(szDisplayName, szName);
|
||||
|
||||
// Delete registry value
|
||||
HKEY hKey;
|
||||
LSTATUS error = RegOpenKeyExW(HKEY_CURRENT_USER, COMPUTER_DESCRIPTIONS_KEY, 0, KEY_WRITE, &hKey);
|
||||
if (error == ERROR_SUCCESS)
|
||||
{
|
||||
RegDeleteValueW(hKey, L"DummyServerName");
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(SHGetComputerDisplayNameW)
|
||||
{
|
||||
if (IsWindowsVistaOrGreater())
|
||||
{
|
||||
skip("Tests on Vista+ will cause exception\n");
|
||||
return;
|
||||
}
|
||||
|
||||
HINSTANCE hShell32 = GetModuleHandleW(L"shell32.dll");
|
||||
s_pSHGetComputerDisplayNameW =
|
||||
(FN_SHGetComputerDisplayNameW)GetProcAddress(hShell32, MAKEINTRESOURCEA(752));
|
||||
if (!s_pSHGetComputerDisplayNameW)
|
||||
{
|
||||
skip("SHGetComputerDisplayNameW not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
HINSTANCE hNetApi32 = LoadLibraryW(L"netapi32.dll");
|
||||
if (!hNetApi32)
|
||||
{
|
||||
skip("netapi32.dll not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
s_pNetServerGetInfo = (FN_NetServerGetInfo)GetProcAddress(hNetApi32, "NetServerGetInfo");
|
||||
s_pNetApiBufferFree = (FN_NetApiBufferFree)GetProcAddress(hNetApi32, "NetApiBufferFree");
|
||||
if (!s_pNetServerGetInfo || !s_pNetApiBufferFree)
|
||||
{
|
||||
skip("NetServerGetInfo or NetApiBufferFree not found\n");
|
||||
FreeLibrary(hNetApi32);
|
||||
return;
|
||||
}
|
||||
|
||||
TEST_SHGetComputerDisplayNameW();
|
||||
|
||||
FreeLibrary(hNetApi32);
|
||||
}
|
|
@ -43,6 +43,7 @@ extern void func_ShellExecuteW(void);
|
|||
extern void func_ShellHook(void);
|
||||
extern void func_ShellState(void);
|
||||
extern void func_SHGetAttributesFromDataObject(void);
|
||||
extern void func_SHGetComputerDisplayNameW(void);
|
||||
extern void func_SHGetFileInfo(void);
|
||||
extern void func_SHGetUnreadMailCountW(void);
|
||||
extern void func_SHGetUserDisplayName(void);
|
||||
|
@ -97,6 +98,7 @@ const struct test winetest_testlist[] =
|
|||
{ "ShellHook", func_ShellHook },
|
||||
{ "ShellState", func_ShellState },
|
||||
{ "SHGetAttributesFromDataObject", func_SHGetAttributesFromDataObject },
|
||||
{ "SHGetComputerDisplayNameW", func_SHGetComputerDisplayNameW },
|
||||
{ "SHGetFileInfo", func_SHGetFileInfo },
|
||||
{ "SHGetUnreadMailCountW", func_SHGetUnreadMailCountW },
|
||||
{ "SHGetUserDisplayName", func_SHGetUserDisplayName },
|
||||
|
|
|
@ -966,6 +966,17 @@ CopyStreamUI(
|
|||
_Inout_opt_ IProgressDialog *pProgress,
|
||||
_In_opt_ DWORDLONG dwlSize);
|
||||
|
||||
// Flags for SHGetComputerDisplayNameW
|
||||
#define SHGCDN_NOCACHE 0x1
|
||||
#define SHGCDN_NOSERVERNAME 0x10000
|
||||
|
||||
HRESULT WINAPI
|
||||
SHGetComputerDisplayNameW(
|
||||
_In_opt_ LPWSTR pszServerName,
|
||||
_In_ DWORD dwFlags,
|
||||
_Out_writes_z_(cchNameMax) LPWSTR pszName,
|
||||
_In_ DWORD cchNameMax);
|
||||
|
||||
/*****************************************************************************
|
||||
* INVALID_FILETITLE_CHARACTERS
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue