source: trunk/dll/worker.c@ 1682

Last change on this file since 1682 was 1682, checked in by Gregg Young, 13 years ago

Added optional confirmation dialogs for delete move and copy to compare dir Ticket 277; Added EA compare option to compare dir Ticket 80; Minor code cleanup.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 49.9 KB
Line 
1
2/***********************************************************************
3
4 $Id: worker.c 1682 2013-01-07 00:36:38Z gyoung $
5
6 Worker thread
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2001, 2009 Steven H. Levine
10
11 16 Oct 02 SHL Comments
12 18 Oct 02 SHL MassAction:Archive - force extension so file found
13 06 Jun 05 SHL Indent -i2
14 06 Jun 05 SHL Rework Action for VAC3.65 compat
15 27 Jul 05 SHL IDM_DOITYOURSELF - avoid need to strip in ExecOnList
16 22 Jul 06 SHL Comments
17 22 Jul 06 SHL Check more run time errors
18 03 Nov 06 SHL Renames
19 03 Nov 06 SHL Count thread usage
20 21 Apr 07 GKY Find FM2Utils by path or utils directory
21 16 Jun 07 SHL Update for OpenWatcom
22 06 Aug 07 GKY Reduce DosSleep times (ticket 148)
23 07 Aug 07 SHL Use BldQuotedFileName
24 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
25 26 Aug 07 SHL Revert to DosSleep(0)
26 29 Feb 08 GKY Refactor global command line variables to notebook.h
27 22 Jun 08 GKY Made Felete move to xworkplace trash can on systems that have it
28 16 JUL 08 GKY Use TMP directory for temp files
29 20 Jul 08 GKY Add save/append filename to clipboard.
30 02 Aug 08 GKY Limit use of "trash can" to local writable fixed drives or to trash can supported
31 drives list if it exists. Fix ability to deselect use of trash can.
32 01 Sep 08 GKY Add code to retry on Netdrives "pipe error"
33 04 Dec 08 GKY Add a DosSleep to allow file extract to complete before rescan
34 04 Dec 08 GKY Add mutex semaphore and disable fSyncUpdates for file deletes to prevent the creation
35 on dead CNRITEMS.
36 10 Dec 08 SHL Integrate exception handler support
37 25 Dec 08 GKY Add code to allow write verify to be turned off on a per drive basis
38 25 Dec 08 GKY Add DRIVE_RSCANNED flag to monitor for the first recursive drive scan per session
39 to prevent duplicate directory names in tree following a copy before initial scan.
40 07 Feb 09 GKY Allow user to turn off alert and/or error beeps in settings notebook.
41 08 Mar 09 GKY Removed variable aurguments from docopyf and unlinkf (not used)
42 08 Mar 09 GKY Additional strings move to PCSZs
43 28 Jun 09 GKY Added AddBackslashToPath() to remove repeatative code.
44 26 Jul 09 GKY Fix failure of containers to update when Tree container isn't open in FM2 lite
45 13 Dec 09 GKY Attempt to fix container update issues with FM/2 lite
46 17 JAN 10 GKY Changes to get working with Watcom 1.9 Beta (1/16/10).
47 Mostly cast CHAR CONSTANT * as CHAR *.
48 20 Nov 10 GKY Check that pTmpDir IsValid and recreate if not found; Fixes hangs caused
49 by temp file creation failures.
50 12 Nov 11 GKY Fixed extract failure caused by spaces in the arc file name.
51 04 Aug 12 GKY Changes to use Unlock to unlock files if Unlock.exe is in path both from menu/toolbar and as part of
52 copy, move and delete operations
53 04 Aug 12 GKY Changes to allow copy and move over readonly files with a warning dialog; also added a warning dialog
54 for delete of readonly files
55
56***********************************************************************/
57
58#include <stdlib.h>
59#include <string.h>
60#include <ctype.h>
61#include <share.h>
62#include <process.h> // _beginthread // 10 Dec 08 SHL
63#include <time.h>
64
65#define INCL_DOS
66#define INCL_DOSERRORS
67// #define INCL_WINPROGRAMLIST // 13 Jul 09 SHL dropped
68// #define INCL_WINHELP // 13 Jul 09 SHL dropped
69#define INCL_LONGLONG
70#define INCL_WINPOINTERS // WinSetFileIcon
71// #define INCL_WINWORKPLACE // 13 Jul 09 SHL dropped
72#define INCL_WINSHELLDATA // PrfQueryProfileData
73
74#include "fm3dll.h"
75#include "fm3dll2.h" // #define's for UM_*, control id's, etc.
76#include "mainwnd2.h" // Data declaration(s)
77#include "arccnrs.h" // Data declaration(s)
78#include "init.h" // Data declaration(s)
79#include "defview.h" // Data declaration(s)
80#include "newview.h" // Data declarations
81#include "fm3dlg.h"
82#include "fm3str.h"
83#include "comp.h" // FCOMPARE
84#include "pathutil.h" // BldQuotedFileName
85#include "makelist.h" // AddToList
86#include "errutil.h" // Dos_Error...
87#include "strutil.h" // GetPString
88#include "notebook.h" // External viewers
89#include "worker.h" // Action
90#include "notify.h" // AddNote
91#include "copyf.h" // AdjustWildcardName, make_deleteable
92#include "attribs.h" // AttrListDlgProc
93#include "chklist.h" // CheckListProc
94#include "info.h" // DrvInfoProc
95#include "extract.h" // ExtractDlgProc
96#include "info.h" // FileInfoProc
97#include "valid.h" // GetDesktopName, IsNewer
98#include "saveclip.h" // ListToClipboardHab
99#include "shadow.h" // MakeShadows
100#include "mkdir.h" // MassMkdir
101#include "uudecode.h" // MergeDlgProc
102#include "objcnr.h" // ObjCnrDlgProc
103#include "printer.h" // PrintDlgProc, PrintListThread
104#include "rename.h" // RenameProc
105#include "srchpath.h" // RunFM2Util
106#include "mainwnd.h" // TopWindowName
107#include "uudecode.h" // UUD
108#include "walkem.h" // WalkCopyDlgProc, WalkDlgProc, WalkMoveDlgProc
109#include "archive.h" // ArchiveDlgProc
110#include "misc.h" // Broadcast
111#include "common.h" // DecrThreadUsage, IncrThreadUsage
112#include "eas.h" // DisplayEAsProc
113#include "systemf.h" // ExecOnList
114#include "avl.h" // SBoxDlgProc
115#include "subj.h" // Subject
116#include "stristr.h" // stristr
117#include "wrappers.h" // xfopen
118#include "fortify.h"
119#include "excputil.h" // 06 May 08 SHL added
120
121// Data definitions
122#pragma data_seg(GLOBAL2)
123FILE *LogFileHandle;
124BOOL fUnlock;
125
126#pragma data_seg(DATA2)
127
128static PSZ pszSrcFile = __FILE__;
129
130#ifdef UNDO
131
132static VOID LINFO undo;
133
134VOID FreeUndo(VOID)
135{
136 if (undo->list)
137 FreeList(undo->list);
138 memset(&undo, 0, sizeof(undo));
139}
140
141VOID Undo(HWND hwndCnr, HWND hwndFrame, HWND hwndClient, HWND hwndParent)
142{
143 LISTINFO *li;
144 WORKER *wk;
145
146 if (undo->type && undo->list && undo->list[0]) {
147 switch (undo->type) {
148 case IDM_MOVE:
149 case IDM_COPY:
150 case IDM_EXTRACT:
151 {
152# ifdef FORTIFY
153 Fortify_EnterScope();
154# endif
155 li = xmallocz(sizeof(LISTINFO), pszSrcFile, __LINE__);
156 if (li) {
157 wk = xmallocz(sizeof(WORKER), pszSrcFile, __LINE__);
158 if (wk) {
159 wk->size = sizeof(WORKER);
160 wk->hwndCnr = hwndCnr;
161 wk->hwndParent = hwndParent;
162 wk->hwndFrame = hwndFrame;
163 wk->hwndClient = hwndClient;
164 wk->li = li;
165 *wk->li = *undo;
166 switch (undo->type) {
167 case IDM_COPY:
168 case IDM_EXTRACT:
169 li->type = IDM_PERMDELETE;
170 break;
171 }
172 if (xbeginthread(MassAction,
173 122880,
174 wk,
175 pszSrcFile,
176 __LINE__) == -1)
177 {
178 FreeListInfo(wk->li);
179 free(wk);
180# ifdef FORTIFY
181 Fortify_LeaveScope();
182# endif
183 }
184 }
185 else
186 FreeListInfo(li);
187 }
188 }
189 break;
190 } // switch
191 }
192 FreeUndo();
193# ifdef FORTIFY
194 Fortify_LeaveScope();
195# endif
196}
197
198#endif // defined(UNDO)
199
200/**
201 * Apply action to file list
202 * Action repeated for each item in list
203 */
204
205VOID Action(VOID * args)
206{
207 WORKER *wk = (WORKER *)args;
208 HAB hab2;
209 HMQ hmq2;
210 CHAR **files = NULL;
211 INT plen = 0;
212 CHAR *p, *pp;
213 CHAR szQuotedDirName[CCHMAXPATH];
214 CHAR szQuotedFileName[CCHMAXPATH];
215
216
217 if (wk) {
218# ifdef FORTIFY
219 Fortify_EnterScope();
220# endif
221 if (wk->li && wk->li->list && wk->li->list[0]) {
222 hab2 = WinInitialize(0);
223 if (hab2) {
224 hmq2 = WinCreateMsgQueue(hab2, 0);
225 if (hmq2) {
226 CHAR message[(CCHMAXPATH * 2) + 80], wildname[CCHMAXPATH];
227 UINT x;
228 BOOL dontask = FALSE, wildcarding = FALSE, overold =
229 FALSE, overnew = FALSE, noreadonlywarn = FALSE, usedtarget;
230
231 WinCancelShutdown(hmq2, TRUE);
232 IncrThreadUsage();
233 *wildname = 0;
234 // Do action specific preprocessing
235 switch (wk->li->type) {
236 case IDM_MERGE:
237 if (wk->li->type == IDM_MERGE) {
238 if (TestBinary(wk->li->list[0]))
239 wk->li->type = IDM_MERGEBINARY;
240 else
241 wk->li->type = IDM_MERGETEXT;
242 }
243 strcpy(wk->li->targetpath, wk->li->list[0]);
244 p = strrchr(wk->li->targetpath, '\\');
245 if (p) {
246 p++;
247 *p = 0;
248 }
249 else
250 strcat(wk->li->targetpath, PCSZ_BACKSLASH);
251 sprintf(wk->li->targetpath + strlen(wk->li->targetpath),
252 "MERGE.%03x", (clock() & 4095L));
253 if (!WinDlgBox(HWND_DESKTOP,
254 wk->hwndFrame,
255 MergeDlgProc, FM3ModHandle, MRG_FRAME, (PVOID) wk))
256 goto Abort;
257 if (!wk->li->type ||
258 !*wk->li->targetpath || !wk->li->list || !wk->li->list[0])
259 goto Abort;
260 if (IsFile(wk->li->targetpath) != 1 && !wk->li->list[1]) {
261 saymsg(MB_CANCEL | MB_ICONEXCLAMATION,
262 wk->hwndFrame,
263 GetPString(IDS_AHEMTEXT),
264 GetPString(IDS_SILLYMERGETEXT));
265 goto Abort;
266 }
267 break;
268 case IDM_WILDMOVE:
269 wildcarding = TRUE;
270 wk->li->type = IDM_MOVE;
271 break;
272 case IDM_WILDRENAME:
273 wildcarding = TRUE;
274 wk->li->type = IDM_RENAME;
275 break;
276 case IDM_WILDCOPY:
277 wildcarding = TRUE;
278 wk->li->type = IDM_COPY;
279 break;
280 case IDM_MOVEPRESERVE:
281 {
282 CHAR preserve[CCHMAXPATH], *end;
283
284 wk->li->type = IDM_MOVE;
285 strcpy(preserve, wk->li->list[0] + 2);
286 end = strrchr(preserve, '\\');
287 if (end) {
288 end++;
289 for (x = 1; wk->li->list[x]; x++) {
290 p = preserve;
291 pp = wk->li->list[x] + 2;
292 while (p < end && toupper(*p) == toupper(*pp)) {
293 p++;
294 pp++;
295 }
296 if (*p == '\\')
297 p++;
298 if (p < end)
299 end = p;
300 }
301 *end = 0;
302 }
303 else
304 *preserve = 0;
305 plen = strlen(preserve);
306 if (plen)
307 plen += 2;
308 }
309 break;
310 case IDM_COPYPRESERVE:
311 {
312 CHAR preserve[CCHMAXPATH], *end;
313
314 wk->li->type = IDM_COPY;
315 strcpy(preserve, wk->li->list[0] + 2);
316 end = strrchr(preserve, '\\');
317 if (end) {
318 end++;
319 for (x = 1; wk->li->list[x]; x++) {
320 p = preserve;
321 pp = wk->li->list[x] + 2;
322 while (p < end && toupper(*p) == toupper(*pp)) {
323 p++;
324 pp++;
325 }
326 if (*p == '\\')
327 p++;
328 if (p < end)
329 end = p;
330 }
331 *end = 0;
332 }
333 else
334 *preserve = 0;
335 plen = strlen(preserve);
336 if (plen)
337 plen += 2;
338 }
339 break;
340 }
341 // Process each list item
342 if (wk->li && wk->li->list && wk->li->list[0]) {
343 UINT cFilesModified = 0; // Required for AddToList
344 UINT cItemsAllocated = 0; // Required for AddToList
345 UINT cItemsInList;
346 for (cItemsInList = 0; wk->li->list[cItemsInList]; cItemsInList++); // Count
347 for (x = 0; wk->li->list[x]; x++) {
348 switch (wk->li->type) {
349 case IDM_COLLECTFROMFILE:
350 if (Collector) {
351
352 CHAR *temp = xstrdup(wk->li->list[x], pszSrcFile, __LINE__);
353
354 if (temp) {
355 if (!PostMsg(Collector,
356 UM_COLLECTFROMFILE, MPFROMP(temp), MPVOID))
357 free(temp);
358 }
359 }
360 break;
361
362 case IDM_MERGEBINARY:
363 case IDM_MERGETEXT:
364 case IDM_MERGEBINARYAPPEND:
365 case IDM_MERGETEXTAPPEND:
366 {
367 FILE *in, *out;
368 CHAR *moder, *modew;
369 int c;
370
371 switch (wk->li->type) {
372 case IDM_MERGEBINARY:
373 moder = "rb";
374 modew = "wb";
375 break;
376 case IDM_MERGEBINARYAPPEND:
377 moder = "rb";
378 modew = "a+b";
379 break;
380 case IDM_MERGETEXTAPPEND:
381 moder = "r";
382 modew = "a+";
383 break;
384 default:
385 moder = "r";
386 modew = "w";
387 break;
388 }
389 in = xfsopen(wk->li->list[x], moder, SH_DENYWR, pszSrcFile, __LINE__, TRUE);
390 if (!in) {
391 if (saymsg(MB_ENTERCANCEL,
392 HWND_DESKTOP,
393 GetPString(IDS_MERGEERRORTEXT),
394 GetPString(IDS_CANTOPENINPUTTEXT),
395 wk->li->list[x]) == MBID_CANCEL)
396 goto Abort;
397 }
398 else {
399 out = xfsopen(wk->li->targetpath, modew, SH_DENYWR,
400 pszSrcFile, __LINE__, TRUE);
401 if (out) {
402 fseek(out, 0L, SEEK_END);
403 switch (wk->li->type) {
404 case IDM_MERGEBINARY:
405 wk->li->type = IDM_MERGEBINARYAPPEND;
406 break;
407 default:
408 wk->li->type = IDM_MERGETEXTAPPEND;
409 break;
410 }
411 sprintf(message,
412 GetPString(IDS_MERGINGTEXT),
413 wk->li->list[x], wk->li->targetpath);
414 AddNote(message);
415 while ((c = fgetc(in)) != EOF)
416 fputc(c, out);
417 fclose(out);
418 sprintf(message,
419 GetPString(IDS_MERGECOMPLETETEXT),
420 wk->li->list[x], wk->li->targetpath);
421 AddNote(message);
422 }
423 else {
424 saymsg(MB_CANCEL,
425 HWND_DESKTOP,
426 GetPString(IDS_MERGEERRORTEXT),
427 GetPString(IDS_CANTOPENOUTPUTTEXT),
428 wk->li->targetpath);
429 fclose(in);
430 goto Abort;
431 }
432 fclose(in);
433 }
434 }
435 break;
436
437 case IDM_UUDECODE:
438 {
439 CHAR outname[CCHMAXPATH + 2];
440
441 sprintf(message,
442 GetPString(IDS_UUDECODINGTEXT), wk->li->list[x]);
443 AddNote(message);
444 if (UUD(wk->li->list[x], outname) && *outname) {
445 sprintf(message,
446 GetPString(IDS_UUDECODECOMPLETETEXT),
447 wk->li->list[x]);
448 AddNote(message);
449 if (//fSyncUpdates ||
450 AddToList(outname, &files, &cFilesModified, &cItemsAllocated))
451 Broadcast(hab2,
452 wk->hwndCnr,
453 UM_UPDATERECORD, MPFROMP(outname), MPVOID);
454 }
455 else {
456 sprintf(message,
457 GetPString(IDS_UUDECODEABORTEDTEXT),
458 wk->li->list[x]);
459 AddNote(message);
460 }
461 }
462 break;
463
464 case IDM_UNLOCKFILE:
465 if (IsFile(wk->li->list[x]) > 0 && fUnlock) {
466 runemf2(SEPARATE | INVISIBLE | BACKGROUND | WAIT,
467 HWND_DESKTOP, pszSrcFile, __LINE__,
468 NULL, NULL, "%s %s", PCSZ_UNLOCKEXE, wk->li->list[x]);
469 }
470 break;
471
472 case IDM_VIEWARCHIVE:
473 if (IsFile(wk->li->list[x]) > 0) {
474
475 ARC_TYPE *info = NULL; // Say calling for editing - fixme to know why?
476
477 if (WinDlgBox(HWND_DESKTOP,
478 wk->hwndFrame,
479 SBoxDlgProc,
480 FM3ModHandle,
481 ASEL_FRAME, (PVOID) & info) && info) {
482 WinSendMsg(wk->hwndCnr,
483 UM_OPENWINDOWFORME,
484 MPFROMP(wk->li->list[x]), MPFROMP(info));
485 }
486 }
487 break;
488
489 case IDM_EXTRACT:
490 {
491 EXTRDATA ex;
492 BOOL maskspaces = FALSE;
493 CHAR arcname[CCHMAXPATH];
494
495 memset(&ex, 0, sizeof(EXTRDATA));
496 ex.info = find_type(wk->li->list[x], NULL);
497 if (!ex.info || (!ex.info->extract && !ex.info->exwdirs))
498 break;
499 ex.size = sizeof(EXTRDATA);
500 BldQuotedFileName(arcname, wk->li->list[x]);
501 ex.arcname = arcname;
502 if (!*ex.masks)
503 strcpy(ex.masks, "*");
504 strcpy(ex.extractdir, wk->li->targetpath);
505 if (!WinDlgBox(HWND_DESKTOP,
506 wk->hwndFrame,
507 ExtractDlgProc,
508 FM3ModHandle,
509 EXT_FRAME,
510 (PVOID) & ex) ||
511 !ex.ret ||
512 !*ex.command || !*ex.arcname || !*ex.extractdir)
513 goto Abort;
514 {
515 FILESTATUS3 fsa;
516
517 DosError(FERR_DISABLEHARDERR);
518 if (DosQueryPathInfo(ex.extractdir,
519 FIL_STANDARD,
520 &fsa,
521 (ULONG) sizeof(FILESTATUS3)) ||
522 !(fsa.attrFile & FILE_DIRECTORY))
523 goto Abort;
524 }
525 if (needs_quoting(ex.masks) && !strchr(ex.masks, '\"'))
526 maskspaces = TRUE;
527 if (!runemf2(SEPARATE | WINDOWED | WAIT |
528 fArcStuffVisible ? 0 : (BACKGROUND | MINIMIZED),
529 HWND_DESKTOP, pszSrcFile, __LINE__, ex.extractdir, NULL,
530 "%s %s %s%s%s",
531 ex.command,
532 ex.arcname,
533 maskspaces ? "\"" : NullStr,
534 *ex.masks ? ex.masks : "\"*\"",
535 maskspaces ? "\"" : NullStr) &&
536 !stricmp(ex.extractdir, wk->directory)) {
537 DosSleep(100); // wait for runemf2 to complete so rescan will actually show something
538 if (WinIsWindow((HAB) 0, wk->hwndCnr))
539 WinSendMsg(wk->hwndCnr,
540 WM_COMMAND,
541 MPFROM2SHORT(IDM_RESCAN, 0), MPVOID);
542 }
543 }
544 break;
545
546 case IDM_SUBJECT:
547 {
548 INT ret;
549
550 ret = Subject(wk->hwndFrame, wk->li->list[x]);
551 if (!ret)
552 goto Abort;
553 if (ret == 1) {
554 if (//fSyncUpdates ||
555 AddToList(wk->li->list[x],
556 &files, &cFilesModified, &cItemsAllocated))
557 Broadcast(hab2,
558 wk->hwndCnr,
559 UM_UPDATERECORD,
560 MPFROMP(wk->li->list[x]), MPVOID);
561 }
562 }
563 break;
564
565 case IDM_INFO:
566 if (IsFullName(wk->li->list[x]) &&
567 !(driveflags[toupper(*wk->li->list[x]) - 'A'] &
568 DRIVE_INVALID)) {
569 if (!IsRoot(wk->li->list[x])) {
570
571 CHAR *list[2];
572
573 list[0] = wk->li->list[x];
574 list[1] = NULL;
575 if (!WinDlgBox(HWND_DESKTOP,
576 HWND_DESKTOP,
577 FileInfoProc,
578 FM3ModHandle, FLE_FRAME, (PVOID) list)) {
579 goto Abort;
580 }
581 }
582 else {
583 if (!WinDlgBox(HWND_DESKTOP,
584 HWND_DESKTOP,
585 DrvInfoProc,
586 FM3ModHandle,
587 INFO_FRAME, (PVOID) wk->li->list[x]))
588 goto Abort;
589 }
590 }
591 break;
592
593 case IDM_OPENWINDOW:
594 if (!IsFile(wk->li->list[x]) &&
595 WinIsWindow(hab2, wk->hwndCnr))
596 WinSendMsg(wk->hwndCnr,
597 UM_OPENWINDOWFORME,
598 MPFROMP(wk->li->list[x]), MPVOID);
599 break;
600
601 case IDM_OPENICON:
602 case IDM_OPENDETAILS:
603 case IDM_OPENTREE:
604 {
605 FILESTATUS3 fsa;
606
607 DosError(FERR_DISABLEHARDERR);
608 if (DosQueryPathInfo(wk->li->list[x],
609 FIL_STANDARD,
610 &fsa,
611 (ULONG) sizeof(FILESTATUS3)) ||
612 !(fsa.attrFile & FILE_DIRECTORY))
613 break;
614 }
615 // else intentional fallthru
616 case IDM_OPENDEFAULT:
617 case IDM_OPENSETTINGS:
618 {
619 CHAR *s;
620
621 switch (wk->li->type) {
622 case IDM_OPENICON:
623 s = (PSZ) PCSZ_ICON;
624 break;
625 case IDM_OPENDETAILS:
626 s = (PSZ) Details;
627 break;
628 case IDM_OPENTREE:
629 s = (PSZ) PCSZ_TREE;
630 break;
631 case IDM_OPENSETTINGS:
632 s = (PSZ) Settings;
633 break;
634 default:
635 s = (PSZ) Default;
636 break;
637 }
638 OpenObject(wk->li->list[x], s, wk->hwndFrame);
639 }
640 break;
641
642 case IDM_WPSMOVE:
643 case IDM_WPSCOPY:
644 case IDM_MOVE:
645 case IDM_COPY:
646 case IDM_RENAME:
647 {
648
649 // Select target
650 if (!*wk->li->targetpath && (wk->li->type == IDM_MOVE ||
651 wk->li->type == IDM_COPY ||
652 wk->li->type == IDM_WPSMOVE ||
653 wk->li->type == IDM_WPSCOPY)) {
654
655 APIRET rc = 1;
656 usedtarget = FALSE;
657 if (hwndMain) {
658 if (!*targetdir)
659 TopWindowName(hwndMain,
660 wk->hwndFrame, wk->li->targetpath);
661 else {
662 strcpy(wk->li->targetpath, targetdir);
663 usedtarget = TRUE;
664 }
665 }
666 if (!*wk->li->targetpath)
667 strcpy(wk->li->targetpath, wk->directory);
668 if (!*wk->li->targetpath) {
669 strcpy(wk->li->targetpath, wk->li->list[0]);
670 p = strrchr(wk->li->targetpath, '\\');
671 if (p) {
672 if (*(p - 1) == ':')
673 p++;
674 *p = 0;
675 }
676 }
677 MakeValidDir(wk->li->targetpath);
678 if (fConfirmTarget ||
679 (!*targetdir && strcmp(realappname, "FM/4"))) {
680 RetryPath:
681 // Confirm target
682 usedtarget = FALSE;
683 if (wk->li->type == IDM_MOVE ||
684 wk->li->type == IDM_WPSMOVE) {
685 rc = WinDlgBox(HWND_DESKTOP,
686 wk->hwndFrame,
687 WalkMoveDlgProc,
688 FM3ModHandle,
689 WALK_FRAME, MPFROMP(wk->li->targetpath));
690 }
691 else if (wk->li->type == IDM_COPY ||
692 wk->li->type == IDM_WPSCOPY) {
693 rc = WinDlgBox(HWND_DESKTOP,
694 wk->hwndFrame,
695 WalkCopyDlgProc,
696 FM3ModHandle,
697 WALK_FRAME, MPFROMP(wk->li->targetpath));
698 }
699 else
700 rc = WinDlgBox(HWND_DESKTOP,
701 wk->hwndFrame,
702 WalkDlgProc,
703 FM3ModHandle,
704 WALK_FRAME, MPFROMP(wk->li->targetpath));
705 }
706 if (!rc || !*wk->li->targetpath)
707 goto Abort;
708 // Check target OK
709 if (driveflags[toupper(*wk->li->targetpath) - 'A'] &
710 DRIVE_NOTWRITEABLE) {
711 saymsg(MB_CANCEL,
712 wk->hwndFrame,
713 GetPString(IDS_ERRORTEXT),
714 GetPString(IDS_NOTWRITENOTARGETTEXT));
715 goto RetryPath;
716 }
717 }
718 Retry:
719 {
720 // Target OK so far
721 CHAR newname[CCHMAXPATH];
722 APIRET rc;
723 INT ret;
724 FILESTATUS4L fs4;
725 BOOL isnewer;
726 BOOL existed;
727 BOOL fResetVerify = FALSE;
728 INT type = wk->li->type == IDM_RENAME ?
729 MOVE :
730 wk->li->type == IDM_MOVE ?
731 MOVE : (wk->li->type == IDM_WPSMOVE) ?
732 WPSMOVE : wk->li->type == IDM_WPSCOPY ?
733 WPSCOPY : COPY;
734 PCSZ moving = wk->li->type == IDM_RENAME ?
735 GetPString(IDS_RENAMINGTEXT) :
736 wk->li->type == IDM_MOVE || wk->li->type == IDM_WPSMOVE ?
737 GetPString(IDS_MOVINGTEXT) : GetPString(IDS_COPYINGTEXT);
738 PCSZ move = wk->li->type == IDM_RENAME ?
739 GetPString(IDS_RENAMETEXT) :
740 wk->li->type == IDM_MOVE ||
741 wk->li->type == IDM_WPSMOVE ?
742 GetPString(IDS_MOVETEXT) : GetPString(IDS_COPYTEXT);
743 PCSZ moved = wk->li->type == IDM_RENAME ?
744 GetPString(IDS_RENAMEDTEXT) :
745 wk->li->type == IDM_MOVE || wk->li->type == IDM_WPSMOVE ?
746 GetPString(IDS_MOVEDTEXT) : GetPString(IDS_COPIEDTEXT);
747
748 if (*wk->li->targetpath) {
749 strcpy(newname, wk->li->targetpath);
750 AddBackslashToPath(newname);
751 if (plen)
752 p = wk->li->list[x] + plen;
753 else {
754 p = strrchr(wk->li->list[x], '\\');
755 if (p)
756 p++;
757 else
758 p = wk->li->list[x];
759 }
760 strcat(newname, p);
761 }
762 else
763 strcpy(newname, wk->li->list[x]);
764 if ((wildcarding || wk->li->type == IDM_RENAME) &&
765 *wildname)
766 {
767 CHAR testname[CCHMAXPATH];
768 strcpy(testname, wildname);
769 if (AdjustWildcardName(newname, testname))
770 strcpy(newname, testname);
771 }
772 existed = IsFile(newname) != -1;
773 isnewer = IsNewer(wk->li->list[x], newname);
774 if (existed && wk->li->type != IDM_RENAME && dontask) {
775 if (!overold && !overnew)
776 break;
777 if (!overold && !isnewer)
778 break;
779 if (!overnew && isnewer)
780 break;
781 }
782 // Confirm overwrite unless bypassed
783 if ((wk->li->type == IDM_RENAME &&
784 (!dontask || !*wildname)) ||
785 (!dontask && existed) ||
786 (!dontask && wildcarding) ||
787 (IsFile(newname) == 0 && IsFile(wk->li->list[x]) > 0))
788 {
789 MOVEIT mv;
790 memset(&mv, 0, sizeof(MOVEIT));
791 mv.rename = (wk->li->type == IDM_RENAME);
792 mv.source = wk->li->list[x];
793 strcpy(mv.target, newname);
794 rc = WinDlgBox(HWND_DESKTOP,
795 wk->hwndFrame,
796 RenameProc,
797 FM3ModHandle, REN_FRAME, (PVOID) & mv);
798 if (!rc)
799 goto Abort;
800
801 DosSleep(1);
802 if (mv.skip || !*mv.target)
803 break;
804 if (mv.dontask)
805 dontask = TRUE;
806 if (mv.overold)
807 overold = TRUE;
808 if (mv.overnew)
809 overnew = TRUE;
810 if (mv.noreadonlywarn)
811 noreadonlywarn = TRUE;
812 if (wildcarding || wk->li->type == IDM_RENAME) {
813 p = strrchr(mv.target, '\\');
814 if (p && (strchr(p, '*') || strchr(p, '?'))) {
815 strcpy(wildname, mv.target);
816 AdjustWildcardName(wk->li->list[x], mv.target);
817 }
818 else
819 *wildname = 0;
820 }
821 strcpy(newname, mv.target);
822 existed = (IsFile(newname) != -1);
823 isnewer = IsNewer(wk->li->list[x], newname);
824 if (!mv.overwrite) {
825 if (existed && wk->li->type != IDM_RENAME && dontask) {
826 if (!overold && !overnew)
827 break;
828 if (!overold && !isnewer)
829 break;
830 if (!overnew && isnewer)
831 break;
832 }
833 }
834 }
835 if (!strcmp(wk->li->list[x], newname) ||
836 (wk->li->type == IDM_COPY &&
837 !stricmp(wk->li->list[x], newname)))
838 break;
839 sprintf(message,
840 " %s \"%s\" %s\"%s\"%s [%u %s%u]",
841 moving,
842 wk->li->list[x],
843 GetPString(IDS_TOTEXT), // Has trailing space
844 newname,
845 usedtarget ?
846 GetPString(IDS_TOTARGETTEXT) :
847 NullStr,
848 x + 1,
849 GetPString(IDS_OFTEXT), // Has trailing space
850 cItemsInList);
851 AddNote(message);
852 if (fVerify && (driveflags[toupper(*wk->li->targetpath) - 'A'] & DRIVE_WRITEVERIFYOFF) |
853 (driveflags[toupper(*wk->li->list[x]) - 'A'] & DRIVE_WRITEVERIFYOFF)) {
854 DosSetVerify(FALSE);
855 fResetVerify = TRUE;
856 }
857 if (plen) {
858 // make directory/ies, if required
859
860 CHAR dirpart[CCHMAXPATH];
861
862 strcpy(dirpart, newname);
863 p = strrchr(dirpart, '\\');
864 if (p) {
865 *p = 0;
866 if (p > dirpart + 3)
867 MassMkdir((hwndMain) ? hwndMain : wk->hwndCnr,
868 dirpart);
869 }
870 }
871 if (fRealIdle)
872 priority_idle();
873
874 rc = docopyf(type, wk->li->list[x], newname);
875 if (rc == ERROR_ACCESS_DENIED || rc == ERROR_SHARING_VIOLATION) {
876 if (rc == ERROR_ACCESS_DENIED && noreadonlywarn)
877 rc = -1;
878 ret = make_deleteable(newname, rc);
879 rc = docopyf(type, wk->li->list[x], newname);
880 }
881 if (!ret && (rc == ERROR_ACCESS_DENIED || (rc == ERROR_SHARING_VIOLATION && fUnlock)))
882 rc = NO_ERROR;
883 if (fResetVerify) {
884 DosSetVerify(fVerify);
885 fResetVerify = FALSE;
886 }
887 priority_normal();
888 if (rc) {
889 if ((rc == ERROR_DISK_FULL ||
890 rc == ERROR_HANDLE_DISK_FULL) &&
891 isalpha(*newname) &&
892 (driveflags[toupper(*newname) - 'A'] &
893 DRIVE_REMOVABLE)
894 && !(driveflags[toupper(*newname) - 'A'] &
895 DRIVE_NOTWRITEABLE)
896 && toupper(*newname) != toupper(*wk->li->list[x])
897 && !DosQueryPathInfo(wk->li->list[x], FIL_QUERYEASIZEL,
898 &fs4, sizeof(fs4))
899 && !(fs4.attrFile & FILE_DIRECTORY)) {
900
901 FSALLOCATE fsa;
902 ULONGLONG ullFreeBytes;
903 CHAR *ptr;
904 INT cntr;
905
906 Notify(GetPString(IDS_FITTINGTEXT));
907 DosError(FERR_DISABLEHARDERR);
908 if (!DosQueryFSInfo(toupper(*newname) - '@',
909 FSIL_ALLOC,
910 &fsa, sizeof(FSALLOCATE))) {
911 // Assume large file support
912 ullFreeBytes = (ULONGLONG) fsa.cUnitAvail * fsa.cSectorUnit *
913 fsa.cbSector;
914 if (ullFreeBytes) {
915 // Find item that will fit in available space
916 for (cntr = x + 1; wk->li->list[cntr]; cntr++) {
917 DosError(FERR_DISABLEHARDERR);
918 if (!DosQueryPathInfo(wk->li->list[cntr],
919 FIL_QUERYEASIZEL,
920 &fs4,
921 sizeof(fs4)) &&
922 !(fs4.attrFile & FILE_DIRECTORY) &&
923 // fixme to use CBLIST_TO_EASIZE?
924 fs4.cbFile + fs4.cbList <= ullFreeBytes) {
925 // Swap with failing item
926 ptr = wk->li->list[x];
927 wk->li->list[x] = wk->li->list[cntr];
928 wk->li->list[cntr] = ptr;
929 goto Retry;
930 }
931 }
932 Notify(GetPString(IDS_COULDNTFITTEXT));
933 }
934 }
935 rc = saymsg(MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION,
936 wk->hwndFrame,
937 GetPString(IDS_DISKFULLTEXT),
938 GetPString(IDS_ANOTHERDISKTEXT));
939 if (rc == MBID_RETRY)
940 goto Retry;
941 if (rc == MBID_ABORT)
942 goto Abort;
943 }
944 else {
945 if (LogFileHandle) {
946 fprintf(LogFileHandle,
947 GetPString(IDS_LOGTOFAILEDTEXT),
948 move, wk->li->list[x], newname, rc);
949 }
950 rc = Dos_Error(MB_ENTERCANCEL,
951 rc,
952 wk->hwndFrame,
953 pszSrcFile,
954 __LINE__,
955 "%s %s\"%s\" %s\"%s\" %s.",
956 move,
957 GetPString(IDS_OFTEXT), // Has trailing space
958 wk->li->list[x],
959 GetPString(IDS_TOTEXT),
960 newname, GetPString(IDS_FAILEDTEXT));
961 if (rc == MBID_CANCEL)
962 goto Abort;
963 }
964 }
965 else {
966 if (LogFileHandle) {
967 fprintf(LogFileHandle,
968 "%s \"%s\" %s\"%s\"\n",
969 moved,
970 wk->li->list[x],
971 GetPString(IDS_TOTEXT), newname);
972 }
973 if (!strcmp(realappname, "FM/4") ||
974 ((driveflags[*wk->li->targetpath - 'A'] & DRIVE_RSCANNED) &&
975 AddToList(wk->li->list[x],
976 &files, &cFilesModified, &cItemsAllocated)))
977 Broadcast(hab2,
978 wk->hwndCnr,
979 UM_UPDATERECORD,
980 MPFROMP(wk->li->list[x]), MPVOID);
981 if (!strcmp(realappname, "FM/4") ||
982 (driveflags[*wk->li->targetpath - 'A'] & DRIVE_RSCANNED) &&
983 AddToList(newname, &files, &cFilesModified, &cItemsAllocated))
984 Broadcast(hab2,
985 wk->hwndCnr,
986 UM_UPDATERECORD, MPFROMP(newname), MPVOID);
987 }
988 }
989 break;
990 }
991
992 case IDM_COMPARE:
993 if ((!IsFile(wk->li->targetpath) ||
994 IsRoot(wk->li->targetpath)) &&
995 (!IsFile(wk->li->list[x]) || IsRoot(wk->li->list[x]))) {
996 if (!*dircompare && WinIsWindow(hab2, wk->hwndCnr))
997 WinSendMsg(wk->hwndCnr,
998 UM_COMPARE,
999 MPFROMP(wk->li->targetpath),
1000 MPFROMP(wk->li->list[x]));
1001 else {
1002 runemf2(SEPARATE,
1003 HWND_DESKTOP, pszSrcFile, __LINE__,
1004 NULL, NULL,
1005 "%s %s %s",
1006 dircompare,
1007 BldQuotedFileName(szQuotedDirName, wk->li->targetpath),
1008 BldQuotedFileName(szQuotedFileName, wk->li->list[x]));
1009 }
1010 }
1011 else if (*compare) {
1012 CHAR *fakelist[3];
1013
1014 fakelist[0] = wk->li->list[x];
1015 fakelist[1] = wk->li->targetpath;
1016 fakelist[2] = NULL;
1017 ExecOnList(wk->hwndFrame,
1018 compare,
1019 WINDOWED | SEPARATEKEEP, NULL, NULL, fakelist, NULL,
1020 pszSrcFile, __LINE__);
1021 }
1022 else {
1023 FCOMPARE fc;
1024
1025 memset(&fc, 0, sizeof(fc));
1026 fc.size = sizeof(fc);
1027 fc.hwndParent = wk->hwndParent;
1028 strcpy(fc.file1, wk->li->list[x]);
1029 strcpy(fc.file2, wk->li->targetpath);
1030 if (WinDlgBox(HWND_DESKTOP,
1031 wk->hwndFrame,
1032 CFileDlgProc,
1033 FM3ModHandle, FCMP_FRAME, (PVOID) & fc))
1034 goto Abort;
1035 }
1036 break;
1037 } // switch
1038 DosSleep(0);
1039 } // for list
1040
1041 // Do action specific post-processing
1042 switch (wk->li->type) {
1043 case IDM_MOVE:
1044 case IDM_COPY:
1045 case IDM_WPSMOVE:
1046 case IDM_WPSCOPY:
1047 case IDM_RENAME:
1048 sprintf(message,
1049 GetPString(IDS_OPSCOMPLETETEXT),
1050 wk->li->type == IDM_MOVE ?
1051 GetPString(IDS_MOVETEXT) :
1052 wk->li->type == IDM_COPY ?
1053 GetPString(IDS_COPYTEXT) :
1054 wk->li->type == IDM_WPSMOVE ?
1055 GetPString(IDS_WPSMOVETEXT) :
1056 wk->li->type == IDM_WPSCOPY ?
1057 GetPString(IDS_WPSCOPYTEXT) :
1058 GetPString(IDS_RENAMETEXT),
1059 &"s"[x == 1], // s or nul
1060 (wk->li->type == IDM_MOVE ||
1061 wk->li->type == IDM_COPY ||
1062 wk->li->type == IDM_WPSMOVE ||
1063 wk->li->type == IDM_WPSCOPY) ?
1064 GetPString(IDS_TOTEXT) : NullStr,
1065 (wk->li->type == IDM_MOVE ||
1066 wk->li->type == IDM_COPY ||
1067 wk->li->type == IDM_WPSMOVE ||
1068 wk->li->type == IDM_WPSCOPY) ?
1069 wk->li->targetpath : NullStr,
1070 GetPString(x != 1 ? IDS_ARETEXT : IDS_ISTEXT));
1071 Notify(message);
1072 if (toupper(*wk->li->targetpath) < 'C' && !fAlertBeepOff)
1073 DosBeep(1000, 25); // Wake up user
1074 DosSleep(16);//05 Aug 07 GKY 33
1075 if (wk->li->type == IDM_WPSMOVE || wk->li->type == IDM_WPSCOPY)
1076 DosSleep(48);//05 Aug 07 GKY 96
1077 break;
1078 default:
1079 break;
1080 }
1081 } // if have non-empty list
1082
1083 Abort:
1084
1085 if (files) {
1086 if (!strcmp(realappname, "FM/4") || !hwndTree ||
1087 (driveflags[*wk->li->targetpath - 'A'] & DRIVE_RSCANNED))
1088 Broadcast(hab2,
1089 wk->hwndCnr,
1090 UM_UPDATERECORDLIST, MPFROMP(files), MPVOID);
1091 FreeList(files);
1092 }
1093
1094 if (WinIsWindow(hab2, wk->hwndCnr))
1095 PostMsg(wk->hwndCnr, UM_RESCAN, MPVOID, MPVOID);
1096
1097 WinDestroyMsgQueue(hmq2);
1098 } // if queue
1099 DecrThreadUsage();
1100 WinTerminate(hab2);
1101 } // if hab2
1102 } // if list not empty
1103
1104 if (wk->li)
1105 FreeListInfo(wk->li);
1106 free(wk);
1107# ifdef FORTIFY
1108 Fortify_LeaveScope();
1109# endif
1110 DosPostEventSem(CompactSem);
1111 }
1112}
1113
1114/**
1115 * Apply file list to action
1116 * All items in list processed as a group, if possible
1117 */
1118
1119VOID MassAction(VOID * args)
1120{
1121 WORKER *wk = (WORKER *) args;
1122 HAB hab2;
1123 HMQ hmq2;
1124 CHAR **files = NULL;
1125 CHAR *p, *pp;
1126 UINT numfiles = 0, numalloc = 0;
1127
1128
1129 if (wk) {
1130# ifdef FORTIFY
1131 // Fortify_BecomeOwner(wk);
1132 Fortify_EnterScope();
1133# endif
1134 if (wk->li && wk->li->list && wk->li->list[0]) {
1135 hab2 = WinInitialize(0);
1136 if (hab2) {
1137 hmq2 = WinCreateMsgQueue(hab2, 0);
1138 if (hmq2) {
1139 WinCancelShutdown(hmq2, TRUE);
1140 IncrThreadUsage();
1141 DosError(FERR_DISABLEHARDERR);
1142 if (IsRoot(wk->li->list[0]) || !IsFile(wk->li->list[0])) {
1143 if (wk->li->type == IDM_VIEW)
1144 wk->li->type = IDM_INFO;
1145 if (wk->li->type == IDM_EDIT)
1146 wk->li->type = IDM_EAS;
1147 }
1148 switch (wk->li->type) {
1149 case IDM_INFO:
1150 if (WinDlgBox(HWND_DESKTOP,
1151 wk->hwndFrame,
1152 FileInfoProc,
1153 FM3ModHandle, FLE_FRAME, (PVOID) wk->li->list) != 2)
1154 {
1155 break;
1156 }
1157 // else intentional fallthru
1158 case IDM_UPDATE:
1159 Broadcast(hab2,
1160 wk->hwndCnr,
1161 UM_UPDATERECORDLIST, MPFROMP(wk->li->list), MPVOID);
1162 break;
1163
1164 case IDM_EAS:
1165 if (WinDlgBox(HWND_DESKTOP,
1166 wk->hwndFrame,
1167 DisplayEAsProc,
1168 FM3ModHandle, EA_FRAME, (PVOID) wk->li->list))
1169 Broadcast(hab2,
1170 wk->hwndCnr,
1171 UM_UPDATERECORDLIST, MPFROMP(wk->li->list), MPVOID);
1172 break;
1173
1174 case IDM_DOITYOURSELF:
1175 ExecOnList(wk->hwndFrame,
1176 "%a",
1177 WINDOWED | SEPARATE | PROMPT, NULL,
1178 NULL, wk->li->list, GetPString(IDS_DOITYOURSELFTEXT),
1179 pszSrcFile, __LINE__);
1180 break;
1181
1182 case IDM_MCIPLAY:
1183 {
1184 UINT x;
1185 UINT MaxFM2playStrLen = 24;
1186 ULONG total;
1187 CHAR fbuf[CCHMAXPATH];
1188
1189 if (DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT |
1190 SEARCH_CUR_DIRECTORY,
1191 (CHAR *) PCSZ_PATH, (CHAR *) PCSZ_FM2PLAYEXE, (PBYTE)fbuf, CCHMAXPATH - 1))
1192 total += MaxFM2playStrLen;
1193 else
1194 total = strlen(fbuf);
1195 for (x = 0; wk->li->list[x]; x++)
1196 total += (strlen(wk->li->list[x]) + 1 +
1197 (needs_quoting(wk->li->list[x]) * 2));
1198 if (total > 1000) {
1199
1200 FILE *fp;
1201 CHAR szTempFile[CCHMAXPATH];
1202 CHAR *modew = "w";
1203
1204 if (pTmpDir && !IsValidDir(pTmpDir))
1205 DosCreateDir(pTmpDir, 0);
1206 BldFullPathName(szTempFile, pTmpDir, PCSZ_FM2PLAYTEMP);
1207 fp = xfopen(szTempFile, modew, pszSrcFile, __LINE__, FALSE);
1208 if (fp) {
1209 fprintf(fp, "%s", ";AV/2-built FM2Play listfile\n");
1210 for (x = 0; wk->li->list[x]; x++)
1211 fprintf(fp, "%s\n", wk->li->list[x]);
1212 fprintf(fp, ";end\n");
1213 fclose(fp);
1214 strrev(szTempFile);
1215 strcat(szTempFile, "@/");
1216 strrev(szTempFile);
1217 RunFM2Util(PCSZ_FM2PLAYEXE, szTempFile);
1218 }
1219 }
1220 }
1221 // intentional fallthru
1222 case IDM_FAKEEXTRACT:
1223 case IDM_FAKEEXTRACTM:
1224 if (wk->li->type == IDM_MCIPLAY ||
1225 (*wk->li->arcname && wk->li->info &&
1226 wk->li->info->extract && *wk->li->targetpath)) {
1227
1228 CHAR szBuffer[1025];
1229 CHAR fbuf[CCHMAXPATH];
1230 UINT x;
1231
1232 if (wk->li->type == IDM_FAKEEXTRACT ||
1233 wk->li->type == IDM_FAKEEXTRACTM) {
1234 strcpy(szBuffer,
1235 (wk->li->info->exwdirs) ?
1236 wk->li->info->exwdirs : wk->li->info->extract);
1237 strcat(szBuffer, " ");
1238 BldQuotedFileName(szBuffer + strlen(szBuffer), wk->li->arcname);
1239 }
1240 else {
1241 if (DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT |
1242 SEARCH_CUR_DIRECTORY,
1243 (CHAR *) PCSZ_PATH, (CHAR *) PCSZ_FM2PLAYEXE, (PBYTE)fbuf, CCHMAXPATH - 1))
1244 strcpy(szBuffer, "UTILS\\FM2PLAY.EXE");
1245 else
1246 strcpy(szBuffer, PCSZ_FM2PLAYEXE);
1247 }
1248 p = &szBuffer[strlen(szBuffer)];
1249 strcat(szBuffer, " ");
1250 x = 0;
1251 while (wk->li->list[x]) {
1252 pp = wk->li->list[x];
1253 while (*pp) {
1254 if (*pp == '/')
1255 *pp = '\\';
1256 pp++;
1257 }
1258 BldQuotedFileName(szBuffer + strlen(szBuffer), wk->li->list[x]);
1259 x++;
1260 if (!wk->li->list[x] || strlen(szBuffer) +
1261 strlen(wk->li->list[x]) + 5 > 1024) {
1262 runemf2(SEPARATE | WINDOWED | BACKGROUND | MINIMIZED | WAIT,
1263 HWND_DESKTOP, pszSrcFile, __LINE__,
1264 (wk->li->type == IDM_FAKEEXTRACT ||
1265 wk->li->type == IDM_FAKEEXTRACTM) ?
1266 wk->li->targetpath : NULL,
1267 NULL,
1268 "%s", szBuffer);
1269 DosSleep(1);
1270 *p = 0;
1271 }
1272 strcat(szBuffer, " ");
1273 }
1274 if (wk->li->type == IDM_MCIPLAY)
1275 break;
1276 strcpy(szBuffer, wk->li->targetpath);
1277 AddBackslashToPath(wk->li->targetpath);
1278 //if (wk->li->targetpath[strlen(wk->li->targetpath) - 1] != '\\')
1279 // strcat(szBuffer, "\\");
1280 p = szBuffer + strlen(szBuffer);
1281 for (x = 0; wk->li->list[x]; x++) {
1282 strcpy(p, wk->li->list[x]);
1283 free(wk->li->list[x]);
1284 wk->li->list[x] = xstrdup(szBuffer, pszSrcFile, __LINE__);
1285 }
1286 if (wk->li->list[0])
1287 Broadcast(hab2,
1288 wk->hwndCnr,
1289 UM_UPDATERECORDLIST, MPFROMP(wk->li->list), MPVOID);
1290 }
1291 break;
1292
1293 case IDM_SETICON:
1294 if (*wk->li->targetpath) {
1295
1296 ICONINFO ici;
1297
1298 memset(&ici, 0, sizeof(ICONINFO));
1299 ici.cb = sizeof(ICONINFO);
1300 ici.fFormat = ICON_FILE;
1301 ici.pszFileName = wk->li->list[0];
1302 if (!WinSetFileIcon((PSZ) wk->li->targetpath,
1303 (PICONINFO) & ici)) {
1304 ici.fFormat = ICON_CLEAR;
1305 WinSetFileIcon((PSZ) wk->li->targetpath, (PICONINFO) & ici);
1306 }
1307 Broadcast(hab2,
1308 wk->hwndCnr,
1309 UM_UPDATERECORD, MPFROMP(wk->li->targetpath), MPVOID);
1310 }
1311 break;
1312
1313 case IDM_APPENDTOCLIP:
1314 case IDM_SAVETOCLIP:
1315 case IDM_SAVETOCLIPFILENAME:
1316 case IDM_APPENDTOCLIPFILENAME:
1317 ListToClipboardHab(hab2,
1318 wk->li->list,
1319 wk->li->type);
1320 break;
1321
1322 case IDM_ARCHIVEM:
1323 case IDM_ARCHIVE:
1324 {
1325 DIRCNRDATA ad;
1326 CHAR szBuffer[1025];
1327 ARC_TYPE *info = NULL;
1328 char *pch;
1329 UINT x;
1330
1331 memset(&ad, 0, sizeof(DIRCNRDATA));
1332 strcpy(ad.arcname, wk->li->targetpath);
1333 if (*wk->li->targetpath && IsFile(wk->li->targetpath) > 0) {
1334 info = find_type(wk->li->targetpath, NULL);
1335 ad.namecanchange = 0;
1336 }
1337 else {
1338 if (*wk->li->targetpath && !IsFile(wk->li->targetpath))
1339 AddBackslashToPath(wk->li->targetpath);
1340 ad.namecanchange = 1;
1341 }
1342 strcpy(ad.arcname, wk->li->targetpath);
1343 if (wk->li->type == IDM_ARCHIVEM)
1344 ad.fmoving = TRUE;
1345 if (!info) {
1346 ad.info = arcsighead; // Hide dups
1347 if (!WinDlgBox(HWND_DESKTOP,
1348 wk->hwndFrame,
1349 SBoxDlgProc,
1350 FM3ModHandle,
1351 ASEL_FRAME, (PVOID) & ad.info) || !ad.info) {
1352 break; // we blew it
1353 }
1354 }
1355 else
1356 ad.info = info;
1357 if (!ad.info || (!ad.info->create &&
1358 !ad.info->move &&
1359 !ad.info->createwdirs &&
1360 !ad.info->movewdirs &&
1361 !ad.info->createrecurse))
1362 break;
1363 if (!*wk->li->targetpath && *wk->directory) {
1364 strcpy(ad.arcname, wk->directory);
1365 AddBackslashToPath(ad.arcname);
1366 }
1367 if (!WinDlgBox(HWND_DESKTOP, wk->hwndFrame, ArchiveDlgProc, FM3ModHandle,
1368 ARCH_FRAME, (PVOID) & ad) || !*ad.arcname || !*ad.command) // we blew it
1369 break;
1370 // Provide extension so containers work
1371 pch = strrchr(ad.arcname, '\\');
1372 if (pch)
1373 pch = strrchr(pch, '.');
1374 else
1375 pch = strrchr(ad.arcname, '.');
1376 if (!pch && ad.info->ext) {
1377 strcat(ad.arcname, ".");
1378 strcat(ad.arcname, ad.info->ext);
1379 }
1380 // build the sucker
1381 strcpy(szBuffer, ad.command);
1382 strcat(szBuffer, " ");
1383 BldQuotedFileName(szBuffer + strlen(szBuffer), ad.arcname);
1384 p = &szBuffer[strlen(szBuffer)];
1385 if (ad.mask.szMask) {
1386 strcat(szBuffer, " ");
1387 strcat(szBuffer, ad.mask.szMask);
1388 }
1389 strcat(szBuffer, " ");
1390 x = 0;
1391 while (wk->li->list[x]) {
1392 FILESTATUS3 fsa;
1393 memset(&fsa, 0, sizeof(FILESTATUS3));
1394 DosError(FERR_DISABLEHARDERR);
1395 DosQueryPathInfo(wk->li->list[x],
1396 FIL_STANDARD,
1397 &fsa, (ULONG) sizeof(FILESTATUS3));
1398 if (fsa.attrFile & FILE_DIRECTORY) {
1399 BldQuotedFullPathName(szBuffer + strlen(szBuffer), wk->li->list[x], "*");
1400 }
1401 else
1402 BldQuotedFileName(szBuffer + strlen(szBuffer), wk->li->list[x]);
1403 x++;
1404 if (!wk->li->list[x] ||
1405 strlen(szBuffer) + strlen(wk->li->list[x]) + 5 > 1024) {
1406 runemf2(SEPARATE | WINDOWED | WAIT |
1407 (fArcStuffVisible ? 0 : (BACKGROUND | MINIMIZED)),
1408 HWND_DESKTOP, pszSrcFile, __LINE__, NULL, NULL,
1409 "%s", szBuffer);
1410 DosSleep(1);
1411 *p = 0;
1412 }
1413 strcat(szBuffer, " ");
1414 }
1415 Broadcast(hab2,
1416 wk->hwndCnr,
1417 UM_UPDATERECORDLIST, MPFROMP(wk->li->list), MPVOID);
1418 Broadcast(hab2,
1419 wk->hwndCnr,
1420 UM_UPDATERECORD, MPFROMP(ad.arcname), MPVOID);
1421 }
1422 break;
1423
1424 case IDM_VIEW:
1425 if (!TestBinary(wk->li->list[0])) {
1426 wk->li->type = IDM_VIEWTEXT;
1427 goto SkipViewing;
1428 }
1429 else
1430 wk->li->type = IDM_VIEWBINARY;
1431 // intentional fallthru
1432 case IDM_VIEWBINARY:
1433 if (*binview) {
1434 ExecOnList((HWND) 0,
1435 binview,
1436 WINDOWED | SEPARATE, NULL, NULL, wk->li->list, NULL,
1437 pszSrcFile, __LINE__);
1438 break;
1439 }
1440 // else intentional fallthru
1441 case IDM_VIEWTEXT:
1442 SkipViewing:
1443 if (*viewer)
1444 ExecOnList((HWND) 0, viewer,
1445 WINDOWED | SEPARATE |
1446 ((fViewChild) ? CHILD : 0),
1447 NULL, NULL, wk->li->list, NULL,
1448 pszSrcFile, __LINE__);
1449 else {
1450
1451 CHAR *temp;
1452 UINT x;
1453 ULONG viewtype;
1454
1455 viewtype = (wk->li->type == IDM_VIEWTEXT) ? 8 :
1456 (wk->li->type == IDM_VIEWBINARY) ? 16 : 0;
1457 for (x = 0; wk->li->list[x]; x++) {
1458 temp = xstrdup(wk->li->list[x], pszSrcFile, __LINE__);
1459 if (temp && WinIsWindow(hab2, wk->hwndCnr)) {
1460 if (!PostMsg(wk->hwndCnr,
1461 UM_LOADFILE,
1462 MPFROMLONG(5 + viewtype), MPFROMP(temp)))
1463 free(temp);
1464 }
1465 DosSleep(1);
1466 }
1467 }
1468 break;
1469
1470 case IDM_EDIT:
1471 if (!TestBinary(wk->li->list[0])) {
1472 wk->li->type = IDM_EDITTEXT;
1473 goto SkipEditing;
1474 }
1475 else
1476 wk->li->type = IDM_EDITBINARY;
1477 // intentional fallthru
1478 case IDM_EDITBINARY:
1479 if (*bined) {
1480 ExecOnList((HWND) 0,
1481 bined,
1482 WINDOWED | SEPARATE, NULL, NULL, wk->li->list, NULL,
1483 pszSrcFile, __LINE__);
1484 break;
1485 }
1486 // else intentional fallthru
1487 case IDM_EDITTEXT:
1488 SkipEditing:
1489 if (*editor)
1490 ExecOnList((HWND) 0,
1491 editor,
1492 WINDOWED | SEPARATE, NULL, NULL, wk->li->list, NULL,
1493 pszSrcFile, __LINE__);
1494 else {
1495
1496 CHAR *temp;
1497 UINT x;
1498 ULONG viewtype;
1499
1500 viewtype = (wk->li->type == IDM_EDITTEXT) ? 8 :
1501 (wk->li->type == IDM_EDITBINARY) ? 16 : 0;
1502 for (x = 0; wk->li->list[x]; x++) {
1503 temp = xstrdup(wk->li->list[x], pszSrcFile, __LINE__);
1504 if (temp && WinIsWindow(hab2, wk->hwndCnr)) {
1505 if (!PostMsg(wk->hwndCnr,
1506 UM_LOADFILE,
1507 MPFROMLONG(4 + viewtype), MPFROMP(temp)))
1508 free(temp);
1509 }
1510 DosSleep(1);
1511 }
1512 }
1513 break;
1514
1515 case IDM_SHADOW2:
1516 case IDM_OBJECT:
1517 case IDM_SHADOW:
1518 {
1519 CHAR objectpath[CCHMAXPATH];
1520 APIRET rc;
1521
1522 if (!*wk->li->targetpath || IsFile(wk->li->targetpath)) {
1523 GetDesktopName(objectpath, sizeof(objectpath));
1524 rc = WinDlgBox(HWND_DESKTOP,
1525 wk->hwndFrame,
1526 ObjCnrDlgProc,
1527 FM3ModHandle,
1528 OBJCNR_FRAME, MPFROMP(objectpath));
1529 if (rc) {
1530 if (rc > 1)
1531 strcpy(objectpath, "<WP_DESKTOP>");
1532 }
1533 else
1534 break;
1535 }
1536 else
1537 strcpy(objectpath, wk->li->targetpath);
1538 AddNote(GetPString(IDS_MAKINGOBJSTEXT));
1539 MakeShadows(wk->hwndFrame,
1540 wk->li->list,
1541 (wk->li->type == IDM_SHADOW) +
1542 (wk->li->type == IDM_SHADOW2) * 2,
1543 objectpath, NULL);
1544 AddNote(GetPString(IDS_MADEOBJSTEXT));
1545 }
1546 break;
1547
1548 case IDM_PRINT:
1549 if (WinDlgBox(HWND_DESKTOP,
1550 wk->hwndFrame,
1551 PrintDlgProc,
1552 FM3ModHandle, PRN_FRAME, MPFROMP(wk->li))) {
1553 if (wk->li && wk->li->list && wk->li->list[0]) {
1554 strcpy(wk->li->targetpath, printer);
1555 if (xbeginthread(PrintListThread,
1556 65536,
1557 wk->li,
1558 pszSrcFile,
1559 __LINE__) != -1)
1560 {
1561 wk->li = NULL; // prevent LISTINFO li from being freed here
1562 }
1563 }
1564 }
1565 break;
1566
1567 case IDM_ATTRS:
1568 if (WinDlgBox(HWND_DESKTOP,
1569 wk->hwndFrame,
1570 AttrListDlgProc,
1571 FM3ModHandle, ATR_FRAME, MPFROMP(wk->li))) {
1572 if (wk->li && wk->li->list && wk->li->list[0])
1573 Broadcast(hab2,
1574 wk->hwndCnr,
1575 UM_UPDATERECORDLIST, MPFROMP(wk->li->list), MPVOID);
1576 }
1577 break;
1578
1579 case IDM_PERMDELETE:
1580 case IDM_DELETE:
1581 {
1582 CHECKLIST cl;
1583 INT isdir = 0, sysdir = 0, ro = 0, hs = 0;
1584 UINT x;
1585 FILESTATUS3 fsa;
1586 CHAR prompt[CCHMAXPATH * 3];
1587 APIRET error = 0;
1588 HOBJECT hObjectdest, hObjectofObject;
1589 BYTE G_abSupportedDrives[24] = {0};
1590 ULONG cbSupportedDrives = sizeof(G_abSupportedDrives);
1591
1592 for (x = 0; wk->li->list[x]; x++) {
1593 if (IsRoot(wk->li->list[x])) {
1594 wk->li->list = RemoveFromList(wk->li->list,
1595 wk->li->list[x]);
1596 if (!wk->li->list)
1597 break;
1598 x--;
1599 continue;
1600 }
1601 DosError(FERR_DISABLEHARDERR);
1602 if (DosQueryPathInfo(wk->li->list[x],
1603 FIL_STANDARD, &fsa,
1604 (ULONG) sizeof(FILESTATUS3))) {
1605 wk->li->list = RemoveFromList(wk->li->list,
1606 wk->li->list[x]);
1607 if (!wk->li->list)
1608 break;
1609 x--;
1610 continue;
1611 }
1612 if (fsa.attrFile & FILE_DIRECTORY) {
1613 isdir++;
1614 if (stristr(wk->li->list[x], ":\\OS2\\") ||
1615 !stricmp(wk->li->list[x] + 1, ":\\OS2"))
1616 sysdir++;
1617 }
1618 else {
1619 if (fsa.attrFile & (FILE_HIDDEN | FILE_SYSTEM))
1620 hs++;
1621 if (fsa.attrFile & FILE_READONLY)
1622 ro++;
1623 }
1624 }
1625 if (!wk->li->list)
1626 break;
1627 if (fConfirmDelete || isdir || hs || ro) {
1628 memset(&cl, 0, sizeof(cl));
1629 cl.size = sizeof(cl);
1630 cl.list = wk->li->list;
1631 cl.prompt = prompt;
1632 cl.flags |= CHECK_FILES;
1633 cl.cmd = wk->li->type;
1634 sprintf(prompt,
1635 GetPString(IDS_DELPROMPT1TEXT),
1636 (wk->li->type == IDM_DELETE) ?
1637 NullStr :
1638 GetPString(IDS_PERMANENTLYTEXT),
1639 &"s"[wk->li->list[1] == NULL]);
1640 if (isdir) {
1641 sprintf(&prompt[strlen(prompt)],
1642 GetPString(IDS_DELPROMPT2TEXT),
1643 isdir,
1644 (isdir > 1) ?
1645 GetPString(IDS_ARETEXT) :
1646 GetPString(IDS_ISTEXT),
1647 (isdir == 1) ?
1648 GetPString(IDS_ATEXT) :
1649 NullStr,
1650 (isdir > 1) ?
1651 GetPString(IDS_IESTEXT) : GetPString(IDS_YTEXT));
1652 if (sysdir)
1653 sprintf(&prompt[strlen(prompt)],
1654 GetPString(IDS_DELPROMPT3TEXT),
1655 sysdir,
1656 (sysdir == 1) ?
1657 GetPString(IDS_YTEXT) : GetPString(IDS_IESTEXT));
1658 }
1659 if (ro)
1660 sprintf(&prompt[strlen(prompt)],
1661 GetPString(IDS_DELPROMPT4TEXT),
1662 ro,
1663 &"s"[ro == 1],
1664 (ro > 1) ?
1665 GetPString(IDS_ARETEXT) : GetPString(IDS_ISTEXT));
1666 if (hs)
1667 sprintf(&prompt[strlen(prompt)],
1668 GetPString(IDS_DELPROMPT5TEXT),
1669 hs,
1670 &"s"[hs == 1],
1671 (hs > 1) ?
1672 GetPString(IDS_ARETEXT) : GetPString(IDS_ISTEXT));
1673 if ((ro || hs || sysdir) && !fAlertBeepOff)
1674 DosBeep(300, 100); // Wake up user
1675 strcat(prompt, GetPString(IDS_DELPROMPT6TEXT));
1676 error = WinDlgBox(HWND_DESKTOP,
1677 wk->hwndFrame,
1678 CheckListProc,
1679 FM3ModHandle, CHECK_FRAME, MPFROMP(&cl));
1680 if (!error || error == 65535)
1681 break;
1682 wk->li->list = cl.list;
1683 if (!wk->li->list || !wk->li->list[0])
1684 break;
1685 }
1686 if (fVerify && driveflags[toupper(*wk->li->list[0]) - 'A'] & DRIVE_WRITEVERIFYOFF)
1687 DosSetVerify(FALSE);
1688 DosRequestMutexSem(hmtxFM2Delete, SEM_INDEFINITE_WAIT); // Prevent race 12-3-08 GKY
1689 for (x = 0; wk->li->list[x]; x++) {
1690 fsa.attrFile = 0;
1691 DosError(FERR_DISABLEHARDERR);
1692 DosQueryPathInfo(wk->li->list[x],
1693 FIL_STANDARD,
1694 &fsa, (ULONG) sizeof(FILESTATUS3));
1695 if (fsa.attrFile & FILE_DIRECTORY) {
1696 error = (APIRET) wipeallf("%s%s*",
1697 wk->li->list[x],
1698 (*wk->li->list[x] &&
1699 wk->li->
1700 list[x][strlen(wk->li->list[x]) - 1]
1701 != '\\') ? PCSZ_BACKSLASH : NullStr);
1702 DosError(FERR_DISABLEHARDERR);
1703 if (!error)
1704 error = DosDeleteDir(wk->li->list[x]);
1705 else
1706 DosDeleteDir(wk->li->list[x]);
1707 }
1708 else {
1709
1710 DosError(FERR_DISABLEHARDERR);
1711 if (wk->li->type == IDM_DELETE) {
1712 hObjectdest = WinQueryObject("<XWP_TRASHCAN>");
1713 PrfQueryProfileData(HINI_USER,
1714 "XWorkplace",
1715 "TrashCan::Drives",
1716 G_abSupportedDrives,
1717 &cbSupportedDrives);
1718 if (hObjectdest != NULLHANDLE && fTrashCan &&
1719 (G_abSupportedDrives ? (G_abSupportedDrives[toupper(*wk->li->list[x]) - 'C'] &
1720 1):(!(driveflags[toupper(*wk->li->list[x]) - 'A'] &
1721 (DRIVE_REMOVABLE | DRIVE_IGNORE |
1722 DRIVE_REMOTE | DRIVE_VIRTUAL |
1723 DRIVE_NOTWRITEABLE | DRIVE_RAMDISK))))) {
1724 hObjectofObject = WinQueryObject(wk->li->list[x]);
1725 error = WinMoveObject(hObjectofObject, hObjectdest, 0);
1726 }
1727 else {
1728 error = DosDelete(wk->li->list[x]);
1729 }
1730 }
1731 else {
1732 error = DosForceDelete(wk->li->list[x]); ;
1733 }
1734 if (error) {
1735 DosError(FERR_DISABLEHARDERR);
1736 make_deleteable(wk->li->list[x], error);
1737 if (wk->li->type == IDM_DELETE){
1738 hObjectdest = WinQueryObject("<XWP_TRASHCAN>");
1739 PrfQueryProfileData(HINI_USER,
1740 "XWorkplace",
1741 "TrashCan::Drives",
1742 G_abSupportedDrives,
1743 &cbSupportedDrives);
1744 if (hObjectdest != NULLHANDLE && fTrashCan &&
1745 (G_abSupportedDrives ? (G_abSupportedDrives[toupper(*wk->li->list[x]) - 'C'] &
1746 1):(!(driveflags[toupper(*wk->li->list[x]) - 'A'] &
1747 (DRIVE_REMOVABLE | DRIVE_IGNORE |
1748 DRIVE_REMOTE | DRIVE_VIRTUAL |
1749 DRIVE_NOTWRITEABLE | DRIVE_RAMDISK))))) {
1750 hObjectofObject = WinQueryObject(wk->li->list[x]);
1751 error = WinMoveObject(hObjectofObject, hObjectdest, 0);
1752 }
1753 else {
1754 error = DosDelete(wk->li->list[x]);
1755 }
1756 }
1757 else {
1758 error = DosForceDelete(wk->li->list[x]);
1759 }
1760 }
1761 DosReleaseMutexSem(hmtxFM2Delete);
1762 }
1763 if (error) {
1764 if (LogFileHandle)
1765 fprintf(LogFileHandle,
1766 GetPString(IDS_DELETEFAILED1TEXT),
1767 wk->li->list[x], error);
1768 if (Dos_Error(MB_ENTERCANCEL,
1769 error,
1770 wk->hwndFrame,
1771 pszSrcFile,
1772 __LINE__,
1773 GetPString(IDS_DELETEFAILED2TEXT),
1774 wk->li->list[x]) == MBID_CANCEL) {
1775 DosSetVerify(fVerify);
1776 break;
1777 }
1778 }
1779 else {
1780 if (LogFileHandle)
1781 fprintf(LogFileHandle,
1782 GetPString(IDS_DELETEDTEXT), wk->li->list[x]);
1783 sprintf(prompt,
1784 GetPString(IDS_DELETEDTEXT), wk->li->list[x]);
1785 AddNote(prompt);
1786 }
1787 if (//fSyncUpdates ||
1788 AddToList(wk->li->list[x], &files, &numfiles, &numalloc)) {
1789 Broadcast(hab2,
1790 wk->hwndCnr,
1791 UM_UPDATERECORD,
1792 MPFROMP(wk->li->list[x]), MPVOID);
1793 }
1794 } // for
1795 }
1796 if (fVerify)
1797 DosSetVerify(fVerify);
1798 break;
1799 } // switch
1800 if (files) {
1801 Broadcast(hab2,
1802 wk->hwndCnr,
1803 UM_UPDATERECORDLIST, MPFROMP(files), MPVOID);
1804 FreeList(files);
1805 }
1806 if (WinIsWindow(hab2, wk->hwndCnr))
1807 PostMsg(wk->hwndCnr, UM_RESCAN, MPVOID, MPVOID);
1808
1809 WinDestroyMsgQueue(hmq2);
1810 }
1811 DecrThreadUsage();
1812 WinTerminate(hab2);
1813 }
1814 }
1815 FreeListInfo(wk->li);
1816 free(wk);
1817# ifdef FORTIFY
1818 Fortify_LeaveScope();
1819# endif
1820 DosPostEventSem(CompactSem);
1821 }
1822}
1823
1824#pragma alloc_text(MASSACTION,MassAction)
1825#pragma alloc_text(ACTION,Action)
1826#pragma alloc_text(UNDO,FreeUndo,Undo)
Note: See TracBrowser for help on using the repository browser.