}
static const WCHAR ClassicStartMenuW[] = L"SOFTWARE\\Microsoft\\Windows\\"
- "CurrentVersion\\Explorer\\HideDesktopIcons\\ClassicStartMenu";
+ L"CurrentVersion\\Explorer\\HideDesktopIcons\\ClassicStartMenu";
static INT
IsNamespaceExtensionHidden(const WCHAR *iid)
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))
{
{
HRESULT hr = S_OK;
static const DWORD dwDesktopAttributes =
- SFGAO_STORAGE | SFGAO_HASPROPSHEET | SFGAO_STORAGEANCESTOR |
- SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_FILESYSTEM | SFGAO_HASSUBFOLDER;
+ SFGAO_HASSUBFOLDER | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR |
+ SFGAO_STORAGEANCESTOR | SFGAO_HASPROPSHEET | SFGAO_STORAGE | SFGAO_CANLINK;
static const DWORD dwMyComputerAttributes =
- SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET |
- SFGAO_DROPTARGET | SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
+ SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET |
+ SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_CANLINK;
+ static DWORD dwMyNetPlacesAttributes =
+ SFGAO_CANRENAME | SFGAO_CANDELETE | SFGAO_HASPROPSHEET | SFGAO_DROPTARGET |
+ SFGAO_FILESYSANCESTOR | SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_CANLINK;
- TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
- this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
+ TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
+ this, cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
- if (!rgfInOut)
- return E_INVALIDARG;
if (cidl && !apidl)
return E_INVALIDARG;
if (*rgfInOut == 0)
*rgfInOut = ~0;
- if(cidl == 0) {
+ if(cidl == 0)
*rgfInOut &= dwDesktopAttributes;
- } else {
- while (cidl > 0 && *apidl) {
- pdump (*apidl);
- if (_ILIsDesktop(*apidl)) {
+ else
+ {
+ /* TODO: always add SFGAO_CANLINK */
+ for (UINT i = 0; i < cidl; ++i)
+ {
+ pdump(*apidl);
+ if (_ILIsDesktop(*apidl))
*rgfInOut &= dwDesktopAttributes;
- } else if (_ILIsMyComputer(*apidl)) {
+ else if (_ILIsMyComputer(apidl[i]))
*rgfInOut &= dwMyComputerAttributes;
- } else {
- SHELL32_GetItemAttributes ((IShellFolder *)this, *apidl, rgfInOut);
- }
- apidl++;
- cidl--;
+ else if (_ILIsNetHood(apidl[i]))
+ *rgfInOut &= dwMyNetPlacesAttributes;
+ else
+ SHELL32_GetItemAttributes((IShellFolder *)this, apidl[i], rgfInOut);
}
}
/* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
*rgfInOut &= ~SFGAO_VALIDATE;
- TRACE ("-- result=0x%08x\n", *rgfInOut);
+ TRACE("-- result=0x%08x\n", *rgfInOut);
return hr;
}
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;
wszCaption[(sizeof(wszCaption)/sizeof(WCHAR))-1] = 0;
res = SHELL_ConfirmMsgBox(GetActiveWindow(), wszPath, wszCaption, NULL, cidl > 1);
- if (res == IDD_YESTOALL || res == IDYES)
+ if (res == IDC_YESTOALL || res == IDYES)
{
for(i = 0; i < cidl; i++)
{
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