14efff7f4SKatayama Hirofumi MZ /*
24efff7f4SKatayama Hirofumi MZ * PROJECT: mydocs
34efff7f4SKatayama Hirofumi MZ * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
44efff7f4SKatayama Hirofumi MZ * PURPOSE: MyDocs implementation
54efff7f4SKatayama Hirofumi MZ * COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
64efff7f4SKatayama Hirofumi MZ */
74efff7f4SKatayama Hirofumi MZ
84efff7f4SKatayama Hirofumi MZ #include "precomp.hpp"
94efff7f4SKatayama Hirofumi MZ
104efff7f4SKatayama Hirofumi MZ WINE_DEFAULT_DEBUG_CHANNEL(mydocs);
114efff7f4SKatayama Hirofumi MZ
CMyDocsDropHandler()124efff7f4SKatayama Hirofumi MZ CMyDocsDropHandler::CMyDocsDropHandler()
134efff7f4SKatayama Hirofumi MZ {
144efff7f4SKatayama Hirofumi MZ InterlockedIncrement(&g_ModuleRefCnt);
154efff7f4SKatayama Hirofumi MZ }
164efff7f4SKatayama Hirofumi MZ
~CMyDocsDropHandler()174efff7f4SKatayama Hirofumi MZ CMyDocsDropHandler::~CMyDocsDropHandler()
184efff7f4SKatayama Hirofumi MZ {
194efff7f4SKatayama Hirofumi MZ InterlockedDecrement(&g_ModuleRefCnt);
204efff7f4SKatayama Hirofumi MZ }
214efff7f4SKatayama Hirofumi MZ
224efff7f4SKatayama Hirofumi MZ // IDropTarget
234efff7f4SKatayama Hirofumi MZ STDMETHODIMP
DragEnter(IDataObject * pDataObject,DWORD dwKeyState,POINTL pt,DWORD * pdwEffect)244efff7f4SKatayama Hirofumi MZ CMyDocsDropHandler::DragEnter(IDataObject *pDataObject, DWORD dwKeyState,
254efff7f4SKatayama Hirofumi MZ POINTL pt, DWORD *pdwEffect)
264efff7f4SKatayama Hirofumi MZ {
274efff7f4SKatayama Hirofumi MZ TRACE("(%p)\n", this);
284efff7f4SKatayama Hirofumi MZ
294efff7f4SKatayama Hirofumi MZ *pdwEffect &= DROPEFFECT_COPY; // Copy only
304efff7f4SKatayama Hirofumi MZ
314efff7f4SKatayama Hirofumi MZ return S_OK;
324efff7f4SKatayama Hirofumi MZ }
334efff7f4SKatayama Hirofumi MZ
344efff7f4SKatayama Hirofumi MZ STDMETHODIMP
DragOver(DWORD dwKeyState,POINTL pt,DWORD * pdwEffect)354efff7f4SKatayama Hirofumi MZ CMyDocsDropHandler::DragOver(DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
364efff7f4SKatayama Hirofumi MZ {
374efff7f4SKatayama Hirofumi MZ TRACE("(%p)\n", this);
384efff7f4SKatayama Hirofumi MZ
394efff7f4SKatayama Hirofumi MZ *pdwEffect &= DROPEFFECT_COPY; // Copy only
404efff7f4SKatayama Hirofumi MZ
414efff7f4SKatayama Hirofumi MZ return S_OK;
424efff7f4SKatayama Hirofumi MZ }
434efff7f4SKatayama Hirofumi MZ
DragLeave()444efff7f4SKatayama Hirofumi MZ STDMETHODIMP CMyDocsDropHandler::DragLeave()
454efff7f4SKatayama Hirofumi MZ {
464efff7f4SKatayama Hirofumi MZ TRACE("(%p)\n", this);
474efff7f4SKatayama Hirofumi MZ return S_OK;
484efff7f4SKatayama Hirofumi MZ }
494efff7f4SKatayama Hirofumi MZ
504efff7f4SKatayama Hirofumi MZ STDMETHODIMP
Drop(IDataObject * pDataObject,DWORD dwKeyState,POINTL pt,DWORD * pdwEffect)514efff7f4SKatayama Hirofumi MZ CMyDocsDropHandler::Drop(IDataObject *pDataObject, DWORD dwKeyState,
524efff7f4SKatayama Hirofumi MZ POINTL pt, DWORD *pdwEffect)
534efff7f4SKatayama Hirofumi MZ {
544efff7f4SKatayama Hirofumi MZ TRACE("(%p)\n", this);
554efff7f4SKatayama Hirofumi MZ
564efff7f4SKatayama Hirofumi MZ if (!pDataObject)
574efff7f4SKatayama Hirofumi MZ {
584efff7f4SKatayama Hirofumi MZ ERR("pDataObject is NULL\n");
594efff7f4SKatayama Hirofumi MZ *pdwEffect = 0;
604efff7f4SKatayama Hirofumi MZ DragLeave();
614efff7f4SKatayama Hirofumi MZ return E_POINTER;
624efff7f4SKatayama Hirofumi MZ }
634efff7f4SKatayama Hirofumi MZ
644efff7f4SKatayama Hirofumi MZ CComPtr<IShellFolder> pDesktop;
654efff7f4SKatayama Hirofumi MZ HRESULT hr = SHGetDesktopFolder(&pDesktop);
664efff7f4SKatayama Hirofumi MZ if (FAILED_UNEXPECTEDLY(hr))
674efff7f4SKatayama Hirofumi MZ return hr;
684efff7f4SKatayama Hirofumi MZ
694efff7f4SKatayama Hirofumi MZ // Retrieve an HIDA (handle of IDA)
70*eba16dc9SMark Jansen CDataObjectHIDA pida(pDataObject);
71*eba16dc9SMark Jansen if (FAILED_UNEXPECTEDLY(pida.hr()))
724efff7f4SKatayama Hirofumi MZ {
734efff7f4SKatayama Hirofumi MZ *pdwEffect = 0;
744efff7f4SKatayama Hirofumi MZ DragLeave();
75*eba16dc9SMark Jansen return pida.hr();
764efff7f4SKatayama Hirofumi MZ }
774efff7f4SKatayama Hirofumi MZ
784efff7f4SKatayama Hirofumi MZ UINT iItem, cItems = pida->cidl;
794efff7f4SKatayama Hirofumi MZ
804efff7f4SKatayama Hirofumi MZ // get the path of "My Documents"
814efff7f4SKatayama Hirofumi MZ WCHAR szzDir[MAX_PATH + 1];
824efff7f4SKatayama Hirofumi MZ SHGetSpecialFolderPathW(NULL, szzDir, CSIDL_PERSONAL, FALSE);
834efff7f4SKatayama Hirofumi MZ szzDir[lstrlenW(szzDir) + 1] = 0; // ends with double NULs
844efff7f4SKatayama Hirofumi MZ
854efff7f4SKatayama Hirofumi MZ // for all source items
864efff7f4SKatayama Hirofumi MZ CStringW strSrcList;
874efff7f4SKatayama Hirofumi MZ WCHAR szSrc[MAX_PATH];
882dc2ec9dSKatayama Hirofumi MZ PCIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(pida);
894efff7f4SKatayama Hirofumi MZ for (iItem = 0; iItem < cItems; ++iItem)
904efff7f4SKatayama Hirofumi MZ {
914efff7f4SKatayama Hirofumi MZ // query source pidl
922dc2ec9dSKatayama Hirofumi MZ PCITEMID_CHILD pidlChild = HIDA_GetPIDLItem(pida, iItem);
934efff7f4SKatayama Hirofumi MZ CComHeapPtr<ITEMIDLIST> pidl(ILCombine(pidlParent, pidlChild));
944efff7f4SKatayama Hirofumi MZ
954efff7f4SKatayama Hirofumi MZ // can get path?
964efff7f4SKatayama Hirofumi MZ szSrc[0] = 0;
974efff7f4SKatayama Hirofumi MZ if (!SHGetPathFromIDListW(pidl, szSrc))
984efff7f4SKatayama Hirofumi MZ {
994efff7f4SKatayama Hirofumi MZ // try to retrieve path from desktop
1004efff7f4SKatayama Hirofumi MZ STRRET strret;
1014efff7f4SKatayama Hirofumi MZ hr = pDesktop->GetDisplayNameOf(pidl, SHGDN_INFOLDER, &strret);
1024efff7f4SKatayama Hirofumi MZ if (FAILED_UNEXPECTEDLY(hr))
1034efff7f4SKatayama Hirofumi MZ break;
1044efff7f4SKatayama Hirofumi MZ hr = StrRetToBufW(&strret, pidl, szSrc, _countof(szSrc));
1054efff7f4SKatayama Hirofumi MZ if (FAILED_UNEXPECTEDLY(hr))
1064efff7f4SKatayama Hirofumi MZ break;
1074efff7f4SKatayama Hirofumi MZ if (!PathFileExistsW(szSrc))
1084efff7f4SKatayama Hirofumi MZ break;
1094efff7f4SKatayama Hirofumi MZ }
1104efff7f4SKatayama Hirofumi MZ
1114efff7f4SKatayama Hirofumi MZ if (iItem > 0)
1124efff7f4SKatayama Hirofumi MZ strSrcList += L'|'; // separator is '|'
1134efff7f4SKatayama Hirofumi MZ strSrcList += szSrc;
1144efff7f4SKatayama Hirofumi MZ }
1154efff7f4SKatayama Hirofumi MZ
1164efff7f4SKatayama Hirofumi MZ if (iItem != cItems)
1174efff7f4SKatayama Hirofumi MZ {
1184efff7f4SKatayama Hirofumi MZ // source not found
1194efff7f4SKatayama Hirofumi MZ CStringW strText;
1204efff7f4SKatayama Hirofumi MZ strText.Format(IDS_NOSRCFILEFOUND, szSrc[0] ? szSrc : L"(null)");
1214efff7f4SKatayama Hirofumi MZ MessageBoxW(NULL, strText, NULL, MB_ICONERROR);
1224efff7f4SKatayama Hirofumi MZ
1234efff7f4SKatayama Hirofumi MZ *pdwEffect = 0;
1244efff7f4SKatayama Hirofumi MZ DragLeave();
1254efff7f4SKatayama Hirofumi MZ return E_FAIL;
1264efff7f4SKatayama Hirofumi MZ }
1274efff7f4SKatayama Hirofumi MZ
1284efff7f4SKatayama Hirofumi MZ strSrcList += L"||"; // double separators
1294efff7f4SKatayama Hirofumi MZ
1304efff7f4SKatayama Hirofumi MZ // lock the buffer
1314efff7f4SKatayama Hirofumi MZ LPWSTR pszzSrcList = strSrcList.GetBuffer();
1324efff7f4SKatayama Hirofumi MZ
1334efff7f4SKatayama Hirofumi MZ // convert every separator to a NUL
1344efff7f4SKatayama Hirofumi MZ INT cch = strSrcList.GetLength();
1354efff7f4SKatayama Hirofumi MZ for (INT i = 0; i < cch; ++i)
1364efff7f4SKatayama Hirofumi MZ {
1374efff7f4SKatayama Hirofumi MZ if (pszzSrcList[i] == L'|')
1384efff7f4SKatayama Hirofumi MZ pszzSrcList[i] = L'\0';
1394efff7f4SKatayama Hirofumi MZ }
1404efff7f4SKatayama Hirofumi MZ
1414efff7f4SKatayama Hirofumi MZ // copy them
1424efff7f4SKatayama Hirofumi MZ SHFILEOPSTRUCTW fileop = { NULL };
1434efff7f4SKatayama Hirofumi MZ fileop.wFunc = FO_COPY;
1444efff7f4SKatayama Hirofumi MZ fileop.pFrom = pszzSrcList;
1454efff7f4SKatayama Hirofumi MZ fileop.pTo = szzDir;
1464efff7f4SKatayama Hirofumi MZ fileop.fFlags = FOF_ALLOWUNDO | FOF_FILESONLY | FOF_MULTIDESTFILES | FOF_NOCONFIRMMKDIR;
147a5a30fc2SKyle Katarn int res = SHFileOperationW(&fileop);
148a5a30fc2SKyle Katarn if (res)
149a5a30fc2SKyle Katarn {
150a5a30fc2SKyle Katarn ERR("SHFileOperationW failed with 0x%x\n", res);
151a5a30fc2SKyle Katarn hr = E_FAIL;
152a5a30fc2SKyle Katarn }
1534efff7f4SKatayama Hirofumi MZ
1544efff7f4SKatayama Hirofumi MZ // unlock buffer
1554efff7f4SKatayama Hirofumi MZ strSrcList.ReleaseBuffer();
1564efff7f4SKatayama Hirofumi MZ
1574efff7f4SKatayama Hirofumi MZ DragLeave();
1584efff7f4SKatayama Hirofumi MZ return hr;
1594efff7f4SKatayama Hirofumi MZ }
1604efff7f4SKatayama Hirofumi MZ
1614efff7f4SKatayama Hirofumi MZ // IPersistFile
GetCurFile(LPOLESTR * ppszFileName)1624efff7f4SKatayama Hirofumi MZ STDMETHODIMP CMyDocsDropHandler::GetCurFile(LPOLESTR *ppszFileName)
1634efff7f4SKatayama Hirofumi MZ {
1644efff7f4SKatayama Hirofumi MZ FIXME("(%p)\n", this);
1654efff7f4SKatayama Hirofumi MZ return E_NOTIMPL;
1664efff7f4SKatayama Hirofumi MZ }
1674efff7f4SKatayama Hirofumi MZ
IsDirty()1684efff7f4SKatayama Hirofumi MZ STDMETHODIMP CMyDocsDropHandler::IsDirty()
1694efff7f4SKatayama Hirofumi MZ {
1704efff7f4SKatayama Hirofumi MZ FIXME("(%p)\n", this);
1714efff7f4SKatayama Hirofumi MZ return E_NOTIMPL;
1724efff7f4SKatayama Hirofumi MZ }
1734efff7f4SKatayama Hirofumi MZ
Load(LPCOLESTR pszFileName,DWORD dwMode)1744efff7f4SKatayama Hirofumi MZ STDMETHODIMP CMyDocsDropHandler::Load(LPCOLESTR pszFileName, DWORD dwMode)
1754efff7f4SKatayama Hirofumi MZ {
1764efff7f4SKatayama Hirofumi MZ return S_OK;
1774efff7f4SKatayama Hirofumi MZ }
1784efff7f4SKatayama Hirofumi MZ
Save(LPCOLESTR pszFileName,BOOL fRemember)1794efff7f4SKatayama Hirofumi MZ STDMETHODIMP CMyDocsDropHandler::Save(LPCOLESTR pszFileName, BOOL fRemember)
1804efff7f4SKatayama Hirofumi MZ {
1814efff7f4SKatayama Hirofumi MZ FIXME("(%p)\n", this);
1824efff7f4SKatayama Hirofumi MZ return E_NOTIMPL;
1834efff7f4SKatayama Hirofumi MZ }
1844efff7f4SKatayama Hirofumi MZ
SaveCompleted(LPCOLESTR pszFileName)1854efff7f4SKatayama Hirofumi MZ STDMETHODIMP CMyDocsDropHandler::SaveCompleted(LPCOLESTR pszFileName)
1864efff7f4SKatayama Hirofumi MZ {
1874efff7f4SKatayama Hirofumi MZ FIXME("(%p)\n", this);
1884efff7f4SKatayama Hirofumi MZ return E_NOTIMPL;
1894efff7f4SKatayama Hirofumi MZ }
1904efff7f4SKatayama Hirofumi MZ
1914efff7f4SKatayama Hirofumi MZ // IPersist
GetClassID(CLSID * lpClassId)1924efff7f4SKatayama Hirofumi MZ STDMETHODIMP CMyDocsDropHandler::GetClassID(CLSID * lpClassId)
1934efff7f4SKatayama Hirofumi MZ {
1944efff7f4SKatayama Hirofumi MZ TRACE("(%p)\n", this);
1954efff7f4SKatayama Hirofumi MZ
1964efff7f4SKatayama Hirofumi MZ if (!lpClassId)
1974efff7f4SKatayama Hirofumi MZ {
1984efff7f4SKatayama Hirofumi MZ ERR("lpClassId is NULL\n");
1994efff7f4SKatayama Hirofumi MZ return E_POINTER;
2004efff7f4SKatayama Hirofumi MZ }
2014efff7f4SKatayama Hirofumi MZ
2024efff7f4SKatayama Hirofumi MZ *lpClassId = CLSID_MyDocsDropHandler;
2034efff7f4SKatayama Hirofumi MZ
2044efff7f4SKatayama Hirofumi MZ return S_OK;
2054efff7f4SKatayama Hirofumi MZ }
206