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