Index: boot/bootdata/hivecls.inf =================================================================== --- boot/bootdata/hivecls.inf (revision 62412) +++ boot/bootdata/hivecls.inf (working copy) @@ -100,6 +100,7 @@ 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","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}" Index: dll/win32/shell32/changenotify.cpp =================================================================== --- dll/win32/shell32/changenotify.cpp (revision 62412) +++ dll/win32/shell32/changenotify.cpp (working copy) @@ -264,6 +264,25 @@ 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; } Index: dll/win32/shell32/CMakeLists.txt =================================================================== --- dll/win32/shell32/CMakeLists.txt (revision 62412) +++ dll/win32/shell32/CMakeLists.txt (working copy) @@ -54,6 +54,7 @@ folders/fonts.cpp folders/cpanel.cpp folders/recyclebin.cpp + droptargets/CexeDropHandler.cpp shlexec.cpp shlfileop.cpp shlfolder.cpp Index: dll/win32/shell32/droptargets =================================================================== --- dll/win32/shell32/droptargets (revision 0) +++ dll/win32/shell32/droptargets (working copy) Property changes on: dll/win32/shell32/droptargets ___________________________________________________________________ Added: bugtraq:message ## -0,0 +1 ## +See issue #%BUGID% for more details. \ No newline at end of property Added: tsvn:logminsize ## -0,0 +1 ## +10 \ No newline at end of property Added: bugtraq:logregex ## -0,0 +1,2 ## +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))? +(\d+) \ No newline at end of property Added: bugtraq:url ## -0,0 +1 ## +http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID% \ No newline at end of property Index: dll/win32/shell32/droptargets/CexeDropHandler.cpp =================================================================== --- dll/win32/shell32/droptargets/CexeDropHandler.cpp (revision 0) +++ dll/win32/shell32/droptargets/CexeDropHandler.cpp (working copy) @@ -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 Property changes on: dll/win32/shell32/droptargets/CexeDropHandler.cpp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: dll/win32/shell32/droptargets/CexeDropHandler.h =================================================================== --- dll/win32/shell32/droptargets/CexeDropHandler.h (revision 0) +++ dll/win32/shell32/droptargets/CexeDropHandler.h (working copy) @@ -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_ */ Property changes on: dll/win32/shell32/droptargets/CexeDropHandler.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: dll/win32/shell32/folders/cpanel.cpp =================================================================== --- dll/win32/shell32/folders/cpanel.cpp (revision 62412) +++ dll/win32/shell32/folders/cpanel.cpp (working copy) @@ -340,7 +340,7 @@ CLSIDFromString (szElement + 2, &clsid); pidlTemp = _ILCreateGuid (PT_GUID, clsid); } - else if( (pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, lpszDisplayName)) ) + else if( (pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, lpszDisplayName, FALSE)) ) { *ppidl = pidlTemp; return S_OK; Index: dll/win32/shell32/folders/desktop.cpp =================================================================== --- dll/win32/shell32/folders/desktop.cpp (revision 62412) +++ dll/win32/shell32/folders/desktop.cpp (working copy) @@ -348,7 +348,7 @@ pidlTemp = _ILCreateNetwork(); szNext = lpszDisplayName; } - else if( (pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, lpszDisplayName)) ) + else if( (pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, lpszDisplayName, FALSE)) ) { *ppidl = pidlTemp; return S_OK; @@ -651,7 +651,7 @@ 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 @@ else { InitFormatEtc (formatetc, CF_HDROP, TYMED_HGLOBAL); - if SUCCEEDED(pDataObject->QueryGetData(&formatetc)); + if (SUCCEEDED(pDataObject->QueryGetData(&formatetc))) { passthroughtofs = TRUE; } @@ -1488,4 +1488,53 @@ /* 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 Index: dll/win32/shell32/folders/desktop.h =================================================================== --- dll/win32/shell32/folders/desktop.h (revision 62412) +++ dll/win32/shell32/folders/desktop.h (working copy) @@ -40,6 +40,7 @@ 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(); Index: dll/win32/shell32/folders/fs.cpp =================================================================== --- dll/win32/shell32/folders/fs.cpp (revision 62412) +++ dll/win32/shell32/folders/fs.cpp (working copy) @@ -81,6 +81,7 @@ cfShellIDList = 0; SF_RegisterClipFmt(); fAcceptFmt = FALSE; + m_bGroupPolicyActive = 0; } CFSFolder::~CFSFolder() @@ -109,7 +110,7 @@ * find data for the path. * This allows binding of paths that don't exist. */ -LPITEMIDLIST SHELL32_CreatePidlFromBindCtx(IBindCtx *pbc, LPCWSTR path) +LPITEMIDLIST SHELL32_CreatePidlFromBindCtx(IBindCtx *pbc, LPCWSTR path, BOOL bFolder) { IFileSystemBindData *fsbd = NULL; LPITEMIDLIST pidl = NULL; @@ -134,6 +135,8 @@ if (SUCCEEDED(r)) { lstrcpynW(&wfd.cFileName[0], path, MAX_PATH); + if (bFolder) + wfd.dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY; pidl = _ILCreateFromFindDataW(&wfd); } fsbd->Release(); @@ -203,7 +206,7 @@ /* get the next element */ szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH); - pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, szElement); + pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, szElement, szNext != NULL); if (pidlTemp != NULL) { hr = S_OK; @@ -502,7 +505,7 @@ 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 +1620,9 @@ } hr = ppf->Save(wszTarget, FALSE); + if (FAILED(hr)) + break; + SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, wszTarget, NULL); } else { @@ -1653,6 +1659,9 @@ break; hr = ppf->Save(wszTarget, TRUE); + if (FAILED(hr)) + break; + SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, wszTarget, NULL); } } } @@ -1748,4 +1757,114 @@ //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 Index: dll/win32/shell32/folders/fs.h =================================================================== --- dll/win32/shell32/folders/fs.h (revision 62412) +++ dll/win32/shell32/folders/fs.h (working copy) @@ -44,10 +44,14 @@ 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(); Index: dll/win32/shell32/folders/mydocuments.cpp =================================================================== --- dll/win32/shell32/folders/mydocuments.cpp (revision 62412) +++ dll/win32/shell32/folders/mydocuments.cpp (working copy) @@ -78,6 +78,7 @@ { pidlRoot = NULL; sPathTarget = NULL; + mFSDropTarget = NULL; } CMyDocsFolder::~CMyDocsFolder() @@ -85,6 +86,7 @@ TRACE ("-- destroying IShellFolder(%p)\n", this); SHFree(pidlRoot); HeapFree(GetProcessHeap(), 0, sPathTarget); + mFSDropTarget->Release(); } HRESULT WINAPI CMyDocsFolder::FinalConstruct() @@ -98,6 +100,29 @@ 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; } @@ -129,7 +154,7 @@ CLSIDFromString(szElement + 2, &clsid); pidlTemp = _ILCreateGuid (PT_GUID, clsid); } - else if( (pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, lpszDisplayName)) ) + else if( (pidlTemp = SHELL32_CreatePidlFromBindCtx(pbc, lpszDisplayName, FALSE)) ) { *ppidl = pidlTemp; return S_OK; @@ -271,8 +296,7 @@ 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 @@ *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 Index: dll/win32/shell32/folders/mydocuments.h =================================================================== --- dll/win32/shell32/folders/mydocuments.h (revision 62412) +++ dll/win32/shell32/folders/mydocuments.h (working copy) @@ -26,12 +26,14 @@ 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 @@ // 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 @@ 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() }; Index: dll/win32/shell32/precomp.h =================================================================== --- dll/win32/shell32/precomp.h (revision 62412) +++ dll/win32/shell32/precomp.h (working copy) @@ -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" Index: dll/win32/shell32/res/rgs/exedrophandler.rgs =================================================================== --- dll/win32/shell32/res/rgs/exedrophandler.rgs (revision 0) +++ dll/win32/shell32/res/rgs/exedrophandler.rgs (working copy) @@ -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' + } + } + } +} \ No newline at end of file Property changes on: dll/win32/shell32/res/rgs/exedrophandler.rgs ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: dll/win32/shell32/rgs_res.rc =================================================================== --- dll/win32/shell32/rgs_res.rc (revision 62412) +++ dll/win32/shell32/rgs_res.rc (working copy) @@ -23,3 +23,4 @@ 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 Index: dll/win32/shell32/shell32_main.cpp =================================================================== --- dll/win32/shell32/shell32_main.cpp (revision 62412) +++ dll/win32/shell32/shell32_main.cpp (working copy) @@ -1371,6 +1371,7 @@ 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; Index: dll/win32/shell32/shelllink.cpp =================================================================== --- dll/win32/shell32/shelllink.cpp (revision 62412) +++ dll/win32/shell32/shelllink.cpp (working copy) @@ -2168,6 +2168,68 @@ 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 */ Index: dll/win32/shell32/shelllink.h =================================================================== --- dll/win32/shell32/shelllink.h (revision 62412) +++ dll/win32/shell32/shelllink.h (working copy) @@ -35,7 +35,8 @@ public IShellExtInit, public IContextMenu, public IObjectWithSite, - public IShellPropSheetExt + public IShellPropSheetExt, + public IDropTarget { public: /* link file formats */ @@ -75,6 +76,7 @@ BOOL bDirty; INT iIdOpen; /* id of the "Open" entry in the context menu */ CComPtr site; + IDropTarget *mDropTarget; public: CShellLink(); ~CShellLink(); @@ -160,6 +162,12 @@ 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) @@ -176,6 +184,7 @@ COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) COM_INTERFACE_ENTRY_IID(IID_IShellPropSheetExt, IShellPropSheetExt) COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite) + COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget) END_COM_MAP() }; Index: dll/win32/shell32/shfldr.h =================================================================== --- dll/win32/shell32/shfldr.h (revision 62412) +++ dll/win32/shell32/shfldr.h (working copy) @@ -49,7 +49,7 @@ 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); +LPITEMIDLIST SHELL32_CreatePidlFromBindCtx(IBindCtx *pbc, LPCWSTR path, BOOL bFolder); static int __inline SHELL32_GUIDToStringA (REFGUID guid, LPSTR str) { Index: dll/win32/shell32/shlfileop.cpp =================================================================== --- dll/win32/shell32/shlfileop.cpp (revision 62412) +++ dll/win32/shell32/shlfileop.cpp (working copy) @@ -559,7 +559,8 @@ } if (ret) { - SHChangeNotify(SHCNE_RENAMEITEM, SHCNF_PATHW, src, dest); + SHChangeNotify(SHCNE_CREATE, SHCNF_PATHW, dest, NULL); + SHChangeNotify(SHCNE_DELETE, SHCNF_PATHW, src, NULL); return ERROR_SUCCESS; } return GetLastError(); @@ -1474,7 +1475,10 @@ { 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,7 @@ /* delete the file or directory */ if (IsAttribFile(fileEntry->attributes)) - bPathExists = DeleteFileW(fileEntry->szFullPath); + bPathExists = SHNotifyDeleteFileW(fileEntry->szFullPath); else bPathExists = SHELL_DeleteDirectoryW(lpFileOp->hwnd, fileEntry->szFullPath, FALSE); Index: dll/win32/shell32/shresdef.h =================================================================== --- dll/win32/shell32/shresdef.h (revision 62412) +++ dll/win32/shell32/shresdef.h (working copy) @@ -523,3 +523,4 @@ #define IDR_DRVDEFEXT 148 #define IDR_MENUBAND 149 #define IDR_MENUDESKBAR 150 +#define IDR_EXEDROPHANDLER 151 Index: include/psdk/shlguid_undoc.h =================================================================== --- include/psdk/shlguid_undoc.h (revision 62412) +++ include/psdk/shlguid_undoc.h (working copy) @@ -105,6 +105,8 @@ 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