From 6adc874cbbddbf09734216545aa2e190181240d5 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Thu, 21 May 2026 22:35:23 +0300 Subject: [PATCH] [SHLWAPI] Use kernelbase This replaces implementations that no longer exist in Wine-10.0's shlwapi Also forward some exports to kernelbase_ros. This is to prevent them from being reimported from shell32, which forwards them here. It is not exactly what Windows does (which exports the import stubs), but it should be good enough for now. --- dll/win32/shlwapi/CMakeLists.txt | 2 +- dll/win32/shlwapi/ordinal.c | 114 -- dll/win32/shlwapi/path.c | 2808 ------------------------------ dll/win32/shlwapi/shlwapi.spec | 169 +- dll/win32/shlwapi/string.c | 1765 ------------------- dll/win32/shlwapi/url.c | 2542 --------------------------- 6 files changed, 87 insertions(+), 7313 deletions(-) diff --git a/dll/win32/shlwapi/CMakeLists.txt b/dll/win32/shlwapi/CMakeLists.txt index 3fe8a6e600f..df78519ffb2 100644 --- a/dll/win32/shlwapi/CMakeLists.txt +++ b/dll/win32/shlwapi/CMakeLists.txt @@ -69,6 +69,6 @@ add_dependencies(shlwapi_autocomp psdk) set_module_type(shlwapi win32dll UNICODE) target_link_libraries(shlwapi uuid wine crtheap cppstl) add_delay_importlibs(shlwapi userenv oleaut32 ole32 comctl32 comdlg32 mpr mlang urlmon shell32 winmm version) -add_importlibs(shlwapi shcore user32 gdi32 advapi32 wininet msvcrt kernel32 ntdll) +add_importlibs(shlwapi shcore user32 gdi32 advapi32 wininet msvcrt kernelbase kernel32 kernel32_vista ntdll) #add_pch(shlwapi precomp.h "${PCH_SKIP_SOURCE}") add_cd_file(TARGET shlwapi DESTINATION reactos/system32 FOR all) diff --git a/dll/win32/shlwapi/ordinal.c b/dll/win32/shlwapi/ordinal.c index 73d91c9adf0..4138bb16f6e 100644 --- a/dll/win32/shlwapi/ordinal.c +++ b/dll/win32/shlwapi/ordinal.c @@ -783,120 +783,6 @@ BOOL WINAPI GetStringType3ExW(LPWSTR src, INT count, LPWORD type) return GetStringTypeW(CT_CTYPE3, src, count, type); } -/************************************************************************* - * @ [SHLWAPI.151] - * - * Compare two Ascii strings up to a given length. - * - * PARAMS - * lpszSrc [I] Source string - * lpszCmp [I] String to compare to lpszSrc - * len [I] Maximum length - * - * RETURNS - * A number greater than, less than or equal to 0 depending on whether - * lpszSrc is greater than, less than or equal to lpszCmp. - */ -DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len) -{ - return StrCmpNA(lpszSrc, lpszCmp, len); -} - -/************************************************************************* - * @ [SHLWAPI.152] - * - * Unicode version of StrCmpNCA. - */ -DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len) -{ - return StrCmpNW(lpszSrc, lpszCmp, len); -} - -/************************************************************************* - * @ [SHLWAPI.153] - * - * Compare two Ascii strings up to a given length, ignoring case. - * - * PARAMS - * lpszSrc [I] Source string - * lpszCmp [I] String to compare to lpszSrc - * len [I] Maximum length - * - * RETURNS - * A number greater than, less than or equal to 0 depending on whether - * lpszSrc is greater than, less than or equal to lpszCmp. - */ -DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len) -{ - return StrCmpNIA(lpszSrc, lpszCmp, len); -} - -/************************************************************************* - * @ [SHLWAPI.154] - * - * Unicode version of StrCmpNICA. - */ -DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len) -{ - return StrCmpNIW(lpszSrc, lpszCmp, len); -} - -/************************************************************************* - * @ [SHLWAPI.155] - * - * Compare two Ascii strings. - * - * PARAMS - * lpszSrc [I] Source string - * lpszCmp [I] String to compare to lpszSrc - * - * RETURNS - * A number greater than, less than or equal to 0 depending on whether - * lpszSrc is greater than, less than or equal to lpszCmp. - */ -DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp) -{ - return lstrcmpA(lpszSrc, lpszCmp); -} - -/************************************************************************* - * @ [SHLWAPI.156] - * - * Unicode version of StrCmpCA. - */ -DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp) -{ - return lstrcmpW(lpszSrc, lpszCmp); -} - -/************************************************************************* - * @ [SHLWAPI.157] - * - * Compare two Ascii strings, ignoring case. - * - * PARAMS - * lpszSrc [I] Source string - * lpszCmp [I] String to compare to lpszSrc - * - * RETURNS - * A number greater than, less than or equal to 0 depending on whether - * lpszSrc is greater than, less than or equal to lpszCmp. - */ -DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp) -{ - return lstrcmpiA(lpszSrc, lpszCmp); -} - -/************************************************************************* - * @ [SHLWAPI.158] - * - * Unicode version of StrCmpICA. - */ -DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp) -{ - return lstrcmpiW(lpszSrc, lpszCmp); -} - /************************************************************************* * @ [SHLWAPI.160] * diff --git a/dll/win32/shlwapi/path.c b/dll/win32/shlwapi/path.c index c5726a41302..2f9f377e40e 100644 --- a/dll/win32/shlwapi/path.c +++ b/dll/win32/shlwapi/path.c @@ -67,251 +67,8 @@ static fnpIsNetDrive pIsNetDrive; #endif /* __REACTOS__ */ - HRESULT WINAPI SHGetWebFolderFilePathW(LPCWSTR,LPWSTR,DWORD); -static inline WCHAR* heap_strdupAtoW(LPCSTR str) -{ - WCHAR *ret = NULL; - - if (str) - { - DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); - ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); - if (ret) - MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); - } - - return ret; -} - -/************************************************************************* - * PathAppendA [SHLWAPI.@] - * - * Append one path to another. - * - * PARAMS - * lpszPath [I/O] Initial part of path, and destination for output - * lpszAppend [I] Path to append - * - * RETURNS - * Success: TRUE. lpszPath contains the newly created path. - * Failure: FALSE, if either path is NULL, or PathCombineA() fails. - * - * NOTES - * lpszAppend must contain at least one backslash ('\') if not NULL. - * Because PathCombineA() is used to join the paths, the resulting - * path is also canonicalized. - */ -BOOL WINAPI PathAppendA (LPSTR lpszPath, LPCSTR lpszAppend) -{ - TRACE("(%s,%s)\n",debugstr_a(lpszPath), debugstr_a(lpszAppend)); - - if (lpszPath && lpszAppend) - { - if (!PathIsUNCA(lpszAppend)) - while (*lpszAppend == '\\') - lpszAppend++; - if (PathCombineA(lpszPath, lpszPath, lpszAppend)) - return TRUE; - } - return FALSE; -} - -/************************************************************************* - * PathAppendW [SHLWAPI.@] - * - * See PathAppendA. - */ -BOOL WINAPI PathAppendW(LPWSTR lpszPath, LPCWSTR lpszAppend) -{ - TRACE("(%s,%s)\n",debugstr_w(lpszPath), debugstr_w(lpszAppend)); - - if (lpszPath && lpszAppend) - { - if (!PathIsUNCW(lpszAppend)) - while (*lpszAppend == '\\') - lpszAppend++; - if (PathCombineW(lpszPath, lpszPath, lpszAppend)) - return TRUE; - } - return FALSE; -} - -/************************************************************************* - * PathCombineA [SHLWAPI.@] - * - * Combine two paths together. - * - * PARAMS - * lpszDest [O] Destination for combined path - * lpszDir [I] Directory path - * lpszFile [I] File path - * - * RETURNS - * Success: The output path - * Failure: NULL, if inputs are invalid. - * - * NOTES - * lpszDest should be at least MAX_PATH in size, and may point to the same - * memory location as lpszDir. The combined path is canonicalised. - */ -LPSTR WINAPI PathCombineA(LPSTR lpszDest, LPCSTR lpszDir, LPCSTR lpszFile) -{ - WCHAR szDest[MAX_PATH]; - WCHAR szDir[MAX_PATH]; - WCHAR szFile[MAX_PATH]; - TRACE("(%p,%s,%s)\n", lpszDest, debugstr_a(lpszDir), debugstr_a(lpszFile)); - - /* Invalid parameters */ - if (!lpszDest) - return NULL; - if (!lpszDir && !lpszFile) - goto fail; - - if (lpszDir) - if (!MultiByteToWideChar(CP_ACP,0,lpszDir,-1,szDir,MAX_PATH)) - goto fail; - - if (lpszFile) - if (!MultiByteToWideChar(CP_ACP,0,lpszFile,-1,szFile,MAX_PATH)) - goto fail; - - if (PathCombineW(szDest, lpszDir ? szDir : NULL, lpszFile ? szFile : NULL)) - if (WideCharToMultiByte(CP_ACP,0,szDest,-1,lpszDest,MAX_PATH,0,0)) - return lpszDest; - -fail: - lpszDest[0] = 0; - return NULL; -} - -/************************************************************************* - * PathCombineW [SHLWAPI.@] - * - * See PathCombineA. - */ -LPWSTR WINAPI PathCombineW(LPWSTR lpszDest, LPCWSTR lpszDir, LPCWSTR lpszFile) -{ - WCHAR szTemp[MAX_PATH]; - BOOL bUseBoth = FALSE, bStrip = FALSE; - - TRACE("(%p,%s,%s)\n", lpszDest, debugstr_w(lpszDir), debugstr_w(lpszFile)); - - /* Invalid parameters */ - if (!lpszDest) - return NULL; - if (!lpszDir && !lpszFile) - { - lpszDest[0] = 0; - return NULL; - } - - if ((!lpszFile || !*lpszFile) && lpszDir) - { - /* Use dir only */ - lstrcpynW(szTemp, lpszDir, MAX_PATH); - } - else if (!lpszDir || !*lpszDir || !PathIsRelativeW(lpszFile)) - { - if (!lpszDir || !*lpszDir || *lpszFile != '\\' || PathIsUNCW(lpszFile)) - { - /* Use file only */ - lstrcpynW(szTemp, lpszFile, MAX_PATH); - } - else - { - bUseBoth = TRUE; - bStrip = TRUE; - } - } - else - bUseBoth = TRUE; - - if (bUseBoth) - { - lstrcpynW(szTemp, lpszDir, MAX_PATH); - if (bStrip) - { - PathStripToRootW(szTemp); - lpszFile++; /* Skip '\' */ - } - if (!PathAddBackslashW(szTemp) || strlenW(szTemp) + strlenW(lpszFile) >= MAX_PATH) - { - lpszDest[0] = 0; - return NULL; - } - strcatW(szTemp, lpszFile); - } - - PathCanonicalizeW(lpszDest, szTemp); - return lpszDest; -} - -/************************************************************************* - * PathAddBackslashA [SHLWAPI.@] - * - * Append a backslash ('\') to a path if one doesn't exist. - * - * PARAMS - * lpszPath [I/O] The path to append a backslash to. - * - * RETURNS - * Success: The position of the last backslash in the path. - * Failure: NULL, if lpszPath is NULL or the path is too large. - */ -LPSTR WINAPI PathAddBackslashA(LPSTR lpszPath) -{ - size_t iLen; - LPSTR prev = lpszPath; - - TRACE("(%s)\n",debugstr_a(lpszPath)); - - if (!lpszPath || (iLen = strlen(lpszPath)) >= MAX_PATH) - return NULL; - - if (iLen) - { - do { - lpszPath = CharNextA(prev); - if (*lpszPath) - prev = lpszPath; - } while (*lpszPath); - if (*prev != '\\') - { - *lpszPath++ = '\\'; - *lpszPath = '\0'; - } - } - return lpszPath; -} - -/************************************************************************* - * PathAddBackslashW [SHLWAPI.@] - * - * See PathAddBackslashA. - */ -LPWSTR WINAPI PathAddBackslashW( LPWSTR lpszPath ) -{ - size_t iLen; - - TRACE("(%s)\n",debugstr_w(lpszPath)); - - if (!lpszPath || (iLen = strlenW(lpszPath)) >= MAX_PATH) - return NULL; - - if (iLen) - { - lpszPath += iLen; - if (lpszPath[-1] != '\\') - { - *lpszPath++ = '\\'; - *lpszPath = '\0'; - } - } - return lpszPath; -} - /************************************************************************* * PathBuildRootA [SHLWAPI.@] * @@ -359,389 +116,6 @@ LPWSTR WINAPI PathBuildRootW(LPWSTR lpszPath, int drive) return lpszPath; } -/************************************************************************* - * PathFindFileNameA [SHLWAPI.@] - * - * Locate the start of the file name in a path - * - * PARAMS - * lpszPath [I] Path to search - * - * RETURNS - * A pointer to the first character of the file name - */ -LPSTR WINAPI PathFindFileNameA(LPCSTR lpszPath) -{ - LPCSTR lastSlash = lpszPath; - - TRACE("(%s)\n",debugstr_a(lpszPath)); - - while (lpszPath && *lpszPath) - { - if ((*lpszPath == '\\' || *lpszPath == '/' || *lpszPath == ':') && - lpszPath[1] && lpszPath[1] != '\\' && lpszPath[1] != '/') - lastSlash = lpszPath + 1; - lpszPath = CharNextA(lpszPath); - } - return (LPSTR)lastSlash; -} - -/************************************************************************* - * PathFindFileNameW [SHLWAPI.@] - * - * See PathFindFileNameA. - */ -LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath) -{ - LPCWSTR lastSlash = lpszPath; - - TRACE("(%s)\n",debugstr_w(lpszPath)); - - while (lpszPath && *lpszPath) - { - if ((*lpszPath == '\\' || *lpszPath == '/' || *lpszPath == ':') && - lpszPath[1] && lpszPath[1] != '\\' && lpszPath[1] != '/') - lastSlash = lpszPath + 1; - lpszPath++; - } - return (LPWSTR)lastSlash; -} - -/************************************************************************* - * PathFindExtensionA [SHLWAPI.@] - * - * Locate the start of the file extension in a path - * - * PARAMS - * lpszPath [I] The path to search - * - * RETURNS - * A pointer to the first character of the extension, the end of - * the string if the path has no extension, or NULL If lpszPath is NULL - */ -LPSTR WINAPI PathFindExtensionA( LPCSTR lpszPath ) -{ - LPCSTR lastpoint = NULL; - - TRACE("(%s)\n", debugstr_a(lpszPath)); - - if (lpszPath) - { - while (*lpszPath) - { - if (*lpszPath == '\\' || *lpszPath==' ') - lastpoint = NULL; - else if (*lpszPath == '.') - lastpoint = lpszPath; - lpszPath = CharNextA(lpszPath); - } - } - return (LPSTR)(lastpoint ? lastpoint : lpszPath); -} - -/************************************************************************* - * PathFindExtensionW [SHLWAPI.@] - * - * See PathFindExtensionA. - */ -LPWSTR WINAPI PathFindExtensionW( LPCWSTR lpszPath ) -{ - LPCWSTR lastpoint = NULL; - - TRACE("(%s)\n", debugstr_w(lpszPath)); - - if (lpszPath) - { - while (*lpszPath) - { - if (*lpszPath == '\\' || *lpszPath==' ') - lastpoint = NULL; - else if (*lpszPath == '.') - lastpoint = lpszPath; - lpszPath++; - } - } - return (LPWSTR)(lastpoint ? lastpoint : lpszPath); -} - -/************************************************************************* - * PathGetArgsA [SHLWAPI.@] - * - * Find the next argument in a string delimited by spaces. - * - * PARAMS - * lpszPath [I] The string to search for arguments in - * - * RETURNS - * The start of the next argument in lpszPath, or NULL if lpszPath is NULL - * - * NOTES - * Spaces in quoted strings are ignored as delimiters. - */ -LPSTR WINAPI PathGetArgsA(LPCSTR lpszPath) -{ - BOOL bSeenQuote = FALSE; - - TRACE("(%s)\n",debugstr_a(lpszPath)); - - if (lpszPath) - { - while (*lpszPath) - { - if ((*lpszPath==' ') && !bSeenQuote) - return (LPSTR)lpszPath + 1; - if (*lpszPath == '"') - bSeenQuote = !bSeenQuote; - lpszPath = CharNextA(lpszPath); - } - } - return (LPSTR)lpszPath; -} - -/************************************************************************* - * PathGetArgsW [SHLWAPI.@] - * - * See PathGetArgsA. - */ -LPWSTR WINAPI PathGetArgsW(LPCWSTR lpszPath) -{ - BOOL bSeenQuote = FALSE; - - TRACE("(%s)\n",debugstr_w(lpszPath)); - - if (lpszPath) - { - while (*lpszPath) - { - if ((*lpszPath==' ') && !bSeenQuote) - return (LPWSTR)lpszPath + 1; - if (*lpszPath == '"') - bSeenQuote = !bSeenQuote; - lpszPath++; - } - } - return (LPWSTR)lpszPath; -} - -/************************************************************************* - * PathGetDriveNumberA [SHLWAPI.@] - * - * Return the drive number from a path - * - * PARAMS - * lpszPath [I] Path to get the drive number from - * - * RETURNS - * Success: The drive number corresponding to the drive in the path - * Failure: -1, if lpszPath contains no valid drive - */ -int WINAPI PathGetDriveNumberA(LPCSTR lpszPath) -{ - TRACE ("(%s)\n",debugstr_a(lpszPath)); - - if (lpszPath && !IsDBCSLeadByte(*lpszPath) && lpszPath[1] == ':' && - tolower(*lpszPath) >= 'a' && tolower(*lpszPath) <= 'z') - return tolower(*lpszPath) - 'a'; - return -1; -} - -/************************************************************************* - * PathGetDriveNumberW [SHLWAPI.@] - * - * See PathGetDriveNumberA. - */ -int WINAPI PathGetDriveNumberW(const WCHAR *path) -{ - WCHAR drive; - - static const WCHAR nt_prefixW[] = {'\\','\\','?','\\'}; - - TRACE("(%s)\n", debugstr_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'; -} - -/************************************************************************* - * PathRemoveFileSpecA [SHLWAPI.@] - * - * Remove the file specification from a path. - * - * PARAMS - * lpszPath [I/O] Path to remove the file spec from - * - * RETURNS - * TRUE If the path was valid and modified - * FALSE Otherwise - */ -BOOL WINAPI PathRemoveFileSpecA(LPSTR lpszPath) -{ - LPSTR lpszFileSpec = lpszPath; - BOOL bModified = FALSE; - - TRACE("(%s)\n",debugstr_a(lpszPath)); - - if(lpszPath) - { - /* Skip directory or UNC path */ - if (*lpszPath == '\\') - lpszFileSpec = ++lpszPath; - if (*lpszPath == '\\') - lpszFileSpec = ++lpszPath; - - while (*lpszPath) - { - if(*lpszPath == '\\') - lpszFileSpec = lpszPath; /* Skip dir */ - else if(*lpszPath == ':') - { - lpszFileSpec = ++lpszPath; /* Skip drive */ - if (*lpszPath == '\\') - lpszFileSpec++; - } - if (!(lpszPath = CharNextA(lpszPath))) - break; - } - - if (*lpszFileSpec) - { - *lpszFileSpec = '\0'; - bModified = TRUE; - } - } - return bModified; -} - -/************************************************************************* - * PathRemoveFileSpecW [SHLWAPI.@] - * - * See PathRemoveFileSpecA. - */ -BOOL WINAPI PathRemoveFileSpecW(LPWSTR lpszPath) -{ - LPWSTR lpszFileSpec = lpszPath; - BOOL bModified = FALSE; - - TRACE("(%s)\n",debugstr_w(lpszPath)); - - if(lpszPath) - { - /* Skip directory or UNC path */ - if (*lpszPath == '\\') - lpszFileSpec = ++lpszPath; - if (*lpszPath == '\\') - lpszFileSpec = ++lpszPath; - - while (*lpszPath) - { - if(*lpszPath == '\\') - lpszFileSpec = lpszPath; /* Skip dir */ - else if(*lpszPath == ':') - { - lpszFileSpec = ++lpszPath; /* Skip drive */ - if (*lpszPath == '\\') - lpszFileSpec++; - } - lpszPath++; - } - - if (*lpszFileSpec) - { - *lpszFileSpec = '\0'; - bModified = TRUE; - } - } - return bModified; -} - -/************************************************************************* - * PathStripPathA [SHLWAPI.@] - * - * Remove the initial path from the beginning of a filename - * - * PARAMS - * lpszPath [I/O] Path to remove the initial path from - * - * RETURNS - * Nothing. - */ -void WINAPI PathStripPathA(LPSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_a(lpszPath)); - - if (lpszPath) - { - LPSTR lpszFileName = PathFindFileNameA(lpszPath); - if(lpszFileName != lpszPath) - RtlMoveMemory(lpszPath, lpszFileName, strlen(lpszFileName)+1); - } -} - -/************************************************************************* - * PathStripPathW [SHLWAPI.@] - * - * See PathStripPathA. - */ -void WINAPI PathStripPathW(LPWSTR lpszPath) -{ - LPWSTR lpszFileName; - - TRACE("(%s)\n", debugstr_w(lpszPath)); - lpszFileName = PathFindFileNameW(lpszPath); - if(lpszFileName != lpszPath) - RtlMoveMemory(lpszPath, lpszFileName, (strlenW(lpszFileName)+1)*sizeof(WCHAR)); -} - -/************************************************************************* - * PathStripToRootA [SHLWAPI.@] - * - * Reduce a path to its root. - * - * PARAMS - * lpszPath [I/O] the path to reduce - * - * RETURNS - * Success: TRUE if the stripped path is a root path - * Failure: FALSE if the path cannot be stripped or is NULL - */ -BOOL WINAPI PathStripToRootA(LPSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_a(lpszPath)); - - if (!lpszPath) - return FALSE; - while(!PathIsRootA(lpszPath)) - if (!PathRemoveFileSpecA(lpszPath)) - return FALSE; - return TRUE; -} - -/************************************************************************* - * PathStripToRootW [SHLWAPI.@] - * - * See PathStripToRootA. - */ -BOOL WINAPI PathStripToRootW(LPWSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_w(lpszPath)); - - if (!lpszPath) - return FALSE; - while(!PathIsRootW(lpszPath)) - if (!PathRemoveFileSpecW(lpszPath)) - return FALSE; - return TRUE; -} - /************************************************************************* * PathRemoveArgsA [SHLWAPI.@] * @@ -788,333 +162,6 @@ void WINAPI PathRemoveArgsW(LPWSTR lpszPath) } } -/************************************************************************* - * PathRemoveExtensionA [SHLWAPI.@] - * - * Remove the file extension from a path - * - * PARAMS - * lpszPath [I/O] Path to remove the extension from - * - * NOTES - * The NUL terminator must be written only if extension exists - * and if the pointed character is not already NUL. - * - * RETURNS - * Nothing. - */ -void WINAPI PathRemoveExtensionA(LPSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_a(lpszPath)); - - if (lpszPath) - { - lpszPath = PathFindExtensionA(lpszPath); - if (lpszPath && *lpszPath != '\0') - *lpszPath = '\0'; - } -} - -/************************************************************************* - * PathRemoveExtensionW [SHLWAPI.@] - * - * See PathRemoveExtensionA. -*/ -void WINAPI PathRemoveExtensionW(LPWSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_w(lpszPath)); - - if (lpszPath) - { - lpszPath = PathFindExtensionW(lpszPath); - if (lpszPath && *lpszPath != '\0') - *lpszPath = '\0'; - } -} - -/************************************************************************* - * PathRemoveBackslashA [SHLWAPI.@] - * - * Remove a trailing backslash from a path. - * - * PARAMS - * lpszPath [I/O] Path to remove backslash from - * - * RETURNS - * Success: A pointer to the end of the path - * Failure: NULL, if lpszPath is NULL - */ -LPSTR WINAPI PathRemoveBackslashA( LPSTR lpszPath ) -{ - LPSTR szTemp = NULL; - - TRACE("(%s)\n", debugstr_a(lpszPath)); - - if(lpszPath) - { - szTemp = CharPrevA(lpszPath, lpszPath + strlen(lpszPath)); - if (!PathIsRootA(lpszPath) && *szTemp == '\\') - *szTemp = '\0'; - } - return szTemp; -} - -/************************************************************************* - * PathRemoveBackslashW [SHLWAPI.@] - * - * See PathRemoveBackslashA. - */ -LPWSTR WINAPI PathRemoveBackslashW( LPWSTR lpszPath ) -{ - LPWSTR szTemp = NULL; - - TRACE("(%s)\n", debugstr_w(lpszPath)); - - if(lpszPath) - { - szTemp = lpszPath + strlenW(lpszPath); - if (szTemp > lpszPath) szTemp--; - if (!PathIsRootW(lpszPath) && *szTemp == '\\') - *szTemp = '\0'; - } - return szTemp; -} - -/************************************************************************* - * PathRemoveBlanksA [SHLWAPI.@] - * - * Remove Spaces from the start and end of a path. - * - * PARAMS - * lpszPath [I/O] Path to strip blanks from - * - * RETURNS - * Nothing. - */ -void WINAPI PathRemoveBlanksA(LPSTR pszPath) -{ - LPSTR start, first; - - TRACE("(%s)\n", debugstr_a(pszPath)); - - if (!pszPath || !*pszPath) - return; - - start = first = pszPath; - - while (*pszPath == ' ') - pszPath = CharNextA(pszPath); - - while (*pszPath) - *start++ = *pszPath++; - - if (start != first) - while (start[-1] == ' ') - start--; - - *start = '\0'; -} - -/************************************************************************* - * PathRemoveBlanksW [SHLWAPI.@] - * - * See PathRemoveBlanksA. - */ -void WINAPI PathRemoveBlanksW(LPWSTR pszPath) -{ - LPWSTR start, first; - - TRACE("(%s)\n", debugstr_w(pszPath)); - - if (!pszPath || !*pszPath) - return; - - start = first = pszPath; - - while (*pszPath == ' ') - pszPath++; - - while (*pszPath) - *start++ = *pszPath++; - - if (start != first) - while (start[-1] == ' ') - start--; - - *start = '\0'; -} - -/************************************************************************* - * PathQuoteSpacesA [SHLWAPI.@] - * - * Surround a path containing spaces in quotes. - * - * PARAMS - * lpszPath [I/O] Path to quote - * - * RETURNS - * Nothing. - * - * NOTES - * The path is not changed if it is invalid or has no spaces. - */ -VOID WINAPI PathQuoteSpacesA(LPSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_a(lpszPath)); - - if(lpszPath && StrChrA(lpszPath,' ')) - { - size_t iLen = strlen(lpszPath) + 1; - - if (iLen + 2 < MAX_PATH) - { - memmove(lpszPath + 1, lpszPath, iLen); - lpszPath[0] = '"'; - lpszPath[iLen] = '"'; - lpszPath[iLen + 1] = '\0'; - } - } -} - -/************************************************************************* - * PathQuoteSpacesW [SHLWAPI.@] - * - * See PathQuoteSpacesA. - */ -VOID WINAPI PathQuoteSpacesW(LPWSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_w(lpszPath)); - - if(lpszPath && StrChrW(lpszPath,' ')) - { - int iLen = strlenW(lpszPath) + 1; - - if (iLen + 2 < MAX_PATH) - { - memmove(lpszPath + 1, lpszPath, iLen * sizeof(WCHAR)); - lpszPath[0] = '"'; - lpszPath[iLen] = '"'; - lpszPath[iLen + 1] = '\0'; - } - } -} - -/************************************************************************* - * PathUnquoteSpacesA [SHLWAPI.@] - * - * Remove quotes ("") from around a path, if present. - * - * PARAMS - * lpszPath [I/O] Path to strip quotes from - * - * RETURNS - * Nothing - * - * NOTES - * If the path contains a single quote only, an empty string will result. - * Otherwise quotes are only removed if they appear at the start and end - * of the path. - */ -VOID WINAPI PathUnquoteSpacesA(LPSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_a(lpszPath)); - - if (lpszPath && *lpszPath == '"') - { - DWORD dwLen = strlen(lpszPath) - 1; - - if (lpszPath[dwLen] == '"') - { - lpszPath[dwLen] = '\0'; - for (; *lpszPath; lpszPath++) - *lpszPath = lpszPath[1]; - } - } -} - -/************************************************************************* - * PathUnquoteSpacesW [SHLWAPI.@] - * - * See PathUnquoteSpacesA. - */ -VOID WINAPI PathUnquoteSpacesW(LPWSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_w(lpszPath)); - - if (lpszPath && *lpszPath == '"') - { - DWORD dwLen = strlenW(lpszPath) - 1; - - if (lpszPath[dwLen] == '"') - { - lpszPath[dwLen] = '\0'; - for (; *lpszPath; lpszPath++) - *lpszPath = lpszPath[1]; - } - } -} - -/************************************************************************* - * PathParseIconLocationA [SHLWAPI.@] - * - * Parse the location of an icon from a path. - * - * PARAMS - * lpszPath [I/O] The path to parse the icon location from. - * - * RETURNS - * Success: The number of the icon - * Failure: 0 if the path does not contain an icon location or is NULL - * - * NOTES - * The path has surrounding quotes and spaces removed regardless - * of whether the call succeeds or not. - */ -int WINAPI PathParseIconLocationA(LPSTR lpszPath) -{ - int iRet = 0; - LPSTR lpszComma; - - TRACE("(%s)\n", debugstr_a(lpszPath)); - - if (lpszPath) - { - if ((lpszComma = strchr(lpszPath, ','))) - { - *lpszComma++ = '\0'; - iRet = StrToIntA(lpszComma); - } - PathUnquoteSpacesA(lpszPath); - PathRemoveBlanksA(lpszPath); - } - return iRet; -} - -/************************************************************************* - * PathParseIconLocationW [SHLWAPI.@] - * - * See PathParseIconLocationA. - */ -int WINAPI PathParseIconLocationW(LPWSTR lpszPath) -{ - int iRet = 0; - LPWSTR lpszComma; - - TRACE("(%s)\n", debugstr_w(lpszPath)); - - if (lpszPath) - { - if ((lpszComma = StrChrW(lpszPath, ','))) - { - *lpszComma++ = '\0'; - iRet = StrToIntW(lpszComma); - } - PathUnquoteSpacesW(lpszPath); - PathRemoveBlanksW(lpszPath); - } - return iRet; -} - /************************************************************************* * @ [SHLWAPI.4] * @@ -1554,132 +601,6 @@ BOOL WINAPI PathCompactPathExW(LPWSTR lpszDest, LPCWSTR lpszPath, return TRUE; } -/************************************************************************* - * PathIsRelativeA [SHLWAPI.@] - * - * Determine if a path is a relative path. - * - * PARAMS - * lpszPath [I] Path to check - * - * RETURNS - * TRUE: The path is relative, or is invalid. - * FALSE: The path is not relative. - */ -BOOL WINAPI PathIsRelativeA (LPCSTR lpszPath) -{ - TRACE("(%s)\n",debugstr_a(lpszPath)); - - if (!lpszPath || !*lpszPath || IsDBCSLeadByte(*lpszPath)) - return TRUE; - if (*lpszPath == '\\' || (*lpszPath && lpszPath[1] == ':')) - return FALSE; - return TRUE; -} - -/************************************************************************* - * PathIsRelativeW [SHLWAPI.@] - * - * See PathIsRelativeA. - */ -BOOL WINAPI PathIsRelativeW (LPCWSTR lpszPath) -{ - TRACE("(%s)\n",debugstr_w(lpszPath)); - - if (!lpszPath || !*lpszPath) - return TRUE; - if (*lpszPath == '\\' || (*lpszPath && lpszPath[1] == ':')) - return FALSE; - return TRUE; -} - -/************************************************************************* - * PathIsRootA [SHLWAPI.@] - * - * Determine if a path is a root path. - * - * PARAMS - * lpszPath [I] Path to check - * - * RETURNS - * TRUE If lpszPath is valid and a root path, - * FALSE Otherwise - */ -BOOL WINAPI PathIsRootA(LPCSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_a(lpszPath)); - - if (lpszPath && *lpszPath) - { - if (*lpszPath == '\\') - { - if (!lpszPath[1]) - return TRUE; /* \ */ - else if (lpszPath[1]=='\\') - { - BOOL bSeenSlash = FALSE; - lpszPath += 2; - - /* Check for UNC root path */ - while (*lpszPath) - { - if (*lpszPath == '\\') - { - if (bSeenSlash) - return FALSE; - bSeenSlash = TRUE; - } - lpszPath = CharNextA(lpszPath); - } - return TRUE; - } - } - else if (lpszPath[1] == ':' && lpszPath[2] == '\\' && lpszPath[3] == '\0') - return TRUE; /* X:\ */ - } - return FALSE; -} - -/************************************************************************* - * PathIsRootW [SHLWAPI.@] - * - * See PathIsRootA. - */ -BOOL WINAPI PathIsRootW(LPCWSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_w(lpszPath)); - - if (lpszPath && *lpszPath) - { - if (*lpszPath == '\\') - { - if (!lpszPath[1]) - return TRUE; /* \ */ - else if (lpszPath[1]=='\\') - { - BOOL bSeenSlash = FALSE; - lpszPath += 2; - - /* Check for UNC root path */ - while (*lpszPath) - { - if (*lpszPath == '\\') - { - if (bSeenSlash) - return FALSE; - bSeenSlash = TRUE; - } - lpszPath++; - } - return TRUE; - } - } - else if (lpszPath[1] == ':' && lpszPath[2] == '\\' && lpszPath[3] == '\0') - return TRUE; /* X:\ */ - } - return FALSE; -} - /************************************************************************* * PathIsDirectoryA [SHLWAPI.@] * @@ -1784,56 +705,6 @@ BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath) return dwAttr & FILE_ATTRIBUTE_DIRECTORY; } -/************************************************************************* - * PathFileExistsA [SHLWAPI.@] - * - * Determine if a file exists. - * - * PARAMS - * lpszPath [I] Path to check - * - * RETURNS - * TRUE If the file exists and is readable - * FALSE Otherwise - */ -BOOL WINAPI PathFileExistsA(LPCSTR lpszPath) -{ - UINT iPrevErrMode; - DWORD dwAttr; - - TRACE("(%s)\n",debugstr_a(lpszPath)); - - if (!lpszPath) - return FALSE; - - /* Prevent a dialog box if path is on a disk that has been ejected. */ - iPrevErrMode = SetErrorMode(SEM_FAILCRITICALERRORS); - dwAttr = GetFileAttributesA(lpszPath); - SetErrorMode(iPrevErrMode); - return dwAttr != INVALID_FILE_ATTRIBUTES; -} - -/************************************************************************* - * PathFileExistsW [SHLWAPI.@] - * - * See PathFileExistsA. - */ -BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath) -{ - UINT iPrevErrMode; - DWORD dwAttr; - - TRACE("(%s)\n",debugstr_w(lpszPath)); - - if (!lpszPath) - return FALSE; - - iPrevErrMode = SetErrorMode(SEM_FAILCRITICALERRORS); - dwAttr = GetFileAttributesW(lpszPath); - SetErrorMode(iPrevErrMode); - return dwAttr != INVALID_FILE_ATTRIBUTES; -} - /************************************************************************* * PathFileExistsAndAttributesA [SHLWAPI.445] * @@ -1891,196 +762,6 @@ BOOL WINAPI PathFileExistsAndAttributesW(LPCWSTR lpszPath, DWORD *dwAttr) return (dwVal != INVALID_FILE_ATTRIBUTES); } -/************************************************************************* - * PathMatchSingleMaskA [internal] - */ -static BOOL PathMatchSingleMaskA(LPCSTR name, LPCSTR mask) -{ - while (*name && *mask && *mask!=';') - { - if (*mask == '*') - { - do - { - if (PathMatchSingleMaskA(name,mask+1)) - return TRUE; /* try substrings */ - } while (*name++); - return FALSE; - } - - if (toupper(*mask) != toupper(*name) && *mask != '?') - return FALSE; - - name = CharNextA(name); - mask = CharNextA(mask); - } - - if (!*name) - { - while (*mask == '*') - mask++; - if (!*mask || *mask == ';') - return TRUE; - } - return FALSE; -} - -/************************************************************************* - * PathMatchSingleMaskW [internal] - */ -static BOOL PathMatchSingleMaskW(LPCWSTR name, LPCWSTR mask) -{ - while (*name && *mask && *mask != ';') - { - if (*mask == '*') - { - do - { - if (PathMatchSingleMaskW(name,mask+1)) - return TRUE; /* try substrings */ - } while (*name++); - return FALSE; - } - - if (toupperW(*mask) != toupperW(*name) && *mask != '?') - return FALSE; - - name++; - mask++; - } - if (!*name) - { - while (*mask == '*') - mask++; - if (!*mask || *mask == ';') - return TRUE; - } - return FALSE; -} - -/************************************************************************* - * PathMatchSpecA [SHLWAPI.@] - * - * Determine if a path matches one or more search masks. - * - * PARAMS - * lpszPath [I] Path to check - * lpszMask [I] Search mask(s) - * - * RETURNS - * TRUE If lpszPath is valid and is matched - * FALSE Otherwise - * - * NOTES - * Multiple search masks may be given if they are separated by ";". The - * pattern "*.*" is treated specially in that it matches all paths (for - * backwards compatibility with DOS). - */ -BOOL WINAPI PathMatchSpecA(LPCSTR lpszPath, LPCSTR lpszMask) -{ - TRACE("(%s,%s)\n", lpszPath, lpszMask); - - if (!lstrcmpA(lpszMask, "*.*")) - return TRUE; /* Matches every path */ - - while (*lpszMask) - { - while (*lpszMask == ' ') - lpszMask++; /* Eat leading spaces */ - - if (PathMatchSingleMaskA(lpszPath, lpszMask)) - return TRUE; /* Matches the current mask */ - - while (*lpszMask && *lpszMask != ';') - lpszMask = CharNextA(lpszMask); /* masks separated by ';' */ - - if (*lpszMask == ';') - lpszMask++; - } - return FALSE; -} - -/************************************************************************* - * PathMatchSpecW [SHLWAPI.@] - * - * See PathMatchSpecA. - */ -BOOL WINAPI PathMatchSpecW(LPCWSTR lpszPath, LPCWSTR lpszMask) -{ - static const WCHAR szStarDotStar[] = { '*', '.', '*', '\0' }; - - TRACE("(%s,%s)\n", debugstr_w(lpszPath), debugstr_w(lpszMask)); - - if (!lstrcmpW(lpszMask, szStarDotStar)) - return TRUE; /* Matches every path */ - - while (*lpszMask) - { - while (*lpszMask == ' ') - lpszMask++; /* Eat leading spaces */ - - if (PathMatchSingleMaskW(lpszPath, lpszMask)) - return TRUE; /* Matches the current path */ - - while (*lpszMask && *lpszMask != ';') - lpszMask++; /* masks separated by ';' */ - - if (*lpszMask == ';') - lpszMask++; - } - return FALSE; -} - -/************************************************************************* - * PathIsSameRootA [SHLWAPI.@] - * - * Determine if two paths share the same root. - * - * PARAMS - * lpszPath1 [I] Source path - * lpszPath2 [I] Path to compare with - * - * RETURNS - * TRUE If both paths are valid and share the same root. - * FALSE If either path is invalid or the paths do not share the same root. - */ -BOOL WINAPI PathIsSameRootA(LPCSTR lpszPath1, LPCSTR lpszPath2) -{ - LPCSTR lpszStart; - int dwLen; - - TRACE("(%s,%s)\n", debugstr_a(lpszPath1), debugstr_a(lpszPath2)); - - if (!lpszPath1 || !lpszPath2 || !(lpszStart = PathSkipRootA(lpszPath1))) - return FALSE; - - dwLen = PathCommonPrefixA(lpszPath1, lpszPath2, NULL) + 1; - if (lpszStart - lpszPath1 > dwLen) - return FALSE; /* Paths not common up to length of the root */ - return TRUE; -} - -/************************************************************************* - * PathIsSameRootW [SHLWAPI.@] - * - * See PathIsSameRootA. - */ -BOOL WINAPI PathIsSameRootW(LPCWSTR lpszPath1, LPCWSTR lpszPath2) -{ - LPCWSTR lpszStart; - int dwLen; - - TRACE("(%s,%s)\n", debugstr_w(lpszPath1), debugstr_w(lpszPath2)); - - if (!lpszPath1 || !lpszPath2 || !(lpszStart = PathSkipRootW(lpszPath1))) - return FALSE; - - dwLen = PathCommonPrefixW(lpszPath1, lpszPath2, NULL) + 1; - if (lpszStart - lpszPath1 > dwLen) - return FALSE; /* Paths not common up to length of the root */ - return TRUE; -} - /************************************************************************* * PathIsContentTypeA [SHLWAPI.@] * @@ -2137,93 +818,6 @@ BOOL WINAPI PathIsContentTypeW(LPCWSTR lpszPath, LPCWSTR lpszContentType) return FALSE; } -/************************************************************************* - * PathIsFileSpecA [SHLWAPI.@] - * - * Determine if a path is a file specification. - * - * PARAMS - * lpszPath [I] Path to check - * - * RETURNS - * TRUE If lpszPath is a file specification (i.e. Contains no directories). - * FALSE Otherwise. - */ -BOOL WINAPI PathIsFileSpecA(LPCSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_a(lpszPath)); - - if (!lpszPath) - return FALSE; - - while (*lpszPath) - { - if (*lpszPath == '\\' || *lpszPath == ':') - return FALSE; - lpszPath = CharNextA(lpszPath); - } - return TRUE; -} - -/************************************************************************* - * PathIsFileSpecW [SHLWAPI.@] - * - * See PathIsFileSpecA. - */ -BOOL WINAPI PathIsFileSpecW(LPCWSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_w(lpszPath)); - - if (!lpszPath) - return FALSE; - - while (*lpszPath) - { - if (*lpszPath == '\\' || *lpszPath == ':') - return FALSE; - lpszPath++; - } - return TRUE; -} - -/************************************************************************* - * PathIsPrefixA [SHLWAPI.@] - * - * Determine if a path is a prefix of another. - * - * PARAMS - * lpszPrefix [I] Prefix - * lpszPath [I] Path to check - * - * RETURNS - * TRUE If lpszPath has lpszPrefix as its prefix, - * FALSE If either path is NULL or lpszPrefix is not a prefix - */ -BOOL WINAPI PathIsPrefixA (LPCSTR lpszPrefix, LPCSTR lpszPath) -{ - TRACE("(%s,%s)\n", debugstr_a(lpszPrefix), debugstr_a(lpszPath)); - - if (lpszPrefix && lpszPath && - PathCommonPrefixA(lpszPath, lpszPrefix, NULL) == (int)strlen(lpszPrefix)) - return TRUE; - return FALSE; -} - -/************************************************************************* - * PathIsPrefixW [SHLWAPI.@] - * - * See PathIsPrefixA. - */ -BOOL WINAPI PathIsPrefixW(LPCWSTR lpszPrefix, LPCWSTR lpszPath) -{ - TRACE("(%s,%s)\n", debugstr_w(lpszPrefix), debugstr_w(lpszPath)); - - if (lpszPrefix && lpszPath && - PathCommonPrefixW(lpszPath, lpszPrefix, NULL) == (int)strlenW(lpszPrefix)) - return TRUE; - return FALSE; -} - /************************************************************************* * PathIsSystemFolderA [SHLWAPI.@] * @@ -2268,431 +862,6 @@ BOOL WINAPI PathIsSystemFolderW(LPCWSTR lpszPath, DWORD dwAttrib) return TRUE; } -/************************************************************************* - * PathIsUNCA [SHLWAPI.@] - * - * Determine if a path is in UNC format. - * - * PARAMS - * lpszPath [I] Path to check - * - * RETURNS - * TRUE: The path is UNC. - * FALSE: The path is not UNC or is NULL. - */ -BOOL WINAPI PathIsUNCA(LPCSTR lpszPath) -{ - TRACE("(%s)\n",debugstr_a(lpszPath)); - -/* - * On Windows 2003, tests show that strings starting with "\\?" are - * considered UNC, while on Windows Vista+ this is not the case anymore. - */ -// #ifdef __REACTOS__ -#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA) - if (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\') && (lpszPath[2]!='?')) -#else - if (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\')) -#endif - return TRUE; - return FALSE; -} - -/************************************************************************* - * PathIsUNCW [SHLWAPI.@] - * - * See PathIsUNCA. - */ -BOOL WINAPI PathIsUNCW(LPCWSTR lpszPath) -{ - TRACE("(%s)\n",debugstr_w(lpszPath)); - -/* - * On Windows 2003, tests show that strings starting with "\\?" are - * considered UNC, while on Windows Vista+ this is not the case anymore. - */ -// #ifdef __REACTOS__ -#if (_WIN32_WINNT >= _WIN32_WINNT_VISTA) - if (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\') && (lpszPath[2]!='?')) -#else - if (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\')) -#endif - return TRUE; - return FALSE; -} - -/************************************************************************* - * PathIsUNCServerA [SHLWAPI.@] - * - * Determine if a path is a UNC server name ("\\SHARENAME"). - * - * PARAMS - * lpszPath [I] Path to check. - * - * RETURNS - * TRUE If lpszPath is a valid UNC server name. - * FALSE Otherwise. - * - * NOTES - * This routine is bug compatible with Win32: Server names with a - * trailing backslash (e.g. "\\FOO\"), return FALSE incorrectly. - * Fixing this bug may break other shlwapi functions! - */ -BOOL WINAPI PathIsUNCServerA(LPCSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_a(lpszPath)); - - if (lpszPath && *lpszPath++ == '\\' && *lpszPath++ == '\\') - { - while (*lpszPath) - { - if (*lpszPath == '\\') - return FALSE; - lpszPath = CharNextA(lpszPath); - } - return TRUE; - } - return FALSE; -} - -/************************************************************************* - * PathIsUNCServerW [SHLWAPI.@] - * - * See PathIsUNCServerA. - */ -BOOL WINAPI PathIsUNCServerW(LPCWSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_w(lpszPath)); - - if (lpszPath && lpszPath[0] == '\\' && lpszPath[1] == '\\') - { - return !strchrW( lpszPath + 2, '\\' ); - } - return FALSE; -} - -/************************************************************************* - * PathIsUNCServerShareA [SHLWAPI.@] - * - * Determine if a path is a UNC server share ("\\SHARENAME\SHARE"). - * - * PARAMS - * lpszPath [I] Path to check. - * - * RETURNS - * TRUE If lpszPath is a valid UNC server share. - * FALSE Otherwise. - * - * NOTES - * This routine is bug compatible with Win32: Server shares with a - * trailing backslash (e.g. "\\FOO\BAR\"), return FALSE incorrectly. - * Fixing this bug may break other shlwapi functions! - */ -BOOL WINAPI PathIsUNCServerShareA(LPCSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_a(lpszPath)); - - if (lpszPath && *lpszPath++ == '\\' && *lpszPath++ == '\\') - { - BOOL bSeenSlash = FALSE; - while (*lpszPath) - { - if (*lpszPath == '\\') - { - if (bSeenSlash) - return FALSE; - bSeenSlash = TRUE; - } - lpszPath = CharNextA(lpszPath); - } - return bSeenSlash; - } - return FALSE; -} - -/************************************************************************* - * PathIsUNCServerShareW [SHLWAPI.@] - * - * See PathIsUNCServerShareA. - */ -BOOL WINAPI PathIsUNCServerShareW(LPCWSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_w(lpszPath)); - - if (lpszPath && *lpszPath++ == '\\' && *lpszPath++ == '\\') - { - BOOL bSeenSlash = FALSE; - while (*lpszPath) - { - if (*lpszPath == '\\') - { - if (bSeenSlash) - return FALSE; - bSeenSlash = TRUE; - } - lpszPath++; - } - return bSeenSlash; - } - return FALSE; -} - -/************************************************************************* - * PathCanonicalizeA [SHLWAPI.@] - * - * Convert a path to its canonical form. - * - * PARAMS - * lpszBuf [O] Output path - * lpszPath [I] Path to canonicalize - * - * RETURNS - * Success: TRUE. lpszBuf contains the output path, - * Failure: FALSE, If input path is invalid. lpszBuf is undefined - */ -BOOL WINAPI PathCanonicalizeA(LPSTR lpszBuf, LPCSTR lpszPath) -{ - BOOL bRet = FALSE; - - TRACE("(%p,%s)\n", lpszBuf, debugstr_a(lpszPath)); - - if (lpszBuf) - *lpszBuf = '\0'; - - if (!lpszBuf || !lpszPath) - SetLastError(ERROR_INVALID_PARAMETER); - else - { - WCHAR szPath[MAX_PATH]; - WCHAR szBuff[MAX_PATH]; - int ret = MultiByteToWideChar(CP_ACP,0,lpszPath,-1,szPath,MAX_PATH); - - if (!ret) { - WARN("Failed to convert string to widechar (too long?), LE %d.\n", GetLastError()); - return FALSE; - } - bRet = PathCanonicalizeW(szBuff, szPath); - WideCharToMultiByte(CP_ACP,0,szBuff,-1,lpszBuf,MAX_PATH,0,0); - } - return bRet; -} - - -/************************************************************************* - * PathCanonicalizeW [SHLWAPI.@] - * - * See PathCanonicalizeA. - */ -BOOL WINAPI PathCanonicalizeW(LPWSTR lpszBuf, LPCWSTR lpszPath) -{ - LPWSTR lpszDst = lpszBuf; - LPCWSTR lpszSrc = lpszPath; - - TRACE("(%p,%s)\n", lpszBuf, debugstr_w(lpszPath)); - - if (lpszBuf) - *lpszDst = '\0'; - - if (!lpszBuf || !lpszPath) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if (!*lpszPath) - { - *lpszBuf++ = '\\'; - *lpszBuf = '\0'; - return TRUE; - } - - /* Copy path root */ - if (*lpszSrc == '\\') - { - *lpszDst++ = *lpszSrc++; - } - else if (*lpszSrc && lpszSrc[1] == ':') - { - /* X:\ */ - *lpszDst++ = *lpszSrc++; - *lpszDst++ = *lpszSrc++; - if (*lpszSrc == '\\') - *lpszDst++ = *lpszSrc++; - } - - /* Canonicalize the rest of the path */ - while (*lpszSrc) - { - if (*lpszSrc == '.') - { - if (lpszSrc[1] == '\\' && (lpszSrc == lpszPath || lpszSrc[-1] == '\\' || lpszSrc[-1] == ':')) - { - lpszSrc += 2; /* Skip .\ */ - } - else if (lpszSrc[1] == '.' && (lpszDst == lpszBuf || lpszDst[-1] == '\\')) - { - /* \.. backs up a directory, over the root if it has no \ following X:. - * .. is ignored if it would remove a UNC server name or initial \\ - */ - if (lpszDst != lpszBuf) - { - *lpszDst = '\0'; /* Allow PathIsUNCServerShareA test on lpszBuf */ - if (lpszDst > lpszBuf+1 && lpszDst[-1] == '\\' && - (lpszDst[-2] != '\\' || lpszDst > lpszBuf+2)) - { - if (lpszDst[-2] == ':' && (lpszDst > lpszBuf+3 || lpszDst[-3] == ':')) - { - lpszDst -= 2; - while (lpszDst > lpszBuf && *lpszDst != '\\') - lpszDst--; - if (*lpszDst == '\\') - lpszDst++; /* Reset to last '\' */ - else - lpszDst = lpszBuf; /* Start path again from new root */ - } - else if (lpszDst[-2] != ':' && !PathIsUNCServerShareW(lpszBuf)) - lpszDst -= 2; - } - while (lpszDst > lpszBuf && *lpszDst != '\\') - lpszDst--; - if (lpszDst == lpszBuf) - { - *lpszDst++ = '\\'; - lpszSrc++; - } - } - lpszSrc += 2; /* Skip .. in src path */ - } - else - *lpszDst++ = *lpszSrc++; - } - else - *lpszDst++ = *lpszSrc++; - } - /* Append \ to naked drive specs */ - if (lpszDst - lpszBuf == 2 && lpszDst[-1] == ':') - *lpszDst++ = '\\'; - *lpszDst++ = '\0'; - return TRUE; -} - -/************************************************************************* - * PathFindNextComponentA [SHLWAPI.@] - * - * Find the next component in a path. - * - * PARAMS - * lpszPath [I] Path to find next component in - * - * RETURNS - * Success: A pointer to the next component, or the end of the string. - * Failure: NULL, If lpszPath is invalid - * - * NOTES - * A 'component' is either a backslash character (\) or UNC marker (\\). - * Because of this, relative paths (e.g "c:foo") are regarded as having - * only one component. - */ -LPSTR WINAPI PathFindNextComponentA(LPCSTR lpszPath) -{ - LPSTR lpszSlash; - - TRACE("(%s)\n", debugstr_a(lpszPath)); - - if(!lpszPath || !*lpszPath) - return NULL; - - if ((lpszSlash = StrChrA(lpszPath, '\\'))) - { - if (lpszSlash[1] == '\\') - lpszSlash++; - return lpszSlash + 1; - } - return (LPSTR)lpszPath + strlen(lpszPath); -} - -/************************************************************************* - * PathFindNextComponentW [SHLWAPI.@] - * - * See PathFindNextComponentA. - */ -LPWSTR WINAPI PathFindNextComponentW(LPCWSTR lpszPath) -{ - LPWSTR lpszSlash; - - TRACE("(%s)\n", debugstr_w(lpszPath)); - - if(!lpszPath || !*lpszPath) - return NULL; - - if ((lpszSlash = StrChrW(lpszPath, '\\'))) - { - if (lpszSlash[1] == '\\') - lpszSlash++; - return lpszSlash + 1; - } - return (LPWSTR)lpszPath + strlenW(lpszPath); -} - -/************************************************************************* - * PathAddExtensionA [SHLWAPI.@] - * - * Add a file extension to a path - * - * PARAMS - * lpszPath [I/O] Path to add extension to - * lpszExtension [I] Extension to add to lpszPath - * - * RETURNS - * TRUE If the path was modified, - * FALSE If lpszPath or lpszExtension are invalid, lpszPath has an - * extension already, or the new path length is too big. - * - * FIXME - * What version of shlwapi.dll adds "exe" if lpszExtension is NULL? Win2k - * does not do this, so the behaviour was removed. - */ -BOOL WINAPI PathAddExtensionA(LPSTR lpszPath, LPCSTR lpszExtension) -{ - size_t dwLen; - - TRACE("(%s,%s)\n", debugstr_a(lpszPath), debugstr_a(lpszExtension)); - - if (!lpszPath || !lpszExtension || *(PathFindExtensionA(lpszPath))) - return FALSE; - - dwLen = strlen(lpszPath); - - if (dwLen + strlen(lpszExtension) >= MAX_PATH) - return FALSE; - - strcpy(lpszPath + dwLen, lpszExtension); - return TRUE; -} - -/************************************************************************* - * PathAddExtensionW [SHLWAPI.@] - * - * See PathAddExtensionA. - */ -BOOL WINAPI PathAddExtensionW(LPWSTR lpszPath, LPCWSTR lpszExtension) -{ - size_t dwLen; - - TRACE("(%s,%s)\n", debugstr_w(lpszPath), debugstr_w(lpszExtension)); - - if (!lpszPath || !lpszExtension || *(PathFindExtensionW(lpszPath))) - return FALSE; - - dwLen = strlenW(lpszPath); - - if (dwLen + strlenW(lpszExtension) >= MAX_PATH) - return FALSE; - - strcpyW(lpszPath + dwLen, lpszExtension); - return TRUE; -} - /************************************************************************* * PathMakePrettyA [SHLWAPI.@] * @@ -2764,135 +933,6 @@ BOOL WINAPI PathMakePrettyW(LPWSTR lpszPath) return TRUE; } -/************************************************************************* - * PathCommonPrefixA [SHLWAPI.@] - * - * Determine the length of the common prefix between two paths. - * - * PARAMS - * lpszFile1 [I] First path for comparison - * lpszFile2 [I] Second path for comparison - * achPath [O] Destination for common prefix string - * - * RETURNS - * The length of the common prefix. This is 0 if there is no common - * prefix between the paths or if any parameters are invalid. If the prefix - * is non-zero and achPath is not NULL, achPath is filled with the common - * part of the prefix and NUL terminated. - * - * NOTES - * A common prefix of 2 is always returned as 3. It is thus possible for - * the length returned to be invalid (i.e. Longer than one or both of the - * strings given as parameters). This Win32 behaviour has been implemented - * here, and cannot be changed (fixed?) without breaking other SHLWAPI calls. - * To work around this when using this function, always check that the byte - * at [common_prefix_len-1] is not a NUL. If it is, deduct 1 from the prefix. - */ -int WINAPI PathCommonPrefixA(LPCSTR lpszFile1, LPCSTR lpszFile2, LPSTR achPath) -{ - size_t iLen = 0; - LPCSTR lpszIter1 = lpszFile1; - LPCSTR lpszIter2 = lpszFile2; - - TRACE("(%s,%s,%p)\n", debugstr_a(lpszFile1), debugstr_a(lpszFile2), achPath); - - if (achPath) - *achPath = '\0'; - - if (!lpszFile1 || !lpszFile2) - return 0; - - /* Handle roots first */ - if (PathIsUNCA(lpszFile1)) - { - if (!PathIsUNCA(lpszFile2)) - return 0; - lpszIter1 += 2; - lpszIter2 += 2; - } - else if (PathIsUNCA(lpszFile2)) - return 0; /* Know already lpszFile1 is not UNC */ - - do - { - /* Update len */ - if ((!*lpszIter1 || *lpszIter1 == '\\') && - (!*lpszIter2 || *lpszIter2 == '\\')) - iLen = lpszIter1 - lpszFile1; /* Common to this point */ - - if (!*lpszIter1 || (tolower(*lpszIter1) != tolower(*lpszIter2))) - break; /* Strings differ at this point */ - - lpszIter1++; - lpszIter2++; - } while (1); - - if (iLen == 2) - iLen++; /* Feature/Bug compatible with Win32 */ - - if (iLen && achPath) - { - memcpy(achPath,lpszFile1,iLen); - achPath[iLen] = '\0'; - } - return iLen; -} - -/************************************************************************* - * PathCommonPrefixW [SHLWAPI.@] - * - * See PathCommonPrefixA. - */ -int WINAPI PathCommonPrefixW(LPCWSTR lpszFile1, LPCWSTR lpszFile2, LPWSTR achPath) -{ - size_t iLen = 0; - LPCWSTR lpszIter1 = lpszFile1; - LPCWSTR lpszIter2 = lpszFile2; - - TRACE("(%s,%s,%p)\n", debugstr_w(lpszFile1), debugstr_w(lpszFile2), achPath); - - if (achPath) - *achPath = '\0'; - - if (!lpszFile1 || !lpszFile2) - return 0; - - /* Handle roots first */ - if (PathIsUNCW(lpszFile1)) - { - if (!PathIsUNCW(lpszFile2)) - return 0; - lpszIter1 += 2; - lpszIter2 += 2; - } - else if (PathIsUNCW(lpszFile2)) - return 0; /* Know already lpszFile1 is not UNC */ - - do - { - /* Update len */ - if ((!*lpszIter1 || *lpszIter1 == '\\') && - (!*lpszIter2 || *lpszIter2 == '\\')) - iLen = lpszIter1 - lpszFile1; /* Common to this point */ - - if (!*lpszIter1 || (tolowerW(*lpszIter1) != tolowerW(*lpszIter2))) - break; /* Strings differ at this point */ - - lpszIter1++; - lpszIter2++; - } while (1); - - if (iLen == 2) - iLen++; /* Feature/Bug compatible with Win32 */ - - if (iLen && achPath) - { - memcpy(achPath,lpszFile1,iLen * sizeof(WCHAR)); - achPath[iLen] = '\0'; - } - return iLen; -} - /************************************************************************* * PathCompactPathA [SHLWAPI.@] * @@ -3052,56 +1092,6 @@ end: return bRet; } -/************************************************************************* - * PathGetCharTypeA [SHLWAPI.@] - * - * Categorise a character from a file path. - * - * PARAMS - * ch [I] Character to get the type of - * - * RETURNS - * A set of GCT_ bit flags (from "shlwapi.h") indicating the character type. - */ -UINT WINAPI PathGetCharTypeA(UCHAR ch) -{ - return PathGetCharTypeW(ch); -} - -/************************************************************************* - * PathGetCharTypeW [SHLWAPI.@] - * - * See PathGetCharTypeA. - */ -UINT WINAPI PathGetCharTypeW(WCHAR ch) -{ - UINT flags = 0; - - TRACE("(%d)\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; -} - /************************************************************************* * SHLWAPI_UseSystemForSystemFolders * @@ -3188,491 +1178,6 @@ BOOL WINAPI PathMakeSystemFolderW(LPCWSTR lpszPath) return SetFileAttributesW(lpszPath, dwAttr | dwDefaultAttr); } -/************************************************************************* - * PathRenameExtensionA [SHLWAPI.@] - * - * Swap the file extension in a path with another extension. - * - * PARAMS - * lpszPath [I/O] Path to swap the extension in - * lpszExt [I] The new extension - * - * RETURNS - * TRUE if lpszPath was modified, - * FALSE if lpszPath or lpszExt is NULL, or the new path is too long - */ -BOOL WINAPI PathRenameExtensionA(LPSTR lpszPath, LPCSTR lpszExt) -{ - LPSTR lpszExtension; - - TRACE("(%s,%s)\n", debugstr_a(lpszPath), debugstr_a(lpszExt)); - - lpszExtension = PathFindExtensionA(lpszPath); - - if (!lpszExtension || (lpszExtension - lpszPath + strlen(lpszExt) >= MAX_PATH)) - return FALSE; - - strcpy(lpszExtension, lpszExt); - return TRUE; -} - -/************************************************************************* - * PathRenameExtensionW [SHLWAPI.@] - * - * See PathRenameExtensionA. - */ -BOOL WINAPI PathRenameExtensionW(LPWSTR lpszPath, LPCWSTR lpszExt) -{ - LPWSTR lpszExtension; - - TRACE("(%s,%s)\n", debugstr_w(lpszPath), debugstr_w(lpszExt)); - - lpszExtension = PathFindExtensionW(lpszPath); - - if (!lpszExtension || (lpszExtension - lpszPath + strlenW(lpszExt) >= MAX_PATH)) - return FALSE; - - strcpyW(lpszExtension, lpszExt); - return TRUE; -} - -/************************************************************************* - * PathSearchAndQualifyA [SHLWAPI.@] - * - * Determine if a given path is correct and fully qualified. - * - * PARAMS - * lpszPath [I] Path to check - * lpszBuf [O] Output for correct path - * cchBuf [I] Size of lpszBuf - * - * RETURNS - * Unknown. - */ -BOOL WINAPI PathSearchAndQualifyA(LPCSTR lpszPath, LPSTR lpszBuf, UINT cchBuf) -{ - TRACE("(%s,%p,0x%08x)\n", debugstr_a(lpszPath), lpszBuf, cchBuf); - - if(SearchPathA(NULL, lpszPath, NULL, cchBuf, lpszBuf, NULL)) - return TRUE; - return !!GetFullPathNameA(lpszPath, cchBuf, lpszBuf, NULL); -} - -/************************************************************************* - * PathSearchAndQualifyW [SHLWAPI.@] - * - * See PathSearchAndQualifyA. - */ -BOOL WINAPI PathSearchAndQualifyW(LPCWSTR lpszPath, LPWSTR lpszBuf, UINT cchBuf) -{ - TRACE("(%s,%p,0x%08x)\n", debugstr_w(lpszPath), lpszBuf, cchBuf); - - if(SearchPathW(NULL, lpszPath, NULL, cchBuf, lpszBuf, NULL)) - return TRUE; - return !!GetFullPathNameW(lpszPath, cchBuf, lpszBuf, NULL); -} - -/************************************************************************* - * PathSkipRootA [SHLWAPI.@] - * - * Return the portion of a path following the drive letter or mount point. - * - * PARAMS - * lpszPath [I] The path to skip on - * - * RETURNS - * Success: A pointer to the next character after the root. - * Failure: NULL, if lpszPath is invalid, has no root or is a multibyte string. - */ -LPSTR WINAPI PathSkipRootA(LPCSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_a(lpszPath)); - - if (!lpszPath || !*lpszPath) - return NULL; - - if (*lpszPath == '\\' && lpszPath[1] == '\\') - { - /* Network share: skip share server and mount point */ - lpszPath += 2; - if ((lpszPath = StrChrA(lpszPath, '\\')) && - (lpszPath = StrChrA(lpszPath + 1, '\\'))) - lpszPath++; - return (LPSTR)lpszPath; - } - - if (IsDBCSLeadByte(*lpszPath)) - return NULL; - - /* Check x:\ */ - if (lpszPath[0] && lpszPath[1] == ':' && lpszPath[2] == '\\') - return (LPSTR)lpszPath + 3; - return NULL; -} - -/************************************************************************* - * PathSkipRootW [SHLWAPI.@] - * - * See PathSkipRootA. - */ -LPWSTR WINAPI PathSkipRootW(LPCWSTR lpszPath) -{ - TRACE("(%s)\n", debugstr_w(lpszPath)); - - if (!lpszPath || !*lpszPath) - return NULL; - - if (*lpszPath == '\\' && lpszPath[1] == '\\') - { - /* Network share: skip share server and mount point */ - lpszPath += 2; - if ((lpszPath = StrChrW(lpszPath, '\\')) && - (lpszPath = StrChrW(lpszPath + 1, '\\'))) - lpszPath++; - return (LPWSTR)lpszPath; - } - - /* Check x:\ */ - if (lpszPath[0] && lpszPath[1] == ':' && lpszPath[2] == '\\') - return (LPWSTR)lpszPath + 3; - return NULL; -} - -/************************************************************************* - * PathCreateFromUrlA [SHLWAPI.@] - * - * See PathCreateFromUrlW - */ -HRESULT WINAPI PathCreateFromUrlA(LPCSTR pszUrl, LPSTR pszPath, - LPDWORD pcchPath, DWORD dwReserved) -{ - WCHAR bufW[MAX_PATH]; - WCHAR *pathW = bufW; - UNICODE_STRING urlW; - HRESULT ret; - DWORD lenW = sizeof(bufW)/sizeof(WCHAR), lenA; - - if (!pszUrl || !pszPath || !pcchPath || !*pcchPath) - return E_INVALIDARG; - - if(!RtlCreateUnicodeStringFromAsciiz(&urlW, pszUrl)) - return E_INVALIDARG; - if((ret = PathCreateFromUrlW(urlW.Buffer, pathW, &lenW, dwReserved)) == E_POINTER) { - pathW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR)); - ret = PathCreateFromUrlW(urlW.Buffer, pathW, &lenW, dwReserved); - } - if(ret == S_OK) { - RtlUnicodeToMultiByteSize(&lenA, pathW, lenW * sizeof(WCHAR)); - if(*pcchPath > lenA) { - RtlUnicodeToMultiByteN(pszPath, *pcchPath - 1, &lenA, pathW, lenW * sizeof(WCHAR)); - pszPath[lenA] = 0; - *pcchPath = lenA; - } else { - *pcchPath = lenA + 1; - ret = E_POINTER; - } - } - if(pathW != bufW) HeapFree(GetProcessHeap(), 0, pathW); - RtlFreeUnicodeString(&urlW); - return ret; -} - -/************************************************************************* - * PathCreateFromUrlW [SHLWAPI.@] - * - * Create a path from a URL - * - * PARAMS - * lpszUrl [I] URL to convert into a path - * lpszPath [O] Output buffer for the resulting Path - * pcchPath [I] Length of lpszPath - * dwFlags [I] Flags controlling the conversion - * - * RETURNS - * Success: S_OK. lpszPath contains the URL in path format, - * Failure: An HRESULT error code such as E_INVALIDARG. - */ -HRESULT WINAPI PathCreateFromUrlW(LPCWSTR pszUrl, LPWSTR pszPath, - LPDWORD pcchPath, DWORD dwReserved) -{ - static const WCHAR file_colon[] = { 'f','i','l','e',':',0 }; - static const WCHAR localhost[] = { 'l','o','c','a','l','h','o','s','t',0 }; - DWORD nslashes, unescape, len; - const WCHAR *src; - WCHAR *tpath, *dst; - HRESULT ret; - - TRACE("(%s,%p,%p,0x%08x)\n", debugstr_w(pszUrl), pszPath, pcchPath, dwReserved); - - if (!pszUrl || !pszPath || !pcchPath || !*pcchPath) - return E_INVALIDARG; - - if (lstrlenW(pszUrl) < 5) - return E_INVALIDARG; - - if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pszUrl, 5, - file_colon, 5) != CSTR_EQUAL) - return E_INVALIDARG; - pszUrl += 5; - ret = S_OK; - - src = pszUrl; - nslashes = 0; - while (*src == '/' || *src == '\\') { - nslashes++; - src++; - } - - /* We need a temporary buffer so we can compute what size to ask for. - * We know that the final string won't be longer than the current pszUrl - * plus at most two backslashes. All the other transformations make it - * shorter. - */ - len = 2 + lstrlenW(pszUrl) + 1; - if (*pcchPath < len) - tpath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); - else - tpath = pszPath; - - len = 0; - dst = tpath; - unescape = 1; - switch (nslashes) - { - case 0: - /* 'file:' + escaped DOS path */ - break; - case 1: - /* 'file:/' + escaped DOS path */ - /* fall through */ - case 3: - /* 'file:///' (implied localhost) + escaped DOS path */ - if (!isalphaW(*src) || (src[1] != ':' && src[1] != '|')) - src -= 1; - break; - case 2: - if (lstrlenW(src) >= 10 && CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, - src, 9, localhost, 9) == CSTR_EQUAL && (src[9] == '/' || src[9] == '\\')) - { - /* 'file://localhost/' + escaped DOS path */ - src += 10; - } - else if (isalphaW(*src) && (src[1] == ':' || src[1] == '|')) - { - /* 'file://' + unescaped DOS path */ - unescape = 0; - } - else - { - /* 'file://hostname:port/path' (where path is escaped) - * or 'file:' + escaped UNC path (\\server\share\path) - * The second form is clearly specific to Windows and it might - * even be doing a network lookup to try to figure it out. - */ - while (*src && *src != '/' && *src != '\\') - src++; - len = src - pszUrl; - StrCpyNW(dst, pszUrl, len + 1); - dst += len; - if (*src && isalphaW(src[1]) && (src[2] == ':' || src[2] == '|')) - { - /* 'Forget' to add a trailing '/', just like Windows */ - src++; - } - } - break; - case 4: - /* 'file://' + unescaped UNC path (\\server\share\path) */ - unescape = 0; - if (isalphaW(*src) && (src[1] == ':' || src[1] == '|')) - break; - /* fall through */ - default: - /* 'file:/...' + escaped UNC path (\\server\share\path) */ - src -= 2; - } - - /* Copy the remainder of the path */ - len += lstrlenW(src); - StrCpyW(dst, src); - - /* First do the Windows-specific path conversions */ - for (dst = tpath; *dst; dst++) - if (*dst == '/') *dst = '\\'; - if (isalphaW(*tpath) && tpath[1] == '|') - tpath[1] = ':'; /* c| -> c: */ - - /* And only then unescape the path (i.e. escaped slashes are left as is) */ - if (unescape) - { - ret = UrlUnescapeW(tpath, NULL, &len, URL_UNESCAPE_INPLACE); - if (ret == S_OK) - { - /* When working in-place UrlUnescapeW() does not set len */ - len = lstrlenW(tpath); - } - } - - if (*pcchPath < len + 1) - { - ret = E_POINTER; - *pcchPath = len + 1; - } - else - { - *pcchPath = len; - if (tpath != pszPath) - StrCpyW(pszPath, tpath); - } - if (tpath != pszPath) - HeapFree(GetProcessHeap(), 0, tpath); - - TRACE("Returning (%u) %s\n", *pcchPath, debugstr_w(pszPath)); - return ret; -} - -/************************************************************************* - * PathCreateFromUrlAlloc [SHLWAPI.@] - */ -HRESULT WINAPI PathCreateFromUrlAlloc(LPCWSTR pszUrl, LPWSTR *pszPath, - DWORD dwReserved) -{ - WCHAR pathW[MAX_PATH]; - DWORD size; - HRESULT hr; - - size = MAX_PATH; - hr = PathCreateFromUrlW(pszUrl, pathW, &size, dwReserved); - if (SUCCEEDED(hr)) - { - /* Yes, this is supposed to crash if pszPath is NULL */ - *pszPath = StrDupW(pathW); - } - return hr; -} - -/************************************************************************* - * PathRelativePathToA [SHLWAPI.@] - * - * Create a relative path from one path to another. - * - * PARAMS - * lpszPath [O] Destination for relative path - * lpszFrom [I] Source path - * dwAttrFrom [I] File attribute of source path - * lpszTo [I] Destination path - * dwAttrTo [I] File attributes of destination path - * - * RETURNS - * TRUE If a relative path can be formed. lpszPath contains the new path - * FALSE If the paths are not relative or any parameters are invalid - * - * NOTES - * lpszTo should be at least MAX_PATH in length. - * - * Calling this function with relative paths for lpszFrom or lpszTo may - * give erroneous results. - * - * The Win32 version of this function contains a bug where the lpszTo string - * may be referenced 1 byte beyond the end of the string. As a result random - * garbage may be written to the output path, depending on what lies beyond - * the last byte of the string. This bug occurs because of the behaviour of - * PathCommonPrefix() (see notes for that function), and no workaround seems - * possible with Win32. - * - * This bug has been fixed here, so for example the relative path from "\\" - * to "\\" is correctly determined as "." in this implementation. - */ -BOOL WINAPI PathRelativePathToA(LPSTR lpszPath, LPCSTR lpszFrom, DWORD dwAttrFrom, - LPCSTR lpszTo, DWORD dwAttrTo) -{ - BOOL bRet = FALSE; - - TRACE("(%p,%s,0x%08x,%s,0x%08x)\n", lpszPath, debugstr_a(lpszFrom), - dwAttrFrom, debugstr_a(lpszTo), dwAttrTo); - - if(lpszPath && lpszFrom && lpszTo) - { - WCHAR szPath[MAX_PATH]; - WCHAR szFrom[MAX_PATH]; - WCHAR szTo[MAX_PATH]; - MultiByteToWideChar(CP_ACP,0,lpszFrom,-1,szFrom,MAX_PATH); - MultiByteToWideChar(CP_ACP,0,lpszTo,-1,szTo,MAX_PATH); - bRet = PathRelativePathToW(szPath,szFrom,dwAttrFrom,szTo,dwAttrTo); - WideCharToMultiByte(CP_ACP,0,szPath,-1,lpszPath,MAX_PATH,0,0); - } - return bRet; -} - -/************************************************************************* - * PathRelativePathToW [SHLWAPI.@] - * - * See PathRelativePathToA. - */ -BOOL WINAPI PathRelativePathToW(LPWSTR lpszPath, LPCWSTR lpszFrom, DWORD dwAttrFrom, - LPCWSTR lpszTo, DWORD dwAttrTo) -{ - static const WCHAR szPrevDirSlash[] = { '.', '.', '\\', '\0' }; - static const WCHAR szPrevDir[] = { '.', '.', '\0' }; - WCHAR szFrom[MAX_PATH]; - WCHAR szTo[MAX_PATH]; - DWORD dwLen; - - TRACE("(%p,%s,0x%08x,%s,0x%08x)\n", lpszPath, debugstr_w(lpszFrom), - dwAttrFrom, debugstr_w(lpszTo), dwAttrTo); - - if(!lpszPath || !lpszFrom || !lpszTo) - return FALSE; - - *lpszPath = '\0'; - lstrcpynW(szFrom, lpszFrom, MAX_PATH); - lstrcpynW(szTo, lpszTo, MAX_PATH); - - if(!(dwAttrFrom & FILE_ATTRIBUTE_DIRECTORY)) - PathRemoveFileSpecW(szFrom); - if(!(dwAttrTo & FILE_ATTRIBUTE_DIRECTORY)) - PathRemoveFileSpecW(szTo); - - /* Paths can only be relative if they have a common root */ - if(!(dwLen = PathCommonPrefixW(szFrom, szTo, 0))) - return FALSE; - - /* Strip off lpszFrom components to the root, by adding "..\" */ - lpszFrom = szFrom + dwLen; - if (!*lpszFrom) - { - lpszPath[0] = '.'; - lpszPath[1] = '\0'; - } - if (*lpszFrom == '\\') - lpszFrom++; - - while (*lpszFrom) - { - lpszFrom = PathFindNextComponentW(lpszFrom); - strcatW(lpszPath, *lpszFrom ? szPrevDirSlash : szPrevDir); - } - - /* From the root add the components of lpszTo */ - lpszTo += dwLen; - /* We check lpszTo[-1] to avoid skipping end of string. See the notes for - * this function. - */ - if (*lpszTo && lpszTo[-1]) - { - if (*lpszTo != '\\') - lpszTo--; - dwLen = strlenW(lpszPath); - if (dwLen + strlenW(lpszTo) >= MAX_PATH) - { - *lpszPath = '\0'; - return FALSE; - } - strcpyW(lpszPath + dwLen, lpszTo); - } - return TRUE; -} - /************************************************************************* * PathUnmakeSystemFolderA [SHLWAPI.@] * @@ -3847,95 +1352,6 @@ BOOL WINAPI PathIsNetworkPathW(LPCWSTR lpszPath) #endif } -/************************************************************************* - * PathIsLFNFileSpecA [SHLWAPI.@] - * - * Determine if the given path is a long file name - * - * PARAMS - * lpszPath [I] Path to check - * - * RETURNS - * TRUE If path is a long file name, - * FALSE If path is a valid DOS short file name - */ -BOOL WINAPI PathIsLFNFileSpecA(LPCSTR lpszPath) -{ - DWORD dwNameLen = 0, dwExtLen = 0; - - TRACE("(%s)\n",debugstr_a(lpszPath)); - - if (!lpszPath) - return FALSE; - - while (*lpszPath) - { - if (*lpszPath == ' ') - return TRUE; /* DOS names cannot have spaces */ - if (*lpszPath == '.') - { - if (dwExtLen) - return TRUE; /* DOS names have only one dot */ - dwExtLen = 1; - } - else if (dwExtLen) - { - dwExtLen++; - if (dwExtLen > 4) - return TRUE; /* DOS extensions are <= 3 chars*/ - } - else - { - dwNameLen++; - if (dwNameLen > 8) - return TRUE; /* DOS names are <= 8 chars */ - } - lpszPath += IsDBCSLeadByte(*lpszPath) ? 2 : 1; - } - return FALSE; /* Valid DOS path */ -} - -/************************************************************************* - * PathIsLFNFileSpecW [SHLWAPI.@] - * - * See PathIsLFNFileSpecA. - */ -BOOL WINAPI PathIsLFNFileSpecW(LPCWSTR lpszPath) -{ - DWORD dwNameLen = 0, dwExtLen = 0; - - TRACE("(%s)\n",debugstr_w(lpszPath)); - - if (!lpszPath) - return FALSE; - - while (*lpszPath) - { - if (*lpszPath == ' ') - return TRUE; /* DOS names cannot have spaces */ - if (*lpszPath == '.') - { - if (dwExtLen) - return TRUE; /* DOS names have only one dot */ - dwExtLen = 1; - } - else if (dwExtLen) - { - dwExtLen++; - if (dwExtLen > 4) - return TRUE; /* DOS extensions are <= 3 chars*/ - } - else - { - dwNameLen++; - if (dwNameLen > 8) - return TRUE; /* DOS names are <= 8 chars */ - } - lpszPath++; - } - return FALSE; /* Valid DOS path */ -} - /************************************************************************* * PathIsDirectoryEmptyA [SHLWAPI.@] * @@ -4144,120 +1560,6 @@ void WINAPI PathUndecorateW(WCHAR *path) memmove(skip, ext, (wcslen(ext) + 1) * sizeof(WCHAR)); } -/************************************************************************* - * PathUnExpandEnvStringsA [SHLWAPI.@] - * - * Substitute folder names in a path with their corresponding environment - * strings. - * - * PARAMS - * path [I] Buffer containing the path to unexpand. - * buffer [O] Buffer to receive the unexpanded path. - * buf_len [I] Size of pszBuf in characters. - * - * RETURNS - * Success: TRUE - * Failure: FALSE - */ -BOOL WINAPI PathUnExpandEnvStringsA(LPCSTR path, LPSTR buffer, UINT buf_len) -{ - WCHAR bufferW[MAX_PATH], *pathW; - DWORD len; - BOOL ret; - - TRACE("(%s, %p, %d)\n", debugstr_a(path), buffer, buf_len); - - pathW = heap_strdupAtoW(path); - if (!pathW) return FALSE; - - ret = PathUnExpandEnvStringsW(pathW, bufferW, MAX_PATH); - HeapFree(GetProcessHeap(), 0, pathW); - if (!ret) return FALSE; - - len = WideCharToMultiByte(CP_ACP, 0, bufferW, -1, NULL, 0, NULL, NULL); - if (buf_len < len + 1) return FALSE; - - WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buffer, buf_len, NULL, NULL); - return TRUE; -} - -static const WCHAR allusersprofileW[] = {'%','A','L','L','U','S','E','R','S','P','R','O','F','I','L','E','%',0}; -static const WCHAR appdataW[] = {'%','A','P','P','D','A','T','A','%',0}; -static const WCHAR programfilesW[] = {'%','P','r','o','g','r','a','m','F','i','l','e','s','%',0}; -static const WCHAR systemrootW[] = {'%','S','y','s','t','e','m','R','o','o','t','%',0}; -static const WCHAR systemdriveW[] = {'%','S','y','s','t','e','m','D','r','i','v','e','%',0}; -static const WCHAR userprofileW[] = {'%','U','S','E','R','P','R','O','F','I','L','E','%',0}; - -struct envvars_map -{ - const WCHAR *var; - UINT varlen; - WCHAR path[MAX_PATH]; - DWORD len; -}; - -static void init_envvars_map(struct envvars_map *map) -{ - while (map->var) - { - map->len = ExpandEnvironmentStringsW(map->var, map->path, sizeof(map->path)/sizeof(WCHAR)); - /* exclude null from length */ - if (map->len) map->len--; - map++; - } -} - -/************************************************************************* - * PathUnExpandEnvStringsW [SHLWAPI.@] - * - * Unicode version of PathUnExpandEnvStringsA. - */ -BOOL WINAPI PathUnExpandEnvStringsW(LPCWSTR path, LPWSTR buffer, UINT buf_len) -{ - static struct envvars_map null_var = {NULL, 0, {0}, 0}; - struct envvars_map *match = &null_var, *cur; - struct envvars_map envvars[] = { - { allusersprofileW, sizeof(allusersprofileW)/sizeof(WCHAR) }, - { appdataW, sizeof(appdataW)/sizeof(WCHAR) }, - { programfilesW, sizeof(programfilesW)/sizeof(WCHAR) }, - { systemrootW, sizeof(systemrootW)/sizeof(WCHAR) }, - { systemdriveW, sizeof(systemdriveW)/sizeof(WCHAR) }, - { userprofileW, sizeof(userprofileW)/sizeof(WCHAR) }, - { NULL } - }; - DWORD pathlen; - UINT needed; - - TRACE("(%s, %p, %d)\n", debugstr_w(path), buffer, buf_len); - - pathlen = strlenW(path); - init_envvars_map(envvars); - cur = envvars; - while (cur->var) - { - /* path can't contain expanded value or value wasn't retrieved */ - if (cur->len == 0 || cur->len > pathlen || strncmpiW(cur->path, path, cur->len)) - { - cur++; - continue; - } - - if (cur->len > match->len) - match = cur; - cur++; - } - - /* 'varlen' includes NULL termination char */ - needed = match->varlen + pathlen - match->len; - if (match->len == 0 || needed > buf_len) return FALSE; - - strcpyW(buffer, match->var); - strcatW(buffer, &path[match->len]); - TRACE("ret %s\n", debugstr_w(buffer)); - - return TRUE; -} - /************************************************************************* * @ [SHLWAPI.440] * @@ -4335,113 +1637,3 @@ HRESULT WINAPI SHGetWebFolderFilePathW(LPCWSTR lpszFile, LPWSTR lpszPath, DWORD return S_OK; return E_FAIL; } - -#ifndef __REACTOS__ /* Defined in */ -#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 -#endif - -static const DWORD SHELL_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 -}; - -/************************************************************************* - * @ [SHLWAPI.455] - * - * Check if an ASCII char is of a certain class - */ -BOOL WINAPI PathIsValidCharA( char c, DWORD class ) -{ - if ((unsigned)c > 0x7e) - return class & PATH_CHAR_CLASS_OTHER_VALID; - - return class & SHELL_charclass[(unsigned)c]; -} - -/************************************************************************* - * @ [SHLWAPI.456] - * - * Check if a Unicode char is of a certain class - */ -BOOL WINAPI PathIsValidCharW( WCHAR c, DWORD class ) -{ - if (c > 0x7e) - return class & PATH_CHAR_CLASS_OTHER_VALID; - - return class & SHELL_charclass[c]; -} diff --git a/dll/win32/shlwapi/shlwapi.spec b/dll/win32/shlwapi/shlwapi.spec index 6f7de2d4d19..b905fe79d2d 100644 --- a/dll/win32/shlwapi/shlwapi.spec +++ b/dll/win32/shlwapi/shlwapi.spec @@ -148,14 +148,14 @@ 148 stdcall -noname VkKeyScanWrapW(long) user32.VkKeyScanW 149 stdcall -noname WinHelpWrapW(long wstr long long) user32.WinHelpW 150 stdcall -noname wvsprintfWrapW(ptr wstr ptr) user32.wvsprintfW -151 stdcall -noname StrCmpNCA(str ptr long) -152 stdcall -noname StrCmpNCW(wstr wstr long) -153 stdcall -noname StrCmpNICA(long long long) -154 stdcall -noname StrCmpNICW(wstr wstr long) -155 stdcall -ordinal StrCmpCA(str str) -156 stdcall -ordinal StrCmpCW(wstr wstr) -157 stdcall -ordinal StrCmpICA(str str) -158 stdcall -ordinal StrCmpICW(wstr wstr) +151 stdcall -noname StrCmpNCA(str ptr long) kernelbase_ros.StrCmpNCA +152 stdcall -noname StrCmpNCW(wstr wstr long) kernelbase_ros.StrCmpNCW +153 stdcall -noname StrCmpNICA(long long long) kernelbase_ros.StrCmpNICA +154 stdcall -noname StrCmpNICW(wstr wstr long) kernelbase_ros.StrCmpNICW +155 stdcall -ordinal StrCmpCA(str str) kernelbase_ros.StrCmpCA +156 stdcall -ordinal StrCmpCW(wstr wstr) kernelbase_ros.StrCmpCW +157 stdcall -ordinal StrCmpICA(str str) kernelbase_ros.StrCmpICA +158 stdcall -ordinal StrCmpICW(wstr wstr) kernelbase_ros.StrCmpICW 159 stdcall -noname CompareStringAltW(long long wstr long wstr long) kernel32.CompareStringW 160 stdcall -noname SHAboutInfoA(ptr long) 161 stdcall -noname SHAboutInfoW(ptr long) @@ -396,8 +396,8 @@ 396 stub -noname MLHtmlHelpA 397 stub -noname MLWinHelpW 398 stub -noname MLHtmlHelpW -399 stdcall -noname StrCpyNXA(ptr str long) -400 stdcall -noname StrCpyNXW(ptr wstr long) +399 stdcall -noname StrCpyNXA(ptr str long) kernelbase_ros.StrCpyNXA +400 stdcall -noname StrCpyNXW(ptr wstr long) kernelbase_ros.StrCpyNXW 401 stdcall -noname PageSetupDlgWrapW(ptr) 402 stdcall -noname PrintDlgWrapW(ptr) 403 stdcall -noname GetOpenFileNameWrapW(ptr) @@ -459,7 +459,7 @@ 459 stdcall -noname SHExpandEnvironmentStringsA(str ptr long) kernel32.ExpandEnvironmentStringsA 460 stdcall -noname SHExpandEnvironmentStringsW(wstr ptr long) kernel32.ExpandEnvironmentStringsW 461 stdcall -noname SHGetAppCompatFlags(long) -462 stdcall -noname UrlFixupW(wstr wstr long) +462 stdcall -noname UrlFixupW(wstr wstr long) kernelbase_ros.UrlFixupW 463 stdcall -noname SHExpandEnvironmentStringsForUserA(ptr str ptr long) userenv.ExpandEnvironmentStringsForUserA 464 stdcall -noname SHExpandEnvironmentStringsForUserW(ptr wstr ptr long) userenv.ExpandEnvironmentStringsForUserW 465 stdcall -noname PathUnExpandEnvStringsForUserA(ptr str ptr long) @@ -659,6 +659,8 @@ @ stdcall PathMakeSystemFolderA(str) @ stdcall PathMakeSystemFolderW(wstr) @ stdcall PathMatchSpecA(str str) +@ stdcall -version=0x600 PathMatchSpecExA(str str long) +@ stdcall -version=0x600 PathMatchSpecExW(wstr wstr long) @ stdcall PathMatchSpecW(wstr wstr) @ stdcall PathParseIconLocationA(str) @ stdcall PathParseIconLocationW(wstr) @@ -770,31 +772,31 @@ @ stdcall SHSkipJunction(ptr ptr) @ stdcall SHStrDupA(str ptr) @ stdcall SHStrDupW(wstr ptr) -@ stdcall StrCSpnA(str str) -@ stdcall StrCSpnIA(str str) -@ stdcall StrCSpnIW(wstr wstr) -@ stdcall StrCSpnW(wstr wstr) -@ stdcall StrCatBuffA(str str long) -@ stdcall StrCatBuffW(wstr wstr long) -@ stdcall StrCatChainW (ptr long long wstr) +@ stdcall StrCSpnA(str str) kernelbase_ros.StrCSpnA +@ stdcall StrCSpnIA(str str) kernelbase_ros.StrCSpnIA +@ stdcall StrCSpnIW(wstr wstr) kernelbase_ros.StrCSpnIW +@ stdcall StrCSpnW(wstr wstr) kernelbase_ros.StrCSpnW +@ stdcall StrCatBuffA(str str long) kernelbase_ros.StrCatBuffA +@ stdcall StrCatBuffW(wstr wstr long) kernelbase_ros.StrCatBuffW +@ stdcall StrCatChainW (ptr long long wstr) kernelbase_ros.StrCatChainW @ stdcall StrCatW(ptr wstr) -@ stdcall StrChrA(str long) -@ stdcall StrChrIA(str long) -@ stdcall StrChrIW(wstr long) +@ stdcall StrChrA(str long) kernelbase_ros.StrChrA +@ stdcall StrChrIA(str long) kernelbase_ros.StrChrIA +@ stdcall StrChrIW(wstr long) kernelbase_ros.StrChrIW @ stub StrChrNIW -@ stdcall StrChrNW(wstr long long) -@ stdcall StrChrW(wstr long) -@ stdcall StrCmpIW(wstr wstr) -@ stdcall StrCmpLogicalW(wstr wstr) -@ stdcall StrCmpNA(str str long) -@ stdcall StrCmpNIA(str str long) -@ stdcall StrCmpNIW(wstr wstr long) -@ stdcall StrCmpNW(wstr wstr long) -@ stdcall StrCmpW(wstr wstr) -@ stdcall StrCpyNW(ptr wstr long) +@ stdcall StrChrNW(wstr long long) kernelbase_ros.StrChrNW +@ stdcall StrChrW(wstr long) kernelbase_ros.StrChrW +@ stdcall StrCmpIW(wstr wstr) kernelbase_ros.StrCmpIW +@ stdcall StrCmpLogicalW(wstr wstr) kernelbase_ros.StrCmpLogicalW +@ stdcall StrCmpNA(str str long) kernelbase_ros.StrCmpNA +@ stdcall StrCmpNIA(str str long) kernelbase_ros.StrCmpNIA +@ stdcall StrCmpNIW(wstr wstr long) kernelbase_ros.StrCmpNIW +@ stdcall StrCmpNW(wstr wstr long) kernelbase_ros.StrCmpNW +@ stdcall StrCmpW(wstr wstr) kernelbase_ros.StrCmpW +@ stdcall StrCpyNW(ptr wstr long) kernelbase_ros.StrCpyNW @ stdcall StrCpyW(ptr wstr) -@ stdcall StrDupA(str) -@ stdcall StrDupW(wstr) +@ stdcall StrDupA(str) kernelbase_ros.StrDupA +@ stdcall StrDupW(wstr) kernelbase_ros.StrDupW @ stdcall StrFormatByteSize64A(int64 ptr long) @ stdcall StrFormatByteSizeA(long ptr long) @ stdcall -version=0x600+ StrFormatByteSizeEx(int64 long ptr long) @@ -807,62 +809,63 @@ @ stdcall StrIsIntlEqualW(long wstr wstr long) @ stdcall StrNCatA(str str long) @ stdcall StrNCatW(wstr wstr long) -@ stdcall StrPBrkA(str str) -@ stdcall StrPBrkW(wstr wstr) -@ stdcall StrRChrA(str str long) -@ stdcall StrRChrIA(str str long) -@ stdcall StrRChrIW(wstr wstr long) -@ stdcall StrRChrW(wstr wstr long) -@ stdcall StrRStrIA(str str str) -@ stdcall StrRStrIW(wstr wstr wstr) +@ stdcall StrPBrkA(str str) kernelbase_ros.StrPBrkA +@ stdcall StrPBrkW(wstr wstr) kernelbase_ros.StrPBrkW +@ stdcall StrRChrA(str str long) kernelbase_ros.StrRChrA +@ stdcall StrRChrIA(str str long) kernelbase_ros.StrRChrIA +@ stdcall StrRChrIW(wstr wstr long) kernelbase_ros.StrRChrIW +@ stdcall StrRChrW(wstr wstr long) kernelbase_ros.StrRChrW +@ stdcall StrRStrIA(str str str) kernelbase_ros.StrRStrIA +@ stdcall StrRStrIW(wstr wstr wstr) kernelbase_ros.StrRStrIW @ stdcall StrRetToBSTR(ptr ptr ptr) @ stdcall StrRetToBufA(ptr ptr ptr long) @ stdcall StrRetToBufW(ptr ptr ptr long) @ stdcall StrRetToStrA(ptr ptr ptr) @ stdcall StrRetToStrW(ptr ptr ptr) -@ stdcall StrSpnA(str str) -@ stdcall StrSpnW(wstr wstr) -@ stdcall StrStrA(str str) -@ stdcall StrStrIA(str str) -@ stdcall StrStrIW(wstr wstr) -@ stdcall StrStrNIW(wstr wstr long) -@ stdcall StrStrNW(wstr wstr long) -@ stdcall StrStrW(wstr wstr) -@ stdcall StrToInt64ExA(str long ptr) -@ stdcall StrToInt64ExW(wstr long ptr) -@ stdcall StrToIntA(str) -@ stdcall StrToIntExA(str long ptr) -@ stdcall StrToIntExW(wstr long ptr) -@ stdcall StrToIntW(wstr) -@ stdcall StrTrimA(str str) -@ stdcall StrTrimW(wstr wstr) -@ stdcall UrlApplySchemeA(str ptr ptr long) -@ stdcall UrlApplySchemeW(wstr ptr ptr long) -@ stdcall UrlCanonicalizeA(str ptr ptr long) -@ stdcall UrlCanonicalizeW(wstr ptr ptr long) -@ stdcall UrlCombineA(str str ptr ptr long) -@ stdcall UrlCombineW(wstr wstr ptr ptr long) -@ stdcall UrlCompareA(str str long) -@ stdcall UrlCompareW(wstr wstr long) -@ stdcall UrlCreateFromPathA(str ptr ptr long) -@ stdcall UrlCreateFromPathW(wstr ptr ptr long) -@ stdcall UrlEscapeA(str ptr ptr long) -@ stdcall UrlEscapeW(wstr ptr ptr long) -@ stdcall UrlGetLocationA(str) -@ stdcall UrlGetLocationW(wstr) -@ stdcall UrlGetPartA(str ptr ptr long long) -@ stdcall UrlGetPartW(wstr ptr ptr long long) -@ stdcall UrlHashA(str ptr long) -@ stdcall UrlHashW(wstr ptr long) -@ stdcall UrlIsA(str long) -@ stdcall UrlIsNoHistoryA(str) -@ stdcall UrlIsNoHistoryW(wstr) -@ stdcall UrlIsOpaqueA(str) -@ stdcall UrlIsOpaqueW(wstr) -@ stdcall UrlIsW(wstr long) -@ stdcall UrlUnescapeA(str ptr ptr long) -@ stdcall UrlUnescapeW(wstr ptr ptr long) +@ stdcall StrSpnA(str str) kernelbase_ros.StrSpnA +@ stdcall StrSpnW(wstr wstr) kernelbase_ros.StrSpnW +@ stdcall StrStrA(str str) kernelbase_ros.StrStrA +@ stdcall StrStrIA(str str) kernelbase_ros.StrStrIA +@ stdcall StrStrIW(wstr wstr) kernelbase_ros.StrStrIW +@ stdcall StrStrNIW(wstr wstr long) kernelbase_ros.StrStrNIW +@ stdcall StrStrNW(wstr wstr long) kernelbase_ros.StrStrNW +@ stdcall StrStrW(wstr wstr) kernelbase_ros.StrStrW +@ stdcall StrToInt64ExA(str long ptr) kernelbase_ros.StrToInt64ExA +@ stdcall StrToInt64ExW(wstr long ptr) kernelbase_ros.StrToInt64ExW +@ stdcall StrToIntA(str) kernelbase_ros.StrToIntA +@ stdcall StrToIntExA(str long ptr) kernelbase_ros.StrToIntExA +@ stdcall StrToIntExW(wstr long ptr) kernelbase_ros.StrToIntExW +@ stdcall StrToIntW(wstr) kernelbase_ros.StrToIntW +@ stdcall StrTrimA(str str) kernelbase_ros.StrTrimA +@ stdcall StrTrimW(wstr wstr) kernelbase_ros.StrTrimW +@ stdcall UrlApplySchemeA(str ptr ptr long) kernelbase_ros.UrlApplySchemeA +@ stdcall UrlApplySchemeW(wstr ptr ptr long) kernelbase_ros.UrlApplySchemeW +@ stdcall UrlCanonicalizeA(str ptr ptr long) kernelbase_ros.UrlCanonicalizeA +@ stdcall UrlCanonicalizeW(wstr ptr ptr long) kernelbase_ros.UrlCanonicalizeW +@ stdcall UrlCombineA(str str ptr ptr long) kernelbase_ros.UrlCombineA +@ stdcall UrlCombineW(wstr wstr ptr ptr long) kernelbase_ros.UrlCombineW +@ stdcall UrlCompareA(str str long) kernelbase_ros.UrlCompareA +@ stdcall UrlCompareW(wstr wstr long) kernelbase_ros.UrlCompareW +@ stdcall UrlCreateFromPathA(str ptr ptr long) kernelbase_ros.UrlCreateFromPathA +@ stdcall UrlCreateFromPathW(wstr ptr ptr long) kernelbase_ros.UrlCreateFromPathW +@ stdcall UrlEscapeA(str ptr ptr long) kernelbase_ros.UrlEscapeA +@ stdcall UrlEscapeW(wstr ptr ptr long) kernelbase_ros.UrlEscapeW +@ stdcall UrlGetLocationA(str) kernelbase_ros.UrlGetLocationA +@ stdcall UrlGetLocationW(wstr) kernelbase_ros.UrlGetLocationW +@ stdcall UrlGetPartA(str ptr ptr long long) kernelbase_ros.UrlGetPartA +@ stdcall UrlGetPartW(wstr ptr ptr long long) kernelbase_ros.UrlGetPartW +@ stdcall UrlHashA(str ptr long) kernelbase_ros.UrlHashA +@ stdcall UrlHashW(wstr ptr long) kernelbase_ros.UrlHashW +@ stdcall UrlIsA(str long) kernelbase_ros.UrlIsA +@ stdcall UrlIsNoHistoryA(str) kernelbase_ros.UrlIsNoHistoryA +@ stdcall UrlIsNoHistoryW(wstr) kernelbase_ros.UrlIsNoHistoryW +@ stdcall UrlIsOpaqueA(str) kernelbase_ros.UrlIsOpaqueA +@ stdcall UrlIsOpaqueW(wstr) kernelbase_ros.UrlIsOpaqueW +@ stdcall UrlIsW(wstr long) kernelbase_ros.UrlIsW +@ stdcall UrlUnescapeA(str ptr ptr long) kernelbase_ros.UrlUnescapeA +@ stdcall UrlUnescapeW(wstr ptr ptr long) kernelbase_ros.UrlUnescapeW @ varargs wnsprintfA(ptr long str) @ varargs wnsprintfW(ptr long wstr) @ stdcall wvnsprintfA(ptr long str ptr) @ stdcall wvnsprintfW(ptr long wstr ptr) + diff --git a/dll/win32/shlwapi/string.c b/dll/win32/shlwapi/string.c index d7e21d56a27..3e939b119a6 100644 --- a/dll/win32/shlwapi/string.c +++ b/dll/win32/shlwapi/string.c @@ -135,301 +135,6 @@ static int FormatDouble(double value, int decimals, LPWSTR pszBuf, int cchBuf) return GetNumberFormatW(LOCALE_USER_DEFAULT, 0, buf, &fmt, pszBuf, cchBuf); } -/************************************************************************* - * SHLWAPI_ChrCmpHelperA - * - * Internal helper for SHLWAPI_ChrCmpA/ChrCMPIA. - * - * NOTES - * Both this function and its Unicode counterpart are very inefficient. To - * fix this, CompareString must be completely implemented and optimised - * first. Then the core character test can be taken out of that function and - * placed here, so that it need never be called at all. Until then, do not - * attempt to optimise this code unless you are willing to test that it - * still performs correctly. - */ -static BOOL SHLWAPI_ChrCmpHelperA(WORD ch1, WORD ch2, DWORD dwFlags) -{ - 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(), dwFlags, str1, -1, str2, -1) - CSTR_EQUAL; -} - -/************************************************************************* - * SHLWAPI_ChrCmpA - * - * Internal helper function. - */ -static BOOL WINAPI SHLWAPI_ChrCmpA(WORD ch1, WORD ch2) -{ - return SHLWAPI_ChrCmpHelperA(ch1, ch2, 0); -} - -/************************************************************************* - * ChrCmpIA (SHLWAPI.385) - * - * Compare two characters, ignoring case. - * - * PARAMS - * ch1 [I] First character to compare - * ch2 [I] Second character to compare - * - * RETURNS - * FALSE, if the characters are equal. - * Non-zero otherwise. - */ -BOOL WINAPI ChrCmpIA(WORD ch1, WORD ch2) -{ - TRACE("(%d,%d)\n", ch1, ch2); - - return SHLWAPI_ChrCmpHelperA(ch1, ch2, NORM_IGNORECASE); -} - -/************************************************************************* - * ChrCmpIW [SHLWAPI.386] - * - * See ChrCmpIA. - */ -BOOL WINAPI ChrCmpIW(WCHAR ch1, WCHAR ch2) -{ - return CompareStringW(GetThreadLocale(), NORM_IGNORECASE, &ch1, 1, &ch2, 1) - CSTR_EQUAL; -} - -/************************************************************************* - * StrChrA [SHLWAPI.@] - * - * Find a given character in a string. - * - * PARAMS - * lpszStr [I] String to search in. - * ch [I] Character to search for. - * - * RETURNS - * Success: A pointer to the first occurrence of ch in lpszStr, or NULL if - * not found. - * Failure: NULL, if any arguments are invalid. - */ -LPSTR WINAPI StrChrA(LPCSTR lpszStr, WORD ch) -{ - TRACE("(%s,%i)\n", debugstr_a(lpszStr), ch); - - if (lpszStr) - { - while (*lpszStr) - { - if (!SHLWAPI_ChrCmpA(*lpszStr, ch)) - return (LPSTR)lpszStr; - lpszStr = CharNextA(lpszStr); - } - } - return NULL; -} - -/************************************************************************* - * StrChrW [SHLWAPI.@] - * - * See StrChrA. - */ -LPWSTR WINAPI StrChrW(LPCWSTR lpszStr, WCHAR ch) -{ - LPWSTR lpszRet = NULL; - - TRACE("(%s,%i)\n", debugstr_w(lpszStr), ch); - - if (lpszStr) - lpszRet = strchrW(lpszStr, ch); - return lpszRet; -} - -/************************************************************************* - * StrChrIA [SHLWAPI.@] - * - * Find a given character in a string, ignoring case. - * - * PARAMS - * lpszStr [I] String to search in. - * ch [I] Character to search for. - * - * RETURNS - * Success: A pointer to the first occurrence of ch in lpszStr, or NULL if - * not found. - * Failure: NULL, if any arguments are invalid. - */ -LPSTR WINAPI StrChrIA(LPCSTR lpszStr, WORD ch) -{ - TRACE("(%s,%i)\n", debugstr_a(lpszStr), ch); - - if (lpszStr) - { - while (*lpszStr) - { - if (!ChrCmpIA(*lpszStr, ch)) - return (LPSTR)lpszStr; - lpszStr = CharNextA(lpszStr); - } - } - return NULL; -} - -/************************************************************************* - * StrChrIW [SHLWAPI.@] - * - * See StrChrA. - */ -LPWSTR WINAPI StrChrIW(LPCWSTR lpszStr, WCHAR ch) -{ - TRACE("(%s,%i)\n", debugstr_w(lpszStr), ch); - - if (lpszStr) - { - ch = toupperW(ch); - while (*lpszStr) - { - if (toupperW(*lpszStr) == ch) - return (LPWSTR)lpszStr; - lpszStr++; - } - lpszStr = NULL; - } - return (LPWSTR)lpszStr; -} - -/************************************************************************* - * StrChrNW [SHLWAPI.@] - */ -LPWSTR WINAPI StrChrNW(LPCWSTR lpszStr, WCHAR ch, UINT cchMax) -{ - TRACE("(%s(%i),%i)\n", debugstr_wn(lpszStr,cchMax), cchMax, ch); - - if (lpszStr) - { - while (*lpszStr && cchMax-- > 0) - { - if (*lpszStr == ch) - return (LPWSTR)lpszStr; - lpszStr++; - } - } - return NULL; -} - -/************************************************************************* - * StrCmpIW [SHLWAPI.@] - * - * Compare two strings, ignoring case. - * - * PARAMS - * lpszStr [I] First string to compare - * lpszComp [I] Second string to compare - * - * RETURNS - * An integer less than, equal to or greater than 0, indicating that - * lpszStr is less than, the same, or greater than lpszComp. - */ -int WINAPI StrCmpIW(LPCWSTR lpszStr, LPCWSTR lpszComp) -{ - TRACE("(%s,%s)\n", debugstr_w(lpszStr),debugstr_w(lpszComp)); - return CompareStringW(GetThreadLocale(), NORM_IGNORECASE, lpszStr, -1, lpszComp, -1) - CSTR_EQUAL; -} - -/************************************************************************* - * StrCmpNA [SHLWAPI.@] - * - * Compare two strings, up to a maximum length. - * - * PARAMS - * lpszStr [I] First string to compare - * lpszComp [I] Second string to compare - * iLen [I] Number of chars to compare - * - * RETURNS - * An integer less than, equal to or greater than 0, indicating that - * lpszStr is less than, the same, or greater than lpszComp. - */ -INT WINAPI StrCmpNA(LPCSTR lpszStr, LPCSTR lpszComp, INT iLen) -{ - TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszComp), iLen); - return CompareStringA(GetThreadLocale(), 0, lpszStr, iLen, lpszComp, iLen) - CSTR_EQUAL; -} - -/************************************************************************* - * StrCmpNW [SHLWAPI.@] - * - * See StrCmpNA. - */ -INT WINAPI StrCmpNW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen) -{ - TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszComp), iLen); - return CompareStringW(GetThreadLocale(), 0, lpszStr, iLen, lpszComp, iLen) - CSTR_EQUAL; -} - -/************************************************************************* - * StrCmpNIA [SHLWAPI.@] - * - * Compare two strings, up to a maximum length, ignoring case. - * - * PARAMS - * lpszStr [I] First string to compare - * lpszComp [I] Second string to compare - * iLen [I] Number of chars to compare - * - * RETURNS - * An integer less than, equal to or greater than 0, indicating that - * lpszStr is less than, the same, or greater than lpszComp. - */ -int WINAPI StrCmpNIA(LPCSTR lpszStr, LPCSTR lpszComp, int iLen) -{ - TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszComp), iLen); - return CompareStringA(GetThreadLocale(), NORM_IGNORECASE, lpszStr, iLen, lpszComp, iLen) - CSTR_EQUAL; -} - -/************************************************************************* - * StrCmpNIW [SHLWAPI.@] - * - * See StrCmpNIA. - */ -INT WINAPI StrCmpNIW(LPCWSTR lpszStr, LPCWSTR lpszComp, int iLen) -{ - TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszComp), iLen); - return CompareStringW(GetThreadLocale(), NORM_IGNORECASE, lpszStr, iLen, lpszComp, iLen) - CSTR_EQUAL; -} - -/************************************************************************* - * StrCmpW [SHLWAPI.@] - * - * Compare two strings. - * - * PARAMS - * lpszStr [I] First string to compare - * lpszComp [I] Second string to compare - * - * RETURNS - * An integer less than, equal to or greater than 0, indicating that - * lpszStr is less than, the same, or greater than lpszComp. - */ -int WINAPI StrCmpW(LPCWSTR lpszStr, LPCWSTR lpszComp) -{ - TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszComp)); - return CompareStringW(GetThreadLocale(), 0, lpszStr, -1, lpszComp, -1) - CSTR_EQUAL; -} /************************************************************************* * StrCatW [SHLWAPI.@] @@ -452,46 +157,6 @@ LPWSTR WINAPI StrCatW(LPWSTR lpszStr, LPCWSTR lpszSrc) return lpszStr; } -/************************************************************************* - * StrCatChainW [SHLWAPI.@] - * - * Concatenates two unicode strings. - * - * PARAMS - * lpszStr [O] Initial string - * cchMax [I] Length of destination buffer - * ichAt [I] Offset from the destination buffer to begin concatenation - * lpszCat [I] String to concatenate - * - * RETURNS - * The offset from the beginning of pszDst to the terminating NULL. - */ -DWORD WINAPI StrCatChainW(LPWSTR lpszStr, DWORD cchMax, DWORD ichAt, LPCWSTR lpszCat) -{ - TRACE("(%s,%u,%d,%s)\n", debugstr_w(lpszStr), cchMax, ichAt, debugstr_w(lpszCat)); - - if (ichAt == -1) - ichAt = strlenW(lpszStr); - - if (!cchMax) - return ichAt; - - if (ichAt == cchMax) - ichAt--; - - if (lpszCat && ichAt < cchMax) - { - lpszStr += ichAt; - while (ichAt < cchMax - 1 && *lpszCat) - { - *lpszStr++ = *lpszCat++; - ichAt++; - } - *lpszStr = 0; - } - - return ichAt; -} /************************************************************************* * StrCpyW [SHLWAPI.@] @@ -514,1077 +179,6 @@ LPWSTR WINAPI StrCpyW(LPWSTR lpszStr, LPCWSTR lpszSrc) return lpszStr; } -/************************************************************************* - * StrCpyNW [SHLWAPI.@] - * - * Copy a string to another string, up to a maximum number of characters. - * - * PARAMS - * dst [O] Destination string - * src [I] Source string - * count [I] Maximum number of chars to copy - * - * RETURNS - * dst. - */ -LPWSTR WINAPI StrCpyNW(LPWSTR dst, LPCWSTR src, int count) -{ - LPWSTR d = dst; - LPCWSTR s = src; - - TRACE("(%p,%s,%i)\n", dst, debugstr_w(src), count); - - if (s) - { - while ((count > 1) && *s) - { - count--; - *d++ = *s++; - } - } - if (count) *d = 0; - - return dst; -} - -/************************************************************************* - * SHLWAPI_StrStrHelperA - * - * Internal implementation of StrStrA/StrStrIA - */ -static LPSTR SHLWAPI_StrStrHelperA(LPCSTR lpszStr, LPCSTR lpszSearch, - INT (WINAPI *pStrCmpFn)(LPCSTR,LPCSTR,INT)) -{ - size_t iLen; - LPCSTR end; - - if (!lpszStr || !lpszSearch || !*lpszSearch) - return NULL; - - iLen = strlen(lpszSearch); - end = lpszStr + strlen(lpszStr); - - while (lpszStr + iLen <= end) - { - if (!pStrCmpFn(lpszStr, lpszSearch, iLen)) - return (LPSTR)lpszStr; - lpszStr = CharNextA(lpszStr); - } - return NULL; -} - -/************************************************************************* - * StrStrA [SHLWAPI.@] - * - * Find a substring within a string. - * - * PARAMS - * lpszStr [I] String to search in - * lpszSearch [I] String to look for - * - * RETURNS - * The start of lpszSearch within lpszStr, or NULL if not found. - */ -LPSTR WINAPI StrStrA(LPCSTR lpszStr, LPCSTR lpszSearch) -{ - TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch)); - - return SHLWAPI_StrStrHelperA(lpszStr, lpszSearch, StrCmpNA); -} - -/************************************************************************* - * StrStrW [SHLWAPI.@] - * - * See StrStrA. - */ -LPWSTR WINAPI StrStrW(LPCWSTR lpszStr, LPCWSTR lpszSearch) -{ - TRACE("(%s, %s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch)); - - if (!lpszStr || !lpszSearch || !*lpszSearch) return NULL; - return strstrW( lpszStr, lpszSearch ); -} - -/************************************************************************* - * StrRStrIA [SHLWAPI.@] - * - * Find the last occurrence of a substring within a string. - * - * PARAMS - * lpszStr [I] String to search in - * lpszEnd [I] End of lpszStr - * lpszSearch [I] String to look for - * - * RETURNS - * The last occurrence lpszSearch within lpszStr, or NULL if not found. - */ -LPSTR WINAPI StrRStrIA(LPCSTR lpszStr, LPCSTR lpszEnd, LPCSTR lpszSearch) -{ - LPSTR lpszRet = NULL; - WORD ch1, ch2; - INT iLen; - - TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch)); - - if (!lpszStr || !lpszSearch || !*lpszSearch) - return NULL; - - if (IsDBCSLeadByte(*lpszSearch)) - ch1 = *lpszSearch << 8 | (UCHAR)lpszSearch[1]; - else - ch1 = *lpszSearch; - iLen = lstrlenA(lpszSearch); - - if (!lpszEnd) - lpszEnd = lpszStr + lstrlenA(lpszStr); - else /* reproduce the broken behaviour on Windows */ - lpszEnd += min(iLen - 1, lstrlenA(lpszEnd)); - - while (lpszStr + iLen <= lpszEnd && *lpszStr) - { - ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | (UCHAR)lpszStr[1] : *lpszStr; - if (!ChrCmpIA(ch1, ch2)) - { - if (!StrCmpNIA(lpszStr, lpszSearch, iLen)) - lpszRet = (LPSTR)lpszStr; - } - lpszStr = CharNextA(lpszStr); - } - return lpszRet; -} - -/************************************************************************* - * StrRStrIW [SHLWAPI.@] - * - * See StrRStrIA. - */ -LPWSTR WINAPI StrRStrIW(LPCWSTR lpszStr, LPCWSTR lpszEnd, LPCWSTR lpszSearch) -{ - LPWSTR lpszRet = NULL; - INT iLen; - - TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch)); - - if (!lpszStr || !lpszSearch || !*lpszSearch) - return NULL; - - iLen = strlenW(lpszSearch); - - if (!lpszEnd) - lpszEnd = lpszStr + strlenW(lpszStr); - else /* reproduce the broken behaviour on Windows */ - lpszEnd += min(iLen - 1, lstrlenW(lpszEnd)); - - while (lpszStr + iLen <= lpszEnd && *lpszStr) - { - if (!ChrCmpIW(*lpszSearch, *lpszStr)) - { - if (!StrCmpNIW(lpszStr, lpszSearch, iLen)) - lpszRet = (LPWSTR)lpszStr; - } - lpszStr++; - } - return lpszRet; -} - -/************************************************************************* - * StrStrIA [SHLWAPI.@] - * - * Find a substring within a string, ignoring case. - * - * PARAMS - * lpszStr [I] String to search in - * lpszSearch [I] String to look for - * - * RETURNS - * The start of lpszSearch within lpszStr, or NULL if not found. - */ -LPSTR WINAPI StrStrIA(LPCSTR lpszStr, LPCSTR lpszSearch) -{ - TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszSearch)); - - return SHLWAPI_StrStrHelperA(lpszStr, lpszSearch, StrCmpNIA); -} - -/************************************************************************* - * StrStrIW [SHLWAPI.@] - * - * See StrStrIA. - */ -LPWSTR WINAPI StrStrIW(LPCWSTR lpszStr, LPCWSTR lpszSearch) -{ - int iLen; - LPCWSTR end; - - TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch)); - - if (!lpszStr || !lpszSearch || !*lpszSearch) - return NULL; - - iLen = strlenW(lpszSearch); - end = lpszStr + strlenW(lpszStr); - - while (lpszStr + iLen <= end) - { - if (!StrCmpNIW(lpszStr, lpszSearch, iLen)) - return (LPWSTR)lpszStr; - lpszStr++; - } - return NULL; -} - -/************************************************************************* - * StrStrNW [SHLWAPI.@] - * - * Find a substring within a string up to a given number of initial characters. - * - * PARAMS - * lpFirst [I] String to search in - * lpSrch [I] String to look for - * cchMax [I] Maximum number of initial search characters - * - * RETURNS - * The start of lpFirst within lpSrch, or NULL if not found. - */ -LPWSTR WINAPI StrStrNW(LPCWSTR lpFirst, LPCWSTR lpSrch, UINT cchMax) -{ - UINT i; - int len; - - TRACE("(%s, %s, %u)\n", debugstr_w(lpFirst), debugstr_w(lpSrch), cchMax); - - if (!lpFirst || !lpSrch || !*lpSrch || !cchMax) - return NULL; - - len = strlenW(lpSrch); - - for (i = cchMax; *lpFirst && (i > 0); i--, lpFirst++) - { - if (!strncmpW(lpFirst, lpSrch, len)) - return (LPWSTR)lpFirst; - } - - return NULL; -} - -/************************************************************************* - * StrStrNIW [SHLWAPI.@] - * - * Find a substring within a string up to a given number of initial characters, - * ignoring case. - * - * PARAMS - * lpFirst [I] String to search in - * lpSrch [I] String to look for - * cchMax [I] Maximum number of initial search characters - * - * RETURNS - * The start of lpFirst within lpSrch, or NULL if not found. - */ -LPWSTR WINAPI StrStrNIW(LPCWSTR lpFirst, LPCWSTR lpSrch, UINT cchMax) -{ - UINT i; - int len; - - TRACE("(%s, %s, %u)\n", debugstr_w(lpFirst), debugstr_w(lpSrch), cchMax); - - if (!lpFirst || !lpSrch || !*lpSrch || !cchMax) - return NULL; - - len = strlenW(lpSrch); - - for (i = cchMax; *lpFirst && (i > 0); i--, lpFirst++) - { - if (!strncmpiW(lpFirst, lpSrch, len)) - return (LPWSTR)lpFirst; - } - - return NULL; -} - -#ifdef __REACTOS__ -#define IS_DIGIT(c) ((UINT)(c) - '0' <= 9) -#endif -/************************************************************************* - * StrToIntA [SHLWAPI.@] - * - * Read a signed integer from a string. - * - * PARAMS - * lpszStr [I] String to read integer from - * - * RETURNS - * The signed integer value represented by the string, or 0 if no integer is - * present. - * - * NOTES - * No leading space is allowed before the number, although a leading '-' is. - */ -int WINAPI StrToIntA(LPCSTR lpszStr) -{ -#ifdef __REACTOS__ - if (!lpszStr) - return 0; - - INT result = 0; - BOOL isNegative = FALSE; - - if (*lpszStr == '-') - { - isNegative = TRUE; - ++lpszStr; - } - - while (IS_DIGIT(*lpszStr)) - { - result *= 10; - result += (*lpszStr - '0'); - ++lpszStr; - } - - return isNegative ? -result : result; -#else - int iRet = 0; - - TRACE("(%s)\n", debugstr_a(lpszStr)); - - if (!lpszStr) - { - WARN("Invalid lpszStr would crash under Win32!\n"); - return 0; - } - - if (*lpszStr == '-' || isdigit(*lpszStr)) - StrToIntExA(lpszStr, 0, &iRet); - return iRet; -#endif -} - -/************************************************************************* - * StrToIntW [SHLWAPI.@] - * - * See StrToIntA. - */ -int WINAPI StrToIntW(LPCWSTR lpszStr) -{ -#ifdef __REACTOS__ - if (!lpszStr) - return 0; - - INT result = 0; - BOOL isNegative = FALSE; - - if (*lpszStr == L'-') - { - isNegative = TRUE; - ++lpszStr; - } - - while (IS_DIGIT(*lpszStr)) - { - result *= 10; - result += (*lpszStr - L'0'); - ++lpszStr; - } - - return isNegative ? -result : result; -#else - int iRet = 0; - - TRACE("(%s)\n", debugstr_w(lpszStr)); - - if (!lpszStr) - { - WARN("Invalid lpszStr would crash under Win32!\n"); - return 0; - } - - if (*lpszStr == '-' || isdigitW(*lpszStr)) - StrToIntExW(lpszStr, 0, &iRet); - return iRet; -#endif -} - -/************************************************************************* - * StrToIntExA [SHLWAPI.@] - * - * Read an integer from a string. - * - * PARAMS - * lpszStr [I] String to read integer from - * dwFlags [I] Flags controlling the conversion - * lpiRet [O] Destination for read integer. - * - * RETURNS - * Success: TRUE. lpiRet contains the integer value represented by the string. - * Failure: FALSE, if the string is invalid, or no number is present. - * - * NOTES - * Leading whitespace, '-' and '+' are allowed before the number. If - * dwFlags includes STIF_SUPPORT_HEX, hexadecimal numbers are allowed, if - * preceded by '0x'. If this flag is not set, or there is no '0x' prefix, - * the string is treated as a decimal string. A leading '-' is ignored for - * hexadecimal numbers. - */ -BOOL WINAPI StrToIntExA(LPCSTR lpszStr, DWORD dwFlags, int *lpiRet) -{ - LONGLONG li; - BOOL bRes; - - TRACE("(%s,%08X,%p)\n", debugstr_a(lpszStr), dwFlags, lpiRet); - - bRes = StrToInt64ExA(lpszStr, dwFlags, &li); -#ifdef __REACTOS__ - if (lpiRet) *lpiRet = bRes ? (INT)li : 0; -#else - if (bRes) *lpiRet = li; -#endif - return bRes; -} - -/************************************************************************* - * StrToInt64ExA [SHLWAPI.@] - * - * See StrToIntExA. - */ -BOOL WINAPI StrToInt64ExA(LPCSTR lpszStr, DWORD dwFlags, LONGLONG *lpiRet) -{ -#ifdef __REACTOS__ - if (!lpszStr) - return FALSE; - - WCHAR wideBuf[MAX_PATH]; - if (MultiByteToWideChar(CP_ACP, 0, lpszStr, -1, wideBuf, _countof(wideBuf)) <= 0) - return FALSE; - - wideBuf[_countof(wideBuf) - 1] = UNICODE_NULL; // SECURITY: Avoid buffer overrun - return StrToInt64ExW(wideBuf, dwFlags, lpiRet); -#else - BOOL bNegative = FALSE; - LONGLONG iRet = 0; - - TRACE("(%s,%08X,%p)\n", debugstr_a(lpszStr), dwFlags, lpiRet); - - if (!lpszStr || !lpiRet) - { - WARN("Invalid parameter would crash under Win32!\n"); - return FALSE; - } - if (dwFlags > STIF_SUPPORT_HEX) WARN("Unknown flags %08x\n", dwFlags); - - /* Skip leading space, '+', '-' */ - while (isspace(*lpszStr)) - lpszStr = CharNextA(lpszStr); - - if (*lpszStr == '-') - { - bNegative = TRUE; - lpszStr++; - } - else if (*lpszStr == '+') - lpszStr++; - - if (dwFlags & STIF_SUPPORT_HEX && - *lpszStr == '0' && tolower(lpszStr[1]) == 'x') - { - /* Read hex number */ - lpszStr += 2; - - if (!isxdigit(*lpszStr)) - return FALSE; - - while (isxdigit(*lpszStr)) - { - iRet = iRet * 16; - if (isdigit(*lpszStr)) - iRet += (*lpszStr - '0'); - else - iRet += 10 + (tolower(*lpszStr) - 'a'); - lpszStr++; - } - *lpiRet = iRet; - return TRUE; - } - - /* Read decimal number */ - if (!isdigit(*lpszStr)) - return FALSE; - - while (isdigit(*lpszStr)) - { - iRet = iRet * 10; - iRet += (*lpszStr - '0'); - lpszStr++; - } - *lpiRet = bNegative ? -iRet : iRet; - return TRUE; -#endif -} - -/************************************************************************* - * StrToIntExW [SHLWAPI.@] - * - * See StrToIntExA. - */ -BOOL WINAPI StrToIntExW(LPCWSTR lpszStr, DWORD dwFlags, int *lpiRet) -{ - LONGLONG li; - BOOL bRes; - - TRACE("(%s,%08X,%p)\n", debugstr_w(lpszStr), dwFlags, lpiRet); - - bRes = StrToInt64ExW(lpszStr, dwFlags, &li); -#ifdef __REACTOS__ - if (lpiRet) *lpiRet = bRes ? (INT)li : 0; -#else - if (bRes) *lpiRet = li; -#endif - return bRes; -} - -/************************************************************************* - * StrToInt64ExW [SHLWAPI.@] - * - * See StrToIntExA. - */ -BOOL WINAPI StrToInt64ExW(LPCWSTR lpszStr, DWORD dwFlags, LONGLONG *lpiRet) -{ -#ifdef __REACTOS__ - if (!lpszStr) - return FALSE; - - // Skip spaces - LPCWSTR pch = lpszStr; - while (*pch == L' ' || *pch == L'\n' || *pch == L'\t') - pch++; - - BOOL isNegative = FALSE; - if (*pch == L'+' || *pch == L'-') - { - isNegative = (*pch == L'-'); - ++pch; - } - - ULONGLONG value = 0; - LPCWSTR start = pch; - - if ((dwFlags & STIF_SUPPORT_HEX) && - *pch == L'0' && (pch[1] == L'x' || pch[1] == L'X')) // "0x" or "0X" - { - pch += 2; - start = pch; - for (;;) - { - INT digit; - if (IS_DIGIT(*pch)) digit = *pch - L'0'; - else if (L'a' <= *pch && *pch <= L'f') digit = *pch - L'a' + 10; - else if (L'A' <= *pch && *pch <= L'F') digit = *pch - L'A' + 10; - else break; - - value *= 16; - value += digit; - ++pch; - } - isNegative = FALSE; - } - else - { - while (IS_DIGIT(*pch)) - { - value *= 10; - value += (*pch - L'0'); - ++pch; - } - } - - if (pch == start) - { - if (lpiRet) - *lpiRet = 0; - return FALSE; // No data - } - - if (lpiRet) - *lpiRet = isNegative ? -(LONGLONG)value : (LONGLONG)value; - - return TRUE; -#else - BOOL bNegative = FALSE; - LONGLONG iRet = 0; - - TRACE("(%s,%08X,%p)\n", debugstr_w(lpszStr), dwFlags, lpiRet); - - if (!lpszStr || !lpiRet) - { - WARN("Invalid parameter would crash under Win32!\n"); - return FALSE; - } - if (dwFlags > STIF_SUPPORT_HEX) WARN("Unknown flags %08x\n", dwFlags); - - /* Skip leading space, '+', '-' */ - while (isspaceW(*lpszStr)) lpszStr++; - - if (*lpszStr == '-') - { - bNegative = TRUE; - lpszStr++; - } - else if (*lpszStr == '+') - lpszStr++; - - if (dwFlags & STIF_SUPPORT_HEX && - *lpszStr == '0' && tolowerW(lpszStr[1]) == 'x') - { - /* Read hex number */ - lpszStr += 2; - - if (!isxdigitW(*lpszStr)) - return FALSE; - - while (isxdigitW(*lpszStr)) - { - iRet = iRet * 16; - if (isdigitW(*lpszStr)) - iRet += (*lpszStr - '0'); - else - iRet += 10 + (tolowerW(*lpszStr) - 'a'); - lpszStr++; - } - *lpiRet = iRet; - return TRUE; - } - - /* Read decimal number */ - if (!isdigitW(*lpszStr)) - return FALSE; - - while (isdigitW(*lpszStr)) - { - iRet = iRet * 10; - iRet += (*lpszStr - '0'); - lpszStr++; - } - *lpiRet = bNegative ? -iRet : iRet; - return TRUE; -#endif -} - -/************************************************************************* - * StrDupA [SHLWAPI.@] - * - * Duplicate a string. - * - * PARAMS - * lpszStr [I] String to duplicate. - * - * RETURNS - * Success: A pointer to a new string containing the contents of lpszStr - * Failure: NULL, if memory cannot be allocated - * - * NOTES - * The string memory is allocated with LocalAlloc(), and so should be released - * by calling LocalFree(). - */ -LPSTR WINAPI StrDupA(LPCSTR lpszStr) -{ - int iLen; - LPSTR lpszRet; - - TRACE("(%s)\n",debugstr_a(lpszStr)); - -#ifdef __REACTOS__ - if (!lpszStr) - return NULL; -#endif - iLen = lpszStr ? strlen(lpszStr) + 1 : 1; - lpszRet = LocalAlloc(LMEM_FIXED, iLen); - - if (lpszRet) - { - if (lpszStr) - memcpy(lpszRet, lpszStr, iLen); - else - *lpszRet = '\0'; - } - return lpszRet; -} - -/************************************************************************* - * StrDupW [SHLWAPI.@] - * - * See StrDupA. - */ -LPWSTR WINAPI StrDupW(LPCWSTR lpszStr) -{ - int iLen; - LPWSTR lpszRet; - - TRACE("(%s)\n",debugstr_w(lpszStr)); - -#ifdef __REACTOS__ - if (!lpszStr) - return NULL; -#endif - iLen = (lpszStr ? strlenW(lpszStr) + 1 : 1) * sizeof(WCHAR); - lpszRet = LocalAlloc(LMEM_FIXED, iLen); - - if (lpszRet) - { - if (lpszStr) - memcpy(lpszRet, lpszStr, iLen); - else - *lpszRet = '\0'; - } - return lpszRet; -} - -/************************************************************************* - * SHLWAPI_StrSpnHelperA - * - * Internal implementation of StrSpnA/StrCSpnA/StrCSpnIA - */ -static int SHLWAPI_StrSpnHelperA(LPCSTR lpszStr, LPCSTR lpszMatch, - LPSTR (WINAPI *pStrChrFn)(LPCSTR,WORD), - BOOL bInvert) -{ - LPCSTR lpszRead = lpszStr; - if (lpszStr && *lpszStr && lpszMatch) - { - while (*lpszRead) - { - LPCSTR lpszTest = pStrChrFn(lpszMatch, *lpszRead); - - if (!bInvert && !lpszTest) - break; - if (bInvert && lpszTest) - break; - lpszRead = CharNextA(lpszRead); - }; - } - return lpszRead - lpszStr; -} - -/************************************************************************* - * StrSpnA [SHLWAPI.@] - * - * Find the length of the start of a string that contains only certain - * characters. - * - * PARAMS - * lpszStr [I] String to search - * lpszMatch [I] Characters that can be in the substring - * - * RETURNS - * The length of the part of lpszStr containing only chars from lpszMatch, - * or 0 if any parameter is invalid. - */ -int WINAPI StrSpnA(LPCSTR lpszStr, LPCSTR lpszMatch) -{ - TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch)); - - return SHLWAPI_StrSpnHelperA(lpszStr, lpszMatch, StrChrA, FALSE); -} - -/************************************************************************* - * StrSpnW [SHLWAPI.@] - * - * See StrSpnA. - */ -int WINAPI StrSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch) -{ - if (!lpszStr || !lpszMatch) return 0; - return strspnW( lpszStr, lpszMatch ); -} - -/************************************************************************* - * StrCSpnA [SHLWAPI.@] - * - * Find the length of the start of a string that does not contain certain - * characters. - * - * PARAMS - * lpszStr [I] String to search - * lpszMatch [I] Characters that cannot be in the substring - * - * RETURNS - * The length of the part of lpszStr containing only chars not in lpszMatch, - * or 0 if any parameter is invalid. - */ -int WINAPI StrCSpnA(LPCSTR lpszStr, LPCSTR lpszMatch) -{ - TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch)); - - return SHLWAPI_StrSpnHelperA(lpszStr, lpszMatch, StrChrA, TRUE); -} - -/************************************************************************* - * StrCSpnW [SHLWAPI.@] - * - * See StrCSpnA. - */ -int WINAPI StrCSpnW(LPCWSTR lpszStr, LPCWSTR lpszMatch) -{ - if (!lpszStr || !lpszMatch) return 0; - return strcspnW( lpszStr, lpszMatch ); -} - -/************************************************************************* - * StrCSpnIA [SHLWAPI.@] - * - * Find the length of the start of a string that does not contain certain - * characters, ignoring case. - * - * PARAMS - * lpszStr [I] String to search - * lpszMatch [I] Characters that cannot be in the substring - * - * RETURNS - * The length of the part of lpszStr containing only chars not in lpszMatch, - * or 0 if any parameter is invalid. - */ -int WINAPI StrCSpnIA(LPCSTR lpszStr, LPCSTR lpszMatch) -{ - TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch)); - - return SHLWAPI_StrSpnHelperA(lpszStr, lpszMatch, StrChrIA, TRUE); -} - -/************************************************************************* - * StrCSpnIW [SHLWAPI.@] - * - * See StrCSpnIA. - */ -int WINAPI StrCSpnIW(LPCWSTR lpszStr, LPCWSTR lpszMatch) -{ - LPCWSTR lpszRead = lpszStr; - - TRACE("(%s,%s)\n",debugstr_w(lpszStr), debugstr_w(lpszMatch)); - - if (lpszStr && *lpszStr && lpszMatch) - { - while (*lpszRead) - { - if (StrChrIW(lpszMatch, *lpszRead)) break; - lpszRead++; - } - } - return lpszRead - lpszStr; -} - -/************************************************************************* - * StrPBrkA [SHLWAPI.@] - * - * Search a string for any of a group of characters. - * - * PARAMS - * lpszStr [I] String to search - * lpszMatch [I] Characters to match - * - * RETURNS - * A pointer to the first matching character in lpszStr, or NULL if no - * match was found. - */ -LPSTR WINAPI StrPBrkA(LPCSTR lpszStr, LPCSTR lpszMatch) -{ - TRACE("(%s,%s)\n",debugstr_a(lpszStr), debugstr_a(lpszMatch)); - - if (lpszStr && lpszMatch && *lpszMatch) - { - while (*lpszStr) - { - if (StrChrA(lpszMatch, *lpszStr)) - return (LPSTR)lpszStr; - lpszStr = CharNextA(lpszStr); - } - } - return NULL; -} - -/************************************************************************* - * StrPBrkW [SHLWAPI.@] - * - * See StrPBrkA. - */ -LPWSTR WINAPI StrPBrkW(LPCWSTR lpszStr, LPCWSTR lpszMatch) -{ - if (!lpszStr || !lpszMatch) return NULL; - return strpbrkW( lpszStr, lpszMatch ); -} - -/************************************************************************* - * SHLWAPI_StrRChrHelperA - * - * Internal implementation of StrRChrA/StrRChrIA. - */ -static LPSTR SHLWAPI_StrRChrHelperA(LPCSTR lpszStr, - LPCSTR lpszEnd, WORD ch, - BOOL (WINAPI *pChrCmpFn)(WORD,WORD)) -{ - LPCSTR lpszRet = NULL; - - if (lpszStr) - { - WORD ch2; - - if (!lpszEnd) - lpszEnd = lpszStr + lstrlenA(lpszStr); - - while (*lpszStr && lpszStr <= lpszEnd) - { - ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | lpszStr[1] : *lpszStr; - - if (!pChrCmpFn(ch, ch2)) - lpszRet = lpszStr; - lpszStr = CharNextA(lpszStr); - } - } - return (LPSTR)lpszRet; -} - -/************************************************************************** - * StrRChrA [SHLWAPI.@] - * - * Find the last occurrence of a character in string. - * - * PARAMS - * lpszStr [I] String to search in - * lpszEnd [I] Place to end search, or NULL to search until the end of lpszStr - * ch [I] Character to search for. - * - * RETURNS - * Success: A pointer to the last occurrence of ch in lpszStr before lpszEnd, - * or NULL if not found. - * Failure: NULL, if any arguments are invalid. - */ -LPSTR WINAPI StrRChrA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch) -{ - TRACE("(%s,%s,%x)\n", debugstr_a(lpszStr), debugstr_a(lpszEnd), ch); - - return SHLWAPI_StrRChrHelperA(lpszStr, lpszEnd, ch, SHLWAPI_ChrCmpA); -} - -/************************************************************************** - * StrRChrW [SHLWAPI.@] - * - * See StrRChrA. - */ -LPWSTR WINAPI StrRChrW(LPCWSTR str, LPCWSTR 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; -} - -/************************************************************************** - * StrRChrIA [SHLWAPI.@] - * - * Find the last occurrence of a character in string, ignoring case. - * - * PARAMS - * lpszStr [I] String to search in - * lpszEnd [I] Place to end search, or NULL to search until the end of lpszStr - * ch [I] Character to search for. - * - * RETURNS - * Success: A pointer to the last occurrence of ch in lpszStr before lpszEnd, - * or NULL if not found. - * Failure: NULL, if any arguments are invalid. - */ -LPSTR WINAPI StrRChrIA(LPCSTR lpszStr, LPCSTR lpszEnd, WORD ch) -{ - TRACE("(%s,%s,%x)\n", debugstr_a(lpszStr), debugstr_a(lpszEnd), ch); - - return SHLWAPI_StrRChrHelperA(lpszStr, lpszEnd, ch, ChrCmpIA); -} - -/************************************************************************** - * StrRChrIW [SHLWAPI.@] - * - * See StrRChrIA. - */ -LPWSTR WINAPI StrRChrIW(LPCWSTR str, LPCWSTR 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; -} - -/************************************************************************* - * StrCatBuffA [SHLWAPI.@] - * - * Concatenate two strings together. - * - * PARAMS - * lpszStr [O] String to concatenate to - * lpszCat [I] String to add to lpszCat - * cchMax [I] Maximum number of characters for the whole string - * - * RETURNS - * lpszStr. - * - * NOTES - * cchMax determines the number of characters in the final length of the - * string, not the number appended to lpszStr from lpszCat. - */ -LPSTR WINAPI StrCatBuffA(LPSTR lpszStr, LPCSTR lpszCat, INT cchMax) -{ - INT iLen; - - TRACE("(%p,%s,%d)\n", lpszStr, debugstr_a(lpszCat), cchMax); - - if (!lpszStr) - { - WARN("Invalid lpszStr would crash under Win32!\n"); - return NULL; - } - - iLen = strlen(lpszStr); - cchMax -= iLen; - - if (cchMax > 0) - StrCpyNA(lpszStr + iLen, lpszCat, cchMax); - return lpszStr; -} - -/************************************************************************* - * StrCatBuffW [SHLWAPI.@] - * - * See StrCatBuffA. - */ -LPWSTR WINAPI StrCatBuffW(LPWSTR lpszStr, LPCWSTR lpszCat, INT cchMax) -{ - INT iLen; - - TRACE("(%p,%s,%d)\n", lpszStr, debugstr_w(lpszCat), cchMax); - - if (!lpszStr) - { - WARN("Invalid lpszStr would crash under Win32!\n"); - return NULL; - } - - iLen = strlenW(lpszStr); - cchMax -= iLen; - - if (cchMax > 0) - StrCpyNW(lpszStr + iLen, lpszCat, cchMax); - return lpszStr; -} - /************************************************************************* * StrRetToBufA [SHLWAPI.@] * @@ -1950,95 +544,6 @@ LPWSTR WINAPI StrNCatW(LPWSTR lpszStr, LPCWSTR lpszCat, INT cchMax) return lpszRet; } -/************************************************************************* - * StrTrimA [SHLWAPI.@] - * - * Remove characters from the start and end of a string. - * - * PARAMS - * lpszStr [O] String to remove characters from - * lpszTrim [I] Characters to remove from lpszStr - * - * RETURNS - * TRUE If lpszStr was valid and modified - * FALSE Otherwise - */ -BOOL WINAPI StrTrimA(LPSTR lpszStr, LPCSTR lpszTrim) -{ - DWORD dwLen; - LPSTR lpszRead = lpszStr; - BOOL bRet = FALSE; - - TRACE("(%s,%s)\n", debugstr_a(lpszStr), debugstr_a(lpszTrim)); - - if (lpszRead && *lpszRead) - { - while (*lpszRead && StrChrA(lpszTrim, *lpszRead)) - lpszRead = CharNextA(lpszRead); /* Skip leading matches */ - - dwLen = strlen(lpszRead); - - if (lpszRead != lpszStr) - { - memmove(lpszStr, lpszRead, dwLen + 1); - bRet = TRUE; - } - if (dwLen > 0) - { - lpszRead = lpszStr + dwLen; - while (StrChrA(lpszTrim, lpszRead[-1])) - lpszRead = CharPrevA(lpszStr, lpszRead); /* Skip trailing matches */ - - if (lpszRead != lpszStr + dwLen) - { - *lpszRead = '\0'; - bRet = TRUE; - } - } - } - return bRet; -} - -/************************************************************************* - * StrTrimW [SHLWAPI.@] - * - * See StrTrimA. - */ -BOOL WINAPI StrTrimW(LPWSTR lpszStr, LPCWSTR lpszTrim) -{ - DWORD dwLen; - LPWSTR lpszRead = lpszStr; - BOOL bRet = FALSE; - - TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszTrim)); - - if (lpszRead && *lpszRead) - { - while (*lpszRead && StrChrW(lpszTrim, *lpszRead)) lpszRead++; - - dwLen = strlenW(lpszRead); - - if (lpszRead != lpszStr) - { - memmove(lpszStr, lpszRead, (dwLen + 1) * sizeof(WCHAR)); - bRet = TRUE; - } - if (dwLen > 0) - { - lpszRead = lpszStr + dwLen; - while (StrChrW(lpszTrim, lpszRead[-1])) - lpszRead--; /* Skip trailing matches */ - - if (lpszRead != lpszStr + dwLen) - { - *lpszRead = '\0'; - bRet = TRUE; - } - } - } - return bRet; -} - /************************************************************************* * _SHStrDupAA [INTERNAL] * @@ -2316,175 +821,6 @@ INT WINAPI StrFromTimeIntervalW(LPWSTR lpszStr, UINT cchMax, DWORD dwMS, return iRet; } -/************************************************************************* - * StrIsIntlEqualA [SHLWAPI.@] - * - * Compare two strings. - * - * PARAMS - * bCase [I] Whether to compare case sensitively - * lpszStr [I] First string to compare - * lpszComp [I] Second string to compare - * iLen [I] Length to compare - * - * RETURNS - * TRUE If the strings are equal. - * FALSE Otherwise. - */ -BOOL WINAPI StrIsIntlEqualA(BOOL bCase, LPCSTR lpszStr, LPCSTR lpszComp, - int iLen) -{ - DWORD dwFlags; - - TRACE("(%d,%s,%s,%d)\n", bCase, - debugstr_a(lpszStr), debugstr_a(lpszComp), iLen); - - /* FIXME: This flag is undocumented and unknown by our CompareString. - * We need a define for it. - */ - dwFlags = 0x10000000; - if (!bCase) dwFlags |= NORM_IGNORECASE; - - return (CompareStringA(GetThreadLocale(), dwFlags, lpszStr, iLen, lpszComp, iLen) == CSTR_EQUAL); -} - -/************************************************************************* - * StrIsIntlEqualW [SHLWAPI.@] - * - * See StrIsIntlEqualA. - */ -BOOL WINAPI StrIsIntlEqualW(BOOL bCase, LPCWSTR lpszStr, LPCWSTR lpszComp, - int iLen) -{ - DWORD dwFlags; - - TRACE("(%d,%s,%s,%d)\n", bCase, - debugstr_w(lpszStr),debugstr_w(lpszComp), iLen); - - /* FIXME: This flag is undocumented and unknown by our CompareString. - * We need a define for it. - */ - dwFlags = 0x10000000; - if (!bCase) dwFlags |= NORM_IGNORECASE; - - return (CompareStringW(GetThreadLocale(), dwFlags, lpszStr, iLen, lpszComp, iLen) == CSTR_EQUAL); -} - -/************************************************************************* - * @ [SHLWAPI.399] - * - * Copy a string to another string, up to a maximum number of characters. - * - * PARAMS - * lpszDest [O] Destination string - * lpszSrc [I] Source string - * iLen [I] Maximum number of chars to copy - * - * RETURNS - * Success: A pointer to the last character written to lpszDest. - * Failure: lpszDest, if any arguments are invalid. - */ -LPSTR WINAPI StrCpyNXA(LPSTR lpszDest, LPCSTR lpszSrc, int iLen) -{ - TRACE("(%p,%s,%i)\n", lpszDest, debugstr_a(lpszSrc), iLen); - - if (lpszDest && lpszSrc && iLen > 0) - { - while ((iLen-- > 1) && *lpszSrc) - *lpszDest++ = *lpszSrc++; - if (iLen >= 0) - *lpszDest = '\0'; - } - return lpszDest; -} - -/************************************************************************* - * @ [SHLWAPI.400] - * - * Unicode version of StrCpyNXA. - */ -LPWSTR WINAPI StrCpyNXW(LPWSTR lpszDest, LPCWSTR lpszSrc, int iLen) -{ - TRACE("(%p,%s,%i)\n", lpszDest, debugstr_w(lpszSrc), iLen); - - if (lpszDest && lpszSrc && iLen > 0) - { - while ((iLen-- > 1) && *lpszSrc) - *lpszDest++ = *lpszSrc++; - if (iLen >= 0) - *lpszDest = '\0'; - } - return lpszDest; -} - -/************************************************************************* - * StrCmpLogicalW [SHLWAPI.@] - * - * Compare two strings, ignoring case and comparing digits as numbers. - * - * PARAMS - * lpszStr [I] First string to compare - * lpszComp [I] Second string to compare - * iLen [I] Length to compare - * - * RETURNS - * TRUE If the strings are equal. - * FALSE Otherwise. - */ -INT WINAPI StrCmpLogicalW(LPCWSTR lpszStr, LPCWSTR lpszComp) -{ - INT iDiff; - - TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszComp)); - - if (lpszStr && lpszComp) - { - while (*lpszStr) - { - if (!*lpszComp) - return 1; - else if (isdigitW(*lpszStr)) - { - int iStr, iComp; - - if (!isdigitW(*lpszComp)) - return -1; - - /* Compare the numbers */ - StrToIntExW(lpszStr, 0, &iStr); - StrToIntExW(lpszComp, 0, &iComp); - - if (iStr < iComp) - return -1; - else if (iStr > iComp) - return 1; - - /* Skip */ - while (isdigitW(*lpszStr)) - lpszStr++; - while (isdigitW(*lpszComp)) - lpszComp++; - } - else if (isdigitW(*lpszComp)) - return 1; - else - { - iDiff = ChrCmpIW(*lpszStr,*lpszComp); - if (iDiff > 0) - return 1; - else if (iDiff < 0) - return -1; - - lpszStr++; - lpszComp++; - } - } - if (*lpszComp) - return -1; - } - return 0; -} - /* Structure for formatting byte strings */ typedef struct tagSHLWAPI_BYTEFORMATS { @@ -2693,38 +1029,6 @@ LPSTR WINAPI StrFormatByteSizeA(DWORD dwBytes, LPSTR lpszDest, UINT cchMax) return StrFormatByteSize64A(dwBytes, lpszDest, cchMax); } -/************************************************************************* - * @ [SHLWAPI.162] - * - * Remove a hanging lead byte from the end of a string, if present. - * - * PARAMS - * lpStr [I] String to check for a hanging lead byte - * size [I] Length of lpStr - * - * RETURNS - * Success: The new length of the string. Any hanging lead bytes are removed. - * Failure: 0, if any parameters are invalid. - */ -DWORD WINAPI SHTruncateString(LPSTR lpStr, DWORD size) -{ - if (lpStr && size) - { - LPSTR lastByte = lpStr + size - 1; - - while(lpStr < lastByte) - lpStr += IsDBCSLeadByte(*lpStr) ? 2 : 1; - - if(lpStr == lastByte && IsDBCSLeadByte(*lpStr)) - { - *lpStr = '\0'; - size--; - } - return size; - } - return 0; -} - /************************************************************************* * @ [SHLWAPI.203] * @@ -3000,75 +1304,6 @@ BOOL WINAPI DoesStringRoundTripW(LPCWSTR lpSrcStr, LPSTR lpDst, INT iLen) return !wcscmp(lpSrcStr, szBuff); } -/************************************************************************* - * SHLoadIndirectString [SHLWAPI.@] - * - * If passed a string that begins with '@', extract the string from the - * appropriate resource, otherwise do a straight copy. - * - */ -HRESULT WINAPI SHLoadIndirectString(LPCWSTR src, LPWSTR dst, UINT dst_len, void **reserved) -{ - WCHAR *dllname = NULL; - HMODULE hmod = NULL; - HRESULT hr = E_FAIL; -#ifdef __REACTOS__ - WCHAR szExpanded[512]; -#endif - - TRACE("(%s %p %08x %p)\n", debugstr_w(src), dst, dst_len, reserved); - - if(src[0] == '@') - { - WCHAR *index_str; - int index; - -#ifdef __REACTOS__ - if (wcschr(src, '%') != NULL) - { - ExpandEnvironmentStringsW(src, szExpanded, ARRAY_SIZE(szExpanded)); - src = szExpanded; - } -#endif - dst[0] = 0; - dllname = StrDupW(src + 1); - index_str = strchrW(dllname, ','); - - if(!index_str) goto end; - - *index_str = 0; - index_str++; - index = atoiW(index_str); - -#ifdef __REACTOS__ - hmod = LoadLibraryExW(dllname, NULL, LOAD_LIBRARY_AS_DATAFILE); -#else - hmod = LoadLibraryW(dllname); -#endif - if(!hmod) goto end; - - if(index < 0) - { - if(LoadStringW(hmod, -index, dst, dst_len)) - hr = S_OK; - } - else - FIXME("can't handle non-negative indices (%d)\n", index); - } - else - { - if(dst != src) - lstrcpynW(dst, src, dst_len); - hr = S_OK; - } - - TRACE("returning %s\n", debugstr_w(dst)); -end: - if(hmod) FreeLibrary(hmod); - LocalFree(dllname); - return hr; -} - BOOL WINAPI IsCharSpaceA(CHAR c) { WORD CharType; diff --git a/dll/win32/shlwapi/url.c b/dll/win32/shlwapi/url.c index fae290ca4ac..58906517320 100644 --- a/dll/win32/shlwapi/url.c +++ b/dll/win32/shlwapi/url.c @@ -25,7 +25,6 @@ #include "winbase.h" #include "winnls.h" #include "winerror.h" -#include "wine/unicode.h" #include "wininet.h" #include "winreg.h" #include "winternl.h" @@ -40,2478 +39,6 @@ HRESULT WINAPI MLBuildResURLW(LPCWSTR,HMODULE,DWORD,LPCWSTR,LPWSTR,DWORD); WINE_DEFAULT_DEBUG_CHANNEL(shell); -static inline WCHAR *heap_strdupAtoW(const char *str) -{ - LPWSTR ret = NULL; - - if(str) { - DWORD len; - - len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0); - ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len); - } - - return ret; -} - -/* The following schemes were identified in the native version of - * SHLWAPI.DLL version 5.50 - */ -static const struct { - URL_SCHEME scheme_number; - WCHAR scheme_name[12]; -} shlwapi_schemes[] = { - {URL_SCHEME_FTP, {'f','t','p',0}}, - {URL_SCHEME_HTTP, {'h','t','t','p',0}}, - {URL_SCHEME_GOPHER, {'g','o','p','h','e','r',0}}, - {URL_SCHEME_MAILTO, {'m','a','i','l','t','o',0}}, - {URL_SCHEME_NEWS, {'n','e','w','s',0}}, - {URL_SCHEME_NNTP, {'n','n','t','p',0}}, - {URL_SCHEME_TELNET, {'t','e','l','n','e','t',0}}, - {URL_SCHEME_WAIS, {'w','a','i','s',0}}, - {URL_SCHEME_FILE, {'f','i','l','e',0}}, - {URL_SCHEME_MK, {'m','k',0}}, - {URL_SCHEME_HTTPS, {'h','t','t','p','s',0}}, - {URL_SCHEME_SHELL, {'s','h','e','l','l',0}}, - {URL_SCHEME_SNEWS, {'s','n','e','w','s',0}}, - {URL_SCHEME_LOCAL, {'l','o','c','a','l',0}}, - {URL_SCHEME_JAVASCRIPT, {'j','a','v','a','s','c','r','i','p','t',0}}, - {URL_SCHEME_VBSCRIPT, {'v','b','s','c','r','i','p','t',0}}, - {URL_SCHEME_ABOUT, {'a','b','o','u','t',0}}, - {URL_SCHEME_RES, {'r','e','s',0}}, -}; - -typedef struct { - LPCWSTR pScheme; /* [out] start of scheme */ - DWORD szScheme; /* [out] size of scheme (until colon) */ - LPCWSTR pUserName; /* [out] start of Username */ - DWORD szUserName; /* [out] size of Username (until ":" or "@") */ - LPCWSTR pPassword; /* [out] start of Password */ - DWORD szPassword; /* [out] size of Password (until "@") */ - LPCWSTR pHostName; /* [out] start of Hostname */ - DWORD szHostName; /* [out] size of Hostname (until ":" or "/") */ - LPCWSTR pPort; /* [out] start of Port */ - DWORD szPort; /* [out] size of Port (until "/" or eos) */ - LPCWSTR pQuery; /* [out] start of Query */ - DWORD szQuery; /* [out] size of Query (until eos) */ -} WINE_PARSE_URL; - -typedef enum { - SCHEME, - HOST, - PORT, - USERPASS, -} WINE_URL_SCAN_TYPE; - -static const CHAR hexDigits[] = "0123456789ABCDEF"; - -static const WCHAR fileW[] = {'f','i','l','e','\0'}; - -static const unsigned char HashDataLookup[256] = { - 0x01, 0x0E, 0x6E, 0x19, 0x61, 0xAE, 0x84, 0x77, 0x8A, 0xAA, 0x7D, 0x76, 0x1B, - 0xE9, 0x8C, 0x33, 0x57, 0xC5, 0xB1, 0x6B, 0xEA, 0xA9, 0x38, 0x44, 0x1E, 0x07, - 0xAD, 0x49, 0xBC, 0x28, 0x24, 0x41, 0x31, 0xD5, 0x68, 0xBE, 0x39, 0xD3, 0x94, - 0xDF, 0x30, 0x73, 0x0F, 0x02, 0x43, 0xBA, 0xD2, 0x1C, 0x0C, 0xB5, 0x67, 0x46, - 0x16, 0x3A, 0x4B, 0x4E, 0xB7, 0xA7, 0xEE, 0x9D, 0x7C, 0x93, 0xAC, 0x90, 0xB0, - 0xA1, 0x8D, 0x56, 0x3C, 0x42, 0x80, 0x53, 0x9C, 0xF1, 0x4F, 0x2E, 0xA8, 0xC6, - 0x29, 0xFE, 0xB2, 0x55, 0xFD, 0xED, 0xFA, 0x9A, 0x85, 0x58, 0x23, 0xCE, 0x5F, - 0x74, 0xFC, 0xC0, 0x36, 0xDD, 0x66, 0xDA, 0xFF, 0xF0, 0x52, 0x6A, 0x9E, 0xC9, - 0x3D, 0x03, 0x59, 0x09, 0x2A, 0x9B, 0x9F, 0x5D, 0xA6, 0x50, 0x32, 0x22, 0xAF, - 0xC3, 0x64, 0x63, 0x1A, 0x96, 0x10, 0x91, 0x04, 0x21, 0x08, 0xBD, 0x79, 0x40, - 0x4D, 0x48, 0xD0, 0xF5, 0x82, 0x7A, 0x8F, 0x37, 0x69, 0x86, 0x1D, 0xA4, 0xB9, - 0xC2, 0xC1, 0xEF, 0x65, 0xF2, 0x05, 0xAB, 0x7E, 0x0B, 0x4A, 0x3B, 0x89, 0xE4, - 0x6C, 0xBF, 0xE8, 0x8B, 0x06, 0x18, 0x51, 0x14, 0x7F, 0x11, 0x5B, 0x5C, 0xFB, - 0x97, 0xE1, 0xCF, 0x15, 0x62, 0x71, 0x70, 0x54, 0xE2, 0x12, 0xD6, 0xC7, 0xBB, - 0x0D, 0x20, 0x5E, 0xDC, 0xE0, 0xD4, 0xF7, 0xCC, 0xC4, 0x2B, 0xF9, 0xEC, 0x2D, - 0xF4, 0x6F, 0xB6, 0x99, 0x88, 0x81, 0x5A, 0xD9, 0xCA, 0x13, 0xA5, 0xE7, 0x47, - 0xE6, 0x8E, 0x60, 0xE3, 0x3E, 0xB3, 0xF6, 0x72, 0xA2, 0x35, 0xA0, 0xD7, 0xCD, - 0xB4, 0x2F, 0x6D, 0x2C, 0x26, 0x1F, 0x95, 0x87, 0x00, 0xD8, 0x34, 0x3F, 0x17, - 0x25, 0x45, 0x27, 0x75, 0x92, 0xB8, 0xA3, 0xC8, 0xDE, 0xEB, 0xF8, 0xF3, 0xDB, - 0x0A, 0x98, 0x83, 0x7B, 0xE5, 0xCB, 0x4C, 0x78, 0xD1 }; - -static DWORD get_scheme_code(LPCWSTR scheme, DWORD scheme_len) -{ - unsigned int i; - - for(i=0; i < sizeof(shlwapi_schemes)/sizeof(shlwapi_schemes[0]); i++) { - if(scheme_len == strlenW(shlwapi_schemes[i].scheme_name) - && !memicmpW(scheme, shlwapi_schemes[i].scheme_name, scheme_len)) - return shlwapi_schemes[i].scheme_number; - } - - return URL_SCHEME_UNKNOWN; -} - -/************************************************************************* - * @ [SHLWAPI.1] - * - * Parse a Url into its constituent parts. - * - * PARAMS - * x [I] Url to parse - * y [O] Undocumented structure holding the parsed information - * - * RETURNS - * Success: S_OK. y contains the parsed Url details. - * Failure: An HRESULT error code. - */ -HRESULT WINAPI ParseURLA(LPCSTR x, PARSEDURLA *y) -{ - WCHAR scheme[INTERNET_MAX_SCHEME_LENGTH]; - const char *ptr = x; - int len; - - TRACE("%s %p\n", debugstr_a(x), y); - - if(y->cbSize != sizeof(*y)) - return E_INVALIDARG; - - while(*ptr && (isalnum(*ptr) || *ptr == '-' || *ptr == '+' || *ptr == '.')) - ptr++; - - if (*ptr != ':' || ptr <= x+1) { - y->pszProtocol = NULL; - return URL_E_INVALID_SYNTAX; - } - - y->pszProtocol = x; - y->cchProtocol = ptr-x; - y->pszSuffix = ptr+1; - y->cchSuffix = strlen(y->pszSuffix); - - len = MultiByteToWideChar(CP_ACP, 0, x, ptr-x, - scheme, sizeof(scheme)/sizeof(WCHAR)); - y->nScheme = get_scheme_code(scheme, len); - - return S_OK; -} - -/************************************************************************* - * @ [SHLWAPI.2] - * - * Unicode version of ParseURLA. - */ -HRESULT WINAPI ParseURLW(LPCWSTR x, PARSEDURLW *y) -{ - const WCHAR *ptr = x; - - TRACE("%s %p\n", debugstr_w(x), y); - - if(y->cbSize != sizeof(*y)) - return E_INVALIDARG; - - while(*ptr && (isalnumW(*ptr) || *ptr == '-' || *ptr == '+' || *ptr == '.')) - ptr++; - - if (*ptr != ':' || ptr <= x+1) { - y->pszProtocol = NULL; - return URL_E_INVALID_SYNTAX; - } - - y->pszProtocol = x; - y->cchProtocol = ptr-x; - y->pszSuffix = ptr+1; - y->cchSuffix = strlenW(y->pszSuffix); - y->nScheme = get_scheme_code(x, ptr-x); - - return S_OK; -} - -/************************************************************************* - * UrlCanonicalizeA [SHLWAPI.@] - * - * Canonicalize a Url. - * - * PARAMS - * pszUrl [I] Url to cCanonicalize - * pszCanonicalized [O] Destination for converted Url. - * pcchCanonicalized [I/O] Length of pszUrl, destination for length of pszCanonicalized - * dwFlags [I] Flags controlling the conversion. - * - * RETURNS - * Success: S_OK. The pszCanonicalized contains the converted Url. - * Failure: E_POINTER, if *pcchCanonicalized is too small. - * - * MSDN incorrectly describes the flags for this function. They should be: - *| URL_DONT_ESCAPE_EXTRA_INFO 0x02000000 - *| URL_ESCAPE_SPACES_ONLY 0x04000000 - *| URL_ESCAPE_PERCENT 0x00001000 - *| URL_ESCAPE_UNSAFE 0x10000000 - *| URL_UNESCAPE 0x10000000 - *| URL_DONT_SIMPLIFY 0x08000000 - *| URL_ESCAPE_SEGMENT_ONLY 0x00002000 - */ -HRESULT WINAPI UrlCanonicalizeA(LPCSTR pszUrl, LPSTR pszCanonicalized, - LPDWORD pcchCanonicalized, DWORD dwFlags) -{ - LPWSTR url, canonical; - HRESULT ret; - - TRACE("(%s, %p, %p, 0x%08x) *pcchCanonicalized: %d\n", debugstr_a(pszUrl), pszCanonicalized, - pcchCanonicalized, dwFlags, pcchCanonicalized ? *pcchCanonicalized : -1); - - if(!pszUrl || !pszCanonicalized || !pcchCanonicalized || !*pcchCanonicalized) - return E_INVALIDARG; - - url = heap_strdupAtoW(pszUrl); - canonical = HeapAlloc(GetProcessHeap(), 0, *pcchCanonicalized*sizeof(WCHAR)); - if(!url || !canonical) { - HeapFree(GetProcessHeap(), 0, url); - HeapFree(GetProcessHeap(), 0, canonical); - return E_OUTOFMEMORY; - } - - ret = UrlCanonicalizeW(url, canonical, pcchCanonicalized, dwFlags); - if(ret == S_OK) - WideCharToMultiByte(CP_ACP, 0, canonical, -1, pszCanonicalized, - *pcchCanonicalized+1, NULL, NULL); - - HeapFree(GetProcessHeap(), 0, url); - HeapFree(GetProcessHeap(), 0, canonical); - return ret; -} - -/************************************************************************* - * UrlCanonicalizeW [SHLWAPI.@] - * - * See UrlCanonicalizeA. - */ -HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized, - LPDWORD pcchCanonicalized, DWORD dwFlags) -{ - HRESULT hr = S_OK; - DWORD EscapeFlags; - LPCWSTR wk1, root; - LPWSTR lpszUrlCpy, url, wk2, mp, mp2; - INT state; - DWORD nByteLen, nLen, nWkLen; - BOOL is_file_url; - WCHAR slash = '\0'; - - static const WCHAR wszFile[] = {'f','i','l','e',':'}; - static const WCHAR wszRes[] = {'r','e','s',':'}; - static const WCHAR wszHttp[] = {'h','t','t','p',':'}; - static const WCHAR wszLocalhost[] = {'l','o','c','a','l','h','o','s','t'}; - static const WCHAR wszFilePrefix[] = {'f','i','l','e',':','/','/','/'}; - - TRACE("(%s, %p, %p, 0x%08x) *pcchCanonicalized: %d\n", debugstr_w(pszUrl), pszCanonicalized, - pcchCanonicalized, dwFlags, pcchCanonicalized ? *pcchCanonicalized : -1); - - if(!pszUrl || !pszCanonicalized || !pcchCanonicalized || !*pcchCanonicalized) - return E_INVALIDARG; - - if(!*pszUrl) { - *pszCanonicalized = 0; - return S_OK; - } - - /* Remove '\t' characters from URL */ - nByteLen = (strlenW(pszUrl) + 1) * sizeof(WCHAR); /* length in bytes */ - url = HeapAlloc(GetProcessHeap(), 0, nByteLen); - if(!url) - return E_OUTOFMEMORY; - - wk1 = pszUrl; - wk2 = url; - do { - while(*wk1 == '\t') - wk1++; - *wk2++ = *wk1; - } while(*wk1++); - - /* Allocate memory for simplified URL (before escaping) */ - nByteLen = (wk2-url)*sizeof(WCHAR); - lpszUrlCpy = HeapAlloc(GetProcessHeap(), 0, - nByteLen+sizeof(wszFilePrefix)+sizeof(WCHAR)); - if(!lpszUrlCpy) { - HeapFree(GetProcessHeap(), 0, url); - return E_OUTOFMEMORY; - } - - is_file_url = !strncmpW(wszFile, url, sizeof(wszFile)/sizeof(WCHAR)); - - if ((nByteLen >= sizeof(wszHttp) && - !memcmp(wszHttp, url, sizeof(wszHttp))) || is_file_url) - slash = '/'; - - if((dwFlags & (URL_FILE_USE_PATHURL | URL_WININET_COMPATIBILITY)) && is_file_url) - slash = '\\'; - - if(nByteLen >= sizeof(wszRes) && !memcmp(wszRes, url, sizeof(wszRes))) { - dwFlags &= ~URL_FILE_USE_PATHURL; - slash = '\0'; - } - - /* - * state = - * 0 initial 1,3 - * 1 have 2[+] alnum 2,3 - * 2 have scheme (found :) 4,6,3 - * 3 failed (no location) - * 4 have // 5,3 - * 5 have 1[+] alnum 6,3 - * 6 have location (found /) save root location - */ - - wk1 = url; - wk2 = lpszUrlCpy; - state = 0; - - if(url[1] == ':') { /* Assume path */ - memcpy(wk2, wszFilePrefix, sizeof(wszFilePrefix)); - wk2 += sizeof(wszFilePrefix)/sizeof(WCHAR); - if (dwFlags & (URL_FILE_USE_PATHURL | URL_WININET_COMPATIBILITY)) - { - slash = '\\'; - --wk2; - } - else - dwFlags |= URL_ESCAPE_UNSAFE; - state = 5; - is_file_url = TRUE; - } else if(url[0] == '/') { - state = 5; - is_file_url = TRUE; - } - - while (*wk1) { - switch (state) { - case 0: - if (!isalnumW(*wk1)) {state = 3; break;} - *wk2++ = *wk1++; - if (!isalnumW(*wk1)) {state = 3; break;} - *wk2++ = *wk1++; - state = 1; - break; - case 1: - *wk2++ = *wk1; - if (*wk1++ == ':') state = 2; - break; - case 2: - *wk2++ = *wk1++; - if (*wk1 != '/') {state = 6; break;} - *wk2++ = *wk1++; - if((dwFlags & URL_FILE_USE_PATHURL) && nByteLen >= sizeof(wszLocalhost) - && is_file_url - && !memcmp(wszLocalhost, wk1, sizeof(wszLocalhost))){ - wk1 += sizeof(wszLocalhost)/sizeof(WCHAR); - while(*wk1 == '\\' && (dwFlags & URL_FILE_USE_PATHURL)) - wk1++; - } - - if(*wk1 == '/' && (dwFlags & URL_FILE_USE_PATHURL)){ - wk1++; - }else if(is_file_url){ - const WCHAR *body = wk1; - - while(*body == '/') - ++body; - - if(isalnumW(*body) && *(body+1) == ':'){ - if(!(dwFlags & (URL_WININET_COMPATIBILITY | URL_FILE_USE_PATHURL))){ - if(slash) - *wk2++ = slash; - else - *wk2++ = '/'; - } - }else{ - if(dwFlags & URL_WININET_COMPATIBILITY){ - if(*wk1 == '/' && *(wk1+1) != '/'){ - *wk2++ = '\\'; - }else{ - *wk2++ = '\\'; - *wk2++ = '\\'; - } - }else{ - if(*wk1 == '/' && *(wk1+1) != '/'){ - if(slash) - *wk2++ = slash; - else - *wk2++ = '/'; - } - } - } - wk1 = body; - } - state = 4; - break; - case 3: - nWkLen = strlenW(wk1); - memcpy(wk2, wk1, (nWkLen + 1) * sizeof(WCHAR)); - mp = wk2; - wk1 += nWkLen; - wk2 += nWkLen; - - if(slash) { - while(mp < wk2) { - if(*mp == '/' || *mp == '\\') - *mp = slash; - mp++; - } - } - break; - case 4: - if (!isalnumW(*wk1) && (*wk1 != '-') && (*wk1 != '.') && (*wk1 != ':')) - {state = 3; break;} - while(isalnumW(*wk1) || (*wk1 == '-') || (*wk1 == '.') || (*wk1 == ':')) - *wk2++ = *wk1++; - state = 5; - if (!*wk1) { - if(slash) - *wk2++ = slash; - else - *wk2++ = '/'; - } - break; - case 5: - if (*wk1 != '/' && *wk1 != '\\') {state = 3; break;} - while(*wk1 == '/' || *wk1 == '\\') { - if(slash) - *wk2++ = slash; - else - *wk2++ = *wk1; - wk1++; - } - state = 6; - break; - case 6: - if(dwFlags & URL_DONT_SIMPLIFY) { - state = 3; - break; - } - - /* Now at root location, cannot back up any more. */ - /* "root" will point at the '/' */ - - root = wk2-1; - while (*wk1) { - mp = strchrW(wk1, '/'); - mp2 = strchrW(wk1, '\\'); - if(mp2 && (!mp || mp2 < mp)) - mp = mp2; - if (!mp) { - nWkLen = strlenW(wk1); - memcpy(wk2, wk1, (nWkLen + 1) * sizeof(WCHAR)); - wk1 += nWkLen; - wk2 += nWkLen; - continue; - } - nLen = mp - wk1; - if(nLen) { - memcpy(wk2, wk1, nLen * sizeof(WCHAR)); - wk2 += nLen; - wk1 += nLen; - } - if(slash) - *wk2++ = slash; - else - *wk2++ = *wk1; - wk1++; - - while (*wk1 == '.') { - TRACE("found '/.'\n"); - if (wk1[1] == '/' || wk1[1] == '\\') { - /* case of /./ -> skip the ./ */ - wk1 += 2; - } - else if (wk1[1] == '.' && (wk1[2] == '/' - || wk1[2] == '\\' || wk1[2] == '?' - || wk1[2] == '#' || !wk1[2])) { - /* case /../ -> need to backup wk2 */ - TRACE("found '/../'\n"); - *(wk2-1) = '\0'; /* set end of string */ - mp = strrchrW(root, '/'); - mp2 = strrchrW(root, '\\'); - if(mp2 && (!mp || mp2 < mp)) - mp = mp2; - if (mp && (mp >= root)) { - /* found valid backup point */ - wk2 = mp + 1; - if(wk1[2] != '/' && wk1[2] != '\\') - wk1 += 2; - else - wk1 += 3; - } - else { - /* did not find point, restore '/' */ - *(wk2-1) = slash; - break; - } - } - else - break; - } - } - *wk2 = '\0'; - break; - default: - FIXME("how did we get here - state=%d\n", state); - HeapFree(GetProcessHeap(), 0, lpszUrlCpy); - HeapFree(GetProcessHeap(), 0, url); - return E_INVALIDARG; - } - *wk2 = '\0'; - TRACE("Simplified, orig <%s>, simple <%s>\n", - debugstr_w(pszUrl), debugstr_w(lpszUrlCpy)); - } - nLen = lstrlenW(lpszUrlCpy); - while ((nLen > 0) && ((lpszUrlCpy[nLen-1] <= ' '))) - lpszUrlCpy[--nLen]=0; - - if((dwFlags & URL_UNESCAPE) || - ((dwFlags & URL_FILE_USE_PATHURL) && nByteLen >= sizeof(wszFile) - && !memcmp(wszFile, url, sizeof(wszFile)))) - UrlUnescapeW(lpszUrlCpy, NULL, &nLen, URL_UNESCAPE_INPLACE); - - if((EscapeFlags = dwFlags & (URL_ESCAPE_UNSAFE | - URL_ESCAPE_SPACES_ONLY | - URL_ESCAPE_PERCENT | - URL_DONT_ESCAPE_EXTRA_INFO | - URL_ESCAPE_SEGMENT_ONLY ))) { - EscapeFlags &= ~URL_ESCAPE_UNSAFE; - hr = UrlEscapeW(lpszUrlCpy, pszCanonicalized, pcchCanonicalized, - EscapeFlags); - } else { /* No escaping needed, just copy the string */ - nLen = lstrlenW(lpszUrlCpy); - if(nLen < *pcchCanonicalized) - memcpy(pszCanonicalized, lpszUrlCpy, (nLen + 1)*sizeof(WCHAR)); - else { - hr = E_POINTER; - nLen++; - } - *pcchCanonicalized = nLen; - } - - HeapFree(GetProcessHeap(), 0, lpszUrlCpy); - HeapFree(GetProcessHeap(), 0, url); - - if (hr == S_OK) - TRACE("result %s\n", debugstr_w(pszCanonicalized)); - - return hr; -} - -/************************************************************************* - * UrlCombineA [SHLWAPI.@] - * - * Combine two Urls. - * - * PARAMS - * pszBase [I] Base Url - * pszRelative [I] Url to combine with pszBase - * pszCombined [O] Destination for combined Url - * pcchCombined [O] Destination for length of pszCombined - * dwFlags [I] URL_ flags from "shlwapi.h" - * - * RETURNS - * Success: S_OK. pszCombined contains the combined Url, pcchCombined - * contains its length. - * Failure: An HRESULT error code indicating the error. - */ -HRESULT WINAPI UrlCombineA(LPCSTR pszBase, LPCSTR pszRelative, - LPSTR pszCombined, LPDWORD pcchCombined, - DWORD dwFlags) -{ - LPWSTR base, relative, combined; - DWORD ret, len, len2; - - TRACE("(base %s, Relative %s, Combine size %d, flags %08x) using W version\n", - debugstr_a(pszBase),debugstr_a(pszRelative), - pcchCombined?*pcchCombined:0,dwFlags); - - if(!pszBase || !pszRelative || !pcchCombined) - return E_INVALIDARG; - - base = HeapAlloc(GetProcessHeap(), 0, - (3*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR)); - relative = base + INTERNET_MAX_URL_LENGTH; - combined = relative + INTERNET_MAX_URL_LENGTH; - - MultiByteToWideChar(CP_ACP, 0, pszBase, -1, base, INTERNET_MAX_URL_LENGTH); - MultiByteToWideChar(CP_ACP, 0, pszRelative, -1, relative, INTERNET_MAX_URL_LENGTH); - len = *pcchCombined; - - ret = UrlCombineW(base, relative, pszCombined?combined:NULL, &len, dwFlags); - if (ret != S_OK) { - *pcchCombined = len; - HeapFree(GetProcessHeap(), 0, base); - return ret; - } - - len2 = WideCharToMultiByte(CP_ACP, 0, combined, len, NULL, 0, NULL, NULL); - if (len2 > *pcchCombined) { - *pcchCombined = len2; - HeapFree(GetProcessHeap(), 0, base); - return E_POINTER; - } - WideCharToMultiByte(CP_ACP, 0, combined, len+1, pszCombined, (*pcchCombined)+1, - NULL, NULL); - *pcchCombined = len2; - HeapFree(GetProcessHeap(), 0, base); - return S_OK; -} - -/************************************************************************* - * UrlCombineW [SHLWAPI.@] - * - * See UrlCombineA. - */ -HRESULT WINAPI UrlCombineW(LPCWSTR pszBase, LPCWSTR pszRelative, - LPWSTR pszCombined, LPDWORD pcchCombined, - DWORD dwFlags) -{ - PARSEDURLW base, relative; - DWORD myflags, sizeloc = 0; - DWORD i, len, res1, res2, process_case = 0; - LPWSTR work, preliminary, mbase, mrelative; - static const WCHAR myfilestr[] = {'f','i','l','e',':','/','/','/','\0'}; - static const WCHAR fragquerystr[] = {'#','?',0}; - HRESULT ret; - - TRACE("(base %s, Relative %s, Combine size %d, flags %08x)\n", - debugstr_w(pszBase),debugstr_w(pszRelative), - pcchCombined?*pcchCombined:0,dwFlags); - - if(!pszBase || !pszRelative || !pcchCombined) - return E_INVALIDARG; - - base.cbSize = sizeof(base); - relative.cbSize = sizeof(relative); - - /* Get space for duplicates of the input and the output */ - preliminary = HeapAlloc(GetProcessHeap(), 0, (3*INTERNET_MAX_URL_LENGTH) * - sizeof(WCHAR)); - mbase = preliminary + INTERNET_MAX_URL_LENGTH; - mrelative = mbase + INTERNET_MAX_URL_LENGTH; - *preliminary = '\0'; - - /* Canonicalize the base input prior to looking for the scheme */ - myflags = dwFlags & (URL_DONT_SIMPLIFY | URL_UNESCAPE); - len = INTERNET_MAX_URL_LENGTH; - UrlCanonicalizeW(pszBase, mbase, &len, myflags); - - /* Canonicalize the relative input prior to looking for the scheme */ - len = INTERNET_MAX_URL_LENGTH; - UrlCanonicalizeW(pszRelative, mrelative, &len, myflags); - - /* See if the base has a scheme */ - res1 = ParseURLW(mbase, &base); - if (res1) { - /* if pszBase has no scheme, then return pszRelative */ - TRACE("no scheme detected in Base\n"); - process_case = 1; - } - else do { - BOOL manual_search = FALSE; - - work = (LPWSTR)base.pszProtocol; - for(i=0; i len_htmW) { - work -= len_htmW; - if (strncmpiW(work, htmW, len_htmW) == 0) - manual_search = TRUE; - work += len_htmW; - } - - if (!manual_search && - work - base.pszSuffix > len_htmlW) { - work -= len_htmlW; - if (strncmpiW(work, htmlW, len_htmlW) == 0) - manual_search = TRUE; - work += len_htmlW; - } - } - - if (manual_search) { - /* search backwards starting from the current position */ - while (*work != '/' && work > base.pszSuffix + sizeloc) - --work; - base.cchSuffix = work - base.pszSuffix + 1; - }else { - /* search backwards starting from the end of the string */ - work = strrchrW((base.pszSuffix+sizeloc), '/'); - if (work) { - len = (DWORD)(work - base.pszSuffix + 1); - base.cchSuffix = len; - }else - base.cchSuffix = sizeloc; - } - - /* - * At this point: - * .pszSuffix points to location (starting with '//') - * .cchSuffix length of location (above) and rest less the last - * leaf (if any) - * sizeloc length of location (above) up to but not including - * the last '/' - */ - - res2 = ParseURLW(mrelative, &relative); - if (res2) { - /* no scheme in pszRelative */ - TRACE("no scheme detected in Relative\n"); - relative.pszSuffix = mrelative; /* case 3,4,5 depends on this */ - relative.cchSuffix = strlenW(mrelative); - if (*pszRelative == ':') { - /* case that is either left alone or uses pszBase */ - if (dwFlags & URL_PLUGGABLE_PROTOCOL) { - process_case = 5; - break; - } - process_case = 1; - break; - } - if (isalnumW(*mrelative) && (*(mrelative + 1) == ':')) { - /* case that becomes "file:///" */ - strcpyW(preliminary, myfilestr); - process_case = 1; - break; - } - if ((*mrelative == '/') && (*(mrelative+1) == '/')) { - /* pszRelative has location and rest */ - process_case = 3; - break; - } - if (*mrelative == '/') { - /* case where pszRelative is root to location */ - process_case = 4; - break; - } - if (*mrelative == '#') { - if(!(work = strchrW(base.pszSuffix+base.cchSuffix, '#'))) - work = (LPWSTR)base.pszSuffix + strlenW(base.pszSuffix); - - memcpy(preliminary, base.pszProtocol, (work-base.pszProtocol)*sizeof(WCHAR)); - preliminary[work-base.pszProtocol] = '\0'; - process_case = 1; - break; - } - process_case = (*base.pszSuffix == '/' || base.nScheme == URL_SCHEME_MK) ? 5 : 3; - break; - }else { - work = (LPWSTR)relative.pszProtocol; - for(i=0; i lenA) { - RtlUnicodeToMultiByteN(pszEscaped, *pcchEscaped - 1, &lenA, escapedW, lenW * sizeof(WCHAR)); - pszEscaped[lenA] = 0; - *pcchEscaped = lenA; - } else { - *pcchEscaped = lenA + 1; - ret = E_POINTER; - } - } - if(escapedW != bufW) HeapFree(GetProcessHeap(), 0, escapedW); - RtlFreeUnicodeString(&urlW); - return ret; -} - -#define WINE_URL_BASH_AS_SLASH 0x01 -#define WINE_URL_COLLAPSE_SLASHES 0x02 -#define WINE_URL_ESCAPE_SLASH 0x04 -#define WINE_URL_ESCAPE_HASH 0x08 -#define WINE_URL_ESCAPE_QUESTION 0x10 -#define WINE_URL_STOP_ON_HASH 0x20 -#define WINE_URL_STOP_ON_QUESTION 0x40 - -static inline BOOL URL_NeedEscapeW(WCHAR ch, DWORD flags, DWORD int_flags) -{ - if (flags & URL_ESCAPE_SPACES_ONLY) - return ch == ' '; - - if ((flags & URL_ESCAPE_PERCENT) && (ch == '%')) - return TRUE; - - if ((flags & URL_ESCAPE_AS_UTF8) && (ch >= 0x80)) - return TRUE; - - if (ch <= 31 || (ch >= 127 && ch <= 255) ) - return TRUE; - - if (isalnumW(ch)) - return FALSE; - - switch (ch) { - case ' ': - case '<': - case '>': - case '\"': - case '{': - case '}': - case '|': - case '\\': - case '^': - case ']': - case '[': - case '`': - case '&': - return TRUE; - case '/': - return !!(int_flags & WINE_URL_ESCAPE_SLASH); - case '?': - return !!(int_flags & WINE_URL_ESCAPE_QUESTION); - case '#': - return !!(int_flags & WINE_URL_ESCAPE_HASH); - default: - return FALSE; - } -} - - -/************************************************************************* - * UrlEscapeW [SHLWAPI.@] - * - * Converts unsafe characters in a Url into escape sequences. - * - * PARAMS - * pszUrl [I] Url to modify - * pszEscaped [O] Destination for modified Url - * pcchEscaped [I/O] Length of pszUrl, destination for length of pszEscaped - * dwFlags [I] URL_ flags from "shlwapi.h" - * - * RETURNS - * Success: S_OK. pszEscaped contains the escaped Url, pcchEscaped - * contains its length. - * Failure: E_POINTER, if pszEscaped is not large enough. In this case - * pcchEscaped is set to the required length. - * - * Converts unsafe characters into their escape sequences. - * - * NOTES - * - By default this function stops converting at the first '?' or - * '#' character. - * - If dwFlags contains URL_ESCAPE_SPACES_ONLY then only spaces are - * converted, but the conversion continues past a '?' or '#'. - * - Note that this function did not work well (or at all) in shlwapi version 4. - * - * BUGS - * Only the following flags are implemented: - *| URL_ESCAPE_SPACES_ONLY - *| URL_DONT_ESCAPE_EXTRA_INFO - *| URL_ESCAPE_SEGMENT_ONLY - *| URL_ESCAPE_PERCENT - */ -HRESULT WINAPI UrlEscapeW( - LPCWSTR pszUrl, - LPWSTR pszEscaped, - LPDWORD pcchEscaped, - DWORD dwFlags) -{ - LPCWSTR src; - DWORD needed = 0, ret; - BOOL stop_escaping = FALSE; - WCHAR next[12], *dst, *dst_ptr; - INT i, len; - PARSEDURLW parsed_url; - DWORD int_flags; - DWORD slashes = 0; - static const WCHAR localhost[] = {'l','o','c','a','l','h','o','s','t',0}; - - TRACE("(%p(%s) %p %p 0x%08x)\n", pszUrl, debugstr_w(pszUrl), - pszEscaped, pcchEscaped, dwFlags); - - if(!pszUrl || !pcchEscaped || !pszEscaped || *pcchEscaped == 0) - return E_INVALIDARG; - - if(dwFlags & ~(URL_ESCAPE_SPACES_ONLY | - URL_ESCAPE_SEGMENT_ONLY | - URL_DONT_ESCAPE_EXTRA_INFO | - URL_ESCAPE_PERCENT | - URL_ESCAPE_AS_UTF8)) - FIXME("Unimplemented flags: %08x\n", dwFlags); - - dst_ptr = dst = HeapAlloc(GetProcessHeap(), 0, *pcchEscaped*sizeof(WCHAR)); - if(!dst_ptr) - return E_OUTOFMEMORY; - - /* fix up flags */ - if (dwFlags & URL_ESCAPE_SPACES_ONLY) - /* if SPACES_ONLY specified, reset the other controls */ - dwFlags &= ~(URL_DONT_ESCAPE_EXTRA_INFO | - URL_ESCAPE_PERCENT | - URL_ESCAPE_SEGMENT_ONLY); - - else - /* if SPACES_ONLY *not* specified the assume DONT_ESCAPE_EXTRA_INFO */ - dwFlags |= URL_DONT_ESCAPE_EXTRA_INFO; - - - int_flags = 0; - if(dwFlags & URL_ESCAPE_SEGMENT_ONLY) { - int_flags = WINE_URL_ESCAPE_QUESTION | WINE_URL_ESCAPE_HASH | WINE_URL_ESCAPE_SLASH; - } else { - parsed_url.cbSize = sizeof(parsed_url); - if(ParseURLW(pszUrl, &parsed_url) != S_OK) - parsed_url.nScheme = URL_SCHEME_INVALID; - - TRACE("scheme = %d (%s)\n", parsed_url.nScheme, debugstr_wn(parsed_url.pszProtocol, parsed_url.cchProtocol)); - - if(dwFlags & URL_DONT_ESCAPE_EXTRA_INFO) - int_flags = WINE_URL_STOP_ON_HASH | WINE_URL_STOP_ON_QUESTION; - - switch(parsed_url.nScheme) { - case URL_SCHEME_FILE: - int_flags |= WINE_URL_BASH_AS_SLASH | WINE_URL_COLLAPSE_SLASHES | WINE_URL_ESCAPE_HASH; - int_flags &= ~WINE_URL_STOP_ON_HASH; - break; - - case URL_SCHEME_HTTP: - case URL_SCHEME_HTTPS: - int_flags |= WINE_URL_BASH_AS_SLASH; - if(parsed_url.pszSuffix[0] != '/' && parsed_url.pszSuffix[0] != '\\') - int_flags |= WINE_URL_ESCAPE_SLASH; - break; - - case URL_SCHEME_MAILTO: - int_flags |= WINE_URL_ESCAPE_SLASH | WINE_URL_ESCAPE_QUESTION | WINE_URL_ESCAPE_HASH; - int_flags &= ~(WINE_URL_STOP_ON_QUESTION | WINE_URL_STOP_ON_HASH); - break; - - case URL_SCHEME_INVALID: - break; - - case URL_SCHEME_FTP: - default: - if(parsed_url.pszSuffix[0] != '/') - int_flags |= WINE_URL_ESCAPE_SLASH; - break; - } - } - - for(src = pszUrl; *src; ) { - WCHAR cur = *src; - len = 0; - - if((int_flags & WINE_URL_COLLAPSE_SLASHES) && src == pszUrl + parsed_url.cchProtocol + 1) { - int localhost_len = sizeof(localhost)/sizeof(WCHAR) - 1; - while(cur == '/' || cur == '\\') { - slashes++; - cur = *++src; - } - if(slashes == 2 && !strncmpiW(src, localhost, localhost_len)) { /* file://localhost/ -> file:/// */ - if(*(src + localhost_len) == '/' || *(src + localhost_len) == '\\') - src += localhost_len + 1; - slashes = 3; - } - - switch(slashes) { - case 1: - case 3: - next[0] = next[1] = next[2] = '/'; - len = 3; - break; - case 0: - len = 0; - break; - default: - next[0] = next[1] = '/'; - len = 2; - break; - } - } - if(len == 0) { - - if(cur == '#' && (int_flags & WINE_URL_STOP_ON_HASH)) - stop_escaping = TRUE; - - if(cur == '?' && (int_flags & WINE_URL_STOP_ON_QUESTION)) - stop_escaping = TRUE; - - if(cur == '\\' && (int_flags & WINE_URL_BASH_AS_SLASH) && !stop_escaping) cur = '/'; - - if(URL_NeedEscapeW(cur, dwFlags, int_flags) && stop_escaping == FALSE) { - if(dwFlags & URL_ESCAPE_AS_UTF8) { - char utf[16]; - - if ((cur >= 0xd800 && cur <= 0xdfff) && - (src[1] >= 0xdc00 && src[1] <= 0xdfff)) - { -#ifdef __REACTOS__ - len = WideCharToMultiByte( CP_UTF8, 0, src, 2, - utf, sizeof(utf), NULL, NULL ); -#else - len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, src, 2, - utf, sizeof(utf), NULL, NULL ); -#endif - src++; - } - else -#ifdef __REACTOS__ - len = WideCharToMultiByte( CP_UTF8, 0, &cur, 1, - utf, sizeof(utf), NULL, NULL ); -#else - len = WideCharToMultiByte( CP_UTF8, WC_ERR_INVALID_CHARS, &cur, 1, - utf, sizeof(utf), NULL, NULL ); -#endif - - if (!len) { - utf[0] = 0xef; - utf[1] = 0xbf; - utf[2] = 0xbd; - len = 3; - } - - for(i = 0; i < len; i++) { - next[i*3+0] = '%'; - next[i*3+1] = hexDigits[(utf[i] >> 4) & 0xf]; - next[i*3+2] = hexDigits[utf[i] & 0xf]; - } - len *= 3; - } else { - next[0] = '%'; - next[1] = hexDigits[(cur >> 4) & 0xf]; - next[2] = hexDigits[cur & 0xf]; - len = 3; - } - } else { - next[0] = cur; - len = 1; - } - src++; - } - - if(needed + len <= *pcchEscaped) { - memcpy(dst, next, len*sizeof(WCHAR)); - dst += len; - } - needed += len; - } - - if(needed < *pcchEscaped) { - *dst = '\0'; - memcpy(pszEscaped, dst_ptr, (needed+1)*sizeof(WCHAR)); - - ret = S_OK; - } else { - needed++; /* add one for the '\0' */ - ret = E_POINTER; - } - *pcchEscaped = needed; - - HeapFree(GetProcessHeap(), 0, dst_ptr); - return ret; -} - - -/************************************************************************* - * UrlUnescapeA [SHLWAPI.@] - * - * Converts Url escape sequences back to ordinary characters. - * - * PARAMS - * pszUrl [I/O] Url to convert - * pszUnescaped [O] Destination for converted Url - * pcchUnescaped [I/O] Size of output string - * dwFlags [I] URL_ESCAPE_ Flags from "shlwapi.h" - * - * RETURNS - * Success: S_OK. The converted value is in pszUnescaped, or in pszUrl if - * dwFlags includes URL_ESCAPE_INPLACE. - * Failure: E_POINTER if the converted Url is bigger than pcchUnescaped. In - * this case pcchUnescaped is set to the size required. - * NOTES - * If dwFlags includes URL_DONT_ESCAPE_EXTRA_INFO, the conversion stops at - * the first occurrence of either a '?' or '#' character. - */ -HRESULT WINAPI UrlUnescapeA( - LPSTR pszUrl, - LPSTR pszUnescaped, - LPDWORD pcchUnescaped, - DWORD dwFlags) -{ - char *dst, next; - LPCSTR src; - HRESULT ret; - DWORD needed; - BOOL stop_unescaping = FALSE; - - TRACE("(%s, %p, %p, 0x%08x)\n", debugstr_a(pszUrl), pszUnescaped, - pcchUnescaped, dwFlags); - - if (!pszUrl) return E_INVALIDARG; - - if(dwFlags & URL_UNESCAPE_INPLACE) - dst = pszUrl; - else - { - if (!pszUnescaped || !pcchUnescaped) return E_INVALIDARG; - dst = pszUnescaped; - } - - for(src = pszUrl, needed = 0; *src; src++, needed++) { - if(dwFlags & URL_DONT_UNESCAPE_EXTRA_INFO && - (*src == '#' || *src == '?')) { - stop_unescaping = TRUE; - next = *src; - } else if(*src == '%' && isxdigit(*(src + 1)) && isxdigit(*(src + 2)) - && stop_unescaping == FALSE) { - INT ih; - char buf[3]; - memcpy(buf, src + 1, 2); - buf[2] = '\0'; - ih = strtol(buf, NULL, 16); - next = (CHAR) ih; - src += 2; /* Advance to end of escape */ - } else - next = *src; - - if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped) - *dst++ = next; - } - - if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped) { - *dst = '\0'; - ret = S_OK; - } else { - needed++; /* add one for the '\0' */ - ret = E_POINTER; - } - if(!(dwFlags & URL_UNESCAPE_INPLACE)) - *pcchUnescaped = needed; - - if (ret == S_OK) { - TRACE("result %s\n", (dwFlags & URL_UNESCAPE_INPLACE) ? - debugstr_a(pszUrl) : debugstr_a(pszUnescaped)); - } - - return ret; -} - -/************************************************************************* - * UrlUnescapeW [SHLWAPI.@] - * - * See UrlUnescapeA. - */ -HRESULT WINAPI UrlUnescapeW( - LPWSTR pszUrl, - LPWSTR pszUnescaped, - LPDWORD pcchUnescaped, - DWORD dwFlags) -{ - WCHAR *dst, next; - LPCWSTR src; - HRESULT ret; - DWORD needed; - BOOL stop_unescaping = FALSE; - - TRACE("(%s, %p, %p, 0x%08x)\n", debugstr_w(pszUrl), pszUnescaped, - pcchUnescaped, dwFlags); - - if(!pszUrl) return E_INVALIDARG; - - if(dwFlags & URL_UNESCAPE_INPLACE) - dst = pszUrl; - else - { - if (!pszUnescaped || !pcchUnescaped) return E_INVALIDARG; - dst = pszUnescaped; - } - - for(src = pszUrl, needed = 0; *src; src++, needed++) { - if(dwFlags & URL_DONT_UNESCAPE_EXTRA_INFO && - (*src == '#' || *src == '?')) { - stop_unescaping = TRUE; - next = *src; - } else if(*src == '%' && isxdigitW(*(src + 1)) && isxdigitW(*(src + 2)) - && stop_unescaping == FALSE) { - INT ih; - WCHAR buf[5] = {'0','x',0}; - memcpy(buf + 2, src + 1, 2*sizeof(WCHAR)); - buf[4] = 0; - StrToIntExW(buf, STIF_SUPPORT_HEX, &ih); - next = (WCHAR) ih; - src += 2; /* Advance to end of escape */ - } else - next = *src; - - if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped) - *dst++ = next; - } - - if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped) { - *dst = '\0'; - ret = S_OK; - } else { - needed++; /* add one for the '\0' */ - ret = E_POINTER; - } - if(!(dwFlags & URL_UNESCAPE_INPLACE)) - *pcchUnescaped = needed; - - if (ret == S_OK) { - TRACE("result %s\n", (dwFlags & URL_UNESCAPE_INPLACE) ? - debugstr_w(pszUrl) : debugstr_w(pszUnescaped)); - } - - return ret; -} - -/************************************************************************* - * UrlGetLocationA [SHLWAPI.@] - * - * Get the location from a Url. - * - * PARAMS - * pszUrl [I] Url to get the location from - * - * RETURNS - * A pointer to the start of the location in pszUrl, or NULL if there is - * no location. - * - * NOTES - * - MSDN erroneously states that "The location is the segment of the Url - * starting with a '?' or '#' character". Neither V4 nor V5 of shlwapi.dll - * stop at '?' and always return a NULL in this case. - * - MSDN also erroneously states that "If a file URL has a query string, - * the returned string is the query string". In all tested cases, if the - * Url starts with "fi" then a NULL is returned. V5 gives the following results: - *| Result Url - *| ------ --- - *| NULL file://aa/b/cd#hohoh - *| #hohoh http://aa/b/cd#hohoh - *| NULL fi://aa/b/cd#hohoh - *| #hohoh ff://aa/b/cd#hohoh - */ -LPCSTR WINAPI UrlGetLocationA( - LPCSTR pszUrl) -{ - PARSEDURLA base; - DWORD res1; - - base.cbSize = sizeof(base); - res1 = ParseURLA(pszUrl, &base); - if (res1) return NULL; /* invalid scheme */ - - /* if scheme is file: then never return pointer */ - if (strncmp(base.pszProtocol, "file", min(4,base.cchProtocol)) == 0) return NULL; - - /* Look for '#' and return its addr */ - return strchr(base.pszSuffix, '#'); -} - -/************************************************************************* - * UrlGetLocationW [SHLWAPI.@] - * - * See UrlGetLocationA. - */ -LPCWSTR WINAPI UrlGetLocationW( - LPCWSTR pszUrl) -{ - PARSEDURLW base; - DWORD res1; - - base.cbSize = sizeof(base); - res1 = ParseURLW(pszUrl, &base); - if (res1) return NULL; /* invalid scheme */ - - /* if scheme is file: then never return pointer */ - if (strncmpW(base.pszProtocol, fileW, min(4,base.cchProtocol)) == 0) return NULL; - - /* Look for '#' and return its addr */ - return strchrW(base.pszSuffix, '#'); -} - -/************************************************************************* - * UrlCompareA [SHLWAPI.@] - * - * Compare two Urls. - * - * PARAMS - * pszUrl1 [I] First Url to compare - * pszUrl2 [I] Url to compare to pszUrl1 - * fIgnoreSlash [I] TRUE = compare only up to a final slash - * - * RETURNS - * less than zero, zero, or greater than zero indicating pszUrl2 is greater - * than, equal to, or less than pszUrl1 respectively. - */ -INT WINAPI UrlCompareA( - LPCSTR pszUrl1, - LPCSTR pszUrl2, - BOOL fIgnoreSlash) -{ - INT ret, len, len1, len2; - - if (!fIgnoreSlash) - return strcmp(pszUrl1, pszUrl2); - len1 = strlen(pszUrl1); - if (pszUrl1[len1-1] == '/') len1--; - len2 = strlen(pszUrl2); - if (pszUrl2[len2-1] == '/') len2--; - if (len1 == len2) - return strncmp(pszUrl1, pszUrl2, len1); - len = min(len1, len2); - ret = strncmp(pszUrl1, pszUrl2, len); - if (ret) return ret; - if (len1 > len2) return 1; - return -1; -} - -/************************************************************************* - * UrlCompareW [SHLWAPI.@] - * - * See UrlCompareA. - */ -INT WINAPI UrlCompareW( - LPCWSTR pszUrl1, - LPCWSTR pszUrl2, - BOOL fIgnoreSlash) -{ - INT ret; - size_t len, len1, len2; - - if (!fIgnoreSlash) - return strcmpW(pszUrl1, pszUrl2); - len1 = strlenW(pszUrl1); - if (pszUrl1[len1-1] == '/') len1--; - len2 = strlenW(pszUrl2); - if (pszUrl2[len2-1] == '/') len2--; - if (len1 == len2) - return strncmpW(pszUrl1, pszUrl2, len1); - len = min(len1, len2); - ret = strncmpW(pszUrl1, pszUrl2, len); - if (ret) return ret; - if (len1 > len2) return 1; - return -1; -} - -/************************************************************************* - * HashData [SHLWAPI.@] - * - * Hash an input block into a variable sized digest. - * - * PARAMS - * lpSrc [I] Input block - * nSrcLen [I] Length of lpSrc - * lpDest [I] Output for hash digest - * nDestLen [I] Length of lpDest - * - * RETURNS - * Success: TRUE. lpDest is filled with the computed hash value. - * Failure: FALSE, if any argument is invalid. - */ -HRESULT WINAPI HashData(const unsigned char *lpSrc, DWORD nSrcLen, - unsigned char *lpDest, DWORD nDestLen) -{ - INT srcCount = nSrcLen - 1, destCount = nDestLen - 1; - - if (!lpSrc || !lpDest) - return E_INVALIDARG; - - while (destCount >= 0) - { - lpDest[destCount] = (destCount & 0xff); - destCount--; - } - - while (srcCount >= 0) - { - destCount = nDestLen - 1; - while (destCount >= 0) - { - lpDest[destCount] = HashDataLookup[lpSrc[srcCount] ^ lpDest[destCount]]; - destCount--; - } - srcCount--; - } - return S_OK; -} - -/************************************************************************* - * UrlHashA [SHLWAPI.@] - * - * Produce a Hash from a Url. - * - * PARAMS - * pszUrl [I] Url to hash - * lpDest [O] Destinationh for hash - * nDestLen [I] Length of lpDest - * - * RETURNS - * Success: S_OK. lpDest is filled with the computed hash value. - * Failure: E_INVALIDARG, if any argument is invalid. - */ -HRESULT WINAPI UrlHashA(LPCSTR pszUrl, unsigned char *lpDest, DWORD nDestLen) -{ - if (IsBadStringPtrA(pszUrl, -1) || IsBadWritePtr(lpDest, nDestLen)) - return E_INVALIDARG; - - HashData((const BYTE*)pszUrl, (int)strlen(pszUrl), lpDest, nDestLen); - return S_OK; -} - -/************************************************************************* - * UrlHashW [SHLWAPI.@] - * - * See UrlHashA. - */ -HRESULT WINAPI UrlHashW(LPCWSTR pszUrl, unsigned char *lpDest, DWORD nDestLen) -{ - char szUrl[MAX_PATH]; - - TRACE("(%s,%p,%d)\n",debugstr_w(pszUrl), lpDest, nDestLen); - - if (IsBadStringPtrW(pszUrl, -1) || IsBadWritePtr(lpDest, nDestLen)) - return E_INVALIDARG; - - /* Win32 hashes the data as an ASCII string, presumably so that both A+W - * return the same digests for the same URL. - */ - WideCharToMultiByte(CP_ACP, 0, pszUrl, -1, szUrl, MAX_PATH, NULL, NULL); - HashData((const BYTE*)szUrl, (int)strlen(szUrl), lpDest, nDestLen); - return S_OK; -} - -/************************************************************************* - * UrlApplySchemeA [SHLWAPI.@] - * - * Apply a scheme to a Url. - * - * PARAMS - * pszIn [I] Url to apply scheme to - * pszOut [O] Destination for modified Url - * pcchOut [I/O] Length of pszOut/destination for length of pszOut - * dwFlags [I] URL_ flags from "shlwapi.h" - * - * RETURNS - * Success: S_OK: pszOut contains the modified Url, pcchOut contains its length. - * Failure: An HRESULT error code describing the error. - */ -HRESULT WINAPI UrlApplySchemeA(LPCSTR pszIn, LPSTR pszOut, LPDWORD pcchOut, DWORD dwFlags) -{ - LPWSTR in, out; - HRESULT ret; - DWORD len; - - TRACE("(%s, %p, %p:out size %d, 0x%08x)\n", debugstr_a(pszIn), - pszOut, pcchOut, pcchOut ? *pcchOut : 0, dwFlags); - - if (!pszIn || !pszOut || !pcchOut) return E_INVALIDARG; - - in = HeapAlloc(GetProcessHeap(), 0, - (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR)); - out = in + INTERNET_MAX_URL_LENGTH; - - MultiByteToWideChar(CP_ACP, 0, pszIn, -1, in, INTERNET_MAX_URL_LENGTH); - len = INTERNET_MAX_URL_LENGTH; - - ret = UrlApplySchemeW(in, out, &len, dwFlags); - if (ret != S_OK) { - HeapFree(GetProcessHeap(), 0, in); - return ret; - } - - len = WideCharToMultiByte(CP_ACP, 0, out, -1, NULL, 0, NULL, NULL); - if (len > *pcchOut) { - ret = E_POINTER; - goto cleanup; - } - - WideCharToMultiByte(CP_ACP, 0, out, -1, pszOut, *pcchOut, NULL, NULL); - len--; - -cleanup: - *pcchOut = len; - HeapFree(GetProcessHeap(), 0, in); - return ret; -} - -static HRESULT URL_GuessScheme(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut) -{ - HKEY newkey; - BOOL j; - INT index; - DWORD value_len, data_len, dwType, i; - WCHAR reg_path[MAX_PATH]; - WCHAR value[MAX_PATH], data[MAX_PATH]; - WCHAR Wxx, Wyy; - - MultiByteToWideChar(CP_ACP, 0, - "Software\\Microsoft\\Windows\\CurrentVersion\\URL\\Prefixes", - -1, reg_path, MAX_PATH); - RegOpenKeyExW(HKEY_LOCAL_MACHINE, reg_path, 0, 1, &newkey); - index = 0; - while(value_len = data_len = MAX_PATH, - RegEnumValueW(newkey, index, value, &value_len, - 0, &dwType, (LPVOID)data, &data_len) == 0) { - TRACE("guess %d %s is %s\n", - index, debugstr_w(value), debugstr_w(data)); - - j = FALSE; - for(i=0; i *pcchOut) { - *pcchOut = strlenW(data) + strlenW(pszIn) + 1; - RegCloseKey(newkey); - return E_POINTER; - } - strcpyW(pszOut, data); - strcatW(pszOut, pszIn); - *pcchOut = strlenW(pszOut); - TRACE("matched and set to %s\n", debugstr_w(pszOut)); - RegCloseKey(newkey); - return S_OK; - } - index++; - } - RegCloseKey(newkey); - return E_FAIL; -} - -static HRESULT URL_CreateFromPath(LPCWSTR pszPath, LPWSTR pszUrl, LPDWORD pcchUrl) -{ - DWORD needed; - HRESULT ret = S_OK; - WCHAR *pszNewUrl; - WCHAR file_colonW[] = {'f','i','l','e',':',0}; - WCHAR three_slashesW[] = {'/','/','/',0}; - PARSEDURLW parsed_url; - - parsed_url.cbSize = sizeof(parsed_url); - if(ParseURLW(pszPath, &parsed_url) == S_OK) { - if(parsed_url.nScheme != URL_SCHEME_INVALID && parsed_url.cchProtocol > 1) { - needed = strlenW(pszPath); - if (needed >= *pcchUrl) { - *pcchUrl = needed + 1; - return E_POINTER; - } else { - *pcchUrl = needed; - return S_FALSE; - } - } - } - - pszNewUrl = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath) + 9) * sizeof(WCHAR)); /* "file:///" + pszPath_len + 1 */ - strcpyW(pszNewUrl, file_colonW); - if(isalphaW(pszPath[0]) && pszPath[1] == ':') - strcatW(pszNewUrl, three_slashesW); - strcatW(pszNewUrl, pszPath); - ret = UrlEscapeW(pszNewUrl, pszUrl, pcchUrl, URL_ESCAPE_PERCENT); - HeapFree(GetProcessHeap(), 0, pszNewUrl); - return ret; -} - -static HRESULT URL_ApplyDefault(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut) -{ - HKEY newkey; - DWORD data_len, dwType; - WCHAR data[MAX_PATH]; - - static const WCHAR prefix_keyW[] = - {'S','o','f','t','w','a','r','e', - '\\','M','i','c','r','o','s','o','f','t', - '\\','W','i','n','d','o','w','s', - '\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n', - '\\','U','R','L', - '\\','D','e','f','a','u','l','t','P','r','e','f','i','x',0}; - - /* get and prepend default */ - RegOpenKeyExW(HKEY_LOCAL_MACHINE, prefix_keyW, 0, 1, &newkey); - data_len = sizeof(data); - RegQueryValueExW(newkey, NULL, 0, &dwType, (LPBYTE)data, &data_len); - RegCloseKey(newkey); - if (strlenW(data) + strlenW(pszIn) + 1 > *pcchOut) { - *pcchOut = strlenW(data) + strlenW(pszIn) + 1; - return E_POINTER; - } - strcpyW(pszOut, data); - strcatW(pszOut, pszIn); - *pcchOut = strlenW(pszOut); - TRACE("used default %s\n", debugstr_w(pszOut)); - return S_OK; -} - -/************************************************************************* - * UrlApplySchemeW [SHLWAPI.@] - * - * See UrlApplySchemeA. - */ -HRESULT WINAPI UrlApplySchemeW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut, DWORD dwFlags) -{ - PARSEDURLW in_scheme; - DWORD res1; - HRESULT ret; - - TRACE("(%s, %p, %p:out size %d, 0x%08x)\n", debugstr_w(pszIn), - pszOut, pcchOut, pcchOut ? *pcchOut : 0, dwFlags); - - if (!pszIn || !pszOut || !pcchOut) return E_INVALIDARG; - - if (dwFlags & URL_APPLY_GUESSFILE) { - if (*pcchOut > 1 && ':' == pszIn[1]) { - res1 = *pcchOut; - ret = URL_CreateFromPath(pszIn, pszOut, &res1); - if (ret == S_OK || ret == E_POINTER){ - *pcchOut = res1; - return ret; - } - else if (ret == S_FALSE) - { - return ret; - } - } - } - - in_scheme.cbSize = sizeof(in_scheme); - /* See if the base has a scheme */ - res1 = ParseURLW(pszIn, &in_scheme); - if (res1) { - /* no scheme in input, need to see if we need to guess */ - if (dwFlags & URL_APPLY_GUESSSCHEME) { - if ((ret = URL_GuessScheme(pszIn, pszOut, pcchOut)) != E_FAIL) - return ret; - } - } - - /* If we are here, then either invalid scheme, - * or no scheme and can't/failed guess. - */ - if ( ( ((res1 == 0) && (dwFlags & URL_APPLY_FORCEAPPLY)) || - ((res1 != 0)) ) && - (dwFlags & URL_APPLY_DEFAULT)) { - /* find and apply default scheme */ - return URL_ApplyDefault(pszIn, pszOut, pcchOut); - } - - return S_FALSE; -} - -/************************************************************************* - * UrlIsA [SHLWAPI.@] - * - * Determine if a Url is of a certain class. - * - * PARAMS - * pszUrl [I] Url to check - * Urlis [I] URLIS_ constant from "shlwapi.h" - * - * RETURNS - * TRUE if pszUrl belongs to the class type in Urlis. - * FALSE Otherwise. - */ -BOOL WINAPI UrlIsA(LPCSTR pszUrl, URLIS Urlis) -{ - PARSEDURLA base; - DWORD res1; - LPCSTR last; - - TRACE("(%s %d)\n", debugstr_a(pszUrl), Urlis); - - if(!pszUrl) - return FALSE; - - switch (Urlis) { - - case URLIS_OPAQUE: - base.cbSize = sizeof(base); - res1 = ParseURLA(pszUrl, &base); - if (res1) return FALSE; /* invalid scheme */ - switch (base.nScheme) - { - case URL_SCHEME_MAILTO: - case URL_SCHEME_SHELL: - case URL_SCHEME_JAVASCRIPT: - case URL_SCHEME_VBSCRIPT: - case URL_SCHEME_ABOUT: - return TRUE; - } - return FALSE; - - case URLIS_FILEURL: - return (CompareStringA(LOCALE_INVARIANT, NORM_IGNORECASE, pszUrl, 5, - "file:", 5) == CSTR_EQUAL); - - case URLIS_DIRECTORY: - last = pszUrl + strlen(pszUrl) - 1; - return (last >= pszUrl && (*last == '/' || *last == '\\' )); - - case URLIS_URL: - return PathIsURLA(pszUrl); - - case URLIS_NOHISTORY: - case URLIS_APPLIABLE: - case URLIS_HASQUERY: - default: - FIXME("(%s %d): stub\n", debugstr_a(pszUrl), Urlis); - } - return FALSE; -} - -/************************************************************************* - * UrlIsW [SHLWAPI.@] - * - * See UrlIsA. - */ -BOOL WINAPI UrlIsW(LPCWSTR pszUrl, URLIS Urlis) -{ - static const WCHAR file_colon[] = { 'f','i','l','e',':',0 }; - PARSEDURLW base; - DWORD res1; - LPCWSTR last; - - TRACE("(%s %d)\n", debugstr_w(pszUrl), Urlis); - - if(!pszUrl) - return FALSE; - - switch (Urlis) { - - case URLIS_OPAQUE: - base.cbSize = sizeof(base); - res1 = ParseURLW(pszUrl, &base); - if (res1) return FALSE; /* invalid scheme */ - switch (base.nScheme) - { - case URL_SCHEME_MAILTO: - case URL_SCHEME_SHELL: - case URL_SCHEME_JAVASCRIPT: - case URL_SCHEME_VBSCRIPT: - case URL_SCHEME_ABOUT: - return TRUE; - } - return FALSE; - - case URLIS_FILEURL: - return (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE, pszUrl, 5, - file_colon, 5) == CSTR_EQUAL); - - case URLIS_DIRECTORY: - last = pszUrl + strlenW(pszUrl) - 1; - return (last >= pszUrl && (*last == '/' || *last == '\\')); - - case URLIS_URL: - return PathIsURLW(pszUrl); - - case URLIS_NOHISTORY: - case URLIS_APPLIABLE: - case URLIS_HASQUERY: - default: - FIXME("(%s %d): stub\n", debugstr_w(pszUrl), Urlis); - } - return FALSE; -} - -/************************************************************************* - * UrlIsNoHistoryA [SHLWAPI.@] - * - * Determine if a Url should not be stored in the users history list. - * - * PARAMS - * pszUrl [I] Url to check - * - * RETURNS - * TRUE, if pszUrl should be excluded from the history list, - * FALSE otherwise. - */ -BOOL WINAPI UrlIsNoHistoryA(LPCSTR pszUrl) -{ - return UrlIsA(pszUrl, URLIS_NOHISTORY); -} - -/************************************************************************* - * UrlIsNoHistoryW [SHLWAPI.@] - * - * See UrlIsNoHistoryA. - */ -BOOL WINAPI UrlIsNoHistoryW(LPCWSTR pszUrl) -{ - return UrlIsW(pszUrl, URLIS_NOHISTORY); -} - -/************************************************************************* - * UrlIsOpaqueA [SHLWAPI.@] - * - * Determine if a Url is opaque. - * - * PARAMS - * pszUrl [I] Url to check - * - * RETURNS - * TRUE if pszUrl is opaque, - * FALSE Otherwise. - * - * NOTES - * An opaque Url is one that does not start with "://". - */ -BOOL WINAPI UrlIsOpaqueA(LPCSTR pszUrl) -{ - return UrlIsA(pszUrl, URLIS_OPAQUE); -} - -/************************************************************************* - * UrlIsOpaqueW [SHLWAPI.@] - * - * See UrlIsOpaqueA. - */ -BOOL WINAPI UrlIsOpaqueW(LPCWSTR pszUrl) -{ - return UrlIsW(pszUrl, URLIS_OPAQUE); -} - -/************************************************************************* - * Scans for characters of type "type" and when not matching found, - * returns pointer to it and length in size. - * - * Characters tested based on RFC 1738 - */ -static LPCWSTR URL_ScanID(LPCWSTR start, LPDWORD size, WINE_URL_SCAN_TYPE type) -{ - static DWORD alwayszero = 0; - BOOL cont = TRUE; - - *size = 0; - - switch(type){ - - case SCHEME: - while (cont) { - if ( (islowerW(*start) && isalphaW(*start)) || - isdigitW(*start) || - (*start == '+') || - (*start == '-') || - (*start == '.')) { - start++; - (*size)++; - } - else - cont = FALSE; - } - - if(*start != ':') - *size = 0; - - break; - - case USERPASS: - while (cont) { - if ( isalphaW(*start) || - isdigitW(*start) || - /* user/password only characters */ - (*start == ';') || - (*start == '?') || - (*start == '&') || - (*start == '=') || - /* *extra* characters */ - (*start == '!') || - (*start == '*') || - (*start == '\'') || - (*start == '(') || - (*start == ')') || - (*start == ',') || - /* *safe* characters */ - (*start == '$') || - (*start == '_') || - (*start == '+') || - (*start == '-') || - (*start == '.') || - (*start == ' ')) { - start++; - (*size)++; - } else if (*start == '%') { - if (isxdigitW(*(start+1)) && - isxdigitW(*(start+2))) { - start += 3; - *size += 3; - } else - cont = FALSE; - } else - cont = FALSE; - } - break; - - case PORT: - while (cont) { - if (isdigitW(*start)) { - start++; - (*size)++; - } - else - cont = FALSE; - } - break; - - case HOST: - while (cont) { - if (isalnumW(*start) || - (*start == '-') || - (*start == '.') || - (*start == ' ') || - (*start == '*') ) { - start++; - (*size)++; - } - else - cont = FALSE; - } - break; - default: - FIXME("unknown type %d\n", type); - return (LPWSTR)&alwayszero; - } - /* TRACE("scanned %d characters next char %p<%c>\n", - *size, start, *start); */ - return start; -} - -/************************************************************************* - * Attempt to parse URL into pieces. - */ -static LONG URL_ParseUrl(LPCWSTR pszUrl, WINE_PARSE_URL *pl) -{ - LPCWSTR work; - - memset(pl, 0, sizeof(WINE_PARSE_URL)); - pl->pScheme = pszUrl; - work = URL_ScanID(pl->pScheme, &pl->szScheme, SCHEME); - if (!*work || (*work != ':')) goto ErrorExit; - work++; - if ((*work != '/') || (*(work+1) != '/')) goto SuccessExit; - pl->pUserName = work + 2; - work = URL_ScanID(pl->pUserName, &pl->szUserName, USERPASS); - if (*work == ':' ) { - /* parse password */ - work++; - pl->pPassword = work; - work = URL_ScanID(pl->pPassword, &pl->szPassword, USERPASS); - if (*work != '@') { - /* what we just parsed must be the hostname and port - * so reset pointers and clear then let it parse */ - pl->szUserName = pl->szPassword = 0; - work = pl->pUserName - 1; - pl->pUserName = pl->pPassword = 0; - } - } else if (*work == '@') { - /* no password */ - pl->szPassword = 0; - pl->pPassword = 0; - } else if (!*work || (*work == '/') || (*work == '.')) { - /* what was parsed was hostname, so reset pointers and let it parse */ - pl->szUserName = pl->szPassword = 0; - work = pl->pUserName - 1; - pl->pUserName = pl->pPassword = 0; - } else goto ErrorExit; - - /* now start parsing hostname or hostnumber */ - work++; - pl->pHostName = work; - work = URL_ScanID(pl->pHostName, &pl->szHostName, HOST); - if (*work == ':') { - /* parse port */ - work++; - pl->pPort = work; - work = URL_ScanID(pl->pPort, &pl->szPort, PORT); - } - if (*work == '/') { - /* see if query string */ - pl->pQuery = strchrW(work, '?'); - if (pl->pQuery) pl->szQuery = strlenW(pl->pQuery); - } - SuccessExit: - TRACE("parse successful: scheme=%p(%d), user=%p(%d), pass=%p(%d), host=%p(%d), port=%p(%d), query=%p(%d)\n", - pl->pScheme, pl->szScheme, - pl->pUserName, pl->szUserName, - pl->pPassword, pl->szPassword, - pl->pHostName, pl->szHostName, - pl->pPort, pl->szPort, - pl->pQuery, pl->szQuery); - return S_OK; - ErrorExit: - FIXME("failed to parse %s\n", debugstr_w(pszUrl)); - return E_INVALIDARG; -} - -/************************************************************************* - * UrlGetPartA [SHLWAPI.@] - * - * Retrieve part of a Url. - * - * PARAMS - * pszIn [I] Url to parse - * pszOut [O] Destination for part of pszIn requested - * pcchOut [I] Size of pszOut - * [O] length of pszOut string EXCLUDING '\0' if S_OK, otherwise - * needed size of pszOut INCLUDING '\0'. - * dwPart [I] URL_PART_ enum from "shlwapi.h" - * dwFlags [I] URL_ flags from "shlwapi.h" - * - * RETURNS - * Success: S_OK. pszOut contains the part requested, pcchOut contains its length. - * Failure: An HRESULT error code describing the error. - */ -HRESULT WINAPI UrlGetPartA(LPCSTR pszIn, LPSTR pszOut, LPDWORD pcchOut, - DWORD dwPart, DWORD dwFlags) -{ - LPWSTR in, out; - DWORD ret, len, len2; - - if(!pszIn || !pszOut || !pcchOut || *pcchOut <= 0) - return E_INVALIDARG; - - in = HeapAlloc(GetProcessHeap(), 0, - (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR)); - out = in + INTERNET_MAX_URL_LENGTH; - - MultiByteToWideChar(CP_ACP, 0, pszIn, -1, in, INTERNET_MAX_URL_LENGTH); - - len = INTERNET_MAX_URL_LENGTH; - ret = UrlGetPartW(in, out, &len, dwPart, dwFlags); - - if (FAILED(ret)) { - HeapFree(GetProcessHeap(), 0, in); - return ret; - } - - len2 = WideCharToMultiByte(CP_ACP, 0, out, len, NULL, 0, NULL, NULL); - if (len2 > *pcchOut) { - *pcchOut = len2+1; - HeapFree(GetProcessHeap(), 0, in); - return E_POINTER; - } - len2 = WideCharToMultiByte(CP_ACP, 0, out, len+1, pszOut, *pcchOut, NULL, NULL); - *pcchOut = len2-1; - HeapFree(GetProcessHeap(), 0, in); - return ret; -} - -/************************************************************************* - * UrlGetPartW [SHLWAPI.@] - * - * See UrlGetPartA. - */ -HRESULT WINAPI UrlGetPartW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut, - DWORD dwPart, DWORD dwFlags) -{ - WINE_PARSE_URL pl; - HRESULT ret; - DWORD scheme, size, schsize; - LPCWSTR addr, schaddr; - - TRACE("(%s %p %p(%d) %08x %08x)\n", - debugstr_w(pszIn), pszOut, pcchOut, *pcchOut, dwPart, dwFlags); - - if(!pszIn || !pszOut || !pcchOut || *pcchOut <= 0) - return E_INVALIDARG; - - *pszOut = '\0'; - - addr = strchrW(pszIn, ':'); - if(!addr) - scheme = URL_SCHEME_UNKNOWN; - else - scheme = get_scheme_code(pszIn, addr-pszIn); - - ret = URL_ParseUrl(pszIn, &pl); - - switch (dwPart) { - case URL_PART_SCHEME: - if (!pl.szScheme) { - *pcchOut = 0; - return S_FALSE; - } - addr = pl.pScheme; - size = pl.szScheme; - break; - - case URL_PART_HOSTNAME: - switch(scheme) { - case URL_SCHEME_FTP: - case URL_SCHEME_HTTP: - case URL_SCHEME_GOPHER: - case URL_SCHEME_TELNET: - case URL_SCHEME_FILE: - case URL_SCHEME_HTTPS: - break; - default: - *pcchOut = 0; - return E_FAIL; - } - - if(scheme==URL_SCHEME_FILE && (!pl.szHostName || - (pl.szHostName==1 && *(pl.pHostName+1)==':'))) { - *pcchOut = 0; - return S_FALSE; - } - - if (!pl.szHostName) { - *pcchOut = 0; - return S_FALSE; - } - addr = pl.pHostName; - size = pl.szHostName; - break; - - case URL_PART_USERNAME: - if (!pl.szUserName) { - *pcchOut = 0; - return S_FALSE; - } - addr = pl.pUserName; - size = pl.szUserName; - break; - - case URL_PART_PASSWORD: - if (!pl.szPassword) { - *pcchOut = 0; - return S_FALSE; - } - addr = pl.pPassword; - size = pl.szPassword; - break; - - case URL_PART_PORT: - if (!pl.szPort) { - *pcchOut = 0; - return S_FALSE; - } - addr = pl.pPort; - size = pl.szPort; - break; - - case URL_PART_QUERY: - if (!pl.szQuery) { - *pcchOut = 0; - return S_FALSE; - } - addr = pl.pQuery; - size = pl.szQuery; - break; - - default: - *pcchOut = 0; - return E_INVALIDARG; - } - - if (dwFlags == URL_PARTFLAG_KEEPSCHEME) { - if(!pl.pScheme || !pl.szScheme) { - *pcchOut = 0; - return E_FAIL; - } - schaddr = pl.pScheme; - schsize = pl.szScheme; - if (*pcchOut < schsize + size + 2) { - *pcchOut = schsize + size + 2; - return E_POINTER; - } - memcpy(pszOut, schaddr, schsize*sizeof(WCHAR)); - pszOut[schsize] = ':'; - memcpy(pszOut+schsize+1, addr, size*sizeof(WCHAR)); - pszOut[schsize+1+size] = 0; - *pcchOut = schsize + 1 + size; - } - else { - if (*pcchOut < size + 1) {*pcchOut = size+1; return E_POINTER;} - memcpy(pszOut, addr, size*sizeof(WCHAR)); - pszOut[size] = 0; - *pcchOut = size; - } - TRACE("len=%d %s\n", *pcchOut, debugstr_w(pszOut)); - - return ret; -} - -/************************************************************************* - * PathIsURLA [SHLWAPI.@] - * - * Check if the given path is a Url. - * - * PARAMS - * lpszPath [I] Path to check. - * - * RETURNS - * TRUE if lpszPath is a Url. - * FALSE if lpszPath is NULL or not a Url. - */ -BOOL WINAPI PathIsURLA(LPCSTR lpstrPath) -{ - PARSEDURLA base; - HRESULT hres; - - TRACE("%s\n", debugstr_a(lpstrPath)); - - if (!lpstrPath || !*lpstrPath) return FALSE; - - /* get protocol */ - base.cbSize = sizeof(base); - hres = ParseURLA(lpstrPath, &base); - return hres == S_OK && (base.nScheme != URL_SCHEME_INVALID); -} - -/************************************************************************* - * PathIsURLW [SHLWAPI.@] - * - * See PathIsURLA. - */ -BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath) -{ - PARSEDURLW base; - HRESULT hres; - - TRACE("%s\n", debugstr_w(lpstrPath)); - - if (!lpstrPath || !*lpstrPath) return FALSE; - - /* get protocol */ - base.cbSize = sizeof(base); - hres = ParseURLW(lpstrPath, &base); - return hres == S_OK && (base.nScheme != URL_SCHEME_INVALID); -} - -/************************************************************************* - * UrlCreateFromPathA [SHLWAPI.@] - * - * See UrlCreateFromPathW - */ -HRESULT WINAPI UrlCreateFromPathA(LPCSTR pszPath, LPSTR pszUrl, LPDWORD pcchUrl, DWORD dwReserved) -{ - WCHAR bufW[INTERNET_MAX_URL_LENGTH]; - WCHAR *urlW = bufW; - UNICODE_STRING pathW; - HRESULT ret; - DWORD lenW = sizeof(bufW)/sizeof(WCHAR), lenA; - - if(!RtlCreateUnicodeStringFromAsciiz(&pathW, pszPath)) - return E_INVALIDARG; - if((ret = UrlCreateFromPathW(pathW.Buffer, urlW, &lenW, dwReserved)) == E_POINTER) { - urlW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR)); - ret = UrlCreateFromPathW(pathW.Buffer, urlW, &lenW, dwReserved); - } - if(ret == S_OK || ret == S_FALSE) { - RtlUnicodeToMultiByteSize(&lenA, urlW, lenW * sizeof(WCHAR)); - if(*pcchUrl > lenA) { - RtlUnicodeToMultiByteN(pszUrl, *pcchUrl - 1, &lenA, urlW, lenW * sizeof(WCHAR)); - pszUrl[lenA] = 0; - *pcchUrl = lenA; - } else { - *pcchUrl = lenA + 1; - ret = E_POINTER; - } - } - if(urlW != bufW) HeapFree(GetProcessHeap(), 0, urlW); - RtlFreeUnicodeString(&pathW); - return ret; -} - -/************************************************************************* - * UrlCreateFromPathW [SHLWAPI.@] - * - * Create a Url from a file path. - * - * PARAMS - * pszPath [I] Path to convert - * pszUrl [O] Destination for the converted Url - * pcchUrl [I/O] Length of pszUrl - * dwReserved [I] Reserved, must be 0 - * - * RETURNS - * Success: S_OK pszUrl contains the converted path, S_FALSE if the path is already a Url - * Failure: An HRESULT error code. - */ -HRESULT WINAPI UrlCreateFromPathW(LPCWSTR pszPath, LPWSTR pszUrl, LPDWORD pcchUrl, DWORD dwReserved) -{ - HRESULT ret; - - TRACE("(%s, %p, %p, 0x%08x)\n", debugstr_w(pszPath), pszUrl, pcchUrl, dwReserved); - - /* Validate arguments */ - if (dwReserved != 0) - return E_INVALIDARG; - if (!pszUrl || !pcchUrl) - return E_INVALIDARG; - - ret = URL_CreateFromPath(pszPath, pszUrl, pcchUrl); - - if (S_FALSE == ret) - strcpyW(pszUrl, pszPath); - - return ret; -} - #ifndef __REACTOS__ /************************************************************************* * SHAutoComplete [SHLWAPI.@] @@ -2631,72 +158,3 @@ HRESULT WINAPI MLBuildResURLW(LPCWSTR lpszLibName, HMODULE hMod, DWORD dwFlags, } return hRet; } - -/*********************************************************************** - * UrlFixupW [SHLWAPI.462] - * - * Checks the scheme part of a URL and attempts to correct misspellings. - * - * PARAMS - * lpszUrl [I] Pointer to the URL to be corrected - * lpszTranslatedUrl [O] Pointer to a buffer to store corrected URL - * dwMaxChars [I] Maximum size of corrected URL - * - * RETURNS - * success: S_OK if URL corrected or already correct - * failure: S_FALSE if unable to correct / COM error code if other error - * - */ -HRESULT WINAPI UrlFixupW(LPCWSTR url, LPWSTR translatedUrl, DWORD maxChars) -{ - DWORD srcLen; - - FIXME("(%s,%p,%d) STUB\n", debugstr_w(url), translatedUrl, maxChars); - - if (!url) - return E_FAIL; - - srcLen = lstrlenW(url) + 1; - - /* For now just copy the URL directly */ - lstrcpynW(translatedUrl, url, (maxChars < srcLen) ? maxChars : srcLen); - - return S_OK; -} - -/************************************************************************* - * IsInternetESCEnabled [SHLWAPI.@] -#ifdef __REACTOS__ - * - * https://learn.microsoft.com/en-us/windows/win32/api/shlwapi/nf-shlwapi-isinternetescenabled -#endif - */ -BOOL WINAPI IsInternetESCEnabled(void) -{ -#ifdef __REACTOS__ - BOOL ret; - DWORD cbValue, dwValue; - HKEY hKey; - LSTATUS error; - static const PCWSTR pszZoneMapKey = - L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\ZoneMap"; - - TRACE("()\n"); - - ret = FALSE; - error = RegOpenKeyExW(HKEY_CURRENT_USER, pszZoneMapKey, 0, KEY_READ, &hKey); - if (error == ERROR_SUCCESS) - { - dwValue = 0; - cbValue = sizeof(dwValue); - error = RegQueryValueExW(hKey, L"IEharden", NULL, NULL, (PBYTE)&dwValue, &cbValue); - if (error == ERROR_SUCCESS) - ret = (dwValue == TRUE); - RegCloseKey(hKey); - } - return ret; -#else - FIXME(": stub\n"); - return FALSE; -#endif -}