1 #include "main.h"
2
3 #include "../filesys.h"
4 #include "../file_transfers.h"
5 #include "../flist.h"
6 #include "../friend.h"
7 #include "../debug.h"
8 #include "../tox.h"
9 #include "../macros.h"
10
11 typedef struct {
12 IDropTarget dt;
13 LONG ref;
14 } my_IDropTarget;
15
dnd_AddRef(IDropTarget * lpMyObj)16 ULONG __stdcall dnd_AddRef(IDropTarget *lpMyObj) {
17 my_IDropTarget *p = (void*)lpMyObj;
18 return InterlockedIncrement(&p->ref);
19 }
20
dnd_Release(IDropTarget * lpMyObj)21 ULONG __stdcall dnd_Release(IDropTarget *lpMyObj) {
22 my_IDropTarget *p = (void*)lpMyObj;
23 LONG count = InterlockedDecrement(&p->ref);
24
25 if (!count) {
26 free(lpMyObj->lpVtbl);
27 free(lpMyObj);
28 }
29
30 return count;
31 }
32
dnd_QueryInterface(IDropTarget * lpMyObj,REFIID riid,LPVOID FAR * lppvObj)33 HRESULT __stdcall dnd_QueryInterface(IDropTarget *lpMyObj, REFIID riid, LPVOID FAR *lppvObj) {
34 *lppvObj = NULL;
35
36 // PRINT_GUID (riid);
37 if (IsEqualIID (riid, &IID_IUnknown) || IsEqualIID (riid, &IID_IDropTarget)) {
38 dnd_AddRef (lpMyObj);
39 *lppvObj = lpMyObj;
40 return S_OK;
41 }
42
43 return E_NOINTERFACE;
44 }
45
dnd_DragEnter(IDropTarget * UNUSED (lpMyObj),IDataObject * UNUSED (pDataObject),DWORD UNUSED (grfKeyState),POINTL UNUSED (pt),DWORD * pdwEffect)46 HRESULT __stdcall dnd_DragEnter(IDropTarget *UNUSED(lpMyObj), IDataObject *UNUSED(pDataObject),
47 DWORD UNUSED(grfKeyState), POINTL UNUSED(pt), DWORD *pdwEffect) {
48 *pdwEffect = DROPEFFECT_COPY;
49 return S_OK;
50 }
51
dnd_DragOver(IDropTarget * UNUSED (lpMyObj),DWORD UNUSED (grfKeyState),POINTL UNUSED (pt),DWORD * pdwEffect)52 HRESULT __stdcall dnd_DragOver(IDropTarget *UNUSED(lpMyObj), DWORD UNUSED(grfKeyState),
53 POINTL UNUSED(pt), DWORD *pdwEffect) {
54 *pdwEffect = DROPEFFECT_COPY;
55 return S_OK;
56 }
57
dnd_DragLeave(IDropTarget * UNUSED (lpMyObj))58 HRESULT __stdcall dnd_DragLeave(IDropTarget *UNUSED(lpMyObj)) {
59 return S_OK;
60 }
61
dnd_Drop(IDropTarget * UNUSED (lpMyObj),IDataObject * pDataObject,DWORD UNUSED (grfKeyState),POINTL UNUSED (pt),DWORD * pdwEffect)62 HRESULT __stdcall dnd_Drop(IDropTarget *UNUSED(lpMyObj), IDataObject *pDataObject,
63 DWORD UNUSED(grfKeyState), POINTL UNUSED(pt), DWORD *pdwEffect) {
64 *pdwEffect = DROPEFFECT_COPY;
65 LOG_NOTE("DnD", "Dropped!" );
66
67 if (!flist_get_friend()) {
68 return S_OK;
69 }
70
71 FORMATETC format = {
72 .cfFormat = CF_HDROP,
73 .dwAspect = DVASPECT_CONTENT,
74 .lindex = -1,
75 .tymed = TYMED_HGLOBAL,
76 };
77 STGMEDIUM medium;
78
79 HRESULT r = pDataObject->lpVtbl->GetData(pDataObject, &format, &medium);
80 if (r == S_OK) {
81 HDROP h = medium.hGlobal;
82 int count = DragQueryFile(h, ~0, NULL, 0);
83 LOG_INFO("WINDND", "%u files dropped\n", count);
84
85 for (int i = 0; i < count; i++) {
86 LOG_NOTE("WINDND", "Sending file number %i", i);
87 UTOX_MSG_FT *msg = calloc(1, sizeof(UTOX_MSG_FT));
88 if (!msg) {
89 LOG_ERR("WINDND", "Unable to alloc for UTOX_MSG_FT");
90 return 0;
91 }
92
93 char *path = calloc(1, UTOX_FILE_NAME_LENGTH);
94 if (!path) {
95 LOG_ERR("WINDND", "Unable to alloc for UTOX_MSG_FT");
96 free(msg);
97 return 0;
98 }
99
100 DragQueryFile(h, i, path, UTOX_FILE_NAME_LENGTH);
101
102 msg->file = fopen(path, "rb");
103 if (!msg->file) {
104 LOG_ERR("WINDND", "Unable to read file %s" , path);
105 free(msg);
106 free(path);
107 return 0;
108 }
109
110 msg->name = (uint8_t *)path;
111 postmessage_toxcore(TOX_FILE_SEND_NEW, flist_get_friend()->number, 0, msg);
112 LOG_INFO("WINDND", "File number %i sent!" , i);
113 }
114
115 ReleaseStgMedium(&medium);
116 } else {
117 LOG_ERR("WINDND", "itz failed! %lX", r);
118 }
119
120 return S_OK;
121 }
122
dnd_init(HWND window)123 void dnd_init(HWND window) {
124 my_IDropTarget *p;
125 p = malloc(sizeof(my_IDropTarget));
126 p->dt.lpVtbl = malloc(sizeof(*(p->dt.lpVtbl)));
127 p->ref = 0;
128
129 p->dt.lpVtbl->QueryInterface = dnd_QueryInterface;
130 p->dt.lpVtbl->AddRef = dnd_AddRef;
131 p->dt.lpVtbl->Release = dnd_Release;
132
133 p->dt.lpVtbl->DragEnter = dnd_DragEnter;
134 p->dt.lpVtbl->DragLeave = dnd_DragLeave;
135 p->dt.lpVtbl->DragOver = dnd_DragOver;
136 p->dt.lpVtbl->Drop = dnd_Drop;
137
138 CoLockObjectExternal((struct IUnknown*)p, TRUE, FALSE);
139
140 RegisterDragDrop(window, (IDropTarget*)p);
141 }
142