📄 string.c
字号:
* pidl [I] ITEMIDLIST for lpStrRet->uType = STRRET_OFFSET
* pBstrOut [O] Destination for converted BSTR
*
* RETURNS
* Success: S_OK. pBstrOut contains the new string.
* Failure: E_FAIL, if any parameters are invalid.
*/
HRESULT WINAPI StrRetToBSTR(STRRET *lpStrRet, LPCITEMIDLIST pidl, BSTR* pBstrOut)
{
HRESULT hRet = E_FAIL;
switch (lpStrRet->uType)
{
case STRRET_WSTR:
*pBstrOut = SysAllocString(lpStrRet->u.pOleStr);
if (*pBstrOut)
hRet = S_OK;
CoTaskMemFree(lpStrRet->u.pOleStr);
break;
case STRRET_CSTR:
hRet = _SHStrDupAToBSTR(lpStrRet->u.cStr, pBstrOut);
break;
case STRRET_OFFSET:
hRet = _SHStrDupAToBSTR(((LPCSTR)&pidl->mkid) + lpStrRet->u.uOffset, pBstrOut);
break;
default:
*pBstrOut = NULL;
}
return hRet;
}
/*************************************************************************
* StrFormatKBSizeA [SHLWAPI.@]
*
* Create a formatted string containing a byte count in Kilobytes.
*
* PARAMS
* llBytes [I] Byte size to format
* lpszDest [I] Destination for formatted string
* cchMax [I] Size of lpszDest
*
* RETURNS
* lpszDest.
*/
LPSTR WINAPI StrFormatKBSizeA(LONGLONG llBytes, LPSTR lpszDest, UINT cchMax)
{
WCHAR wszBuf[256];
if (!StrFormatKBSizeW(llBytes, wszBuf, 256))
return NULL;
if (!WideCharToMultiByte(CP_ACP, 0, wszBuf, -1, lpszDest, cchMax, NULL, NULL))
return NULL;
return lpszDest;
}
/*************************************************************************
* StrFormatKBSizeW [SHLWAPI.@]
*
* See StrFormatKBSizeA.
*/
LPWSTR WINAPI StrFormatKBSizeW(LONGLONG llBytes, LPWSTR lpszDest, UINT cchMax)
{
static const WCHAR kb[] = {' ','K','B',0};
LONGLONG llKB = (llBytes + 1023) >> 10;
int len;
TRACE("(0x%s,%p,%d)\n", wine_dbgstr_longlong(llBytes), lpszDest, cchMax);
if (!FormatInt(llKB, lpszDest, cchMax))
return NULL;
len = lstrlenW(lpszDest);
if (cchMax - len < 4)
return NULL;
lstrcatW(lpszDest, kb);
return lpszDest;
}
/*************************************************************************
* StrNCatA [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 to concatenate
*
* RETURNS
* lpszStr.
*
* NOTES
* cchMax determines the number of characters that are appended to lpszStr,
* not the total length of the string.
*/
LPSTR WINAPI StrNCatA(LPSTR lpszStr, LPCSTR lpszCat, INT cchMax)
{
LPSTR lpszRet = lpszStr;
TRACE("(%s,%s,%i)\n", debugstr_a(lpszStr), debugstr_a(lpszCat), cchMax);
if (!lpszStr)
{
WARN("Invalid lpszStr would crash under Win32!\n");
return NULL;
}
StrCpyNA(lpszStr + strlen(lpszStr), lpszCat, cchMax);
return lpszRet;
}
/*************************************************************************
* StrNCatW [SHLWAPI.@]
*
* See StrNCatA.
*/
LPWSTR WINAPI StrNCatW(LPWSTR lpszStr, LPCWSTR lpszCat, INT cchMax)
{
LPWSTR lpszRet = lpszStr;
TRACE("(%s,%s,%i)\n", debugstr_w(lpszStr), debugstr_w(lpszCat), cchMax);
if (!lpszStr)
{
WARN("Invalid lpszStr would crash under Win32\n");
return NULL;
}
StrCpyNW(lpszStr + strlenW(lpszStr), lpszCat, 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]
*
* Duplicates a ASCII string to ASCII. The destination buffer is allocated.
*/
static HRESULT _SHStrDupAA(LPCSTR src, LPSTR * dest)
{
HRESULT hr;
int len = 0;
if (src) {
len = lstrlenA(src) + 1;
*dest = CoTaskMemAlloc(len);
} else {
*dest = NULL;
}
if (*dest) {
lstrcpynA(*dest,src, len);
hr = S_OK;
} else {
hr = E_OUTOFMEMORY;
}
TRACE("%s->(%p)\n", debugstr_a(src), *dest);
return hr;
}
/*************************************************************************
* SHStrDupA [SHLWAPI.@]
*
* Return a Unicode copy of a string, in memory allocated by CoTaskMemAlloc().
*
* PARAMS
* lpszStr [I] String to copy
* lppszDest [O] Destination for the new string copy
*
* RETURNS
* Success: S_OK. lppszDest contains the new string in Unicode format.
* Failure: E_OUTOFMEMORY, If any arguments are invalid or memory allocation
* fails.
*/
HRESULT WINAPI SHStrDupA(LPCSTR lpszStr, LPWSTR * lppszDest)
{
HRESULT hRet;
int len = 0;
if (lpszStr)
{
len = MultiByteToWideChar(0, 0, lpszStr, -1, 0, 0) * sizeof(WCHAR);
*lppszDest = CoTaskMemAlloc(len);
}
else
*lppszDest = NULL;
if (*lppszDest)
{
MultiByteToWideChar(0, 0, lpszStr, -1, *lppszDest, len/sizeof(WCHAR));
hRet = S_OK;
}
else
hRet = E_OUTOFMEMORY;
TRACE("%s->(%p)\n", debugstr_a(lpszStr), *lppszDest);
return hRet;
}
/*************************************************************************
* _SHStrDupAW [INTERNAL]
*
* Duplicates a UNICODE to a ASCII string. The destination buffer is allocated.
*/
static HRESULT _SHStrDupAW(LPCWSTR src, LPSTR * dest)
{
HRESULT hr;
int len = 0;
if (src) {
len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
*dest = CoTaskMemAlloc(len);
} else {
*dest = NULL;
}
if (*dest) {
WideCharToMultiByte(CP_ACP, 0, src, -1, *dest, len, NULL, NULL);
hr = S_OK;
} else {
hr = E_OUTOFMEMORY;
}
TRACE("%s->(%p)\n", debugstr_w(src), *dest);
return hr;
}
/*************************************************************************
* SHStrDupW [SHLWAPI.@]
*
* See SHStrDupA.
*/
HRESULT WINAPI SHStrDupW(LPCWSTR src, LPWSTR * dest)
{
HRESULT hr;
int len = 0;
if (src) {
len = (lstrlenW(src) + 1) * sizeof(WCHAR);
*dest = CoTaskMemAlloc(len);
} else {
*dest = NULL;
}
if (*dest) {
memcpy(*dest, src, len);
hr = S_OK;
} else {
hr = E_OUTOFMEMORY;
}
TRACE("%s->(%p)\n", debugstr_w(src), *dest);
return hr;
}
/*************************************************************************
* SHLWAPI_WriteReverseNum
*
* Internal helper for SHLWAPI_WriteTimeClass.
*/
static inline LPWSTR SHLWAPI_WriteReverseNum(LPWSTR lpszOut, DWORD dwNum)
{
*lpszOut-- = '\0';
/* Write a decimal number to a string, backwards */
do
{
DWORD dwNextDigit = dwNum % 10;
*lpszOut-- = '0' + dwNextDigit;
dwNum = (dwNum - dwNextDigit) / 10;
} while (dwNum > 0);
return lpszOut;
}
/*************************************************************************
* SHLWAPI_FormatSignificant
*
* Internal helper for SHLWAPI_WriteTimeClass.
*/
static inline int SHLWAPI_FormatSignificant(LPWSTR lpszNum, int dwDigits)
{
/* Zero non significant digits, return remaining significant digits */
while (*lpszNum)
{
lpszNum++;
if (--dwDigits == 0)
{
while (*lpszNum)
*lpszNum++ = '0';
return 0;
}
}
return dwDigits;
}
/*************************************************************************
* SHLWAPI_WriteTimeClass
*
* Internal helper for StrFromTimeIntervalW.
*/
static int SHLWAPI_WriteTimeClass(LPWSTR lpszOut, DWORD dwValue,
UINT uClassStringId, int iDigits)
{
WCHAR szBuff[64], *szOut = szBuff + 32;
szOut = SHLWAPI_WriteReverseNum(szOut, dwValue);
iDigits = SHLWAPI_FormatSignificant(szOut + 1, iDigits);
*szOut = ' ';
LoadStringW(shlwapi_hInstance, uClassStringId, szBuff + 32, 32);
strcatW(lpszOut, szOut);
return iDigits;
}
/*************************************************************************
* StrFromTimeIntervalA [SHLWAPI.@]
*
* Format a millisecond time interval into a string
*
* PARAMS
* lpszStr [O] Output buffer for formatted time interval
* cchMax [I] Size of lpszStr
* dwMS [I] Number of milliseconds
* iDigits [I] Number of digits to print
*
* RETURNS
* The length of the formatted string, or 0 if any parameter is invalid.
*
* NOTES
* This implementation mimics the Win32 behaviour of always writing a leading
* space before the time interval begins.
*
* iDigits is used to provide approximate times if accuracy is not important.
* This number of digits will be written of the first non-zero time class
* (hours/minutes/seconds). If this does not complete the time classification,
* the remaining digits are changed to zeros (i.e. The time is _not_ rounded).
* If there are digits remaining following the writing of a time class, the
* next time class will be written.
*
* For example, given dwMS represents 138 hours,43 minutes and 15 seconds, the
* following will result from the given values of iDigits:
*
*| iDigits 1 2 3 4 5 ...
*| lpszStr "100 hr" "130 hr" "138 hr" "138 hr 40 min" "138 hr 43 min" ...
*/
INT WINAPI StrFromTimeIntervalA(LPSTR lpszStr, UINT cchMax, DWORD dwMS,
int iDigits)
{
INT iRet = 0;
TRACE("(%p,%d,%d,%d)\n", lpszStr, cchMax, dwMS, iDigits);
if (lpszStr && cchMax)
{
WCHAR szBuff[128];
StrFromTimeIntervalW(szBuff, sizeof(szBuff)/sizeof(WCHAR), dwMS, iDigits);
WideCharToMultiByte(CP_ACP,0,szBuff,-1,lpszStr,cchMax,0,0);
}
return iRet;
}
/*************************************************************************
* StrFromTimeIntervalW [SHLWAPI.@]
*
* See StrFromTimeIntervalA.
*/
INT WINAPI StrFromTimeIntervalW(LPWSTR lpszStr, UINT cchMax, DWORD dwMS,
int iDigits)
{
INT iRet = 0;
TRACE("(%p,%d,%d,%d)\n", lpszStr, cchMax, dwMS, iDigits);
if (lpszStr && cchMax)
{
WCHAR szCopy[128];
DWORD dwHours, dwMinutes;
if (!iDigits || cchMax == 1)
{
*lpszStr = '\0';
return 0;
}
/* Calculate the time classes */
dwMS = (dwMS + 500) / 1000;
dwHours = dwMS / 3600;
dwMS -= dwHours * 3600;
dwMinutes = dwMS / 60;
dwMS -= dwMinutes * 60;
szCopy[0] = '\0';
if (dwHours)
iDigits = SHLWAPI_WriteTimeClass(szCopy, dwHours, IDS_TIME_INTERVAL_HOURS, iDigits);
if (dwMinutes && iDigits)
iDigits = SHLWAPI_WriteTimeClass(szCopy, dwMinutes, IDS_TIME_INTERVAL_MINUTES, iDigits);
if (iDigits) /* Always write seconds if we have significant digits */
SHLWAPI_WriteTimeClass(szCopy, dwMS, IDS_TIME_INTERVAL_SECONDS, iDigits);
lstrcpynW(lpszStr, szCopy, cchMax);
iRet = strlenW(lpszStr);
}
return iRet;
}
/*************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -