source: trunk/dll/droplist.c@ 1010

Last change on this file since 1010 was 1009, checked in by Steven Levine, 17 years ago

Add xfree xstrdup Fortify support
Add MT capable Fortify scope logic

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