source: trunk/dll/droplist.c@ 618

Last change on this file since 618 was 618, checked in by Steven Levine, 18 years ago

Add more drag/drop error checking
Use FreeDragInfoData
Sync with NumItemsToUnhilite AcceptOneDrop GetOneDrop mods

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.7 KB
Line 
1
2/***********************************************************************
3
4 $Id: droplist.c 618 2007-04-20 19:19:03Z stevenhl $
5
6 Drop support
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2003, 2006 Steven H.Levine
10
11 22 Nov 02 SHL Baseline
12 08 Feb 03 SHL DropHelp: calc EA size consistently
13 21 Jul 06 SHL Drop dup code
14 22 Jul 06 SHL Check more run time errors
15 06 Apr 07 GKY Work around PM DragInfo and DrgFreeDISH limits
16 06 Apr 07 GKY Add some error checking in drag/drop
17 19 Apr 07 SHL Use FreeDragInfoData
18 19 Apr 07 SHL Add more drag/drop error checking
19
20***********************************************************************/
21
22#define INCL_DOS
23#define INCL_WIN
24#include <os2.h>
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <ctype.h>
30
31#include "fm3dll.h"
32#include "fm3str.h"
33
34static PSZ pszSrcFile = __FILE__;
35
36static ULONG GetDropCount(HWND hwnd, MPARAM mp1);
37
38#pragma alloc_text(DROPLIST,DoFileDrop,FullDrgName,TwoDrgNames,GetOneDrop)
39
40BOOL TwoDrgNames(PDRAGITEM pDItem, CHAR * buffer1, ULONG buflen1,
41 char *buffer2, ULONG buflen2)
42{
43 /*
44 * Gets archive name from directory field, file name from file field
45 * Returns FALSE on error, TRUE on success.
46 */
47
48 register ULONG len;
49 BOOL ret = FALSE;
50
51 if (pDItem && buffer2 && buflen2) { /* else error calling function */
52 if (buffer1 && buflen1) /* zero buffers */
53 *buffer1 = 0;
54 *buffer2 = 0;
55
56 if (buffer1 && buflen1) {
57 len = DrgQueryStrName(pDItem->hstrContainerName, buflen1, buffer1);
58 buffer1[len] = 0;
59 if (len) { /* be sure we get full pathname of arc file */
60
61 char szTemp[CCHMAXPATH + 2];
62
63 if (!DosQueryPathInfo(buffer1,
64 FIL_QUERYFULLNAME, szTemp, sizeof(szTemp))) {
65 strncpy(buffer1, szTemp, buflen1);
66 buffer1[buflen1 - 1] = 0;
67 }
68 }
69 { /* be sure that file/directory is accessible */
70 FILESTATUS3 fsa3;
71
72 DosError(FERR_DISABLEHARDERR);
73 if (DosQueryPathInfo(buffer1,
74 FIL_STANDARD,
75 &fsa3,
76 sizeof(fsa3)) ||
77 (fsa3.attrFile & FILE_DIRECTORY) != 0) {
78 *buffer1 = 0;
79 return ret;
80 }
81 }
82 }
83
84 len = DrgQueryStrName(pDItem->hstrSourceName, buflen2, buffer2);
85 buffer2[len] = 0;
86 if (len)
87 ret = TRUE;
88 }
89 return ret;
90}
91
92BOOL FullDrgName(PDRAGITEM pDItem, CHAR * buffer, ULONG buflen)
93{
94 /*
95 * Gets full name of file from a dragged item.
96 * Returns FALSE on error, TRUE on success.
97 */
98
99 register ULONG len, blen;
100 BOOL ret = FALSE;
101 APIRET rc;
102
103 if (pDItem && buffer && buflen) { /* else error calling function */
104 *buffer = 0; /* zero buffer */
105
106 blen = DrgQueryStrName(pDItem->hstrContainerName, buflen, buffer);
107 if(!blen)
108 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
109 "DrgQueryStrName");
110 else {
111 if (*(buffer + (blen - 1)) != '\\') {
112 *(buffer + blen) = '\\';
113 blen++;
114 }
115 }
116 buffer[blen] = 0;
117 len = DrgQueryStrName(pDItem->hstrSourceName,
118 buflen - blen, buffer + blen);
119 if(!len) {
120 // DbgMsg(pszSrcFile, __LINE__, "0x%x %d %d", pDItem->hstrSourceName,
121 // buflen - blen, buffer + blen);
122 // Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
123 // "DrgQueryStrName");
124 }
125 buffer[blen + len] = 0;
126 { /* be sure we get full pathname of file/directory */
127 char szTemp[CCHMAXPATH + 2];
128 rc = DosQueryPathInfo(buffer,
129 FIL_QUERYFULLNAME, szTemp, sizeof(szTemp));
130 if (!rc) {
131 strncpy(buffer, szTemp, buflen);
132 buffer[buflen - 1] = 0;
133 }
134 else
135 Dos_Error(MB_CANCEL, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
136 "DosQueryPathInfo");
137 }
138 { /* be sure that file/directory is accessible */
139 FILESTATUS3 fsa3;
140
141 rc = DosQueryPathInfo(buffer, FIL_STANDARD, &fsa3, sizeof(fsa3));
142 if (!rc)
143 ret = TRUE;
144 else {
145 Dos_Error(MB_CANCEL, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
146 "DosQueryPathInfo");
147 *buffer = 0;
148 }
149 }
150 }
151 return ret;
152}
153
154BOOL GetOneDrop(HWND hwnd, MPARAM mp1, MPARAM mp2, char *buffer, ULONG buflen)
155{
156 PDRAGITEM pDItem; /* DRAGITEM struct ptr */
157 PDRAGINFO pDInfo; /* DRAGINFO struct ptr */
158 ULONG numitems;
159 register ULONG curitem;
160 BOOL ret = FALSE;
161
162 if (buffer && buflen)
163 *buffer = 0; /* zero buffer field */
164
165 pDInfo = (PDRAGINFO) mp1; /* Get DRAGINFO pointer */
166 if (pDInfo) {
167 if (!DrgAccessDraginfo(pDInfo)) {
168 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
169 "DrgAccessDraginfo");
170 }
171 else {
172 numitems = DrgQueryDragitemCount(pDInfo);
173 pDItem = DrgQueryDragitemPtr(pDInfo,0);
174 if (buflen && buffer) {
175 if (DrgVerifyRMF(pDItem, /* Check valid rendering */
176 DRM_OS2FILE, /* mechanisms and data */
177 NULL) && !(pDItem->fsControl & DC_PREPARE))
178 ret = FullDrgName(pDItem, buffer, buflen);
179 }
180 // Return targetfail to source for all items - fixme to know why
181 for (curitem = 0; curitem < numitems; curitem++) {
182 pDItem = DrgQueryDragitemPtr(pDInfo,curitem);
183 DrgSendTransferMsg(pDInfo->hwndSource, DM_ENDCONVERSATION,
184 MPFROMLONG(pDItem->ulItemID),
185 MPFROMLONG(DMFL_TARGETFAIL));
186 }
187 FreeDragInfoData(hwnd, pDInfo);
188 }
189 }
190
191 return ret;
192}
193
194BOOL AcceptOneDrop(HWND hwnd, MPARAM mp1, MPARAM mp2)
195{
196 PDRAGITEM pDItem; /* Pointer to DRAGITEM */
197 PDRAGINFO pDInfo; /* Pointer to DRAGINFO */
198 BOOL ret = FALSE;
199
200 pDInfo = (PDRAGINFO) mp1; /* Get DRAGINFO pointer */
201 if (pDInfo) {
202 if (!DrgAccessDraginfo(pDInfo)) {
203 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
204 "DrgAccessDraginfo");
205 }
206 else {
207 pDItem = DrgQueryDragitemPtr(pDInfo, 0);
208
209 /* Check valid rendering mechanisms and data formats */
210 if (DrgVerifyRMF(pDItem, DRM_OS2FILE, NULL))
211 ret = TRUE;
212
213 // FreeDragInfoData(hwnd, pDInfo); // 20 Apr 07 SHL
214 DrgFreeDraginfo(pDInfo);
215 }
216 }
217 return ret;
218}
219
220static ULONG GetDropCount(HWND hwnd, MPARAM mp1)
221{
222 PDRAGINFO pDInfo;
223 ULONG numitems;
224
225 pDInfo = mp1;
226 if (pDInfo) {
227 if (!DrgAccessDraginfo(pDInfo)) {
228 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
229 "DrgAccessDraginfo");
230 numitems = 0; // Oh well
231 }
232 else {
233 numitems = DrgQueryDragitemCount(pDInfo);
234 FreeDragInfoData(hwnd, pDInfo);
235 }
236 }
237 return numitems;
238}
239
240void DropHelp(MPARAM mp1, MPARAM mp2, HWND hwnd, char *text)
241{
242 ULONG numitems;
243
244 numitems = GetDropCount(hwnd, mp1);
245 saymsg(MB_ENTER | MB_ICONASTERISK,
246 hwnd, GetPString(IDS_FM2DROPHELPTEXT), text, numitems, numitems);
247}
248
249LISTINFO *DoFileDrop(HWND hwndCnr, CHAR * directory, BOOL arcfilesok,
250 MPARAM mp1, MPARAM mp2)
251{
252
253 /* builds a list from the dropped files */
254
255 BOOL isArc = FALSE, arctest = FALSE;
256 PDRAGITEM pDItem;
257 PDRAGINFO pDInfo;
258 PCNRITEM pci;
259 CHAR szFrom[CCHMAXPATH + 1], szArc[CCHMAXPATH + 1];
260 CHAR **files = NULL;
261 INT numfiles = 0, numalloc = 0;
262 ULONG curitem, numitems, *cbFile = NULL, *ulitemID = NULL;
263 LISTINFO *li = NULL;
264 ARC_TYPE *arcinfo = NULL;
265 USHORT Operation;
266
267 *szArc = 0;
268 pci = (PCNRITEM) ((PCNRDRAGINFO) mp2)->pRecord;
269 pDInfo = ((PCNRDRAGINFO) mp2)->pDragInfo;
270 if (!pDInfo)
271 return NULL;
272 if (!DrgAccessDraginfo(pDInfo)) {
273 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
274 "DrgAccessDraginfo");
275 numitems = 0; // Avoid death
276 }
277 else {
278 numitems = DrgQueryDragitemCount(pDInfo);
279 Operation = pDInfo->usOperation;
280 pDItem = DrgQueryDragitemPtr(pDInfo, 0);
281 if (!pDItem) {
282 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
283 "DrgQueryDragitemPtr");
284 }
285 else {
286 if (Operation == DO_MOVE && !(pDItem->fsSupportedOps & DO_MOVEABLE)) {
287 saymsg(MB_ENTER, HWND_DESKTOP, GetPString(IDS_WARNINGTEXT),
288 GetPString(IDS_FORCINGCOPYTEXT));
289 Operation = DO_COPY;
290 }
291 }
292 }
293
294 for (curitem = 0; curitem < numitems; curitem++) {
295 pDItem = DrgQueryDragitemPtr(pDInfo, curitem);
296 if (!pDItem) {
297 Win_Error(hwndCnr, hwndCnr, pszSrcFile, __LINE__,
298 "DrgQueryDragitemPtr(%u)", curitem);
299 break;
300 }
301
302 /* ambiguous drop request -- see what's allowed */
303 if (Operation == DO_DEFAULT || Operation >= DO_UNKNOWN) {
304 if (pDItem->fsSupportedOps & DO_COPYABLE)
305 Operation = DO_COPY;
306 else if (pDItem->fsSupportedOps & DO_MOVEABLE)
307 Operation = DO_MOVE;
308 else if (pDItem->fsSupportedOps & DO_LINKABLE)
309 Operation = DO_LINK;
310 }
311 else {
312 /* ignore object if selected command not allowed for it */
313 BOOL ok;
314 switch (Operation) {
315 case DO_MOVE:
316 ok = pDItem->fsSupportedOps & DO_MOVEABLE;
317 break;
318 case DO_COPY:
319 ok = pDItem->fsSupportedOps & DO_COPYABLE;
320 break;
321 case DO_LINK:
322 ok = pDItem->fsSupportedOps & DO_LINKABLE;
323 break;
324 default:
325 ok = FALSE;
326 }
327 if (!ok) {
328 // Fail request
329 DrgSendTransferMsg(pDItem->hwndItem,
330 DM_ENDCONVERSATION,
331 MPFROMLONG(pDItem->ulItemID),
332 MPFROMLONG(DMFL_TARGETFAIL));
333 continue;
334 }
335 }
336
337 if (DrgVerifyRMF(pDItem,
338 DRM_OS2FILE,
339 NULL) ||
340 (arcfilesok &&
341 ((arctest = DrgVerifyRMF(pDItem,
342 DRM_FM2ARCMEMBER,
343 DRF_FM2ARCHIVE)) != FALSE))) {
344 if (pDItem->fsControl & DC_PREPARE) {
345 DrgSendTransferMsg(pDItem->hwndItem,
346 DM_ENDCONVERSATION,
347 MPFROMLONG(pDItem->ulItemID),
348 MPFROMLONG(DMFL_TARGETFAIL));
349 continue;
350 }
351
352 if (arctest || isArc) {
353 if (!isArc) {
354 if (TwoDrgNames(pDItem,
355 szArc,
356 sizeof(szArc),
357 szFrom, sizeof(szFrom)) && *szArc && *szFrom) {
358 isArc = TRUE;
359 arcinfo = find_type(szArc, arcsighead);
360 }
361 if (!arcinfo || !arcinfo->extract || !*arcinfo->extract) {
362 *szArc = *szFrom = 0;
363 isArc = FALSE;
364 }
365 }
366 else
367 TwoDrgNames(pDItem, NULL, 0, szFrom, sizeof(szFrom));
368 }
369 else
370 FullDrgName(pDItem, szFrom, sizeof(szFrom));
371
372 if (!*szFrom) {
373 DrgSendTransferMsg(pDItem->hwndItem,
374 DM_ENDCONVERSATION,
375 MPFROMLONG(pDItem->ulItemID),
376 MPFROMLONG(DMFL_TARGETFAIL));
377 continue;
378 }
379
380 if (numfiles + 2 > numalloc) {
381
382 CHAR **test;
383 ULONG *ltest;
384
385 numalloc += 12;
386 test =
387 xrealloc(files, numalloc * sizeof(CHAR *), pszSrcFile, __LINE__);
388 if (!test)
389 break;
390 files = test;
391 ltest =
392 xrealloc(cbFile, numalloc * sizeof(ULONG), pszSrcFile, __LINE__);
393 if (!ltest)
394 break;
395 cbFile = ltest;
396 ltest =
397 xrealloc(ulitemID, numalloc * sizeof(ULONG), pszSrcFile, __LINE__);
398 if (!ltest)
399 break;
400 ulitemID = ltest;
401 }
402 cbFile[numfiles] = 0;
403 if (!isArc) {
404
405 FILESTATUS4 fsa4;
406
407 if (!DosQueryPathInfo(szFrom, FIL_QUERYEASIZE, &fsa4, sizeof(fsa4)))
408 cbFile[numfiles] = fsa4.cbFile + CBLIST_TO_EASIZE(fsa4.cbList);
409 }
410 ulitemID[numfiles] = pDItem->ulItemID;
411 files[numfiles] = xstrdup(szFrom, pszSrcFile, __LINE__);
412 files[numfiles + 1] = NULL;
413 if (!files[numfiles])
414 break;
415 numfiles++;
416 DrgSendTransferMsg(pDItem->hwndItem,
417 DM_ENDCONVERSATION,
418 MPFROMLONG(pDItem->ulItemID),
419 MPFROMLONG(DMFL_TARGETSUCCESSFUL));
420 }
421 else
422 DrgSendTransferMsg(pDItem->hwndItem,
423 DM_ENDCONVERSATION,
424 MPFROMLONG(pDItem->ulItemID),
425 MPFROMLONG(DMFL_TARGETFAIL));
426 } // for
427
428 if (files && numfiles && files[0] && cbFile && ulitemID) {
429 li = xmallocz(sizeof(LISTINFO), pszSrcFile, __LINE__);
430 if (li) {
431 li->type = Operation;
432 li->hwnd = hwndCnr;
433 li->list = files;
434 li->cbFile = cbFile;
435 li->ulitemID = ulitemID;
436 li->hwndS = pDInfo->hwndSource;
437 if (!pci && directory)
438 strcpy(li->targetpath, directory);
439 else if (pci)
440 strcpy(li->targetpath, pci->szFileName);
441 if (isArc) {
442 strcpy(li->arcname, szArc);
443 li->info = arcinfo;
444 }
445 SortList(li);
446 }
447 else {
448 if (cbFile)
449 free(cbFile);
450 if (ulitemID)
451 free(ulitemID);
452 if (files)
453 FreeList(files);
454 }
455 }
456 else {
457 if (cbFile)
458 free(cbFile);
459 if (ulitemID)
460 free(ulitemID);
461 if (files)
462 FreeList(files);
463 }
464
465 FreeDragInfoData(hwndCnr, pDInfo);
466
467 return li;
468}
Note: See TracBrowser for help on using the repository browser.