source: trunk/dll/worker.c@ 1712

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

Added comments

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