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)
10 WINE_DEFAULT_DEBUG_CHANNEL(mydocs
);
12 static CLIPFORMAT g_cfHIDA
= 0;
14 CMyDocsDropHandler::CMyDocsDropHandler()
16 InterlockedIncrement(&g_ModuleRefCnt
);
19 CMyDocsDropHandler::~CMyDocsDropHandler()
21 InterlockedDecrement(&g_ModuleRefCnt
);
26 CMyDocsDropHandler::DragEnter(IDataObject
*pDataObject
, DWORD dwKeyState
,
27 POINTL pt
, DWORD
*pdwEffect
)
29 TRACE("(%p)\n", this);
31 *pdwEffect
&= DROPEFFECT_COPY
; // Copy only
37 CMyDocsDropHandler::DragOver(DWORD dwKeyState
, POINTL pt
, DWORD
*pdwEffect
)
39 TRACE("(%p)\n", this);
41 *pdwEffect
&= DROPEFFECT_COPY
; // Copy only
46 STDMETHODIMP
CMyDocsDropHandler::DragLeave()
48 TRACE("(%p)\n", this);
53 CMyDocsDropHandler::Drop(IDataObject
*pDataObject
, DWORD dwKeyState
,
54 POINTL pt
, DWORD
*pdwEffect
)
56 TRACE("(%p)\n", this);
60 ERR("pDataObject is NULL\n");
66 CComPtr
<IShellFolder
> pDesktop
;
67 HRESULT hr
= SHGetDesktopFolder(&pDesktop
);
68 if (FAILED_UNEXPECTEDLY(hr
))
71 // get the clipboard format
73 g_cfHIDA
= ::RegisterClipboardFormatW(CFSTR_SHELLIDLIST
);
75 // Retrieve an HIDA (handle of IDA)
77 FORMATETC fmt
= { g_cfHIDA
, NULL
, DVASPECT_CONTENT
, -1, TYMED_HGLOBAL
};
78 hr
= pDataObject
->GetData(&fmt
, &medium
);
79 if (FAILED_UNEXPECTEDLY(hr
))
87 LPIDA pida
= reinterpret_cast<LPIDA
>(GlobalLock(medium
.hGlobal
));
88 UINT iItem
, cItems
= pida
->cidl
;
90 // get the path of "My Documents"
91 WCHAR szzDir
[MAX_PATH
+ 1];
92 SHGetSpecialFolderPathW(NULL
, szzDir
, CSIDL_PERSONAL
, FALSE
);
93 szzDir
[lstrlenW(szzDir
) + 1] = 0; // ends with double NULs
95 // for all source items
97 WCHAR szSrc
[MAX_PATH
];
98 PCIDLIST_ABSOLUTE pidlParent
= HIDA_GetPIDLFolder(pida
);
99 for (iItem
= 0; iItem
< cItems
; ++iItem
)
102 PCITEMID_CHILD pidlChild
= HIDA_GetPIDLItem(pida
, iItem
);
103 CComHeapPtr
<ITEMIDLIST
> pidl(ILCombine(pidlParent
, pidlChild
));
107 if (!SHGetPathFromIDListW(pidl
, szSrc
))
109 // try to retrieve path from desktop
111 hr
= pDesktop
->GetDisplayNameOf(pidl
, SHGDN_INFOLDER
, &strret
);
112 if (FAILED_UNEXPECTEDLY(hr
))
114 hr
= StrRetToBufW(&strret
, pidl
, szSrc
, _countof(szSrc
));
115 if (FAILED_UNEXPECTEDLY(hr
))
117 if (!PathFileExistsW(szSrc
))
122 strSrcList
+= L
'|'; // separator is '|'
127 GlobalUnlock(medium
.hGlobal
);
133 strText
.Format(IDS_NOSRCFILEFOUND
, szSrc
[0] ? szSrc
: L
"(null)");
134 MessageBoxW(NULL
, strText
, NULL
, MB_ICONERROR
);
141 strSrcList
+= L
"||"; // double separators
144 LPWSTR pszzSrcList
= strSrcList
.GetBuffer();
146 // convert every separator to a NUL
147 INT cch
= strSrcList
.GetLength();
148 for (INT i
= 0; i
< cch
; ++i
)
150 if (pszzSrcList
[i
] == L
'|')
151 pszzSrcList
[i
] = L
'\0';
155 SHFILEOPSTRUCTW fileop
= { NULL
};
156 fileop
.wFunc
= FO_COPY
;
157 fileop
.pFrom
= pszzSrcList
;
159 fileop
.fFlags
= FOF_ALLOWUNDO
| FOF_FILESONLY
| FOF_MULTIDESTFILES
| FOF_NOCONFIRMMKDIR
;
160 int res
= SHFileOperationW(&fileop
);
163 ERR("SHFileOperationW failed with 0x%x\n", res
);
168 strSrcList
.ReleaseBuffer();
175 STDMETHODIMP
CMyDocsDropHandler::GetCurFile(LPOLESTR
*ppszFileName
)
177 FIXME("(%p)\n", this);
181 STDMETHODIMP
CMyDocsDropHandler::IsDirty()
183 FIXME("(%p)\n", this);
187 STDMETHODIMP
CMyDocsDropHandler::Load(LPCOLESTR pszFileName
, DWORD dwMode
)
192 STDMETHODIMP
CMyDocsDropHandler::Save(LPCOLESTR pszFileName
, BOOL fRemember
)
194 FIXME("(%p)\n", this);
198 STDMETHODIMP
CMyDocsDropHandler::SaveCompleted(LPCOLESTR pszFileName
)
200 FIXME("(%p)\n", this);
205 STDMETHODIMP
CMyDocsDropHandler::GetClassID(CLSID
* lpClassId
)
207 TRACE("(%p)\n", this);
211 ERR("lpClassId is NULL\n");
215 *lpClassId
= CLSID_MyDocsDropHandler
;