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 -}