Reactos

[SHELL32] Add SHFileOp error UI and use it for CFSFolder renaming (#7858)

authored by

Whindmar Saksit and committed by
GitHub
ac3ecb2b 774b3a6e

+225 -84
+3 -2
dll/win32/shell32/CDefView.cpp
··· 2821 2821 } 2822 2822 2823 2823 WCHAR szName[MAX_PATH], *pszText = lpdi->item.pszText; 2824 - if (SUCCEEDED(Shell_DisplayNameOf(m_pSFParent, pidl, SHGDN_FOREDITING | SHGDN_INFOLDER, 2825 - szName, _countof(szName)))) 2824 + if (SUCCEEDED(DisplayNameOfW(m_pSFParent, pidl, SHGDN_FOREDITING | SHGDN_INFOLDER, 2825 + szName, _countof(szName)))) 2826 2826 { 2827 2827 pszText = szName; 2828 2828 ::SetWindowText(hEdit, pszText); ··· 2875 2875 ILFree(pidlNew);// A SHCNE has updated the item already 2876 2876 else if (!LV_UpdateItem(lpdi->item.iItem, pidlNew)) 2877 2877 ILFree(pidlNew); 2878 + OnStateChange(CDBOSC_RENAME); 2878 2879 } 2879 2880 else 2880 2881 {
+1 -1
dll/win32/shell32/droptargets/CFSDropTarget.cpp
··· 622 622 // If the target is a virtual item, we ask for the friendly name because SHGDN_FORPARSING will return a GUID. 623 623 BOOL UseParsing = (att & (SFGAO_FILESYSTEM | SFGAO_FOLDER)) == SFGAO_FILESYSTEM; 624 624 DWORD ShgdnFor = UseParsing ? SHGDN_FORPARSING : SHGDN_FOREDITING; 625 - hr = Shell_DisplayNameOf(psfFrom, apidl[i], ShgdnFor | SHGDN_INFOLDER, targetName, _countof(targetName)); 625 + hr = DisplayNameOfW(psfFrom, apidl[i], ShgdnFor | SHGDN_INFOLDER, targetName, _countof(targetName)); 626 626 } 627 627 if (FAILED_UNEXPECTEDLY(hr)) 628 628 {
+7 -9
dll/win32/shell32/folders/CFSFolder.cpp
··· 1558 1558 PITEMID_CHILD *pPidlOut) 1559 1559 { 1560 1560 WCHAR szSrc[MAX_PATH + 1], szDest[MAX_PATH + 1], szNameBuf[MAX_PATH]; 1561 - BOOL bIsFolder = _ILIsFolder (ILFindLastID (pidl)); 1561 + BOOL bIsFolder = ItemIsFolder(ILFindLastID(pidl)); 1562 1562 1563 1563 TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner, pidl, 1564 1564 debugstr_w (lpName), dwFlags, pPidlOut); 1565 + 1566 + if (pPidlOut) 1567 + *pPidlOut = NULL; 1565 1568 1566 1569 LPCWSTR pszName = GetItemFileName(pidl, szNameBuf, _countof(szNameBuf)); 1567 1570 if (!pszName) ··· 1595 1598 if (pPidlOut) 1596 1599 hr = SHILClone(pidl, pPidlOut); 1597 1600 } 1598 - else if (MoveFileW(szSrc, szDest)) 1601 + else 1599 1602 { 1600 - if (pPidlOut) 1603 + hr = SHELL_SingleFileOperation(hwndOwner, FO_RENAME, szSrc, szDest, FOF_SILENT | FOF_ALLOWUNDO, NULL); 1604 + if (SUCCEEDED(hr) && pPidlOut) 1601 1605 hr = ParseDisplayName(hwndOwner, NULL, PathFindFileNameW(szDest), NULL, pPidlOut, NULL); 1602 - 1603 - SHChangeNotify(bIsFolder ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM, SHCNF_PATHW, szSrc, szDest); 1604 - } 1605 - else 1606 - { 1607 - hr = HResultFromWin32(GetLastError()); 1608 1606 } 1609 1607 return hr; 1610 1608 }
+5 -13
dll/win32/shell32/folders/CRecycleBin.cpp
··· 510 510 typedef struct _FILEOPDATA 511 511 { 512 512 PCUITEMID_CHILD_ARRAY apidl; 513 - UINT cidl, index; 514 - BBITEMDATA *pItem; 513 + UINT cidl; 515 514 } FILEOPDATA; 516 515 517 516 static HRESULT CALLBACK FileOpCallback(FILEOPCALLBACKEVENT Event, LPCWSTR Src, LPCWSTR Dst, UINT Attrib, HRESULT hrOp, void *CallerData) 518 517 { 519 518 FILEOPDATA &data = *(FILEOPDATA*)CallerData; 520 - if (Event == FOCE_PREMOVEITEM || Event == FOCE_PREDELETEITEM) 519 + if ((Event == FOCE_POSTDELETEITEM || Event == FOCE_POSTMOVEITEM) && SUCCEEDED(hrOp)) 521 520 { 522 - data.pItem = NULL; 523 521 for (UINT i = 0; i < data.cidl; ++i) 524 522 { 525 523 BBITEMDATA *pItem = ValidateItem(data.apidl[i]); 526 524 if (pItem && !_wcsicmp(Src, GetItemRecycledFullPath(*pItem))) 527 525 { 528 - data.pItem = pItem; 529 - data.index = i; 526 + RECYCLEBINFILEIDENTITY identity = { pItem->DeletionTime, GetItemRecycledFullPath(*pItem) }; 527 + RemoveFromRecycleBinDatabase(&identity); 528 + CRecycleBin_NotifyRemovedFromRecycleBin(data.apidl[i]); 530 529 break; 531 530 } 532 531 } 533 - } 534 - else if ((Event == FOCE_POSTDELETEITEM || Event == FOCE_POSTMOVEITEM) && SUCCEEDED(hrOp) && data.pItem) 535 - { 536 - RECYCLEBINFILEIDENTITY identity = { data.pItem->DeletionTime, GetItemRecycledFullPath(*data.pItem) }; 537 - RemoveFromRecycleBinDatabase(&identity); 538 - CRecycleBin_NotifyRemovedFromRecycleBin(data.apidl[data.index]); 539 - data.pItem = NULL; 540 532 } 541 533 else if (Event == FOCE_FINISHOPERATIONS) 542 534 {
+8 -9
dll/win32/shell32/precomp.h
··· 242 242 EXTERN_C INT 243 243 Shell_ParseSpecialFolder(_In_ LPCWSTR pszStart, _Out_ LPWSTR *ppch, _Out_ INT *pcch); 244 244 245 - HRESULT 246 - Shell_DisplayNameOf( 247 - _In_ IShellFolder *psf, 248 - _In_ LPCITEMIDLIST pidl, 249 - _In_ DWORD dwFlags, 250 - _Out_ LPWSTR pszBuf, 251 - _In_ UINT cchBuf); 252 - 253 245 EXTERN_C 254 246 HRESULT SHBindToObject( 255 247 _In_opt_ IShellFolder *psf, ··· 331 323 FOCE_FINISHOPERATIONS, 332 324 FOCE_PREMOVEITEM, 333 325 FOCE_POSTMOVEITEM, 326 + FOCE_PRECOPYITEM, 327 + FOCE_POSTCOPYITEM, 334 328 FOCE_PREDELETEITEM, 335 - FOCE_POSTDELETEITEM 329 + FOCE_POSTDELETEITEM, 330 + FOCE_PRERENAMEITEM, 331 + FOCE_POSTRENAMEITEM, 332 + FOCE_PRENEWITEM, 333 + FOCE_POSTNEWITEM 336 334 } FILEOPCALLBACKEVENT; 337 335 typedef HRESULT (CALLBACK *FILEOPCALLBACK)(FILEOPCALLBACKEVENT Event, LPCWSTR Source, LPCWSTR Destination, 338 336 UINT Attributes, HRESULT hr, void *CallerData); 339 337 int SHELL32_FileOperation(LPSHFILEOPSTRUCTW lpFileOp, FILEOPCALLBACK Callback, void *CallerData); 338 + HRESULT SHELL_SingleFileOperation(HWND hWnd, UINT Op, PCWSTR Src, PCWSTR Dest, UINT Flags, PWSTR *ppNewName); 340 339 341 340 #endif /* _PRECOMP_H__ */
+1
dll/win32/shell32/shell32.spec
··· 466 466 754 stub -noname SHLimitInputEditWithFlags 467 467 755 stdcall -noname PathIsEqualOrSubFolder(wstr wstr) 468 468 756 stub -noname DeleteFileThumbnail 469 + 757 stdcall -version=0x600+ DisplayNameOfW(ptr ptr long ptr long)
+175 -41
dll/win32/shell32/shlfileop.cpp
··· 47 47 WCHAR szBuilderString[50]; 48 48 FILEOPCALLBACK Callback; 49 49 void *CallerCallbackData; 50 + HWND hWndOwner; 51 + BOOL bHasDisplayedError; 50 52 } FILE_OPERATION; 51 53 52 54 #define ERROR_SHELL_INTERNAL_FILE_NOT_FOUND 1026 ··· 83 85 84 86 DWORD WINAPI _FileOpCountManager(FILE_OPERATION *op, const FILE_LIST *flFrom); 85 87 static BOOL _FileOpCount(FILE_OPERATION *op, LPWSTR pwszBuf, BOOL bFolder, DWORD *ticks); 88 + 89 + static HRESULT SHELL32_FileOpErrorToHResult(int err, BOOL AnyOperationsAborted = FALSE) 90 + { 91 + enum { de_min = DE_SAMEFILE, de_max = 0xB7 /*DE_ERROR_MAX*/ }; 92 + const bool IsDeErr = (err & ~ERRORONDEST) >= de_min && (err & ~ERRORONDEST) <= de_max; 93 + if (err == DE_OPCANCELLED || AnyOperationsAborted) 94 + return HRESULT_FROM_WIN32(ERROR_CANCELLED); 95 + if (err == DE_ACCESSDENIEDSRC) 96 + return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED); 97 + if (err == DE_FILENAMETOOLONG) 98 + return HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE); 99 + if (err == ERROR_SHELL_INTERNAL_FILE_NOT_FOUND) 100 + return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 101 + if (err == ERROR_ALREADY_EXISTS) 102 + return HRESULT_FROM_WIN32(err); 103 + return IsDeErr ? E_FAIL : HRESULT_FROM_WIN32(err); 104 + } 105 + 106 + static BOOL CanShowFileOpErrorUI(const SHFILEOPSTRUCTW &fos) 107 + { 108 + if ((fos.fFlags & FOF_SILENT) && !fos.hwnd) 109 + return FALSE; 110 + return !(fos.fFlags & FOF_NOERRORUI); 111 + } 112 + 113 + static void HandleDesktopIniOp(PCWSTR Path) 114 + { 115 + // Refresh the parent folder if somebody changes the desktop.ini inside 116 + PCWSTR Name = PathFindFileNameW(Path); 117 + if ((Name[0] | 32) != 'd' || _wcsicmp(Name, L"desktop.ini")) 118 + return; 119 + WCHAR Dir[MAX_PATH]; 120 + if (FAILED_UNEXPECTEDLY(StringCchCopyW(Dir, _countof(Dir), Path))) 121 + return; 122 + PathRemoveFileSpecW(Dir); 123 + if (!(GetFileAttributesW(Dir) & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY))) 124 + return; 125 + SHChangeNotify(SHCNE_UPDATEITEM, SHCNF_PATHW, Dir, NULL); 126 + } 86 127 87 128 /* Confirm dialogs with an optional "Yes To All" as used in file operations confirmations 88 129 */ ··· 366 407 static HRESULT FileOpCallback(FILE_OPERATION *op, FILEOPCALLBACKEVENT Event, LPCWSTR Source, 367 408 LPCWSTR Destination, UINT Attributes, HRESULT hrOp = S_OK) 368 409 { 410 + if ((Attributes & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM)) == FILE_ATTRIBUTE_SYSTEM) 411 + { 412 + if (Event == FOCE_POSTDELETEITEM) 413 + HandleDesktopIniOp(Source); 414 + if (Event == FOCE_POSTCOPYITEM) 415 + HandleDesktopIniOp(Destination); 416 + if (Event == FOCE_POSTMOVEITEM || Event == FOCE_POSTRENAMEITEM) 417 + { 418 + HandleDesktopIniOp(Source); 419 + HandleDesktopIniOp(Destination); 420 + } 421 + } 422 + 369 423 HRESULT hr = S_OK; 370 424 if (op->Callback) 371 425 { ··· 398 452 if (FAILED(FileOpCallback(op, FOCE_PREDELETEITEM, pszDir, NULL, wfd.dwFileAttributes))) 399 453 return FALSE; 400 454 401 - if (!bShowUI || (ret = SHELL_ConfirmDialogW(op->req->hwnd, ASK_DELETE_FOLDER, pszDir, NULL))) 455 + if (!bShowUI || (ret = SHELL_ConfirmDialogW(op->hWndOwner, ASK_DELETE_FOLDER, pszDir, NULL))) 402 456 { 403 457 do 404 458 { ··· 699 753 CStringW strTitle, strMask, strText; 700 754 LPWSTR lpMsgBuffer; 701 755 702 - if (error == ERROR_SUCCESS || (op->req->fFlags & (FOF_NOERRORUI | FOF_SILENT))) 703 - goto exit; 756 + if (error == ERROR_SUCCESS || !CanShowFileOpErrorUI(*op->req)) 757 + return error; 704 758 705 759 strTitle.LoadStringW(op->req->wFunc == FO_COPY ? IDS_COPYERRORTITLE : IDS_MOVEERRORTITLE); 706 760 ··· 716 770 PathFindFileNameW(src), 717 771 lpMsgBuffer); 718 772 719 - MessageBoxW(op->req->hwnd, strText, strTitle, MB_ICONERROR); 773 + MessageBoxW(op->hWndOwner, strText, strTitle, MB_ICONERROR); 720 774 LocalFree(lpMsgBuffer); 721 - 722 - exit: 775 + op->bHasDisplayedError++; 723 776 return error; 724 777 } 725 778 ··· 744 797 745 798 _SetOperationTexts(op, src, dest); 746 799 747 - UINT attrib = isdir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL; 748 - if (FAILED(FileOpCallback(op, FOCE_PREMOVEITEM, src, dest, attrib))) 800 + const BOOL IsRen = op->req->wFunc == FO_RENAME; 801 + UINT attrib = GetFileAttributesW(src); 802 + if (attrib == INVALID_FILE_ATTRIBUTES) 803 + attrib = isdir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL; 804 + if (FAILED(FileOpCallback(op, IsRen ? FOCE_PRERENAMEITEM : FOCE_PREMOVEITEM, src, dest, attrib))) 749 805 return ERROR_CANCELLED; 750 806 751 807 ret = MoveFileWithProgressW(src, dest, SHCopyProgressRoutine, op, MOVEFILE_REPLACE_EXISTING); ··· 753 809 /* MOVEFILE_REPLACE_EXISTING fails with dirs, so try MoveFile */ 754 810 if (!ret) 755 811 ret = MoveFileW(src, dest); 812 + DWORD LastError = GetLastError(); 756 813 757 814 if (!ret) 758 815 { 759 - DWORD dwAttr; 760 - 761 - dwAttr = SHFindAttrW(dest, FALSE); 762 - if (INVALID_FILE_ATTRIBUTES == dwAttr) 763 - { 764 - /* Source file may be write protected or a system file */ 765 - dwAttr = GetFileAttributesW(src); 766 - if (IsAttrib(dwAttr, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)) 767 - if (SetFileAttributesW(src, dwAttr & ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM))) 768 - ret = MoveFileW(src, dest); 769 - } 816 + DWORD dwAttr = SHFindAttrW(dest, FALSE); 817 + if (INVALID_FILE_ATTRIBUTES == dwAttr) 818 + { 819 + /* Source file may be write protected or a system file */ 820 + dwAttr = GetFileAttributesW(src); 821 + if (IsAttrib(dwAttr, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)) 822 + { 823 + if (SetFileAttributesW(src, dwAttr & ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM))) 824 + { 825 + ret = MoveFileW(src, dest); 826 + LastError = GetLastError(); 827 + SetFileAttributesW(ret ? dest : src, dwAttr); 828 + } 829 + } 830 + } 770 831 } 771 - FileOpCallback(op, FOCE_POSTMOVEITEM, src, dest, attrib, ret ? S_OK : E_FAIL); 832 + FileOpCallback(op, IsRen ? FOCE_POSTRENAMEITEM : FOCE_POSTMOVEITEM, src, dest, attrib, ret ? S_OK : E_FAIL); 772 833 if (ret) 773 834 { 774 - SHChangeNotify(isdir ? SHCNE_MKDIR : SHCNE_CREATE, SHCNF_PATHW, dest, NULL); 775 - SHChangeNotify(isdir ? SHCNE_RMDIR : SHCNE_DELETE, SHCNF_PATHW, src, NULL); 835 + if (IsRen) 836 + { 837 + SHChangeNotify(isdir ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM, SHCNF_PATHW, src, dest); 838 + } 839 + else 840 + { 841 + SHChangeNotify(isdir ? SHCNE_MKDIR : SHCNE_CREATE, SHCNF_PATHW, dest, NULL); 842 + SHChangeNotify(isdir ? SHCNE_RMDIR : SHCNE_DELETE, SHCNF_PATHW, src, NULL); 843 + } 776 844 return ERROR_SUCCESS; 777 845 } 778 - 779 - return CheckForError(op, GetLastError(), src); 846 + return CheckForError(op, LastError, src); 780 847 } 781 848 782 849 static BOOL SHIsCdRom(LPCWSTR path) ··· 819 886 820 887 /* Destination file may already exist with read only attribute */ 821 888 attribs = GetFileAttributesW(dest); 889 + if (FAILED(FileOpCallback(op, FOCE_PRECOPYITEM, src, dest, attribs))) 890 + return ERROR_CANCELLED; 891 + 822 892 if (IsAttrib(attribs, FILE_ATTRIBUTE_READONLY)) 823 893 SetFileAttributesW(dest, attribs & ~FILE_ATTRIBUTE_READONLY); 824 894 ··· 832 902 } 833 903 834 904 ret = CopyFileExW(src, dest, SHCopyProgressRoutine, op, &op->bCancelled, bFailIfExists); 835 - if (ret) 905 + const DWORD error = ret ? 0 : GetLastError(); 906 + FileOpCallback(op, FOCE_POSTCOPYITEM, src, dest, attribs, HRESULT_FROM_WIN32(error)); 907 + if (!error) 836 908 { 837 909 // We are copying from a CD-ROM volume, which is readonly 838 910 if (SHIsCdRom(src)) ··· 845 917 SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, dest, NULL); 846 918 return ERROR_SUCCESS; 847 919 } 848 - 849 - return CheckForError(op, GetLastError(), src); 920 + return CheckForError(op, error, src); 850 921 } 851 922 852 923 /************************************************************************* ··· 1376 1447 } 1377 1448 else if (!(op->req->fFlags & FOF_NOCONFIRMATION)) 1378 1449 { 1379 - if (!SHELL_ConfirmDialogW(op->req->hwnd, ASK_OVERWRITE_FOLDER, feFrom->szFilename, op)) 1450 + if (!SHELL_ConfirmDialogW(op->hWndOwner, ASK_OVERWRITE_FOLDER, feFrom->szFilename, op)) 1380 1451 { 1381 1452 /* Vista returns an ERROR_CANCELLED even if user pressed "No" */ 1382 1453 if (!op->bManyItems) ··· 1417 1488 } 1418 1489 else if (!(op->req->fFlags & FOF_NOCONFIRMATION)) 1419 1490 { 1420 - if (!SHELL_ConfirmDialogW(op->req->hwnd, ASK_OVERWRITE_FILE, PathFindFileNameW(szTo), op)) 1491 + if (!SHELL_ConfirmDialogW(op->hWndOwner, ASK_OVERWRITE_FILE, PathFindFileNameW(szTo), op)) 1421 1492 return FALSE; 1422 1493 } 1423 1494 } ··· 1629 1700 if (bTrash && SHELL_GetSetting(SSF_NOCONFIRMRECYCLE, fNoConfirmRecycle)) 1630 1701 confirm = FALSE; 1631 1702 if (confirm || (!bTrash && op->req->fFlags & FOF_WANTNUKEWARNING)) 1632 - if (!confirm_delete_list(op->req->hwnd, op->req->fFlags, bTrash, flFrom)) 1703 + if (!confirm_delete_list(op->hWndOwner, op->req->fFlags, bTrash, flFrom)) 1633 1704 { 1634 1705 op->req->fAnyOperationsAborted = TRUE; 1635 1706 return 0; ··· 1669 1740 1670 1741 /* Note: Windows silently deletes the file in such a situation, we show a dialog */ 1671 1742 if (!(op->req->fFlags & FOF_NOCONFIRMATION) || (op->req->fFlags & FOF_WANTNUKEWARNING)) 1672 - bDelete = SHELL_ConfirmDialogW(op->req->hwnd, ASK_CANT_TRASH_ITEM, fileEntry->szFullPath, NULL); 1743 + bDelete = SHELL_ConfirmDialogW(op->hWndOwner, ASK_CANT_TRASH_ITEM, fileEntry->szFullPath, NULL); 1673 1744 else 1674 1745 bDelete = TRUE; 1675 1746 ··· 1762 1833 } 1763 1834 else if (!(op->req->fFlags & FOF_NOCONFIRMATION)) 1764 1835 { 1765 - if (!SHELL_ConfirmDialogW(op->req->hwnd, ASK_OVERWRITE_FILE, PathFindFileNameW(szTo), op)) 1836 + if (!SHELL_ConfirmDialogW(op->hWndOwner, ASK_OVERWRITE_FILE, PathFindFileNameW(szTo), op)) 1766 1837 return FALSE; 1767 1838 } 1768 1839 } ··· 1924 1995 #define GET_FILENAME(fe) ((fe)->szFilename[0] ? (fe)->szFilename : (fe)->szFullPath) 1925 1996 1926 1997 static DWORD 1927 - validate_operation(LPSHFILEOPSTRUCTW lpFileOp, FILE_LIST *flFrom, FILE_LIST *flTo) 1998 + validate_operation(FILE_OPERATION &op, FILE_LIST *flFrom, FILE_LIST *flTo) 1928 1999 { 1929 2000 DWORD i, k, dwNumDest; 1930 2001 WCHAR szFrom[MAX_PATH], szTo[MAX_PATH]; 1931 2002 CStringW strTitle, strText; 1932 2003 const FILE_ENTRY *feFrom; 1933 2004 const FILE_ENTRY *feTo; 2005 + const SHFILEOPSTRUCTW *lpFileOp = op.req; 1934 2006 UINT wFunc = lpFileOp->wFunc; 1935 - HWND hwnd = lpFileOp->hwnd; 1936 2007 1937 2008 dwNumDest = flTo->dwNumFiles; 1938 2009 ··· 1956 2027 if (lstrcmpiW(szFrom, szTo) == 0 && 1957 2028 (wFunc == FO_MOVE || !(lpFileOp->fFlags & FOF_RENAMEONCOLLISION))) 1958 2029 { 1959 - if (!(lpFileOp->fFlags & (FOF_NOERRORUI | FOF_SILENT))) 2030 + if (CanShowFileOpErrorUI(*lpFileOp)) 1960 2031 { 1961 2032 if (wFunc == FO_MOVE) 1962 2033 { ··· 1972 2043 strText.Format(IDS_COPYERRORSAME, GET_FILENAME(feFrom)); 1973 2044 return ERROR_SUCCESS; 1974 2045 } 1975 - MessageBoxW(hwnd, strText, strTitle, MB_ICONERROR); 2046 + MessageBoxW(op.hWndOwner, strText, strTitle, MB_ICONERROR); 2047 + op.bHasDisplayedError++; 1976 2048 return DE_SAMEFILE; 1977 2049 } 1978 2050 return DE_OPCANCELLED; ··· 1992 2064 1993 2065 if (compare == 0) 1994 2066 { 1995 - if (!(lpFileOp->fFlags & (FOF_NOERRORUI | FOF_SILENT))) 2067 + if (CanShowFileOpErrorUI(*lpFileOp)) 1996 2068 { 1997 2069 if (wFunc == FO_MOVE) 1998 2070 { ··· 2004 2076 strTitle.LoadStringW(IDS_COPYERRORTITLE); 2005 2077 strText.Format(IDS_COPYERRORSUBFOLDER, GET_FILENAME(feFrom)); 2006 2078 } 2007 - MessageBoxW(hwnd, strText, strTitle, MB_ICONERROR); 2079 + MessageBoxW(op.hWndOwner, strText, strTitle, MB_ICONERROR); 2080 + op.bHasDisplayedError++; 2008 2081 return DE_DESTSUBTREE; 2009 2082 } 2010 2083 return DE_OPCANCELLED; ··· 2049 2122 op.bManyItems = (flFrom.dwNumFiles > 1); 2050 2123 op.Callback = Callback; 2051 2124 op.CallerCallbackData = CallerData; 2125 + op.hWndOwner = GetAncestor(lpFileOp->hwnd, GA_ROOT); 2052 2126 2053 - ret = validate_operation(lpFileOp, &flFrom, &flTo); 2127 + ret = validate_operation(op, &flFrom, &flTo); 2054 2128 if (ret) 2055 2129 goto cleanup; 2056 2130 ··· 2062 2136 if (FAILED(ret)) 2063 2137 goto cleanup; 2064 2138 2065 - op.progress->StartProgressDialog(op.req->hwnd, NULL, PROGDLG_NORMAL & PROGDLG_AUTOTIME, NULL); 2139 + op.progress->StartProgressDialog(op.hWndOwner, NULL, PROGDLG_NORMAL & PROGDLG_AUTOTIME, NULL); 2066 2140 _SetOperationTitle(&op); 2067 2141 _FileOpCountManager(&op, &flFrom); 2068 2142 } ··· 2103 2177 2104 2178 if (ret == ERROR_CANCELLED) 2105 2179 lpFileOp->fAnyOperationsAborted = TRUE; 2180 + if (ret == ERROR_SHELL_INTERNAL_FILE_NOT_FOUND && LOBYTE(GetVersion()) >= 6) 2181 + ret = ERROR_FILE_NOT_FOUND; 2106 2182 2107 - FileOpCallback(&op, FOCE_FINISHOPERATIONS, NULL, NULL, 0, HRESULT_FROM_WIN32(ret)); 2183 + HRESULT hr = SHELL32_FileOpErrorToHResult(ret); 2184 + TRACE("SHFO FINISHOPERATIONS %#x (%d)\n", hr, ret); 2185 + FileOpCallback(&op, FOCE_FINISHOPERATIONS, NULL, NULL, 0, hr); 2186 + 2187 + if (FAILED(hr) && CanShowFileOpErrorUI(*op.req) && !op.bHasDisplayedError) 2188 + SHELL_ErrorBox(op.hWndOwner, hr); 2108 2189 2109 2190 CoUninitialize(); 2110 2191 ··· 2348 2429 WCHAR wpath[MAX_PATH]; 2349 2430 MultiByteToWideChar( CP_ACP, 0, path, -1, wpath, MAX_PATH); 2350 2431 return SHPathPrepareForWriteW(hwnd, modless, wpath, flags); 2432 + } 2433 + 2434 + static PWSTR SHELL_DupSZZ(PCWSTR Input) 2435 + { 2436 + SIZE_T len = wcslen(Input), cb = (len + 2) * sizeof(*Input); 2437 + PWSTR Output = (PWSTR)SHAlloc(cb); 2438 + if (Output) 2439 + { 2440 + CopyMemory(Output, Input, cb - sizeof(*Input)); 2441 + Output[len + 1] = UNICODE_NULL; 2442 + } 2443 + return Output; 2444 + } 2445 + 2446 + HRESULT SHELL_SingleFileOperation(HWND hWnd, UINT Op, PCWSTR Src, PCWSTR Dest, UINT Flags, PWSTR *ppNewName) 2447 + { 2448 + HRESULT hr = S_OK; 2449 + if ((Src = SHELL_DupSZZ(Src)) == NULL) 2450 + hr = E_OUTOFMEMORY; 2451 + if (Dest && (Dest = SHELL_DupSZZ(Dest)) == NULL) 2452 + hr = E_OUTOFMEMORY; 2453 + 2454 + SHFILEOPSTRUCTW fos = { hWnd, Op, Src, Dest, (FILEOP_FLAGS)Flags }; 2455 + if (ppNewName) 2456 + { 2457 + *ppNewName = NULL; 2458 + fos.fFlags |= FOF_WANTMAPPINGHANDLE; 2459 + } 2460 + 2461 + if (SUCCEEDED(hr)) 2462 + { 2463 + int err = SHFileOperationW(&fos); 2464 + hr = SHELL32_FileOpErrorToHResult(err, fos.fAnyOperationsAborted); 2465 + } 2466 + else if (CanShowFileOpErrorUI(fos)) 2467 + { 2468 + SHELL_ErrorBox(hWnd, hr); 2469 + } 2470 + SHFree(const_cast<PWSTR>(Src)); 2471 + SHFree(const_cast<PWSTR>(Dest)); 2472 + 2473 + if (fos.hNameMappings) 2474 + { 2475 + if (SUCCEEDED(hr) && ppNewName) 2476 + { 2477 + assert(DSA_GetItemCount((HDSA)fos.hNameMappings) == 1); 2478 + SHNAMEMAPPINGW *pMap = (SHNAMEMAPPINGW*)DSA_GetItemPtr((HDSA)fos.hNameMappings, 0); 2479 + if ((*ppNewName = SHELL_DupSZZ(pMap->pszNewPath)) == NULL) 2480 + hr = S_FALSE; 2481 + } 2482 + SHFreeNameMappings(fos.hNameMappings); 2483 + } 2484 + return hr; 2351 2485 } 2352 2486 2353 2487
+6 -3
dll/win32/shell32/utils.cpp
··· 402 402 return hr; 403 403 } 404 404 405 - HRESULT 406 - Shell_DisplayNameOf( 405 + /*********************************************************************** 406 + * DisplayNameOfW [SHELL32.757] (Vista+) 407 + */ 408 + EXTERN_C HRESULT WINAPI 409 + DisplayNameOfW( 407 410 _In_ IShellFolder *psf, 408 411 _In_ LPCITEMIDLIST pidl, 409 412 _In_ DWORD dwFlags, ··· 492 495 if (SUCCEEDED(hr)) 493 496 { 494 497 if (pszText) 495 - hr = Shell_DisplayNameOf(psfFolder, ppidlLast, dwFlags, pszText, cchBuf); 498 + hr = DisplayNameOfW(psfFolder, ppidlLast, dwFlags, pszText, cchBuf); 496 499 497 500 if (SUCCEEDED(hr)) 498 501 {
+1 -6
dll/win32/shimgvw/shimgvw.c
··· 1392 1392 FileOp.pFrom = szCurFile; 1393 1393 FileOp.fFlags = GetKeyState(VK_SHIFT) < 0 ? 0 : FOF_ALLOWUNDO; 1394 1394 error = g_szFile[0] ? SHFileOperationW(&FileOp) : ERROR_FILE_NOT_FOUND; 1395 - if (error != 0) 1396 - { 1397 - enum { SHFO_FIRSTCUSTOMERROR = 0x71 /* DE_SAMEFILE */ }; 1398 - if (!FileOp.fAnyOperationsAborted && error != ERROR_CANCELLED) 1399 - ErrorBox(FileOp.hwnd, error < SHFO_FIRSTCUSTOMERROR ? error : E_FAIL); 1395 + if (error) 1400 1396 return; 1401 - } 1402 1397 1403 1398 /* Reload the file list and go next file */ 1404 1399 pFreeFileList(g_pCurrentFile);
+18
sdk/include/reactos/undocshell.h
··· 19 19 #ifndef __WINE_UNDOCSHELL_H 20 20 #define __WINE_UNDOCSHELL_H 21 21 22 + #ifndef SHSTDAPI 23 + #if defined(_SHELL32_) /* DECLSPEC_IMPORT disabled because of CORE-6504: */ || TRUE 24 + #define SHSTDAPI_(type) type WINAPI 25 + #else 26 + #define SHSTDAPI_(type) EXTERN_C DECLSPEC_IMPORT type WINAPI 27 + #endif 28 + #define SHSTDAPI SHSTDAPI_(HRESULT) 29 + #endif 30 + 22 31 #ifdef __cplusplus 23 32 extern "C" { 24 33 #endif /* defined(__cplusplus) */ ··· 77 86 LPCITEMIDLIST pidl, 78 87 LPVOID path, 79 88 DWORD type); 89 + 90 + #if (NTDDI_VERSION >= NTDDI_LONGHORN) || defined(_SHELL32_) 91 + SHSTDAPI DisplayNameOfW( 92 + _In_ IShellFolder *psf, 93 + _In_ LPCITEMIDLIST pidl, 94 + _In_ DWORD dwFlags, 95 + _Out_ LPWSTR pszBuf, 96 + _In_ UINT cchBuf); 97 + #endif 80 98 81 99 LPITEMIDLIST WINAPI ILGlobalClone(LPCITEMIDLIST pidl); 82 100 void WINAPI ILGlobalFree(LPITEMIDLIST pidl);