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()
LPBC pbc,
LPOLESTR lpszDisplayName,
DWORD *pchEaten,
- LPITEMIDLIST *ppidl,
+ PIDLIST_RELATIVE *ppidl,
DWORD *pdwAttributes)
{
WCHAR szElement[MAX_PATH];
/**************************************************************************
* CDesktopFolder::EnumObjects
*/
-HRESULT WINAPI CDesktopFolder::EnumObjects(
- HWND hwndOwner,
- DWORD dwFlags,
- LPENUMIDLIST *ppEnumIDList)
+HRESULT WINAPI CDesktopFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
{
- CComObject<CDesktopFolderEnum> *theEnumerator;
- CComPtr<IEnumIDList> result;
- HRESULT hResult;
-
- TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner, dwFlags, ppEnumIDList);
-
- if (ppEnumIDList == NULL)
- return E_POINTER;
- *ppEnumIDList = NULL;
-
- ATLTRY (theEnumerator = new CComObject<CDesktopFolderEnum>);
-
- if (theEnumerator == NULL)
- return E_OUTOFMEMORY;
-
- hResult = theEnumerator->QueryInterface (IID_IEnumIDList, (void **)&result);
- if (FAILED (hResult))
- {
- delete theEnumerator;
- return hResult;
- }
-
- hResult = theEnumerator->Initialize (this, hwndOwner, dwFlags);
- if (FAILED (hResult))
- return hResult;
- *ppEnumIDList = result.Detach ();
-
- TRACE ("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList);
-
- return S_OK;
+ return ShellObjectCreatorInit<CDesktopFolderEnum>(this, hwndOwner, dwFlags, IID_IEnumIDList, ppEnumIDList);
}
/**************************************************************************
* CDesktopFolder::BindToObject
*/
HRESULT WINAPI CDesktopFolder::BindToObject(
- LPCITEMIDLIST pidl,
+ PCUIDLIST_RELATIVE pidl,
LPBC pbcReserved,
REFIID riid,
LPVOID *ppvOut)
* CDesktopFolder::BindToStorage
*/
HRESULT WINAPI CDesktopFolder::BindToStorage(
- LPCITEMIDLIST pidl,
+ PCUIDLIST_RELATIVE pidl,
LPBC pbcReserved,
REFIID riid,
LPVOID *ppvOut)
/**************************************************************************
* CDesktopFolder::CompareIDs
*/
-HRESULT WINAPI CDesktopFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
+HRESULT WINAPI CDesktopFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
{
int nReturn;
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))
{
*/
HRESULT WINAPI CDesktopFolder::GetAttributesOf(
UINT cidl,
- LPCITEMIDLIST *apidl,
+ PCUITEMID_CHILD_ARRAY apidl,
DWORD *rgfInOut)
{
HRESULT hr = S_OK;
HRESULT WINAPI CDesktopFolder::GetUIObjectOf(
HWND hwndOwner,
UINT cidl,
- LPCITEMIDLIST *apidl,
+ PCUITEMID_CHILD_ARRAY apidl,
REFIID riid,
UINT *prgfInOut,
LPVOID *ppvOut)
else if (IsEqualIID (riid, IID_IExtractIconA) && (cidl == 1))
{
pidl = ILCombine (pidlRoot, apidl[0]);
- pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
+ pObj = IExtractIconA_Constructor (pidl);
SHFree (pidl);
hr = S_OK;
}
else if (IsEqualIID (riid, IID_IExtractIconW) && (cidl == 1))
{
pidl = ILCombine (pidlRoot, apidl[0]);
- pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl);
+ pObj = IExtractIconW_Constructor (pidl);
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 || FAILED(hr = this->_GetDropTarget(apidl[0], (LPVOID*) &pObj)))
+ {
+ IDropTarget * pDt = NULL;
+ hr = this->QueryInterface(IID_PPV_ARG(IDropTarget, &pDt));
+ pObj = pDt;
+ }
}
else if ((IsEqualIID(riid, IID_IShellLinkW) ||
IsEqualIID(riid, IID_IShellLinkA)) && (cidl == 1))
* NOTES
* special case: pidl = null gives desktop-name back
*/
-HRESULT WINAPI CDesktopFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
+HRESULT WINAPI CDesktopFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
{
HRESULT hr = S_OK;
LPWSTR pszPath;
if ((clsid = _ILGetGUIDPointer (pidl)))
{
- if (GET_SHGDN_FOR (dwFlags) & SHGDN_FORPARSING)
+ if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING)
{
int bWantsForParsing;
*/
HRESULT WINAPI CDesktopFolder::SetNameOf(
HWND hwndOwner,
- LPCITEMIDLIST pidl, /* simple pidl */
+ PCUITEMID_CHILD pidl, /* simple pidl */
LPCOLESTR lpName,
DWORD dwFlags,
- LPITEMIDLIST *pPidlOut)
+ PITEMID_CHILD *pPidlOut)
{
CComPtr<IShellFolder2> psf;
HRESULT hr;
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;
}
HRESULT WINAPI CDesktopFolder::GetDetailsEx(
- LPCITEMIDLIST pidl,
+ PCUITEMID_CHILD pidl,
const SHCOLUMNID *pscid,
VARIANT *pv)
{
}
HRESULT WINAPI CDesktopFolder::GetDetailsOf(
- LPCITEMIDLIST pidl,
+ PCUITEMID_CHILD pidl,
UINT iColumn,
SHELLDETAILS *psd)
{
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)
+{
+ TRACE("(%p)->(DataObject=%p)\n", this, pDataObject);
+ FORMATETC fmt;
+ FORMATETC fmt2;
+ fAcceptFmt = FALSE;
+
+ InitFormatEtc (fmt, cfShellIDList, TYMED_HGLOBAL);
+ InitFormatEtc (fmt2, CF_HDROP, TYMED_HGLOBAL);
+
+ if (SUCCEEDED(pDataObject->QueryGetData(&fmt)))
+ fAcceptFmt = TRUE;
+ else if (SUCCEEDED(pDataObject->QueryGetData(&fmt2)))
+ fAcceptFmt = TRUE;
+
+ 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;
+ 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];
+ //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))
+ {
+ CComPtr<IDropTarget> pDT;
+ hr = this->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));
+ }
+
+ /* 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))
+ {
+ CComPtr<IShellFolder> psf;
+ hr = this->BindToObject(pidlNext, NULL, IID_PPV_ARG(IShellFolder, &psf));
+ CoTaskMemFree(pidlNext);
+ if (SUCCEEDED(hr))
+ {
+ hr = psf->GetUIObjectOf(NULL, 1, &pidl, IID_IDropTarget, NULL, ppvOut);
+ 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