* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include "precomp.h"
+#include "config.h"
+#include "wine/port.h"
#include <math.h>
-#include <mlang.h>
-#include <ddeml.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#define NONAMELESSUNION
+
+#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 "mlang.h"
+#include "ddeml.h"
+#include "wine/unicode.h"
+#include "wine/debug.h"
+
+#include "resource.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(shell);
extern HINSTANCE shlwapi_hInstance;
* PARAMS
* lpszStr [I] First string to compare
* lpszComp [I] Second string to compare
- * iLen [I] Maximum number of chars to compare.
+ * iLen [I] Number of chars to compare
*
* RETURNS
* An integer less than, equal to or greater than 0, indicating that
* PARAMS
* lpszStr [I] First string to compare
* lpszComp [I] Second string to compare
- * iLen [I] Maximum number of chars to compare.
+ * iLen [I] Number of chars to compare
*
* RETURNS
* An integer less than, equal to or greater than 0, indicating that
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.@]
*
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)
+ while (lpszStr + iLen <= end)
{
if (!pStrCmpFn(lpszStr, lpszSearch, iLen))
return (LPSTR)lpszStr;
*/
LPSTR WINAPI StrRStrIA(LPCSTR lpszStr, LPCSTR lpszEnd, LPCSTR lpszSearch)
{
+ LPSTR lpszRet = NULL;
WORD ch1, ch2;
INT iLen;
if (!lpszStr || !lpszSearch || !*lpszSearch)
return NULL;
- if (!lpszEnd)
- lpszEnd = lpszStr + lstrlenA(lpszStr);
- if (lpszEnd == lpszStr)
- return NULL;
-
if (IsDBCSLeadByte(*lpszSearch))
ch1 = *lpszSearch << 8 | (UCHAR)lpszSearch[1];
else
ch1 = *lpszSearch;
iLen = lstrlenA(lpszSearch);
- do
+ if (!lpszEnd)
+ lpszEnd = lpszStr + lstrlenA(lpszStr);
+ else /* reproduce the broken behaviour on Windows */
+ lpszEnd += min(iLen - 1, lstrlenA(lpszEnd));
+
+ while (lpszStr + iLen <= lpszEnd && *lpszStr)
{
- lpszEnd = CharPrevA(lpszStr, lpszEnd);
- ch2 = IsDBCSLeadByte(*lpszEnd)? *lpszEnd << 8 | (UCHAR)lpszEnd[1] : *lpszEnd;
+ ch2 = IsDBCSLeadByte(*lpszStr)? *lpszStr << 8 | (UCHAR)lpszStr[1] : *lpszStr;
if (!ChrCmpIA(ch1, ch2))
{
- if (!StrCmpNIA(lpszEnd, lpszSearch, iLen))
- return (LPSTR)lpszEnd;
+ if (!StrCmpNIA(lpszStr, lpszSearch, iLen))
+ lpszRet = (LPSTR)lpszStr;
}
- } while (lpszEnd > lpszStr);
- return NULL;
+ lpszStr = CharNextA(lpszStr);
+ }
+ return lpszRet;
}
/*************************************************************************
*/
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));
- iLen = strlenW(lpszSearch);
-
- while (lpszEnd > lpszStr)
+ while (lpszStr + iLen <= lpszEnd && *lpszStr)
{
- lpszEnd--;
- if (!StrCmpNIW(lpszEnd, lpszSearch, iLen))
- return (LPWSTR)lpszEnd;
+ if (!ChrCmpIW(*lpszSearch, *lpszStr))
+ {
+ if (!StrCmpNIW(lpszStr, lpszSearch, iLen))
+ lpszRet = (LPWSTR)lpszStr;
+ }
+ lpszStr++;
}
- return NULL;
+ return lpszRet;
}
/*************************************************************************
LPWSTR WINAPI StrStrIW(LPCWSTR lpszStr, LPCWSTR lpszSearch)
{
int iLen;
+ LPCWSTR end;
TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch));
return NULL;
iLen = strlenW(lpszSearch);
+ end = lpszStr + strlenW(lpszStr);
- while (*lpszStr)
+ while (lpszStr + iLen <= end)
{
if (!StrCmpNIW(lpszStr, lpszSearch, iLen))
return (LPWSTR)lpszStr;
default:
FIXME("unknown type!\n");
- return FALSE;
+ return E_NOTIMPL;
}
return S_OK;
}
*/
HRESULT WINAPI StrRetToBufW (LPSTRRET src, const ITEMIDLIST *pidl, LPWSTR dest, UINT len)
{
- TRACE("dest=%p len=0x%x strret=%p pidl=%p\n", dest, len, src, pidl);
+ TRACE("dest=%p len=0x%x strret=%p pidl=%p\n", dest, len, src, pidl);
- if (!src)
- {
- WARN("Invalid lpStrRet would crash under Win32!\n");
- if (dest)
- *dest = '\0';
- return E_FAIL;
- }
+ if (!dest || !len)
+ return E_FAIL;
- if (!dest || !len)
- return E_FAIL;
+ if (!src)
+ {
+ WARN("Invalid lpStrRet would crash under Win32!\n");
+ if (dest)
+ *dest = '\0';
+ return E_FAIL;
+ }
- *dest = '\0';
+ *dest = '\0';
+
+ switch (src->uType) {
+ case STRRET_WSTR: {
+ size_t dst_len;
+ if (!src->u.pOleStr)
+ return E_FAIL;
+ dst_len = strlenW(src->u.pOleStr);
+ memcpy(dest, src->u.pOleStr, min(dst_len, len-1) * sizeof(WCHAR));
+ dest[min(dst_len, len-1)] = 0;
+ CoTaskMemFree(src->u.pOleStr);
+ if (len <= dst_len)
+ {
+ dest[0] = 0;
+ return E_NOT_SUFFICIENT_BUFFER;
+ }
+ break;
+ }
- switch (src->uType)
- {
- case STRRET_WSTR:
- lstrcpynW(dest, src->u.pOleStr, len);
- CoTaskMemFree(src->u.pOleStr);
- break;
+ case STRRET_CSTR:
+ if (!MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ))
+ dest[len-1] = 0;
+ break;
- case STRRET_CSTR:
- if (!MultiByteToWideChar( CP_ACP, 0, src->u.cStr, -1, dest, len ))
- dest[len-1] = 0;
- break;
+ case STRRET_OFFSET:
+ if (pidl)
+ {
+ if (!MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset, -1,
+ dest, len ))
+ dest[len-1] = 0;
+ }
+ break;
- case STRRET_OFFSET:
- if (pidl)
- {
- if (!MultiByteToWideChar( CP_ACP, 0, ((LPCSTR)&pidl->mkid)+src->u.uOffset, -1,
- dest, len ))
- dest[len-1] = 0;
- }
- break;
+ default:
+ FIXME("unknown type!\n");
+ return E_NOTIMPL;
+ }
- default:
- FIXME("unknown type!\n");
- return FALSE;
- }
- return S_OK;
+ return S_OK;
}
/*************************************************************************
mem = HeapAlloc(GetProcessHeap(), 0, reqLen);
if (mem)
{
- reqLen = WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem,
- reqLen, NULL, NULL);
+ WideCharToMultiByte(CodePage, 0, lpSrcStr, len, mem, reqLen, NULL, NULL);
reqLen = SHTruncateString(mem, dstlen -1);
reqLen++;