Mikołaj Zalewski : shell32: If possible use SHFileOperationW to delete in unixfs.
Alexandre Julliard
julliard at wine.codeweavers.com
Fri Jul 7 11:10:15 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: 4485bf0b617b674ff0f579dbed7b80dd45b9f75f
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=4485bf0b617b674ff0f579dbed7b80dd45b9f75f
Author: Mikołaj Zalewski <mikolaj at zalewski.pl>
Date: Thu Jul 6 20:38:37 2006 +0200
shell32: If possible use SHFileOperationW to delete in unixfs.
This gives confirmation dialogs, recursive directory removal etc.
---
dlls/shell32/shfldr_unixfs.c | 104 ++++++++++++++++++++++++++++++++++++++----
1 files changed, 93 insertions(+), 11 deletions(-)
diff --git a/dlls/shell32/shfldr_unixfs.c b/dlls/shell32/shfldr_unixfs.c
index b74b458..2fd7de5 100644
--- a/dlls/shell32/shfldr_unixfs.c
+++ b/dlls/shell32/shfldr_unixfs.c
@@ -1763,6 +1763,87 @@ static HRESULT WINAPI UnixFolder_ISFHelp
}
}
+/*
+ * Delete specified files by converting the path to DOS paths and calling
+ * SHFileOperationW. If an error occurs it returns an error code. If the paths can't
+ * be converted, S_FALSE is returned. In such situation DeleteItems will try to delete
+ * the files using syscalls
+ */
+static HRESULT UNIXFS_delete_with_shfileop(UnixFolder *This, UINT cidl, LPCITEMIDLIST *apidl)
+{
+ char szAbsolute[FILENAME_MAX], *pszRelative;
+ LPWSTR wszPathsList, wszListPos;
+ SHFILEOPSTRUCTW op;
+ HRESULT ret;
+ int i;
+
+ lstrcpyA(szAbsolute, This->m_pszPath);
+ pszRelative = szAbsolute + lstrlenA(szAbsolute);
+
+ wszListPos = wszPathsList = HeapAlloc(GetProcessHeap(), 0, cidl*MAX_PATH*sizeof(WCHAR)+1);
+ if (wszPathsList == NULL)
+ return E_OUTOFMEMORY;
+ for (i=0; i<cidl; i++) {
+ LPWSTR wszDosPath;
+
+ if (!_ILIsFolder(apidl[i]) && !_ILIsValue(apidl[i]))
+ continue;
+ if (!UNIXFS_filename_from_shitemid(apidl[i], pszRelative))
+ {
+ HeapFree(GetProcessHeap(), 0, wszPathsList);
+ return E_INVALIDARG;
+ }
+ wszDosPath = wine_get_dos_file_name(szAbsolute);
+ if (wszDosPath == NULL || lstrlenW(wszDosPath) >= MAX_PATH)
+ {
+ HeapFree(GetProcessHeap(), 0, wszPathsList);
+ HeapFree(GetProcessHeap(), 0, wszDosPath);
+ return S_FALSE;
+ }
+ lstrcpyW(wszListPos, wszDosPath);
+ wszListPos += lstrlenW(wszListPos)+1;
+ HeapFree(GetProcessHeap(), 0, wszDosPath);
+ }
+ *wszListPos = 0;
+
+ ZeroMemory(&op, sizeof(op));
+ op.hwnd = GetActiveWindow();
+ op.wFunc = FO_DELETE;
+ op.pFrom = wszPathsList;
+ if (!SHFileOperationW(&op))
+ {
+ WARN("SHFileOperationW failed\n");
+ ret = E_FAIL;
+ }
+ else
+ ret = S_OK;
+
+ HeapFree(GetProcessHeap(), 0, wszPathsList);
+ return ret;
+}
+
+static HRESULT UNIXFS_delete_with_syscalls(UnixFolder *This, UINT cidl, LPCITEMIDLIST *apidl)
+{
+ char szAbsolute[FILENAME_MAX], *pszRelative;
+ int i;
+
+ lstrcpyA(szAbsolute, This->m_pszPath);
+ pszRelative = szAbsolute + lstrlenA(szAbsolute);
+
+ for (i=0; i<cidl; i++) {
+ if (!UNIXFS_filename_from_shitemid(apidl[i], pszRelative))
+ return E_INVALIDARG;
+ if (_ILIsFolder(apidl[i])) {
+ if (rmdir(szAbsolute))
+ return E_FAIL;
+ } else if (_ILIsValue(apidl[i])) {
+ if (unlink(szAbsolute))
+ return E_FAIL;
+ }
+ }
+ return S_OK;
+}
+
static HRESULT WINAPI UnixFolder_ISFHelper_DeleteItems(ISFHelper* iface, UINT cidl,
LPCITEMIDLIST* apidl)
{
@@ -1771,26 +1852,27 @@ static HRESULT WINAPI UnixFolder_ISFHelp
LPITEMIDLIST pidlAbsolute;
HRESULT hr = S_OK;
UINT i;
+ struct stat st;
TRACE("(iface=%p, cidl=%d, apidl=%p)\n", iface, cidl, apidl);
+ hr = UNIXFS_delete_with_shfileop(This, cidl, apidl);
+ if (hr == S_FALSE)
+ hr = UNIXFS_delete_with_syscalls(This, cidl, apidl);
+
lstrcpyA(szAbsolute, This->m_pszPath);
pszRelative = szAbsolute + lstrlenA(szAbsolute);
- for (i=0; i<cidl && SUCCEEDED(hr); i++) {
+ /* we need to manually send the notifies if the files doesn't exist */
+ for (i=0; i<cidl; i++) {
if (!UNIXFS_filename_from_shitemid(apidl[i], pszRelative))
- return E_INVALIDARG;
+ continue;
pidlAbsolute = ILCombine(This->m_pidlLocation, apidl[i]);
- if (_ILIsFolder(apidl[i])) {
- if (rmdir(szAbsolute)) {
- hr = E_FAIL;
- } else {
+ if (stat(szAbsolute, &st))
+ {
+ if (_ILIsFolder(apidl[i])) {
SHChangeNotify(SHCNE_RMDIR, SHCNF_IDLIST, pidlAbsolute, NULL);
- }
- } else if (_ILIsValue(apidl[i])) {
- if (unlink(szAbsolute)) {
- hr = E_FAIL;
- } else {
+ } else if (_ILIsValue(apidl[i])) {
SHChangeNotify(SHCNE_DELETE, SHCNF_IDLIST, pidlAbsolute, NULL);
}
}
More information about the wine-cvs
mailing list