source: filezilla/trunk/fuentes/src/interface/dndobjects.cpp

Last change on this file was 3185, checked in by jrpelegrina, 3 years ago

Update new version: 3.15.02

File size: 6.5 KB
Line 
1#include <filezilla.h>
2#include "dndobjects.h"
3
4#if FZ3_USESHELLEXT
5
6#include <initguid.h>
7#include "../fzshellext/shellext.h"
8#include <shlobj.h>
9#include <wx/stdpaths.h>
10
11CShellExtensionInterface::CShellExtensionInterface()
12{
13        m_shellExtension = 0;
14
15        CoCreateInstance(CLSID_ShellExtension, NULL,
16          CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, IID_IUnknown,
17          &m_shellExtension);
18
19        if (m_shellExtension)
20                m_hMutex = CreateMutex(0, false, _T("FileZilla3DragDropExtLogMutex"));
21        else
22                m_hMutex = 0;
23
24        m_hMapping = 0;
25}
26
27CShellExtensionInterface::~CShellExtensionInterface()
28{
29        if (m_shellExtension)
30        {
31                ((IUnknown*)m_shellExtension)->Release();
32                CoFreeUnusedLibraries();
33        }
34
35        if (m_hMapping)
36                CloseHandle(m_hMapping);
37
38        if (m_hMutex)
39                CloseHandle(m_hMutex);
40
41        if (!m_dragDirectory.empty())
42                RemoveDirectory(m_dragDirectory.wc_str());
43}
44
45wxString CShellExtensionInterface::InitDrag()
46{
47        if (!m_shellExtension)
48                return wxString();
49
50        if (!m_hMutex)
51                return wxString();
52
53        if (!CreateDragDirectory())
54                return wxString();
55
56        m_hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, DRAG_EXT_MAPPING_LENGTH, DRAG_EXT_MAPPING);
57        if (!m_hMapping)
58                return wxString();
59
60        char* data = (char*)MapViewOfFile(m_hMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, DRAG_EXT_MAPPING_LENGTH);
61        if (!data)
62        {
63                CloseHandle(m_hMapping);
64                m_hMapping = 0;
65                return wxString();
66        }
67
68        DWORD result = WaitForSingleObject(m_hMutex, 250);
69        if (result != WAIT_OBJECT_0)
70        {
71                UnmapViewOfFile(data);
72                return wxString();
73        }
74
75        *data = DRAG_EXT_VERSION;
76        data[1] = 1;
77        wcscpy((wchar_t*)(data + 2), m_dragDirectory.wc_str(wxConvLocal));
78
79        ReleaseMutex(m_hMutex);
80
81        UnmapViewOfFile(data);
82
83        return m_dragDirectory;
84}
85
86wxString CShellExtensionInterface::GetTarget()
87{
88        if (!m_shellExtension)
89                return wxString();
90
91        if (!m_hMutex)
92                return wxString();
93
94        if (!m_hMapping)
95                return wxString();
96
97        char* data = (char*)MapViewOfFile(m_hMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, DRAG_EXT_MAPPING_LENGTH);
98        if (!data)
99        {
100                CloseHandle(m_hMapping);
101                m_hMapping = 0;
102                return wxString();
103        }
104
105        DWORD result = WaitForSingleObject(m_hMutex, 250);
106        if (result != WAIT_OBJECT_0)
107        {
108                UnmapViewOfFile(data);
109                return wxString();
110        }
111
112        wxString target;
113        const char reply = data[1];
114        if (reply == 2)
115        {
116                data[DRAG_EXT_MAPPING_LENGTH - 1] = 0;
117                target = (wchar_t*)(data + 2);
118        }
119
120        ReleaseMutex(m_hMutex);
121
122        UnmapViewOfFile(data);
123
124        if (target.empty())
125                return target;
126
127        if (target.Last() == '\\')
128                target.RemoveLast();
129        int pos = target.Find('\\', true);
130        if (pos < 1)
131                return wxString();
132        target = target.Left(pos + 1);
133
134        return target;
135}
136
137bool CShellExtensionInterface::CreateDragDirectory()
138{
139        for (int i = 0; i < 10; ++i) {
140                auto const now = fz::datetime::now();
141                int64_t value = now.get_time_t();
142                value *= 1000;
143                value += now.get_milliseconds();
144                value *= 10;
145                value += i;
146
147                wxFileName dirname(wxStandardPaths::Get().GetTempDir(), DRAG_EXT_DUMMY_DIR_PREFIX + std::to_wstring(value));
148                dirname.Normalize();
149                wxString dir = dirname.GetFullPath();
150
151                if (dir.Len() > MAX_PATH)
152                        return false;
153
154                if (CreateDirectory(dir.wc_str(), 0)) {
155                        m_dragDirectory = dir;
156                        return true;
157                }
158        }
159
160        return true;
161}
162
163std::unique_ptr<CShellExtensionInterface> CShellExtensionInterface::CreateInitialized()
164{
165        auto ret = std::make_unique<CShellExtensionInterface>();
166        if (!ret->IsLoaded() || ret->InitDrag().empty()) {
167                ret.reset();
168        }
169
170        return ret;
171}
172
173//{7BB79969-2C7E-4107-996C-36DB90890AB2}
174
175#endif //__WXMSW__
176
177CRemoteDataObject::CRemoteDataObject(const CServer& server, const CServerPath& path)
178        : wxDataObjectSimple(wxDataFormat(_T("FileZilla3RemoteDataObject")))
179        , m_server(server)
180        , m_path(path)
181        , m_didSendData()
182        , m_processId(wxGetProcessId())
183{
184}
185
186CRemoteDataObject::CRemoteDataObject()
187        : wxDataObjectSimple(wxDataFormat(_T("FileZilla3RemoteDataObject")))
188        , m_didSendData()
189        , m_processId(wxGetProcessId())
190{
191}
192
193size_t CRemoteDataObject::GetDataSize() const
194{
195        wxASSERT(!m_path.empty());
196
197        wxCHECK(m_xmlFile.GetElement(), 0);
198
199        m_expectedSize = m_xmlFile.GetRawDataLength() + 1;
200
201        return m_expectedSize;
202}
203
204bool CRemoteDataObject::GetDataHere(void *buf) const
205{
206        wxASSERT(!m_path.empty());
207
208        wxCHECK(m_xmlFile.GetElement(), false);
209
210        m_xmlFile.GetRawDataHere((char*)buf, m_expectedSize);
211        if (m_expectedSize > 0) {
212                static_cast<char*>(buf)[m_expectedSize - 1] = 0;
213        }
214
215        const_cast<CRemoteDataObject*>(this)->m_didSendData = true;
216        return true;
217}
218
219void CRemoteDataObject::Finalize()
220{
221        // Convert data into XML
222        auto element = m_xmlFile.CreateEmpty();
223        element = element.append_child("RemoteDataObject");
224
225        AddTextElement(element, "ProcessId", m_processId);
226
227        auto xServer = element.append_child("Server");
228        SetServer(xServer, m_server);
229
230        AddTextElement(element, "Path", m_path.GetSafePath());
231
232        auto files = element.append_child("Files");
233        for (std::list<t_fileInfo>::const_iterator iter = m_fileList.begin(); iter != m_fileList.end(); ++iter) {
234                auto file = files.append_child("File");
235                AddTextElement(file, "Name", iter->name);
236                AddTextElement(file, "Dir", iter->dir ? 1 : 0);
237                AddTextElement(file, "Size", iter->size);
238                AddTextElement(file, "Link", iter->link ? 1 : 0);
239        }
240}
241
242bool CRemoteDataObject::SetData(size_t len, const void* buf)
243{
244        char* data = (char*)buf;
245        if (!len || data[len - 1] != 0)
246                return false;
247
248        if (!m_xmlFile.ParseData(data))
249                return false;
250
251        auto element = m_xmlFile.GetElement();
252        if (!element || !(element = element.child("RemoteDataObject")))
253                return false;
254
255        m_processId = GetTextElementInt(element, "ProcessId", -1);
256        if (m_processId == -1)
257                return false;
258
259        auto server = element.child("Server");
260        if (!server || !::GetServer(server, m_server))
261                return false;
262
263        wxString path = GetTextElement(element, "Path");
264        if (path.empty() || !m_path.SetSafePath(path))
265                return false;
266
267        m_fileList.clear();
268        auto files = element.child("Files");
269        if (!files)
270                return false;
271
272        for (auto file = files.child("File"); file; file = file.next_sibling("File")) {
273                t_fileInfo info;
274                info.name = GetTextElement(file, "Name");
275                if (info.name.empty())
276                        return false;
277
278                const int dir = GetTextElementInt(file, "Dir", -1);
279                if (dir == -1)
280                        return false;
281                info.dir = dir == 1;
282
283                info.size = GetTextElementInt(file, "Size", -2);
284                if (info.size <= -2)
285                        return false;
286
287                info.link = GetTextElementBool(file, "Link", false);
288
289                m_fileList.push_back(info);
290        }
291
292        return true;
293}
294
295void CRemoteDataObject::AddFile(const wxString& name, bool dir, int64_t size, bool link)
296{
297        t_fileInfo info;
298        info.name = name;
299        info.dir = dir;
300        info.size = size;
301        info.link = link;
302
303        m_fileList.push_back(info);
304}
Note: See TracBrowser for help on using the repository browser.