📄 path.c
字号:
/*
* Path Functions
*
* Copyright 1999, 2000 Juergen Schmied
* Copyright 2001, 2002 Jon Griffiths
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "wine/port.h"
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include "wine/unicode.h"
#include "windef.h"
#include "winbase.h"
#include "wingdi.h"
#include "winuser.h"
#include "winreg.h"
#include "winternl.h"
#define NO_SHLWAPI_STREAM
#include "shlwapi.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
/* Get a function pointer from a DLL handle */
#define GET_FUNC(func, module, name, fail) \
do { \
if (!func) { \
if (!SHLWAPI_h##module && !(SHLWAPI_h##module = LoadLibraryA(#module ".dll"))) return fail; \
func = (fn##func)GetProcAddress(SHLWAPI_h##module, name); \
if (!func) return fail; \
} \
} while (0)
/* DLL handles for late bound calls */
static HMODULE SHLWAPI_hshell32;
/* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
typedef BOOL (WINAPI *fnpIsNetDrive)(int);
static fnpIsNetDrive pIsNetDrive;
HRESULT WINAPI SHGetWebFolderFilePathW(LPCWSTR,LPWSTR,DWORD);
/*************************************************************************
* 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)
{
lpszDest[0] = 0;
return NULL;
}
if (lpszDir)
MultiByteToWideChar(CP_ACP,0,lpszDir,-1,szDir,MAX_PATH);
if (lpszFile)
MultiByteToWideChar(CP_ACP,0,lpszFile,-1,szFile,MAX_PATH);
if (PathCombineW(szDest, lpszDir ? szDir : NULL, lpszFile ? szFile : NULL))
if (WideCharToMultiByte(CP_ACP,0,szDest,-1,lpszDest,MAX_PATH,0,0))
return lpszDest;
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;
TRACE("(%s)\n",debugstr_a(lpszPath));
if (!lpszPath || (iLen = strlen(lpszPath)) >= MAX_PATH)
return NULL;
if (iLen)
{
lpszPath += iLen;
if (lpszPath[-1] != '\\')
{
*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.@]
*
* Create a root drive string (e.g. "A:\") from a drive number.
*
* PARAMS
* lpszPath [O] Destination for the drive string
*
* RETURNS
* lpszPath
*
* NOTES
* If lpszPath is NULL or drive is invalid, nothing is written to lpszPath.
*/
LPSTR WINAPI PathBuildRootA(LPSTR lpszPath, int drive)
{
TRACE("(%p,%d)\n", lpszPath, drive);
if (lpszPath && drive >= 0 && drive < 26)
{
lpszPath[0] = 'A' + drive;
lpszPath[1] = ':';
lpszPath[2] = '\\';
lpszPath[3] = '\0';
}
return lpszPath;
}
/*************************************************************************
* PathBuildRootW [SHLWAPI.@]
*
* See PathBuildRootA.
*/
LPWSTR WINAPI PathBuildRootW(LPWSTR lpszPath, int drive)
{
TRACE("(%p,%d)\n", lpszPath, drive);
if (lpszPath && drive >= 0 && drive < 26)
{
lpszPath[0] = 'A' + drive;
lpszPath[1] = ':';
lpszPath[2] = '\\';
lpszPath[3] = '\0';
}
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -