-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathCDropTarget.asm
More file actions
422 lines (355 loc) · 10.2 KB
/
CDropTarget.asm
File metadata and controls
422 lines (355 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
;--- IDropTarget installs left explorer panel as a drop target
.386
.model flat, stdcall
option casemap:none
option proc:private
.nolist
.nocref
WIN32_LEAN_AND_MEAN equ 1
INCL_OLE2 equ 1
_WIN32_IE equ 500h
include windows.inc
include commctrl.inc
include windowsx.inc
include shellapi.inc
include objidl.inc
include olectl.inc
include shlguid.inc
include shlobj.inc
include shlwapi.inc
include shobjidl.inc
include macros.inc
?AGGREGATION = 0 ;no aggregation
?EVENTSUPPORT = 0 ;no event support
include olecntrl.inc
include debugout.inc
include rsrc.inc
.list
.cref
INSIDE_CShellBrowser equ 1
LPDROPTARGETHELPER typedef ptr IDropTargetHelper
LPSHELLLINK typedef ptr IShellLink
include CShellBrowser.inc
if ?DROPTARGET
includelib shlwapi.lib
.const
CDropTargetVtbl label dword
IUnknownVtbl {QueryInterface_, AddRef_, Release_}
dd DragEnter_, DragOver_, DragLeave_, Drop_
;CLSID_ShellLink GUID sCLSID_ShellLink
;IID_IShellLink sIID_IShellLinkA
.code
__this textequ <ebx>
_this textequ <[__this].CShellBrowser>
MEMBER hWnd, hWndTV, bRButton
MEMBER pMalloc
@MakeStubsEx CShellBrowser, IDropTarget, QueryInterface, AddRef, Release
@MakeStubs CShellBrowser, IDropTarget, DragEnter, DragOver, DragLeave, Drop
DragEnter proc uses __this this_:ptr CShellBrowser, pDataObject:LPDATAOBJECT, grfKeyState:DWORD, pt:POINTL, pdwEffect:ptr DWORD
local fe:FORMATETC
mov __this,this_
;----------------------------- check if data is acceptable
mov fe.cfFormat, CF_HDROP
mov fe.ptd, NULL
mov fe.dwAspect, DVASPECT_CONTENT
mov fe.lindex, -1
mov fe.tymed, TYMED_HGLOBAL
invoke vf(pDataObject, IDataObject, QueryGetData), addr fe
mov ecx, pdwEffect
DebugOut "IShellBrowser::DragEnter(%X), IDataObject::QueryGetData=%X %X", grfKeyState, eax, dword ptr [ecx]
.IF (eax != S_OK)
mov dword ptr [ecx], DROPEFFECT_NONE
if 1
.ELSE
mov edx, grfKeyState
and edx, MK_CONTROL or MK_SHIFT
mov eax, [ecx]
.if (edx == (MK_CONTROL or MK_SHIFT))
and eax, DROPEFFECT_LINK
.elseif (edx == MK_CONTROL)
and eax,DROPEFFECT_COPY
.else
and eax,DROPEFFECT_MOVE
.endif
.if (!eax)
mov eax, DROPEFFECT_COPY
.endif
and DWORD PTR [ecx], eax
endif
.endif
.if (grfKeyState & MK_RBUTTON)
mov m_bRButton, TRUE
.else
mov m_bRButton, FALSE
.endif
if ?DRAGDROPHELPER
.if (g_pDropTargetHelper)
mov ecx, pdwEffect
invoke vf(g_pDropTargetHelper, IDropTargetHelper, DragEnter), m_hWnd, pDataObject, addr pt, [ecx]
DebugOut "IDropTargetHelper::DragEnter=%X", eax
.endif
endif
return S_OK
align 4
DragEnter endp
DragOver proc uses __this this_:ptr CShellBrowser, grfKeyState:DWORD, pt:POINTL, pdwEffect:ptr DWORD
local tvht:TV_HITTESTINFO
mov __this,this_
DebugOut "IShellBrowser::DragOver(%X)", grfKeyState
mov eax, pt.x
mov tvht.pt.x, eax
mov eax, pt.y
mov tvht.pt.y, eax
invoke ScreenToClient, m_hWndTV, addr tvht.pt
invoke TreeView_HitTest( m_hWndTV, addr tvht)
.if (eax)
invoke TreeView_SelectDropTarget( m_hWndTV, eax)
mov ecx, pdwEffect
mov eax, [ecx]
mov edx, grfKeyState
and edx, MK_CONTROL or MK_SHIFT
.if (edx == (MK_CONTROL or MK_SHIFT))
and eax, DROPEFFECT_LINK
.elseif (edx == MK_CONTROL)
and eax,DROPEFFECT_COPY
.else
and eax,DROPEFFECT_MOVE
.endif
.if (!eax)
mov eax, DROPEFFECT_COPY
.endif
.else
mov eax, DROPEFFECT_NONE
.endif
mov ecx, pdwEffect
and DWORD PTR [ecx], eax
if ?DRAGDROPHELPER
.if (g_pDropTargetHelper)
invoke vf(g_pDropTargetHelper, IDropTargetHelper, DragOver), addr pt, [ecx]
ifdef _DEBUG
mov ecx, pdwEffect
endif
DebugOut "IDropTargetHelper::DragOver=%X, %X", eax, dword ptr [ecx]
.endif
endif
return S_OK
align 4
DragOver endp
DragLeave proc uses __this this_:ptr CShellBrowser
mov __this,this_
DebugOut "IShellBrowser::DragLeave"
invoke TreeView_SelectDropTarget( m_hWndTV, NULL)
if ?DRAGDROPHELPER
.if (g_pDropTargetHelper)
invoke vf(g_pDropTargetHelper, IDropTargetHelper, DragLeave)
DebugOut "IDropTargetHelper::DragLeave=%X", eax
.endif
endif
return S_OK
align 4
DragLeave endp
IDM_MOVE equ FCIDM_BROWSERFIRST+0
IDM_COPY equ FCIDM_BROWSERFIRST+1
IDM_CREATESHORTCUT equ FCIDM_BROWSERFIRST+2
IDM_CANCEL equ FCIDM_BROWSERFIRST+3
DisplayContextMenu proc uses esi grfKeyState:DWORD, dwEffect:DWORD
local dwDefault:DWORD
local pt:POINT
mov dwDefault, 0
invoke CreatePopupMenu
mov esi, eax
.if (dwEffect & DROPEFFECT_MOVE)
invoke AppendMenu, esi, MF_STRING, IDM_MOVE, CStr("Move Here")
.if (!(grfKeyState & MK_CONTROL))
mov dwDefault, IDM_MOVE
.endif
.endif
.if (dwEffect & DROPEFFECT_COPY)
invoke AppendMenu, esi, MF_STRING, IDM_COPY, CStr("Copy Here")
.if (grfKeyState & MK_CONTROL)
mov dwDefault, IDM_COPY
.endif
.endif
.if (dwEffect & DROPEFFECT_LINK)
invoke AppendMenu, esi, MF_STRING, IDM_CREATESHORTCUT, CStr("Create Shortcut(s) Here")
mov ecx, grfKeyState
and ecx, MK_CONTROL or MK_SHIFT
.if (ecx == MK_CONTROL or MK_SHIFT)
mov dwDefault, IDM_CREATESHORTCUT
.endif
.endif
invoke AppendMenu, esi, MF_SEPARATOR, -1, 0
invoke AppendMenu, esi, MF_STRING, IDM_CANCEL, CStr("Cancel")
.if (dwDefault)
invoke SetMenuDefaultItem, esi, dwDefault, FALSE
.endif
invoke GetCursorPos, addr pt
invoke TrackPopupMenu, esi, TPM_LEFTALIGN or TPM_LEFTBUTTON or TPM_RETURNCMD,\
pt.x, pt.y, 0, m_hWnd, NULL
.if (eax == IDM_COPY)
mov eax, MK_CONTROL
.elseif (eax == IDM_CREATESHORTCUT)
mov eax, MK_CONTROL or MK_SHIFT
.elseif (eax == IDM_MOVE)
mov eax, MK_RBUTTON
.else
xor eax, eax
.endif
push eax
invoke DestroyMenu, esi
pop eax
ret
DisplayContextMenu endp
CreateLink proc lpszPathObj:LPSTR, lpszPathLink:LPSTR , lpszDesc:LPSTR
local hres:DWORD
local pShellLink:LPSHELLLINK
local pPersistFile:LPPERSISTFILE
local wsz[MAX_PATH]:WORD
invoke CoCreateInstance, addr CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, addr IID_IShellLinkA, addr pShellLink
.if (eax == S_OK)
; // Set the path to the shortcut target and add the
; // description.
invoke vf(pShellLink, IShellLinkA, SetPath), lpszPathObj
invoke vf(pShellLink, IShellLinkA, SetDescription), lpszDesc
; // Query IShellLink for the IPersistFile interface for saving the
; // shortcut in persistent storage.
invoke vf(pShellLink, IShellLinkA, QueryInterface), addr IID_IPersistFile,
addr pPersistFile
.if (eax == S_OK)
invoke MultiByteToWideChar, CP_ACP, 0, lpszPathLink, -1, addr wsz, MAX_PATH
; // Save the link by calling IPersistFile::Save.
invoke vf(pPersistFile, IPersistFile, Save), addr wsz, TRUE
invoke vf(pPersistFile, IUnknown, Release)
.endif
invoke vf(pShellLink, IUnknown, Release)
.endif
ret
CreateLink endp
?COPYDROPFILES equ 1
;--- grfKeyState doesnt show mouse button state (because the drop
;--- gets into effect if the mouse button is released!)
Drop proc uses __this esi this_:ptr CShellBrowser, pDataObject:LPDATAOBJECT, grfKeyState:DWORD, pt:POINTL, pdwEffect:ptr DWORD
local pidl:LPITEMIDLIST
local fe:FORMATETC
local dwFiles:DWORD
local dwSize:DWORD
local stgmedium:STGMEDIUM
local shfos:SHFILEOPSTRUCT
local szPath[MAX_PATH]:BYTE
local szPathTmp[MAX_PATH]:BYTE
local szDesc[MAX_PATH]:BYTE
local szFile[MAX_PATH]:BYTE
mov __this,this_
DebugOut "IShellBrowser::Drop(%X)", grfKeyState
mov fe.cfFormat, CF_HDROP
mov fe.ptd, NULL
mov fe.dwAspect,DVASPECT_CONTENT
mov fe.lindex,-1
mov fe.tymed, TYMED_HGLOBAL
invoke vf(pDataObject, IDataObject, GetData), ADDR fe, ADDR stgmedium
.if (eax != S_OK)
jmp exit
.endif
if ?COPYDROPFILES
;--------------------------------- get number of files dropped
invoke DragQueryFile, stgmedium.hGlobal, -1, 0, 0
mov dwFiles, eax
mov dwSize, 1
xor esi, esi
.while (esi < dwFiles)
invoke DragQueryFile, stgmedium.hGlobal, esi, 0, 0
inc eax
add dwSize, eax
inc esi
.endw
invoke LocalAlloc, LMEM_FIXED, dwSize
.if (!eax)
jmp exit2
.endif
mov shfos.pFrom, eax
mov edx, eax
xor esi, esi
.while (esi < dwFiles)
push edx
invoke DragQueryFile, stgmedium.hGlobal, esi, edx, MAX_PATH
pop edx
add edx, eax
mov byte ptr [edx],0
inc edx
inc esi
.endw
mov byte ptr [edx],0
else
mov eax, stgmedium.hGlobal ;that doesnt work with wide chars
add eax,[eax].DROPFILES.pFiles
mov shfos.pFrom, eax
endif
mov eax, m_hWnd
mov shfos.hwnd, eax
invoke TreeView_GetDropHilight( m_hWndTV)
invoke GetFullPidl@CShellBrowser, eax
mov pidl, eax
invoke SHGetPathFromIDList, pidl, addr szPath
invoke vf(m_pMalloc, IMalloc, Free), pidl
lea eax, szPath
mov shfos.pTo, eax
mov edx, grfKeyState
.if (m_bRButton)
mov ecx, pdwEffect
invoke DisplayContextMenu, edx, [ecx]
.if (!eax)
jmp exit2
.endif
mov edx, eax
.endif
mov ecx, pdwEffect
mov ecx, [ecx]
and edx, MK_CONTROL or MK_SHIFT
.if ((ecx & DROPEFFECT_LINK) && (edx == MK_CONTROL or MK_SHIFT))
mov esi, shfos.pFrom
.while (byte ptr [esi])
invoke lstrlen, esi
mov dwSize, eax
invoke lstrcpy, addr szFile, esi
invoke PathStripPath, addr szFile
invoke wsprintf, addr szDesc, CStr("Shortcut of %s"), addr szFile
invoke wsprintf, addr szPathTmp, CStr("%s\%s.lnk"), shfos.pTo, addr szFile
invoke CreateLink, esi, addr szPathTmp, addr szDesc
add esi, dwSize
inc esi
.endw
.else
.if ((ecx & DROPEFFECT_MOVE) && (!edx))
mov shfos.wFunc, FO_MOVE
.elseif (ecx & DROPEFFECT_COPY)
mov shfos.wFunc, FO_COPY
.else
jmp exit3
.endif
mov shfos.fFlags, FOF_ALLOWUNDO
mov shfos.fAnyOperationsAborted, FALSE
;; mov shfos.hNameMappings, xxx
;; mov shfos.lpszProgressTitle, xxx
invoke SHFileOperation, addr shfos
.endif
exit3:
if ?COPYDROPFILES
invoke LocalFree, shfos.pFrom
endif
exit2:
invoke ReleaseStgMedium, addr stgmedium
exit:
invoke TreeView_SelectDropTarget( m_hWndTV, NULL)
if ?DRAGDROPHELPER
.if (g_pDropTargetHelper)
mov ecx, pdwEffect
invoke vf(g_pDropTargetHelper, IDropTargetHelper, Drop), pDataObject, addr pt, [ecx]
DebugOut "IDropTargetHelper::Drop=%X", eax
.endif
endif
return S_OK
align 4
Drop endp
endif
end