Author: pborobia Date: Fri Sep 1 09:36:36 2006 New Revision: 23855
URL: http://svn.reactos.org/svn/reactos?rev=23855&view=rev Log: * Implement shell32 cut/copy & paste/paste link
Modified: branches/clipboard/dll/win32/shell32/shfldr_fs.c branches/clipboard/dll/win32/shell32/shlfileop.c branches/clipboard/dll/win32/shell32/shv_bg_cmenu.c branches/clipboard/dll/win32/shell32/shv_item_cmenu.c
Modified: branches/clipboard/dll/win32/shell32/shfldr_fs.c URL: http://svn.reactos.org/svn/reactos/branches/clipboard/dll/win32/shell32/shfl... ============================================================================== --- branches/clipboard/dll/win32/shell32/shfldr_fs.c (original) +++ branches/clipboard/dll/win32/shell32/shfldr_fs.c Fri Sep 1 09:36:36 2006 @@ -1,4 +1,3 @@ - /* * file system folder * @@ -54,6 +53,8 @@ #include "shfldr.h"
WINE_DEFAULT_DEBUG_CHANNEL (shell); + +extern BOOL fileMoving;
/*********************************************************************** * IShellFolder implementation @@ -1232,11 +1233,14 @@
IShellFolder_QueryInterface (pSFFrom, &IID_IPersistFolder2, (LPVOID *) & ppf2); - if (ppf2) { + if (ppf2) + { LPITEMIDLIST pidl;
- if (SUCCEEDED (IPersistFolder2_GetCurFolder (ppf2, &pidl))) { - for (i = 0; i < cidl; i++) { + if (SUCCEEDED (IPersistFolder2_GetCurFolder (ppf2, &pidl))) + { + for (i = 0; i < cidl; i++) + { SHGetPathFromIDListA (pidl, szSrcPath); PathAddBackslashA (szSrcPath); _ILSimpleGetText (apidl[i], szSrcPath + strlen (szSrcPath), @@ -1246,7 +1250,43 @@ PathAddBackslashA (szDstPath); _ILSimpleGetText (apidl[i], szDstPath + strlen (szDstPath), MAX_PATH); - MESSAGE ("would copy %s to %s\n", szSrcPath, szDstPath); + _ILSimpleGetText (apidl[i], szDstPath + strlen (szDstPath), MAX_PATH); + DPRINT1 ("copy %s to %s\n", szSrcPath, szDstPath); + + if (fileMoving) + { + fileMoving = FALSE; + SHNotifyMoveFileA(szSrcPath, szDstPath); + } + else + { + SHNotifyCopyFileA(szSrcPath, szDstPath, TRUE); + } + + /* FIXME: to work with folders we need SHFileOperation! + SHFILEOPSTRUCTA op; + + if (fileMoving) + { + op.wFunc = FO_MOVE; + fileMoving = FALSE; + } + else + { + op.wFunc = FO_COPY; + } + + op.pTo = szDstPath; + op.pFrom = szSrcPath; + op.fFlags = FOF_SIMPLEPROGRESS; + op.hwnd = NULL; + op.hNameMappings = NULL; + op.lpszProgressTitle = NULL; + + UINT bRes = SHFileOperationA(&op); + DbgPrint("CopyItems SHFileOperationA 0x%08x\n", bRes); + */ + } SHFree (pidl); }
Modified: branches/clipboard/dll/win32/shell32/shlfileop.c URL: http://svn.reactos.org/svn/reactos/branches/clipboard/dll/win32/shell32/shlf... ============================================================================== --- branches/clipboard/dll/win32/shell32/shlfileop.c (original) +++ branches/clipboard/dll/win32/shell32/shlfileop.c Fri Sep 1 09:36:36 2006 @@ -478,6 +478,65 @@ return GetLastError(); }
+DWORD SHNotifyMoveFileA(LPCSTR src, LPCSTR dest) +{ + BOOL ret; + LPWSTR destW; + + ret = MoveFileA(src, dest); + if (!ret) + { + DWORD dwAttr; + + SHELL32_AnsiToUnicodeBuf(dest, &destW, 0); + dwAttr = SHFindAttrW(destW, FALSE); + SHELL32_FreeUnicodeBuf(destW); + if (INVALID_FILE_ATTRIBUTES == dwAttr) + { + /* Source file may be write protected or a system file */ + dwAttr = GetFileAttributesA(src); + if (IsAttrib(dwAttr, FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM)) + if (SetFileAttributesA(src, dwAttr & ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM))) + ret = MoveFileA(src, dest); + } + } + if (ret) + { + //SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_PATHA, src, dest); + SHChangeNotify(SHCNE_CREATE, SHCNF_PATHA, dest, NULL); + SHChangeNotify(SHCNE_DELETE, SHCNF_PATHA, src, NULL); + return ERROR_SUCCESS; + } + return GetLastError(); +} + +/************************************************************************ + * SHNotifyCopyFile [internal] + * + * Copies a file. Also triggers a change notify if one exists. + * + * PARAMS + * src [I] path to source file to move + * dest [I] path to target file to move to + * bFailIfExists [I] if TRUE, the target file will not be overwritten if + * a file with this name already exists + * + * RETURNS + * ERROR_SUCCESS if successful + */ +DWORD SHNotifyCopyFileA(LPCSTR src, LPCSTR dest, BOOL bFailIfExists) +{ + BOOL ret; + + ret = CopyFileA(src, dest, bFailIfExists); + if (ret) + { + SHChangeNotify(SHCNE_CREATE, SHCNF_PATHA, dest, NULL); + return ERROR_SUCCESS; + } + return GetLastError(); +} + /************************************************************************* * SHCreateDirectory [SHELL32.165] * @@ -649,6 +708,30 @@ } return dwAttr; } + +/* +DWORD SHFindAttrA(LPSTR pName, BOOL fileOnly) +{ + WIN32_FIND_DATAA wfd; + BOOL b_FileMask = fileOnly && (NULL != StrPBrkA(pName, wWildcardChars)); + DWORD dwAttr = INVALID_FILE_ATTRIBUTES; + HANDLE hFind = FindFirstFileA(pName, &wfd); + + if (INVALID_HANDLE_VALUE != hFind) + { + do + { + if (b_FileMask && IsAttribDir(wfd.dwFileAttributes)) + continue; + dwAttr = wfd.dwFileAttributes; + break; + } + while (FindNextFileA(hFind, &wfd)); + FindClose(hFind); + } + return dwAttr; +} +*/
/************************************************************************* *
Modified: branches/clipboard/dll/win32/shell32/shv_bg_cmenu.c URL: http://svn.reactos.org/svn/reactos/branches/clipboard/dll/win32/shell32/shv_... ============================================================================== --- branches/clipboard/dll/win32/shell32/shv_bg_cmenu.c (original) +++ branches/clipboard/dll/win32/shell32/shv_bg_cmenu.c Fri Sep 1 09:36:36 2006 @@ -18,6 +18,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + #include <string.h>
#define COBJMACROS @@ -37,6 +38,8 @@ #include "undocshell.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell); + +extern BOOL fileMoving;
/************************************************************************** * IContextMenu Implementation @@ -215,6 +218,192 @@ } }
+/***************************************************************************/ +static BOOL DoLink(LPCSTR pSrcFile, LPCSTR pDstFile) +{ + IShellLinkA *psl = NULL; + IPersistFile *pPf = NULL; + HRESULT hres; + WCHAR widelink[MAX_PATH]; + BOOL ret = FALSE; + + CoInitialize(0); + + hres = CoCreateInstance( &CLSID_ShellLink, + NULL, + CLSCTX_INPROC_SERVER, + &IID_IShellLinkA, + (LPVOID )&psl); + + if(SUCCEEDED(hres)) + { + hres = IShellLinkA_QueryInterface(psl, &IID_IPersistFile, (LPVOID *)&pPf); + if(FAILED(hres)) + { + ERR("failed QueryInterface for IPersistFile %08lx\n", hres); + goto fail; + } + + DPRINT1("shortcut point to %s\n", pSrcFile); + + hres = IShellLinkA_SetPath(psl, pSrcFile); + + if(FAILED(hres)) + { + ERR("failed Set{IDList|Path} %08lx\n", hres); + goto fail; + } + + MultiByteToWideChar(CP_ACP, 0, pDstFile, -1, widelink, MAX_PATH); + + /* create the short cut */ + hres = IPersistFile_Save(pPf, widelink, TRUE); + + if(FAILED(hres)) + { + ERR("failed IPersistFile::Save %08lx\n", hres); + IPersistFile_Release(pPf); + IShellLinkA_Release(psl); + goto fail; + } + + hres = IPersistFile_SaveCompleted(pPf, widelink); + IPersistFile_Release(pPf); + IShellLinkA_Release(psl); + DPRINT1("shortcut %s has been created, result=%08lx\n", pDstFile, hres); + ret = TRUE; + } + else + { + DPRINT1("CoCreateInstance failed, hres=%08lx\n", hres); + } + + fail: + CoUninitialize(); + return ret; +} + +static BOOL MakeLink(IContextMenu2 *iface) +{ + + BgCmImpl *This = (BgCmImpl *)iface; + BOOL bSuccess = FALSE; + IDataObject * pda; + + TRACE("\n"); + + if(SUCCEEDED(OleGetClipboard(&pda))) + { + STGMEDIUM medium; + FORMATETC formatetc; + + TRACE("pda=%p\n", pda); + + /* Set the FORMATETC structure*/ + InitFormatEtc(formatetc, RegisterClipboardFormatA(CFSTR_SHELLIDLIST), TYMED_HGLOBAL); + + /* Get the pidls from IDataObject */ + if(SUCCEEDED(IDataObject_GetData(pda, &formatetc, &medium))) + { + LPITEMIDLIST * apidl; + LPITEMIDLIST pidl; + IShellFolder *psfFrom = NULL, *psfDesktop; + + LPIDA lpcida = GlobalLock(medium.u.hGlobal); + TRACE("cida=%p\n", lpcida); + + apidl = _ILCopyCidaToaPidl(&pidl, lpcida); + + /* bind to the source shellfolder */ + SHGetDesktopFolder(&psfDesktop); + if(psfDesktop) + { + IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (LPVOID*)&psfFrom); + IShellFolder_Release(psfDesktop); + } + + if (psfFrom) + { + /* get source and destination shellfolder */ + IPersistFolder2 *ppfdst = NULL; + IPersistFolder2 *ppfsrc = NULL; + IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppfdst); + IShellFolder_QueryInterface(psfFrom, &IID_IPersistFolder2, (LPVOID*)&ppfsrc); + + DPRINT1("[%p,%p]\n",ppfdst,ppfsrc); + + /* do the link/s */ + /* hack to get desktop path */ + if ( (ppfdst && ppfsrc) || (This->bDesktop && ppfsrc) ) + { + int i; + char szSrcPath[MAX_PATH]; + char szDstPath[MAX_PATH]; + BOOL ret = FALSE; + LPITEMIDLIST pidl2; + char filename[MAX_PATH]; + char linkFilename[MAX_PATH]; + char srcFilename[MAX_PATH]; + + IPersistFolder2_GetCurFolder(ppfsrc, &pidl2); + SHGetPathFromIDListA (pidl2, szSrcPath); + + if (This->bDesktop) + { + SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, &pidl2); + SHGetPathFromIDListA (pidl2, szDstPath); + } + else + { + IPersistFolder2_GetCurFolder(ppfdst, &pidl2); + SHGetPathFromIDListA (pidl2, szDstPath); + } + + for (i = 0; i < lpcida->cidl; i++) + { + _ILSimpleGetText (apidl[i], filename, MAX_PATH); + + DPRINT1("filename %s\n", filename); + + lstrcpyA(linkFilename, szDstPath); + PathAddBackslashA(linkFilename); + lstrcatA(linkFilename, "Shortcut to "); + lstrcatA(linkFilename, filename); + lstrcatA(linkFilename, ".lnk"); + + DPRINT1("linkFilename %s\n", linkFilename); + + lstrcpyA(srcFilename, szSrcPath); + PathAddBackslashA(srcFilename); + lstrcatA(srcFilename, filename); + + DPRINT1("srcFilename %s\n", srcFilename); + + ret = DoLink(srcFilename, linkFilename); + + if (ret) + { + SHChangeNotify(SHCNE_CREATE, SHCNF_PATHA, linkFilename, NULL); + } + } + } + if(ppfdst) IPersistFolder2_Release(ppfdst); + if(ppfsrc) IPersistFolder2_Release(ppfsrc); + IShellFolder_Release(psfFrom); + } + + _ILFreeaPidl(apidl, lpcida->cidl); + SHFree(pidl); + + /* release the medium*/ + ReleaseStgMedium(&medium); + } + IDataObject_Release(pda); + } + return bSuccess; +} + + /************************************************************************** * DoPaste */ @@ -261,16 +450,27 @@ { /* get source and destination shellfolder */ ISFHelper *psfhlpdst, *psfhlpsrc; - IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlpdst); + + if (This->bDesktop) + { + /* unimplemented + SHGetDesktopFolder(&psfDesktop); + IFSFolder_Constructor(psfDesktop, &IID_ISFHelper, (LPVOID*)&psfhlpdst); + IShellFolder_QueryInterface(psfhlpdst, &IID_ISFHelper, (LPVOID*)&psfhlpdst); + */ + IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlpdst); + } + else + { + IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper, (LPVOID*)&psfhlpdst); + } + IShellFolder_QueryInterface(psfFrom, &IID_ISFHelper, (LPVOID*)&psfhlpsrc);
/* do the copy/move */ if (psfhlpdst && psfhlpsrc) { ISFHelper_CopyItems(psfhlpdst, psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl); - /* FIXME handle move - ISFHelper_DeleteItems(psfhlpsrc, lpcida->cidl, apidl); - */ } if(psfhlpdst) ISFHelper_Release(psfhlpdst); if(psfhlpsrc) ISFHelper_Release(psfhlpsrc); @@ -285,30 +485,7 @@ } IDataObject_Release(pda); } -#if 0 - HGLOBAL hMem; - - OpenClipboard(NULL); - hMem = GetClipboardData(CF_HDROP); - - if(hMem) - { - char * pDropFiles = (char *)GlobalLock(hMem); - if(pDropFiles) - { - int len, offset = sizeof(DROPFILESTRUCT); - - while( pDropFiles[offset] != 0) - { - len = strlen(pDropFiles + offset); - TRACE("%s\n", pDropFiles + offset); - offset += len+1; - } - } - GlobalUnlock(hMem); - } - CloseClipboard(); -#endif + return bSuccess; }
@@ -371,6 +548,10 @@
case FCIDM_SHVIEW_INSERT: DoPaste(iface); + break; + + case FCIDM_SHVIEW_INSERTLINK: + MakeLink(iface); break;
case FCIDM_SHVIEW_PROPERTIES:
Modified: branches/clipboard/dll/win32/shell32/shv_item_cmenu.c URL: http://svn.reactos.org/svn/reactos/branches/clipboard/dll/win32/shell32/shv_... ============================================================================== --- branches/clipboard/dll/win32/shell32/shv_item_cmenu.c (original) +++ branches/clipboard/dll/win32/shell32/shv_item_cmenu.c Fri Sep 1 09:36:36 2006 @@ -39,6 +39,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(shell);
+/* ugly hack for cut&psate files */ +BOOL fileMoving = FALSE; + /************************************************************************** * IContextMenu Implementation */ @@ -372,6 +375,8 @@ LPSHELLBROWSER lpSB; LPSHELLVIEW lpSV; LPDATAOBJECT lpDo; + + fileMoving = bCut;
TRACE("(%p)->(wnd=%p,bCut=0x%08x)\n",This, hwnd, bCut);