source: trunk/dll/worker.c@ 1673

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

Update to Doxygen comment style Ticket 55. Also some minor code cleanup.

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