source: trunk/dll/droplist.c@ 1036

Last change on this file since 1036 was 1018, checked in by Gregg Young, 17 years ago

Additional fortify scopes mostly for "lists"

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