source: trunk/dll/droplist.c@ 1787

Last change on this file since 1787 was 1780, checked in by Gregg Young, 11 years ago

Fixed errors found by cppcheck. Most had the potential to cause difficult to reproduce traps. Also fixed retry code for failure to create an archive work directory and the failure of the mailto code to drop trailing >.

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