shell32/unixfs: Added unicode support in folder and file pidls.
diff --git a/dlls/shell32/shfldr_unixfs.c b/dlls/shell32/shfldr_unixfs.c
index 1ded2d8..394a8c6 100644
--- a/dlls/shell32/shfldr_unixfs.c
+++ b/dlls/shell32/shfldr_unixfs.c
@@ -168,16 +168,14 @@
#define ADJUST_THIS(c,m,p) ((c*)(((long)p)-(long)&(((c*)0)->lp##m##Vtbl)))
#define STATIC_CAST(i,p) ((i*)&p->lp##i##Vtbl)
-/* FileStruct reserves one byte for szNames, thus we don't have to
- * alloc a byte for the terminating '\0' of 'name'. Two of the
- * additional bytes are for SHITEMID's cb field. One is for IDLDATA's
- * type field. One is for FileStruct's szNames field, to terminate
- * the alternate DOS name, which we don't use here.
- */
-#define SHITEMID_LEN_FROM_NAME_LEN(n) \
- (sizeof(USHORT)+sizeof(PIDLTYPE)+sizeof(FileStruct)+(n)+sizeof(char))
-#define NAME_LEN_FROM_LPSHITEMID(s) \
- (((LPSHITEMID)s)->cb-sizeof(USHORT)-sizeof(PIDLTYPE)-sizeof(FileStruct)-sizeof(char))
+#define LEN_SHITEMID_FIXED_PART ((USHORT) \
+ ( sizeof(USHORT) /* SHITEMID's cb field. */ \
+ + sizeof(PIDLTYPE) /* PIDLDATA's type field. */ \
+ + sizeof(FileStruct) /* Well, the FileStruct. */ \
+ - sizeof(char) /* One char too much in FileStruct. */ \
+ + sizeof(FileStructW) /* You name it. */ \
+ - sizeof(WCHAR) /* One WCHAR too much in FileStructW. */ \
+ + sizeof(WORD) )) /* Offset of FileStructW field in PIDL. */
#define PATHMODE_UNIX 0
#define PATHMODE_DOS 1
@@ -191,7 +189,7 @@
const IDropTargetVtbl *lpIDropTargetVtbl;
const ISFHelperVtbl *lpISFHelperVtbl;
LONG m_cRef;
- CHAR *m_pszPath; /* Target path of the shell folder */
+ CHAR *m_pszPath; /* Target path of the shell folder (CP_UNIXCP) */
LPITEMIDLIST m_pidlLocation; /* Location in the shell namespace */
DWORD m_dwPathMode;
DWORD m_dwAttributes;
@@ -229,7 +227,126 @@
}
/******************************************************************************
- * UNIXFS_is_pidl_of_type [INTERNAL]
+ * UNIXFS_filename_from_shitemid [Internal]
+ *
+ * Get CP_UNIXCP encoded filename corresponding to the first item of a pidl
+ *
+ * PARAMS
+ * pidl [I] A simple SHITEMID
+ * pszPathElement [O] Filename in CP_UNIXCP encoding will be stored here
+ *
+ * RETURNS
+ * Success: Number of bytes necessary to store the CP_UNIXCP encoded filename
+ * _without_ the terminating NUL.
+ * Failure: 0
+ *
+ * NOTES
+ * Size of the buffer at pszPathElement has to be FILENAME_MAX. pszPathElement
+ * may be NULL, if you are only interested in the return value.
+ */
+static int UNIXFS_filename_from_shitemid(LPCITEMIDLIST pidl, char* pszPathElement) {
+ FileStructW *pFileStructW = _ILGetFileStructW(pidl);
+ int cLen = 0;
+
+ if (pFileStructW) {
+ cLen = WideCharToMultiByte(CP_UNIXCP, 0, pFileStructW->wszName, -1, pszPathElement,
+ pszPathElement ? FILENAME_MAX : 0, 0, 0);
+ } else {
+ /* There might be pidls slipping in from shfldr_fs.c, which don't contain the
+ * FileStructW field. In this case, we have to convert from CP_ACP to CP_UNIXCP. */
+ char *pszText = _ILGetTextPointer(pidl);
+ WCHAR *pwszPathElement = NULL;
+ int cWideChars;
+
+ cWideChars = MultiByteToWideChar(CP_ACP, 0, pszText, -1, NULL, 0);
+ if (!cWideChars) goto cleanup;
+
+ pwszPathElement = SHAlloc(cWideChars * sizeof(WCHAR));
+ if (!pwszPathElement) goto cleanup;
+
+ cWideChars = MultiByteToWideChar(CP_ACP, 0, pszText, -1, pwszPathElement, cWideChars);
+ if (!cWideChars) goto cleanup;
+
+ cLen = WideCharToMultiByte(CP_UNIXCP, 0, pwszPathElement, -1, pszPathElement,
+ pszPathElement ? FILENAME_MAX : 0, 0, 0);
+
+ cleanup:
+ SHFree(pwszPathElement);
+ }
+
+ if (cLen) cLen--; /* Don't count terminating NUL! */
+ return cLen;
+}
+
+/******************************************************************************
+ * UNIXFS_shitemid_len_from_filename [Internal]
+ *
+ * Computes the necessary length of a pidl to hold a path element
+ *
+ * PARAMS
+ * szPathElement [I] The path element string in CP_UNIXCP encoding.
+ * ppszPathElement [O] Path element string in CP_ACP encoding.
+ * ppwszPathElement [O] Path element string as WCHAR string.
+ *
+ * RETURNS
+ * Success: Length in bytes of a SHITEMID representing szPathElement
+ * Failure: 0
+ *
+ * NOTES
+ * Provide NULL values if not interested in pp(w)szPathElement. Otherwise
+ * caller is responsible to free ppszPathElement and ppwszPathElement with
+ * SHFree.
+ */
+static USHORT UNIXFS_shitemid_len_from_filename(
+ const char *szPathElement, char **ppszPathElement, WCHAR **ppwszPathElement)
+{
+ USHORT cbPidlLen = 0;
+ WCHAR *pwszPathElement = NULL;
+ char *pszPathElement = NULL;
+ int cWideChars, cChars;
+
+ /* There and Back Again: A Hobbit's Holiday. CP_UNIXCP might be some ANSI
+ * codepage or it might be a real multi-byte encoding like utf-8. There is no
+ * other way to figure out the length of the corresponding WCHAR and CP_ACP
+ * strings without actually doing the full CP_UNIXCP -> WCHAR -> CP_ACP cycle. */
+
+ cWideChars = MultiByteToWideChar(CP_UNIXCP, 0, szPathElement, -1, NULL, 0);
+ if (!cWideChars) goto cleanup;
+
+ pwszPathElement = SHAlloc(cWideChars * sizeof(WCHAR));
+ if (!pwszPathElement) goto cleanup;
+
+ cWideChars = MultiByteToWideChar(CP_UNIXCP, 0, szPathElement, -1, pwszPathElement, cWideChars);
+ if (!cWideChars) goto cleanup;
+
+ cChars = WideCharToMultiByte(CP_ACP, 0, pwszPathElement, -1, NULL, 0, 0, 0);
+ if (!cChars) goto cleanup;
+
+ pszPathElement = SHAlloc(cChars);
+ if (!pszPathElement) goto cleanup;
+
+ cChars = WideCharToMultiByte(CP_ACP, 0, pwszPathElement, -1, pszPathElement, cChars, 0, 0);
+ if (!cChars) goto cleanup;
+
+ /* (cChars & 0x1) is for the potential alignment byte */
+ cbPidlLen = LEN_SHITEMID_FIXED_PART + cChars + (cChars & 0x1) + cWideChars * sizeof(WCHAR);
+
+cleanup:
+ if (cbPidlLen && ppszPathElement)
+ *ppszPathElement = pszPathElement;
+ else
+ SHFree(pszPathElement);
+
+ if (cbPidlLen && ppwszPathElement)
+ *ppwszPathElement = pwszPathElement;
+ else
+ SHFree(pwszPathElement);
+
+ return cbPidlLen;
+}
+
+/******************************************************************************
+ * UNIXFS_is_pidl_of_type [Internal]
*
* Checks for the first SHITEMID of an ITEMIDLIST if it passes a filter.
*
@@ -413,6 +530,28 @@
}
/******************************************************************************
+ * UNIXFS_seconds_since_1970_to_dos_date_time [Internal]
+ *
+ * Convert unix time to FAT time
+ *
+ * PARAMS
+ * ss1970 [I] Unix time (seconds since 1970)
+ * pDate [O] Corresponding FAT date
+ * pTime [O] Corresponding FAT time
+ */
+static inline void UNIXFS_seconds_since_1970_to_dos_date_time(
+ time_t ss1970, LPWORD pDate, LPWORD pTime)
+{
+ LARGE_INTEGER time;
+ FILETIME fileTime;
+
+ RtlSecondsSince1970ToTime( ss1970, &time );
+ fileTime.dwLowDateTime = time.u.LowPart;
+ fileTime.dwHighDateTime = time.u.HighPart;
+ FileTimeToDosDateTime(&fileTime, pDate, pTime);
+}
+
+/******************************************************************************
* UNIXFS_build_shitemid [Internal]
*
* Constructs a new SHITEMID for the last component of path 'pszUnixPath' into
@@ -432,39 +571,57 @@
* a 0 USHORT value.
*/
static char* UNIXFS_build_shitemid(char *pszUnixPath, void *pIDL) {
- LARGE_INTEGER time;
- FILETIME fileTime;
LPPIDLDATA pIDLData;
struct stat fileStat;
- char *pszComponent;
- int cComponentLen;
+ char *pszComponentU, *pszComponentA;
+ WCHAR *pwszComponentW;
+ int cComponentULen, cComponentALen;
+ USHORT cbLen;
+ FileStructW *pFileStructW;
+ WORD uOffsetW, *pOffsetW;
TRACE("(pszUnixPath=%s, pIDL=%p)\n", debugstr_a(pszUnixPath), pIDL);
- /* Compute the SHITEMID's length and wipe it. */
- pszComponent = strrchr(pszUnixPath, '/') + 1;
- cComponentLen = strlen(pszComponent);
- memset(pIDL, 0, SHITEMID_LEN_FROM_NAME_LEN(cComponentLen));
- ((LPSHITEMID)pIDL)->cb = SHITEMID_LEN_FROM_NAME_LEN(cComponentLen) ;
-
/* We are only interested in regular files and directories. */
if (stat(pszUnixPath, &fileStat)) return NULL;
if (!S_ISDIR(fileStat.st_mode) && !S_ISREG(fileStat.st_mode)) return NULL;
+ /* Compute the SHITEMID's length and wipe it. */
+ pszComponentU = strrchr(pszUnixPath, '/') + 1;
+ cComponentULen = strlen(pszComponentU);
+ cbLen = UNIXFS_shitemid_len_from_filename(pszComponentU, &pszComponentA, &pwszComponentW);
+ if (!cbLen) return NULL;
+ memset(pIDL, 0, cbLen);
+ ((LPSHITEMID)pIDL)->cb = cbLen;
+
/* Set shell32's standard SHITEMID data fields. */
pIDLData = _ILGetDataPointer((LPCITEMIDLIST)pIDL);
pIDLData->type = S_ISDIR(fileStat.st_mode) ? PT_FOLDER : PT_VALUE;
pIDLData->u.file.dwFileSize = (DWORD)fileStat.st_size;
- RtlSecondsSince1970ToTime( fileStat.st_mtime, &time );
- fileTime.dwLowDateTime = time.u.LowPart;
- fileTime.dwHighDateTime = time.u.HighPart;
- FileTimeToDosDateTime(&fileTime, &pIDLData->u.file.uFileDate, &pIDLData->u.file.uFileTime);
+ UNIXFS_seconds_since_1970_to_dos_date_time(fileStat.st_mtime, &pIDLData->u.file.uFileDate,
+ &pIDLData->u.file.uFileTime);
pIDLData->u.file.uFileAttribs = 0;
if (S_ISDIR(fileStat.st_mode)) pIDLData->u.file.uFileAttribs |= FILE_ATTRIBUTE_DIRECTORY;
- if (pszComponent[0] == '.') pIDLData->u.file.uFileAttribs |= FILE_ATTRIBUTE_HIDDEN;
- memcpy(pIDLData->u.file.szNames, pszComponent, cComponentLen);
+ if (pszComponentU[0] == '.') pIDLData->u.file.uFileAttribs |= FILE_ATTRIBUTE_HIDDEN;
+ cComponentALen = lstrlenA(pszComponentA) + 1;
+ memcpy(pIDLData->u.file.szNames, pszComponentA, cComponentALen);
+
+ pFileStructW = (FileStructW*)(pIDLData->u.file.szNames + cComponentALen + (cComponentALen & 0x1));
+ uOffsetW = (WORD)(((LPBYTE)pFileStructW) - ((LPBYTE)pIDL));
+ pFileStructW->cbLen = cbLen - uOffsetW;
+ UNIXFS_seconds_since_1970_to_dos_date_time(fileStat.st_mtime, &pFileStructW->uCreationDate,
+ &pFileStructW->uCreationTime);
+ UNIXFS_seconds_since_1970_to_dos_date_time(fileStat.st_atime, &pFileStructW->uLastAccessDate,
+ &pFileStructW->uLastAccessTime);
+ lstrcpyW(pFileStructW->wszName, pwszComponentW);
- return pszComponent + cComponentLen;
+ pOffsetW = (WORD*)(((LPBYTE)pIDL) + cbLen - sizeof(WORD));
+ *pOffsetW = uOffsetW;
+
+ SHFree(pszComponentA);
+ SHFree(pwszComponentW);
+
+ return pszComponentU + cComponentULen;
}
/******************************************************************************
@@ -484,8 +641,9 @@
*/
static BOOL UNIXFS_path_to_pidl(UnixFolder *pUnixFolder, const WCHAR *path, LPITEMIDLIST *ppidl) {
LPITEMIDLIST pidl;
- int cSubDirs, cPidlLen, cPathLen;
- char *pSlash, szCompletePath[FILENAME_MAX], *pNextPathElement;
+ int cPidlLen, cPathLen;
+ char *pSlash, *pNextSlash, szCompletePath[FILENAME_MAX], *pNextPathElement, *pszAPath;
+ WCHAR *pwszPath;
TRACE("pUnixFolder=%p, path=%s, ppidl=%p\n", pUnixFolder, debugstr_w(path), ppidl);
@@ -551,17 +709,28 @@
* and _not_ terminated by a '/'. */
TRACE("complete path: %s, relative path: %s\n", szCompletePath, pNextPathElement);
- /* Count the number of sub-directories in the path */
- cSubDirs = 0;
- pSlash = pNextPathElement;
+ /* Convert to CP_ACP and WCHAR */
+ if (!UNIXFS_shitemid_len_from_filename(pNextPathElement, &pszAPath, &pwszPath))
+ return 0;
+
+ /* Compute the length of the complete ITEMIDLIST */
+ cPidlLen = 0;
+ pSlash = pszAPath;
while (pSlash) {
- cSubDirs++;
- pSlash = strchr(pSlash+1, '/');
+ pNextSlash = strchr(pSlash+1, '/');
+ cPidlLen += LEN_SHITEMID_FIXED_PART + /* Fixed part length plus potential alignment byte. */
+ (pNextSlash ? (pNextSlash - pSlash) & 0x1 : lstrlenA(pSlash) & 0x1);
+ pSlash = pNextSlash;
}
-
- /* Allocate enough memory to hold the path. The -cSubDirs is for the '/'
- * characters, which are not stored in the ITEMIDLIST. */
- cPidlLen = strlen(pNextPathElement) - cSubDirs + cSubDirs * SHITEMID_LEN_FROM_NAME_LEN(0) + sizeof(USHORT);
+
+ /* The USHORT is for the ITEMIDLIST terminator. The NUL terminators for the sub-path-strings
+ * are accounted for by the '/' separators, which are not stored in the SHITEMIDs. Above we
+ * have ensured that the number of '/'s exactly matches the number of sub-path-strings. */
+ cPidlLen += lstrlenA(pszAPath) + lstrlenW(pwszPath) * sizeof(WCHAR) + sizeof(USHORT);
+
+ SHFree(pszAPath);
+ SHFree(pwszPath);
+
*ppidl = pidl = (LPITEMIDLIST)SHAlloc(cPidlLen);
if (!pidl) return FALSE;
@@ -613,7 +782,7 @@
/* Determine the path's length bytes */
while (current && current->mkid.cb) {
- dwPathLen += NAME_LEN_FROM_LPSHITEMID(current) + 1; /* For the '/' */
+ dwPathLen += UNIXFS_filename_from_shitemid(current, NULL) + 1; /* For the '/' */
current = ILGetNext(current);
};
@@ -636,8 +805,7 @@
This->m_dwAttributes |= SFGAO_FILESYSTEM;
}
while (current && current->mkid.cb) {
- memcpy(pNextDir, _ILGetTextPointer(current), NAME_LEN_FROM_LPSHITEMID(current));
- pNextDir += NAME_LEN_FROM_LPSHITEMID(current);
+ pNextDir += UNIXFS_filename_from_shitemid(current, pNextDir);
if (!(This->m_dwAttributes & SFGAO_FILESYSTEM)) {
*pNextDir = '\0';
if (!stat(This->m_pszPath, &statPrefix) && UNIXFS_is_dos_device(&statPrefix))
@@ -847,8 +1015,8 @@
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD)1);
compare = CompareStringA(LOCALE_USER_DEFAULT, NORM_IGNORECASE,
- _ILGetTextPointer(pidl1), NAME_LEN_FROM_LPSHITEMID(pidl1),
- _ILGetTextPointer(pidl2), NAME_LEN_FROM_LPSHITEMID(pidl2));
+ _ILGetTextPointer(pidl1), -1,
+ _ILGetTextPointer(pidl2), -1);
if ((compare == CSTR_LESS_THAN) || (compare == CSTR_GREATER_THAN))
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (WORD)((compare == CSTR_LESS_THAN)?-1:1));
@@ -921,9 +1089,8 @@
for (i=0; i<cidl; i++) {
if (!(This->m_dwAttributes & SFGAO_FILESYSTEM)) {
struct stat fileStat;
- char *pszName = _ILGetTextPointer(apidl[i]);
- if (!pszName) return E_INVALIDARG;
- lstrcpyA(pszRelativePath, pszName);
+ if (!UNIXFS_filename_from_shitemid(apidl[i], pszRelativePath))
+ return E_INVALIDARG;
if (stat(szAbsolutePath, &fileStat) || !UNIXFS_is_dos_device(&fileStat))
*rgfInOut &= ~SFGAO_FILESYSTEM;
}
@@ -986,22 +1153,6 @@
}
}
-/******************************************************************************
- * Translate file name from unix to ANSI encoding.
- */
-static void strcpyn_U2A(char *win_fn, UINT win_fn_len, const char *unix_fn)
-{
- UINT len;
- WCHAR *unicode_fn;
-
- len = MultiByteToWideChar(CP_UNIXCP, 0, unix_fn, -1, NULL, 0);
- unicode_fn = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
- MultiByteToWideChar(CP_UNIXCP, 0, unix_fn, -1, unicode_fn, len);
-
- WideCharToMultiByte(CP_ACP, 0, unicode_fn, len, win_fn, win_fn_len, NULL, NULL);
- HeapFree(GetProcessHeap(), 0, unicode_fn);
-}
-
static HRESULT WINAPI UnixFolder_IShellFolder2_GetDisplayNameOf(IShellFolder2* iface,
LPCITEMIDLIST pidl, SHGDNF uFlags, STRRET* lpName)
{
@@ -1014,16 +1165,20 @@
(GET_SHGDN_RELATION(uFlags) != SHGDN_INFOLDER))
{
if (!pidl || !pidl->mkid.cb) {
- lpName->uType = STRRET_CSTR;
+ lpName->uType = STRRET_WSTR;
if (This->m_dwPathMode == PATHMODE_UNIX) {
- strcpyn_U2A(lpName->u.cStr, MAX_PATH, This->m_pszPath);
+ UINT len = MultiByteToWideChar(CP_UNIXCP, 0, This->m_pszPath, -1, NULL, 0);
+ lpName->u.pOleStr = SHAlloc(len * sizeof(WCHAR));
+ if (!lpName->u.pOleStr) return HRESULT_FROM_WIN32(GetLastError());
+ MultiByteToWideChar(CP_UNIXCP, 0, This->m_pszPath, -1, lpName->u.pOleStr, len);
} else {
- WCHAR *pwszDosPath = wine_get_dos_file_name(This->m_pszPath);
- if (!pwszDosPath)
- return HRESULT_FROM_WIN32(GetLastError());
- PathRemoveBackslashW(pwszDosPath);
- WideCharToMultiByte(CP_ACP, 0, pwszDosPath, -1, lpName->u.cStr, MAX_PATH, NULL, NULL);
- HeapFree(GetProcessHeap(), 0, pwszDosPath);
+ LPWSTR pwszDosFileName = wine_get_dos_file_name(This->m_pszPath);
+ if (!pwszDosFileName) return HRESULT_FROM_WIN32(GetLastError());
+ lpName->u.pOleStr = SHAlloc((lstrlenW(pwszDosFileName) + 1) * sizeof(WCHAR));
+ if (!lpName->u.pOleStr) return HRESULT_FROM_WIN32(GetLastError());
+ lstrcpyW(lpName->u.pOleStr, pwszDosFileName);
+ PathRemoveBackslashW(lpName->u.pOleStr);
+ HeapFree(GetProcessHeap(), 0, pwszDosFileName);
}
} else {
IShellFolder *pSubFolder;
@@ -1036,18 +1191,20 @@
IShellFolder_Release(pSubFolder);
}
} else {
- char *pszFileName = _ILGetTextPointer(pidl);
- lpName->uType = STRRET_CSTR;
- strcpyn_U2A(lpName->u.cStr, MAX_PATH, pszFileName ? pszFileName : "");
+ WCHAR wszFileName[MAX_PATH];
+ if (!_ILSimpleGetTextW(pidl, wszFileName, MAX_PATH)) return E_INVALIDARG;
+ lpName->uType = STRRET_WSTR;
+ lpName->u.pOleStr = SHAlloc((lstrlenW(wszFileName)+1)*sizeof(WCHAR));
+ if (!lpName->u.pOleStr) return HRESULT_FROM_WIN32(GetLastError());
+ lstrcpyW(lpName->u.pOleStr, wszFileName);
+ if (!(GET_SHGDN_FOR(uFlags) & SHGDN_FORPARSING) && This->m_dwPathMode == PATHMODE_DOS &&
+ !_ILIsFolder(pidl) && wszFileName[0] != '.' && SHELL_FS_HideExtension(wszFileName))
+ {
+ PathRemoveExtensionW(lpName->u.pOleStr);
+ }
}
- /* If in dos mode, do some post-processing on the path.
- * (e.g. remove filename extension, if uFlags & SHGDN_FOREDITING)
- */
- if (SUCCEEDED(hr) && This->m_dwPathMode == PATHMODE_DOS && !_ILIsFolder(pidl))
- SHELL_FS_ProcessDisplayFilename(lpName->u.cStr, uFlags);
-
- TRACE("--> %s\n", lpName->u.cStr);
+ TRACE("--> %s\n", debugstr_w(lpName->u.pOleStr));
return hr;
}
@@ -1075,7 +1232,7 @@
/* build source path */
memcpy(szSrc, This->m_pszPath, cBasePathLen);
- lstrcpyA(szSrc+cBasePathLen, _ILGetTextPointer(pidl));
+ UNIXFS_filename_from_shitemid(pidl, szSrc + cBasePathLen);
/* build destination path */
if (uFlags & SHGDN_FORPARSING) { /* absolute path in lpszName */
@@ -1091,8 +1248,10 @@
if (_ILSimpleGetTextW(pidl, wszSrcRelative, MAX_PATH) &&
SHELL_FS_HideExtension(wszSrcRelative))
{
- char *pszExt = PathFindExtensionA(_ILGetTextPointer(pidl));
- lstrcatA(szDest, pszExt);
+ WCHAR *pwszExt = PathFindExtensionW(wszSrcRelative);
+ int cLenDest = strlen(szDest);
+ WideCharToMultiByte(CP_UNIXCP, 0, pwszExt, -1, szDest + cLenDest,
+ FILENAME_MAX - cLenDest, NULL, NULL);
}
}
@@ -1198,11 +1357,10 @@
} else {
struct stat statItem;
if (iColumn == 4 || iColumn == 5 || iColumn == 6) {
- char szPath[FILENAME_MAX], *pszFile = _ILGetTextPointer(pidl);
- if (!pszFile)
+ char szPath[FILENAME_MAX];
+ strcpy(szPath, This->m_pszPath);
+ if (!UNIXFS_filename_from_shitemid(pidl, szPath + strlen(szPath)))
return E_INVALIDARG;
- lstrcpyA(szPath, This->m_pszPath);
- lstrcatA(szPath, pszFile);
if (stat(szPath, &statItem))
return E_INVALIDARG;
}
@@ -1635,7 +1793,8 @@
pszRelative = szAbsolute + lstrlenA(szAbsolute);
for (i=0; i<cidl && SUCCEEDED(hr); i++) {
- lstrcpyA(pszRelative, _ILGetTextPointer(apidl[i]));
+ if (!UNIXFS_filename_from_shitemid(apidl[i], pszRelative))
+ return E_INVALIDARG;
pidlAbsolute = ILCombine(This->m_pidlLocation, apidl[i]);
if (_ILIsFolder(apidl[i])) {
if (rmdir(szAbsolute)) {
@@ -1693,7 +1852,7 @@
return E_FAIL;
/* Build the unix path of the current destination item */
- lstrcpyA(pszRelativeDst, _ILGetTextPointer(apidl[i]));
+ UNIXFS_filename_from_shitemid(apidl[i], pszRelativeDst);
FIXME("Would copy %s to %s. Not yet implemented.\n", szSrc, szAbsoluteDst);
}
@@ -2036,7 +2195,8 @@
* and see if it passes the filter.
*/
lstrcpyA(pszRelativePath, pDirEntry->d_name);
- rgelt[i] = (LPITEMIDLIST)SHAlloc(SHITEMID_LEN_FROM_NAME_LEN(lstrlenA(pszRelativePath))+sizeof(USHORT));
+ rgelt[i] = (LPITEMIDLIST)SHAlloc(
+ UNIXFS_shitemid_len_from_filename(pszRelativePath, NULL, NULL)+sizeof(USHORT));
if (!UNIXFS_build_shitemid(This->m_szFolder, rgelt[i]) ||
!UNIXFS_is_pidl_of_type(rgelt[i], This->m_fFilter))
{
diff --git a/dlls/shell32/tests/shlfolder.c b/dlls/shell32/tests/shlfolder.c
index 7a51844..7abeae1 100644
--- a/dlls/shell32/tests/shlfolder.c
+++ b/dlls/shell32/tests/shlfolder.c
@@ -370,10 +370,7 @@
/* WinXP stores the filenames as both ANSI and UNICODE in the pidls */
pidlLast = pILFindLastID(pidlTestFile);
- todo_wine {
- ok( pidlLast->mkid.cb >= 76, "Expected pidl length of at least 76, got %d.\n",
- pidlLast->mkid.cb);
- }
+ ok(pidlLast->mkid.cb >=76, "Expected pidl length of at least 76, got %d.\n", pidlLast->mkid.cb);
if (pidlLast->mkid.cb >= 76) {
ok(!lstrcmpW((WCHAR*)&pidlLast->mkid.abID[46], wszFileName),
"WinXP stores the filename as a wchar-string at this position!\n");
@@ -1163,8 +1160,8 @@
todo_wine { ok(pidlFile->mkid.abID[18] == '~', "Should be derived 8.3 name!\n"); }
if (i == 0) /* First file name has an even number of chars. No need for alignment. */
- todo_wine { ok(pidlFile->mkid.abID[12 + strlen(szFile) + 1] != '\0',
- "Alignment byte, where there shouldn't be!\n"); }
+ ok(pidlFile->mkid.abID[12 + strlen(szFile) + 1] != '\0',
+ "Alignment byte, where there shouldn't be!\n");
if (i == 1) /* Second file name has an uneven number of chars => alignment byte */
ok(pidlFile->mkid.abID[12 + strlen(szFile) + 1] == '\0',
@@ -1172,9 +1169,9 @@
/* The offset of the FileStructW member is stored as a WORD at the end of the pidl. */
cbOffset = *(WORD*)(((LPBYTE)pidlFile)+pidlFile->mkid.cb-sizeof(WORD));
- todo_wine { ok (cbOffset >= sizeof(struct FileStructA) &&
+ ok (cbOffset >= sizeof(struct FileStructA) &&
cbOffset <= pidlFile->mkid.cb - sizeof(struct FileStructW),
- "Wrong offset value (%d) stored at the end of the PIDL\n", cbOffset); }
+ "Wrong offset value (%d) stored at the end of the PIDL\n", cbOffset);
if (cbOffset >= sizeof(struct FileStructA) &&
cbOffset <= pidlFile->mkid.cb - sizeof(struct FileStructW))