📄 path.c
字号:
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]
*
* Unicode version of PathFileExistsDefExtA.
*/
BOOL WINAPI PathFileExistsDefExtW(LPWSTR lpszPath,DWORD dwWhich)
{
static const WCHAR pszExts[7][5] = { { '.', 'p', 'i', 'f', 0},
{ '.', 'c', 'o', 'm', 0},
{ '.', 'e', 'x', 'e', 0},
{ '.', 'b', 'a', 't', 0},
{ '.', 'l', 'n', 'k', 0},
{ '.', 'c', 'm', 'd', 0},
{ 0, 0, 0, 0, 0} };
TRACE("(%s,%d)\n", debugstr_w(lpszPath), dwWhich);
if (!lpszPath || PathIsUNCServerW(lpszPath) || PathIsUNCServerShareW(lpszPath))
return FALSE;
if (dwWhich)
{
LPCWSTR szExt = PathFindExtensionW(lpszPath);
if (!*szExt || dwWhich & 0x40)
{
size_t iChoose = 0;
int iLen = lstrlenW(lpszPath);
if (iLen > (MAX_PATH - 5))
return FALSE;
while ( (dwWhich & 0x1) && pszExts[iChoose][0] )
{
lstrcpyW(lpszPath + iLen, pszExts[iChoose]);
if (PathFileExistsW(lpszPath))
return TRUE;
iChoose++;
dwWhich >>= 1;
}
*(lpszPath + iLen) = (WCHAR)'\0';
return FALSE;
}
}
return PathFileExistsW(lpszPath);
}
/*************************************************************************
* @ [SHLWAPI.3]
*
* Determine if a file exists locally and is of an executable type.
*
* PARAMS
* lpszPath [I/O] File to search for
* dwWhich [I] Type of executable to search for
*
* RETURNS
* TRUE If the file was found. lpszPath contains the file name.
* FALSE Otherwise.
*
* NOTES
* lpszPath is modified in place and must be at least MAX_PATH in length.
* If the function returns FALSE, the path is modified to its original state.
* If the given path contains an extension or dwWhich is 0, executable
* extensions are not checked.
*
* Ordinals 3-6 are a classic case of MS exposing limited functionality to
* users (here through PathFindOnPathA()) and keeping advanced functionality for
* their own developers exclusive use. Monopoly, anyone?
*/
BOOL WINAPI PathFileExistsDefExtA(LPSTR lpszPath,DWORD dwWhich)
{
BOOL bRet = FALSE;
TRACE("(%s,%d)\n", debugstr_a(lpszPath), dwWhich);
if (lpszPath)
{
WCHAR szPath[MAX_PATH];
MultiByteToWideChar(CP_ACP,0,lpszPath,-1,szPath,MAX_PATH);
bRet = PathFileExistsDefExtW(szPath, dwWhich);
if (bRet)
WideCharToMultiByte(CP_ACP,0,szPath,-1,lpszPath,MAX_PATH,0,0);
}
return bRet;
}
/*************************************************************************
* SHLWAPI_PathFindInOtherDirs
*
* Internal helper for SHLWAPI_PathFindOnPathExA/W.
*/
static BOOL WINAPI SHLWAPI_PathFindInOtherDirs(LPWSTR lpszFile, DWORD dwWhich)
{
static const WCHAR szSystem[] = { 'S','y','s','t','e','m','\0'};
static const WCHAR szPath[] = { 'P','A','T','H','\0'};
DWORD dwLenPATH;
LPCWSTR lpszCurr;
WCHAR *lpszPATH;
WCHAR buff[MAX_PATH];
TRACE("(%s,%08x)\n", debugstr_w(lpszFile), dwWhich);
/* Try system directories */
GetSystemDirectoryW(buff, MAX_PATH);
if (!PathAppendW(buff, lpszFile))
return FALSE;
if (PathFileExistsDefExtW(buff, dwWhich))
{
strcpyW(lpszFile, buff);
return TRUE;
}
GetWindowsDirectoryW(buff, MAX_PATH);
if (!PathAppendW(buff, szSystem ) || !PathAppendW(buff, lpszFile))
return FALSE;
if (PathFileExistsDefExtW(buff, dwWhich))
{
strcpyW(lpszFile, buff);
return TRUE;
}
GetWindowsDirectoryW(buff, MAX_PATH);
if (!PathAppendW(buff, lpszFile))
return FALSE;
if (PathFileExistsDefExtW(buff, dwWhich))
{
strcpyW(lpszFile, buff);
return TRUE;
}
/* Try dirs listed in %PATH% */
dwLenPATH = GetEnvironmentVariableW(szPath, buff, MAX_PATH);
if (!dwLenPATH || !(lpszPATH = HeapAlloc(GetProcessHeap(), 0, (dwLenPATH + 1) * sizeof (WCHAR))))
return FALSE;
GetEnvironmentVariableW(szPath, lpszPATH, dwLenPATH + 1);
lpszCurr = lpszPATH;
while (lpszCurr)
{
LPCWSTR lpszEnd = lpszCurr;
LPWSTR pBuff = buff;
while (*lpszEnd == ' ')
lpszEnd++;
while (*lpszEnd && *lpszEnd != ';')
*pBuff++ = *lpszEnd++;
*pBuff = '\0';
if (*lpszEnd)
lpszCurr = lpszEnd + 1;
else
lpszCurr = NULL; /* Last Path, terminate after this */
if (!PathAppendW(buff, lpszFile))
{
HeapFree(GetProcessHeap(), 0, lpszPATH);
return FALSE;
}
if (PathFileExistsDefExtW(buff, dwWhich))
{
strcpyW(lpszFile, buff);
HeapFree(GetProcessHeap(), 0, lpszPATH);
return TRUE;
}
}
HeapFree(GetProcessHeap(), 0, lpszPATH);
return FALSE;
}
/*************************************************************************
* @ [SHLWAPI.5]
*
* Search a range of paths for a specific type of executable.
*
* PARAMS
* lpszFile [I/O] File to search for
* lppszOtherDirs [I] Other directories to look in
* dwWhich [I] Type of executable to search for
*
* RETURNS
* Success: TRUE. The path to the executable is stored in lpszFile.
* Failure: FALSE. The path to the executable is unchanged.
*/
BOOL WINAPI PathFindOnPathExA(LPSTR lpszFile,LPCSTR *lppszOtherDirs,DWORD dwWhich)
{
WCHAR szFile[MAX_PATH];
WCHAR buff[MAX_PATH];
TRACE("(%s,%p,%08x)\n", debugstr_a(lpszFile), lppszOtherDirs, dwWhich);
if (!lpszFile || !PathIsFileSpecA(lpszFile))
return FALSE;
MultiByteToWideChar(CP_ACP,0,lpszFile,-1,szFile,MAX_PATH);
/* Search provided directories first */
if (lppszOtherDirs && *lppszOtherDirs)
{
WCHAR szOther[MAX_PATH];
LPCSTR *lpszOtherPath = lppszOtherDirs;
while (lpszOtherPath && *lpszOtherPath && (*lpszOtherPath)[0])
{
MultiByteToWideChar(CP_ACP,0,*lpszOtherPath,-1,szOther,MAX_PATH);
PathCombineW(buff, szOther, szFile);
if (PathFileExistsDefExtW(buff, dwWhich))
{
WideCharToMultiByte(CP_ACP,0,buff,-1,lpszFile,MAX_PATH,0,0);
return TRUE;
}
lpszOtherPath++;
}
}
/* Not found, try system and path dirs */
if (SHLWAPI_PathFindInOtherDirs(szFile, dwWhich))
{
WideCharToMultiByte(CP_ACP,0,szFile,-1,lpszFile,MAX_PATH,0,0);
return TRUE;
}
return FALSE;
}
/*************************************************************************
* @ [SHLWAPI.6]
*
* Unicode version of PathFindOnPathExA.
*/
BOOL WINAPI PathFindOnPathExW(LPWSTR lpszFile,LPCWSTR *lppszOtherDirs,DWORD dwWhich)
{
WCHAR buff[MAX_PATH];
TRACE("(%s,%p,%08x)\n", debugstr_w(lpszFile), lppszOtherDirs, dwWhich);
if (!lpszFile || !PathIsFileSpecW(lpszFile))
return FALSE;
/* Search provided directories first */
if (lppszOtherDirs && *lppszOtherDirs)
{
LPCWSTR *lpszOtherPath = lppszOtherDirs;
while (lpszOtherPath && *lpszOtherPath && (*lpszOtherPath)[0])
{
PathCombineW(buff, *lpszOtherPath, lpszFile);
if (PathFileExistsDefExtW(buff, dwWhich))
{
strcpyW(lpszFile, buff);
return TRUE;
}
lpszOtherPath++;
}
}
/* Not found, try system and path dirs */
return SHLWAPI_PathFindInOtherDirs(lpszFile, dwWhich);
}
/*************************************************************************
* PathFindOnPathA [SHLWAPI.@]
*
* Search a range of paths for an executable.
*
* PARAMS
* lpszFile [I/O] File to search for
* lppszOtherDirs [I] Other directories to look in
*
* RETURNS
* Success: TRUE. The path to the executable is stored in lpszFile.
* Failure: FALSE. The path to the executable is unchanged.
*/
BOOL WINAPI PathFindOnPathA(LPSTR lpszFile, LPCSTR *lppszOtherDirs)
{
TRACE("(%s,%p)\n", debugstr_a(lpszFile), lppszOtherDirs);
return PathFindOnPathExA(lpszFile, lppszOtherDirs, 0);
}
/*************************************************************************
* PathFindOnPathW [SHLWAPI.@]
*
* See PathFindOnPathA.
*/
BOOL WINAPI PathFindOnPathW(LPWSTR lpszFile, LPCWSTR *lppszOtherDirs)
{
TRACE("(%s,%p)\n", debugstr_w(lpszFile), lppszOtherDirs);
return PathFindOnPathExW(lpszFile,lppszOtherDirs, 0);
}
/*************************************************************************
* PathCompactPathExA [SHLWAPI.@]
*
* Compact a path into a given number of characters.
*
* PARAMS
* lpszDest [O] Destination for compacted path
* lpszPath [I] Source path
* cchMax [I] Maximum size of compacted path
* dwFlags [I] Reserved
*
* RETURNS
* Success: TRUE. The compacted path is written to lpszDest.
* Failure: FALSE. lpszPath is undefined.
*
* NOTES
* If cchMax is given as 0, lpszDest will still be NUL terminated.
*
* The Win32 version of this function contains a bug: When cchMax == 7,
* 8 bytes will be written to lpszDest. This bug is fixed in the Wine
* implementation.
*
* Some relative paths will be different when cchMax == 5 or 6. This occurs
* because Win32 will insert a "\" in lpszDest, even if one is
* not present in the original path.
*/
BOOL WINAPI PathCompactPathExA(LPSTR lpszDest, LPCSTR lpszPath,
UINT cchMax, DWORD dwFlags)
{
BOOL bRet = FALSE;
TRACE("(%p,%s,%d,0x%08x)\n", lpszDest, debugstr_a(lpszPath), cchMax, dwFlags);
if (lpszPath && lpszDest)
{
WCHAR szPath[MAX_PATH];
WCHAR szDest[MAX_PATH];
MultiByteToWideChar(CP_ACP,0,lpszPath,-1,szPath,MAX_PATH);
szDest[0] = '\0';
bRet = PathCompactPathExW(szDest, szPath, cchMax, dwFlags);
WideCharToMultiByte(CP_ACP,0,szDest,-1,lpszDest,MAX_PATH,0,0);
}
return bRet;
}
/*************************************************************************
* PathCompactPathExW [SHLWAPI.@]
*
* See PathCompactPathExA.
*/
BOOL WINAPI PathCompactPathExW(LPWSTR lpszDest, LPCWSTR lpszPath,
UINT cchMax, DWORD dwFlags)
{
static const WCHAR szEllipses[] = { '.', '.', '.', '\0' };
LPCWSTR lpszFile;
DWORD dwLen, dwFileLen = 0;
TRACE("(%p,%s,%d,0x%08x)\n", lpszDest, debugstr_w(lpszPath), cchMax, dwFlags);
if (!lpszPath)
return FALSE;
if (!lpszDest)
{
WARN("Invalid lpszDest would crash under Win32!\n");
return FALSE;
}
*lpszDest = '\0';
if (cchMax < 2)
return TRUE;
dwLen = strlenW(lpszPath) + 1;
if (dwLen < cchMax)
{
/* Don't need to compact */
memcpy(lpszDest, lpszPath, dwLen * sizeof(WCHAR));
return TRUE;
}
/* Path must be compacted to fit into lpszDest */
lpszFile = PathFindFileNameW(lpszPath);
dwFileLen = lpszPath + dwLen - lpszFile;
if (dwFileLen == dwLen)
{
/* No root in psth */
if (cchMax <= 4)
{
while (--cchMax > 0) /* No room left for anything but ellipses */
*lpszDest++ = '.';
*lpszDest = '\0';
return TRUE;
}
/* Compact the file name with ellipses at the end */
cchMax -= 4;
memcpy(lpszDest, lpszFile, cchMax * sizeof(WCHAR));
strcpyW(lpszDest + cchMax, szEllipses);
return TRUE;
}
/* We have a root in the path */
lpszFile--; /* Start compacted filename with the path separator */
dwFileLen++;
if (dwFileLen + 3 > cchMax)
{
/* Compact the file name */
if (cchMax <= 4)
{
while (--cchMax > 0) /* No room left for anything but ellipses */
*lpszDest++ = '.';
*lpszDest = '\0';
return TRUE;
}
strcpyW(lpszDest, szEllipses);
lpszDest += 3;
cchMax -= 4;
*lpszDest++ = *lpszFile++;
if (cchMax <= 4)
{
while (--cchMax > 0) /* No room left for anything but ellipses */
*lpszDest++ = '.';
*lpszDest = '\0';
return TRUE;
}
cchMax -= 4;
memcpy(lpszDest, lpszFile, cchMax * sizeof(WCHAR));
strcpyW(lpszDest + cchMax, szEllipses);
return TRUE;
}
/* Only the root needs to be Compacted */
dwLen = cchMax - dwFileLen - 3;
memcpy(lpszDest, lpszPath, dwLen * sizeof(WCHAR));
strcpyW(lpszDest + dwLen, szEllipses);
strcpyW(lpszDest + dwLen + 3, lpszFile);
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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -