source: trunk/dll/droplist.c@ 779

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

Lock in DoFileDrop sanity checks

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.1 KB
Line 
1
2/***********************************************************************
3
4 $Id: droplist.c 749 2007-08-02 16:47:07Z 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
23***********************************************************************/
24
25#define INCL_DOS
26#define INCL_WIN
27#include <os2.h>
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <ctype.h>
33
34#include "fm3dll.h"
35#include "fm3str.h"
36
37static PSZ pszSrcFile = __FILE__;
38
39static ULONG GetDropCount(HWND hwnd, MPARAM mp1);
40
41#pragma alloc_text(DROPLIST,DoFileDrop,FullDrgName,TwoDrgNames,GetOneDrop,CheckPmDrgLimit)
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) != 0) {
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 register ULONG len, blen;
129 BOOL ret = FALSE;
130 APIRET rc;
131
132 if (pDItem && buffer && buflen) { /* else error calling function */
133 *buffer = 0; /* zero buffer */
134
135 blen = DrgQueryStrName(pDItem->hstrContainerName, buflen, buffer);
136 if(!blen)
137 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
138 "DrgQueryStrName");
139 else {
140 if (*(buffer + (blen - 1)) != '\\') {
141 *(buffer + blen) = '\\';
142 blen++;
143 }
144 }
145 buffer[blen] = 0;
146 len = DrgQueryStrName(pDItem->hstrSourceName,
147 buflen - blen, buffer + blen);
148 if(!len) {
149 // DbgMsg(pszSrcFile, __LINE__, "0x%x %d %d", pDItem->hstrSourceName,
150 // buflen - blen, buffer + blen);
151 // Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
152 // "DrgQueryStrName");
153 }
154 buffer[blen + len] = 0;
155 { /* be sure we get full pathname of file/directory */
156 char szTemp[CCHMAXPATH + 2];
157 rc = DosQueryPathInfo(buffer,
158 FIL_QUERYFULLNAME, szTemp, sizeof(szTemp));
159 if (!rc) {
160 strncpy(buffer, szTemp, buflen);
161 buffer[buflen - 1] = 0;
162 }
163 else
164 Dos_Error(MB_CANCEL, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
165 "DosQueryPathInfo");
166 }
167 { /* be sure that file/directory is accessible */
168 FILESTATUS3 fsa3;
169
170 rc = DosQueryPathInfo(buffer, FIL_STANDARD, &fsa3, sizeof(fsa3));
171 if (!rc)
172 ret = TRUE;
173 else {
174 Dos_Error(MB_CANCEL, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
175 "DosQueryPathInfo");
176 *buffer = 0;
177 }
178 }
179 }
180 return ret;
181}
182
183BOOL GetOneDrop(HWND hwnd, MPARAM mp1, MPARAM mp2, char *buffer, ULONG buflen)
184{
185 PDRAGITEM pDItem; /* DRAGITEM struct ptr */
186 PDRAGINFO pDInfo; /* DRAGINFO struct ptr */
187 ULONG numitems;
188 register ULONG curitem;
189 BOOL ret = FALSE;
190
191 if (buffer && buflen)
192 *buffer = 0; /* zero buffer field */
193
194 pDInfo = (PDRAGINFO) mp1; /* Get DRAGINFO pointer */
195 if (pDInfo) {
196 if (!DrgAccessDraginfo(pDInfo)) {
197 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
198 "DrgAccessDraginfo");
199 }
200 else {
201 numitems = DrgQueryDragitemCount(pDInfo);
202 pDItem = DrgQueryDragitemPtr(pDInfo,0);
203 if (buflen && buffer) {
204 if (DrgVerifyRMF(pDItem, /* Check valid rendering */
205 DRM_OS2FILE, /* mechanisms and data */
206 NULL) && !(pDItem->fsControl & DC_PREPARE))
207 ret = FullDrgName(pDItem, buffer, buflen);
208 }
209 // Return targetfail to source for all items - fixme to know why
210 for (curitem = 0; curitem < numitems; curitem++) {
211 pDItem = DrgQueryDragitemPtr(pDInfo,curitem);
212 DrgSendTransferMsg(pDInfo->hwndSource, DM_ENDCONVERSATION,
213 MPFROMLONG(pDItem->ulItemID),
214 MPFROMLONG(DMFL_TARGETFAIL));
215 }
216 FreeDragInfoData(hwnd, pDInfo);
217 }
218 }
219
220 return ret;
221}
222
223BOOL AcceptOneDrop(HWND hwnd, MPARAM mp1, MPARAM mp2)
224{
225 PDRAGITEM pDItem; /* Pointer to DRAGITEM */
226 PDRAGINFO pDInfo; /* Pointer to DRAGINFO */
227 BOOL ret = FALSE;
228
229 pDInfo = (PDRAGINFO) mp1; /* Get DRAGINFO pointer */
230 if (pDInfo) {
231 if (!DrgAccessDraginfo(pDInfo)) {
232 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
233 "DrgAccessDraginfo");
234 }
235 else {
236 pDItem = DrgQueryDragitemPtr(pDInfo, 0);
237
238 /* Check valid rendering mechanisms and data formats */
239 if (DrgVerifyRMF(pDItem, DRM_OS2FILE, NULL))
240 ret = TRUE;
241
242 // FreeDragInfoData(hwnd, pDInfo); // 20 Apr 07 SHL
243 DrgFreeDraginfo(pDInfo);
244 }
245 }
246 return ret;
247}
248
249static ULONG GetDropCount(HWND hwnd, MPARAM mp1)
250{
251 PDRAGINFO pDInfo;
252 ULONG numitems;
253
254 pDInfo = mp1;
255 if (pDInfo) {
256 if (!DrgAccessDraginfo(pDInfo)) {
257 Win_Error(HWND_DESKTOP, HWND_DESKTOP, pszSrcFile, __LINE__,
258 "DrgAccessDraginfo");
259 numitems = 0; // Oh well
260 }
261 else {
262 numitems = DrgQueryDragitemCount(pDInfo);
263 FreeDragInfoData(hwnd, pDInfo);
264 }
265 }
266 return numitems;
267}
268
269void DropHelp(MPARAM mp1, MPARAM mp2, HWND hwnd, char *text)
270{
271 ULONG numitems;
272
273 numitems = GetDropCount(hwnd, mp1);
274 saymsg(MB_ENTER | MB_ICONASTERISK,
275 hwnd, GetPString(IDS_FM2DROPHELPTEXT), text, numitems, numitems);
276}
277
278LISTINFO *DoFileDrop(HWND hwndCnr, CHAR * directory, BOOL arcfilesok,
279 MPARAM mp1, MPARAM mp2)
280{
281 /* builds a list from the dropped files */
282
283 BOOL isArc = FALSE, arctest = FALSE;
284 PDRAGITEM pDItem;
285 PDRAGINFO pDInfo;
286 PCNRITEM pci;
287 CHAR szFrom[CCHMAXPATH + 1], szArc[CCHMAXPATH + 1];
288 CHAR **files = NULL;
289 UINT numfiles = 0, numalloc = 0;
290 ULONG curitem, numitems, *cbFile = NULL, *ulitemID = 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 ULONG *ltest;
420
421 numalloc += 12;
422 test =
423 xrealloc(files, numalloc * sizeof(CHAR *), pszSrcFile, __LINE__);
424 if (!test)
425 break;
426 files = test;
427 ltest =
428 xrealloc(cbFile, numalloc * sizeof(ULONG), pszSrcFile, __LINE__);
429 if (!ltest)
430 break;
431 cbFile = ltest;
432 ltest =
433 xrealloc(ulitemID, numalloc * sizeof(ULONG), pszSrcFile, __LINE__);
434 if (!ltest)
435 break;
436 ulitemID = ltest;
437 }
438 cbFile[numfiles] = 0;
439 if (!isArc) {
440
441 FILESTATUS4 fsa4;
442
443 if (!DosQueryPathInfo(szFrom, FIL_QUERYEASIZE, &fsa4, sizeof(fsa4)))
444 cbFile[numfiles] = fsa4.cbFile + CBLIST_TO_EASIZE(fsa4.cbList);
445 }
446 ulitemID[numfiles] = pDItem->ulItemID;
447 files[numfiles] = xstrdup(szFrom, pszSrcFile, __LINE__);
448 files[numfiles + 1] = NULL;
449 if (!files[numfiles])
450 break;
451 numfiles++;
452 DrgSendTransferMsg(pDItem->hwndItem,
453 DM_ENDCONVERSATION,
454 MPFROMLONG(pDItem->ulItemID),
455 MPFROMLONG(DMFL_TARGETSUCCESSFUL));
456 numok++;
457 }
458 else {
459 DrgSendTransferMsg(pDItem->hwndItem,
460 DM_ENDCONVERSATION,
461 MPFROMLONG(pDItem->ulItemID),
462 MPFROMLONG(DMFL_TARGETFAIL));
463 numfail++;
464 }
465 } // for curitem
466
467 if (files && numfiles && files[0] && cbFile && ulitemID) {
468 li = xmallocz(sizeof(LISTINFO), pszSrcFile, __LINE__);
469 if (li) {
470 li->type = Operation;
471 li->hwnd = hwndCnr;
472 li->list = files;
473 li->cbFile = cbFile;
474 li->ulitemID = ulitemID;
475 li->hwndS = pDInfo->hwndSource;
476 if (!pci && directory)
477 strcpy(li->targetpath, directory);
478 else if (pci)
479 strcpy(li->targetpath, pci->pszFileName);
480 if (isArc) {
481 strcpy(li->arcname, szArc);
482 li->info = arcinfo;
483 }
484 SortList(li);
485 }
486 else {
487 if (cbFile)
488 free(cbFile);
489 if (ulitemID)
490 free(ulitemID);
491 if (files)
492 FreeList(files);
493 }
494 }
495 else {
496 if (cbFile)
497 free(cbFile);
498 if (ulitemID)
499 free(ulitemID);
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 is 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}
Note: See TracBrowser for help on using the repository browser.