return ret ? S_OK : E_FAIL;
}
+void CDesktopFolder::SF_RegisterClipFmt()
+{
+ TRACE ("(%p)\n", this);
+
+ if (!cfShellIDList)
+ cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
+}
+
CDesktopFolder::CDesktopFolder()
{
pidlRoot = NULL;
sPathTarget = NULL;
+ cfShellIDList = 0;
+ SF_RegisterClipFmt();
+ fAcceptFmt = FALSE;
}
CDesktopFolder::~CDesktopFolder()
if (theEnumerator == NULL)
return E_OUTOFMEMORY;
- hResult = theEnumerator->QueryInterface (IID_IEnumIDList, (void **)&result);
+ hResult = theEnumerator->QueryInterface(IID_PPV_ARG(IEnumIDList, &result));
if (FAILED (hResult))
{
delete theEnumerator;
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))
{
SHFree (pidl);
hr = S_OK;
}
- else if (IsEqualIID (riid, IID_IDropTarget) && (cidl >= 1))
+ else if (IsEqualIID (riid, IID_IDropTarget))
{
- hr = this->QueryInterface (IID_IDropTarget, (LPVOID *)&pObj);
+ /* 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)));
+ else
+ hr = this->QueryInterface(IID_IDropTarget, (LPVOID*)&pObj);
}
else if ((IsEqualIID(riid, IID_IShellLinkW) ||
IsEqualIID(riid, IID_IShellLinkA)) && (cidl == 1))
if (_ILGetGUIDPointer(pidl))
{
- if (SUCCEEDED(BindToObject(pidl, NULL, IID_IShellFolder2, (LPVOID *)&psf)))
+ if (SUCCEEDED(BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder2, &psf))))
{
hr = psf->SetNameOf(hwndOwner, pidl, lpName, dwFlags, pPidlOut);
return hr;
return ret;
}
-HRESULT WINAPI CDesktopFolder::CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl)
+HRESULT WINAPI CDesktopFolder::CopyItems(IShellFolder *pSFFrom, UINT cidl, LPCITEMIDLIST *apidl, bool bCopy)
{
CComPtr<IPersistFolder2> ppf2;
WCHAR szSrcPath[MAX_PATH];
TRACE ("(%p)->(%p,%u,%p)\n", this, pSFFrom, cidl, apidl);
- pSFFrom->QueryInterface(IID_IPersistFolder2, (LPVOID *)&ppf2);
+ pSFFrom->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
if (ppf2)
{
if (FAILED(ppf2->GetCurFolder(&pidl)))
}
op.pTo = szTargetPath;
+ op.fFlags = 0;
}
else
{
op.pTo = pszTargetList;
+ op.fFlags = FOF_MULTIDESTFILES;
}
op.hwnd = GetActiveWindow();
- op.wFunc = FO_COPY;
- op.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR;
+ op.wFunc = bCopy ? FO_COPY : FO_MOVE;
+ op.fFlags |= FOF_ALLOWUNDO | FOF_NOCONFIRMMKDIR;
res = SHFileOperationW(&op);
}
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.
+ *
+ */
+BOOL CDesktopFolder::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 (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 CDesktopFolder::DragEnter(IDataObject *pDataObject,
+ DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
+{
+ FORMATETC fmt;
+
+ InitFormatEtc (fmt, cfShellIDList, TYMED_HGLOBAL);
+ fAcceptFmt = (S_OK == pDataObject->QueryGetData(&fmt)) ?
+ TRUE : FALSE;
+
+ QueryDrop(dwKeyState, pdwEffect);
+ return S_OK;
+}
+
+HRESULT WINAPI CDesktopFolder::DragOver(DWORD dwKeyState, POINTL pt,
+ DWORD *pdwEffect)
+{
+ TRACE("(%p)\n", this);
+
+ if (!pdwEffect)
+ return E_INVALIDARG;
+
+ QueryDrop(dwKeyState, pdwEffect);
+
+ return S_OK;
+}
+
+HRESULT WINAPI CDesktopFolder::DragLeave()
+{
+ TRACE("(%p)\n", this);
+ fAcceptFmt = FALSE;
+ return S_OK;
+}
+
+HRESULT WINAPI CDesktopFolder::Drop(IDataObject *pDataObject,
+ DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
+{
+ TRACE("(%p) object dropped desktop\n", this);
+
+ STGMEDIUM medium;
+ FORMATETC formatetc;
+ InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
+ HRESULT hr = pDataObject->GetData(&formatetc, &medium);
+ if (FAILED(hr))
+ return 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;
+ }
+
+ /* We only want to really move files around if they don't already
+ come from the desktop, or we're linking or copying */
+ if ((!_ILIsDesktop(pidl)) || (dwKeyState & MK_CONTROL))
+ {
+ LPITEMIDLIST pidl = NULL;
+
+ WCHAR szPath[MAX_PATH];
+ LPWSTR pathPtr;
+
+ /* build a complete path to create a simple pidl */
+ lstrcpynW(szPath, sPathTarget, MAX_PATH);
+ pathPtr = PathAddBackslashW(szPath);
+ //hr = _ILCreateFromPathW(szPath, &pidl);
+ hr = this->ParseDisplayName(NULL, NULL, szPath, NULL, &pidl, NULL);
+
+ if (SUCCEEDED(hr))
+ {
+ IDropTarget *pDT;
+ hr = this->BindToObject(pidl, NULL, IID_IDropTarget, (LPVOID*)&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));
+ }
+
+ /* Todo, rewrite the registry such that the icons are well placed.
+ Blocked by no bags implementation. */
+
+ SHFree(pidl);
+ _ILFreeaPidl(apidl, lpcida->cidl);
+ ReleaseStgMedium(&medium);
+ return hr;
+}
\ No newline at end of file