diff --git a/reactos/boot/bootdata/hivecls.inf b/reactos/boot/bootdata/hivecls.inf index 98071809b98..10db21badfd 100644 --- a/reactos/boot/bootdata/hivecls.inf +++ b/reactos/boot/bootdata/hivecls.inf @@ -100,6 +100,7 @@ HKCR,"exefile","FriendlyTypeName",0x00020000,"@%SystemRoot%\system32\shell32.dll HKCR,"exefile\Defaulticon","",0x00000000,"%1" HKCR,"exefile\shell\open\command","",0x00000000,"""%1"" %*" HKCR,"exefile\shell\runas\command","",0x00020000,"""%1"" %*" +HKCR,"exefile\shellex\DropHandler","",0x00020000,"{86C86720-42A0-1069-A2E8-08002B30309D}" ; Fonts HKCR,".fon","",0x00000000,"fonfile" @@ -191,6 +192,7 @@ HKCR,"lnkfile","NeverShowExt",0x00000000,"" HKCR,"lnkfile","IsShortcut",0x00000000,"yes" HKCR,"lnkfile\CLSID","",0x00000000,"{00021401-0000-0000-C000-000000000046}" HKCR,"lnkfile\shellex\IconHandler","",0x00000000,"{00021401-0000-0000-C000-000000000046}" +HKCR,"lnkfile\shellex\DropHandler","",0x00000000,"{00021401-0000-0000-C000-000000000046}" HKCR,"lnkfile\shellex\ContextMenuHandlers\{00021401-0000-0000-C000-000000000046}","",0x00000000,"" HKCR,"lnkfile\shellex\PropertySheetHandlers\Shellink Property Page", "", 0x00000000, "{00021401-0000-0000-C000-000000000046}" diff --git a/reactos/dll/win32/shell32/CMakeLists.txt b/reactos/dll/win32/shell32/CMakeLists.txt index 89c5417e74c..b59b679eb28 100644 --- a/reactos/dll/win32/shell32/CMakeLists.txt +++ b/reactos/dll/win32/shell32/CMakeLists.txt @@ -54,6 +54,7 @@ list(APPEND SOURCE folders/fonts.cpp folders/cpanel.cpp folders/recyclebin.cpp + droptargets/CexeDropHandler.cpp shlexec.cpp shlfileop.cpp shlfolder.cpp diff --git a/reactos/dll/win32/shell32/changenotify.cpp b/reactos/dll/win32/shell32/changenotify.cpp index e776158e3b2..71eee583fc8 100644 --- a/reactos/dll/win32/shell32/changenotify.cpp +++ b/reactos/dll/win32/shell32/changenotify.cpp @@ -264,6 +264,25 @@ static BOOL should_notify( LPCITEMIDLIST changed, LPCITEMIDLIST watched, BOOL su return TRUE; if( sub && ILIsParent( watched, changed, TRUE ) ) return TRUE; + if (sub && _ILIsDesktop(watched)) { + WCHAR wszPath[MAX_PATH]; + SHGetSpecialFolderPathW(0, wszPath, CSIDL_DESKTOPDIRECTORY, FALSE); + LPITEMIDLIST deskpidl = SHSimpleIDListFromPathW(wszPath); + if (ILIsParent(deskpidl, changed, TRUE)) + { + ILFree(deskpidl); + return TRUE; + } + ILFree(deskpidl); + SHGetSpecialFolderPathW(0, wszPath, CSIDL_COMMON_DESKTOPDIRECTORY, FALSE); + deskpidl = SHSimpleIDListFromPathW(wszPath); + if (ILIsParent(deskpidl, changed, TRUE)) + { + ILFree(deskpidl); + return TRUE; + } + ILFree(deskpidl); + } return FALSE; } @@ -272,7 +291,7 @@ static BOOL should_notify( LPCITEMIDLIST changed, LPCITEMIDLIST watched, BOOL su */ void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2) { - LPCITEMIDLIST Pidls[2]; + LPITEMIDLIST Pidls[2]; LPNOTIFICATIONLIST ptr; UINT typeFlag = uFlags & SHCNF_TYPE; @@ -316,10 +335,43 @@ void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID case SHCNF_PATHW: if (dwItem1) Pidls[0] = SHSimpleIDListFromPathW((LPCWSTR)dwItem1); if (dwItem2) Pidls[1] = SHSimpleIDListFromPathW((LPCWSTR)dwItem2); + if (wEventId & (SHCNE_MKDIR | SHCNE_RMDIR | SHCNE_UPDATEDIR | SHCNE_RENAMEFOLDER)) + { + /* + * The last items in the ID are currently files. So we chop off the last + * entry, and create a new one using a find data struct. + */ + if (dwItem1 && Pidls[0]){ + ILRemoveLastID(Pidls[0]); + WIN32_FIND_DATAW wfd; + LPWSTR p = PathFindFileNameW((LPCWSTR)dwItem1); + lstrcpynW(&wfd.cFileName[0], p, MAX_PATH); + wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; + LPITEMIDLIST newpidl = _ILCreateFromFindDataW(&wfd); + LPITEMIDLIST oldpidl = ILClone(Pidls[0]); + ILFree(Pidls[0]); + Pidls[0] = ILCombine(oldpidl, newpidl); + ILFree(newpidl); + ILFree(oldpidl); + } + if (dwItem2 && Pidls[1]){ + ILRemoveLastID(Pidls[1]); + WIN32_FIND_DATAW wfd; + LPWSTR p = PathFindFileNameW((LPCWSTR)dwItem2); + lstrcpynW(&wfd.cFileName[0], p, MAX_PATH); + wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; + LPITEMIDLIST newpidl = _ILCreateFromFindDataW(&wfd); + LPITEMIDLIST oldpidl = ILClone(Pidls[0]); + ILFree(Pidls[1]); + Pidls[1] = ILCombine(oldpidl, newpidl); + ILFree(newpidl); + ILFree(oldpidl); + } + } break; case SHCNF_IDLIST: - Pidls[0] = (LPCITEMIDLIST)dwItem1; - Pidls[1] = (LPCITEMIDLIST)dwItem2; + Pidls[0] = (LPITEMIDLIST)dwItem1; + Pidls[1] = (LPITEMIDLIST)dwItem2; break; case SHCNF_PRINTERA: case SHCNF_PRINTERW: diff --git a/reactos/dll/win32/shell32/defcontextmenu.cpp b/reactos/dll/win32/shell32/defcontextmenu.cpp index 72988d120aa..6c5b2b84bee 100644 --- a/reactos/dll/win32/shell32/defcontextmenu.cpp +++ b/reactos/dll/win32/shell32/defcontextmenu.cpp @@ -61,6 +61,7 @@ class CDefaultContextMenu : HRESULT DoPaste(LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink); HRESULT DoOpenOrExplore(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoCreateLink(LPCMINVOKECOMMANDINFO lpcmi); + HRESULT DoRefresh(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoDelete(LPCMINVOKECOMMANDINFO lpcmi); HRESULT DoCopyOrCut(LPCMINVOKECOMMANDINFO lpcmi, BOOL bCopy); HRESULT DoRename(LPCMINVOKECOMMANDINFO lpcmi); @@ -931,19 +932,34 @@ NotifyShellViewWindow(LPCMINVOKECOMMANDINFO lpcmi, BOOL bRefresh) if (FAILED(lpSB->QueryActiveShellView(&lpSV))) return E_FAIL; - if (LOWORD(lpcmi->lpVerb) == FCIDM_SHVIEW_REFRESH || bRefresh) - lpSV->Refresh(); - else - { - HWND hwndSV = NULL; - if (SUCCEEDED(lpSV->GetWindow(&hwndSV))) - SendMessageW(hwndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0), 0); - } + HWND hwndSV = NULL; + if (SUCCEEDED(lpSV->GetWindow(&hwndSV))) + SendMessageW(hwndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0), 0); lpSV->Release(); return S_OK; } +HRESULT +CDefaultContextMenu::DoRefresh( + LPCMINVOKECOMMANDINFO lpcmi) +{ + CComPtr ppf2 = NULL; + LPITEMIDLIST pidl; + HRESULT hr = m_Dcm.psf->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2)); + if (SUCCEEDED(hr)) + { + hr = ppf2->GetCurFolder(&pidl); + if (SUCCEEDED(hr)) + { + SHChangeNotify(SHCNE_UPDATEDIR, SHCNF_IDLIST, pidl, NULL); + ILFree(pidl); + } + ppf2->Release(); + } + return hr; +} + HRESULT CDefaultContextMenu::DoPaste( LPCMINVOKECOMMANDINFO lpcmi, BOOL bLink) @@ -1512,8 +1528,9 @@ CDefaultContextMenu::InvokeCommand( case 0x33: case FCIDM_SHVIEW_AUTOARRANGE: case FCIDM_SHVIEW_SNAPTOGRID: - case FCIDM_SHVIEW_REFRESH: return NotifyShellViewWindow(lpcmi, FALSE); + case FCIDM_SHVIEW_REFRESH: + return DoRefresh(lpcmi); case FCIDM_SHVIEW_INSERT: return DoPaste(lpcmi, FALSE); case FCIDM_SHVIEW_INSERTLINK: diff --git a/reactos/dll/win32/shell32/dragdrophelper.cpp b/reactos/dll/win32/shell32/dragdrophelper.cpp index 51a46dd1d2a..b042f2df068 100644 --- a/reactos/dll/win32/shell32/dragdrophelper.cpp +++ b/reactos/dll/win32/shell32/dragdrophelper.cpp @@ -36,6 +36,18 @@ CDropTargetHelper::~CDropTargetHelper() { } +HRESULT WINAPI CDropTargetHelper::InitializeFromBitmap(LPSHDRAGIMAGE pshdi, IDataObject *pDataObject) +{ + FIXME ("(%p)->()\n", this); + return E_NOTIMPL; +} +HRESULT WINAPI CDropTargetHelper::InitializeFromWindow(HWND hwnd, POINT *ppt, IDataObject *pDataObject) +{ + FIXME ("(%p)->()\n", this); + return E_NOTIMPL; +} + + HRESULT WINAPI CDropTargetHelper::DragEnter (HWND hwndTarget, IDataObject* pDataObject, POINT* ppt, DWORD dwEffect) { FIXME ("(%p)->(%p %p %p 0x%08x)\n", this, hwndTarget, pDataObject, ppt, dwEffect); diff --git a/reactos/dll/win32/shell32/dragdrophelper.h b/reactos/dll/win32/shell32/dragdrophelper.h index a520ed655f0..5cc7de9b8a3 100644 --- a/reactos/dll/win32/shell32/dragdrophelper.h +++ b/reactos/dll/win32/shell32/dragdrophelper.h @@ -26,6 +26,7 @@ class CDropTargetHelper : public CComCoClass, public CComObjectRootEx, + public IDragSourceHelper, public IDropTargetHelper { private: @@ -33,7 +34,9 @@ public: CDropTargetHelper(); ~CDropTargetHelper(); - //////// + virtual HRESULT WINAPI InitializeFromBitmap(LPSHDRAGIMAGE pshdi, IDataObject *pDataObject); + virtual HRESULT WINAPI InitializeFromWindow(HWND hwnd, POINT *ppt, IDataObject *pDataObject); + virtual HRESULT WINAPI DragEnter (HWND hwndTarget, IDataObject* pDataObject, POINT* ppt, DWORD dwEffect); virtual HRESULT WINAPI DragLeave(); virtual HRESULT WINAPI DragOver(POINT *ppt, DWORD dwEffect); @@ -46,6 +49,7 @@ DECLARE_NOT_AGGREGATABLE(CDropTargetHelper) DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CDropTargetHelper) + COM_INTERFACE_ENTRY_IID(IID_IDragSourceHelper, IDragSourceHelper) COM_INTERFACE_ENTRY_IID(IID_IDropTargetHelper, IDropTargetHelper) END_COM_MAP() }; diff --git a/reactos/dll/win32/shell32/droptargets/CexeDropHandler.cpp b/reactos/dll/win32/shell32/droptargets/CexeDropHandler.cpp new file mode 100644 index 00000000000..06052fca503 --- /dev/null +++ b/reactos/dll/win32/shell32/droptargets/CexeDropHandler.cpp @@ -0,0 +1,138 @@ +/* + * executable drop target handler + * + * Copyright 2014 Huw Campbell + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +WINE_DEFAULT_DEBUG_CHANNEL (shell); + +CExeDropHandler::CExeDropHandler() +{ + pclsid = (CLSID *)&CLSID_ExeDropHandler; +} + +CExeDropHandler::~CExeDropHandler() +{ + +} + +// IDropTarget +HRESULT WINAPI CExeDropHandler::DragEnter(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) +{ + TRACE ("(%p)\n", this); + *pdwEffect = DROPEFFECT_COPY; + return S_OK; +} + +HRESULT WINAPI CExeDropHandler::DragOver(DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) +{ + TRACE ("(%p)\n", this); + *pdwEffect = DROPEFFECT_COPY; + return S_OK; +} + +HRESULT WINAPI CExeDropHandler::DragLeave() +{ + TRACE ("(%p)\n", this); + return S_OK; +} + +HRESULT WINAPI CExeDropHandler::Drop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) +{ + TRACE ("(%p)\n", this); + FORMATETC fmt; + STGMEDIUM medium; + LPWSTR pszSrcList; + InitFormatEtc (fmt, CF_HDROP, TYMED_HGLOBAL); + WCHAR wszBuf[MAX_PATH * 2 + 8], *pszEnd = wszBuf; + size_t cchRemaining = _countof(wszBuf); + + if (SUCCEEDED(pDataObject->GetData(&fmt, &medium)) /* && SUCCEEDED(pDataObject->GetData(&fmt2, &medium))*/) + { + LPDROPFILES lpdf = (LPDROPFILES) GlobalLock(medium.hGlobal); + if (!lpdf) + { + ERR("Error locking global\n"); + return E_FAIL; + } + pszSrcList = (LPWSTR) (((byte*) lpdf) + lpdf->pFiles); + while (*pszSrcList) + { + if (StrChrW(pszSrcList, L' ') && cchRemaining > 3) + StringCchPrintfExW(pszEnd, cchRemaining, &pszEnd, &cchRemaining, 0, L"\"%ls\" ", pszSrcList); + else + StringCchPrintfExW(pszEnd, cchRemaining, &pszEnd, &cchRemaining, 0, L"%ls ", pszSrcList); + + pszSrcList += wcslen(pszSrcList) + 1; + } + } + + ShellExecute(NULL, L"open", sPathTarget, wszBuf, NULL,SW_SHOWNORMAL); + + return S_OK; +} + + +// IPersistFile +HRESULT WINAPI CExeDropHandler::GetCurFile(LPOLESTR *ppszFileName) +{ + FIXME ("(%p)\n", this); + return E_NOTIMPL; +} + +HRESULT WINAPI CExeDropHandler::IsDirty() +{ + FIXME ("(%p)\n", this); + return E_NOTIMPL; +} + +HRESULT WINAPI CExeDropHandler::Load(LPCOLESTR pszFileName, DWORD dwMode) +{ + UINT len = strlenW(pszFileName); + sPathTarget = (WCHAR *)SHAlloc((len + 1) * sizeof(WCHAR)); + memcpy(sPathTarget, pszFileName, (len + 1) * sizeof(WCHAR)); + return S_OK; +} + +HRESULT WINAPI CExeDropHandler::Save(LPCOLESTR pszFileName, BOOL fRemember) +{ + FIXME ("(%p)\n", this); + return E_NOTIMPL; +} + +HRESULT WINAPI CExeDropHandler::SaveCompleted(LPCOLESTR pszFileName) +{ + FIXME ("(%p)\n", this); + return E_NOTIMPL; +} + +/************************************************************************ + * CFSFolder::GetClassID + */ +HRESULT WINAPI CExeDropHandler::GetClassID(CLSID * lpClassId) +{ + TRACE ("(%p)\n", this); + + if (!lpClassId) + return E_POINTER; + + *lpClassId = *pclsid; + + return S_OK; +} \ No newline at end of file diff --git a/reactos/dll/win32/shell32/droptargets/CexeDropHandler.h b/reactos/dll/win32/shell32/droptargets/CexeDropHandler.h new file mode 100644 index 00000000000..7a79f94aca3 --- /dev/null +++ b/reactos/dll/win32/shell32/droptargets/CexeDropHandler.h @@ -0,0 +1,66 @@ +/* + * executable drop target handler + * + * Copyright 2014 Huw Campbell + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef _CEXEDROPHANDLER_H_ +#define _CEXEDROPHANDLER_H_ + +class CExeDropHandler : + public CComCoClass, + public CComObjectRootEx, + public IDropTarget, + public IPersistFile +{ +private: + CLSID *pclsid; + LPWSTR sPathTarget; +public: + CExeDropHandler(); + ~CExeDropHandler(); + + // IDropTarget + virtual HRESULT WINAPI DragEnter(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect); + virtual HRESULT WINAPI DragOver(DWORD dwKeyState, POINTL pt, DWORD *pdwEffect); + virtual HRESULT WINAPI DragLeave(); + virtual HRESULT WINAPI Drop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect); + + // IPersist + virtual HRESULT WINAPI GetClassID(CLSID *lpClassId); + + //////// IPersistFile + virtual HRESULT WINAPI GetCurFile(LPOLESTR *ppszFileName); + virtual HRESULT WINAPI IsDirty(); + virtual HRESULT WINAPI Load(LPCOLESTR pszFileName, DWORD dwMode); + virtual HRESULT WINAPI Save(LPCOLESTR pszFileName, BOOL fRemember); + virtual HRESULT WINAPI SaveCompleted(LPCOLESTR pszFileName); + + +DECLARE_REGISTRY_RESOURCEID(IDR_EXEDROPHANDLER) +DECLARE_NOT_AGGREGATABLE(CExeDropHandler) + +DECLARE_PROTECT_FINAL_CONSTRUCT() + +BEGIN_COM_MAP(CExeDropHandler) + COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) + COM_INTERFACE_ENTRY_IID(IID_IPersistFile, IPersistFile) + COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget) +END_COM_MAP() +}; + +#endif /* _CEXEDROPHANDLER_H_ */ diff --git a/reactos/dll/win32/shell32/folders/desktop.cpp b/reactos/dll/win32/shell32/folders/desktop.cpp index 968bc35aa29..4f5ca9fe0c7 100644 --- a/reactos/dll/win32/shell32/folders/desktop.cpp +++ b/reactos/dll/win32/shell32/folders/desktop.cpp @@ -651,7 +651,7 @@ HRESULT WINAPI CDesktopFolder::GetUIObjectOf( else if (IsEqualIID (riid, IID_IDropTarget)) { /* only interested in attempting to bind to shell folders, not files, semicolon intentionate */ - if (cidl == 1 && SUCCEEDED(this->BindToObject(apidl[0], NULL, IID_IDropTarget, (LPVOID*)&pObj))); + if (cidl == 1 && SUCCEEDED(hr = this->_GetDropTarget(apidl[0], (LPVOID*)&pObj))); else hr = this->QueryInterface(IID_IDropTarget, (LPVOID*)&pObj); } @@ -1451,7 +1451,7 @@ HRESULT WINAPI CDesktopFolder::Drop(IDataObject *pDataObject, else { InitFormatEtc (formatetc, CF_HDROP, TYMED_HGLOBAL); - if SUCCEEDED(pDataObject->QueryGetData(&formatetc)); + if (SUCCEEDED(pDataObject->QueryGetData(&formatetc))) { passthroughtofs = TRUE; } @@ -1488,4 +1488,53 @@ HRESULT WINAPI CDesktopFolder::Drop(IDataObject *pDataObject, /* Todo, rewrite the registry such that the icons are well placed. Blocked by no bags implementation. */ return hr; +} + +HRESULT WINAPI CDesktopFolder::_GetDropTarget(LPCITEMIDLIST pidl, LPVOID *ppvOut) { + HRESULT hr; + + TRACE("CFSFolder::_GetDropTarget entered\n"); + + if (_ILGetGUIDPointer (pidl) || _ILIsFolder (pidl)) + return this->BindToObject(pidl, NULL, IID_IDropTarget, ppvOut); + + LPITEMIDLIST pidlNext = NULL; + + STRRET strFile; + hr = this->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strFile); + if (SUCCEEDED(hr)) + { + WCHAR wszPath[MAX_PATH]; + hr = StrRetToBufW(&strFile, pidl, wszPath, _countof(wszPath)); + + if (SUCCEEDED(hr)) + { + PathRemoveFileSpecW (wszPath); + hr = this->ParseDisplayName(NULL, NULL, wszPath, NULL, &pidlNext, NULL); + + if (SUCCEEDED(hr)) + { + IShellFolder *psf; + hr = this->BindToObject(pidlNext, NULL, IID_IShellFolder, (LPVOID*)&psf); + CoTaskMemFree(pidlNext); + if (SUCCEEDED(hr)) + { + hr = psf->GetUIObjectOf(NULL, 1, &pidl, IID_IDropTarget, NULL, ppvOut); + psf->Release(); + if (FAILED(hr)) + ERR("FS GetUIObjectOf failed: %x\n", hr); + } + else + ERR("BindToObject failed: %x\n", hr); + } + else + ERR("ParseDisplayName failed: %x\n", hr); + } + else + ERR("StrRetToBufW failed: %x\n", hr); + } + else + ERR("GetDisplayNameOf failed: %x\n", hr); + + return hr; } \ No newline at end of file diff --git a/reactos/dll/win32/shell32/folders/desktop.h b/reactos/dll/win32/shell32/folders/desktop.h index 6f4c723d06a..be62108ff10 100644 --- a/reactos/dll/win32/shell32/folders/desktop.h +++ b/reactos/dll/win32/shell32/folders/desktop.h @@ -40,6 +40,7 @@ class CDesktopFolder : BOOL fAcceptFmt; /* flag for pending Drop */ BOOL QueryDrop (DWORD dwKeyState, LPDWORD pdwEffect); void SF_RegisterClipFmt(); + virtual HRESULT WINAPI _GetDropTarget(LPCITEMIDLIST pidl, LPVOID *ppvOut); public: CDesktopFolder(); diff --git a/reactos/dll/win32/shell32/folders/fs.cpp b/reactos/dll/win32/shell32/folders/fs.cpp index 5e61e7196f9..76e19a00543 100644 --- a/reactos/dll/win32/shell32/folders/fs.cpp +++ b/reactos/dll/win32/shell32/folders/fs.cpp @@ -81,6 +81,7 @@ CFSFolder::CFSFolder() cfShellIDList = 0; SF_RegisterClipFmt(); fAcceptFmt = FALSE; + m_bGroupPolicyActive = 0; } CFSFolder::~CFSFolder() @@ -502,7 +503,7 @@ HRESULT WINAPI CFSFolder::GetUIObjectOf(HWND hwndOwner, else if (IsEqualIID (riid, IID_IDropTarget)) { /* only interested in attempting to bind to shell folders, not files (except exe), so if we fail, rebind to root */ - if (cidl == 1 && SUCCEEDED(hr = this->BindToObject(apidl[0], NULL, IID_IDropTarget, (LPVOID*)&pObj))); + if (cidl == 1 && SUCCEEDED(hr = this->_GetDropTarget(apidl[0], (LPVOID*)&pObj))); else hr = this->QueryInterface(IID_IDropTarget, (LPVOID*)&pObj); } @@ -1617,6 +1618,9 @@ HRESULT WINAPI CFSFolder::_DoDrop(IDataObject *pDataObject, } hr = ppf->Save(wszTarget, FALSE); + if (FAILED(hr)) + break; + SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, wszTarget, NULL); } else { @@ -1653,6 +1657,9 @@ HRESULT WINAPI CFSFolder::_DoDrop(IDataObject *pDataObject, break; hr = ppf->Save(wszTarget, TRUE); + if (FAILED(hr)) + break; + SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, wszTarget, NULL); } } } @@ -1748,4 +1755,114 @@ DWORD WINAPI CFSFolder::_DoDropThreadProc(LPVOID lpParameter) { //Release the parameter from the heap. HeapFree(GetProcessHeap(), 0, data); return 0; +} + +HRESULT WINAPI CFSFolder::_GetDropTarget(LPCITEMIDLIST pidl, LPVOID *ppvOut) { + HKEY hKey; + HRESULT hr; + + TRACE("CFSFolder::_GetDropTarget entered\n"); + + if (_ILGetGUIDPointer (pidl) || _ILIsFolder (pidl)) + return this->BindToObject(pidl, NULL, IID_IDropTarget, ppvOut); + + STRRET strFile; + hr = this->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strFile); + if (hr == S_OK) + { + WCHAR wszPath[MAX_PATH]; + hr = StrRetToBufW(&strFile, pidl, wszPath, _countof(wszPath)); + + if (hr == S_OK) + { + LPCWSTR pwszExt = PathFindExtensionW(wszPath); + if (pwszExt[0]) + { + /* enumerate dynamic/static for a given file class */ + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, pwszExt, 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + /* load dynamic extensions from file extension key, for example .jpg */ + _LoadDynamicDropTargetHandlerForKey(hKey, wszPath, ppvOut); + RegCloseKey(hKey); + } + + WCHAR wszTemp[40]; + DWORD dwSize = sizeof(wszTemp); + if (RegGetValueW(HKEY_CLASSES_ROOT, pwszExt, NULL, RRF_RT_REG_SZ, NULL, wszTemp, &dwSize) == ERROR_SUCCESS) + { + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, wszTemp, 0, KEY_READ, &hKey) == ERROR_SUCCESS) + { + /* load dynamic extensions from progid key, for example jpegfile */ + _LoadDynamicDropTargetHandlerForKey(hKey, wszPath, ppvOut); + RegCloseKey(hKey); + } + } + } + } + } + else + ERR("GetDisplayNameOf failed: %x\n", hr); + + return hr; +} + +HRESULT WINAPI CFSFolder::_LoadDynamicDropTargetHandlerForKey(HKEY hRootKey, LPCWSTR pwcsname, LPVOID *ppvOut) +{ + TRACE("CFSFolder::_LoadDynamicDropTargetHandlerForKey entered\n"); + + WCHAR wszName[MAX_PATH], *pwszClsid; + DWORD dwSize = sizeof(wszName); + HRESULT hr; + + if (RegGetValueW(hRootKey, L"shellex\\DropHandler", NULL, RRF_RT_REG_SZ, NULL, wszName, &dwSize) == ERROR_SUCCESS) + { + CLSID clsid; + hr = CLSIDFromString(wszName, &clsid); + if (hr == S_OK) + pwszClsid = wszName; + + if (m_bGroupPolicyActive) + { + if (RegGetValueW(HKEY_LOCAL_MACHINE, + L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", + pwszClsid, + RRF_RT_REG_SZ, + NULL, + NULL, + NULL) == ERROR_SUCCESS) + { + hr = _LoadDynamicDropTargetHandler(&clsid, pwcsname, ppvOut); + } + } + else + { + hr = _LoadDynamicDropTargetHandler(&clsid, pwcsname, ppvOut); + } + } + else + return E_FAIL; + return hr; +} + +HRESULT WINAPI CFSFolder::_LoadDynamicDropTargetHandler(const CLSID *pclsid, LPCWSTR pwcsname, LPVOID *ppvOut) +{ + TRACE("CFSFolder::_LoadDynamicDropTargetHandler entered\n"); + HRESULT hr; + + IPersistFile *pp; + hr = SHCoCreateInstance(NULL, pclsid, NULL, IID_PPV_ARG(IPersistFile, &pp)); + if (hr != S_OK) + { + ERR("SHCoCreateInstance failed %x\n", GetLastError()); + } + pp->Load(pwcsname, 0); + + hr = pp->QueryInterface(IID_PPV_ARG(IDropTarget, (IDropTarget**) ppvOut)); + if (hr != S_OK) + { + ERR("Failed to query for interface IID_IShellExtInit hr %x pclsid %s\n", hr, wine_dbgstr_guid(pclsid)); + return hr; + } + pp->Release(); + return hr; } \ No newline at end of file diff --git a/reactos/dll/win32/shell32/folders/fs.h b/reactos/dll/win32/shell32/folders/fs.h index e32ab2b7aa8..95ca362ccfe 100644 --- a/reactos/dll/win32/shell32/folders/fs.h +++ b/reactos/dll/win32/shell32/folders/fs.h @@ -44,10 +44,14 @@ class CFSFolder : UINT cfShellIDList; /* clipboardformat for IDropTarget */ BOOL fAcceptFmt; /* flag for pending Drop */ BOOL QueryDrop (DWORD dwKeyState, LPDWORD pdwEffect); + DWORD m_bGroupPolicyActive; void SF_RegisterClipFmt(); BOOL GetUniqueFileName(LPWSTR pwszBasePath, LPCWSTR pwszExt, LPWSTR pwszTarget, BOOL bShortcut); static DWORD WINAPI _DoDropThreadProc(LPVOID lpParameter); virtual HRESULT WINAPI _DoDrop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect); + virtual HRESULT WINAPI _GetDropTarget(LPCITEMIDLIST pidl, LPVOID *ppvOut); + virtual HRESULT WINAPI _LoadDynamicDropTargetHandlerForKey(HKEY hRootKey, LPCWSTR pwcsname, LPVOID *ppvOut); + virtual HRESULT WINAPI _LoadDynamicDropTargetHandler(const CLSID *pclsid, LPCWSTR pwcsname, LPVOID *ppvOut); public: CFSFolder(); diff --git a/reactos/dll/win32/shell32/folders/mydocuments.cpp b/reactos/dll/win32/shell32/folders/mydocuments.cpp index 7c1cbd93e0d..f1a0238f936 100644 --- a/reactos/dll/win32/shell32/folders/mydocuments.cpp +++ b/reactos/dll/win32/shell32/folders/mydocuments.cpp @@ -78,6 +78,7 @@ CMyDocsFolder::CMyDocsFolder() { pidlRoot = NULL; sPathTarget = NULL; + mFSDropTarget = NULL; } CMyDocsFolder::~CMyDocsFolder() @@ -85,6 +86,7 @@ CMyDocsFolder::~CMyDocsFolder() TRACE ("-- destroying IShellFolder(%p)\n", this); SHFree(pidlRoot); HeapFree(GetProcessHeap(), 0, sPathTarget); + mFSDropTarget->Release(); } HRESULT WINAPI CMyDocsFolder::FinalConstruct() @@ -98,6 +100,29 @@ HRESULT WINAPI CMyDocsFolder::FinalConstruct() sPathTarget = (LPWSTR)SHAlloc((wcslen(szMyPath) + 1) * sizeof(WCHAR)); wcscpy(sPathTarget, szMyPath); + LPITEMIDLIST pidl = NULL; + + WCHAR szPath[MAX_PATH]; + lstrcpynW(szPath, sPathTarget, MAX_PATH); + PathAddBackslashW(szPath); + CComPtr psfDesktop = NULL; + + HRESULT hr = SHGetDesktopFolder(&psfDesktop); + if (SUCCEEDED(hr)) + hr = psfDesktop->ParseDisplayName(NULL, NULL, szPath, NULL, &pidl, NULL); + else + ERR("Error getting desktop folder\n"); + + if (SUCCEEDED(hr)) + { + hr = psfDesktop->BindToObject(pidl, NULL, IID_IDropTarget, (LPVOID*) &mFSDropTarget); + CoTaskMemFree(pidl); + if (FAILED(hr)) + ERR("Error Binding"); + } + else + ERR("Error creating from %s\n", debugstr_w(szPath)); + return S_OK; } @@ -271,8 +296,7 @@ HRESULT WINAPI CMyDocsFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVO if (IsEqualIID (riid, IID_IDropTarget)) { - WARN ("IDropTarget not implemented\n"); - hr = E_NOTIMPL; + hr = this->QueryInterface (IID_IDropTarget, ppvOut); } else if (IsEqualIID (riid, IID_IContextMenu)) { @@ -679,3 +703,26 @@ HRESULT WINAPI CMyDocsFolder::GetCurFolder(LPITEMIDLIST *pidl) *pidl = ILClone (pidlRoot); return S_OK; } + +HRESULT WINAPI CMyDocsFolder::DragEnter(IDataObject *pDataObject, + DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) +{ + return mFSDropTarget->DragEnter(pDataObject, dwKeyState, pt, pdwEffect); +} + +HRESULT WINAPI CMyDocsFolder::DragOver(DWORD dwKeyState, POINTL pt, + DWORD *pdwEffect) +{ + return mFSDropTarget->DragOver(dwKeyState, pt, pdwEffect); +} + +HRESULT WINAPI CMyDocsFolder::DragLeave() +{ + return mFSDropTarget->DragLeave(); +} + +HRESULT WINAPI CMyDocsFolder::Drop(IDataObject *pDataObject, + DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) +{ + return mFSDropTarget->Drop(pDataObject, dwKeyState, pt, pdwEffect); +} \ No newline at end of file diff --git a/reactos/dll/win32/shell32/folders/mydocuments.h b/reactos/dll/win32/shell32/folders/mydocuments.h index c52ffe5346f..3a70e8c3d26 100644 --- a/reactos/dll/win32/shell32/folders/mydocuments.h +++ b/reactos/dll/win32/shell32/folders/mydocuments.h @@ -26,12 +26,14 @@ class CMyDocsFolder : public CComCoClass, public CComObjectRootEx, public IShellFolder2, - public IPersistFolder2 + public IPersistFolder2, + public IDropTarget { private: /* both paths are parsible from the MyDocuments */ LPWSTR sPathTarget; /* complete path to target used for enumeration and ChangeNotify */ LPITEMIDLIST pidlRoot; /* absolute pidl */ + IDropTarget *mFSDropTarget; public: CMyDocsFolder(); ~CMyDocsFolder(); @@ -67,6 +69,12 @@ class CMyDocsFolder : // IPersistFolder2 virtual HRESULT WINAPI GetCurFolder(LPITEMIDLIST * pidl); + // IDropTarget + virtual HRESULT WINAPI DragEnter(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect); + virtual HRESULT WINAPI DragOver(DWORD dwKeyState, POINTL pt, DWORD *pdwEffect); + virtual HRESULT WINAPI DragLeave(); + virtual HRESULT WINAPI Drop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect); + DECLARE_REGISTRY_RESOURCEID(IDR_MYDOCUMENTS) DECLARE_NOT_AGGREGATABLE(CMyDocsFolder) @@ -78,6 +86,7 @@ class CMyDocsFolder : COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder) COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2) COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) + COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget) END_COM_MAP() }; diff --git a/reactos/dll/win32/shell32/folders/recyclebin.cpp b/reactos/dll/win32/shell32/folders/recyclebin.cpp index 733873a807b..648debf6a47 100644 --- a/reactos/dll/win32/shell32/folders/recyclebin.cpp +++ b/reactos/dll/win32/shell32/folders/recyclebin.cpp @@ -1416,7 +1416,7 @@ BOOL CRecycleBin::QueryDrop(DWORD dwKeyState, LPDWORD pdwEffect) HRESULT WINAPI CRecycleBin::DragEnter(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) { - FIXME("Recycle bin drag over (%p)\n", this); + TRACE("Recycle bin drag over (%p)\n", this); /* The recycle bin accepts pretty much everything, and sets a CSIDL flag. */ fAcceptFmt = TRUE; @@ -1449,7 +1449,7 @@ HRESULT WINAPI CRecycleBin::DragLeave() HRESULT WINAPI CRecycleBin::Drop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) { - FIXME("(%p) object dropped on recycle bin, effect %u\n", this, *pdwEffect); + TRACE("(%p) object dropped on recycle bin, effect %u\n", this, *pdwEffect); /* TODO: pdwEffect should be read and make the drop object be permanently deleted in the move case (shift held) */ diff --git a/reactos/dll/win32/shell32/precomp.h b/reactos/dll/win32/shell32/precomp.h index f464d095bcf..a2a648ba3de 100644 --- a/reactos/dll/win32/shell32/precomp.h +++ b/reactos/dll/win32/shell32/precomp.h @@ -55,6 +55,7 @@ #include "folders/printers.h" #include "folders/admintools.h" #include "folders/recyclebin.h" +#include "droptargets/CexeDropHandler.h" #include "openwithmenu.h" #include "newmenu.h" #include "startmenu.h" diff --git a/reactos/dll/win32/shell32/res/rgs/exedrophandler.rgs b/reactos/dll/win32/shell32/res/rgs/exedrophandler.rgs new file mode 100644 index 00000000000..7e239c975aa --- /dev/null +++ b/reactos/dll/win32/shell32/res/rgs/exedrophandler.rgs @@ -0,0 +1,13 @@ +HKCR +{ + NoRemove CLSID + { + ForceRemove {86C86720-42A0-1069-A2E8-08002B30309D} = s 'Executable Drag and Drop target' + { + InprocServer32 = s '%MODULE%' + { + val ThreadingModel = s 'Apartment' + } + } + } +} diff --git a/reactos/dll/win32/shell32/rgs_res.rc b/reactos/dll/win32/shell32/rgs_res.rc index 4ded01df5eb..7cab2161e66 100644 --- a/reactos/dll/win32/shell32/rgs_res.rc +++ b/reactos/dll/win32/shell32/rgs_res.rc @@ -23,3 +23,4 @@ IDR_STARTMENU REGISTRY "res/rgs/startmenu.rgs" IDR_OPENWITHMENU REGISTRY "res/rgs/openwithmenu.rgs" IDR_FILEDEFEXT REGISTRY "res/rgs/shellfiledefext.rgs" IDR_DRVDEFEXT REGISTRY "res/rgs/shelldrvdefext.rgs" +IDR_EXEDROPHANDLER REGISTRY "res/rgs/exedrophandler.rgs" \ No newline at end of file diff --git a/reactos/dll/win32/shell32/shell32_main.cpp b/reactos/dll/win32/shell32/shell32_main.cpp index 21ccb1aa81d..beeff9dc152 100644 --- a/reactos/dll/win32/shell32/shell32_main.cpp +++ b/reactos/dll/win32/shell32/shell32_main.cpp @@ -1371,6 +1371,7 @@ BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_MenuBandSite, CMenuBandSite) OBJECT_ENTRY(CLSID_MenuBand, CMenuBand) OBJECT_ENTRY(CLSID_MenuDeskBar, CMenuDeskBar) + OBJECT_ENTRY(CLSID_ExeDropHandler, CExeDropHandler) END_OBJECT_MAP() CShell32Module gModule; diff --git a/reactos/dll/win32/shell32/shelllink.cpp b/reactos/dll/win32/shell32/shelllink.cpp index fd54ee719fe..4982f7da306 100644 --- a/reactos/dll/win32/shell32/shelllink.cpp +++ b/reactos/dll/win32/shell32/shelllink.cpp @@ -2168,6 +2168,68 @@ HRESULT WINAPI CShellLink::GetSite(REFIID iid, void ** ppvSite) return site->QueryInterface(iid, ppvSite); } +HRESULT WINAPI CShellLink::DragEnter(IDataObject *pDataObject, + DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) +{ + TRACE("(%p)->(DataObject=%p)\n", this, pDataObject); + LPCITEMIDLIST pidlLast; + IShellFolder *psf; + + HRESULT hr = SHBindToParent(pPidl, IID_PPV_ARG(IShellFolder, &psf), &pidlLast); + + if (SUCCEEDED(hr)) + { + hr = psf->GetUIObjectOf(0, 1, &pidlLast, IID_IDropTarget, NULL, (LPVOID*)&mDropTarget); + + if (SUCCEEDED(hr)) + hr = mDropTarget->DragEnter(pDataObject, dwKeyState, pt, pdwEffect); + else + *pdwEffect = DROPEFFECT_NONE; + + psf->Release(); + } + else + *pdwEffect = DROPEFFECT_NONE; + + return S_OK; +} + + + +HRESULT WINAPI CShellLink::DragOver(DWORD dwKeyState, POINTL pt, + DWORD *pdwEffect) +{ + TRACE("(%p)\n", this); + HRESULT hr = S_OK; + if (mDropTarget) + hr = mDropTarget->DragOver(dwKeyState, pt, pdwEffect); + return hr; +} + +HRESULT WINAPI CShellLink::DragLeave() +{ + TRACE("(%p)\n", this); + HRESULT hr = S_OK; + if (mDropTarget) + { + hr = mDropTarget->DragLeave(); + mDropTarget->Release(); + } + + return hr; +} + +HRESULT WINAPI CShellLink::Drop(IDataObject *pDataObject, + DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) +{ + TRACE("(%p)\n", this); + HRESULT hr = S_OK; + if (mDropTarget) + hr = mDropTarget->Drop(pDataObject, dwKeyState, pt, pdwEffect); + + return hr; +} + /************************************************************************** * IShellLink_ConstructFromFile */ diff --git a/reactos/dll/win32/shell32/shelllink.h b/reactos/dll/win32/shell32/shelllink.h index 47cb0fa8abb..3ccfd3df61a 100644 --- a/reactos/dll/win32/shell32/shelllink.h +++ b/reactos/dll/win32/shell32/shelllink.h @@ -25,140 +25,148 @@ #define _SHELLLINK_H_ class CShellLink : - public CComCoClass, - public CComObjectRootEx, - public IShellLinkA, - public IShellLinkW, - public IPersistFile, - public IPersistStream, - public IShellLinkDataList, - public IShellExtInit, - public IContextMenu, - public IObjectWithSite, - public IShellPropSheetExt + public CComCoClass, + public CComObjectRootEx, + public IShellLinkA, + public IShellLinkW, + public IPersistFile, + public IPersistStream, + public IShellLinkDataList, + public IShellExtInit, + public IContextMenu, + public IDropTarget, + public IObjectWithSite, + public IShellPropSheetExt { public: - /* link file formats */ + /* link file formats */ - #include "pshpack1.h" + #include "pshpack1.h" - struct volume_info - { - DWORD type; - DWORD serial; - WCHAR label[12]; /* assume 8.3 */ - }; + struct volume_info + { + DWORD type; + DWORD serial; + WCHAR label[12]; /* assume 8.3 */ + }; - #include "poppack.h" + #include "poppack.h" private: - /* data structures according to the information in the link */ - LPITEMIDLIST pPidl; - WORD wHotKey; - SYSTEMTIME time1; - SYSTEMTIME time2; - SYSTEMTIME time3; + /* data structures according to the information in the link */ + LPITEMIDLIST pPidl; + WORD wHotKey; + SYSTEMTIME time1; + SYSTEMTIME time2; + SYSTEMTIME time3; - DWORD iShowCmd; - LPWSTR sIcoPath; - INT iIcoNdx; - LPWSTR sPath; - LPWSTR sArgs; - LPWSTR sWorkDir; - LPWSTR sDescription; - LPWSTR sPathRel; - LPWSTR sProduct; - LPWSTR sComponent; - volume_info volume; - LPWSTR sLinkPath; - BOOL bRunAs; - BOOL bDirty; - INT iIdOpen; /* id of the "Open" entry in the context menu */ - CComPtr site; + DWORD iShowCmd; + LPWSTR sIcoPath; + INT iIcoNdx; + LPWSTR sPath; + LPWSTR sArgs; + LPWSTR sWorkDir; + LPWSTR sDescription; + LPWSTR sPathRel; + LPWSTR sProduct; + LPWSTR sComponent; + volume_info volume; + LPWSTR sLinkPath; + BOOL bRunAs; + BOOL bDirty; + INT iIdOpen; /* id of the "Open" entry in the context menu */ + CComPtr site; + IDropTarget *mDropTarget; public: - CShellLink(); - ~CShellLink(); - LPWSTR ShellLink_GetAdvertisedArg(LPCWSTR str); - HRESULT ShellLink_SetAdvertiseInfo(LPCWSTR str); - static INT_PTR CALLBACK SH_ShellLinkDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); + CShellLink(); + ~CShellLink(); + LPWSTR ShellLink_GetAdvertisedArg(LPCWSTR str); + HRESULT ShellLink_SetAdvertiseInfo(LPCWSTR str); + static INT_PTR CALLBACK SH_ShellLinkDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); - // IPersistFile - virtual HRESULT WINAPI GetClassID(CLSID *pclsid); - virtual HRESULT WINAPI IsDirty(); - virtual HRESULT WINAPI Load(LPCOLESTR pszFileName, DWORD dwMode); - virtual HRESULT WINAPI Save(LPCOLESTR pszFileName, BOOL fRemember); - virtual HRESULT WINAPI SaveCompleted(LPCOLESTR pszFileName); - virtual HRESULT WINAPI GetCurFile(LPOLESTR *ppszFileName); + // IPersistFile + virtual HRESULT WINAPI GetClassID(CLSID *pclsid); + virtual HRESULT WINAPI IsDirty(); + virtual HRESULT WINAPI Load(LPCOLESTR pszFileName, DWORD dwMode); + virtual HRESULT WINAPI Save(LPCOLESTR pszFileName, BOOL fRemember); + virtual HRESULT WINAPI SaveCompleted(LPCOLESTR pszFileName); + virtual HRESULT WINAPI GetCurFile(LPOLESTR *ppszFileName); - // IPersistStream -// virtual WINAPI HRESULT GetClassID(CLSID *pclsid); -// virtual HRESULT WINAPI IsDirty(); - virtual HRESULT WINAPI Load(IStream *stm); - virtual HRESULT WINAPI Save(IStream *stm, BOOL fClearDirty); - virtual HRESULT WINAPI GetSizeMax(ULARGE_INTEGER *pcbSize); + // IPersistStream + // virtual WINAPI HRESULT GetClassID(CLSID *pclsid); + // virtual HRESULT WINAPI IsDirty(); + virtual HRESULT WINAPI Load(IStream *stm); + virtual HRESULT WINAPI Save(IStream *stm, BOOL fClearDirty); + virtual HRESULT WINAPI GetSizeMax(ULARGE_INTEGER *pcbSize); - // IShellLinkA - virtual HRESULT WINAPI GetPath(LPSTR pszFile, INT cchMaxPath, WIN32_FIND_DATAA *pfd, DWORD fFlags); - virtual HRESULT WINAPI GetIDList(LPITEMIDLIST * ppidl); - virtual HRESULT WINAPI SetIDList(LPCITEMIDLIST pidl); - virtual HRESULT WINAPI GetDescription(LPSTR pszName,INT cchMaxName); - virtual HRESULT WINAPI SetDescription(LPCSTR pszName); - virtual HRESULT WINAPI GetWorkingDirectory(LPSTR pszDir,INT cchMaxPath); - virtual HRESULT WINAPI SetWorkingDirectory(LPCSTR pszDir); - virtual HRESULT WINAPI GetArguments(LPSTR pszArgs,INT cchMaxPath); - virtual HRESULT WINAPI SetArguments(LPCSTR pszArgs); - virtual HRESULT WINAPI GetHotkey(WORD *pwHotkey); - virtual HRESULT WINAPI SetHotkey(WORD wHotkey); - virtual HRESULT WINAPI GetShowCmd(INT *piShowCmd); - virtual HRESULT WINAPI SetShowCmd(INT iShowCmd); - virtual HRESULT WINAPI GetIconLocation(LPSTR pszIconPath,INT cchIconPath,INT *piIcon); - virtual HRESULT WINAPI SetIconLocation(LPCSTR pszIconPath,INT iIcon); - virtual HRESULT WINAPI SetRelativePath(LPCSTR pszPathRel, DWORD dwReserved); - virtual HRESULT WINAPI Resolve(HWND hwnd, DWORD fFlags); - virtual HRESULT WINAPI SetPath(LPCSTR pszFile); + // IShellLinkA + virtual HRESULT WINAPI GetPath(LPSTR pszFile, INT cchMaxPath, WIN32_FIND_DATAA *pfd, DWORD fFlags); + virtual HRESULT WINAPI GetIDList(LPITEMIDLIST * ppidl); + virtual HRESULT WINAPI SetIDList(LPCITEMIDLIST pidl); + virtual HRESULT WINAPI GetDescription(LPSTR pszName,INT cchMaxName); + virtual HRESULT WINAPI SetDescription(LPCSTR pszName); + virtual HRESULT WINAPI GetWorkingDirectory(LPSTR pszDir,INT cchMaxPath); + virtual HRESULT WINAPI SetWorkingDirectory(LPCSTR pszDir); + virtual HRESULT WINAPI GetArguments(LPSTR pszArgs,INT cchMaxPath); + virtual HRESULT WINAPI SetArguments(LPCSTR pszArgs); + virtual HRESULT WINAPI GetHotkey(WORD *pwHotkey); + virtual HRESULT WINAPI SetHotkey(WORD wHotkey); + virtual HRESULT WINAPI GetShowCmd(INT *piShowCmd); + virtual HRESULT WINAPI SetShowCmd(INT iShowCmd); + virtual HRESULT WINAPI GetIconLocation(LPSTR pszIconPath,INT cchIconPath,INT *piIcon); + virtual HRESULT WINAPI SetIconLocation(LPCSTR pszIconPath,INT iIcon); + virtual HRESULT WINAPI SetRelativePath(LPCSTR pszPathRel, DWORD dwReserved); + virtual HRESULT WINAPI Resolve(HWND hwnd, DWORD fFlags); + virtual HRESULT WINAPI SetPath(LPCSTR pszFile); - // IShellLinkW - virtual HRESULT WINAPI GetPath(LPWSTR pszFile, INT cchMaxPath, WIN32_FIND_DATAW *pfd, DWORD fFlags); -// virtual HRESULT WINAPI GetIDList(LPITEMIDLIST *ppidl); -// virtual HRESULT WINAPI SetIDList(LPCITEMIDLIST pidl); - virtual HRESULT WINAPI GetDescription(LPWSTR pszName, INT cchMaxName); - virtual HRESULT WINAPI SetDescription(LPCWSTR pszName); - virtual HRESULT WINAPI GetWorkingDirectory(LPWSTR pszDir, INT cchMaxPath); - virtual HRESULT WINAPI SetWorkingDirectory(LPCWSTR pszDir); - virtual HRESULT WINAPI GetArguments(LPWSTR pszArgs,INT cchMaxPath); - virtual HRESULT WINAPI SetArguments(LPCWSTR pszArgs); -// virtual HRESULT WINAPI GetHotkey(WORD *pwHotkey); -// virtual HRESULT WINAPI SetHotkey(WORD wHotkey); -// virtual HRESULT WINAPI GetShowCmd(INT *piShowCmd); -// virtual HRESULT WINAPI SetShowCmd(INT iShowCmd); - virtual HRESULT WINAPI GetIconLocation(LPWSTR pszIconPath,INT cchIconPath,INT *piIcon); - virtual HRESULT WINAPI SetIconLocation(LPCWSTR pszIconPath,INT iIcon); - virtual HRESULT WINAPI SetRelativePath(LPCWSTR pszPathRel, DWORD dwReserved); -// virtual HRESULT WINAPI Resolve(HWND hwnd, DWORD fFlags); - virtual HRESULT WINAPI SetPath(LPCWSTR pszFile); + // IShellLinkW + virtual HRESULT WINAPI GetPath(LPWSTR pszFile, INT cchMaxPath, WIN32_FIND_DATAW *pfd, DWORD fFlags); + // virtual HRESULT WINAPI GetIDList(LPITEMIDLIST *ppidl); + // virtual HRESULT WINAPI SetIDList(LPCITEMIDLIST pidl); + virtual HRESULT WINAPI GetDescription(LPWSTR pszName, INT cchMaxName); + virtual HRESULT WINAPI SetDescription(LPCWSTR pszName); + virtual HRESULT WINAPI GetWorkingDirectory(LPWSTR pszDir, INT cchMaxPath); + virtual HRESULT WINAPI SetWorkingDirectory(LPCWSTR pszDir); + virtual HRESULT WINAPI GetArguments(LPWSTR pszArgs,INT cchMaxPath); + virtual HRESULT WINAPI SetArguments(LPCWSTR pszArgs); + // virtual HRESULT WINAPI GetHotkey(WORD *pwHotkey); + // virtual HRESULT WINAPI SetHotkey(WORD wHotkey); + // virtual HRESULT WINAPI GetShowCmd(INT *piShowCmd); + // virtual HRESULT WINAPI SetShowCmd(INT iShowCmd); + virtual HRESULT WINAPI GetIconLocation(LPWSTR pszIconPath,INT cchIconPath,INT *piIcon); + virtual HRESULT WINAPI SetIconLocation(LPCWSTR pszIconPath,INT iIcon); + virtual HRESULT WINAPI SetRelativePath(LPCWSTR pszPathRel, DWORD dwReserved); + // virtual HRESULT WINAPI Resolve(HWND hwnd, DWORD fFlags); + virtual HRESULT WINAPI SetPath(LPCWSTR pszFile); - // IShellLinkDataList - virtual HRESULT WINAPI AddDataBlock(void *pDataBlock); - virtual HRESULT WINAPI CopyDataBlock(DWORD dwSig, void **ppDataBlock); - virtual HRESULT WINAPI RemoveDataBlock(DWORD dwSig); - virtual HRESULT WINAPI GetFlags(DWORD *pdwFlags); - virtual HRESULT WINAPI SetFlags(DWORD dwFlags); + // IShellLinkDataList + virtual HRESULT WINAPI AddDataBlock(void *pDataBlock); + virtual HRESULT WINAPI CopyDataBlock(DWORD dwSig, void **ppDataBlock); + virtual HRESULT WINAPI RemoveDataBlock(DWORD dwSig); + virtual HRESULT WINAPI GetFlags(DWORD *pdwFlags); + virtual HRESULT WINAPI SetFlags(DWORD dwFlags); - // IShellExtInit - virtual HRESULT WINAPI Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID); + // IShellExtInit + virtual HRESULT WINAPI Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID); - // IContextMenu - virtual HRESULT WINAPI QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags); - virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpici); - virtual HRESULT WINAPI GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax); + // IContextMenu + virtual HRESULT WINAPI QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags); + virtual HRESULT WINAPI InvokeCommand(LPCMINVOKECOMMANDINFO lpici); + virtual HRESULT WINAPI GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax); - // IShellPropSheetExt - virtual HRESULT WINAPI AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam); - virtual HRESULT WINAPI ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam); + // IShellPropSheetExt + virtual HRESULT WINAPI AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam); + virtual HRESULT WINAPI ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam); - // IObjectWithSite - virtual HRESULT WINAPI SetSite(IUnknown *punk); - virtual HRESULT WINAPI GetSite(REFIID iid, void **ppvSite); + // IObjectWithSite + virtual HRESULT WINAPI SetSite(IUnknown *punk); + virtual HRESULT WINAPI GetSite(REFIID iid, void **ppvSite); + + // IDropTarget + virtual HRESULT WINAPI DragEnter(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect); + virtual HRESULT WINAPI DragOver(DWORD dwKeyState, POINTL pt, DWORD *pdwEffect); + virtual HRESULT WINAPI DragLeave(); + virtual HRESULT WINAPI Drop(IDataObject *pDataObject, DWORD dwKeyState, POINTL pt, DWORD *pdwEffect); DECLARE_REGISTRY_RESOURCEID(IDR_SHELLLINK) DECLARE_NOT_AGGREGATABLE(CShellLink) @@ -166,16 +174,17 @@ DECLARE_NOT_AGGREGATABLE(CShellLink) DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CShellLink) - COM_INTERFACE_ENTRY2_IID(IID_IPersist, IPersist, IPersistFile) - COM_INTERFACE_ENTRY_IID(IID_IPersistFile, IPersistFile) - COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream) - COM_INTERFACE_ENTRY_IID(IID_IShellLinkA, IShellLinkA) - COM_INTERFACE_ENTRY_IID(IID_IShellLinkW, IShellLinkW) - COM_INTERFACE_ENTRY_IID(IID_IShellLinkDataList, IShellLinkDataList) - COM_INTERFACE_ENTRY_IID(IID_IShellExtInit, IShellExtInit) - COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) - COM_INTERFACE_ENTRY_IID(IID_IShellPropSheetExt, IShellPropSheetExt) - COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite) + COM_INTERFACE_ENTRY2_IID(IID_IPersist, IPersist, IPersistFile) + COM_INTERFACE_ENTRY_IID(IID_IPersistFile, IPersistFile) + COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream) + COM_INTERFACE_ENTRY_IID(IID_IShellLinkA, IShellLinkA) + COM_INTERFACE_ENTRY_IID(IID_IShellLinkW, IShellLinkW) + COM_INTERFACE_ENTRY_IID(IID_IShellLinkDataList, IShellLinkDataList) + COM_INTERFACE_ENTRY_IID(IID_IShellExtInit, IShellExtInit) + COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) + COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget) + COM_INTERFACE_ENTRY_IID(IID_IShellPropSheetExt, IShellPropSheetExt) + COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite) END_COM_MAP() }; diff --git a/reactos/dll/win32/shell32/shfldr.h b/reactos/dll/win32/shell32/shfldr.h index 8a194ce17d5..81111ce4999 100644 --- a/reactos/dll/win32/shell32/shfldr.h +++ b/reactos/dll/win32/shell32/shfldr.h @@ -1,10 +1,10 @@ /* - * Virtual Folder - * common definitions + * Virtual Folder + * common definitions * - * Copyright 1997 Marcus Meissner - * Copyright 1998, 1999, 2002 Juergen Schmied + * Copyright 1997 Marcus Meissner + * Copyright 1998, 1999, 2002 Juergen Schmied * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -40,13 +40,13 @@ BOOL SHELL32_GetCustomFolderAttribute (LPCITEMIDLIST pidl, LPCWSTR pwszHeading, LPCWSTR GetNextElementW (LPCWSTR pszNext, LPWSTR pszOut, DWORD dwOut); HRESULT SHELL32_ParseNextElement (IShellFolder2 * psf, HWND hwndOwner, LPBC pbc, LPITEMIDLIST * pidlInOut, - LPOLESTR szNext, DWORD * pEaten, DWORD * pdwAttributes); + LPOLESTR szNext, DWORD * pEaten, DWORD * pdwAttributes); HRESULT SHELL32_GetItemAttributes (IShellFolder * psf, LPCITEMIDLIST pidl, LPDWORD pdwAttributes); HRESULT SHELL32_GetDisplayNameOfChild (IShellFolder2 * psf, LPCITEMIDLIST pidl, DWORD dwFlags, LPWSTR szOut, - DWORD dwOutLen); + DWORD dwOutLen); HRESULT SHELL32_BindToChild (LPCITEMIDLIST pidlRoot, - LPCWSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut); + LPCWSTR pathRoot, LPCITEMIDLIST pidlComplete, REFIID riid, LPVOID * ppvOut); HRESULT SHELL32_CompareIDs (IShellFolder * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2); LPITEMIDLIST SHELL32_CreatePidlFromBindCtx(IBindCtx *pbc, LPCWSTR path); diff --git a/reactos/dll/win32/shell32/shlfileop.cpp b/reactos/dll/win32/shell32/shlfileop.cpp index 1135afc258a..8fe73ffb51b 100644 --- a/reactos/dll/win32/shell32/shlfileop.cpp +++ b/reactos/dll/win32/shell32/shlfileop.cpp @@ -42,7 +42,7 @@ static const WCHAR wWildcardChars[] = {'*','?',0}; static DWORD SHNotifyCreateDirectoryW(LPCWSTR path, LPSECURITY_ATTRIBUTES sec); static DWORD SHNotifyRemoveDirectoryW(LPCWSTR path); static DWORD SHNotifyDeleteFileW(LPCWSTR path); -static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest); +static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest, BOOL isdir); static DWORD SHNotifyCopyFileW(LPCWSTR src, LPCWSTR dest, BOOL bFailIfExists); static DWORD SHFindAttrW(LPCWSTR pName, BOOL fileOnly); @@ -531,7 +531,7 @@ EXTERN_C DWORD WINAPI Win32DeleteFileW(LPCWSTR path) * RETURNS * ERORR_SUCCESS if successful */ -static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest) +static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest, BOOL isdir) { BOOL ret; @@ -559,7 +559,8 @@ static DWORD SHNotifyMoveFileW(LPCWSTR src, LPCWSTR dest) } if (ret) { - SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_PATHW, src, dest); + SHChangeNotify(isdir ? SHCNE_MKDIR : SHCNE_CREATE, SHCNF_PATHW, dest, NULL); + SHChangeNotify(isdir ? SHCNE_RMDIR : SHCNE_DELETE, SHCNF_PATHW, src, NULL); return ERROR_SUCCESS; } return GetLastError(); @@ -1474,7 +1475,10 @@ static HRESULT delete_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom) { BOOL bDelete; if (TRASH_TrashFile(fileEntry->szFullPath)) + { + SHChangeNotify(SHCNE_DELETE, SHCNF_PATHW, fileEntry->szFullPath, NULL); continue; + } /* Note: Windows silently deletes the file in such a situation, we show a dialog */ if (!(lpFileOp->fFlags & FOF_NOCONFIRMATION) || (lpFileOp->fFlags & FOF_WANTNUKEWARNING)) @@ -1491,7 +1495,10 @@ static HRESULT delete_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom) /* delete the file or directory */ if (IsAttribFile(fileEntry->attributes)) + { bPathExists = DeleteFileW(fileEntry->szFullPath); + SHChangeNotify(SHCNE_DELETE, SHCNF_PATHW, fileEntry->szFullPath, NULL); + } else bPathExists = SHELL_DeleteDirectoryW(lpFileOp->hwnd, fileEntry->szFullPath, FALSE); @@ -1548,7 +1555,7 @@ static void move_to_dir(LPSHFILEOPSTRUCTW lpFileOp, const FILE_ENTRY *feFrom, co PathCombineW(szDestPath, feTo->szFullPath, feFrom->szFilename); if (IsAttribFile(feFrom->attributes)) - SHNotifyMoveFileW(feFrom->szFullPath, szDestPath); + SHNotifyMoveFileW(feFrom->szFullPath, szDestPath, FALSE); else if (!(lpFileOp->fFlags & FOF_FILESONLY && feFrom->bFromWildcard)) move_dir_to_dir(lpFileOp, feFrom, szDestPath); } @@ -1599,7 +1606,7 @@ static HRESULT move_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom, c if (fileDest->bExists && IsAttribDir(fileDest->attributes)) move_to_dir(lpFileOp, entryToMove, fileDest); else - SHNotifyMoveFileW(entryToMove->szFullPath, fileDest->szFullPath); + SHNotifyMoveFileW(entryToMove->szFullPath, fileDest->szFullPath, IsAttribDir(entryToMove->attributes)); } return ERROR_SUCCESS; @@ -1628,7 +1635,7 @@ static HRESULT rename_files(LPSHFILEOPSTRUCTW lpFileOp, const FILE_LIST *flFrom, if (feTo->bExists) return ERROR_ALREADY_EXISTS; - return SHNotifyMoveFileW(feFrom->szFullPath, feTo->szFullPath); + return SHNotifyMoveFileW(feFrom->szFullPath, feTo->szFullPath, IsAttribDir(feFrom->attributes)); } /* alert the user if an unsupported flag is used */ diff --git a/reactos/dll/win32/shell32/shlview.cpp b/reactos/dll/win32/shell32/shlview.cpp index 5cf59f3a64a..5afc0e85fe5 100644 --- a/reactos/dll/win32/shell32/shlview.cpp +++ b/reactos/dll/win32/shell32/shlview.cpp @@ -1807,9 +1807,13 @@ LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL & break; case SHCNE_UPDATEITEM: + LV_RenameItem(Pidls[0], Pidls[0]); + break; + + case SHCNE_UPDATEDIR: + Refresh(); break; } - return TRUE; } @@ -2493,12 +2497,10 @@ HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINT { m_pCurDropTarget->Drop(pDataObject, grfKeyState, pt, pdwEffect); m_pCurDropTarget.Release(); - - this->Refresh(); } - m_pCurDataObject.Release(); m_iDragOverItem = 0; - + m_pCurDataObject.Release(); + m_iDragOverItem = 0; return S_OK; } diff --git a/reactos/dll/win32/shell32/shresdef.h b/reactos/dll/win32/shell32/shresdef.h index deebecb8839..607a42f01fe 100644 --- a/reactos/dll/win32/shell32/shresdef.h +++ b/reactos/dll/win32/shell32/shresdef.h @@ -523,3 +523,4 @@ #define IDR_DRVDEFEXT 148 #define IDR_MENUBAND 149 #define IDR_MENUDESKBAR 150 +#define IDR_EXEDROPHANDLER 151 diff --git a/reactos/include/psdk/shlguid_undoc.h b/reactos/include/psdk/shlguid_undoc.h index 24880ed8fdb..09eb3236f42 100644 --- a/reactos/include/psdk/shlguid_undoc.h +++ b/reactos/include/psdk/shlguid_undoc.h @@ -105,6 +105,8 @@ DEFINE_GUID(CLSID_ShellFileDefExt, 0x21B22460, 0x3AEA, 0x1069, 0xA2, 0xD DEFINE_GUID(CLSID_ShellDrvDefExt, 0x5F5295E0, 0x429F, 0x1069, 0xA2, 0xE2, 0x08, 0x00, 0x2B, 0x30, 0x30, 0x9D); DEFINE_GUID(CLSID_ShellNetDefExt, 0x86422020, 0x42A0, 0x1069, 0xA2, 0xE5, 0x08, 0x00, 0x2B, 0x30, 0x30, 0x9D); +DEFINE_GUID(CLSID_ExeDropHandler, 0x86C86720, 0x42A0, 0x1069, 0xA2, 0xE8, 0x08, 0x00, 0x2B, 0x30, 0x30, 0x9D); + #define CGID_IExplorerToolbar IID_IExplorerToolbar #define SID_IExplorerToolbar IID_IExplorerToolbar #define SID_ITargetFrame2 IID_ITargetFrame2