source: trunk/dll/worker.c@ 1710

Last change on this file since 1710 was 1710, checked in by Gregg Young, 12 years ago

Actually commit the fix for suppressing the readonly warning on temp archive files. Ticket 497

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 50.3 KB
Line 
1
2/***********************************************************************
3
4 $Id: worker.c 1710 2014-02-09 20:07:48Z gyoung $
5
6 Worker thread
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2001, 2014 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 10 Mar 13 GKY Improvrd readonly check on delete to allow cancel and don't ask again options
56 Added saymsg2 for this purpose
57
58***********************************************************************/
59
60#include <stdlib.h>
61#include <string.h>
62#include <ctype.h>
63#include <share.h>
64#include <process.h> // _beginthread // 10 Dec 08 SHL
65#include <time.h>
66
67#define INCL_DOS
68#define INCL_DOSERRORS
69// #define INCL_WINPROGRAMLIST // 13 Jul 09 SHL dropped
70// #define INCL_WINHELP // 13 Jul 09 SHL dropped
71#define INCL_LONGLONG
72#define INCL_WINPOINTERS // WinSetFileIcon
73// #define INCL_WINWORKPLACE // 13 Jul 09 SHL dropped
74#define INCL_WINSHELLDATA // PrfQueryProfileData
75
76#include "fm3dll.h"
77#include "fm3dll2.h" // #define's for UM_*, control id's, etc.
78#include "mainwnd2.h" // Data declaration(s)
79#include "arccnrs.h" // Data declaration(s)
80#include "init.h" // Data declaration(s)
81#include "defview.h" // Data declaration(s)
82#include "newview.h" // Data declarations
83#include "fm3dlg.h"
84#include "fm3str.h"
85#include "comp.h" // FCOMPARE
86#include "pathutil.h" // BldQuotedFileName
87#include "makelist.h" // AddToList
88#include "errutil.h" // Dos_Error...
89#include "strutil.h" // GetPString
90#include "notebook.h" // External viewers
91#include "worker.h" // Action
92#include "notify.h" // AddNote
93#include "copyf.h" // AdjustWildcardName, make_deleteable
94#include "attribs.h" // AttrListDlgProc
95#include "chklist.h" // CheckListProc
96#include "info.h" // DrvInfoProc
97#include "extract.h" // ExtractDlgProc
98#include "info.h" // FileInfoProc
99#include "valid.h" // GetDesktopName, IsNewer
100#include "saveclip.h" // ListToClipboardHab
101#include "shadow.h" // MakeShadows
102#include "mkdir.h" // MassMkdir
103#include "uudecode.h" // MergeDlgProc
104#include "objcnr.h" // ObjCnrDlgProc
105#include "printer.h" // PrintDlgProc, PrintListThread
106#include "rename.h" // RenameProc
107#include "srchpath.h" // RunFM2Util
108#include "mainwnd.h" // TopWindowName
109#include "uudecode.h" // UUD
110#include "walkem.h" // WalkCopyDlgProc, WalkDlgProc, WalkMoveDlgProc
111#include "archive.h" // ArchiveDlgProc
112#include "misc.h" // Broadcast
113#include "common.h" // DecrThreadUsage, IncrThreadUsage
114#include "eas.h" // DisplayEAsProc
115#include "systemf.h" // ExecOnList
116#include "avl.h" // SBoxDlgProc
117#include "subj.h" // Subject
118#include "stristr.h" // stristr
119#include "wrappers.h" // xfopen
120#include "fortify.h"
121#include "excputil.h" // 06 May 08 SHL added
122
123// Data definitions
124#pragma data_seg(GLOBAL2)
125FILE *LogFileHandle;
126BOOL fUnlock;
127
128#pragma data_seg(DATA2)
129
130static PSZ pszSrcFile = __FILE__;
131
132#ifdef UNDO
133
134static VOID LINFO undo;
135
136VOID FreeUndo(VOID)
137{
138 if (undo->list)
139 FreeList(undo->list);
140 memset(&undo, 0, sizeof(undo));
141}
142
143VOID Undo(HWND hwndCnr, HWND hwndFrame, HWND hwndClient, HWND hwndParent)
144{
145 LISTINFO *li;
146 WORKER *wk;
147
148 if (undo->type && undo->list && undo->list[0]) {
149 switch (undo->type) {
150 case IDM_MOVE:
151 case IDM_COPY:
152 case IDM_EXTRACT:
153 {
154# ifdef FORTIFY
155 Fortify_EnterScope();
156# endif
157 li = xmallocz(sizeof(LISTINFO), pszSrcFile, __LINE__);
158 if (li) {
159 wk = xmallocz(sizeof(WORKER), pszSrcFile, __LINE__);
160 if (wk) {
161 wk->size = sizeof(WORKER);
162 wk->hwndCnr = hwndCnr;
163 wk->hwndParent = hwndParent;
164 wk->hwndFrame = hwndFrame;
165 wk->hwndClient = hwndClient;
166 wk->li = li;
167 *wk->li = *undo;
168 switch (undo->type) {
169 case IDM_COPY:
170 case IDM_EXTRACT:
171 li->type = IDM_PERMDELETE;
172 break;
173 }
174 if (xbeginthread(MassAction,
175 122880,
176 wk,
177 pszSrcFile,
178 __LINE__) == -1)
179 {
180 FreeListInfo(wk->li);
181 free(wk);
182# ifdef FORTIFY
183 Fortify_LeaveScope();
184# endif
185 }
186 }
187 else
188 FreeListInfo(li);
189 }
190 }
191 break;
192 } // switch
193 }
194 FreeUndo();
195# ifdef FORTIFY
196 Fortify_LeaveScope();
197# endif
198}
199
200#endif // defined(UNDO)
201
202/**
203 * Apply action to file list
204 * Action repeated for each item in list
205 */
206
207VOID Action(VOID * args)
208{
209 WORKER *wk = (WORKER *)args;
210 HAB hab2;
211 HMQ hmq2;
212 CHAR **files = NULL;
213 INT plen = 0;
214 CHAR *p, *pp;
215 CHAR szQuotedDirName[CCHMAXPATH];
216 CHAR szQuotedFileName[CCHMAXPATH];
217
218
219 if (wk) {
220# ifdef FORTIFY
221 Fortify_EnterScope();
222# endif
223 if (wk->li && wk->li->list && wk->li->list[0]) {
224 hab2 = WinInitialize(0);
225 if (hab2) {
226 hmq2 = WinCreateMsgQueue(hab2, 0);
227 if (hmq2) {
228 CHAR message[(CCHMAXPATH * 2) + 80], wildname[CCHMAXPATH];
229 UINT x;
230 BOOL dontask = FALSE, wildcarding = FALSE, overold =
231 FALSE, overnew = FALSE, noreadonlywarn = FALSE, usedtarget;
232
233 WinCancelShutdown(hmq2, TRUE);
234 IncrThreadUsage();
235 *wildname = 0;
236 // Do action specific preprocessing
237 switch (wk->li->type) {
238 case IDM_MERGE:
239 if (wk->li->type == IDM_MERGE) {
240 if (TestBinary(wk->li->list[0]))
241 wk->li->type = IDM_MERGEBINARY;
242 else
243 wk->li->type = IDM_MERGETEXT;
244 }
245 strcpy(wk->li->targetpath, wk->li->list[0]);
246 p = strrchr(wk->li->targetpath, '\\');
247 if (p) {
248 p++;
249 *p = 0;
250 }
251 else
252 strcat(wk->li->targetpath, PCSZ_BACKSLASH);
253 sprintf(wk->li->targetpath + strlen(wk->li->targetpath),
254 "MERGE.%03x", (clock() & 4095L));
255 if (!WinDlgBox(HWND_DESKTOP,
256 wk->hwndFrame,
257 MergeDlgProc, FM3ModHandle, MRG_FRAME, (PVOID) wk))
258 goto Abort;
259 if (!wk->li->type ||
260 !*wk->li->targetpath || !wk->li->list || !wk->li->list[0])
261 goto Abort;
262 if (IsFile(wk->li->targetpath) != 1 && !wk->li->list[1]) {
263 saymsg(MB_CANCEL | MB_ICONEXCLAMATION,
264 wk->hwndFrame,
265 GetPString(IDS_AHEMTEXT),
266 GetPString(IDS_SILLYMERGETEXT));
267 goto Abort;
268 }
269 break;
270 case IDM_WILDMOVE:
271 wildcarding = TRUE;
272 wk->li->type = IDM_MOVE;
273 break;
274 case IDM_WILDRENAME:
275 wildcarding = TRUE;
276 wk->li->type = IDM_RENAME;
277 break;
278 case IDM_WILDCOPY:
279 wildcarding = TRUE;
280 wk->li->type = IDM_COPY;
281 break;
282 case IDM_MOVEPRESERVE:
283 {
284 CHAR preserve[CCHMAXPATH], *end;
285
286 wk->li->type = IDM_MOVE;
287 strcpy(preserve, wk->li->list[0] + 2);
288 end = strrchr(preserve, '\\');
289 if (end) {
290 end++;
291 for (x = 1; wk->li->list[x]; x++) {
292 p = preserve;
293 pp = wk->li->list[x] + 2;
294 while (p < end && toupper(*p) == toupper(*pp)) {
295 p++;
296 pp++;
297 }
298 if (*p == '\\')
299 p++;
300 if (p < end)
301 end = p;
302 }
303 *end = 0;
304 }
305 else
306 *preserve = 0;
307 plen = strlen(preserve);
308 if (plen)
309 plen += 2;
310 }
311 break;
312 case IDM_COPYPRESERVE:
313 {
314 CHAR preserve[CCHMAXPATH], *end;
315
316 wk->li->type = IDM_COPY;
317 strcpy(preserve, wk->li->list[0] + 2);
318 end = strrchr(preserve, '\\');
319 if (end) {
320 end++;
321 for (x = 1; wk->li->list[x]; x++) {
322 p = preserve;
323 pp = wk->li->list[x] + 2;
324 while (p < end && toupper(*p) == toupper(*pp)) {
325 p++;
326 pp++;
327 }
328 if (*p == '\\')
329 p++;
330 if (p < end)
331 end = p;
332 }
333 *end = 0;
334 }
335 else
336 *preserve = 0;
337 plen = strlen(preserve);
338 if (plen)
339 plen += 2;
340 }
341 break;
342 }
343 // Process each list item
344 if (wk->li && wk->li->list && wk->li->list[0]) {
345 UINT cFilesModified = 0; // Required for AddToList
346 UINT cItemsAllocated = 0; // Required for AddToList
347 UINT cItemsInList;
348 for (cItemsInList = 0; wk->li->list[cItemsInList]; cItemsInList++); // Count
349 for (x = 0; wk->li->list[x]; x++) {
350 switch (wk->li->type) {
351 case IDM_COLLECTFROMFILE:
352 if (Collector) {
353
354 CHAR *temp = xstrdup(wk->li->list[x], pszSrcFile, __LINE__);
355
356 if (temp) {
357 if (!PostMsg(Collector,
358 UM_COLLECTFROMFILE, MPFROMP(temp), MPVOID))
359 free(temp);
360 }
361 }
362 break;
363
364 case IDM_MERGEBINARY:
365 case IDM_MERGETEXT:
366 case IDM_MERGEBINARYAPPEND:
367 case IDM_MERGETEXTAPPEND:
368 {
369 FILE *in, *out;
370 CHAR *moder, *modew;
371 int c;
372
373 switch (wk->li->type) {
374 case IDM_MERGEBINARY:
375 moder = "rb";
376 modew = "wb";
377 break;
378 case IDM_MERGEBINARYAPPEND:
379 moder = "rb";
380 modew = "a+b";
381 break;
382 case IDM_MERGETEXTAPPEND:
383 moder = "r";
384 modew = "a+";
385 break;
386 default:
387 moder = "r";
388 modew = "w";
389 break;
390 }
391 in = xfsopen(wk->li->list[x], moder, SH_DENYWR, pszSrcFile, __LINE__, TRUE);
392 if (!in) {
393 if (saymsg(MB_ENTERCANCEL,
394 HWND_DESKTOP,
395 GetPString(IDS_MERGEERRORTEXT),
396 GetPString(IDS_CANTOPENINPUTTEXT),
397 wk->li->list[x]) == MBID_CANCEL)
398 goto Abort;
399 }
400 else {
401 out = xfsopen(wk->li->targetpath, modew, SH_DENYWR,
402 pszSrcFile, __LINE__, TRUE);
403 if (out) {
404 fseek(out, 0L, SEEK_END);
405 switch (wk->li->type) {
406 case IDM_MERGEBINARY:
407 wk->li->type = IDM_MERGEBINARYAPPEND;
408 break;
409 default:
410 wk->li->type = IDM_MERGETEXTAPPEND;
411 break;
412 }
413 sprintf(message,
414 GetPString(IDS_MERGINGTEXT),
415 wk->li->list[x], wk->li->targetpath);
416 AddNote(message);
417 while ((c = fgetc(in)) != EOF)
418 fputc(c, out);
419 fclose(out);
420 sprintf(message,
421 GetPString(IDS_MERGECOMPLETETEXT),
422 wk->li->list[x], wk->li->targetpath);
423 AddNote(message);
424 }
425 else {
426 saymsg(MB_CANCEL,
427 HWND_DESKTOP,
428 GetPString(IDS_MERGEERRORTEXT),
429 GetPString(IDS_CANTOPENOUTPUTTEXT),
430 wk->li->targetpath);
431 fclose(in);
432 goto Abort;
433 }
434 fclose(in);
435 }
436 }
437 break;
438
439 case IDM_UUDECODE:
440 {
441 CHAR outname[CCHMAXPATH + 2];
442
443 sprintf(message,
444 GetPString(IDS_UUDECODINGTEXT), wk->li->list[x]);
445 AddNote(message);
446 if (UUD(wk->li->list[x], outname) && *outname) {
447 sprintf(message,
448 GetPString(IDS_UUDECODECOMPLETETEXT),
449 wk->li->list[x]);
450 AddNote(message);
451 if (//fSyncUpdates ||
452 AddToList(outname, &files, &cFilesModified, &cItemsAllocated))
453 Broadcast(hab2,
454 wk->hwndCnr,
455 UM_UPDATERECORD, MPFROMP(outname), MPVOID);
456 }
457 else {
458 sprintf(message,
459 GetPString(IDS_UUDECODEABORTEDTEXT),
460 wk->li->list[x]);
461 AddNote(message);
462 }
463 }
464 break;
465
466 case IDM_UNLOCKFILE:
467 if (IsFile(wk->li->list[x]) > 0 && fUnlock) {
468 runemf2(SEPARATE | INVISIBLE | BACKGROUND | WAIT,
469 HWND_DESKTOP, pszSrcFile, __LINE__,
470 NULL, NULL, "%s %s", PCSZ_UNLOCKEXE, wk->li->list[x]);
471 }
472 break;
473
474 case IDM_VIEWARCHIVE:
475 if (IsFile(wk->li->list[x]) > 0) {
476
477 ARC_TYPE *info = NULL; // Say calling for editing - fixme to know why?
478
479 if (WinDlgBox(HWND_DESKTOP,
480 wk->hwndFrame,
481 SBoxDlgProc,
482 FM3ModHandle,
483 ASEL_FRAME, (PVOID) & info) && info) {
484 WinSendMsg(wk->hwndCnr,
485 UM_OPENWINDOWFORME,
486 MPFROMP(wk->li->list[x]), MPFROMP(info));
487 }
488 }
489 break;
490
491 case IDM_EXTRACT:
492 {
493 EXTRDATA ex;
494 BOOL maskspaces = FALSE;
495 CHAR arcname[CCHMAXPATH];
496
497 memset(&ex, 0, sizeof(EXTRDATA));
498 ex.info = find_type(wk->li->list[x], NULL);
499 if (!ex.info || (!ex.info->extract && !ex.info->exwdirs))
500 break;
501 ex.size = sizeof(EXTRDATA);
502 BldQuotedFileName(arcname, wk->li->list[x]);
503 ex.arcname = arcname;
504 if (!*ex.masks)
505 strcpy(ex.masks, "*");
506 strcpy(ex.extractdir, wk->li->targetpath);
507 if (!WinDlgBox(HWND_DESKTOP,
508 wk->hwndFrame,
509 ExtractDlgProc,
510 FM3ModHandle,
511 EXT_FRAME,
512 (PVOID) & ex) ||
513 !ex.ret ||
514 !*ex.command || !*ex.arcname || !*ex.extractdir)
515 goto Abort;
516 {
517 FILESTATUS3 fsa;
518
519 DosError(FERR_DISABLEHARDERR);
520 if (DosQueryPathInfo(ex.extractdir,
521 FIL_STANDARD,
522 &fsa,
523 (ULONG) sizeof(FILESTATUS3)) ||
524 !(fsa.attrFile & FILE_DIRECTORY))
525 goto Abort;
526 }
527 if (needs_quoting(ex.masks) && !strchr(ex.masks, '\"'))
528 maskspaces = TRUE;
529 if (!runemf2(SEPARATE | WINDOWED | WAIT |
530 fArcStuffVisible ? 0 : (BACKGROUND | MINIMIZED),
531 HWND_DESKTOP, pszSrcFile, __LINE__, ex.extractdir, NULL,
532 "%s %s %s%s%s",
533 ex.command,
534 ex.arcname,
535 maskspaces ? "\"" : NullStr,
536 *ex.masks ? ex.masks : "\"*\"",
537 maskspaces ? "\"" : NullStr) &&
538 !stricmp(ex.extractdir, wk->directory)) {
539 DosSleep(100); // wait for runemf2 to complete so rescan will actually show something
540 if (WinIsWindow((HAB) 0, wk->hwndCnr))
541 WinSendMsg(wk->hwndCnr,
542 WM_COMMAND,
543 MPFROM2SHORT(IDM_RESCAN, 0), MPVOID);
544 }
545 }
546 break;
547
548 case IDM_SUBJECT:
549 {
550 INT ret;
551
552 ret = Subject(wk->hwndFrame, wk->li->list[x]);
553 if (!ret)
554 goto Abort;
555 if (ret == 1) {
556 if (//fSyncUpdates ||
557 AddToList(wk->li->list[x],
558 &files, &cFilesModified, &cItemsAllocated))
559 Broadcast(hab2,
560 wk->hwndCnr,
561 UM_UPDATERECORD,
562 MPFROMP(wk->li->list[x]), MPVOID);
563 }
564 }
565 break;
566
567 case IDM_INFO:
568 if (IsFullName(wk->li->list[x]) &&
569 !(driveflags[toupper(*wk->li->list[x]) - 'A'] &
570 DRIVE_INVALID)) {
571 if (!IsRoot(wk->li->list[x])) {
572
573 CHAR *list[2];
574
575 list[0] = wk->li->list[x];
576 list[1] = NULL;
577 if (!WinDlgBox(HWND_DESKTOP,
578 HWND_DESKTOP,
579 FileInfoProc,
580 FM3ModHandle, FLE_FRAME, (PVOID) list)) {
581 goto Abort;
582 }
583 }
584 else {
585 if (!WinDlgBox(HWND_DESKTOP,
586 HWND_DESKTOP,
587 DrvInfoProc,
588 FM3ModHandle,
589 INFO_FRAME, (PVOID) wk->li->list[x]))
590 goto Abort;
591 }
592 }
593 break;
594
595 case IDM_OPENWINDOW:
596 if (!IsFile(wk->li->list[x]) &&
597 WinIsWindow(hab2, wk->hwndCnr))
598 WinSendMsg(wk->hwndCnr,
599 UM_OPENWINDOWFORME,
600 MPFROMP(wk->li->list[x]), MPVOID);
601 break;
602
603 case IDM_OPENICON:
604 case IDM_OPENDETAILS:
605 case IDM_OPENTREE:
606 {
607 FILESTATUS3 fsa;
608
609 DosError(FERR_DISABLEHARDERR);
610 if (DosQueryPathInfo(wk->li->list[x],
611 FIL_STANDARD,
612 &fsa,
613 (ULONG) sizeof(FILESTATUS3)) ||
614 !(fsa.attrFile & FILE_DIRECTORY))
615 break;
616 }
617 // else intentional fallthru
618 case IDM_OPENDEFAULT:
619 case IDM_OPENSETTINGS:
620 {
621 CHAR *s;
622
623 switch (wk->li->type) {
624 case IDM_OPENICON:
625 s = (PSZ) PCSZ_ICON;
626 break;
627 case IDM_OPENDETAILS:
628 s = (PSZ) Details;
629 break;
630 case IDM_OPENTREE:
631 s = (PSZ) PCSZ_TREE;
632 break;
633 case IDM_OPENSETTINGS:
634 s = (PSZ) Settings;
635 break;
636 default:
637 s = (PSZ) Default;
638 break;
639 }
640 OpenObject(wk->li->list[x], s, wk->hwndFrame);
641 }
642 break;
643
644 case IDM_WPSMOVE:
645 case IDM_WPSCOPY:
646 case IDM_MOVE:
647 case IDM_COPY:
648 case IDM_RENAME:
649 {
650
651 // Select target
652 if (!*wk->li->targetpath && (wk->li->type == IDM_MOVE ||
653 wk->li->type == IDM_COPY ||
654 wk->li->type == IDM_WPSMOVE ||
655 wk->li->type == IDM_WPSCOPY)) {
656
657 APIRET rc = 1;
658 usedtarget = FALSE;
659 if (hwndMain) {
660 if (!*targetdir)
661 TopWindowName(hwndMain,
662 wk->hwndFrame, wk->li->targetpath);
663 else {
664 strcpy(wk->li->targetpath, targetdir);
665 usedtarget = TRUE;
666 }
667 }
668 if (!*wk->li->targetpath)
669 strcpy(wk->li->targetpath, wk->directory);
670 if (!*wk->li->targetpath) {
671 strcpy(wk->li->targetpath, wk->li->list[0]);
672 p = strrchr(wk->li->targetpath, '\\');
673 if (p) {
674 if (*(p - 1) == ':')
675 p++;
676 *p = 0;
677 }
678 }
679 MakeValidDir(wk->li->targetpath);
680 if (fConfirmTarget ||
681 (!*targetdir && strcmp(realappname, "FM/4"))) {
682 RetryPath:
683 // Confirm target
684 usedtarget = FALSE;
685 if (wk->li->type == IDM_MOVE ||
686 wk->li->type == IDM_WPSMOVE) {
687 rc = WinDlgBox(HWND_DESKTOP,
688 wk->hwndFrame,
689 WalkMoveDlgProc,
690 FM3ModHandle,
691 WALK_FRAME, MPFROMP(wk->li->targetpath));
692 }
693 else if (wk->li->type == IDM_COPY ||
694 wk->li->type == IDM_WPSCOPY) {
695 rc = WinDlgBox(HWND_DESKTOP,
696 wk->hwndFrame,
697 WalkCopyDlgProc,
698 FM3ModHandle,
699 WALK_FRAME, MPFROMP(wk->li->targetpath));
700 }
701 else
702 rc = WinDlgBox(HWND_DESKTOP,
703 wk->hwndFrame,
704 WalkDlgProc,
705 FM3ModHandle,
706 WALK_FRAME, MPFROMP(wk->li->targetpath));
707 }
708 if (!rc || !*wk->li->targetpath)
709 goto Abort;
710 // Check target OK
711 if (driveflags[toupper(*wk->li->targetpath) - 'A'] &
712 DRIVE_NOTWRITEABLE) {
713 saymsg(MB_CANCEL,
714 wk->hwndFrame,
715 GetPString(IDS_ERRORTEXT),
716 GetPString(IDS_NOTWRITENOTARGETTEXT));
717 goto RetryPath;
718 }
719 }
720 Retry:
721 {
722 // Target OK so far
723 CHAR newname[CCHMAXPATH];
724 APIRET rc;
725 INT ret;
726 FILESTATUS4L fs4;
727 BOOL isnewer;
728 BOOL existed;
729 BOOL fResetVerify = FALSE;
730 INT type = wk->li->type == IDM_RENAME ?
731 MOVE :
732 wk->li->type == IDM_MOVE ?
733 MOVE : (wk->li->type == IDM_WPSMOVE) ?
734 WPSMOVE : wk->li->type == IDM_WPSCOPY ?
735 WPSCOPY : COPY;
736 PCSZ moving = wk->li->type == IDM_RENAME ?
737 GetPString(IDS_RENAMINGTEXT) :
738 wk->li->type == IDM_MOVE || wk->li->type == IDM_WPSMOVE ?
739 GetPString(IDS_MOVINGTEXT) : GetPString(IDS_COPYINGTEXT);
740 PCSZ move = wk->li->type == IDM_RENAME ?
741 GetPString(IDS_RENAMETEXT) :
742 wk->li->type == IDM_MOVE ||
743 wk->li->type == IDM_WPSMOVE ?
744 GetPString(IDS_MOVETEXT) : GetPString(IDS_COPYTEXT);
745 PCSZ moved = wk->li->type == IDM_RENAME ?
746 GetPString(IDS_RENAMEDTEXT) :
747 wk->li->type == IDM_MOVE || wk->li->type == IDM_WPSMOVE ?
748 GetPString(IDS_MOVEDTEXT) : GetPString(IDS_COPIEDTEXT);
749
750 if (*wk->li->targetpath) {
751 strcpy(newname, wk->li->targetpath);
752 AddBackslashToPath(newname);
753 if (plen)
754 p = wk->li->list[x] + plen;
755 else {
756 p = strrchr(wk->li->list[x], '\\');
757 if (p)
758 p++;
759 else
760 p = wk->li->list[x];
761 }
762 strcat(newname, p);
763 }
764 else
765 strcpy(newname, wk->li->list[x]);
766 if ((wildcarding || wk->li->type == IDM_RENAME) &&
767 *wildname)
768 {
769 CHAR testname[CCHMAXPATH];
770 strcpy(testname, wildname);
771 if (AdjustWildcardName(newname, testname))
772 strcpy(newname, testname);
773 }
774 existed = IsFile(newname) != -1;
775 isnewer = IsNewer(wk->li->list[x], newname);
776 if (existed && wk->li->type != IDM_RENAME && dontask) {
777 if (!overold && !overnew)
778 break;
779 if (!overold && !isnewer)
780 break;
781 if (!overnew && isnewer)
782 break;
783 }
784 // Confirm overwrite unless bypassed
785 if ((wk->li->type == IDM_RENAME &&
786 (!dontask || !*wildname)) ||
787 (!dontask && existed) ||
788 (!dontask && wildcarding) ||
789 (IsFile(newname) == 0 && IsFile(wk->li->list[x]) > 0))
790 {
791 MOVEIT mv;
792 memset(&mv, 0, sizeof(MOVEIT));
793 mv.rename = (wk->li->type == IDM_RENAME);
794 mv.source = wk->li->list[x];
795 strcpy(mv.target, newname);
796 rc = WinDlgBox(HWND_DESKTOP,
797 wk->hwndFrame,
798 RenameProc,
799 FM3ModHandle, REN_FRAME, (PVOID) & mv);
800 if (!rc)
801 goto Abort;
802
803 DosSleep(1);
804 if (mv.skip || !*mv.target)
805 break;
806 if (mv.dontask)
807 dontask = TRUE;
808 if (mv.overold)
809 overold = TRUE;
810 if (mv.overnew)
811 overnew = TRUE;
812 if (mv.noreadonlywarn)
813 noreadonlywarn = TRUE;
814 if (wildcarding || wk->li->type == IDM_RENAME) {
815 p = strrchr(mv.target, '\\');
816 if (p && (strchr(p, '*') || strchr(p, '?'))) {
817 strcpy(wildname, mv.target);
818 AdjustWildcardName(wk->li->list[x], mv.target);
819 }
820 else
821 *wildname = 0;
822 }
823 strcpy(newname, mv.target);
824 existed = (IsFile(newname) != -1);
825 isnewer = IsNewer(wk->li->list[x], newname);
826 if (!mv.overwrite) {
827 if (existed && wk->li->type != IDM_RENAME && dontask) {
828 if (!overold && !overnew)
829 break;
830 if (!overold && !isnewer)
831 break;
832 if (!overnew && isnewer)
833 break;
834 }
835 }
836 }
837 if (!strcmp(wk->li->list[x], newname) ||
838 (wk->li->type == IDM_COPY &&
839 !stricmp(wk->li->list[x], newname)))
840 break;
841 sprintf(message,
842 " %s \"%s\" %s\"%s\"%s [%u %s%u]",
843 moving,
844 wk->li->list[x],
845 GetPString(IDS_TOTEXT), // Has trailing space
846 newname,
847 usedtarget ?
848 GetPString(IDS_TOTARGETTEXT) :
849 NullStr,
850 x + 1,
851 GetPString(IDS_OFTEXT), // Has trailing space
852 cItemsInList);
853 AddNote(message);
854 if (fVerify && (driveflags[toupper(*wk->li->targetpath) - 'A'] & DRIVE_WRITEVERIFYOFF) |
855 (driveflags[toupper(*wk->li->list[x]) - 'A'] & DRIVE_WRITEVERIFYOFF)) {
856 DosSetVerify(FALSE);
857 fResetVerify = TRUE;
858 }
859 if (plen) {
860 // make directory/ies, if required
861
862 CHAR dirpart[CCHMAXPATH];
863
864 strcpy(dirpart, newname);
865 p = strrchr(dirpart, '\\');
866 if (p) {
867 *p = 0;
868 if (p > dirpart + 3)
869 MassMkdir((hwndMain) ? hwndMain : wk->hwndCnr,
870 dirpart);
871 }
872 }
873 if (fRealIdle)
874 priority_idle();
875
876 rc = docopyf(type, wk->li->list[x], newname);
877 if (rc == ERROR_ACCESS_DENIED || rc == ERROR_SHARING_VIOLATION) {
878 ret = make_deleteable(newname, rc, noreadonlywarn);
879 rc = docopyf(type, wk->li->list[x], newname);
880 }
881 if (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, // move, copy, rename etc.
957 GetPString(IDS_OFTEXT), // "of " - note trailing space
958 wk->li->list[x],
959 GetPString(IDS_TOTEXT), // "to "
960 newname, GetPString(IDS_FAILEDTEXT)); // "failed"
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 BOOL ignorereadonly = FALSE;
1592
1593 for (x = 0; wk->li->list[x]; x++) {
1594 if (IsRoot(wk->li->list[x])) {
1595 wk->li->list = RemoveFromList(wk->li->list,
1596 wk->li->list[x]);
1597 if (!wk->li->list)
1598 break;
1599 x--;
1600 continue;
1601 }
1602 DosError(FERR_DISABLEHARDERR);
1603 if (DosQueryPathInfo(wk->li->list[x],
1604 FIL_STANDARD, &fsa,
1605 (ULONG) sizeof(FILESTATUS3))) {
1606 wk->li->list = RemoveFromList(wk->li->list,
1607 wk->li->list[x]);
1608 if (!wk->li->list)
1609 break;
1610 x--;
1611 continue;
1612 }
1613 if (fsa.attrFile & FILE_DIRECTORY) {
1614 isdir++;
1615 if (stristr(wk->li->list[x], ":\\OS2\\") ||
1616 !stricmp(wk->li->list[x] + 1, ":\\OS2"))
1617 sysdir++;
1618 }
1619 else {
1620 if (fsa.attrFile & (FILE_HIDDEN | FILE_SYSTEM))
1621 hs++;
1622 if (fsa.attrFile & FILE_READONLY)
1623 ro++;
1624 }
1625 }
1626 if (!wk->li->list)
1627 break;
1628 if (fConfirmDelete || isdir || hs || ro) {
1629 memset(&cl, 0, sizeof(cl));
1630 cl.size = sizeof(cl);
1631 cl.list = wk->li->list;
1632 cl.prompt = prompt;
1633 cl.flags |= CHECK_FILES;
1634 cl.cmd = wk->li->type;
1635 sprintf(prompt,
1636 GetPString(IDS_DELPROMPT1TEXT),
1637 (wk->li->type == IDM_DELETE) ?
1638 NullStr :
1639 GetPString(IDS_PERMANENTLYTEXT),
1640 &"s"[wk->li->list[1] == NULL]);
1641 if (isdir) {
1642 sprintf(&prompt[strlen(prompt)],
1643 GetPString(IDS_DELPROMPT2TEXT),
1644 isdir,
1645 (isdir > 1) ?
1646 GetPString(IDS_ARETEXT) :
1647 GetPString(IDS_ISTEXT),
1648 (isdir == 1) ?
1649 GetPString(IDS_ATEXT) :
1650 NullStr,
1651 (isdir > 1) ?
1652 GetPString(IDS_IESTEXT) : GetPString(IDS_YTEXT));
1653 if (sysdir)
1654 sprintf(&prompt[strlen(prompt)],
1655 GetPString(IDS_DELPROMPT3TEXT),
1656 sysdir,
1657 (sysdir == 1) ?
1658 GetPString(IDS_YTEXT) : GetPString(IDS_IESTEXT));
1659 }
1660 if (ro)
1661 sprintf(&prompt[strlen(prompt)],
1662 GetPString(IDS_DELPROMPT4TEXT),
1663 ro,
1664 &"s"[ro == 1],
1665 (ro > 1) ?
1666 GetPString(IDS_ARETEXT) : GetPString(IDS_ISTEXT));
1667 if (hs)
1668 sprintf(&prompt[strlen(prompt)],
1669 GetPString(IDS_DELPROMPT5TEXT),
1670 hs,
1671 &"s"[hs == 1],
1672 (hs > 1) ?
1673 GetPString(IDS_ARETEXT) : GetPString(IDS_ISTEXT));
1674 if ((ro || hs || sysdir) && !fAlertBeepOff)
1675 DosBeep(300, 100); // Wake up user
1676 strcat(prompt, GetPString(IDS_DELPROMPT6TEXT));
1677 error = WinDlgBox(HWND_DESKTOP,
1678 wk->hwndFrame,
1679 CheckListProc,
1680 FM3ModHandle, CHECK_FRAME, MPFROMP(&cl));
1681 if (!error || error == 65535)
1682 break;
1683 wk->li->list = cl.list;
1684 if (!wk->li->list || !wk->li->list[0])
1685 break;
1686 }
1687 if (fVerify && driveflags[toupper(*wk->li->list[0]) - 'A'] & DRIVE_WRITEVERIFYOFF)
1688 DosSetVerify(FALSE);
1689 DosRequestMutexSem(hmtxFM2Delete, SEM_INDEFINITE_WAIT); // Prevent race 12-3-08 GKY
1690 for (x = 0; wk->li->list[x]; x++) {
1691 fsa.attrFile = 0;
1692 DosError(FERR_DISABLEHARDERR);
1693 DosQueryPathInfo(wk->li->list[x],
1694 FIL_STANDARD,
1695 &fsa, (ULONG) sizeof(FILESTATUS3));
1696 if (fsa.attrFile & FILE_DIRECTORY) {
1697 error = (APIRET) wipeallf(FALSE, "%s%s*",
1698 wk->li->list[x],
1699 (*wk->li->list[x] &&
1700 wk->li->
1701 list[x][strlen(wk->li->list[x]) - 1]
1702 != '\\') ? PCSZ_BACKSLASH : NullStr);
1703 DosError(FERR_DISABLEHARDERR);
1704 if (!error)
1705 error = DosDeleteDir(wk->li->list[x]);
1706 else
1707 DosDeleteDir(wk->li->list[x]);
1708 }
1709 else {
1710
1711 DosError(FERR_DISABLEHARDERR);
1712 if (wk->li->type == IDM_DELETE) {
1713 hObjectdest = WinQueryObject("<XWP_TRASHCAN>");
1714 PrfQueryProfileData(HINI_USER,
1715 "XWorkplace",
1716 "TrashCan::Drives",
1717 G_abSupportedDrives,
1718 &cbSupportedDrives);
1719 if (hObjectdest != NULLHANDLE && fTrashCan &&
1720 (G_abSupportedDrives ? (G_abSupportedDrives[toupper(*wk->li->list[x]) - 'C'] &
1721 1):(!(driveflags[toupper(*wk->li->list[x]) - 'A'] &
1722 (DRIVE_REMOVABLE | DRIVE_IGNORE |
1723 DRIVE_REMOTE | DRIVE_VIRTUAL |
1724 DRIVE_NOTWRITEABLE | DRIVE_RAMDISK))))) {
1725 hObjectofObject = WinQueryObject(wk->li->list[x]);
1726 error = WinMoveObject(hObjectofObject, hObjectdest, 0);
1727 }
1728 else {
1729 error = DosDelete(wk->li->list[x]);
1730 }
1731 }
1732 else {
1733 error = DosForceDelete(wk->li->list[x]); ;
1734 }
1735 if (error) {
1736 INT retrn = 0;
1737
1738 DosError(FERR_DISABLEHARDERR);
1739 retrn = make_deleteable(wk->li->list[x], error, ignorereadonly);
1740 if (retrn == 2)
1741 break;
1742 if (retrn == 1)
1743 ignorereadonly = TRUE;
1744 if (retrn == 3)
1745 continue;
1746 if (wk->li->type == IDM_DELETE){
1747 hObjectdest = WinQueryObject("<XWP_TRASHCAN>");
1748 PrfQueryProfileData(HINI_USER,
1749 "XWorkplace",
1750 "TrashCan::Drives",
1751 G_abSupportedDrives,
1752 &cbSupportedDrives);
1753 if (hObjectdest != NULLHANDLE && fTrashCan &&
1754 (G_abSupportedDrives ? (G_abSupportedDrives[toupper(*wk->li->list[x]) - 'C'] &
1755 1):(!(driveflags[toupper(*wk->li->list[x]) - 'A'] &
1756 (DRIVE_REMOVABLE | DRIVE_IGNORE |
1757 DRIVE_REMOTE | DRIVE_VIRTUAL |
1758 DRIVE_NOTWRITEABLE | DRIVE_RAMDISK))))) {
1759 hObjectofObject = WinQueryObject(wk->li->list[x]);
1760 error = WinMoveObject(hObjectofObject, hObjectdest, 0);
1761 }
1762 else {
1763 error = DosDelete(wk->li->list[x]);
1764 }
1765 }
1766 else {
1767 error = DosForceDelete(wk->li->list[x]);
1768 }
1769 }
1770 DosReleaseMutexSem(hmtxFM2Delete);
1771 }
1772 if (error) {
1773 if (LogFileHandle)
1774 fprintf(LogFileHandle,
1775 GetPString(IDS_DELETEFAILED1TEXT),
1776 wk->li->list[x], error);
1777 if (Dos_Error(MB_ENTERCANCEL,
1778 error,
1779 wk->hwndFrame,
1780 pszSrcFile,
1781 __LINE__,
1782 GetPString(IDS_DELETEFAILED2TEXT),
1783 wk->li->list[x]) == MBID_CANCEL) {
1784 DosSetVerify(fVerify);
1785 break;
1786 }
1787 }
1788 else {
1789 if (LogFileHandle)
1790 fprintf(LogFileHandle,
1791 GetPString(IDS_DELETEDTEXT), wk->li->list[x]);
1792 sprintf(prompt,
1793 GetPString(IDS_DELETEDTEXT), wk->li->list[x]);
1794 AddNote(prompt);
1795 }
1796 if (//fSyncUpdates ||
1797 AddToList(wk->li->list[x], &files, &numfiles, &numalloc)) {
1798 Broadcast(hab2,
1799 wk->hwndCnr,
1800 UM_UPDATERECORD,
1801 MPFROMP(wk->li->list[x]), MPVOID);
1802 } ;
1803 } // for
1804 }
1805 if (fVerify)
1806 DosSetVerify(fVerify);
1807 break;
1808 } // switch
1809 if (files) {
1810 Broadcast(hab2,
1811 wk->hwndCnr,
1812 UM_UPDATERECORDLIST, MPFROMP(files), MPVOID);
1813 FreeList(files);
1814 }
1815 if (WinIsWindow(hab2, wk->hwndCnr))
1816 PostMsg(wk->hwndCnr, UM_RESCAN, MPVOID, MPVOID);
1817
1818 WinDestroyMsgQueue(hmq2);
1819 }
1820 DecrThreadUsage();
1821 WinTerminate(hab2);
1822 }
1823 }
1824 FreeListInfo(wk->li);
1825 free(wk);
1826# ifdef FORTIFY
1827 Fortify_LeaveScope();
1828# endif
1829 DosPostEventSem(CompactSem);
1830 }
1831}
1832
1833#pragma alloc_text(MASSACTION,MassAction)
1834#pragma alloc_text(ACTION,Action)
1835#pragma alloc_text(UNDO,FreeUndo,Undo)
Note: See TracBrowser for help on using the repository browser.