1 /* 2 * PROJECT: mydocs 3 * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+) 4 * PURPOSE: MyDocs implementation 5 * COPYRIGHT: Copyright 2020 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) 6 */ 7 8 #include "precomp.hpp" 9 10 WINE_DEFAULT_DEBUG_CHANNEL(mydocs); 11 12 CMyDocsDropHandler::CMyDocsDropHandler() 13 { 14 InterlockedIncrement(&g_ModuleRefCnt); 15 } 16 17 CMyDocsDropHandler::~CMyDocsDropHandler() 18 { 19 InterlockedDecrement(&g_ModuleRefCnt); 20 } 21 22 // IDropTarget 23 STDMETHODIMP 24 CMyDocsDropHandler::DragEnter(IDataObject *pDataObject, DWORD dwKeyState, 25 POINTL pt, DWORD *pdwEffect) 26 { 27 TRACE("(%p)\n", this); 28 29 *pdwEffect &= DROPEFFECT_COPY; // Copy only 30 31 return S_OK; 32 } 33 34 STDMETHODIMP 35 CMyDocsDropHandler::DragOver(DWORD dwKeyState, POINTL pt, DWORD *pdwEffect) 36 { 37 TRACE("(%p)\n", this); 38 39 *pdwEffect &= DROPEFFECT_COPY; // Copy only 40 41 return S_OK; 42 } 43 44 STDMETHODIMP CMyDocsDropHandler::DragLeave() 45 { 46 TRACE("(%p)\n", this); 47 return S_OK; 48 } 49 50 STDMETHODIMP 51 CMyDocsDropHandler::Drop(IDataObject *pDataObject, DWORD dwKeyState, 52 POINTL pt, DWORD *pdwEffect) 53 { 54 TRACE("(%p)\n", this); 55 56 if (!pDataObject) 57 { 58 ERR("pDataObject is NULL\n"); 59 *pdwEffect = 0; 60 DragLeave(); 61 return E_POINTER; 62 } 63 64 CComPtr<IShellFolder> pDesktop; 65 HRESULT hr = SHGetDesktopFolder(&pDesktop); 66 if (FAILED_UNEXPECTEDLY(hr)) 67 return hr; 68 69 // Retrieve an HIDA (handle of IDA) 70 CDataObjectHIDA pida(pDataObject); 71 if (FAILED_UNEXPECTEDLY(pida.hr())) 72 { 73 *pdwEffect = 0; 74 DragLeave(); 75 return pida.hr(); 76 } 77 78 UINT iItem, cItems = pida->cidl; 79 80 // get the path of "My Documents" 81 WCHAR szzDir[MAX_PATH + 1]; 82 SHGetSpecialFolderPathW(NULL, szzDir, CSIDL_PERSONAL, FALSE); 83 szzDir[lstrlenW(szzDir) + 1] = 0; // ends with double NULs 84 85 // for all source items 86 CStringW strSrcList; 87 WCHAR szSrc[MAX_PATH]; 88 PCIDLIST_ABSOLUTE pidlParent = HIDA_GetPIDLFolder(pida); 89 for (iItem = 0; iItem < cItems; ++iItem) 90 { 91 // query source pidl 92 PCITEMID_CHILD pidlChild = HIDA_GetPIDLItem(pida, iItem); 93 CComHeapPtr<ITEMIDLIST> pidl(ILCombine(pidlParent, pidlChild)); 94 95 // can get path? 96 szSrc[0] = 0; 97 if (!SHGetPathFromIDListW(pidl, szSrc)) 98 { 99 // try to retrieve path from desktop 100 STRRET strret; 101 hr = pDesktop->GetDisplayNameOf(pidl, SHGDN_INFOLDER, &strret); 102 if (FAILED_UNEXPECTEDLY(hr)) 103 break; 104 hr = StrRetToBufW(&strret, pidl, szSrc, _countof(szSrc)); 105 if (FAILED_UNEXPECTEDLY(hr)) 106 break; 107 if (!PathFileExistsW(szSrc)) 108 break; 109 } 110 111 if (iItem > 0) 112 strSrcList += L'|'; // separator is '|' 113 strSrcList += szSrc; 114 } 115 116 if (iItem != cItems) 117 { 118 // source not found 119 CStringW strText; 120 strText.Format(IDS_NOSRCFILEFOUND, szSrc[0] ? szSrc : L"(null)"); 121 MessageBoxW(NULL, strText, NULL, MB_ICONERROR); 122 123 *pdwEffect = 0; 124 DragLeave(); 125 return E_FAIL; 126 } 127 128 strSrcList += L"||"; // double separators 129 130 // lock the buffer 131 LPWSTR pszzSrcList = strSrcList.GetBuffer(); 132 133 // convert every separator to a NUL 134 INT cch = strSrcList.GetLength(); 135 for (INT i = 0; i < cch; ++i) 136 { 137 if (pszzSrcList[i] == L'|') 138 pszzSrcList[i] = L'\0'; 139 } 140 141 // copy them 142 SHFILEOPSTRUCTW fileop = { NULL }; 143 fileop.wFunc = FO_COPY; 144 fileop.pFrom = pszzSrcList; 145 fileop.pTo = szzDir; 146 fileop.fFlags = FOF_ALLOWUNDO | FOF_FILESONLY | FOF_MULTIDESTFILES | FOF_NOCONFIRMMKDIR; 147 int res = SHFileOperationW(&fileop); 148 if (res) 149 { 150 ERR("SHFileOperationW failed with 0x%x\n", res); 151 hr = E_FAIL; 152 } 153 154 // unlock buffer 155 strSrcList.ReleaseBuffer(); 156 157 DragLeave(); 158 return hr; 159 } 160 161 // IPersistFile 162 STDMETHODIMP CMyDocsDropHandler::GetCurFile(LPOLESTR *ppszFileName) 163 { 164 FIXME("(%p)\n", this); 165 return E_NOTIMPL; 166 } 167 168 STDMETHODIMP CMyDocsDropHandler::IsDirty() 169 { 170 FIXME("(%p)\n", this); 171 return E_NOTIMPL; 172 } 173 174 STDMETHODIMP CMyDocsDropHandler::Load(LPCOLESTR pszFileName, DWORD dwMode) 175 { 176 return S_OK; 177 } 178 179 STDMETHODIMP CMyDocsDropHandler::Save(LPCOLESTR pszFileName, BOOL fRemember) 180 { 181 FIXME("(%p)\n", this); 182 return E_NOTIMPL; 183 } 184 185 STDMETHODIMP CMyDocsDropHandler::SaveCompleted(LPCOLESTR pszFileName) 186 { 187 FIXME("(%p)\n", this); 188 return E_NOTIMPL; 189 } 190 191 // IPersist 192 STDMETHODIMP CMyDocsDropHandler::GetClassID(CLSID * lpClassId) 193 { 194 TRACE("(%p)\n", this); 195 196 if (!lpClassId) 197 { 198 ERR("lpClassId is NULL\n"); 199 return E_POINTER; 200 } 201 202 *lpClassId = CLSID_MyDocsDropHandler; 203 204 return S_OK; 205 } 206