📄 string.c
字号:
/*
* Shlwapi string functions
*
* Copyright 1998 Juergen Schmied
* Copyright 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define COM_NO_WINDOWS_H
#include "config.h"
#include "wine/port.h"
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#define NO_SHLWAPI_REG
#define NO_SHLWAPI_STREAM
#include "shlwapi.h"
#include "wingdi.h"
#include "winuser.h"
#include "shlobj.h"
#include "ddeml.h"
#include "wine/unicode.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)
extern HMODULE SHLWAPI_hmlang;
typedef HRESULT (WINAPI *fnpConvertINetUnicodeToMultiByte)(LPDWORD,DWORD,LPCWSTR,LPINT,LPSTR,LPINT);
static fnpConvertINetUnicodeToMultiByte pConvertINetUnicodeToMultiByte;
static HRESULT WINAPI _SHStrDupAA(LPCSTR,LPSTR*);
static HRESULT WINAPI _SHStrDupAW(LPCWSTR,LPSTR*);
/*************************************************************************
* SHLWAPI_ChrCmpHelperA
*
* Internal helper for SHLWAPI_ChrCmpA/ChrCMPIA.
*
* NOTES
* Both this function and its Unicode counterpart are very inneficient. 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 WINAPI 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) - 2;
}
/*************************************************************************
* SHLWAPI_ChrCmpHelperW
*
* Internal helper for SHLWAPI_ChrCmpW/ChrCmpIW.
*/
static BOOL WINAPI SHLWAPI_ChrCmpHelperW(WCHAR ch1, WCHAR ch2, DWORD dwFlags)
{
WCHAR str1[2], str2[2];
str1[0] = ch1;
str1[1] = '\0';
str2[0] = ch2;
str2[1] = '\0';
return CompareStringW(GetThreadLocale(), dwFlags, str1, 2, str2, 2) - 2;
}
/*************************************************************************
* 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);
}
/*************************************************************************
* SHLWAPI_ChrCmpW
*
* Internal helper function.
*/
static BOOL WINAPI SHLWAPI_ChrCmpW(WCHAR ch1, WCHAR ch2)
{
return SHLWAPI_ChrCmpHelperW(ch1, ch2, 0);
}
/*************************************************************************
* ChrCmpIW [SHLWAPI.386]
*
* See ChrCmpIA.
*/
BOOL WINAPI ChrCmpIW(WCHAR ch1, WCHAR ch2)
{
return SHLWAPI_ChrCmpHelperW(ch1, ch2, NORM_IGNORECASE);
}
/*************************************************************************
* 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 = CharNextW(lpszStr);
}
lpszStr = NULL;
}
return (LPWSTR)lpszStr;
}
/*************************************************************************
* 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)
{
int iRet;
TRACE("(%s,%s)\n", debugstr_w(lpszStr),debugstr_w(lpszComp));
iRet = CompareStringW(GetThreadLocale(), NORM_IGNORECASE, lpszStr, -1, lpszComp, -1);
return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0;
}
/*************************************************************************
* 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] Maximum 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)
{
INT iRet;
TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszComp), iLen);
iRet = CompareStringA(GetThreadLocale(), 0, lpszStr, iLen, lpszComp, iLen);
return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0;
}
/*************************************************************************
* StrCmpNW [SHLWAPI.@]
*
* See StrCmpNA.
*/
INT WINAPI StrCmpNW(LPCWSTR lpszStr, LPCWSTR lpszComp, INT iLen)
{
INT iRet;
TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszComp), iLen);
iRet = CompareStringW(GetThreadLocale(), 0, lpszStr, iLen, lpszComp, iLen);
return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0;
}
/*************************************************************************
* 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] Maximum 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)
{
INT iRet;
TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszComp), iLen);
iRet = CompareStringA(GetThreadLocale(), NORM_IGNORECASE, lpszStr, iLen, lpszComp, iLen);
return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0;
}
/*************************************************************************
* StrCmpNIW [SHLWAPI.@]
*
* See StrCmpNIA.
*/
INT WINAPI StrCmpNIW(LPCWSTR lpszStr, LPCWSTR lpszComp, int iLen)
{
INT iRet;
TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszComp), iLen);
iRet = CompareStringW(GetThreadLocale(), NORM_IGNORECASE, lpszStr, iLen, lpszComp, iLen);
return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0;
}
/*************************************************************************
* 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)
{
INT iRet;
TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszComp));
iRet = CompareStringW(GetThreadLocale(), 0, lpszStr, -1, lpszComp, -1);
return iRet == CSTR_LESS_THAN ? -1 : iRet == CSTR_GREATER_THAN ? 1 : 0;
}
/*************************************************************************
* StrCatW [SHLWAPI.@]
*
* Concatanate two strings.
*
* PARAMS
* lpszStr [O] Initial string
* lpszSrc [I] String to concatanate
*
* RETURNS
* lpszStr.
*/
LPWSTR WINAPI StrCatW(LPWSTR lpszStr, LPCWSTR lpszSrc)
{
TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSrc));
strcatW(lpszStr, lpszSrc);
return lpszStr;
}
/*************************************************************************
* StrCpyW [SHLWAPI.@]
*
* Copy a string to another string.
*
* PARAMS
* lpszStr [O] Destination string
* lpszSrc [I] Source string
*
* RETURNS
* lpszStr.
*/
LPWSTR WINAPI StrCpyW(LPWSTR lpszStr, LPCWSTR lpszSrc)
{
TRACE("(%p,%s)\n", lpszStr, debugstr_w(lpszSrc));
strcpyW(lpszStr, lpszSrc);
return lpszStr;
}
/*************************************************************************
* StrCpyNW [SHLWAPI.@]
*
* Copy a string to another string, up to a maximum number of characters.
*
* PARAMS
* lpszStr [O] Destination string
* lpszSrc [I] Source string
* iLen [I] Maximum number of chars to copy
*
* RETURNS
* lpszStr.
*/
LPWSTR WINAPI StrCpyNW(LPWSTR lpszStr, LPCWSTR lpszSrc, int iLen)
{
TRACE("(%p,%s,%i)\n", lpszStr, debugstr_w(lpszSrc), iLen);
lstrcpynW(lpszStr, lpszSrc, iLen);
return lpszStr;
}
/*************************************************************************
* SHLWAPI_StrStrHelperA
*
* Internal implementation of StrStrA/StrStrIA
*/
static LPSTR WINAPI SHLWAPI_StrStrHelperA(LPCSTR lpszStr, LPCSTR lpszSearch,
int (*pStrCmpFn)(LPCSTR,LPCSTR,size_t))
{
size_t iLen;
if (!lpszStr || !lpszSearch || !*lpszSearch)
return NULL;
iLen = strlen(lpszSearch);
while (*lpszStr)
{
if (!pStrCmpFn(lpszStr, lpszSearch, iLen))
return (LPSTR)lpszStr;
lpszStr = CharNextA(lpszStr);
}
return NULL;
}
/*************************************************************************
* SHLWAPI_StrStrHelperW
*
* Internal implementation of StrStrW/StrStrIW
*/
static LPWSTR WINAPI SHLWAPI_StrStrHelperW(LPCWSTR lpszStr, LPCWSTR lpszSearch,
int (*pStrCmpFn)(LPCWSTR,LPCWSTR,int))
{
int iLen;
if (!lpszStr || !lpszSearch || !*lpszSearch)
return NULL;
iLen = strlenW(lpszSearch);
while (*lpszStr)
{
if (!pStrCmpFn(lpszStr, lpszSearch, iLen))
return (LPWSTR)lpszStr;
lpszStr = CharNextW(lpszStr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -