[SHELL32] CCopyToMenu/CMoveToMenu: Check if this_ is NULL
[reactos.git] / dll / win32 / shell32 / CCopyToMenu.cpp
index a20ed44..e72b217 100644 (file)
@@ -9,43 +9,13 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 
-HRESULT _GetCidlFromDataObject(IDataObject *pDataObject, CIDA** ppcida)
-{
-    static CLIPFORMAT s_cfHIDA = 0;
-    if (s_cfHIDA == 0)
-    {
-        s_cfHIDA = static_cast<CLIPFORMAT>(RegisterClipboardFormatW(CFSTR_SHELLIDLIST));
-    }
-
-    FORMATETC fmt = { s_cfHIDA, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
-    STGMEDIUM medium;
-
-    HRESULT hr = pDataObject->GetData(&fmt, &medium);
-    if (FAILED_UNEXPECTEDLY(hr))
-        return hr;
-
-    LPVOID lpSrc = GlobalLock(medium.hGlobal);
-    SIZE_T cbSize = GlobalSize(medium.hGlobal);
-
-    *ppcida = reinterpret_cast<CIDA *>(::CoTaskMemAlloc(cbSize));
-    if (*ppcida)
-    {
-        memcpy(*ppcida, lpSrc, cbSize);
-        hr = S_OK;
-    }
-    else
-    {
-        ERR("Out of memory\n");
-        hr = E_FAIL;
-    }
-    ReleaseStgMedium(&medium);
-    return hr;
-}
 
 CCopyToMenu::CCopyToMenu() :
     m_idCmdFirst(0),
     m_idCmdLast(0),
-    m_idCmdCopyTo(-1)
+    m_idCmdCopyTo(-1),
+    m_fnOldWndProc(NULL),
+    m_bIgnoreTextBoxChange(FALSE)
 {
 }
 
@@ -53,19 +23,44 @@ CCopyToMenu::~CCopyToMenu()
 {
 }
 
-#define WM_ENABLEOK (WM_USER + 0x2000)
-
 static LRESULT CALLBACK
 WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
+    WCHAR szPath[MAX_PATH];
     CCopyToMenu *this_ =
         reinterpret_cast<CCopyToMenu *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
 
     switch (uMsg)
     {
-        case WM_ENABLEOK:
-            SendMessageW(hwnd, BFFM_ENABLEOK, 0, (BOOL)lParam);
-            return 0;
+        case WM_COMMAND:
+        {
+            switch (LOWORD(wParam))
+            {
+                case IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT:
+                {
+                    if (HIWORD(wParam) == EN_CHANGE)
+                    {
+                        if (!this_->m_bIgnoreTextBoxChange)
+                        {
+                            // get the text
+                            GetDlgItemTextW(hwnd, IDC_BROWSE_FOR_FOLDER_FOLDER_TEXT, szPath, _countof(szPath));
+                            StrTrimW(szPath, L" \t");
+
+                            // update OK button
+                            BOOL bValid = !PathIsRelative(szPath) && PathIsDirectoryW(szPath);
+                            SendMessageW(hwnd, BFFM_ENABLEOK, 0, bValid);
+
+                            return 0;
+                        }
+
+                        // reset flag
+                        this_->m_bIgnoreTextBoxChange = FALSE;
+                    }
+                    break;
+                }
+            }
+            break;
+        }
     }
     return CallWindowProcW(this_->m_fnOldWndProc, hwnd, uMsg, wParam, lParam);
 }
@@ -101,11 +96,14 @@ BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
                     SetWindowLongPtr(hwnd, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(WindowProc)));
 
             // Disable OK
-            PostMessageW(hwnd, WM_ENABLEOK, 0, FALSE);
+            PostMessageW(hwnd, BFFM_ENABLEOK, 0, FALSE);
             break;
         }
         case BFFM_SELCHANGED:
         {
+            if (!this_)
+                break;
+
             WCHAR szPath[MAX_PATH];
             LPCITEMIDLIST pidl = reinterpret_cast<LPCITEMIDLIST>(lParam);
 
@@ -113,11 +111,14 @@ BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
             SHGetPathFromIDListW(pidl, szPath);
 
             if (ILIsEqual(pidl, this_->m_pidlFolder))
-                PostMessageW(hwnd, WM_ENABLEOK, 0, FALSE);
+                PostMessageW(hwnd, BFFM_ENABLEOK, 0, FALSE);
             else if (PathFileExistsW(szPath) || _ILIsDesktop(pidl))
-                PostMessageW(hwnd, WM_ENABLEOK, 0, TRUE);
+                PostMessageW(hwnd, BFFM_ENABLEOK, 0, TRUE);
             else
-                PostMessageW(hwnd, WM_ENABLEOK, 0, FALSE);
+                PostMessageW(hwnd, BFFM_ENABLEOK, 0, FALSE);
+
+            // the text box will be updated later soon, ignore it
+            this_->m_bIgnoreTextBoxChange = TRUE;
             break;
         }
     }
@@ -127,10 +128,9 @@ BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
 
 HRESULT CCopyToMenu::DoRealCopy(LPCMINVOKECOMMANDINFO lpici, LPCITEMIDLIST pidl)
 {
-    CComHeapPtr<CIDA> pCIDA;
-    HRESULT hr = _GetCidlFromDataObject(m_pDataObject, &pCIDA);
-    if (FAILED_UNEXPECTEDLY(hr))
-        return hr;
+    CDataObjectHIDA pCIDA(m_pDataObject);
+    if (FAILED_UNEXPECTEDLY(pCIDA.hr()))
+        return pCIDA.hr();
 
     PCUIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(pCIDA);
     if (!pidlParent)
@@ -181,16 +181,21 @@ HRESULT CCopyToMenu::DoRealCopy(LPCMINVOKECOMMANDINFO lpici, LPCITEMIDLIST pidl)
     op.pFrom = strFiles;
     op.pTo = szPath;
     op.fFlags = FOF_ALLOWUNDO;
-    return ((SHFileOperation(&op) == 0) ? S_OK : E_FAIL);
+    int res = SHFileOperationW(&op);
+    if (res)
+    {
+        ERR("SHFileOperationW failed with 0x%x\n", res);
+        return E_FAIL;
+    }
+    return S_OK;
 }
 
 CStringW CCopyToMenu::DoGetFileTitle()
 {
     CStringW ret = L"(file)";
 
-    CComHeapPtr<CIDA> pCIDA;
-    HRESULT hr = _GetCidlFromDataObject(m_pDataObject, &pCIDA);
-    if (FAILED_UNEXPECTEDLY(hr))
+    CDataObjectHIDA pCIDA(m_pDataObject);
+    if (FAILED_UNEXPECTEDLY(pCIDA.hr()))
         return ret;
 
     PCUIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(pCIDA);