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/shell32/shlfileop.cpp?rev=64630&r1=64629&r2=64630&view=diff
==============================================================================
--- 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;


Reply via email to