source: trunk/dll/droplist.c

Last change on this file was 1916, checked in by Gregg Young, 7 days ago

Fix easize so that EAs larger than 32767 show their actual size instead of 32767

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