From 9959e4144f57e39ab4a9475a9142620d10572621 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Fri, 17 May 2019 14:28:20 +0300 Subject: [PATCH] kernelbase: Add some more string handling functions from shlwapi. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/kernelbase/kernelbase.spec | 24 +-- dlls/kernelbase/string.c | 302 ++++++++++++++++++++++++++++++++ 2 files changed, 314 insertions(+), 12 deletions(-) diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 02278fedd80..48276b8bcf9 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -130,7 +130,7 @@ # @ stub CheckTokenCapability @ stdcall CheckTokenMembership(long ptr ptr) advapi32.CheckTokenMembership # @ stub CheckTokenMembershipEx -@ stdcall ChrCmpIA(long long) shlwapi.ChrCmpIA +@ stdcall ChrCmpIA(long long) @ stdcall ChrCmpIW(long long) @ stdcall ClearCommBreak(long) kernel32.ClearCommBreak @ stdcall ClearCommError(long ptr ptr) kernel32.ClearCommError @@ -1532,9 +1532,9 @@ @ stdcall StrCatBuffA(str str long) shlwapi.StrCatBuffA @ stdcall StrCatBuffW(wstr wstr long) shlwapi.StrCatBuffW @ stdcall StrCatChainW(ptr long long wstr) shlwapi.StrCatChainW -@ stdcall StrChrA(str long) shlwapi.StrChrA +@ stdcall StrChrA(str long) # @ stub StrChrA_MB -@ stdcall StrChrIA(str long) shlwapi.StrChrIA +@ stdcall StrChrIA(str long) @ stdcall StrChrIW(wstr long) # @ stub StrChrNIW @ stdcall StrChrNW(wstr long long) @@ -1544,8 +1544,8 @@ @ stdcall StrCmpICA(str str) @ stdcall StrCmpICW(wstr wstr) @ stdcall StrCmpIW(wstr wstr) -@ stdcall StrCmpLogicalW(wstr wstr) shlwapi.StrCmpLogicalW -@ stdcall StrCmpNA(str str long) shlwapi.StrCmpNA +@ stdcall StrCmpLogicalW(wstr wstr) +@ stdcall StrCmpNA(str str long) @ stdcall StrCmpNCA(str ptr long) shlwapi.StrCmpNCA @ stdcall StrCmpNCW(wstr wstr long) shlwapi.StrCmpNCW @ stdcall StrCmpNIA(str str long) @@ -1559,9 +1559,9 @@ @ stdcall StrCpyNXW(ptr wstr long) @ stdcall StrDupA(str) @ stdcall StrDupW(wstr) -@ stdcall StrIsIntlEqualA(long str str long) shlwapi.StrIsIntlEqualA -@ stdcall StrIsIntlEqualW(long wstr wstr long) shlwapi.StrIsIntlEqualW -@ stdcall StrPBrkA(str str) shlwapi.StrPBrkA +@ stdcall StrIsIntlEqualA(long str str long) +@ stdcall StrIsIntlEqualW(long wstr wstr long) +@ stdcall StrPBrkA(str str) @ stdcall StrPBrkW(wstr wstr) @ stdcall StrRChrA(str str long) shlwapi.StrRChrA @ stdcall StrRChrIA(str str long) shlwapi.StrRChrIA @@ -1577,13 +1577,13 @@ @ stdcall StrStrNIW(wstr wstr long) @ stdcall StrStrNW(wstr wstr long) @ stdcall StrStrW(wstr wstr) -@ stdcall StrToInt64ExA(str long ptr) shlwapi.StrToInt64ExA +@ stdcall StrToInt64ExA(str long ptr) @ stdcall StrToInt64ExW(wstr long ptr) -@ stdcall StrToIntA(str) shlwapi.StrToIntA -@ stdcall StrToIntExA(str long ptr) shlwapi.StrToIntExA +@ stdcall StrToIntA(str) +@ stdcall StrToIntExA(str long ptr) @ stdcall StrToIntExW(wstr long ptr) @ stdcall StrToIntW(wstr) -@ stdcall StrTrimA(str str) shlwapi.StrTrimA +@ stdcall StrTrimA(str str) @ stdcall StrTrimW(wstr wstr) @ stdcall SubmitThreadpoolWork(ptr) kernel32.SubmitThreadpoolWork # @ stub SubscribeEdpEnabledStateChange diff --git a/dlls/kernelbase/string.c b/dlls/kernelbase/string.c index fb7bda88284..a858f3a51a6 100644 --- a/dlls/kernelbase/string.c +++ b/dlls/kernelbase/string.c @@ -37,6 +37,31 @@ static WORD get_char_type(WCHAR ch) return type; } +static BOOL char_compare(WORD ch1, WORD ch2, DWORD flags) +{ + char str1[3], str2[3]; + + str1[0] = LOBYTE(ch1); + if (IsDBCSLeadByte(str1[0])) + { + str1[1] = HIBYTE(ch1); + str1[2] = '\0'; + } + else + str1[1] = '\0'; + + str2[0] = LOBYTE(ch2); + if (IsDBCSLeadByte(str2[0])) + { + str2[1] = HIBYTE(ch2); + str2[2] = '\0'; + } + else + str2[1] = '\0'; + + return CompareStringA(GetThreadLocale(), flags, str1, -1, str2, -1) - CSTR_EQUAL; +} + DWORD WINAPI StrCmpCA(const char *str, const char *cmp) { return lstrcmpA(str, cmp); @@ -151,6 +176,23 @@ BOOL WINAPI IsCharUpperW(WCHAR ch) return !!(get_char_type(ch) & C1_UPPER); } +char * WINAPI StrChrA(const char *str, WORD ch) +{ + TRACE("%s, %#x\n", wine_dbgstr_a(str), ch); + + if (!str) + return NULL; + + while (*str) + { + if (!char_compare(*str, ch, 0)) + return (char *)str; + str = CharNextA(str); + } + + return NULL; +} + WCHAR * WINAPI StrChrW(const WCHAR *str, WCHAR ch) { TRACE("%s, %#x\n", wine_dbgstr_w(str), ch); @@ -161,6 +203,23 @@ WCHAR * WINAPI StrChrW(const WCHAR *str, WCHAR ch) return strchrW(str, ch); } +char * WINAPI StrChrIA(const char *str, WORD ch) +{ + TRACE("%s, %i\n", wine_dbgstr_a(str), ch); + + if (!str) + return NULL; + + while (*str) + { + if (!ChrCmpIA(*str, ch)) + return (char *)str; + str = CharNextA(str); + } + + return NULL; +} + WCHAR * WINAPI StrChrIW(const WCHAR *str, WCHAR ch) { TRACE("%s, %#x\n", wine_dbgstr_w(str), ch); @@ -239,6 +298,13 @@ WCHAR * WINAPI StrDupW(const WCHAR *str) return ret; } +BOOL WINAPI ChrCmpIA(WORD ch1, WORD ch2) +{ + TRACE("%#x, %#x\n", ch1, ch2); + + return char_compare(ch1, ch2, NORM_IGNORECASE); +} + BOOL WINAPI ChrCmpIW(WCHAR ch1, WCHAR ch2) { return CompareStringW(GetThreadLocale(), NORM_IGNORECASE, &ch1, 1, &ch2, 1) - CSTR_EQUAL; @@ -300,6 +366,12 @@ WCHAR * WINAPI StrStrNIW(const WCHAR *str, const WCHAR *search, UINT max_len) return NULL; } +int WINAPI StrCmpNA(const char *str, const char *comp, int len) +{ + TRACE("%s, %s, %i\n", wine_dbgstr_a(str), wine_dbgstr_a(comp), len); + return CompareStringA(GetThreadLocale(), 0, str, len, comp, len) - CSTR_EQUAL; +} + int WINAPI StrCmpNW(const WCHAR *str, const WCHAR *comp, int len) { TRACE("%s, %s, %i\n", wine_dbgstr_w(str), wine_dbgstr_w(comp), len); @@ -401,12 +473,67 @@ WCHAR * WINAPI StrRChrIW(const WCHAR *str, const WCHAR *end, WORD ch) return ret; } +char * WINAPI StrPBrkA(const char *str, const char *match) +{ + TRACE("%s, %s\n", wine_dbgstr_a(str), wine_dbgstr_a(match)); + + if (!str || !match || !*match) + return NULL; + + while (*str) + { + if (StrChrA(match, *str)) + return (char *)str; + str = CharNextA(str); + } + + return NULL; +} + WCHAR * WINAPI StrPBrkW(const WCHAR *str, const WCHAR *match) { if (!str || !match) return NULL; return strpbrkW(str, match); } +BOOL WINAPI StrTrimA(char *str, const char *trim) +{ + unsigned int len; + BOOL ret = FALSE; + char *ptr = str; + + TRACE("%s, %s\n", debugstr_a(str), debugstr_a(trim)); + + if (!str || !*str) + return FALSE; + + while (*ptr && StrChrA(trim, *ptr)) + ptr = CharNextA(ptr); /* Skip leading matches */ + + len = strlen(ptr); + + if (ptr != str) + { + memmove(str, ptr, len + 1); + ret = TRUE; + } + + if (len > 0) + { + ptr = str + len; + while (StrChrA(trim, ptr[-1])) + ptr = CharPrevA(str, ptr); /* Skip trailing matches */ + + if (ptr != str + len) + { + *ptr = '\0'; + ret = TRUE; + } + } + + return ret; +} + BOOL WINAPI StrTrimW(WCHAR *str, const WCHAR *trim) { unsigned int len; @@ -445,6 +572,68 @@ BOOL WINAPI StrTrimW(WCHAR *str, const WCHAR *trim) return ret; } +BOOL WINAPI StrToInt64ExA(const char *str, DWORD flags, LONGLONG *ret) +{ + BOOL negative = FALSE; + LONGLONG value = 0; + + TRACE("%s, %#x, %p\n", wine_dbgstr_a(str), flags, ret); + + if (!str || !ret) + return FALSE; + + if (flags > STIF_SUPPORT_HEX) + WARN("Unknown flags %#x\n", flags); + + /* Skip leading space, '+', '-' */ + while (isspace(*str)) + str = CharNextA(str); + + if (*str == '-') + { + negative = TRUE; + str++; + } + else if (*str == '+') + str++; + + if (flags & STIF_SUPPORT_HEX && *str == '0' && tolower(str[1]) == 'x') + { + /* Read hex number */ + str += 2; + + if (!isxdigit(*str)) + return FALSE; + + while (isxdigit(*str)) + { + value *= 16; + if (isdigit(*str)) + value += (*str - '0'); + else + value += 10 + (tolower(*str) - 'a'); + str++; + } + + *ret = value; + return TRUE; + } + + /* Read decimal number */ + if (!isdigit(*str)) + return FALSE; + + while (isdigit(*str)) + { + value *= 10; + value += (*str - '0'); + str++; + } + + *ret = negative ? -value : value; + return TRUE; +} + BOOL WINAPI StrToInt64ExW(const WCHAR *str, DWORD flags, LONGLONG *ret) { BOOL negative = FALSE; @@ -507,6 +696,18 @@ BOOL WINAPI StrToInt64ExW(const WCHAR *str, DWORD flags, LONGLONG *ret) return TRUE; } +BOOL WINAPI StrToIntExA(const char *str, DWORD flags, INT *ret) +{ + LONGLONG value; + BOOL res; + + TRACE("%s, %#x, %p\n", wine_dbgstr_a(str), flags, ret); + + res = StrToInt64ExA(str, flags, &value); + if (res) *ret = value; + return res; +} + BOOL WINAPI StrToIntExW(const WCHAR *str, DWORD flags, INT *ret) { LONGLONG value; @@ -519,6 +720,21 @@ BOOL WINAPI StrToIntExW(const WCHAR *str, DWORD flags, INT *ret) return res; } +int WINAPI StrToIntA(const char *str) +{ + int value = 0; + + TRACE("%s\n", wine_dbgstr_a(str)); + + if (!str) + return 0; + + if (*str == '-' || isdigit(*str)) + StrToIntExA(str, 0, &value); + + return value; +} + int WINAPI StrToIntW(const WCHAR *str) { int value = 0; @@ -818,3 +1034,89 @@ INT WINAPI DECLSPEC_HOTPATCH LoadStringA(HINSTANCE instance, UINT resource_id, L TRACE("returning %s\n", debugstr_a(buffer)); return retval; } + +int WINAPI StrCmpLogicalW(const WCHAR *str, const WCHAR *comp) +{ + TRACE("%s, %s\n", wine_dbgstr_w(str), wine_dbgstr_w(comp)); + + if (!str || !comp) + return 0; + + while (*str) + { + if (!*comp) + return 1; + else if (isdigitW(*str)) + { + int str_value, comp_value; + + if (!isdigitW(*comp)) + return -1; + + /* Compare the numbers */ + StrToIntExW(str, 0, &str_value); + StrToIntExW(comp, 0, &comp_value); + + if (str_value < comp_value) + return -1; + else if (str_value > comp_value) + return 1; + + /* Skip */ + while (isdigitW(*str)) + str++; + while (isdigitW(*comp)) + comp++; + } + else if (isdigitW(*comp)) + return 1; + else + { + int diff = ChrCmpIW(*str, *comp); + if (diff > 0) + return 1; + else if (diff < 0) + return -1; + + str++; + comp++; + } + } + + if (*comp) + return -1; + + return 0; +} + +BOOL WINAPI StrIsIntlEqualA(BOOL case_sensitive, const char *str, const char *cmp, int len) +{ + DWORD flags; + + TRACE("%d, %s, %s, %d\n", case_sensitive, wine_dbgstr_a(str), wine_dbgstr_a(cmp), len); + + /* FIXME: This flag is undocumented and unknown by our CompareString. + * We need a define for it. + */ + flags = 0x10000000; + if (!case_sensitive) + flags |= NORM_IGNORECASE; + + return (CompareStringA(GetThreadLocale(), flags, str, len, cmp, len) == CSTR_EQUAL); +} + +BOOL WINAPI StrIsIntlEqualW(BOOL case_sensitive, const WCHAR *str, const WCHAR *cmp, int len) +{ + DWORD flags; + + TRACE("%d, %s, %s, %d\n", case_sensitive, debugstr_w(str), debugstr_w(cmp), len); + + /* FIXME: This flag is undocumented and unknown by our CompareString. + * We need a define for it. + */ + flags = 0x10000000; + if (!case_sensitive) + flags |= NORM_IGNORECASE; + + return (CompareStringW(GetThreadLocale(), flags, str, len, cmp, len) == CSTR_EQUAL); +}