source: trunk/dll/worker.c@ 1721

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

Fixed move to trashcan to work when the trashcan::drives key hadn't been written to OS2.INI. INI check is now only if fTrashCan is TRUE. Rework readonly check on delete code so it actually works in a logical way and so it works with move to trashcan inabled. Additional improvements to saymsg2. Tickets 506/507

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