Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/kernelbase/kernelbase.spec | 52 +-- dlls/kernelbase/path.c | 560 +++++++++++++++++++++++++++++++- 2 files changed, 585 insertions(+), 27 deletions(-)
diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index d1bcea5593..e586f500a4 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -1060,20 +1060,20 @@ @ stdcall PathFileExistsW(wstr) shlwapi.PathFileExistsW @ stdcall PathFindExtensionA(str) @ stdcall PathFindExtensionW(wstr) -@ stdcall PathFindFileNameA(str) shlwapi.PathFindFileNameA -@ stdcall PathFindFileNameW(wstr) shlwapi.PathFindFileNameW +@ stdcall PathFindFileNameA(str) +@ stdcall PathFindFileNameW(wstr) @ stdcall PathFindNextComponentA(str) shlwapi.PathFindNextComponentA @ stdcall PathFindNextComponentW(wstr) shlwapi.PathFindNextComponentW -@ stdcall PathGetArgsA(str) shlwapi.PathGetArgsA -@ stdcall PathGetArgsW(wstr) shlwapi.PathGetArgsW -@ stdcall PathGetCharTypeA(long) shlwapi.PathGetCharTypeA -@ stdcall PathGetCharTypeW(long) shlwapi.PathGetCharTypeW -@ stdcall PathGetDriveNumberA(str) shlwapi.PathGetDriveNumberA -@ stdcall PathGetDriveNumberW(wstr) shlwapi.PathGetDriveNumberW -@ stdcall PathIsFileSpecA(str) shlwapi.PathIsFileSpecA -@ stdcall PathIsFileSpecW(wstr) shlwapi.PathIsFileSpecW -@ stdcall PathIsLFNFileSpecA(str) shlwapi.PathIsLFNFileSpecA -@ stdcall PathIsLFNFileSpecW(wstr) shlwapi.PathIsLFNFileSpecW +@ stdcall PathGetArgsA(str) +@ stdcall PathGetArgsW(wstr) +@ stdcall PathGetCharTypeA(long) +@ stdcall PathGetCharTypeW(long) +@ stdcall PathGetDriveNumberA(str) +@ stdcall PathGetDriveNumberW(wstr) +@ stdcall PathIsFileSpecA(str) +@ stdcall PathIsFileSpecW(wstr) +@ stdcall PathIsLFNFileSpecA(str) +@ stdcall PathIsLFNFileSpecW(wstr) @ stdcall PathIsPrefixA(str str) @ stdcall PathIsPrefixW(wstr wstr) @ stdcall PathIsRelativeA(str) @@ -1084,15 +1084,15 @@ @ stdcall PathIsSameRootW(wstr wstr) shlwapi.PathIsSameRootW @ stdcall PathIsUNCA(str) @ stdcall PathIsUNCEx(wstr ptr) -@ stdcall PathIsUNCServerA(str) shlwapi.PathIsUNCServerA +@ stdcall PathIsUNCServerA(str) @ stdcall PathIsUNCServerShareA(str) @ stdcall PathIsUNCServerShareW(wstr) -@ stdcall PathIsUNCServerW(wstr) shlwapi.PathIsUNCServerW +@ stdcall PathIsUNCServerW(wstr) @ stdcall PathIsUNCW(wstr) @ stdcall PathIsURLA(str) shlwapi.PathIsURLA @ stdcall PathIsURLW(wstr) shlwapi.PathIsURLW -@ stdcall PathIsValidCharA(long long) shlwapi.PathIsValidCharA -@ stdcall PathIsValidCharW(long long) shlwapi.PathIsValidCharW +@ stdcall PathIsValidCharA(long long) +@ stdcall PathIsValidCharW(long long) @ stdcall PathMatchSpecA(str str) shlwapi.PathMatchSpecA # @ stub PathMatchSpecExA # @ stub PathMatchSpecExW @@ -1103,16 +1103,16 @@ @ stdcall PathQuoteSpacesW(wstr) shlwapi.PathQuoteSpacesW @ stdcall PathRelativePathToA(ptr str long str long) shlwapi.PathRelativePathToA @ stdcall PathRelativePathToW(ptr wstr long wstr long) shlwapi.PathRelativePathToW -@ stdcall PathRemoveBackslashA(str) shlwapi.PathRemoveBackslashA -@ stdcall PathRemoveBackslashW(wstr) shlwapi.PathRemoveBackslashW -@ stdcall PathRemoveBlanksA(str) shlwapi.PathRemoveBlanksA -@ stdcall PathRemoveBlanksW(wstr) shlwapi.PathRemoveBlanksW -@ stdcall PathRemoveExtensionA(str) shlwapi.PathRemoveExtensionA -@ stdcall PathRemoveExtensionW(wstr) shlwapi.PathRemoveExtensionW +@ stdcall PathRemoveBackslashA(str) +@ stdcall PathRemoveBackslashW(wstr) +@ stdcall PathRemoveBlanksA(str) +@ stdcall PathRemoveBlanksW(wstr) +@ stdcall PathRemoveExtensionA(str) +@ stdcall PathRemoveExtensionW(wstr) @ stdcall PathRemoveFileSpecA(str) @ stdcall PathRemoveFileSpecW(wstr) -@ stdcall PathRenameExtensionA(str str) shlwapi.PathRenameExtensionA -@ stdcall PathRenameExtensionW(wstr wstr) shlwapi.PathRenameExtensionW +@ stdcall PathRenameExtensionA(str str) +@ stdcall PathRenameExtensionW(wstr wstr) @ stdcall PathSearchAndQualifyA(str ptr long) shlwapi.PathSearchAndQualifyA @ stdcall PathSearchAndQualifyW(wstr ptr long) shlwapi.PathSearchAndQualifyW @ stdcall PathSkipRootA(str) shlwapi.PathSkipRootA @@ -1123,8 +1123,8 @@ @ stdcall PathStripToRootW(wstr) @ stdcall PathUnExpandEnvStringsA(str ptr long) shlwapi.PathUnExpandEnvStringsA @ stdcall PathUnExpandEnvStringsW(wstr ptr long) shlwapi.PathUnExpandEnvStringsW -@ stdcall PathUnquoteSpacesA(str) shlwapi.PathUnquoteSpacesA -@ stdcall PathUnquoteSpacesW(wstr) shlwapi.PathUnquoteSpacesW +@ stdcall PathUnquoteSpacesA(str) +@ stdcall PathUnquoteSpacesW(wstr) # @ stub PcwAddQueryItem # @ stub PcwClearCounterSetSecurity # @ stub PcwCollectData diff --git a/dlls/kernelbase/path.c b/dlls/kernelbase/path.c index a72ff8e694..49af28effe 100644 --- a/dlls/kernelbase/path.c +++ b/dlls/kernelbase/path.c @@ -23,19 +23,31 @@ #include "winbase.h" #include "pathcch.h" #include "strsafe.h" +#include "shlwapi.h"
#include "wine/debug.h" #include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(path);
-char *char_next(const char *ptr) +static char *char_next(const char *ptr) { if (!*ptr) return (LPSTR)ptr; if (IsDBCSLeadByte( ptr[0] ) && ptr[1]) return (LPSTR)(ptr + 2); return (LPSTR)(ptr + 1); }
+static char * char_prev(const char *start, const char *ptr) +{ + while (*start && (start < ptr)) + { + const char *next = char_next(start); + if (next >= ptr) break; + start = next; + } + return (char *)start; +} + static SIZE_T strnlenW(const WCHAR *string, SIZE_T maxlen) { SIZE_T i; @@ -1618,3 +1630,549 @@ BOOL WINAPI PathIsPrefixW(const WCHAR *prefix, const WCHAR *path)
return prefix && path && PathCommonPrefixW(path, prefix, NULL) == (int)strlenW(prefix); } + +char * WINAPI PathFindFileNameA(const char *path) +{ + const char *last_slash = path; + + TRACE("%s\n", wine_dbgstr_a(path)); + + while (path && *path) + { + if ((*path == '\' || *path == '/' || *path == ':') && + path[1] && path[1] != '\' && path[1] != '/') + last_slash = path + 1; + path = char_next(path); + } + + return (char *)last_slash; +} + +WCHAR * WINAPI PathFindFileNameW(const WCHAR *path) +{ + const WCHAR *last_slash = path; + + TRACE("%s\n", wine_dbgstr_w(path)); + + while (path && *path) + { + if ((*path == '\' || *path == '/' || *path == ':') && + path[1] && path[1] != '\' && path[1] != '/') + last_slash = path + 1; + path++; + } + + return (WCHAR *)last_slash; +} + +char * WINAPI PathGetArgsA(const char *path) +{ + BOOL seen_quote = FALSE; + + TRACE("%s\n", wine_dbgstr_a(path)); + + if (!path) + return NULL; + + while (*path) + { + if (*path == ' ' && !seen_quote) + return (char *)path + 1; + + if (*path == '"') + seen_quote = !seen_quote; + path = char_next(path); + } + + return (char *)path; +} + +WCHAR * WINAPI PathGetArgsW(const WCHAR *path) +{ + BOOL seen_quote = FALSE; + + TRACE("%s\n", wine_dbgstr_w(path)); + + if (!path) + return NULL; + + while (*path) + { + if (*path == ' ' && !seen_quote) + return (WCHAR *)path + 1; + + if (*path == '"') + seen_quote = !seen_quote; + path++; + } + + return (WCHAR *)path; +} + +UINT WINAPI PathGetCharTypeW(WCHAR ch) +{ + UINT flags = 0; + + TRACE("%#x\n", ch); + + if (!ch || ch < ' ' || ch == '<' || ch == '>' || ch == '"' || ch == '|' || ch == '/') + flags = GCT_INVALID; /* Invalid */ + else if (ch == '*' || ch == '?') + flags = GCT_WILD; /* Wildchars */ + else if (ch == '\' || ch == ':') + return GCT_SEPARATOR; /* Path separators */ + else + { + if (ch < 126) + { + if (((ch & 0x1) && ch != ';') || !ch || isalnum(ch) || ch == '$' || ch == '&' || ch == '(' || + ch == '.' || ch == '@' || ch == '^' || ch == ''' || ch == 130 || ch == '`') + { + flags |= GCT_SHORTCHAR; /* All these are valid for DOS */ + } + } + else + flags |= GCT_SHORTCHAR; /* Bug compatible with win32 */ + + flags |= GCT_LFNCHAR; /* Valid for long file names */ + } + + return flags; +} + +UINT WINAPI PathGetCharTypeA(UCHAR ch) +{ + return PathGetCharTypeW(ch); +} + +int WINAPI PathGetDriveNumberA(const char *path) +{ + TRACE("%s\n", wine_dbgstr_a(path)); + + if (path && !IsDBCSLeadByte(*path) && path[1] == ':' && tolower(*path) >= 'a' && tolower(*path) <= 'z') + return tolower(*path) - 'a'; + + return -1; +} + +int WINAPI PathGetDriveNumberW(const WCHAR *path) +{ + static const WCHAR nt_prefixW[] = {'\','\','?','\'}; + WCHAR drive; + + TRACE("%s\n", wine_dbgstr_w(path)); + + if (!path) + return -1; + + if (!strncmpW(path, nt_prefixW, 4)) + path += 4; + + drive = tolowerW(path[0]); + if (drive < 'a' || drive > 'z' || path[1] != ':') + return -1; + + return drive - 'a'; +} + +BOOL WINAPI PathIsFileSpecA(const char *path) +{ + TRACE("%s\n", wine_dbgstr_a(path)); + + if (!path) + return FALSE; + + while (*path) + { + if (*path == '\' || *path == ':') + return FALSE; + path = char_next(path); + } + + return TRUE; +} + +BOOL WINAPI PathIsFileSpecW(const WCHAR *path) +{ + TRACE("%s\n", wine_dbgstr_w(path)); + + if (!path) + return FALSE; + + while (*path) + { + if (*path == '\' || *path == ':') + return FALSE; + path++; + } + + return TRUE; +} + +BOOL WINAPI PathIsUNCServerA(const char *path) +{ + TRACE("%s\n", wine_dbgstr_a(path)); + + if (!(path && path[0] == '\' && path[1] == '\')) + return FALSE; + + while (*path) + { + if (*path == '\') + return FALSE; + path = char_next(path); + } + + return TRUE; +} + +BOOL WINAPI PathIsUNCServerW(const WCHAR *path) +{ + TRACE("%s\n", wine_dbgstr_w(path)); + + if (!(path && path[0] == '\' && path[1] == '\')) + return FALSE; + + return !strchrW(path + 2, '\'); +} + +void WINAPI PathRemoveBlanksA(char *path) +{ + char *start; + + TRACE("%s\n", wine_dbgstr_a(path)); + + if (!path || !*path) + return; + + start = path; + + while (*path == ' ') + path = char_next(path); + + while (*path) + *start++ = *path++; + + if (start != path) + while (start[-1] == ' ') + start--; + + *start = '\0'; +} + +void WINAPI PathRemoveBlanksW(WCHAR *path) +{ + WCHAR *start = path; + + TRACE("%s\n", wine_dbgstr_w(path)); + + if (!path || !*path) + return; + + while (*path == ' ') + path++; + + while (*path) + *start++ = *path++; + + if (start != path) + while (start[-1] == ' ') + start--; + + *start = '\0'; +} + +void WINAPI PathRemoveExtensionA(char *path) +{ + TRACE("%s\n", wine_dbgstr_a(path)); + + if (!path) + return; + + path = PathFindExtensionA(path); + if (path && !*path) + *path = '\0'; +} + +void WINAPI PathRemoveExtensionW(WCHAR *path) +{ + TRACE("%s\n", wine_dbgstr_w(path)); + + if (!path) + return; + + path = PathFindExtensionW(path); + if (path && !*path) + *path = '\0'; +} + +BOOL WINAPI PathRenameExtensionA(char *path, const char *ext) +{ + char *extension; + + TRACE("%s, %s\n", wine_dbgstr_a(path), wine_dbgstr_a(ext)); + + extension = PathFindExtensionA(path); + + if (!extension || (extension - path + strlen(ext) >= MAX_PATH)) + return FALSE; + + strcpy(extension, ext); + return TRUE; +} + +BOOL WINAPI PathRenameExtensionW(WCHAR *path, const WCHAR *ext) +{ + WCHAR *extension; + + TRACE("%s, %s\n", wine_dbgstr_w(path), wine_dbgstr_w(ext)); + + extension = PathFindExtensionW(path); + + if (!extension || (extension - path + strlenW(ext) >= MAX_PATH)) + return FALSE; + + strcpyW(extension, ext); + return TRUE; +} + +void WINAPI PathUnquoteSpacesA(char *path) +{ + unsigned int len; + + TRACE("%s\n", wine_dbgstr_a(path)); + + if (!path || *path != '"') + return; + + len = strlen(path) - 1; + if (path[len] == '"') + { + path[len] = '\0'; + for (; *path; path++) + *path = path[1]; + } +} + +void WINAPI PathUnquoteSpacesW(WCHAR *path) +{ + unsigned int len; + + TRACE("%s\n", wine_dbgstr_w(path)); + + if (!path || *path != '"') + return; + + len = strlenW(path) - 1; + if (path[len] == '"') + { + path[len] = '\0'; + for (; *path; path++) + *path = path[1]; + } +} + +char * WINAPI PathRemoveBackslashA(char *path) +{ + char *ptr; + + TRACE("%s\n", wine_dbgstr_a(path)); + + if (!path) + return NULL; + + ptr = char_prev(path, path + strlen(path)); + if (!PathIsRootA(path) && *ptr == '\') + *ptr = '\0'; + + return ptr; +} + +WCHAR * WINAPI PathRemoveBackslashW(WCHAR *path) +{ + WCHAR *ptr; + + TRACE("%s\n", wine_dbgstr_w(path)); + + if (!path) + return NULL; + + ptr = path + strlenW(path); + if (ptr > path) ptr--; + if (!PathIsRootW(path) && *ptr == '\') + *ptr = '\0'; + + return ptr; +} + +BOOL WINAPI PathIsLFNFileSpecA(const char *path) +{ + unsigned int name_len = 0, ext_len = 0; + + TRACE("%s\n", wine_dbgstr_a(path)); + + if (!path) + return FALSE; + + while (*path) + { + if (*path == ' ') + return TRUE; /* DOS names cannot have spaces */ + if (*path == '.') + { + if (ext_len) + return TRUE; /* DOS names have only one dot */ + ext_len = 1; + } + else if (ext_len) + { + ext_len++; + if (ext_len > 4) + return TRUE; /* DOS extensions are <= 3 chars*/ + } + else + { + name_len++; + if (name_len > 8) + return TRUE; /* DOS names are <= 8 chars */ + } + path = char_next(path); + } + + return FALSE; /* Valid DOS path */ +} + +BOOL WINAPI PathIsLFNFileSpecW(const WCHAR *path) +{ + unsigned int name_len = 0, ext_len = 0; + + TRACE("%s\n", wine_dbgstr_w(path)); + + if (!path) + return FALSE; + + while (*path) + { + if (*path == ' ') + return TRUE; /* DOS names cannot have spaces */ + if (*path == '.') + { + if (ext_len) + return TRUE; /* DOS names have only one dot */ + ext_len = 1; + } + else if (ext_len) + { + ext_len++; + if (ext_len > 4) + return TRUE; /* DOS extensions are <= 3 chars*/ + } + else + { + name_len++; + if (name_len > 8) + return TRUE; /* DOS names are <= 8 chars */ + } + path++; + } + + return FALSE; /* Valid DOS path */ +} + +#define PATH_CHAR_CLASS_LETTER 0x00000001 +#define PATH_CHAR_CLASS_ASTERIX 0x00000002 +#define PATH_CHAR_CLASS_DOT 0x00000004 +#define PATH_CHAR_CLASS_BACKSLASH 0x00000008 +#define PATH_CHAR_CLASS_COLON 0x00000010 +#define PATH_CHAR_CLASS_SEMICOLON 0x00000020 +#define PATH_CHAR_CLASS_COMMA 0x00000040 +#define PATH_CHAR_CLASS_SPACE 0x00000080 +#define PATH_CHAR_CLASS_OTHER_VALID 0x00000100 +#define PATH_CHAR_CLASS_DOUBLEQUOTE 0x00000200 + +#define PATH_CHAR_CLASS_INVALID 0x00000000 +#define PATH_CHAR_CLASS_ANY 0xffffffff + +static const DWORD path_charclass[] = +{ + /* 0x00 */ PATH_CHAR_CLASS_INVALID, /* 0x01 */ PATH_CHAR_CLASS_INVALID, + /* 0x02 */ PATH_CHAR_CLASS_INVALID, /* 0x03 */ PATH_CHAR_CLASS_INVALID, + /* 0x04 */ PATH_CHAR_CLASS_INVALID, /* 0x05 */ PATH_CHAR_CLASS_INVALID, + /* 0x06 */ PATH_CHAR_CLASS_INVALID, /* 0x07 */ PATH_CHAR_CLASS_INVALID, + /* 0x08 */ PATH_CHAR_CLASS_INVALID, /* 0x09 */ PATH_CHAR_CLASS_INVALID, + /* 0x0a */ PATH_CHAR_CLASS_INVALID, /* 0x0b */ PATH_CHAR_CLASS_INVALID, + /* 0x0c */ PATH_CHAR_CLASS_INVALID, /* 0x0d */ PATH_CHAR_CLASS_INVALID, + /* 0x0e */ PATH_CHAR_CLASS_INVALID, /* 0x0f */ PATH_CHAR_CLASS_INVALID, + /* 0x10 */ PATH_CHAR_CLASS_INVALID, /* 0x11 */ PATH_CHAR_CLASS_INVALID, + /* 0x12 */ PATH_CHAR_CLASS_INVALID, /* 0x13 */ PATH_CHAR_CLASS_INVALID, + /* 0x14 */ PATH_CHAR_CLASS_INVALID, /* 0x15 */ PATH_CHAR_CLASS_INVALID, + /* 0x16 */ PATH_CHAR_CLASS_INVALID, /* 0x17 */ PATH_CHAR_CLASS_INVALID, + /* 0x18 */ PATH_CHAR_CLASS_INVALID, /* 0x19 */ PATH_CHAR_CLASS_INVALID, + /* 0x1a */ PATH_CHAR_CLASS_INVALID, /* 0x1b */ PATH_CHAR_CLASS_INVALID, + /* 0x1c */ PATH_CHAR_CLASS_INVALID, /* 0x1d */ PATH_CHAR_CLASS_INVALID, + /* 0x1e */ PATH_CHAR_CLASS_INVALID, /* 0x1f */ PATH_CHAR_CLASS_INVALID, + /* ' ' */ PATH_CHAR_CLASS_SPACE, /* '!' */ PATH_CHAR_CLASS_OTHER_VALID, + /* '"' */ PATH_CHAR_CLASS_DOUBLEQUOTE, /* '#' */ PATH_CHAR_CLASS_OTHER_VALID, + /* '$' */ PATH_CHAR_CLASS_OTHER_VALID, /* '%' */ PATH_CHAR_CLASS_OTHER_VALID, + /* '&' */ PATH_CHAR_CLASS_OTHER_VALID, /* ''' */ PATH_CHAR_CLASS_OTHER_VALID, + /* '(' */ PATH_CHAR_CLASS_OTHER_VALID, /* ')' */ PATH_CHAR_CLASS_OTHER_VALID, + /* '*' */ PATH_CHAR_CLASS_ASTERIX, /* '+' */ PATH_CHAR_CLASS_OTHER_VALID, + /* ',' */ PATH_CHAR_CLASS_COMMA, /* '-' */ PATH_CHAR_CLASS_OTHER_VALID, + /* '.' */ PATH_CHAR_CLASS_DOT, /* '/' */ PATH_CHAR_CLASS_INVALID, + /* '0' */ PATH_CHAR_CLASS_OTHER_VALID, /* '1' */ PATH_CHAR_CLASS_OTHER_VALID, + /* '2' */ PATH_CHAR_CLASS_OTHER_VALID, /* '3' */ PATH_CHAR_CLASS_OTHER_VALID, + /* '4' */ PATH_CHAR_CLASS_OTHER_VALID, /* '5' */ PATH_CHAR_CLASS_OTHER_VALID, + /* '6' */ PATH_CHAR_CLASS_OTHER_VALID, /* '7' */ PATH_CHAR_CLASS_OTHER_VALID, + /* '8' */ PATH_CHAR_CLASS_OTHER_VALID, /* '9' */ PATH_CHAR_CLASS_OTHER_VALID, + /* ':' */ PATH_CHAR_CLASS_COLON, /* ';' */ PATH_CHAR_CLASS_SEMICOLON, + /* '<' */ PATH_CHAR_CLASS_INVALID, /* '=' */ PATH_CHAR_CLASS_OTHER_VALID, + /* '>' */ PATH_CHAR_CLASS_INVALID, /* '?' */ PATH_CHAR_CLASS_LETTER, + /* '@' */ PATH_CHAR_CLASS_OTHER_VALID, /* 'A' */ PATH_CHAR_CLASS_ANY, + /* 'B' */ PATH_CHAR_CLASS_ANY, /* 'C' */ PATH_CHAR_CLASS_ANY, + /* 'D' */ PATH_CHAR_CLASS_ANY, /* 'E' */ PATH_CHAR_CLASS_ANY, + /* 'F' */ PATH_CHAR_CLASS_ANY, /* 'G' */ PATH_CHAR_CLASS_ANY, + /* 'H' */ PATH_CHAR_CLASS_ANY, /* 'I' */ PATH_CHAR_CLASS_ANY, + /* 'J' */ PATH_CHAR_CLASS_ANY, /* 'K' */ PATH_CHAR_CLASS_ANY, + /* 'L' */ PATH_CHAR_CLASS_ANY, /* 'M' */ PATH_CHAR_CLASS_ANY, + /* 'N' */ PATH_CHAR_CLASS_ANY, /* 'O' */ PATH_CHAR_CLASS_ANY, + /* 'P' */ PATH_CHAR_CLASS_ANY, /* 'Q' */ PATH_CHAR_CLASS_ANY, + /* 'R' */ PATH_CHAR_CLASS_ANY, /* 'S' */ PATH_CHAR_CLASS_ANY, + /* 'T' */ PATH_CHAR_CLASS_ANY, /* 'U' */ PATH_CHAR_CLASS_ANY, + /* 'V' */ PATH_CHAR_CLASS_ANY, /* 'W' */ PATH_CHAR_CLASS_ANY, + /* 'X' */ PATH_CHAR_CLASS_ANY, /* 'Y' */ PATH_CHAR_CLASS_ANY, + /* 'Z' */ PATH_CHAR_CLASS_ANY, /* '[' */ PATH_CHAR_CLASS_OTHER_VALID, + /* '\' */ PATH_CHAR_CLASS_BACKSLASH, /* ']' */ PATH_CHAR_CLASS_OTHER_VALID, + /* '^' */ PATH_CHAR_CLASS_OTHER_VALID, /* '_' */ PATH_CHAR_CLASS_OTHER_VALID, + /* '`' */ PATH_CHAR_CLASS_OTHER_VALID, /* 'a' */ PATH_CHAR_CLASS_ANY, + /* 'b' */ PATH_CHAR_CLASS_ANY, /* 'c' */ PATH_CHAR_CLASS_ANY, + /* 'd' */ PATH_CHAR_CLASS_ANY, /* 'e' */ PATH_CHAR_CLASS_ANY, + /* 'f' */ PATH_CHAR_CLASS_ANY, /* 'g' */ PATH_CHAR_CLASS_ANY, + /* 'h' */ PATH_CHAR_CLASS_ANY, /* 'i' */ PATH_CHAR_CLASS_ANY, + /* 'j' */ PATH_CHAR_CLASS_ANY, /* 'k' */ PATH_CHAR_CLASS_ANY, + /* 'l' */ PATH_CHAR_CLASS_ANY, /* 'm' */ PATH_CHAR_CLASS_ANY, + /* 'n' */ PATH_CHAR_CLASS_ANY, /* 'o' */ PATH_CHAR_CLASS_ANY, + /* 'p' */ PATH_CHAR_CLASS_ANY, /* 'q' */ PATH_CHAR_CLASS_ANY, + /* 'r' */ PATH_CHAR_CLASS_ANY, /* 's' */ PATH_CHAR_CLASS_ANY, + /* 't' */ PATH_CHAR_CLASS_ANY, /* 'u' */ PATH_CHAR_CLASS_ANY, + /* 'v' */ PATH_CHAR_CLASS_ANY, /* 'w' */ PATH_CHAR_CLASS_ANY, + /* 'x' */ PATH_CHAR_CLASS_ANY, /* 'y' */ PATH_CHAR_CLASS_ANY, + /* 'z' */ PATH_CHAR_CLASS_ANY, /* '{' */ PATH_CHAR_CLASS_OTHER_VALID, + /* '|' */ PATH_CHAR_CLASS_INVALID, /* '}' */ PATH_CHAR_CLASS_OTHER_VALID, + /* '~' */ PATH_CHAR_CLASS_OTHER_VALID +}; + +BOOL WINAPI PathIsValidCharA(char c, DWORD class) +{ + if ((unsigned)c > 0x7e) + return class & PATH_CHAR_CLASS_OTHER_VALID; + + return class & path_charclass[(unsigned)c]; +} + +BOOL WINAPI PathIsValidCharW(WCHAR c, DWORD class) +{ + if (c > 0x7e) + return class & PATH_CHAR_CLASS_OTHER_VALID; + + return class & path_charclass[c]; +}
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/kernelbase/Makefile.in | 1 + dlls/kernelbase/kernelbase.spec | 2 +- dlls/kernelbase/main.c | 40 +++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/dlls/kernelbase/Makefile.in b/dlls/kernelbase/Makefile.in index a7db45e4c1..88ba774a7c 100644 --- a/dlls/kernelbase/Makefile.in +++ b/dlls/kernelbase/Makefile.in @@ -1,4 +1,5 @@ MODULE = kernelbase.dll +IMPORTS = uuid
C_SRCS = \ main.c \ diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index e586f500a4..7108c40a01 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -1191,7 +1191,7 @@ # @ stub PublishStateChangeNotification @ stdcall PulseEvent(long) kernel32.PulseEvent @ stdcall PurgeComm(long long) kernel32.PurgeComm -@ stdcall QISearch(long long long long) shlwapi.QISearch +@ stdcall QISearch(ptr ptr ptr ptr) @ stdcall QueryActCtxSettingsW(long ptr wstr wstr ptr long ptr) kernel32.QueryActCtxSettingsW @ stdcall QueryActCtxW(long ptr ptr long ptr long ptr) kernel32.QueryActCtxW @ stdcall QueryDepthSList(ptr) kernel32.QueryDepthSList diff --git a/dlls/kernelbase/main.c b/dlls/kernelbase/main.c index 5192dfb3f2..3fce23657b 100644 --- a/dlls/kernelbase/main.c +++ b/dlls/kernelbase/main.c @@ -17,10 +17,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#define COBJMACROS + #include "ntstatus.h" #define WIN32_NO_STATUS #include "windows.h" #include "appmodel.h" +#include "shlwapi.h"
#include "wine/debug.h" #include "winternl.h" @@ -125,3 +128,40 @@ BOOL WINAPI WaitOnAddress(volatile void *addr, void *cmp, SIZE_T size, DWORD tim
return TRUE; } + +HRESULT WINAPI QISearch(void *base, const QITAB *table, REFIID riid, void **obj) +{ + const QITAB *ptr; + IUnknown *unk; + + TRACE("%p, %p, %s, %p\n", base, table, debugstr_guid(riid), obj); + + if (!obj) + return E_POINTER; + + for (ptr = table; ptr->piid; ++ptr) + { + TRACE("trying (offset %d) %s\n", ptr->dwOffset, debugstr_guid(ptr->piid)); + if (IsEqualIID(riid, ptr->piid)) + { + unk = (IUnknown *)((BYTE *)base + ptr->dwOffset); + TRACE("matched, returning (%p)\n", unk); + *obj = unk; + IUnknown_AddRef(unk); + return S_OK; + } + } + + if (IsEqualIID(riid, &IID_IUnknown)) + { + unk = (IUnknown *)((BYTE *)base + table->dwOffset); + TRACE("returning first for IUnknown (%p)\n", unk); + *obj = unk; + IUnknown_AddRef(unk); + return S_OK; + } + + WARN("Not found %s.\n", debugstr_guid(riid)); + *obj = NULL; + return E_NOINTERFACE; +}
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=52260
Your paranoid android.
=== debian9 (build log) ===
error: patch failed: dlls/kernelbase/kernelbase.spec:1060 error: patch failed: dlls/kernelbase/path.c:23 Task: Patch failed to apply
=== debian9 (build log) ===
error: patch failed: dlls/kernelbase/kernelbase.spec:1060 error: patch failed: dlls/kernelbase/path.c:23 Task: Patch failed to apply
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/kernelbase/Makefile.in | 3 +- dlls/kernelbase/kernelbase.spec | 78 ++--- dlls/kernelbase/string.c | 519 ++++++++++++++++++++++++++++++++ 3 files changed, 560 insertions(+), 40 deletions(-) create mode 100644 dlls/kernelbase/string.c
diff --git a/dlls/kernelbase/Makefile.in b/dlls/kernelbase/Makefile.in index 88ba774a7c..dcb03b4fdc 100644 --- a/dlls/kernelbase/Makefile.in +++ b/dlls/kernelbase/Makefile.in @@ -3,4 +3,5 @@ IMPORTS = uuid
C_SRCS = \ main.c \ - path.c + path.c \ + string.c diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 7108c40a01..8294c95282 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -131,7 +131,7 @@ @ stdcall CheckTokenMembership(long ptr ptr) advapi32.CheckTokenMembership # @ stub CheckTokenMembershipEx @ stdcall ChrCmpIA(long long) shlwapi.ChrCmpIA -@ stdcall ChrCmpIW(long long) shlwapi.ChrCmpIW +@ stdcall ChrCmpIW(long long) @ stdcall ClearCommBreak(long) kernel32.ClearCommBreak @ stdcall ClearCommError(long ptr ptr) kernel32.ClearCommError # @ stub CloseGlobalizationUserSettingsKey @@ -843,17 +843,17 @@ @ stdcall IsCharAlphaNumericA(long) user32.IsCharAlphaNumericA @ stdcall IsCharAlphaNumericW(long) user32.IsCharAlphaNumericW @ stdcall IsCharAlphaW(long) user32.IsCharAlphaW -@ stdcall IsCharBlankW(long) shlwapi.IsCharBlankW -@ stdcall IsCharCntrlW(ptr) shlwapi.IsCharCntrlW -@ stdcall IsCharDigitW(long) shlwapi.IsCharDigitW +@ stdcall IsCharBlankW(long) +@ stdcall IsCharCntrlW(long) +@ stdcall IsCharDigitW(long) @ stdcall IsCharLowerA(long) user32.IsCharLowerA @ stdcall IsCharLowerW(long) user32.IsCharLowerW -@ stdcall IsCharPunctW(long) shlwapi.IsCharPunctW -@ stdcall IsCharSpaceA(long) shlwapi.IsCharSpaceA -@ stdcall IsCharSpaceW(long) shlwapi.IsCharSpaceW +@ stdcall IsCharPunctW(long) +@ stdcall IsCharSpaceA(long) +@ stdcall IsCharSpaceW(long) @ stdcall IsCharUpperA(long) user32.IsCharUpperA @ stdcall IsCharUpperW(long) user32.IsCharUpperW -@ stdcall IsCharXDigitW(long) shlwapi.IsCharXDigitW +@ stdcall IsCharXDigitW(long) @ stdcall IsDBCSLeadByte(long) kernel32.IsDBCSLeadByte @ stdcall IsDBCSLeadByteEx(long long) kernel32.IsDBCSLeadByteEx @ stdcall IsDebuggerPresent() kernel32.IsDebuggerPresent @@ -1535,56 +1535,56 @@ @ stdcall StrChrA(str long) shlwapi.StrChrA # @ stub StrChrA_MB @ stdcall StrChrIA(str long) shlwapi.StrChrIA -@ stdcall StrChrIW(wstr long) shlwapi.StrChrIW +@ stdcall StrChrIW(wstr long) # @ stub StrChrNIW -@ stdcall StrChrNW(wstr long long) shlwapi.StrChrNW -@ stdcall StrChrW(wstr long) shlwapi.StrChrW -@ stdcall StrCmpCA(str str) shlwapi.StrCmpCA -@ stdcall StrCmpCW(wstr wstr) shlwapi.StrCmpCW -@ stdcall StrCmpICA(str str) shlwapi.StrCmpICA -@ stdcall StrCmpICW(wstr wstr) shlwapi.StrCmpICW -@ stdcall StrCmpIW(wstr wstr) shlwapi.StrCmpIW +@ stdcall StrChrNW(wstr long long) +@ stdcall StrChrW(wstr long) +@ stdcall StrCmpCA(str str) +@ stdcall StrCmpCW(wstr wstr) +@ 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 StrCmpNCA(str ptr long) shlwapi.StrCmpNCA @ stdcall StrCmpNCW(wstr wstr long) shlwapi.StrCmpNCW -@ stdcall StrCmpNIA(str str long) shlwapi.StrCmpNIA -@ stdcall StrCmpNICA(long long long) shlwapi.StrCmpNICA -@ stdcall StrCmpNICW(wstr wstr long) shlwapi.StrCmpNICW -@ stdcall StrCmpNIW(wstr wstr long) shlwapi.StrCmpNIW -@ stdcall StrCmpNW(wstr wstr long) shlwapi.StrCmpNW -@ stdcall StrCmpW(wstr wstr) shlwapi.StrCmpW -@ stdcall StrCpyNW(ptr wstr long) shlwapi.StrCpyNW -@ stdcall StrCpyNXA(ptr str long) shlwapi.StrCpyNXA -@ stdcall StrCpyNXW(ptr wstr long) shlwapi.StrCpyNXW -@ stdcall StrDupA(str) shlwapi.StrDupA -@ stdcall StrDupW(wstr) shlwapi.StrDupW +@ stdcall StrCmpNIA(str str long) +@ stdcall StrCmpNICA(long long long) +@ stdcall StrCmpNICW(wstr wstr long) +@ stdcall StrCmpNIW(wstr wstr long) +@ stdcall StrCmpNW(wstr wstr long) +@ stdcall StrCmpW(wstr wstr) +@ stdcall StrCpyNW(ptr wstr long) +@ stdcall StrCpyNXA(ptr str long) +@ 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 StrPBrkW(wstr wstr) shlwapi.StrPBrkW +@ stdcall StrPBrkW(wstr wstr) @ stdcall StrRChrA(str str long) shlwapi.StrRChrA @ stdcall StrRChrIA(str str long) shlwapi.StrRChrIA -@ stdcall StrRChrIW(wstr wstr long) shlwapi.StrRChrIW -@ stdcall StrRChrW(wstr wstr long) shlwapi.StrRChrW +@ stdcall StrRChrIW(wstr wstr long) +@ stdcall StrRChrW(wstr wstr long) @ stdcall StrRStrIA(str str str) shlwapi.StrRStrIA @ stdcall StrRStrIW(wstr wstr wstr) shlwapi.StrRStrIW @ stdcall StrSpnA(str str) shlwapi.StrSpnA -@ stdcall StrSpnW(wstr wstr) shlwapi.StrSpnW +@ stdcall StrSpnW(wstr wstr) @ stdcall StrStrA(str str) shlwapi.StrStrA @ stdcall StrStrIA(str str) shlwapi.StrStrIA -@ stdcall StrStrIW(wstr wstr) shlwapi.StrStrIW -@ stdcall StrStrNIW(wstr wstr long) shlwapi.StrStrNIW -@ stdcall StrStrNW(wstr wstr long) shlwapi.StrStrNW -@ stdcall StrStrW(wstr wstr) shlwapi.StrStrW +@ stdcall StrStrIW(wstr wstr) +@ stdcall StrStrNIW(wstr wstr long) +@ stdcall StrStrNW(wstr wstr long) +@ stdcall StrStrW(wstr wstr) @ stdcall StrToInt64ExA(str long ptr) shlwapi.StrToInt64ExA -@ stdcall StrToInt64ExW(wstr long ptr) shlwapi.StrToInt64ExW +@ stdcall StrToInt64ExW(wstr long ptr) @ stdcall StrToIntA(str) shlwapi.StrToIntA @ stdcall StrToIntExA(str long ptr) shlwapi.StrToIntExA -@ stdcall StrToIntExW(wstr long ptr) shlwapi.StrToIntExW -@ stdcall StrToIntW(wstr) shlwapi.StrToIntW +@ stdcall StrToIntExW(wstr long ptr) +@ stdcall StrToIntW(wstr) @ stdcall StrTrimA(str str) shlwapi.StrTrimA -@ stdcall StrTrimW(wstr wstr) shlwapi.StrTrimW +@ stdcall StrTrimW(wstr wstr) @ stdcall SubmitThreadpoolWork(ptr) kernel32.SubmitThreadpoolWork # @ stub SubscribeEdpEnabledStateChange # @ stub SubscribeStateChangeNotification diff --git a/dlls/kernelbase/string.c b/dlls/kernelbase/string.c new file mode 100644 index 0000000000..4991ba3fd1 --- /dev/null +++ b/dlls/kernelbase/string.c @@ -0,0 +1,519 @@ +/* + * Copyright 2019 Nikolay Sivov for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdarg.h> + +#include "windef.h" +#include "winbase.h" +#include "winnls.h" +#include "shlwapi.h" + +#include "wine/debug.h" +#include "wine/unicode.h" + +WINE_DEFAULT_DEBUG_CHANNEL(string); + +DWORD WINAPI StrCmpCA(const char *str, const char *cmp) +{ + return lstrcmpA(str, cmp); +} + +DWORD WINAPI StrCmpCW(const WCHAR *str, const WCHAR *cmp) +{ + return lstrcmpW(str, cmp); +} + +DWORD WINAPI StrCmpICA(const char *str, const char *cmp) +{ + return lstrcmpiA(str, cmp); +} + +DWORD WINAPI StrCmpICW(const WCHAR *str, const WCHAR *cmp) +{ + return lstrcmpiW(str, cmp); +} + +DWORD WINAPI StrCmpNICA(const char *str, const char *cmp, DWORD len) +{ + return StrCmpNIA(str, cmp, len); +} + +DWORD WINAPI StrCmpNICW(const WCHAR *str, const WCHAR *cmp, DWORD len) +{ + return StrCmpNIW(str, cmp, len); +} + +BOOL WINAPI IsCharBlankW(WCHAR wc) +{ + WORD type; + + return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_BLANK); +} + +BOOL WINAPI IsCharCntrlW(WCHAR wc) +{ + WORD type; + + return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_CNTRL); +} + +BOOL WINAPI IsCharDigitW(WCHAR wc) +{ + WORD type; + + return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_DIGIT); +} + +BOOL WINAPI IsCharPunctW(WCHAR wc) +{ + WORD type; + + return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_PUNCT); +} + +BOOL WINAPI IsCharSpaceA(CHAR c) +{ + WORD type; + return GetStringTypeA(GetSystemDefaultLCID(), CT_CTYPE1, &c, 1, &type) && (type & C1_SPACE); +} + +BOOL WINAPI IsCharSpaceW(WCHAR wc) +{ + WORD type; + + return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_SPACE); +} + +BOOL WINAPI IsCharXDigitW(WCHAR wc) +{ + WORD type; + + return GetStringTypeW(CT_CTYPE1, &wc, 1, &type) && (type & C1_XDIGIT); +} + +WCHAR * WINAPI StrChrW(const WCHAR *str, WCHAR ch) +{ + TRACE("%s, %#x\n", wine_dbgstr_w(str), ch); + + if (!str) + return NULL; + + return strchrW(str, ch); +} + +WCHAR * WINAPI StrChrIW(const WCHAR *str, WCHAR ch) +{ + TRACE("%s, %#x\n", wine_dbgstr_w(str), ch); + + if (!str) + return NULL; + + ch = toupperW(ch); + while (*str) + { + if (toupperW(*str) == ch) + return (WCHAR *)str; + str++; + } + str = NULL; + + return (WCHAR *)str; +} + +WCHAR * WINAPI StrChrNW(const WCHAR *str, WCHAR ch, UINT max_len) +{ + TRACE("%s, %#x, %u\n", wine_dbgstr_wn(str, max_len), ch, max_len); + + if (!str) + return NULL; + + while (*str && max_len-- > 0) + { + if (*str == ch) + return (WCHAR *)str; + str++; + } + + return NULL; +} + +char * WINAPI StrDupA(const char *str) +{ + unsigned int len; + char *ret; + + TRACE("%s\n", wine_dbgstr_a(str)); + + len = str ? strlen(str) + 1 : 1; + ret = LocalAlloc(LMEM_FIXED, len); + + if (ret) + { + if (str) + memcpy(ret, str, len); + else + *ret = '\0'; + } + + return ret; +} + +WCHAR * WINAPI StrDupW(const WCHAR *str) +{ + unsigned int len; + WCHAR *ret; + + TRACE("%s\n", wine_dbgstr_w(str)); + + len = (str ? strlenW(str) + 1 : 1) * sizeof(WCHAR); + ret = LocalAlloc(LMEM_FIXED, len); + + if (ret) + { + if (str) + memcpy(ret, str, len); + else + *ret = '\0'; + } + + return ret; +} + +BOOL WINAPI ChrCmpIW(WCHAR ch1, WCHAR ch2) +{ + return CompareStringW(GetThreadLocale(), NORM_IGNORECASE, &ch1, 1, &ch2, 1) - CSTR_EQUAL; +} + +WCHAR * WINAPI StrStrW(const WCHAR *str, const WCHAR *search) +{ + TRACE("%s, %s\n", wine_dbgstr_w(str), wine_dbgstr_w(search)); + + if (!str || !search || !*search) + return NULL; + + return strstrW(str, search); +} + +WCHAR * WINAPI StrStrNW(const WCHAR *str, const WCHAR *search, UINT max_len) +{ + unsigned int i, len; + + TRACE("%s, %s, %u\n", wine_dbgstr_w(str), wine_dbgstr_w(search), max_len); + + if (!str || !search || !*search || !max_len) + return NULL; + + len = strlenW(search); + + for (i = max_len; *str && (i > 0); i--, str++) + { + if (!strncmpW(str, search, len)) + return (WCHAR *)str; + } + + return NULL; +} + +int WINAPI StrCmpNIA(const char *str, const char *cmp, int len) +{ + TRACE("%s, %s, %i\n", wine_dbgstr_a(str), wine_dbgstr_a(cmp), len); + return CompareStringA(GetThreadLocale(), NORM_IGNORECASE, str, len, cmp, len) - CSTR_EQUAL; +} + +WCHAR * WINAPI StrStrNIW(const WCHAR *str, const WCHAR *search, UINT max_len) +{ + unsigned int i, len; + + TRACE("%s, %s, %u\n", wine_dbgstr_w(str), wine_dbgstr_w(search), max_len); + + if (!str || !search || !*search || !max_len) + return NULL; + + len = strlenW(search); + + for (i = max_len; *str && (i > 0); i--, str++) + { + if (!strncmpiW(str, search, len)) + return (WCHAR *)str; + } + + return NULL; +} + +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); + return CompareStringW(GetThreadLocale(), 0, str, len, comp, len) - CSTR_EQUAL; +} + +int WINAPI StrCmpNIW(const WCHAR *str, const WCHAR *comp, int len) +{ + TRACE("%s, %s, %i\n", wine_dbgstr_w(str), wine_dbgstr_w(comp), len); + return CompareStringW(GetThreadLocale(), NORM_IGNORECASE, str, len, comp, len) - CSTR_EQUAL; +} + +int WINAPI StrCmpW(const WCHAR *str, const WCHAR *comp) +{ + TRACE("%s, %s\n", wine_dbgstr_w(str), wine_dbgstr_w(comp)); + return CompareStringW(GetThreadLocale(), 0, str, -1, comp, -1) - CSTR_EQUAL; +} + +int WINAPI StrCmpIW(const WCHAR *str, const WCHAR *comp) +{ + TRACE("%s, %s\n", wine_dbgstr_w(str), wine_dbgstr_w(comp)); + return CompareStringW(GetThreadLocale(), NORM_IGNORECASE, str, -1, comp, -1) - CSTR_EQUAL; +} + +WCHAR * WINAPI StrCpyNW(WCHAR *dst, const WCHAR *src, int count) +{ + const WCHAR *s = src; + WCHAR *d = dst; + + TRACE("%p, %s, %i\n", dst, wine_dbgstr_w(src), count); + + if (s) + { + while ((count > 1) && *s) + { + count--; + *d++ = *s++; + } + } + if (count) *d = 0; + + return dst; +} + +WCHAR * WINAPI StrStrIW(const WCHAR *str, const WCHAR *search) +{ + unsigned int len; + const WCHAR *end; + + TRACE("%s, %s\n", wine_dbgstr_w(str), wine_dbgstr_w(search)); + + if (!str || !search || !*search) + return NULL; + + len = strlenW(search); + end = str + strlenW(str); + + while (str + len <= end) + { + if (!StrCmpNIW(str, search, len)) + return (WCHAR *)str; + str++; + } + + return NULL; +} + +int WINAPI StrSpnW(const WCHAR *str, const WCHAR *match) +{ + if (!str || !match) return 0; + return strspnW(str, match); +} + +WCHAR * WINAPI StrRChrW(const WCHAR *str, const WCHAR *end, WORD ch) +{ + WCHAR *ret = NULL; + + if (!str) return NULL; + if (!end) end = str + strlenW(str); + while (str < end) + { + if (*str == ch) ret = (WCHAR *)str; + str++; + } + return ret; +} + +WCHAR * WINAPI StrRChrIW(const WCHAR *str, const WCHAR *end, WORD ch) +{ + WCHAR *ret = NULL; + + if (!str) return NULL; + if (!end) end = str + strlenW(str); + while (str < end) + { + if (!ChrCmpIW(*str, ch)) ret = (WCHAR *)str; + str++; + } + return ret; +} + +WCHAR * WINAPI StrPBrkW(const WCHAR *str, const WCHAR *match) +{ + if (!str || !match) return NULL; + return strpbrkW(str, match); +} + +BOOL WINAPI StrTrimW(WCHAR *str, const WCHAR *trim) +{ + unsigned int len; + WCHAR *ptr = str; + BOOL ret = FALSE; + + TRACE("%s, %s\n", wine_dbgstr_w(str), wine_dbgstr_w(trim)); + + if (!str || !*str) + return FALSE; + + while (*ptr && StrChrW(trim, *ptr)) + ptr++; + + len = strlenW(ptr); + + if (ptr != str) + { + memmove(str, ptr, (len + 1) * sizeof(WCHAR)); + ret = TRUE; + } + + if (len > 0) + { + ptr = str + len; + while (StrChrW(trim, ptr[-1])) + ptr--; /* Skip trailing matches */ + + if (ptr != str + len) + { + *ptr = '\0'; + ret = TRUE; + } + } + + return ret; +} + +BOOL WINAPI StrToInt64ExW(const WCHAR *str, DWORD flags, LONGLONG *ret) +{ + BOOL negative = FALSE; + LONGLONG value = 0; + + TRACE("%s, %#x, %p\n", wine_dbgstr_w(str), flags, ret); + + if (!str || !ret) + return FALSE; + + if (flags > STIF_SUPPORT_HEX) + WARN("Unknown flags %#x.\n", flags); + + /* Skip leading space, '+', '-' */ + while (isspaceW(*str)) + str++; + + if (*str == '-') + { + negative = TRUE; + str++; + } + else if (*str == '+') + str++; + + if (flags & STIF_SUPPORT_HEX && *str == '0' && tolowerW(str[1]) == 'x') + { + /* Read hex number */ + str += 2; + + if (!isxdigitW(*str)) + return FALSE; + + while (isxdigitW(*str)) + { + value *= 16; + if (isdigitW(*str)) + value += (*str - '0'); + else + value += 10 + (tolowerW(*str) - 'a'); + str++; + } + + *ret = value; + return TRUE; + } + + /* Read decimal number */ + if (!isdigitW(*str)) + return FALSE; + + while (isdigitW(*str)) + { + value *= 10; + value += (*str - '0'); + str++; + } + + *ret = negative ? -value : value; + return TRUE; +} + +BOOL WINAPI StrToIntExW(const WCHAR *str, DWORD flags, INT *ret) +{ + LONGLONG value; + BOOL res; + + TRACE("%s, %#x, %p\n", wine_dbgstr_w(str), flags, ret); + + res = StrToInt64ExW(str, flags, &value); + if (res) *ret = value; + return res; +} + +int WINAPI StrToIntW(const WCHAR *str) +{ + int value = 0; + + TRACE("%s\n", wine_dbgstr_w(str)); + + if (!str) + return 0; + + if (*str == '-' || isdigitW(*str)) + StrToIntExW(str, 0, &value); + return value; +} + +char * WINAPI StrCpyNXA(char *dst, const char *src, int len) +{ + TRACE("%p, %s, %i\n", dst, wine_dbgstr_a(src), len); + + if (dst && src && len > 0) + { + while ((len-- > 1) && *src) + *dst++ = *src++; + if (len >= 0) + *dst = '\0'; + } + + return dst; +} + +WCHAR * WINAPI StrCpyNXW(WCHAR *dst, const WCHAR *src, int len) +{ + TRACE("%p, %s, %i\n", dst, wine_dbgstr_w(src), len); + + if (dst && src && len > 0) + { + while ((len-- > 1) && *src) + *dst++ = *src++; + if (len >= 0) + *dst = '\0'; + } + + return dst; +}
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=52261
Your paranoid android.
=== debian9 (build log) ===
error: patch failed: dlls/kernelbase/kernelbase.spec:1060 error: patch failed: dlls/kernelbase/path.c:23 Task: Patch failed to apply
=== debian9 (build log) ===
error: patch failed: dlls/kernelbase/kernelbase.spec:1060 error: patch failed: dlls/kernelbase/path.c:23 Task: Patch failed to apply
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=52259
Your paranoid android.
=== debian9 (build log) ===
error: patch failed: dlls/kernelbase/kernelbase.spec:1060 error: patch failed: dlls/kernelbase/path.c:23 Task: Patch failed to apply
=== debian9 (build log) ===
error: patch failed: dlls/kernelbase/kernelbase.spec:1060 error: patch failed: dlls/kernelbase/path.c:23 Task: Patch failed to apply