/* Undocumented functions from shdocvw */
extern "C" HRESULT WINAPI IEParseDisplayNameWithBCW(DWORD codepage, LPCWSTR lpszDisplayName, LPBC pbc, LPITEMIDLIST *ppidl);
-/***********************************************************************
-* Desktopfolder implementation
-*/
-
-class CDesktopFolderDropTarget :
- public CComObjectRootEx<CComMultiThreadModelNoCS>,
- public IDropTarget
-{
- private:
- CComPtr<IShellFolder> m_psf;
- BOOL m_fAcceptFmt; /* flag for pending Drop */
- UINT m_cfShellIDList; /* clipboardformat for IDropTarget */
-
- void SF_RegisterClipFmt();
- BOOL QueryDrop (DWORD dwKeyState, LPDWORD pdwEffect);
- public:
- CDesktopFolderDropTarget();
-
- HRESULT WINAPI Initialize(IShellFolder *psf);
-
- // 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);
-
- BEGIN_COM_MAP(CDesktopFolderDropTarget)
- COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget)
- END_COM_MAP()
-};
-
class CDesktopFolderEnum :
public CEnumIDListBase
{
return Result;
}
-static VOID
-SetNamespaceExtensionVisibleStatus(const WCHAR * iid, DWORD dwStatus)
-{
- HKEY hKey;
-
- if (RegOpenKeyExW(HKEY_CURRENT_USER, ClassicStartMenuW, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS)
- {
- RegSetValueExW(hKey, iid, 0, REG_DWORD, (LPBYTE)&dwStatus, sizeof(DWORD));
- RegCloseKey(hKey);
- }
-}
-
/**************************************************************************
* CreateDesktopEnumList()
*/
HRESULT WINAPI CDesktopFolder::FinalConstruct()
{
WCHAR szMyPath[MAX_PATH];
+ HRESULT hr;
+ CComPtr<IPersistFolder3> ppf3;
+
+ /* Create the root pidl */
+ pidlRoot = _ILCreateDesktop();
+
+ /* Create the inner fs folder */
+ hr = SHCoCreateInstance(NULL, &CLSID_ShellFSFolder, NULL, IID_PPV_ARG(IShellFolder, &m_DesktopFSFolder));
+ if (FAILED(hr))
+ return hr;
+
+ hr = m_DesktopFSFolder->QueryInterface(IID_PPV_ARG(IPersistFolder3, &ppf3));
+ if (FAILED(hr))
+ return hr;
+
+ PERSIST_FOLDER_TARGET_INFO info;
+ ZeroMemory(&info, sizeof(PERSIST_FOLDER_TARGET_INFO));
+ info.csidl = CSIDL_DESKTOPDIRECTORY;
+ hr = ppf3->InitializeEx(NULL, pidlRoot, &info);
+
+ /* Create the inner shared fs folder */
+ hr = SHCoCreateInstance(NULL, &CLSID_ShellFSFolder, NULL, IID_PPV_ARG(IShellFolder, &m_SharedDesktopFSFolder));
+ if (FAILED(hr))
+ return hr;
+
+ hr = m_DesktopFSFolder->QueryInterface(IID_PPV_ARG(IPersistFolder3, &ppf3));
+ if (FAILED(hr))
+ return hr;
+
+ info.csidl = CSIDL_COMMON_DESKTOPDIRECTORY;
+ hr = ppf3->InitializeEx(NULL, pidlRoot, &info);
if (!SHGetSpecialFolderPathW( 0, szMyPath, CSIDL_DESKTOPDIRECTORY, TRUE ))
return E_UNEXPECTED;
- pidlRoot = _ILCreateDesktop(); /* my qualified pidl */
sPathTarget = (LPWSTR)SHAlloc((wcslen(szMyPath) + 1) * sizeof(WCHAR));
wcscpy(sPathTarget, szMyPath);
return S_OK;
}
else
{
- /* it's a filesystem path on the desktop. Let a FSFolder parse it */
-
if (*lpszDisplayName)
{
- WCHAR szPath[MAX_PATH];
- LPWSTR pathPtr;
+ /* it's a filesystem path on the desktop. Let a FSFolder parse it */
+ hr = m_DesktopFSFolder->ParseDisplayName(hwndOwner, pbc, lpszDisplayName, pchEaten, ppidl, pdwAttributes);
+ if (SUCCEEDED(hr))
+ return hr;
- /* build a complete path to create a simple pidl */
- lstrcpynW(szPath, sPathTarget, MAX_PATH);
- pathPtr = PathAddBackslashW(szPath);
- if (pathPtr)
- {
- lstrcpynW(pathPtr, lpszDisplayName, MAX_PATH - (pathPtr - szPath));
- hr = _ILCreateFromPathW(szPath, &pidlTemp);
- }
- else
- {
- /* should never reach here, but for completeness */
- hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
- }
+ return m_SharedDesktopFSFolder->ParseDisplayName(hwndOwner, pbc, lpszDisplayName, pchEaten, ppidl, pdwAttributes);
}
else
pidlTemp = _ILCreateMyComputer();
*/
HRESULT WINAPI CDesktopFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
{
- int nReturn;
+ if (_ILIsSpecialFolder(pidl1) || _ILIsSpecialFolder(pidl2))
+ return SHELL32_CompareIDs ((IShellFolder *)this, lParam, pidl1, pidl2);
- TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam, pidl1, pidl2);
- nReturn = SHELL32_CompareIDs ((IShellFolder *)this, lParam, pidl1, pidl2);
- TRACE ("-- %i\n", nReturn);
- return nReturn;
+ return m_DesktopFSFolder->CompareIDs(lParam, pidl1, pidl2);
}
/**************************************************************************
if (IsEqualIID (riid, IID_IDropTarget))
{
- hr = ShellObjectCreatorInit<CDesktopFolderDropTarget>(this, IID_IDropTarget, ppvOut);
+ hr = m_DesktopFSFolder->CreateViewObject(hwndOwner, riid, ppvOut);
}
else if (IsEqualIID (riid, IID_IContextMenu))
{
else if (_ILIsNetHood(apidl[i]))
*rgfInOut &= dwMyNetPlacesAttributes;
else if (_ILIsSpecialFolder(apidl[i]))
- SHELL32_GetItemAttributes(this, apidl[i], rgfInOut);
+ SHELL32_GetGuidItemAttributes(this, apidl[i], rgfInOut);
else if(_ILIsFolder(apidl[i]) || _ILIsValue(apidl[i]))
SHELL32_GetItemAttributes(this, apidl[i], rgfInOut);
else
else if (IsEqualIID (riid, IID_IDropTarget))
{
/* only interested in attempting to bind to shell folders, not files, semicolon intentionate */
- if (cidl != 1 || FAILED(hr = this->_GetDropTarget(apidl[0], (LPVOID*) &pObj)))
+ if (cidl > 1)
{
- IDropTarget * pDt = NULL;
- hr = ShellObjectCreatorInit<CDesktopFolderDropTarget>(this, IID_IDropTarget, &pDt);
- pObj = pDt;
+ hr = this->_GetDropTarget(apidl[0], (LPVOID*) &pObj);
}
}
else if ((IsEqualIID(riid, IID_IShellLinkW) ||
if (!strRet)
return E_INVALIDARG;
+ if (!_ILIsDesktop(pidl) && _ILIsPidlSimple(pidl) && _ILIsSpecialFolder(pidl))
+ {
+ return SHELL32_GetDisplayNameOfGUIDItem(this, L"", pidl, dwFlags, strRet);
+ }
+
pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
if (!pszPath)
return E_OUTOFMEMORY;
}
else if (_ILIsPidlSimple (pidl))
{
- GUID const *clsid;
+ int cLen = 0;
- if ((clsid = _ILGetGUIDPointer (pidl)))
+ /* file system folder or file rooted at the desktop */
+ if ((GET_SHGDN_FOR(dwFlags) == SHGDN_FORPARSING) &&
+ (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER))
{
- if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING)
- {
- int bWantsForParsing;
-
- /*
- * We can only get a filesystem path from a shellfolder if the
- * value WantsFORPARSING in CLSID\\{...}\\shellfolder exists.
- *
- * Exception: The MyComputer folder doesn't have this key,
- * but any other filesystem backed folder it needs it.
- */
- if (IsEqualIID (*clsid, CLSID_MyComputer))
- {
- bWantsForParsing = TRUE;
- }
- else
- {
- /* get the "WantsFORPARSING" flag from the registry */
- static const WCHAR clsidW[] =
- { 'C', 'L', 'S', 'I', 'D', '\\', 0 };
- static const WCHAR shellfolderW[] =
- { '\\', 's', 'h', 'e', 'l', 'l', 'f', 'o', 'l', 'd', 'e', 'r', 0 };
- static const WCHAR wantsForParsingW[] =
- { 'W', 'a', 'n', 't', 's', 'F', 'o', 'r', 'P', 'a', 'r', 's', 'i', 'n',
- 'g', 0
- };
- WCHAR szRegPath[100];
- LONG r;
+ lstrcpynW(pszPath, sPathTarget, MAX_PATH - 1);
+ PathAddBackslashW(pszPath);
+ cLen = wcslen(pszPath);
+ }
- wcscpy (szRegPath, clsidW);
- SHELL32_GUIDToStringW (*clsid, &szRegPath[6]);
- wcscat (szRegPath, shellfolderW);
- r = SHGetValueW(HKEY_CLASSES_ROOT, szRegPath,
- wantsForParsingW, NULL, NULL, NULL);
- if (r == ERROR_SUCCESS)
- bWantsForParsing = TRUE;
- else
- bWantsForParsing = FALSE;
- }
+ _ILSimpleGetTextW(pidl, pszPath + cLen, MAX_PATH - cLen);
+ if (!_ILIsFolder(pidl))
+ SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags);
- if ((GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL) &&
- bWantsForParsing)
- {
- /*
- * we need the filesystem path to the destination folder.
- * Only the folder itself can know it
- */
- hr = SHELL32_GetDisplayNameOfChild (this, pidl, dwFlags,
- pszPath,
- MAX_PATH);
- }
- else
- {
- /* parsing name like ::{...} */
- pszPath[0] = ':';
- pszPath[1] = ':';
- SHELL32_GUIDToStringW (*clsid, &pszPath[2]);
- }
- }
- else
- {
- /* user friendly name */
- HCR_GetClassNameW (*clsid, pszPath, MAX_PATH);
- }
- }
- else
+ if (GetFileAttributes(pszPath) == INVALID_FILE_ATTRIBUTES)
{
- int cLen = 0;
-
- /* file system folder or file rooted at the desktop */
+ /* file system folder or file rooted at the AllUsers desktop */
if ((GET_SHGDN_FOR(dwFlags) == SHGDN_FORPARSING) &&
(GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER))
{
- lstrcpynW(pszPath, sPathTarget, MAX_PATH - 1);
+ SHGetSpecialFolderPathW(0, pszPath, CSIDL_COMMON_DESKTOPDIRECTORY, FALSE);
PathAddBackslashW(pszPath);
cLen = wcslen(pszPath);
}
_ILSimpleGetTextW(pidl, pszPath + cLen, MAX_PATH - cLen);
if (!_ILIsFolder(pidl))
SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags);
-
- if (GetFileAttributes(pszPath) == INVALID_FILE_ATTRIBUTES)
- {
- /* file system folder or file rooted at the AllUsers desktop */
- if ((GET_SHGDN_FOR(dwFlags) == SHGDN_FORPARSING) &&
- (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER))
- {
- SHGetSpecialFolderPathW(0, pszPath, CSIDL_COMMON_DESKTOPDIRECTORY, FALSE);
- PathAddBackslashW(pszPath);
- cLen = wcslen(pszPath);
- }
-
- _ILSimpleGetTextW(pidl, pszPath + cLen, MAX_PATH - cLen);
- if (!_ILIsFolder(pidl))
- SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags);
- }
}
}
else
HRESULT WINAPI CDesktopFolder::GetUniqueName(LPWSTR pwszName, UINT uLen)
{
- CComPtr<IEnumIDList> penum;
- HRESULT hr;
- WCHAR wszText[MAX_PATH];
- WCHAR wszNewFolder[25];
- const WCHAR wszFormat[] = {'%', 's', ' ', '%', 'd', 0 };
-
- LoadStringW(shell32_hInstance, IDS_NEWFOLDER, wszNewFolder, sizeof(wszNewFolder) / sizeof(WCHAR));
-
- TRACE ("(%p)(%p %u)\n", this, pwszName, uLen);
-
- if (uLen < sizeof(wszNewFolder) / sizeof(WCHAR) + 3)
- return E_POINTER;
-
- lstrcpynW (pwszName, wszNewFolder, uLen);
-
- hr = EnumObjects(0,
- SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
- if (penum) {
- LPITEMIDLIST pidl;
- DWORD dwFetched;
- int i = 1;
-
-next:
- penum->Reset ();
- while (S_OK == penum->Next(1, &pidl, &dwFetched) &&
- dwFetched) {
- _ILSimpleGetTextW (pidl, wszText, MAX_PATH);
- if (0 == lstrcmpiW (wszText, pwszName)) {
- _snwprintf (pwszName, uLen, wszFormat, wszNewFolder, i++);
- if (i > 99) {
- hr = E_FAIL;
- break;
- }
- goto next;
- }
- }
+ CComPtr<ISFHelper> psfHelper;
+ HRESULT hr = m_DesktopFSFolder->QueryInterface(IID_PPV_ARG(ISFHelper, &psfHelper));
+ if (FAILED(hr))
+ return hr;
- }
- return hr;
+ return psfHelper->GetUniqueName(pwszName, uLen);
}
HRESULT WINAPI CDesktopFolder::AddFolder(HWND hwnd, LPCWSTR pwszName, LPITEMIDLIST *ppidlOut)
{
- WCHAR wszNewDir[MAX_PATH];
- DWORD bRes;
- HRESULT hres = E_FAIL;
-
- TRACE ("(%p)(%s %p)\n", this, debugstr_w(pwszName), ppidlOut);
-
- wszNewDir[0] = 0;
- if (sPathTarget)
- lstrcpynW(wszNewDir, sPathTarget, MAX_PATH);
- PathAppendW(wszNewDir, pwszName);
- bRes = CreateDirectoryW (wszNewDir, NULL);
- if (bRes)
- {
- SHChangeNotify (SHCNE_MKDIR, SHCNF_PATHW, wszNewDir, NULL);
- hres = S_OK;
- if (ppidlOut)
- hres = _ILCreateFromPathW(wszNewDir, ppidlOut);
- }
+ CComPtr<ISFHelper> psfHelper;
+ HRESULT hr = m_DesktopFSFolder->QueryInterface(IID_PPV_ARG(ISFHelper, &psfHelper));
+ if (FAILED(hr))
+ return hr;
- return hres;
+ return psfHelper->AddFolder(hwnd, pwszName, ppidlOut);
}
HRESULT WINAPI CDesktopFolder::DeleteItems(UINT cidl, LPCITEMIDLIST *apidl)
{
- UINT i;
- SHFILEOPSTRUCTW op;
- WCHAR wszPath[MAX_PATH];
- WCHAR wszCaption[50];
- WCHAR *wszPathsList;
- HRESULT ret;
- WCHAR *wszCurrentPath;
- UINT bRestoreWithDeskCpl = FALSE;
- int res;
-
- TRACE ("(%p)(%u %p)\n", this, cidl, apidl);
- if (cidl == 0) return S_OK;
-
- for(i = 0; i < cidl; i++)
- {
- if (_ILIsMyComputer(apidl[i]))
- bRestoreWithDeskCpl++;
- else if (_ILIsNetHood(apidl[i]))
- bRestoreWithDeskCpl++;
- else if (_ILIsMyDocuments(apidl[i]))
- bRestoreWithDeskCpl++;
- }
-
- if (bRestoreWithDeskCpl)
- {
- /* FIXME use FormatMessage
- * use a similar message resource as in windows
- */
- LoadStringW(shell32_hInstance, IDS_DELETEMULTIPLE_TEXT, wszPath, sizeof(wszPath) / sizeof(WCHAR));
- wszPath[(sizeof(wszPath)/sizeof(WCHAR))-1] = 0;
-
- LoadStringW(shell32_hInstance, IDS_DELETEITEM_CAPTION, wszCaption, sizeof(wszCaption) / sizeof(WCHAR));
- wszCaption[(sizeof(wszCaption)/sizeof(WCHAR))-1] = 0;
-
- res = SHELL_ConfirmMsgBox(GetActiveWindow(), wszPath, wszCaption, NULL, cidl > 1);
- if (res == IDC_YESTOALL || res == IDYES)
- {
- for(i = 0; i < cidl; i++)
- {
- if (_ILIsMyComputer(apidl[i]))
- SetNamespaceExtensionVisibleStatus(L"{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 0x1);
- else if (_ILIsNetHood(apidl[i]))
- SetNamespaceExtensionVisibleStatus(L"{208D2C60-3AEA-1069-A2D7-08002B30309D}", 0x1);
- else if (_ILIsMyDocuments(apidl[i]))
- SetNamespaceExtensionVisibleStatus(L"{450D8FBA-AD25-11D0-98A8-0800361B1103}", 0x1);
- }
- }
- }
- if (sPathTarget)
- lstrcpynW(wszPath, sPathTarget, MAX_PATH);
- else
- wszPath[0] = '\0';
-
- PathAddBackslashW(wszPath);
- wszPathsList = BuildPathsList(wszPath, cidl, apidl);
-
- ZeroMemory(&op, sizeof(op));
- op.hwnd = GetActiveWindow();
- op.wFunc = FO_DELETE;
- op.pFrom = wszPathsList;
- op.fFlags = FOF_ALLOWUNDO;
- if (SHFileOperationW(&op))
- {
- WARN("SHFileOperation failed\n");
- ret = E_FAIL;
- }
- else
- ret = S_OK;
-
- /* we currently need to manually send the notifies */
- wszCurrentPath = wszPathsList;
- for (i = 0; i < cidl; i++)
- {
- LONG wEventId;
-
- if (_ILIsFolder(apidl[i]))
- wEventId = SHCNE_RMDIR;
- else if (_ILIsValue(apidl[i]))
- wEventId = SHCNE_DELETE;
- else
- continue;
-
- /* check if file exists */
- if (GetFileAttributesW(wszCurrentPath) == INVALID_FILE_ATTRIBUTES)
- {
- LPITEMIDLIST pidl = ILCombine(pidlRoot, apidl[i]);
- SHChangeNotify(wEventId, SHCNF_IDLIST, pidl, NULL);
- SHFree(pidl);
- }
-
- wszCurrentPath += wcslen(wszCurrentPath) + 1;
- }
- HeapFree(GetProcessHeap(), 0, wszPathsList);
- return ret;
+ return E_NOTIMPL;
}
HRESULT WINAPI CDesktopFolder::CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, BOOL bCopy)
{
- CComPtr<IPersistFolder2> ppf2;
- WCHAR szSrcPath[MAX_PATH];
- WCHAR szTargetPath[MAX_PATH];
- SHFILEOPSTRUCTW op;
- LPITEMIDLIST pidl;
- LPWSTR pszSrc, pszTarget, pszSrcList, pszTargetList, pszFileName;
- int res, length;
- STRRET strRet;
-
- TRACE ("(%p)->(%p,%u,%p)\n", this, pSFFrom, cidl, apidl);
-
- pSFFrom->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
- if (ppf2)
- {
- if (FAILED(ppf2->GetCurFolder(&pidl)))
- return E_FAIL;
-
- if (FAILED(pSFFrom->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strRet)))
- {
- SHFree (pidl);
- return E_FAIL;
- }
-
- if (FAILED(StrRetToBufW(&strRet, pidl, szSrcPath, MAX_PATH)))
- {
- SHFree (pidl);
- return E_FAIL;
- }
- SHFree (pidl);
-
- pszSrc = PathAddBackslashW (szSrcPath);
-
- wcscpy(szTargetPath, sPathTarget);
- pszTarget = PathAddBackslashW (szTargetPath);
-
- pszSrcList = BuildPathsList(szSrcPath, cidl, apidl);
- pszTargetList = BuildPathsList(szTargetPath, cidl, apidl);
-
- if (!pszSrcList || !pszTargetList)
- {
- if (pszSrcList)
- HeapFree(GetProcessHeap(), 0, pszSrcList);
-
- if (pszTargetList)
- HeapFree(GetProcessHeap(), 0, pszTargetList);
-
- SHFree (pidl);
- return E_OUTOFMEMORY;
- }
- ZeroMemory(&op, sizeof(op));
- if (!pszSrcList[0])
- {
- /* remove trailing backslash */
- pszSrc--;
- pszSrc[0] = L'\0';
- op.pFrom = szSrcPath;
- }
- else
- {
- op.pFrom = pszSrcList;
- }
-
- if (!pszTargetList[0])
- {
- /* remove trailing backslash */
- if (pszTarget - szTargetPath > 3)
- {
- pszTarget--;
- pszTarget[0] = L'\0';
- }
- else
- {
- pszTarget[1] = L'\0';
- }
-
- op.pTo = szTargetPath;
- op.fFlags = 0;
- }
- else
- {
- op.pTo = pszTargetList;
- op.fFlags = FOF_MULTIDESTFILES;
- }
- op.hwnd = GetActiveWindow();
- op.wFunc = bCopy ? FO_COPY : FO_MOVE;
- op.fFlags |= FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR;
-
- res = SHFileOperationW(&op);
-
- if (res == DE_SAMEFILE)
- {
- length = wcslen(szTargetPath);
-
-
- pszFileName = wcsrchr(pszSrcList, '\\');
- pszFileName++;
-
- if (LoadStringW(shell32_hInstance, IDS_COPY_OF, pszTarget, MAX_PATH - length))
- {
- wcscat(szTargetPath, L" ");
- }
-
- wcscat(szTargetPath, pszFileName);
- op.pTo = szTargetPath;
-
- res = SHFileOperationW(&op);
- }
-
-
- HeapFree(GetProcessHeap(), 0, pszSrcList);
- HeapFree(GetProcessHeap(), 0, pszTargetList);
-
- if (res)
- return E_FAIL;
- else
- return S_OK;
- }
- return E_FAIL;
-}
-
-/****************************************************************************
- * IDropTarget implementation
- *
- * This should allow two somewhat separate things, copying files to the users directory,
- * as well as allowing icons to be moved anywhere and updating the registry to save.
- *
- * The first thing I think is best done using fs.cpp to prevent WET code. So we'll simulate
- * a drop to the user's home directory. The second will look at the pointer location and
- * set sensible places for the icons to live.
- *
- */
-void CDesktopFolderDropTarget::SF_RegisterClipFmt()
-{
- TRACE ("(%p)\n", this);
-
- if (!m_cfShellIDList)
- m_cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
-}
-
-CDesktopFolderDropTarget::CDesktopFolderDropTarget() :
- m_psf(NULL),
- m_fAcceptFmt(FALSE),
- m_cfShellIDList(0)
-{
-}
-
-HRESULT WINAPI CDesktopFolderDropTarget::Initialize(IShellFolder *psf)
-{
- m_psf = psf;
- SF_RegisterClipFmt();
- return S_OK;
-}
-
-BOOL CDesktopFolderDropTarget::QueryDrop(DWORD dwKeyState, LPDWORD pdwEffect)
-{
- /* TODO Windows does different drop effects if dragging across drives.
- i.e., it will copy instead of move if the directories are on different disks. */
-
- DWORD dwEffect = DROPEFFECT_MOVE;
-
- *pdwEffect = DROPEFFECT_NONE;
-
- if (m_fAcceptFmt) { /* Does our interpretation of the keystate ... */
- *pdwEffect = KeyStateToDropEffect (dwKeyState);
-
- if (*pdwEffect == DROPEFFECT_NONE)
- *pdwEffect = dwEffect;
-
- /* ... matches the desired effect ? */
- if (dwEffect & *pdwEffect) {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-HRESULT WINAPI CDesktopFolderDropTarget::DragEnter(IDataObject *pDataObject,
- DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
-{
- TRACE("(%p)->(DataObject=%p)\n", this, pDataObject);
- FORMATETC fmt;
- FORMATETC fmt2;
- m_fAcceptFmt = FALSE;
-
- InitFormatEtc (fmt, m_cfShellIDList, TYMED_HGLOBAL);
- InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
-
- if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
- m_fAcceptFmt = TRUE;
- else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2)))
- m_fAcceptFmt = TRUE;
-
- QueryDrop(dwKeyState, pdwEffect);
- return S_OK;
-}
-
-HRESULT WINAPI CDesktopFolderDropTarget::DragOver(DWORD dwKeyState, POINTL pt,
- DWORD *pdwEffect)
-{
- TRACE("(%p)\n", this);
-
- if (!pdwEffect)
- return E_INVALIDARG;
-
- QueryDrop(dwKeyState, pdwEffect);
-
- return S_OK;
-}
-
-HRESULT WINAPI CDesktopFolderDropTarget::DragLeave()
-{
- TRACE("(%p)\n", this);
- m_fAcceptFmt = FALSE;
- return S_OK;
-}
-
-HRESULT WINAPI CDesktopFolderDropTarget::Drop(IDataObject *pDataObject,
- DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
-{
- TRACE("(%p) object dropped desktop\n", this);
-
- STGMEDIUM medium;
- bool passthroughtofs = FALSE;
- FORMATETC formatetc;
- InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
-
- HRESULT hr = pDataObject->GetData(&formatetc, &medium);
- if (SUCCEEDED(hr))
- {
- /* lock the handle */
- LPIDA lpcida = (LPIDA)GlobalLock(medium.hGlobal);
- if (!lpcida)
- {
- ReleaseStgMedium(&medium);
- return E_FAIL;
- }
-
- /* convert the clipboard data into pidl (pointer to id list) */
- LPITEMIDLIST pidl;
- LPITEMIDLIST *apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
- if (!apidl)
- {
- ReleaseStgMedium(&medium);
- return E_FAIL;
- }
- passthroughtofs = !_ILIsDesktop(pidl) || (dwKeyState & MK_CONTROL);
- SHFree(pidl);
- _ILFreeaPidl(apidl, lpcida->cidl);
- ReleaseStgMedium(&medium);
- }
- else
- {
- InitFormatEtc (formatetc, CF_HDROP, TYMED_HGLOBAL);
- if (SUCCEEDED(pDataObject->QueryGetData(&formatetc)))
- {
- passthroughtofs = TRUE;
- }
- }
- /* We only want to really move files around if they don't already
- come from the desktop, or we're linking or copying */
- if (passthroughtofs)
- {
- LPITEMIDLIST pidl = NULL;
-
- WCHAR szPath[MAX_PATH];
- STRRET strRet;
- //LPWSTR pathPtr;
-
- /* build a complete path to create a simple pidl */
- hr = m_psf->GetDisplayNameOf(NULL, SHGDN_NORMAL | SHGDN_FORPARSING, &strRet);
- if (SUCCEEDED(hr))
- {
- hr = StrRetToBufW(&strRet, NULL, szPath, MAX_PATH);
- ASSERT(SUCCEEDED(hr));
- /*pathPtr = */PathAddBackslashW(szPath);
- //hr = _ILCreateFromPathW(szPath, &pidl);
- hr = m_psf->ParseDisplayName(NULL, NULL, szPath, NULL, &pidl, NULL);
- }
-
- if (SUCCEEDED(hr))
- {
- CComPtr<IDropTarget> pDT;
- hr = m_psf->BindToObject(pidl, NULL, IID_PPV_ARG(IDropTarget, &pDT));
- CoTaskMemFree(pidl);
- if (SUCCEEDED(hr))
- SHSimulateDrop(pDT, pDataObject, dwKeyState, NULL, pdwEffect);
- else
- ERR("Error Binding");
- }
- else
- ERR("Error creating from %s\n", debugstr_w(szPath));
- }
+ CComPtr<ISFHelper> psfHelper;
+ HRESULT hr = m_DesktopFSFolder->QueryInterface(IID_PPV_ARG(ISFHelper, &psfHelper));
+ if (FAILED(hr))
+ return hr;
- /* Todo, rewrite the registry such that the icons are well placed.
- Blocked by no bags implementation. */
- return hr;
+ return psfHelper->CopyItems(pSFFrom, cidl, apidl, bCopy);
}
HRESULT WINAPI CDesktopFolder::_GetDropTarget(LPCITEMIDLIST pidl, LPVOID *ppvOut) {