mirror of
https://github.com/reactos/reactos.git
synced 2026-06-01 08:50:24 +08:00
[SHLWAPI][SHLWAPI_APITEST][SDK] Support CharLowerNoDBCSA/W and CharUpperNoDBCSA/W (#8920)
Implementing missing features... JIRA issue: CORE-19278 - Implement CharLowerNoDBCSA, CharLowerNoDBCSW, CharUpperNoDBCSA, and CharUpperNoDBCSW functions. - Modify shlwapi.spec. - Add prototypes into <shlwapi_undoc.h>. - Add CharUpperNoDBCS testcase.
This commit is contained in:
committed by
GitHub
parent
0cd3b555b1
commit
4e01961e20
@@ -448,10 +448,10 @@
|
||||
448 stdcall -noname FixSlashesAndColonW(wstr)
|
||||
449 stub -noname NextPathA
|
||||
450 stub -noname NextPathW
|
||||
451 stub -noname CharUpperNoDBCSA
|
||||
452 stub -noname CharUpperNoDBCSW
|
||||
453 stub -noname CharLowerNoDBCSA
|
||||
454 stub -noname CharLowerNoDBCSW
|
||||
451 stdcall -noname CharUpperNoDBCSA(str)
|
||||
452 stdcall -noname CharUpperNoDBCSW(wstr)
|
||||
453 stdcall -noname CharLowerNoDBCSA(str)
|
||||
454 stdcall -noname CharLowerNoDBCSW(wstr)
|
||||
455 stdcall -noname PathIsValidCharA(long long)
|
||||
456 stdcall -noname PathIsValidCharW(long long)
|
||||
457 stdcall -noname GetLongPathNameWrapW(wstr ptr long) kernel32.GetLongPathNameW
|
||||
|
||||
@@ -41,6 +41,64 @@ GetVersionMajorMinor()
|
||||
return MAKEWORD(HIBYTE(version), LOBYTE(version));
|
||||
}
|
||||
|
||||
static BOOL CharLowerNoDBCSAWorker(PSTR lpString, INT cchMax, BOOL bUppercase)
|
||||
{
|
||||
CHAR szBuff[MAX_PATH];
|
||||
INT cch;
|
||||
if (!lpString)
|
||||
return FALSE;
|
||||
cch = cchMax ? cchMax : lstrlenA(lpString);
|
||||
if (FAILED(StringCchCopyA(szBuff, _countof(szBuff), lpString)))
|
||||
return FALSE;
|
||||
return LCMapStringA(LOCALE_SYSTEM_DEFAULT, (bUppercase ? LCMAP_UPPERCASE : LCMAP_LOWERCASE),
|
||||
szBuff, cch, lpString, cch);
|
||||
}
|
||||
|
||||
static BOOL CharLowerNoDBCSWWorker(PWSTR lpString, INT cchMax, BOOL bUppercase)
|
||||
{
|
||||
WCHAR szDest[MAX_PATH];
|
||||
INT cch;
|
||||
if (!lpString)
|
||||
return FALSE;
|
||||
cch = cchMax ? cchMax : lstrlenW(lpString);
|
||||
if (FAILED(StringCchCopyW(szDest, _countof(szDest), lpString)))
|
||||
return FALSE;
|
||||
return LCMapStringW(LOCALE_SYSTEM_DEFAULT, (bUppercase ? LCMAP_UPPERCASE : LCMAP_LOWERCASE),
|
||||
szDest, cch, lpString, cch);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* CharLowerNoDBCSA [SHLWAPI.453]
|
||||
*/
|
||||
EXTERN_C PSTR WINAPI CharLowerNoDBCSA(_Inout_ PSTR lpString)
|
||||
{
|
||||
return CharLowerNoDBCSAWorker(lpString, 0, FALSE) ? lpString : NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* CharLowerNoDBCSW [SHLWAPI.454]
|
||||
*/
|
||||
EXTERN_C PWSTR WINAPI CharLowerNoDBCSW(_Inout_ PWSTR lpString)
|
||||
{
|
||||
return CharLowerNoDBCSWWorker(lpString, 0, FALSE) ? lpString : NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* CharUpperNoDBCSA [SHLWAPI.451]
|
||||
*/
|
||||
EXTERN_C PSTR WINAPI CharUpperNoDBCSA(_Inout_ PSTR lpString)
|
||||
{
|
||||
return CharLowerNoDBCSAWorker(lpString, 0, TRUE) ? lpString : NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* CharUpperNoDBCSW [SHLWAPI.452]
|
||||
*/
|
||||
EXTERN_C PWSTR WINAPI CharUpperNoDBCSW(_Inout_ PWSTR lpString)
|
||||
{
|
||||
return CharLowerNoDBCSWWorker(lpString, 0, TRUE) ? lpString : NULL;
|
||||
}
|
||||
|
||||
static HRESULT
|
||||
SHInvokeCommandOnContextMenuInternal(
|
||||
_In_opt_ HWND hWnd,
|
||||
|
||||
@@ -6,6 +6,7 @@ include_directories($<TARGET_FILE_DIR:shlwapi_resource_dll>)
|
||||
|
||||
list(APPEND SOURCE
|
||||
AssocQueryString.c
|
||||
CharUpperNoDBCS.cpp
|
||||
IShellFolderHelpers.cpp
|
||||
IsQSForward.cpp
|
||||
IStreamPidl.cpp
|
||||
|
||||
276
modules/rostests/apitests/shlwapi/CharUpperNoDBCS.cpp
Normal file
276
modules/rostests/apitests/shlwapi/CharUpperNoDBCS.cpp
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* PROJECT: ReactOS api tests
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Tests for CharUpperNoDBCSA/W and CharLowerNoDBCSA/W
|
||||
* COPYRIGHT: Copyright 2026 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
||||
*/
|
||||
|
||||
#include <apitest.h>
|
||||
#include <shlwapi.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
typedef PSTR (WINAPI *FN_CharLowerNoDBCSA)(PSTR);
|
||||
typedef PWSTR (WINAPI *FN_CharLowerNoDBCSW)(PWSTR);
|
||||
typedef PSTR (WINAPI *FN_CharUpperNoDBCSA)(PSTR);
|
||||
typedef PWSTR (WINAPI *FN_CharUpperNoDBCSW)(PWSTR);
|
||||
|
||||
static FN_CharLowerNoDBCSA g_fnCharLowerNoDBCSA = NULL;
|
||||
static FN_CharLowerNoDBCSW g_fnCharLowerNoDBCSW = NULL;
|
||||
static FN_CharUpperNoDBCSA g_fnCharUpperNoDBCSA = NULL;
|
||||
static FN_CharUpperNoDBCSW g_fnCharUpperNoDBCSW = NULL;
|
||||
|
||||
static void Test_CharUpperNoDBCSA(void)
|
||||
{
|
||||
// Basic ASCII lowercase → uppercase
|
||||
{
|
||||
char buf[] = "hello world";
|
||||
PSTR ret = g_fnCharUpperNoDBCSA(buf);
|
||||
ok(ret == buf, "ret was %p\n", ret);
|
||||
ok_str(buf, "HELLO WORLD");
|
||||
}
|
||||
|
||||
// Already uppercase → unchanged
|
||||
{
|
||||
char buf[] = "HELLO WORLD";
|
||||
g_fnCharUpperNoDBCSA(buf);
|
||||
ok_str(buf, "HELLO WORLD");
|
||||
}
|
||||
|
||||
// Mixed case
|
||||
{
|
||||
char buf[] = "Hello World";
|
||||
g_fnCharUpperNoDBCSA(buf);
|
||||
ok_str(buf, "HELLO WORLD");
|
||||
}
|
||||
|
||||
// Digits and symbols are unchanged
|
||||
{
|
||||
char buf[] = "abc123!@#";
|
||||
g_fnCharUpperNoDBCSA(buf);
|
||||
ok_str(buf, "ABC123!@#");
|
||||
}
|
||||
|
||||
// Empty string
|
||||
{
|
||||
char buf[] = "";
|
||||
PCSTR ret = g_fnCharUpperNoDBCSA(buf);
|
||||
ok(ret == NULL, "ret was not NULL.\n");
|
||||
ok_int(buf[0], ANSI_NULL);
|
||||
}
|
||||
|
||||
// NULL pointer → must return NULL without crashing
|
||||
{
|
||||
PSTR ret = g_fnCharUpperNoDBCSA(NULL);
|
||||
ok(ret == NULL, "ret was %p\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void Test_CharLowerNoDBCSA(void)
|
||||
{
|
||||
// Basic ASCII uppercase → lowercase
|
||||
{
|
||||
char buf[] = "HELLO WORLD";
|
||||
PSTR ret = g_fnCharLowerNoDBCSA(buf);
|
||||
ok(ret == buf, "ret was %p\n", ret);
|
||||
ok_str(buf, "hello world");
|
||||
}
|
||||
|
||||
// Already lowercase → unchanged
|
||||
{
|
||||
char buf[] = "hello world";
|
||||
g_fnCharLowerNoDBCSA(buf);
|
||||
ok_str(buf, "hello world");
|
||||
}
|
||||
|
||||
// Mixed case
|
||||
{
|
||||
char buf[] = "Hello World";
|
||||
g_fnCharLowerNoDBCSA(buf);
|
||||
ok_str(buf, "hello world");
|
||||
}
|
||||
|
||||
// Digits and symbols are unchanged
|
||||
{
|
||||
char buf[] = "ABC123!@#";
|
||||
g_fnCharLowerNoDBCSA(buf);
|
||||
ok_str(buf, "abc123!@#");
|
||||
}
|
||||
|
||||
// Empty string
|
||||
{
|
||||
char buf[] = "";
|
||||
PCSTR ret = g_fnCharLowerNoDBCSA(buf);
|
||||
ok(ret == NULL, "ret was not NULL.\n");
|
||||
ok_int(buf[0], ANSI_NULL);
|
||||
}
|
||||
|
||||
// NULL pointer → must return NULL without crashing
|
||||
{
|
||||
PSTR ret = g_fnCharLowerNoDBCSA(NULL);
|
||||
ok(ret == NULL, "ret was %p\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void Test_CharUpperNoDBCSW(void)
|
||||
{
|
||||
// Basic ASCII lowercase → uppercase (wide)
|
||||
{
|
||||
wchar_t buf[] = L"hello world";
|
||||
PWSTR ret = g_fnCharUpperNoDBCSW(buf);
|
||||
ok(ret == buf, "ret was %p\n", ret);
|
||||
ok_wstr(buf, L"HELLO WORLD");
|
||||
}
|
||||
|
||||
// Already uppercase → unchanged
|
||||
{
|
||||
wchar_t buf[] = L"HELLO WORLD";
|
||||
g_fnCharUpperNoDBCSW(buf);
|
||||
ok_wstr(buf, L"HELLO WORLD");
|
||||
}
|
||||
|
||||
// Mixed case
|
||||
{
|
||||
wchar_t buf[] = L"Hello World";
|
||||
g_fnCharUpperNoDBCSW(buf);
|
||||
ok_wstr(buf, L"HELLO WORLD");
|
||||
}
|
||||
|
||||
// Digits and symbols are unchanged
|
||||
{
|
||||
wchar_t buf[] = L"abc123!@#";
|
||||
g_fnCharUpperNoDBCSW(buf);
|
||||
ok_wstr(buf, L"ABC123!@#");
|
||||
}
|
||||
|
||||
// Empty string
|
||||
{
|
||||
wchar_t buf[] = L"";
|
||||
PCWSTR ret = g_fnCharUpperNoDBCSW(buf);
|
||||
ok(ret == NULL, "ret was not NULL.\n");
|
||||
ok_int(buf[0], UNICODE_NULL);
|
||||
}
|
||||
|
||||
// NULL pointer → must return NULL without crashing
|
||||
{
|
||||
PWSTR ret = g_fnCharUpperNoDBCSW(NULL);
|
||||
ok(ret == NULL, "ret was %p\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void Test_CharLowerNoDBCSW(void)
|
||||
{
|
||||
// Basic ASCII uppercase → lowercase (wide)
|
||||
{
|
||||
wchar_t buf[] = L"HELLO WORLD";
|
||||
PWSTR ret = g_fnCharLowerNoDBCSW(buf);
|
||||
ok(ret == buf, "ret was %p\n", ret);
|
||||
ok_wstr(buf, L"hello world");
|
||||
}
|
||||
|
||||
// Already lowercase → unchanged
|
||||
{
|
||||
wchar_t buf[] = L"hello world";
|
||||
g_fnCharLowerNoDBCSW(buf);
|
||||
ok_wstr(buf, L"hello world");
|
||||
}
|
||||
|
||||
// Mixed case
|
||||
{
|
||||
wchar_t buf[] = L"Hello World";
|
||||
g_fnCharLowerNoDBCSW(buf);
|
||||
ok_wstr(buf, L"hello world");
|
||||
}
|
||||
|
||||
// Digits and symbols are unchanged
|
||||
{
|
||||
wchar_t buf[] = L"ABC123!@#";
|
||||
g_fnCharLowerNoDBCSW(buf);
|
||||
ok_wstr(buf, L"abc123!@#");
|
||||
}
|
||||
|
||||
// Empty string
|
||||
{
|
||||
wchar_t buf[] = L"";
|
||||
PCWSTR ret = g_fnCharLowerNoDBCSW(buf);
|
||||
ok(ret == NULL, "ret was not NULL.\n");
|
||||
ok_int(buf[0], UNICODE_NULL);
|
||||
}
|
||||
|
||||
// NULL pointer → must return NULL without crashing
|
||||
{
|
||||
PWSTR ret = g_fnCharLowerNoDBCSW(NULL);
|
||||
ok(ret == NULL, "ret was %p\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
static void Test_RoundTrip(void)
|
||||
{
|
||||
{
|
||||
char upper[] = "Hello World 123";
|
||||
char lower[] = "Hello World 123";
|
||||
g_fnCharUpperNoDBCSA(upper); // "HELLO WORLD 123"
|
||||
g_fnCharLowerNoDBCSA(lower); // "hello world 123"
|
||||
|
||||
char rt1[] = "hello world 123";
|
||||
g_fnCharUpperNoDBCSA(rt1); // Lower then Upper → "HELLO WORLD 123"
|
||||
ok_str(rt1, upper);
|
||||
|
||||
char rt2[] = "HELLO WORLD 123";
|
||||
g_fnCharLowerNoDBCSA(rt2); // Upper then Lower → "hello world 123"
|
||||
ok_str(rt2, lower);
|
||||
}
|
||||
|
||||
{
|
||||
wchar_t upper[] = L"Hello World 123";
|
||||
wchar_t lower[] = L"Hello World 123";
|
||||
g_fnCharUpperNoDBCSW(upper);
|
||||
g_fnCharLowerNoDBCSW(lower);
|
||||
|
||||
wchar_t rt1[] = L"hello world 123";
|
||||
g_fnCharUpperNoDBCSW(rt1);
|
||||
ok_wstr(rt1, upper);
|
||||
|
||||
wchar_t rt2[] = L"HELLO WORLD 123";
|
||||
g_fnCharLowerNoDBCSW(rt2);
|
||||
ok_wstr(rt2, lower);
|
||||
}
|
||||
}
|
||||
|
||||
static void Test_NoDBCS(void)
|
||||
{
|
||||
BYTE buf[] = { 0x82, 'a', ANSI_NULL };
|
||||
g_fnCharUpperNoDBCSA((PSTR)buf);
|
||||
ok_int(buf[2], ANSI_NULL);
|
||||
}
|
||||
|
||||
START_TEST(CharUpperNoDBCS)
|
||||
{
|
||||
HINSTANCE hSHLWAPI = LoadLibraryW(L"shlwapi");
|
||||
if (!hSHLWAPI)
|
||||
{
|
||||
skip("shlwapi not found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
g_fnCharLowerNoDBCSA = (FN_CharLowerNoDBCSA)GetProcAddress(hSHLWAPI, MAKEINTRESOURCEA(453));
|
||||
g_fnCharLowerNoDBCSW = (FN_CharLowerNoDBCSW)GetProcAddress(hSHLWAPI, MAKEINTRESOURCEA(454));
|
||||
g_fnCharUpperNoDBCSA = (FN_CharUpperNoDBCSA)GetProcAddress(hSHLWAPI, MAKEINTRESOURCEA(451));
|
||||
g_fnCharUpperNoDBCSW = (FN_CharUpperNoDBCSW)GetProcAddress(hSHLWAPI, MAKEINTRESOURCEA(452));
|
||||
if (!g_fnCharLowerNoDBCSA || !g_fnCharLowerNoDBCSW ||
|
||||
!g_fnCharUpperNoDBCSA || !g_fnCharUpperNoDBCSW)
|
||||
{
|
||||
skip("CharUpperNoDBCSA/W or CharLowerNoDBCSA/W not found\n");
|
||||
FreeLibrary(hSHLWAPI);
|
||||
return;
|
||||
}
|
||||
|
||||
Test_CharUpperNoDBCSA();
|
||||
Test_CharLowerNoDBCSA();
|
||||
Test_CharUpperNoDBCSW();
|
||||
Test_CharLowerNoDBCSW();
|
||||
Test_RoundTrip();
|
||||
Test_NoDBCS();
|
||||
|
||||
FreeLibrary(hSHLWAPI);
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <apitest.h>
|
||||
|
||||
extern void func_AssocQueryString(void);
|
||||
extern void func_CharUpperNoDBCS(void);
|
||||
extern void func_PathFileExistsDefExtAndAttributesW(void);
|
||||
extern void func_PathFindOnPath(void);
|
||||
extern void func_IShellFolderHelpers(void);
|
||||
@@ -24,6 +25,7 @@ extern void func_StrToInt(void);
|
||||
const struct test winetest_testlist[] =
|
||||
{
|
||||
{ "AssocQueryString", func_AssocQueryString },
|
||||
{ "CharUpperNoDBCS", func_CharUpperNoDBCS },
|
||||
{ "PathFileExistsDefExtAndAttributesW", func_PathFileExistsDefExtAndAttributesW },
|
||||
{ "PathFindOnPath", func_PathFindOnPath },
|
||||
{ "IShellFolderHelpers", func_IShellFolderHelpers },
|
||||
|
||||
@@ -129,6 +129,11 @@ MayExecForward(
|
||||
_In_ VARIANT *pvaIn,
|
||||
_Inout_ VARIANT *pvaOut);
|
||||
|
||||
PSTR WINAPI CharLowerNoDBCSA(_Inout_ PSTR lpString);
|
||||
PWSTR WINAPI CharLowerNoDBCSW(_Inout_ PWSTR lpString);
|
||||
PSTR WINAPI CharUpperNoDBCSA(_Inout_ PSTR lpString);
|
||||
PWSTR WINAPI CharUpperNoDBCSW(_Inout_ PWSTR lpString);
|
||||
|
||||
HRESULT WINAPI IsQSForward(_In_opt_ REFGUID pguidCmdGroup, _In_ ULONG cCmds, _In_ OLECMD *prgCmds);
|
||||
BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild);
|
||||
HRESULT WINAPI SHForwardContextMenuMsg(IUnknown* pUnk, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult, BOOL useIContextMenu2);
|
||||
|
||||
Reference in New Issue
Block a user