Author: dquintana
Date: Thu Oct 9 00:10:20 2014
New Revision: 64630
URL:
http://svn.reactos.org/svn/reactos?rev=64630&view=rev
Log:
[SHELL32]
* Rewrite SHFileOperationA using human-readable code.
CORE-8564
Modified:
branches/shell-experiments/dll/win32/shell32/shlfileop.cpp
Modified: branches/shell-experiments/dll/win32/shell32/shlfileop.cpp
URL:
http://svn.reactos.org/svn/reactos/branches/shell-experiments/dll/win32/she…
==============================================================================
--- branches/shell-experiments/dll/win32/shell32/shlfileop.cpp [iso-8859-1] (original)
+++ branches/shell-experiments/dll/win32/shell32/shlfileop.cpp [iso-8859-1] Thu Oct 9
00:10:20 2014
@@ -940,38 +940,56 @@
/*************************************************************************
*
- * SHNameTranslate HelperFunction for SHFileOperationA
- *
- * Translates a list of 0 terminated ASCII strings into Unicode. If *wString
- * is NULL, only the necessary size of the string is determined and returned,
- * otherwise the ASCII strings are copied into it and the buffer is increased
- * to point to the location after the final 0 termination char.
- */
-static DWORD SHNameTranslate(LPWSTR* wString, LPCWSTR* pWToFrom, BOOL more)
-{
- DWORD size = 0, aSize = 0;
- LPCSTR aString = (LPCSTR)*pWToFrom;
-
- if (aString)
- {
+ * _ConvertAtoW helper function for SHFileOperationA
+ *
+ * Converts a string or string-list to unicode.
+ */
+static DWORD _ConvertAtoW(PCSTR strSrc, PCWSTR* pStrDest, BOOL isList)
+{
+ *pStrDest = NULL;
+
+ // If the input is null, nothing to convert.
+ if (!strSrc)
+ return 0;
+
+ // Measure the total size, depending on if it's a zero-terminated list.
+ int sizeA = 0;
+ if (isList)
+ {
+ PCSTR tmpSrc = strSrc;
+ int size;
do
{
- size = lstrlenA(aString) + 1;
- aSize += size;
- aString += size;
- } while ((size != 1) && more);
-
- /* The two sizes might be different in the case of multibyte chars */
- size = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)*pWToFrom, aSize, *wString, 0);
- if (*wString) /* only in the second loop */
- {
- MultiByteToWideChar(CP_ACP, 0, (LPCSTR)*pWToFrom, aSize, *wString, size);
- *pWToFrom = *wString;
- *wString += size;
- }
- }
- return size;
-}
+ size = lstrlenA(tmpSrc) + 1;
+ sizeA += size;
+ tmpSrc += size;
+ } while (size != 1);
+ }
+ else
+ {
+ sizeA = lstrlenA(strSrc) + 1;
+ }
+
+ // Measure the
+ int sizeW = MultiByteToWideChar(CP_ACP, 0, strSrc, sizeA, NULL, 0);
+ if (!sizeW)
+ return GetLastError();
+
+ PWSTR strDest = (PWSTR) HeapAlloc(GetProcessHeap(), 0, sizeW);
+ if (!strDest)
+ return ERROR_OUTOFMEMORY;
+
+ int err = MultiByteToWideChar(CP_ACP, 0, strSrc, sizeA, strDest, sizeW);
+ if (!err)
+ {
+ HeapFree(GetProcessHeap(), 0, strDest);
+ return GetLastError();
+ }
+
+ *pStrDest = strDest;
+ return 0;
+}
+
/*************************************************************************
* SHFileOperationA [SHELL32.@]
*
@@ -990,40 +1008,53 @@
*/
int WINAPI SHFileOperationA(LPSHFILEOPSTRUCTA lpFileOp)
{
- SHFILEOPSTRUCTW nFileOp = *((LPSHFILEOPSTRUCTW)lpFileOp);
- int retCode = 0;
- DWORD size;
- LPWSTR ForFree = NULL, /* we change wString in SHNameTranslate and can't use it
for freeing */
- wString = NULL; /* we change this in SHNameTranslate */
-
- TRACE("\n");
- if (FO_DELETE == (nFileOp.wFunc & FO_MASK))
- nFileOp.pTo = NULL; /* we need a NULL or a valid pointer for translation */
- if (!(nFileOp.fFlags & FOF_SIMPLEPROGRESS))
- nFileOp.lpszProgressTitle = NULL; /* we need a NULL or a valid pointer for
translation */
- while (1) /* every loop calculate size, second translate also, if we have storage for
this */
- {
- size = SHNameTranslate(&wString, &nFileOp.lpszProgressTitle, FALSE); /*
no loop */
- size += SHNameTranslate(&wString, &nFileOp.pFrom, TRUE); /* internal loop
*/
- size += SHNameTranslate(&wString, &nFileOp.pTo, TRUE); /* internal loop
*/
-
- if (ForFree)
- {
- retCode = SHFileOperationW(&nFileOp);
- HeapFree(GetProcessHeap(), 0, ForFree); /* we cannot use wString, it was
changed */
- break;
- }
- else
- {
- wString = ForFree = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, size *
sizeof(WCHAR));
- if (ForFree) continue;
- retCode = ERROR_OUTOFMEMORY;
- nFileOp.fAnyOperationsAborted = TRUE;
- SetLastError(retCode);
- return retCode;
- }
- }
-
+ int errCode, retCode;
+ SHFILEOPSTRUCTW nFileOp = { 0 };
+
+ // Convert A information to W
+ nFileOp.hwnd = lpFileOp->hwnd;
+ nFileOp.wFunc = lpFileOp->wFunc;
+ nFileOp.fFlags = lpFileOp->fFlags;
+
+ errCode = _ConvertAtoW(lpFileOp->pFrom, &nFileOp.pFrom, TRUE);
+ if (errCode != 0)
+ goto cleanup;
+
+ if (FO_DELETE != (nFileOp.wFunc & FO_MASK))
+ {
+ errCode = _ConvertAtoW(lpFileOp->pTo, &nFileOp.pTo, TRUE);
+ if (errCode != 0)
+ goto cleanup;
+ }
+
+ if (nFileOp.fFlags & FOF_SIMPLEPROGRESS)
+ {
+ errCode = _ConvertAtoW(lpFileOp->lpszProgressTitle,
&nFileOp.lpszProgressTitle, FALSE);
+ if (errCode != 0)
+ goto cleanup;
+ }
+
+ // Call the actual function
+ retCode = SHFileOperationW(&nFileOp);
+
+ // Cleanup
+cleanup:
+ if (nFileOp.pFrom)
+ HeapFree(GetProcessHeap(), 0, (PVOID) nFileOp.pFrom);
+ if (nFileOp.pTo)
+ HeapFree(GetProcessHeap(), 0, (PVOID) nFileOp.pTo);
+ if (nFileOp.lpszProgressTitle)
+ HeapFree(GetProcessHeap(), 0, (PVOID) nFileOp.lpszProgressTitle);
+
+ if (errCode != 0)
+ {
+ lpFileOp->fAnyOperationsAborted = TRUE;
+ SetLastError(errCode);
+
+ return errCode;
+ }
+
+ // Thankfully, the
lpFileOp->hNameMappings = nFileOp.hNameMappings;
lpFileOp->fAnyOperationsAborted = nFileOp.fAnyOperationsAborted;
return retCode;