source: trunk/dll/filldir.c@ 1395

Last change on this file since 1395 was 1395, checked in by Gregg Young, 17 years ago

Allow user to turn off alert and/or error beeps in settings notebook. Ticket 341 Move repeated strings to PCSZs. Ticket 6 Add *DateFormat functions to format dates based on locale Ticket 28 Eliminate Win_Error2 by moving function names to PCSZs used in Win_Error Ticket 6

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 59.7 KB
Line 
1
2/***********************************************************************
3
4 $Id: filldir.c 1395 2009-02-08 01:48:16Z gyoung $
5
6 Fill Directory Tree Containers
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2001, 2008 Steven H. Levine
10
11 10 Jan 04 SHL ProcessDirectory: avoid most large drive failures
12 24 May 05 SHL Rework Win_Error usage
13 24 May 05 SHL Rework for CNRITEM.szSubject
14 25 May 05 SHL Rework for ULONGLONG
15 25 May 05 SHL Rework FillInRecordFromFFB
16 25 May 05 SHL Rework FillTreeCnr
17 28 May 05 SHL Drop stale debug code
18 05 Jun 05 SHL Comments
19 09 Jun 05 SHL Rework WinLoadFileIcon enables
20 09 Jun 05 SHL Rework IDFile
21 13 Aug 05 SHL Renames
22 24 Oct 05 SHL FillInRecordFromFFB: correct longname display enable
23 24 Oct 05 SHL FillInRecordFromFSA: correct longname display enable
24 24 Oct 05 SHL Drop obsolete code
25 22 Jul 06 SHL Check more run time errors
26 20 Oct 06 SHL Sync . .. check code
27 22 Oct 06 GKY Add NDFS32 support
28 17 Feb 07 GKY Additional archive and image file tyoes identifed by extension
29 17 Feb 07 GKY Add more drive types
30 09 Mar 07 GKY Use SelectDriveIcon
31 20 Mar 07 GKY Increase extention check to 4 letters for icon selections
32 23 Jun 07 GKY Fixed ram disk without a directory not appearing on states drive list
33 23 Jul 07 SHL Sync with CNRITEM updates (ticket#24)
34 29 Jul 07 SHL Add CNRITEM free and remove support (ticket#24)
35 02 Aug 07 SHL Add FileAttrToString
36 03 Aug 07 GKY Enlarged and made setable everywhere Findbuf (speed file loading)
37 04 Aug 07 SHL Update #pragma alloc_test for new functions
38 06 Aug 07 GKY Reduce DosSleep times (ticket 148)
39 13 Aug 07 SHL Sync code with other FilesToGet usage and optimize
40 13 Aug 07 SHL Move #pragma alloc_text to end for OpenWatcom compat
41 04 Nov 07 GKY Use commaFmtULL to display large file sizes
42 29 Feb 08 GKY Use xfree where appropriate
43 07 Jul 08 SHL Use NULL rather than NullStr in FreeCnrItemData
44 16 JUL 08 GKY Use TMP directory for temp files
45 20 Jul 08 JBS Ticket 114: Support user-selectable env. strings in Tree container.
46 21 Jul 08 JBS Ticket 114: Change env var separator from blank to semicolon
47 02 Aug 08 GKY Remove redundant strcpys from inner loop
48 23 Aug 08 GKY Free pszDisplayName when appropriate
49 01 Sep 08 GKY Updated FreeCnrItemData to prevent trap in strrchr if pci->pszFileName is NULL.
50 05 Sep 08 SHL Correct FreeCnrItemData pszDisplayName pointer overlap check
51 08 Sep 08 SHL Remove extra pszLongName logic in FreeCnrItemData
52 18 Oct 08 GKY Scan drives in 4 passes (local, virtual, remote, flagged slow) to speed tree scans
53 19 Nov 08 SHL Correct and sanitize 4 pass scan logic
54 21 Nov 08 SHL FillTreeCnr: ensure any unchecked drives checked in pass 4
55 24 Nov 08 GKY Add StubyScanThread to treecnr scan/rescan drives all on separate threads
56 24 Nov 08 GKY Replace 4 pass drive scan code with StubyScanThread multithread scan
57 28 Nov 08 SHL FreeCnrItemData: optimize and always NULL pointers
58 28 Nov 08 SHL StubbyScanThread: add else lost in translation
59 30 Nov 08 SHL StubbyScanThread: restore else - we want all drives listed
60 30 Nov 08 SHL FreeCnrItemData: report double free with Runtime_Error
61 04 Dec 08 GKY Use event semaphore to prevent scan of "last" directory container prior to
62 tree scan completion; prevents duplicate directory names in tree.
63 10 Dec 08 SHL Integrate exception handler support
64 25 Dec 08 GKY Add code to allow write verify to be turned off on a per drive basis
65 25 Dec 08 GKY Add ProcessDirectoryThread to allow optional recursive drive scan at startup.
66 07 Feb 09 GKY Eliminate Win_Error2 by moving function names to PCSZs used in Win_Error
67
68***********************************************************************/
69
70#include <stdlib.h>
71#include <string.h>
72#include <malloc.h> // _msize _heapchk
73#include <ctype.h>
74// #include <process.h> // _beginthread
75
76#define INCL_DOS
77#define INCL_WIN
78#define INCL_DOSERRORS
79#define INCL_LONGLONG
80
81#include "fm3dll.h"
82#include "fm3dll2.h" // #define's for UM_*, control id's, etc.
83#include "draglist.h" // Data declaration(s)
84#include "treecnr.h" // Data declaration(s)
85#include "info.h" // Data declaration(s)
86#include "newview.h" // Data declaration(s)
87#include "fm3str.h"
88#include "filldir.h"
89#include "errutil.h" // Dos_Error...
90#include "strutil.h" // GetPString
91#include "misc.h" // GetTidForWindow
92#include "fortify.h" // 06 May 08 SHL
93#include "notebook.h" // INI file fields
94#include "flesh.h" // FleshEnv, Stubby
95#include "update.h" // SelectDriveIcon
96#include "valid.h" // CheckDrive
97#include "filter.h" // Filter
98#include "subj.h" // Subject
99#include "copyf.h" // unlinkf
100#include "literal.h" // wildcard
101#include "commafmt.h" // CommaFmtULL
102#include "wrappers.h" // xDosFindNext
103#include "init.h" // GetTidForWindow
104#include "common.h" // IncrThreadUsage
105#include "excputil.h" // xbeginthread
106
107VOID StubbyScanThread(VOID * arg);
108
109// Data definitions
110static PSZ pszSrcFile = __FILE__;
111static BOOL fFirstTime;
112
113#pragma data_seg(GLOBAL1)
114HPOINTER hptrEnv;
115HPOINTER hptrHidden;
116HPOINTER hptrReadonly;
117HPOINTER hptrSystem;
118
119#pragma data_seg(GLOBAL2)
120CHAR *FM3Tools;
121CHAR *WPProgram;
122volatile INT StubbyScanCount;
123volatile INT ProcessDirCount;
124
125typedef struct {
126 PCNRITEM pci;
127 HWND hwndCnr; // hwnd you want the message posted to
128 HWND hwndDrivesList;
129 BOOL RamDrive;
130}
131STUBBYSCAN;
132
133/**
134 * Return display string given standard file attribute mask
135 * @param fileAttr attribute mask in FILEFINDBUF format
136 * @return fixed length string for display
137 */
138
139const PSZ FileAttrToString(ULONG fileAttr)
140{
141 // From os2win.h
142 // FILE_ATTRIBUTE_READONLY 0x00000001
143 // FILE_ATTRIBUTE_HIDDEN 0x00000002
144 // FILE_ATTRIBUTE_SYSTEM 0x00000004
145 // 0x00000008
146 // FILE_ATTRIBUTE_DIRECTORY 0x00000010
147 // FILE_ATTRIBUTE_ARCHIVE 0x00000020
148
149 static CHAR *apszAttrString[] = {
150 // RHSDA
151 "-----",
152 "R----",
153 "-H---",
154 "RH---",
155 "--S--",
156 "R-S--",
157 "-HS--",
158 "RHS--",
159 "---D-",
160 "R--D-",
161 "-H-D-",
162 "RH-D-",
163 "--SD-",
164 "R-SD-",
165 "-HSD-",
166 "RHSD-",
167 "----A",
168 "R---A",
169 "-H--A",
170 "RH--A",
171 "--S-A",
172 "R-S-A",
173 "-HS-A",
174 "RHS-A",
175 "---DA",
176 "R--DA",
177 "-H-DA",
178 "RH-DA",
179 "--SDA",
180 "R-SDA",
181 "-HSDA",
182 "RHSDA"
183 };
184
185 fileAttr = ((fileAttr & 0x30) >> 1) | (fileAttr & 7); // Drop don't care bit from index
186
187 return apszAttrString[fileAttr];
188
189}
190
191VOID StubbyScanThread(VOID * arg)
192{
193 STUBBYSCAN *StubbyScan;
194 HAB thab;
195 HMQ hmq = (HMQ) 0;
196 BOOL ret;
197
198 DosError(FERR_DISABLEHARDERR);
199
200# ifdef FORTIFY
201 Fortify_EnterScope();
202# endif
203
204 StubbyScan = (STUBBYSCAN *)arg;
205 if (StubbyScan && StubbyScan->pci && StubbyScan->pci->pszFileName && StubbyScan->hwndCnr) {
206 thab = WinInitialize(0);
207 if (thab) {
208 hmq = WinCreateMsgQueue(thab, 0);
209 if (hmq) {
210 StubbyScanCount++;
211 IncrThreadUsage();
212 priority_normal();
213 ret = Stubby(StubbyScan->hwndCnr, StubbyScan->pci);
214 //DbgMsg(pszSrcFile, __LINE__, "Stubby %i ", ret);
215 if (ret == 1) {
216 if (WinIsWindow((HAB)0, StubbyScan->hwndCnr)) {
217 WinSendMsg(StubbyScan->hwndCnr,
218 CM_INVALIDATERECORD,
219 MPFROMP(&StubbyScan->pci),
220 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
221 if (fRScanLocal) {
222 if (!(driveflags[toupper(*StubbyScan->pci->pszFileName) - 'A'] &
223 ((fRScanNoWrite ? 0 : DRIVE_NOTWRITEABLE) |
224 (fRScanRemote ? 0 : DRIVE_REMOTE) |
225 (fRScanSlow ? 0 : DRIVE_SLOW) |
226 (fRScanVirtual ? 0 : DRIVE_VIRTUAL)))
227 && fInitialDriveScan) {
228 WinSendMsg(StubbyScan->hwndCnr, CM_EXPANDTREE, MPFROMP(StubbyScan->pci), MPVOID);
229 //DbgMsg(pszSrcFile, __LINE__, "expanded %x %s", StubbyScan->hwndCnr, StubbyScan->pci->pszFileName);
230 WinSendMsg(StubbyScan->hwndCnr, CM_COLLAPSETREE, MPFROMP(StubbyScan->pci), MPVOID);
231 }
232 }
233 else if ((fRScanRemote && (driveflags[toupper(*StubbyScan->pci->pszFileName) - 'A'] &
234 DRIVE_REMOTE)) ||
235 (fRScanVirtual && (driveflags[toupper(*StubbyScan->pci->pszFileName) - 'A'] &
236 DRIVE_VIRTUAL)) && fInitialDriveScan) {
237 if (!(driveflags[toupper(*StubbyScan->pci->pszFileName) - 'A'] &
238 ((fRScanNoWrite ? NULL : DRIVE_NOTWRITEABLE) |
239 (fRScanSlow ? NULL : DRIVE_SLOW)))) {
240 WinSendMsg(StubbyScan->hwndCnr, CM_EXPANDTREE, MPFROMP(StubbyScan->pci), MPVOID);
241 //DbgMsg(pszSrcFile, __LINE__, "expanded %x %s", StubbyScan->hwndCnr, StubbyScan->pci->pszFileName);
242 WinSendMsg(StubbyScan->hwndCnr, CM_COLLAPSETREE, MPFROMP(StubbyScan->pci), MPVOID);
243 }
244 }
245 }
246 }
247 if (WinIsWindow((HAB)0, StubbyScan->hwndDrivesList)) {
248 WinSendMsg(StubbyScan->hwndDrivesList,
249 LM_INSERTITEM,
250 MPFROM2SHORT(LIT_SORTASCENDING, 0),
251 MPFROMP(StubbyScan->pci->pszFileName));
252 }
253 StubbyScanCount--;
254 /* if (StubbyScanCount == 0) {
255 if (fInitialDriveScan) {
256 WinShowWindow(StubbyScan->hwndCnr, TRUE);
257 WinShowWindow(StubbyScan->hwndDrivesList, TRUE);
258 }
259 fInitialDriveScan = FALSE;
260 }*/
261 WinDestroyMsgQueue(hmq);
262 }
263 DecrThreadUsage();
264 WinTerminate(thab);
265 }
266 free(StubbyScan);
267 } // if StubbyScan
268# ifdef FORTIFY
269 Fortify_LeaveScope();
270# endif
271
272 // _endthread(); // 10 Dec 08 SHL
273}
274
275VOID ProcessDirectoryThread(VOID * arg)
276{
277 PROCESSDIR *ProcessDir;
278 HAB thab;
279 HMQ hmq = (HMQ) 0;
280 //BOOL ret;
281
282 DosError(FERR_DISABLEHARDERR);
283
284# ifdef FORTIFY
285 Fortify_EnterScope();
286# endif
287
288 ProcessDir = (PROCESSDIR *)arg;
289 if (ProcessDir && ProcessDir->pciParent && ProcessDir->pciParent->pszFileName && ProcessDir->hwndCnr) {
290 thab = WinInitialize(0);
291 if (thab) {
292 hmq = WinCreateMsgQueue(thab, 0);
293 if (hmq) {
294 ProcessDirCount ++;
295 IncrThreadUsage();
296 priority_normal();
297 ProcessDirectory(ProcessDir->hwndCnr,
298 ProcessDir->pciParent,
299 ProcessDir->szDirBase,
300 ProcessDir->filestoo,
301 ProcessDir->recurse,
302 ProcessDir->partial,
303 ProcessDir->stopflag,
304 ProcessDir->dcd, // Optional
305 ProcessDir->pulTotalFiles, // Optional
306 ProcessDir->pullTotalBytes); // Optional
307 ProcessDirCount --;
308 WinDestroyMsgQueue(hmq);
309 }
310 DecrThreadUsage();
311 WinTerminate(thab);
312 }
313 free(ProcessDir);
314 } // if ProcessDir
315# ifdef FORTIFY
316 Fortify_LeaveScope();
317# endif
318
319 // _endthread(); // 10 Dec 08 SHL
320}
321
322static HPOINTER IDFile(PSZ p)
323{
324 HPOINTER hptr;
325 ULONG cmp;
326 CHAR cmps[5];
327
328 p = strrchr(p, '.');
329 if (p && !p[5]) {
330 cmps[0] = '.';
331 cmps[1] = toupper(p[1]);
332 cmps[2] = toupper(p[2]);
333 cmps[3] = toupper(p[3]);
334 cmps[4] = toupper(p[4]);
335
336 cmp = *(ULONG *) cmps;
337
338 if (cmp == *(ULONG *) ".EXE" || cmp == *(ULONG *) ".CMD" ||
339 cmp == *(ULONG *) ".BAT" || cmp == *(ULONG *) ".COM")
340 hptr = hptrApp;
341 else if (cmp == *(ULONG *) ".ZIP" || cmp == *(ULONG *) ".LZH" ||
342 cmp == *(ULONG *) ".ARJ" || cmp == *(ULONG *) ".ARC" ||
343 cmp == *(ULONG *) ".ZOO" || cmp == *(ULONG *) ".RAR" ||
344 cmp == *(ULONG *) ".TAR" || cmp == *(ULONG *) ".TGZ" ||
345 cmp == *(ULONG *) ".GZ" || cmp == *(ULONG *) ".Z" ||
346 cmp == *(ULONG *) ".CAB" || cmp == *(ULONG *) ".BZ2")
347 hptr = hptrArc;
348 else if (cmp == *(ULONG *) ".BMP" || cmp == *(ULONG *) ".ICO" ||
349 cmp == *(ULONG *) ".PTR" || cmp == *(ULONG *) ".GIF" ||
350 cmp == *(ULONG *) ".TIF" || cmp == *(ULONG *) ".PCX" ||
351 cmp == *(ULONG *) ".TGA" || cmp == *(ULONG *) ".XBM" ||
352 cmp == *(ULONG *) ".JPEG" || cmp == *(ULONG *) ".JPG" ||
353 cmp == *(ULONG *) ".PNG" || cmp == *(ULONG *) ".PSD" ||
354 cmp == *(ULONG *) ".LGO" || cmp == *(ULONG *) ".EPS" ||
355 cmp == *(ULONG *) ".RLE" || cmp == *(ULONG *) ".RAS" ||
356 cmp == *(ULONG *) ".PLC" || cmp == *(ULONG *) ".MSP" ||
357 cmp == *(ULONG *) ".IFF" || cmp == *(ULONG *) ".FIT" ||
358 cmp == *(ULONG *) ".DCX" || cmp == *(ULONG *) ".MAC" ||
359 cmp == *(ULONG *) ".SFF" || cmp == *(ULONG *) ".SGI" ||
360 cmp == *(ULONG *) ".XWD" || cmp == *(ULONG *) ".XPM" ||
361 cmp == *(ULONG *) ".WPG" || cmp == *(ULONG *) ".CUR" ||
362 cmp == *(ULONG *) ".PNM" || cmp == *(ULONG *) ".PPM" ||
363 cmp == *(ULONG *) ".PGM" || cmp == *(ULONG *) ".PBM")
364 hptr = hptrArt;
365 else
366 hptr = (HPOINTER) 0;
367 }
368 else
369 hptr = (HPOINTER) 0;
370
371 return hptr;
372}
373
374static BOOL IsDefaultIcon(HPOINTER hptr)
375{
376 HPOINTER hptr2;
377 HPOINTER hptr3;
378 UINT u;
379
380 static HPOINTER hptrPMFile;
381 static HPOINTER hptrWPSFile;
382
383 if (!hptrPMFile) {
384 hptrPMFile = WinQuerySysPointer(HWND_DESKTOP, SPTR_FILE, FALSE);
385 }
386
387 // try to guess WPS default file icon
388 hptr2 = (HPOINTER) 0;
389 for (u = 0; !hptrWPSFile && u < 10; u++) {
390 char szFileName[CCHMAXPATH];
391 char *psz;
392
393 if (pTmpDir) {
394 psz = pTmpDir;
395 strcpy(szFileName, psz);
396 psz = szFileName + strlen(szFileName) - 1;
397 if (*psz != '\\') {
398 psz++;
399 *psz++ = '\\';
400 }
401 }
402 else
403 psz = szFileName;
404
405 sprintf(psz, "%08x.%03x", rand() & 0xffffffff, rand() & 0xfff);
406 if (IsFile(szFileName) != 1) {
407 FILE *fp = fopen(szFileName, "w");
408
409 if (fp) {
410 fclose(fp);
411 hptr3 = WinLoadFileIcon(szFileName, FALSE);
412 unlinkf("%s", szFileName);
413 if (!hptr2)
414 hptr2 = hptr3;
415 else if (hptr3 == hptr3) {
416 hptrWPSFile = hptr3; // Got same icon twice
417 break;
418 }
419 }
420 }
421 DosSleep(rand() % 100);
422
423 } // for
424
425 return hptr == hptrPMFile || hptr == hptrWPSFile;
426
427} // IsDefaultIcon
428
429ULONGLONG FillInRecordFromFFB(HWND hwndCnr,
430 PCNRITEM pci,
431 const PSZ pszDirectory,
432 const PFILEFINDBUF4L pffb,
433 const BOOL partial,
434 DIRCNRDATA *dcd)
435{
436 // fill in a container record from a FILEFINDBUF4L structure
437
438 CHAR *p;
439 HPOINTER hptr;
440 ULONG flags;
441
442 pci->hwndCnr = hwndCnr;
443
444 /* note that we cheat below, and accept the full pathname in pszDirectory
445 if !*pffb->achName. This speeds up and simplifies processing elsewhere
446 (like in update.c)
447 */
448 if (!*pffb->achName) {
449 pci->pszFileName = xstrdup(pszDirectory, pszSrcFile, __LINE__);
450 //strcpy(pci->pszFileName, pszDirectory);
451 }
452 else {
453 INT c = strlen(pszDirectory);
454 INT c2 = pffb->cchName + 1;
455 if (pszDirectory[c - 1] != '\\')
456 c2++;
457 pci->pszFileName = xmalloc(c + c2, pszSrcFile, __LINE__);
458# ifdef FORTIFY
459 {
460 if (dcd->type != TREE_FRAME)
461 Fortify_ChangeScope(pci->pszFileName, -1);
462 else {
463 Fortify_SetOwner(pci->pszFileName, 1);
464 Fortify_SetScope(pci->pszFileName, 2);
465 }
466 }
467# endif
468 memcpy(pci->pszFileName, pszDirectory, c + 1);
469 p = pci->pszFileName + c - 1;
470 if (*p != '\\') {
471 p++;
472 *p = '\\';
473 }
474 p++;
475 memcpy(p, pffb->achName, pffb->cchName + 1);
476 }
477 flags = driveflags[toupper(*pci->pszFileName) - 'A'];
478 // load the object's Subject, if required
479 // pci->pszSubject = NullStr; dubplicate see below 12-05-08 GKY
480 if (pffb->cbList > 4L &&
481 dcd && fLoadSubject &&
482 (isalpha(*pci->pszFileName) &&
483 !(flags & DRIVE_NOLOADSUBJS)))
484 {
485 APIRET rc;
486 EAOP2 eaop;
487 PGEA2LIST pgealist;
488 PFEA2LIST pfealist;
489 PGEA2 pgea;
490 PFEA2 pfea;
491 CHAR *value;
492
493 pgealist = xmallocz(sizeof(GEA2LIST) + 32, pszSrcFile, __LINE__);
494 if (pgealist) {
495 pgea = &pgealist->list[0];
496 strcpy(pgea->szName, SUBJECT);
497 pgea->cbName = strlen(pgea->szName);
498 pgea->oNextEntryOffset = 0;
499 pgealist->cbList = (sizeof(GEA2LIST) + pgea->cbName);
500 pfealist = xmallocz(1532, pszSrcFile, __LINE__);
501 if (pfealist) {
502 pfealist->cbList = 1024;
503 eaop.fpGEA2List = pgealist;
504 eaop.fpFEA2List = pfealist;
505 eaop.oError = 0;
506 rc = DosQueryPathInfo(pci->pszFileName, FIL_QUERYEASFROMLIST,
507 (PVOID) & eaop, (ULONG) sizeof(EAOP2));
508 if (!rc) {
509 pfea = &eaop.fpFEA2List->list[0];
510 value = pfea->szName + pfea->cbName + 1;
511 value[pfea->cbValue] = 0;
512 if (*(USHORT *) value == EAT_ASCII)
513 pci->pszSubject = xstrdup(value + (sizeof(USHORT) * 2), pszSrcFile, __LINE__);
514 }
515 free(pfealist);
516 }
517 free(pgealist);
518 }
519 }
520 if (!pci->pszSubject)
521 pci->pszSubject = NullStr;
522
523 // load the object's longname
524 pci->pszLongName = NULL;
525 if (fLoadLongnames &&
526 dcd &&
527 pffb->cbList > 4L &&
528 isalpha(*pci->pszFileName) &&
529 ~flags & DRIVE_NOLONGNAMES &&
530 ~flags & DRIVE_NOLOADLONGS)
531 {
532 APIRET rc;
533 EAOP2 eaop;
534 PGEA2LIST pgealist;
535 PFEA2LIST pfealist;
536 PGEA2 pgea;
537 PFEA2 pfea;
538 CHAR *value;
539
540 pgealist = xmallocz(sizeof(GEA2LIST) + 32, pszSrcFile, __LINE__);
541 if (pgealist) {
542 pgea = &pgealist->list[0];
543 strcpy(pgea->szName, LONGNAME);
544 pgea->cbName = strlen(pgea->szName);
545 pgea->oNextEntryOffset = 0;
546 pgealist->cbList = (sizeof(GEA2LIST) + pgea->cbName);
547 pfealist = xmallocz(1532, pszSrcFile, __LINE__);
548 if (pfealist) {
549 pfealist->cbList = 1024;
550 eaop.fpGEA2List = pgealist;
551 eaop.fpFEA2List = pfealist;
552 eaop.oError = 0;
553 rc = DosQueryPathInfo(pci->pszFileName, FIL_QUERYEASFROMLIST,
554 (PVOID) & eaop, (ULONG) sizeof(EAOP2));
555 if (!rc) {
556 pfea = &eaop.fpFEA2List->list[0];
557 value = pfea->szName + pfea->cbName + 1;
558 value[pfea->cbValue] = 0;
559 if (*(USHORT *) value == EAT_ASCII) {
560 pci->pszLongName = xstrdup(value + (sizeof(USHORT) * 2), pszSrcFile, __LINE__);
561# ifdef FORTIFY
562 {
563 unsigned tid = GetTidForWindow(hwndCnr);
564 if (tid == 1)
565 Fortify_ChangeScope(pci->pszLongName, -1);
566 else
567 Fortify_SetOwner(pci->pszLongName, 1);
568 }
569# endif
570 }
571 }
572 free(pfealist);
573 }
574 free(pgealist);
575 }
576 }
577 if (!pci->pszLongName)
578 pci->pszLongName = NullStr;
579
580 // do anything required to case of filename
581 if (fForceUpper)
582 strupr(pci->pszFileName);
583 else if (fForceLower)
584 strlwr(pci->pszFileName);
585
586 // get an icon to use with it
587 if (pffb->attrFile & FILE_DIRECTORY) {
588 // is directory
589 if (fNoIconsDirs ||
590 (flags & DRIVE_NOLOADICONS) ||
591 !isalpha(*pci->pszFileName)) {
592 hptr = (HPOINTER) 0;
593 }
594 else
595 hptr = WinLoadFileIcon(pci->pszFileName, FALSE);
596 }
597 else {
598 // is file
599 if (fNoIconsFiles ||
600 (flags & DRIVE_NOLOADICONS) ||
601 !isalpha(*pci->pszFileName)) {
602 hptr = (HPOINTER) 0;
603 }
604 else
605 hptr = WinLoadFileIcon(pci->pszFileName, FALSE);
606
607 if (!hptr || IsDefaultIcon(hptr))
608 hptr = IDFile(pci->pszFileName);
609 }
610
611 if (!hptr) {
612 hptr = pffb->attrFile & FILE_DIRECTORY ?
613 hptrDir : pffb->attrFile & FILE_SYSTEM ?
614 hptrSystem : pffb->attrFile & FILE_HIDDEN ?
615 hptrHidden : pffb->attrFile & FILE_READONLY ?
616 hptrReadonly : hptrFile;
617 }
618
619 // Tell container what part of pathname to display
620 if (partial) {
621 p = strrchr(pci->pszFileName, '\\');
622 if (!p) {
623 p = strrchr(pci->pszFileName, ':');
624 if (!p)
625 p = pci->pszFileName;
626 else
627 p++;
628 }
629 else if ((dcd && dcd->type == TREE_FRAME) ||
630 (!(pffb->attrFile & FILE_DIRECTORY) || !*(p + 1))) {
631 p++;
632 }
633 if (!*p)
634 p = pci->pszFileName;
635 }
636 else
637 p = pci->pszFileName;
638 pci->pszDisplayName = p;
639
640 //comma format the file size for large file support
641 {
642 CHAR szBuf[30];
643 CommaFmtULL(szBuf, sizeof(szBuf), pffb->cbFile, ' ');
644 pci->pszFmtFileSize = xstrdup(szBuf, pszSrcFile, __LINE__);
645# ifdef FORTIFY
646 {
647 unsigned tid = GetTidForWindow(hwndCnr);
648 if (tid == 1)
649 Fortify_ChangeScope(pci->pszFmtFileSize, -1);
650 else
651 Fortify_SetOwner(pci->pszFmtFileSize, 1);
652 }
653# endif
654 }
655
656 // now fill the darned thing in...
657 pci->date.day = pffb->fdateLastWrite.day;
658 pci->date.month = pffb->fdateLastWrite.month;
659 pci->date.year = pffb->fdateLastWrite.year + 1980;
660 pci->time.seconds = pffb->ftimeLastWrite.twosecs * 2;
661 pci->time.minutes = pffb->ftimeLastWrite.minutes;
662 pci->time.hours = pffb->ftimeLastWrite.hours;
663 pci->ladate.day = pffb->fdateLastAccess.day;
664 pci->ladate.month = pffb->fdateLastAccess.month;
665 pci->ladate.year = pffb->fdateLastAccess.year + 1980;
666 pci->latime.seconds = pffb->ftimeLastAccess.twosecs * 2;
667 pci->latime.minutes = pffb->ftimeLastAccess.minutes;
668 pci->latime.hours = pffb->ftimeLastAccess.hours;
669 pci->crdate.day = pffb->fdateCreation.day;
670 pci->crdate.month = pffb->fdateCreation.month;
671 pci->crdate.year = pffb->fdateCreation.year + 1980;
672 pci->crtime.seconds = pffb->ftimeCreation.twosecs * 2;
673 pci->crtime.minutes = pffb->ftimeCreation.minutes;
674 pci->crtime.hours = pffb->ftimeCreation.hours;
675 pci->easize = CBLIST_TO_EASIZE(pffb->cbList);
676 pci->cbFile = pffb->cbFile;
677 pci->attrFile = pffb->attrFile;
678 pci->pszDispAttr = FileAttrToString(pci->attrFile);
679 pci->rc.pszIcon = pci->pszDisplayName;
680 pci->rc.hptrIcon = hptr;
681
682 // check to see if record should be visible
683 if (dcd && (*dcd->mask.szMask || dcd->mask.antiattr ||
684 ((dcd->mask.attrFile &
685 (FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY | FILE_ARCHIVED))
686 !=
687 (FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY | FILE_ARCHIVED))))
688 {
689 if (*dcd->mask.szMask || dcd->mask.antiattr) {
690 if (!Filter((PMINIRECORDCORE) pci, (PVOID) & dcd->mask))
691 pci->rc.flRecordAttr |= CRA_FILTERED;
692 }
693 else if ((!(dcd->mask.attrFile & FILE_HIDDEN) &&
694 (pci->attrFile & FILE_HIDDEN)) ||
695 (!(dcd->mask.attrFile & FILE_SYSTEM) &&
696 (pci->attrFile & FILE_SYSTEM)) ||
697 (!(dcd->mask.attrFile & FILE_READONLY) &&
698 (pci->attrFile & FILE_READONLY)) ||
699 (!(dcd->mask.attrFile & FILE_ARCHIVED) &&
700 (pci->attrFile & FILE_ARCHIVED))) {
701 pci->rc.flRecordAttr |= CRA_FILTERED;
702 }
703 }
704
705 return pffb->cbFile + pci->easize;
706
707} // FillInRecordFromFFB
708
709ULONGLONG FillInRecordFromFSA(HWND hwndCnr,
710 PCNRITEM pci,
711 const PSZ pszFileName,
712 const PFILESTATUS4L pfsa4,
713 const BOOL partial,
714 DIRCNRDATA *dcd) // Optional
715{
716 HPOINTER hptr;
717 CHAR *p;
718 ULONG flags;
719
720 // fill in a container record from a FILESTATUS4L structure
721
722 pci->hwndCnr = hwndCnr;
723 pci->pszFileName = xstrdup(pszFileName, pszSrcFile, __LINE__);
724 //strcpy(pci->pszFileName, pszFileName);
725 flags = driveflags[toupper(*pci->pszFileName) - 'A'];
726 // load the object's Subject, if required
727 //pci->pszSubject = NullStr;
728 if (pfsa4->cbList > 4 &&
729 dcd &&
730 fLoadSubject &&
731 (!isalpha(*pci->pszFileName) ||
732 !(flags & DRIVE_NOLOADSUBJS)))
733 {
734 APIRET rc;
735 EAOP2 eaop;
736 PGEA2LIST pgealist;
737 PFEA2LIST pfealist;
738 PGEA2 pgea;
739 PFEA2 pfea;
740 CHAR *value;
741
742 pgealist = xmallocz(sizeof(GEA2LIST) + 32, pszSrcFile, __LINE__);
743 if (pgealist) {
744 pgea = &pgealist->list[0];
745 strcpy(pgea->szName, SUBJECT);
746 pgea->cbName = strlen(pgea->szName);
747 pgea->oNextEntryOffset = 0;
748 pgealist->cbList = (sizeof(GEA2LIST) + pgea->cbName);
749 pfealist = xmallocz(1532, pszSrcFile, __LINE__);
750 if (pfealist) {
751 pfealist->cbList = 1024;
752 eaop.fpGEA2List = pgealist;
753 eaop.fpFEA2List = pfealist;
754 eaop.oError = 0;
755 rc = DosQueryPathInfo(pci->pszFileName, FIL_QUERYEASFROMLIST,
756 (PVOID) & eaop, (ULONG) sizeof(EAOP2));
757 if (!rc) {
758 pfea = &eaop.fpFEA2List->list[0];
759 value = pfea->szName + pfea->cbName + 1;
760 value[pfea->cbValue] = 0;
761 if (*(USHORT *) value == EAT_ASCII)
762 pci->pszSubject = xstrdup(value + (sizeof(USHORT) * 2), pszSrcFile, __LINE__);
763 }
764 free(pfealist);
765 }
766 free(pgealist);
767 }
768 }
769 if (!pci->pszSubject)
770 pci->pszSubject = NullStr;
771
772 pci->pszLongName = NULL;
773 if (fLoadLongnames &&
774 dcd &&
775 pfsa4->cbList > 4L &&
776 isalpha(*pci->pszFileName) &&
777 ~flags & DRIVE_NOLONGNAMES &&
778 ~flags & DRIVE_NOLOADLONGS)
779 {
780 APIRET rc;
781 EAOP2 eaop;
782 PGEA2LIST pgealist;
783 PFEA2LIST pfealist;
784 PGEA2 pgea;
785 PFEA2 pfea;
786 CHAR *value;
787
788 pgealist = xmallocz(sizeof(GEA2LIST) + 32, pszSrcFile, __LINE__);
789 if (pgealist) {
790 pgea = &pgealist->list[0];
791 strcpy(pgea->szName, LONGNAME);
792 pgea->cbName = strlen(pgea->szName);
793 pgea->oNextEntryOffset = 0;
794 pgealist->cbList = (sizeof(GEA2LIST) + pgea->cbName);
795 pfealist = xmallocz(1532, pszSrcFile, __LINE__);
796 if (pfealist) {
797 pfealist->cbList = 1024;
798 eaop.fpGEA2List = pgealist;
799 eaop.fpFEA2List = pfealist;
800 eaop.oError = 0;
801 rc = DosQueryPathInfo(pci->pszFileName, FIL_QUERYEASFROMLIST,
802 (PVOID) & eaop, (ULONG) sizeof(EAOP2));
803 if (!rc) {
804 pfea = &eaop.fpFEA2List->list[0];
805 value = pfea->szName + pfea->cbName + 1; // Point at EA value
806 value[pfea->cbValue] = 0; // Terminate
807 if (*(USHORT *) value == EAT_ASCII) {
808 p = value + sizeof(USHORT) * 2; // Point at value string
809 pci->pszLongName = xstrdup(p, pszSrcFile, __LINE__);
810 }
811 }
812 free(pfealist);
813 }
814 free(pgealist);
815 }
816 }
817 if (!pci->pszLongName)
818 pci->pszLongName = NullStr;
819
820 if (fForceUpper)
821 strupr(pci->pszFileName);
822 else if (fForceLower)
823 strlwr(pci->pszFileName);
824
825 if (pfsa4->attrFile & FILE_DIRECTORY) {
826 if (fNoIconsDirs ||
827 (flags & DRIVE_NOLOADICONS) ||
828 !isalpha(*pci->pszFileName)) {
829 hptr = (HPOINTER) 0;
830 }
831 else
832 hptr = WinLoadFileIcon(pci->pszFileName, FALSE);
833 }
834 else {
835 if (fNoIconsFiles ||
836 (flags & DRIVE_NOLOADICONS) ||
837 !isalpha(*pci->pszFileName)) {
838 hptr = IDFile(pci->pszFileName);
839 }
840 else
841 hptr = WinLoadFileIcon(pci->pszFileName, FALSE);
842 }
843 if (!hptr) {
844 hptr = pfsa4->attrFile & FILE_DIRECTORY ?
845 hptrDir :
846 pfsa4->attrFile & FILE_SYSTEM ?
847 hptrSystem :
848 pfsa4->attrFile & FILE_HIDDEN ?
849 hptrHidden : pfsa4->attrFile & FILE_READONLY ? hptrReadonly : hptrFile;
850 }
851
852 // Tell container what part of pathname to display
853 if (partial) {
854 p = strrchr(pci->pszFileName, '\\');
855 if (!p) {
856 p = strrchr(pci->pszFileName, ':');
857 if (!p)
858 p = pci->pszFileName;
859 else
860 p++;
861 }
862 else if ((dcd && dcd->type == TREE_FRAME) ||
863 !(pfsa4->attrFile & FILE_DIRECTORY) || !*(p + 1))
864 p++;
865 if (!*p)
866 p = pci->pszFileName;
867 }
868 else
869 p = pci->pszFileName;
870 pci->pszDisplayName = p;
871
872 //comma format the file size for large file support
873 {
874 CHAR szBuf[30];
875 CommaFmtULL(szBuf, sizeof(szBuf), pfsa4->cbFile, ' ');
876 pci->pszFmtFileSize = xstrdup(szBuf, pszSrcFile, __LINE__);
877# ifdef FORTIFY
878 {
879 if (dcd && dcd->type == TREE_FRAME) {
880 // Will be freed in TreeCnrWndProc WM_DESTROY
881 // Fortify_SetOwner(pci->pszFmtFileSize, 1);
882 Fortify_SetScope(pci->pszFmtFileSize, 2);
883 }
884 }
885# endif
886 }
887 pci->date.day = pfsa4->fdateLastWrite.day;
888 pci->date.month = pfsa4->fdateLastWrite.month;
889 pci->date.year = pfsa4->fdateLastWrite.year + 1980;
890 pci->time.seconds = pfsa4->ftimeLastWrite.twosecs * 2;
891 pci->time.minutes = pfsa4->ftimeLastWrite.minutes;
892 pci->time.hours = pfsa4->ftimeLastWrite.hours;
893 pci->ladate.day = pfsa4->fdateLastAccess.day;
894 pci->ladate.month = pfsa4->fdateLastAccess.month;
895 pci->ladate.year = pfsa4->fdateLastAccess.year + 1980;
896 pci->latime.seconds = pfsa4->ftimeLastAccess.twosecs * 2;
897 pci->latime.minutes = pfsa4->ftimeLastAccess.minutes;
898 pci->latime.hours = pfsa4->ftimeLastAccess.hours;
899 pci->crdate.day = pfsa4->fdateCreation.day;
900 pci->crdate.month = pfsa4->fdateCreation.month;
901 pci->crdate.year = pfsa4->fdateCreation.year + 1980;
902 pci->crtime.seconds = pfsa4->ftimeCreation.twosecs * 2;
903 pci->crtime.minutes = pfsa4->ftimeCreation.minutes;
904 pci->crtime.hours = pfsa4->ftimeCreation.hours;
905 pci->easize = CBLIST_TO_EASIZE(pfsa4->cbList);
906 pci->cbFile = pfsa4->cbFile;
907 pci->attrFile = pfsa4->attrFile;
908 pci->pszDispAttr = FileAttrToString(pci->attrFile);
909 pci->rc.pszIcon = pci->pszDisplayName;
910 pci->rc.hptrIcon = hptr;
911
912 if (dcd &&
913 (*dcd->mask.szMask || dcd->mask.antiattr ||
914 ((dcd->mask.attrFile &
915 (FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY | FILE_ARCHIVED)) !=
916 (FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY | FILE_ARCHIVED)))) {
917 if (*dcd->mask.szMask || dcd->mask.antiattr) {
918 if (!Filter((PMINIRECORDCORE) pci, (PVOID) & dcd->mask))
919 pci->rc.flRecordAttr |= CRA_FILTERED;
920 }
921 else if ((!(dcd->mask.attrFile & FILE_HIDDEN) &&
922 (pci->attrFile & FILE_HIDDEN)) ||
923 (!(dcd->mask.attrFile & FILE_SYSTEM) &&
924 (pci->attrFile & FILE_SYSTEM)) ||
925 (!(dcd->mask.attrFile & FILE_READONLY) &&
926 (pci->attrFile & FILE_READONLY)) ||
927 (!(dcd->mask.attrFile & FILE_ARCHIVED) &&
928 (pci->attrFile & FILE_ARCHIVED)))
929 pci->rc.flRecordAttr |= CRA_FILTERED;
930 }
931
932 return pfsa4->cbFile + pci->easize;
933
934} // FillInRecordFromFSA
935
936VOID ProcessDirectory(const HWND hwndCnr,
937 const PCNRITEM pciParent,
938 const CHAR *szDirBase,
939 const BOOL filestoo,
940 const BOOL recurse,
941 const BOOL partial,
942 CHAR *stopflag,
943 DIRCNRDATA *dcd, // Optional
944 ULONG *pulTotalFiles, // Optional
945 PULONGLONG pullTotalBytes) // Optional
946{
947 /* put all the directories (and files if filestoo is TRUE) from a
948 * directory into the container. recurse through subdirectories if
949 * recurse is TRUE.
950 */
951
952 PSZ pszFileSpec;
953 INT t;
954 PFILEFINDBUF4L paffbFound;
955 PFILEFINDBUF4L *papffbSelected;
956 PFILEFINDBUF4L pffbFile;
957 PFILEFINDBUF4L paffbTotal = NULL;
958 PFILEFINDBUF4L paffbTemp;
959 HDIR hdir = HDIR_CREATE;
960 ULONG ulFindCnt;
961 ULONG ulFindMax;
962 ULONG ulSelCnt;
963 ULONG ulTotal = 0;
964 ULONGLONG ullBytes;
965 ULONGLONG ullTotalBytes;
966 ULONG ulReturnFiles = 0;
967 ULONGLONG ullReturnBytes = 0;
968 PCH pchEndPath;
969 APIRET rc;
970 PCNRITEM pci;
971 PCNRITEM pciFirst;
972 RECORDINSERT ri;
973 BOOL ok = TRUE;
974 ULONG ulBufBytes;
975 ULONG x;
976
977 if (isalpha(*szDirBase) && szDirBase[1] == ':' && szDirBase[2] == '\\') {
978 if ((driveflags[toupper(*szDirBase) - 'A'] & DRIVE_REMOTE) && fRemoteBug)
979 ulFindMax = 1; // file system gets confused
980 else if (driveflags[toupper(*szDirBase) - 'A'] & DRIVE_ZIPSTREAM)
981 ulFindMax = min(FilesToGet, 225); // anything more is wasted
982 else
983 ulFindMax = FilesToGet; // full-out
984 }
985 else
986 ulFindMax = FilesToGet;
987
988 if (OS2ver[0] == 20 && OS2ver[1] < 30)
989 ulFindMax = min(ulFindMax, (65535 / sizeof(FILEFINDBUF4L)));
990
991 ulBufBytes = ulFindMax * sizeof(FILEFINDBUF4L);
992
993 pszFileSpec = xmalloc(CCHMAXPATH + 2, pszSrcFile, __LINE__);
994 paffbFound = xmalloc(ulBufBytes, pszSrcFile, __LINE__);
995 papffbSelected = xmalloc(sizeof(PFILEFINDBUF4L) * ulFindMax, pszSrcFile, __LINE__);
996
997 if (paffbFound && papffbSelected && pszFileSpec) {
998 t = strlen(szDirBase);
999 memcpy(pszFileSpec, szDirBase, t + 1);
1000 pchEndPath = pszFileSpec + t;
1001 if (*(pchEndPath - 1) != '\\') {
1002 memcpy(pchEndPath, "\\", 2);
1003 pchEndPath++;
1004 }
1005 memcpy(pchEndPath, "*", 2);
1006 DosError(FERR_DISABLEHARDERR);
1007 ulFindCnt = ulFindMax;
1008 rc = xDosFindFirst(pszFileSpec,
1009 &hdir,
1010 FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED |
1011 FILE_SYSTEM | FILE_HIDDEN |
1012 (filestoo ? FILE_DIRECTORY : MUST_HAVE_DIRECTORY),
1013 paffbFound,
1014 ulBufBytes,
1015 &ulFindCnt,
1016 FIL_QUERYEASIZEL);
1017 priority_normal();
1018 *pchEndPath = 0; // Chop off wildcard
1019 if (!rc) {
1020 do {
1021 /*
1022 * remove . and .. from list if present
1023 * also counter file system bugs that sometimes
1024 * allows normal files to slip through when
1025 * only directories should appear (only a few
1026 * network file systems exhibit such a problem).
1027 */
1028
1029 if (stopflag && *stopflag)
1030 goto Abort;
1031 pffbFile = paffbFound;
1032 ulSelCnt = 0;
1033 for (;;) {
1034 if (!*pffbFile->achName ||
1035 (!filestoo && ~pffbFile->attrFile & FILE_DIRECTORY) ||
1036 (pffbFile->attrFile & FILE_DIRECTORY &&
1037 pffbFile->achName[0] == '.' &&
1038 (!pffbFile->achName[1] ||
1039 (pffbFile->achName[1] == '.' && !pffbFile->achName[2])))) {
1040 // ulFindCnt--; // Got . or .. or file to be skipped
1041 }
1042 else
1043 papffbSelected[ulSelCnt++] = pffbFile; // Remember selected file
1044 if (!pffbFile->oNextEntryOffset) {
1045 // ulFindCnt = ulSelCnt; // Remember number selected
1046 break;
1047 }
1048 pffbFile = (PFILEFINDBUF4L)((PBYTE)pffbFile + pffbFile->oNextEntryOffset);
1049 } // for
1050 if (ulSelCnt) {
1051 // One or more entries selected
1052 if (stopflag && *stopflag)
1053 goto Abort;
1054 if (fSyncUpdates) {
1055 pciFirst = WinSendMsg(hwndCnr, CM_ALLOCRECORD,
1056 MPFROMLONG(EXTRA_RECORD_BYTES),
1057 MPFROMLONG(ulSelCnt));
1058 if (!pciFirst) {
1059 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1060 GetPString(IDS_CMALLOCRECERRTEXT));
1061 ok = FALSE;
1062 ullTotalBytes = 0;
1063 }
1064 else {
1065 // 04 Jan 08 SHL fixme like comp.c to handle less than ulSelCnt records
1066 pci = pciFirst;
1067 ullTotalBytes = 0;
1068 // Insert selected in container
1069 for (x = 0; x < ulSelCnt; x++) {
1070 pffbFile = papffbSelected[x];
1071 ullBytes = FillInRecordFromFFB(hwndCnr, pci, pszFileSpec,
1072 pffbFile, partial, dcd);
1073 pci = (PCNRITEM) pci->rc.preccNextRecord;
1074 ullTotalBytes += ullBytes;
1075 } // for
1076 memset(&ri, 0, sizeof(RECORDINSERT));
1077 ri.cb = sizeof(RECORDINSERT);
1078 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1079 ri.pRecordParent = (PRECORDCORE) pciParent;
1080 ri.zOrder = (ULONG) CMA_TOP;
1081 ri.cRecordsInsert = ulSelCnt;
1082 ri.fInvalidateRecord = TRUE;
1083 // !fSyncUpdates && dcd && dcd->type == DIR_FRAME ? FALSE : TRUE; //fSyncUpdates always TRUE 12-1-08 GKY
1084 if (!WinSendMsg(hwndCnr,
1085 CM_INSERTRECORD,
1086 MPFROMP(pciFirst), MPFROMP(&ri))) {
1087 DosSleep(10); // Give GUI time to work
1088 WinSetFocus(HWND_DESKTOP, hwndCnr);
1089 if (!WinSendMsg(hwndCnr,
1090 CM_INSERTRECORD,
1091 MPFROMP(pciFirst), MPFROMP(&ri))) {
1092 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1093 GetPString(IDS_CMINSERTERRTEXT));
1094 ok = FALSE;
1095 ullTotalBytes = 0;
1096 if (WinIsWindow((HAB) 0, hwndCnr))
1097 FreeCnrItemList(hwndCnr, pciFirst);
1098 }
1099 // }
1100 }
1101 }
1102 if (ok) {
1103 ullReturnBytes += ullTotalBytes;
1104 ulReturnFiles += ulSelCnt;
1105 }
1106 } // if sync updates
1107 else {
1108 // Append newly selected entries to aggregate list
1109 paffbTemp = xrealloc(paffbTotal,
1110 sizeof(FILEFINDBUF4L) * (ulSelCnt + ulTotal),
1111 pszSrcFile, __LINE__);
1112 if (paffbTemp) {
1113 // 13 Aug 07 SHL fixme to optimize copy
1114 paffbTotal = paffbTemp;
1115 for (x = 0; x < ulSelCnt; x++)
1116 paffbTotal[x + ulTotal] = *papffbSelected[x];
1117 ulTotal += ulSelCnt;
1118 }
1119 else {
1120 saymsg(MB_ENTER,
1121 HWND_DESKTOP,
1122 GetPString(IDS_ERRORTEXT), GetPString(IDS_OUTOFMEMORY));
1123 break;
1124 }
1125 }
1126 } // if entries selected
1127 if (stopflag && *stopflag)
1128 goto Abort;
1129 DosError(FERR_DISABLEHARDERR);
1130 ulFindCnt = ulFindMax;
1131 rc = xDosFindNext(hdir, paffbFound, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZEL);
1132 priority_normal();
1133 if (rc)
1134 DosError(FERR_DISABLEHARDERR);
1135 } while (!rc);
1136
1137 DosFindClose(hdir);
1138 xfree(paffbFound, pszSrcFile, __LINE__);
1139 paffbFound = NULL;
1140 xfree(papffbSelected, pszSrcFile, __LINE__);
1141 papffbSelected = NULL;
1142
1143 if (ulTotal && paffbTotal) {
1144
1145 if (stopflag && *stopflag)
1146 goto Abort;
1147
1148 pciFirst = WinSendMsg(hwndCnr, CM_ALLOCRECORD,
1149 MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(ulTotal));
1150 if (!pciFirst) {
1151 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1152 GetPString(IDS_CMALLOCRECERRTEXT));
1153 ok = FALSE;
1154 ullTotalBytes = 0;
1155 }
1156 else {
1157 // 04 Jan 08 SHL fixme like comp.c to handle less than ulSelCnt records
1158 pci = pciFirst;
1159 ullTotalBytes = 0;
1160 pffbFile = paffbTotal;
1161 for (x = 0; x < ulTotal; x++) {
1162 ullBytes = FillInRecordFromFFB(hwndCnr, pci, pszFileSpec,
1163 pffbFile, partial, dcd);
1164 pci = (PCNRITEM) pci->rc.preccNextRecord;
1165 ullTotalBytes += ullBytes;
1166 // Can not use offset since we have merged lists - this should be equivalent
1167 pffbFile = (PFILEFINDBUF4L)((PBYTE)pffbFile + sizeof(FILEFINDBUF4L));
1168 }
1169 if (ulTotal) {
1170 memset(&ri, 0, sizeof(RECORDINSERT));
1171 ri.cb = sizeof(RECORDINSERT);
1172 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1173 ri.pRecordParent = (PRECORDCORE) pciParent;
1174 ri.zOrder = (ULONG) CMA_TOP;
1175 ri.cRecordsInsert = ulTotal;
1176 ri.fInvalidateRecord = (!fSyncUpdates && dcd &&
1177 dcd->type == DIR_FRAME) ? FALSE : TRUE;
1178 if (!WinSendMsg(hwndCnr, CM_INSERTRECORD,
1179 MPFROMP(pciFirst), MPFROMP(&ri))) {
1180 DosSleep(10); // Give GUI time to work
1181 WinSetFocus(HWND_DESKTOP, hwndCnr);
1182 if (!WinSendMsg(hwndCnr, CM_INSERTRECORD,
1183 MPFROMP(pciFirst), MPFROMP(&ri))) {
1184 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1185 GetPString(IDS_CMINSERTERRTEXT));
1186 ok = FALSE;
1187 ullTotalBytes = 0;
1188 if (WinIsWindow((HAB) 0, hwndCnr))
1189 FreeCnrItemList(hwndCnr, pciFirst);
1190 }
1191 }
1192 }
1193 }
1194 if (ok) {
1195 ullReturnBytes += ullTotalBytes;
1196 ulReturnFiles += ulFindCnt;
1197 }
1198 }
1199 }
1200
1201 /**
1202 * DosFind for subdirectories of a read-only directory on a FAT volume
1203 * returns path not found if there are no subdirectories
1204 * FAT FS seems to ignore . and .. in this case
1205 * Map to no more files
1206 * We could verify that directory is marked read-only, it's probably not
1207 * worth the extra code since we do verify 2 out of 3 prerequisites
1208 * 15 Jan 08 SHL
1209 */
1210 if (rc == ERROR_PATH_NOT_FOUND && !filestoo) {
1211 ULONG ulDriveType = 0;
1212 CHAR szFSType[CCHMAXPATH];
1213 INT removable = CheckDrive(*pszFileSpec, szFSType, &ulDriveType);
1214 if (removable != -1 && strcmp(szFSType, "FAT") == 0)
1215 rc = ERROR_NO_MORE_FILES;
1216 }
1217
1218 if (rc && rc != ERROR_NO_MORE_FILES) {
1219 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
1220 GetPString(IDS_CANTFINDDIRTEXT), pszFileSpec);
1221 }
1222
1223 if (!fSyncUpdates && dcd && dcd->type == DIR_FRAME)
1224 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPVOID,
1225 MPFROM2SHORT(0, CMA_ERASE));
1226 }
1227Abort:
1228 xfree(paffbTotal, pszSrcFile, __LINE__);
1229 xfree(pszFileSpec, pszSrcFile, __LINE__);
1230 xfree(paffbFound, pszSrcFile, __LINE__);
1231 xfree(papffbSelected, pszSrcFile, __LINE__);
1232
1233 if (recurse) {
1234 pci = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pciParent),
1235 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
1236 while (pci && (INT)pci != -1) {
1237 if ((pci->attrFile & FILE_DIRECTORY))
1238 if (fInitialDriveScan)
1239 Stubby(hwndCnr, pci);
1240 else {
1241 while (StubbyScanCount != 0)
1242 DosSleep(50);
1243 Stubby(hwndCnr, pci);
1244 }
1245 //Stubby(hwndCnr, pci);
1246 pci = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
1247 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1248 }
1249 }
1250
1251 if (pulTotalFiles)
1252 *pulTotalFiles = ulReturnFiles;
1253
1254 if (pullTotalBytes)
1255 *pullTotalBytes = ullReturnBytes;
1256
1257} // ProcessDirectory
1258
1259VOID FillDirCnr(HWND hwndCnr,
1260 CHAR * pszDirectory,
1261 DIRCNRDATA * dcd,
1262 PULONGLONG pullTotalBytes)
1263{
1264 ProcessDirectory(hwndCnr,
1265 (PCNRITEM)NULL,
1266 pszDirectory,
1267 TRUE, // filestoo
1268 FALSE, // recurse
1269 TRUE, // partial
1270 dcd ? &dcd->stopflag : NULL,
1271 dcd,
1272 NULL, // total files
1273 pullTotalBytes);
1274 DosPostEventSem(CompactSem);
1275
1276#if 0 // fixme to be gone or to be configurable
1277 {
1278 int state = _heapchk();
1279 if (state != _HEAPOK)
1280 Runtime_Error(pszSrcFile, __LINE__, "heap corrupted %d", state);
1281 else
1282 DbgMsg(pszSrcFile, __LINE__, "_memavl %u", _memavl());
1283 }
1284#endif
1285
1286} // FillDirCnr
1287
1288VOID FillTreeCnr(HWND hwndCnr, HWND hwndParent)
1289{
1290 ULONG ulCurDriveNum, ulDriveMap, numtoinsert = 0;
1291 ULONG ulDriveType;
1292 PCNRITEM pci, pciFirst = NULL, pciNext, pciParent = NULL;
1293 INT x, removable;
1294 CHAR suggest[32];
1295 CHAR szDrive[] = " :\\";
1296 CHAR szFSType[CCHMAXPATH];
1297 FILESTATUS4L fsa4;
1298 APIRET rc;
1299 BOOL drivesbuilt = FALSE;
1300 ULONG startdrive = 3;
1301 static BOOL didonce = FALSE;
1302
1303 fDummy = TRUE;
1304 *suggest = 0;
1305 for (x = 0; x < 26; x++) {
1306 driveflags[x] &= (DRIVE_IGNORE | DRIVE_NOPRESCAN | DRIVE_NOLOADICONS |
1307 DRIVE_NOLOADSUBJS | DRIVE_NOLOADLONGS |
1308 DRIVE_INCLUDEFILES | DRIVE_SLOW | DRIVE_NOSTATS |
1309 DRIVE_WRITEVERIFYOFF);
1310 }
1311 memset(driveserial, -1, sizeof(driveserial));
1312
1313 DosError(FERR_DISABLEHARDERR);
1314 if (!DosQuerySysInfo(QSV_BOOT_DRIVE,
1315 QSV_BOOT_DRIVE,
1316 (PVOID) &startdrive,
1317 (ULONG) sizeof(ULONG)) &&
1318 startdrive)
1319 {
1320 driveflags[startdrive - 1] |= DRIVE_BOOT;
1321 }
1322
1323 DosError(FERR_DISABLEHARDERR);
1324 rc = DosQCurDisk(&ulCurDriveNum, &ulDriveMap);
1325 if (rc) {
1326 Dos_Error(MB_CANCEL,
1327 rc,
1328 HWND_DESKTOP,
1329 pszSrcFile, __LINE__, PCSZ_FILLDIRQCURERRTEXT);
1330 exit(0);
1331 }
1332
1333 // Calc number of drive items to create
1334 for (x = 0; x < 26; x++) {
1335 if ((ulDriveMap & (1L << x)) && !(driveflags[x] & DRIVE_IGNORE))
1336 numtoinsert++;
1337 }
1338
1339 if (numtoinsert) {
1340 pciFirst = WinSendMsg(hwndCnr,
1341 CM_ALLOCRECORD,
1342 MPFROMLONG(EXTRA_RECORD_BYTES),
1343 MPFROMLONG((ULONG) numtoinsert));
1344 }
1345
1346 if (!pciFirst) {
1347 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__, GetPString(IDS_CMALLOCRECERRTEXT));
1348 // 04 Jan 08 SHL fixme not just up and die
1349 exit(0);
1350 }
1351
1352 // 04 Jan 08 SHL fixme like comp.c to handle less than ulSelCnt records
1353 pci = pciFirst;
1354 for (x = 0; x < 26; x++) {
1355 if ((ulDriveMap & (1L << x)) && !(driveflags[x] & DRIVE_IGNORE)) {
1356
1357 CHAR s[80];
1358 ULONG flags = 0;
1359 ULONG size = sizeof(ULONG);
1360
1361 *szDrive = (CHAR)x + 'A'; // Build path spec
1362
1363 sprintf(s, "%c.DriveFlags", toupper(*szDrive));
1364 if (PrfQueryProfileData(fmprof, appname, s, &flags, &size)) {
1365 driveflags[toupper(*szDrive) - 'A'] |= flags;
1366 }
1367
1368 if (x > 1) {
1369 // Hard drive (2..N)
1370 if (!(driveflags[x] & DRIVE_NOPRESCAN)) {
1371 *szFSType = 0;
1372 ulDriveType = 0;
1373 removable = CheckDrive(*szDrive, szFSType, &ulDriveType);
1374 driveserial[x] = -1;
1375 if (removable != -1) {
1376 struct {
1377 ULONG serial;
1378 CHAR volumelength;
1379 CHAR volumelabel[CCHMAXPATH];
1380 } volser;
1381
1382 DosError(FERR_DISABLEHARDERR);
1383 if (!DosQueryFSInfo((ULONG) x,
1384 FSIL_VOLSER, &volser, sizeof(volser))) {
1385 driveserial[x] = volser.serial;
1386 }
1387 }
1388 else
1389 driveflags[x] |= DRIVE_INVALID;
1390
1391 memset(&fsa4, 0, sizeof(FILESTATUS4L));
1392 driveflags[x] |= removable == -1 || removable == 1 ?
1393 DRIVE_REMOVABLE : 0;
1394 if (ulDriveType & DRIVE_REMOTE)
1395 driveflags[x] |= DRIVE_REMOTE;
1396 if (!stricmp(szFSType,RAMFS)) {
1397 driveflags[x] |= DRIVE_RAMDISK;
1398 driveflags[x] &= ~DRIVE_REMOTE;
1399 }
1400 if (!stricmp(szFSType,NDFS32)) {
1401 driveflags[x] |= DRIVE_VIRTUAL;
1402 driveflags[x] &= ~DRIVE_REMOTE;
1403 }
1404 if (!stricmp(szFSType,NTFS))
1405 driveflags[x] |= DRIVE_NOTWRITEABLE;
1406 if (strcmp(szFSType, HPFS) &&
1407 strcmp(szFSType, JFS) &&
1408 strcmp(szFSType, ISOFS) &&
1409 strcmp(szFSType, CDFS) &&
1410 strcmp(szFSType, FAT32) &&
1411 strcmp(szFSType, NDFS32) &&
1412 strcmp(szFSType, RAMFS) &&
1413 strcmp(szFSType, NTFS) &&
1414 strcmp(szFSType, HPFS386)) {
1415 driveflags[x] |= DRIVE_NOLONGNAMES;
1416 }
1417
1418 if (!strcmp(szFSType, CDFS) || !strcmp(szFSType,ISOFS)) {
1419 removable = 1;
1420 driveflags[x] |= DRIVE_REMOVABLE | DRIVE_NOTWRITEABLE | DRIVE_CDROM;
1421 }
1422 if (!stricmp(szFSType, CBSIFS)) {
1423 driveflags[x] |= DRIVE_ZIPSTREAM;
1424 driveflags[x] &= ~DRIVE_REMOTE;
1425 if (ulDriveType & DRIVE_REMOVABLE)
1426 driveflags[x] |= DRIVE_REMOVABLE;
1427 if (!(ulDriveType & DRIVE_NOLONGNAMES))
1428 driveflags[x] &= ~DRIVE_NOLONGNAMES;
1429 }
1430 if (!fVerifyOffChecked[x]) {
1431 if (driveflags[x] & DRIVE_REMOVABLE)
1432 driveflags[x] |= DRIVE_WRITEVERIFYOFF;
1433 if (!(driveflags[x] & DRIVE_INVALID)) {
1434 CHAR Key[80];
1435
1436 sprintf(Key, "%c.VerifyOffChecked", (CHAR) (x + 'A'));
1437 fVerifyOffChecked[x] = TRUE;
1438 PrfWriteProfileData(fmprof, appname, Key, &fVerifyOffChecked[x], sizeof(BOOL));
1439 }
1440 }
1441 pci->rc.flRecordAttr |= CRA_RECORDREADONLY;
1442 if ((ULONG)(toupper(*szDrive) - '@') == ulCurDriveNum)
1443 pci->rc.flRecordAttr |= (CRA_CURSORED | CRA_SELECTED);
1444
1445 if (removable == 0) {
1446 // Fixed volume
1447 pci->attrFile |= FILE_DIRECTORY;
1448 DosError(FERR_DISABLEHARDERR);
1449 rc = DosQueryPathInfo(szDrive,
1450 FIL_QUERYEASIZEL,
1451 &fsa4, (ULONG) sizeof(FILESTATUS4L));
1452 // ERROR_BAD_NET_RSP = 58
1453 if (rc == 58) {
1454 DosError(FERR_DISABLEHARDERR);
1455 rc = DosQueryPathInfo(szDrive,
1456 FIL_STANDARDL,
1457 &fsa4, (ULONG) sizeof(FILESTATUS4L));
1458 fsa4.cbList = 0;
1459 }
1460 if (rc && !didonce) {
1461 // Guess drive letter
1462 if (!*suggest) {
1463 *suggest = '/';
1464 suggest[1] = 0;
1465 }
1466 sprintf(suggest + strlen(suggest), "%c" , toupper(*szDrive));
1467 pci->pszFileName = xstrdup(szDrive, pszSrcFile, __LINE__);
1468 pci->pszDisplayName = pci->pszFileName;
1469 pci->rc.pszIcon = pci->pszDisplayName;
1470 pci->attrFile = FILE_DIRECTORY;
1471 pci->pszDispAttr = FileAttrToString(pci->attrFile);
1472 driveserial[x] = -1;
1473 }
1474 else
1475 FillInRecordFromFSA(hwndCnr, pci, szDrive, &fsa4, TRUE, NULL);
1476 }
1477 else {
1478 // Removable volume
1479 pci->pszFileName = xstrdup(szDrive, pszSrcFile, __LINE__);
1480 pci->pszDisplayName = pci->pszFileName;
1481 pci->rc.pszIcon = pci->pszDisplayName;
1482 pci->attrFile = FILE_DIRECTORY;
1483 pci->pszDispAttr = FileAttrToString(pci->attrFile);
1484 }
1485 SelectDriveIcon(pci);
1486# ifdef FORTIFY
1487 // Will be freed by TreeCnrWndProc WM_DESTROY
1488 Fortify_SetScope(pci->pszFileName, 2);
1489# endif
1490 }
1491 else {
1492 pci->rc.hptrIcon = hptrDunno;
1493 pci->pszFileName = xstrdup(szDrive, pszSrcFile, __LINE__);
1494# ifdef FORTIFY
1495 // Will be freed by TreeCnrWndProc WM_DESTROY
1496 Fortify_SetScope(pci->pszFileName, 2);
1497# endif
1498 pci->pszDisplayName = pci->pszFileName;
1499 pci->rc.pszIcon = pci->pszFileName;
1500 pci->attrFile = FILE_DIRECTORY;
1501 pci->pszDispAttr = FileAttrToString(pci->attrFile);
1502 driveserial[x] = -1;
1503 }
1504 }
1505 else {
1506 // diskette drive (A or B)
1507 pci->rc.hptrIcon = hptrFloppy;
1508 pci->pszFileName = xstrdup(szDrive, pszSrcFile, __LINE__);
1509 pci->pszDisplayName = pci->pszFileName;
1510 pci->rc.pszIcon = pci->pszDisplayName;
1511 pci->attrFile = FILE_DIRECTORY;
1512 pci->pszDispAttr = FileAttrToString(pci->attrFile);
1513 driveflags[x] |= (DRIVE_REMOVABLE | DRIVE_NOLONGNAMES);
1514 driveserial[x] = -1;
1515 }
1516 pci->rc.flRecordAttr |= CRA_RECORDREADONLY;
1517 pci = (PCNRITEM) pci->rc.preccNextRecord; // next rec
1518 }
1519 else if (!(ulDriveMap & (1L << x)))
1520 driveflags[x] |= DRIVE_INVALID;
1521 } // for drives
1522
1523 PostMsg(hwndMain, UM_BUILDDRIVEBAR, MPVOID, MPVOID);
1524 drivesbuilt = TRUE;
1525
1526 // insert the drives
1527 if (numtoinsert && pciFirst) {
1528 RECORDINSERT ri;
1529
1530 memset(&ri, 0, sizeof(RECORDINSERT));
1531 ri.cb = sizeof(RECORDINSERT);
1532 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1533 ri.pRecordParent = (PRECORDCORE) NULL;
1534 ri.zOrder = (ULONG) CMA_TOP;
1535 ri.cRecordsInsert = numtoinsert;
1536 ri.fInvalidateRecord = FALSE;
1537 if (!WinSendMsg(hwndCnr,
1538 CM_INSERTRECORD, MPFROMP(pciFirst), MPFROMP(&ri)))
1539 {
1540 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1541 GetPString(IDS_CMINSERTERRTEXT));
1542 }
1543 }
1544
1545 // move cursor onto the default drive rather than the first drive
1546 if (!fSwitchTree) {
1547 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1548 CM_QUERYRECORD,
1549 MPVOID,
1550 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
1551 while (pci && (INT)pci != -1) {
1552 if ((ULONG) (toupper(*pci->pszFileName) - '@') == ulCurDriveNum) {
1553 WinSendMsg(hwndCnr,
1554 CM_SETRECORDEMPHASIS,
1555 MPFROMP(pci), MPFROM2SHORT(TRUE, CRA_CURSORED));
1556 break;
1557 }
1558 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1559 CM_QUERYRECORD,
1560 MPFROMP(pci),
1561 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1562 }
1563 }
1564
1565 if (hwndParent) {
1566 WinSendMsg(WinWindowFromID(WinQueryWindow(hwndParent, QW_PARENT),
1567 MAIN_DRIVELIST),
1568 LM_DELETEALL, MPVOID, MPVOID);
1569 }
1570
1571 if (fShowEnv) {
1572 RECORDINSERT ri;
1573
1574 pciParent = WinSendMsg(hwndCnr,
1575 CM_ALLOCRECORD,
1576 MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(1));
1577 if (pciParent) {
1578 pciParent->flags |= RECFLAGS_ENV;
1579 pciParent->pszFileName = xstrdup(GetPString(IDS_ENVVARSTEXT), pszSrcFile, __LINE__);
1580 pciParent->pszDisplayName = pciParent->pszFileName; // 03 Aug 07 SHL
1581 pciParent->rc.hptrIcon = hptrEnv;
1582 pciParent->rc.pszIcon = pciParent->pszFileName;
1583 pciParent->pszDispAttr = FileAttrToString(0);
1584 memset(&ri, 0, sizeof(RECORDINSERT));
1585 ri.cb = sizeof(RECORDINSERT);
1586 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1587 ri.pRecordParent = (PRECORDCORE) NULL;
1588 ri.zOrder = (ULONG) CMA_TOP;
1589 ri.cRecordsInsert = 1;
1590 ri.fInvalidateRecord = FALSE;
1591 if (WinSendMsg(hwndCnr,
1592 CM_INSERTRECORD, MPFROMP(pciParent), MPFROMP(&ri))) {
1593
1594 char *p, *pp;
1595
1596 p = pszTreeEnvVarList;
1597 while (*p == ';')
1598 p++;
1599 while (*p) {
1600 *szFSType = 0;
1601 pp = szFSType;
1602 while (*p && *p != ';')
1603 *pp++ = *p++;
1604 *pp = 0;
1605 while (*p == ';')
1606 p++;
1607 if (*szFSType &&
1608 (!stricmp(szFSType, "LIBPATH") || getenv(szFSType))) {
1609 pci = WinSendMsg(hwndCnr,
1610 CM_ALLOCRECORD,
1611 MPFROMLONG(EXTRA_RECORD_BYTES),
1612 MPFROMLONG(1));
1613 if (pci) {
1614 CHAR fname[CCHMAXPATH];
1615 pci->flags |= RECFLAGS_ENV;
1616 sprintf(fname, "%%%s%%", szFSType);
1617 pci->pszFileName = xstrdup(fname, pszSrcFile, __LINE__);
1618 pci->rc.hptrIcon = hptrEnv;
1619 pci->rc.pszIcon = pci->pszFileName;
1620 pci->pszDispAttr = FileAttrToString(0);
1621 memset(&ri, 0, sizeof(RECORDINSERT));
1622 ri.cb = sizeof(RECORDINSERT);
1623 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1624 ri.pRecordParent = (PRECORDCORE) pciParent;
1625 ri.zOrder = (ULONG) CMA_TOP;
1626 ri.cRecordsInsert = 1;
1627 ri.fInvalidateRecord = FALSE;
1628 if (!WinSendMsg(hwndCnr,
1629 CM_INSERTRECORD,
1630 MPFROMP(pci), MPFROMP(&ri))) {
1631 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1632 GetPString(IDS_CMINSERTERRTEXT));
1633 FreeCnrItem(hwndCnr, pci);
1634 }
1635 }
1636 }
1637 }
1638 WinSendMsg(hwndCnr,
1639 CM_INVALIDATERECORD,
1640 MPFROMP(&pciParent),
1641 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
1642 }
1643 else
1644 FreeCnrItem(hwndCnr, pciParent);
1645 }
1646 } // if show env
1647 {
1648 STUBBYSCAN *stubbyScan;
1649 HWND hwndDrivesList = WinWindowFromID(WinQueryWindow(hwndParent, QW_PARENT),
1650 MAIN_DRIVELIST);
1651
1652 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1653 CM_QUERYRECORD,
1654 MPVOID,
1655 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
1656 StubbyScanCount ++;
1657 while (pci && (INT)pci != -1) {
1658 stubbyScan = xmallocz(sizeof(STUBBYSCAN), pszSrcFile, __LINE__);
1659 if (!stubbyScan)
1660 break;
1661 stubbyScan->pci = pci;
1662 stubbyScan->hwndCnr = hwndCnr;
1663 stubbyScan->hwndDrivesList = hwndDrivesList;
1664 stubbyScan->RamDrive = FALSE;
1665 pciNext = (PCNRITEM) WinSendMsg(hwndCnr,
1666 CM_QUERYRECORD,
1667 MPFROMP(pci),
1668 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1669 if (~pci->flags & RECFLAGS_ENV) {
1670 ULONG drvNum = toupper(*pci->pszFileName) - 'A'; // 0..25
1671 if (drvNum == ulCurDriveNum || drvNum >= 2) {
1672 ULONG flags = driveflags[drvNum]; // Speed up
1673 if (~flags & DRIVE_INVALID &&
1674 ~flags & DRIVE_NOPRESCAN &&
1675 (!fNoRemovableScan || ~flags & DRIVE_REMOVABLE) && !fDrivetoSkip[drvNum])
1676 {
1677 if (DRIVE_RAMDISK)
1678 stubbyScan->RamDrive = TRUE;
1679 if (xbeginthread(StubbyScanThread,
1680 65536,
1681 stubbyScan,
1682 pszSrcFile,
1683 __LINE__) == -1)
1684 {
1685 xfree(stubbyScan, pszSrcFile, __LINE__);
1686 }
1687 } // if drive for scanning
1688 else
1689 WinSendMsg(hwndDrivesList,
1690 LM_INSERTITEM,
1691 MPFROM2SHORT(LIT_SORTASCENDING, 0),
1692 MPFROMP(pci->pszFileName));
1693 }
1694 else {
1695 WinSendMsg(hwndCnr,
1696 CM_INVALIDATERECORD,
1697 MPFROMP(&pci),
1698 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
1699 WinSendMsg(hwndDrivesList,
1700 LM_INSERTITEM,
1701 MPFROM2SHORT(LIT_SORTASCENDING, 0),
1702 MPFROMP(pci->pszFileName));
1703 }
1704 fDrivetoSkip[drvNum] = FALSE;
1705 }
1706 pci = pciNext;
1707 } // while
1708 StubbyScanCount--;
1709 }
1710 if (hwndParent)
1711 WinSendMsg(WinWindowFromID(WinQueryWindow(hwndParent, QW_PARENT),
1712 MAIN_DRIVELIST), LM_SELECTITEM,
1713 MPFROM2SHORT(0, 0), MPFROMLONG(TRUE));
1714
1715 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1716 CM_QUERYRECORD,
1717 MPVOID,
1718 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
1719 while (pci && (INT)pci != -1) {
1720 pciNext = (PCNRITEM) WinSendMsg(hwndCnr,
1721 CM_QUERYRECORD,
1722 MPFROMP(pci),
1723 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1724 if (pci->flags & RECFLAGS_ENV) {
1725 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1726 CM_QUERYRECORD,
1727 MPFROMP(pci),
1728 MPFROM2SHORT(CMA_FIRSTCHILD,
1729 CMA_ITEMORDER));
1730 while (pci && (INT)pci != -1) {
1731 if (pci->flags & RECFLAGS_ENV)
1732 FleshEnv(hwndCnr, pci);
1733 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1734 CM_QUERYRECORD,
1735 MPFROMP(pci),
1736 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1737 }
1738 break;
1739 }
1740 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1741 CM_QUERYRECORD,
1742 MPFROMP(pci),
1743 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1744 }
1745
1746 if (!drivesbuilt && hwndMain)
1747 PostMsg(hwndMain, UM_BUILDDRIVEBAR, MPVOID, MPVOID);
1748 DosSleep(16); // 05 Aug 07 GKY 33
1749 fDummy = FALSE;
1750 DosPostEventSem(CompactSem);
1751
1752 {
1753 BYTE info;
1754 BOOL includesyours = FALSE;
1755
1756 // 10 Jan 08 SHL fixme to understand fFirstTime
1757 if (*suggest || (!(driveflags[1] & DRIVE_IGNORE) && fFirstTime)) {
1758 if (!DosDevConfig(&info, DEVINFO_FLOPPY) && info == 1) {
1759 if (!*suggest) {
1760 *suggest = '/';
1761 suggest[1] = 0;
1762 }
1763 else
1764 memmove(suggest + 2, suggest + 1, strlen(suggest));
1765 suggest[1] = 'B';
1766 }
1767 }
1768 if (*suggest) {
1769 for (x = 2; x < 26; x++) {
1770 if (driveflags[x] & DRIVE_IGNORE) {
1771 includesyours = TRUE;
1772 sprintf(suggest + strlen(suggest), "%c", (char)(x + 'A'));
1773 }
1774 }
1775 strcat(suggest, " %*");
1776 if (saymsg(MB_YESNO | MB_ICONEXCLAMATION,
1777 (hwndParent) ? hwndParent : hwndCnr,
1778 GetPString(IDS_SUGGESTTITLETEXT),
1779 GetPString(IDS_SUGGEST1TEXT),
1780 (includesyours) ? GetPString(IDS_SUGGEST2TEXT) : NullStr,
1781 suggest) == MBID_YES) {
1782 char s[64];
1783
1784 sprintf(s, "PARAMETERS=%s", suggest);
1785 WinCreateObject(WPProgram, "FM/2", s, FM3Folder, CO_UPDATEIFEXISTS);
1786 WinCreateObject(WPProgram,
1787 "FM/2 Lite", s, FM3Folder, CO_UPDATEIFEXISTS);
1788 WinCreateObject(WPProgram,
1789 "Archive Viewer/2", s, FM3Tools, CO_UPDATEIFEXISTS);
1790 WinCreateObject(WPProgram,
1791 "Dir Sizes", s, FM3Tools, CO_UPDATEIFEXISTS);
1792 WinCreateObject(WPProgram,
1793 "Visual Tree", s, FM3Tools, CO_UPDATEIFEXISTS);
1794 WinCreateObject(WPProgram,
1795 "Visual Directory", s, FM3Tools, CO_UPDATEIFEXISTS);
1796 WinCreateObject(WPProgram,
1797 "Global File Viewer", s, FM3Tools, CO_UPDATEIFEXISTS);
1798 WinCreateObject(WPProgram, "Databar", s, FM3Tools, CO_UPDATEIFEXISTS);
1799 }
1800 }
1801 }
1802 didonce = TRUE;
1803 if (fInitialDriveScan) {
1804 HWND hwndDrivesList = WinWindowFromID(WinQueryWindow(hwndParent, QW_PARENT),
1805 MAIN_DRIVELIST);
1806 while (StubbyScanCount != 0 || ProcessDirCount != 0)
1807 DosSleep(50);
1808 WinShowWindow(hwndCnr, TRUE);
1809 WinShowWindow(hwndDrivesList, TRUE);
1810 fInitialDriveScan = FALSE;
1811 }
1812} // FillTreeCnr
1813
1814
1815/**
1816 * Empty all records from a container and free associated storage and
1817 * Free up field infos
1818 */
1819
1820VOID EmptyCnr(HWND hwnd)
1821{
1822 PFIELDINFO pfi;
1823
1824#if 0 // fixme to be gone or to be configurable
1825 {
1826 int state = _heapchk();
1827 if (state != _HEAPOK)
1828 Runtime_Error(pszSrcFile, __LINE__, "heap corrupted %d", state);
1829 }
1830#endif
1831
1832 // Remove all records
1833 RemoveCnrItems(hwnd, NULL, 0, CMA_FREE);
1834
1835 // Remove field info descriptors
1836 pfi = (PFIELDINFO) WinSendMsg(hwnd, CM_QUERYDETAILFIELDINFO, MPVOID,
1837 MPFROMSHORT(CMA_FIRST));
1838 if (pfi &&
1839 (INT)WinSendMsg(hwnd, CM_REMOVEDETAILFIELDINFO, MPVOID,
1840 MPFROM2SHORT(0, CMA_FREE)) == -1) {
1841 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_REMOVEDETAILFIELDINFO hwnd %x", hwnd);
1842 }
1843}
1844
1845/**
1846 * Free storage associated with container item
1847 */
1848
1849VOID FreeCnrItemData(PCNRITEM pci)
1850{
1851 if (pci->pszSubject) {
1852 if (pci->pszSubject != NullStr)
1853 free(pci->pszSubject);
1854 pci->pszSubject = NULL; // Catch illegal references
1855 }
1856
1857 // 08 Sep 08 SHL Remove excess logic
1858 if (pci->pszLongName) {
1859 if (pci->pszLongName != NullStr)
1860 free(pci->pszLongName);
1861 pci->pszLongName = NULL; // Catch illegal references
1862 }
1863
1864 // Bypass free if pszDisplayName points into pszFileName buffer
1865 // 05 Sep 08 SHL Correct pointer overlap compare logic
1866 if (pci->pszDisplayName) {
1867 if (pci->pszDisplayName != NullStr) {
1868 if (!pci->pszFileName ||
1869 pci->pszDisplayName < pci->pszFileName ||
1870 pci->pszDisplayName >= pci->pszFileName + _msize(pci->pszFileName))
1871 {
1872 free(pci->pszDisplayName);
1873 }
1874 }
1875 pci->pszDisplayName = NULL; // Catch illegal references
1876 }
1877
1878 if (!pci->pszFileName)
1879 Runtime_Error(pszSrcFile, __LINE__, "FreeCnrItemData attempting free %p data twice", pci);
1880 else {
1881 if (pci->pszFileName != NullStr)
1882 free(pci->pszFileName);
1883 pci->pszFileName = NULL; // Catch illegal references
1884 }
1885
1886 // 08 Sep 08 SHL Remove excess logic
1887 if (pci->pszLongName) {
1888 if (pci->pszLongName != NullStr)
1889 free(pci->pszLongName);
1890 pci->pszLongName = NULL; // Catch illegal references
1891 }
1892
1893 if (pci->pszFmtFileSize) {
1894 if (pci->pszFmtFileSize != NullStr)
1895 free(pci->pszFmtFileSize);
1896 pci->pszFmtFileSize = NULL; // Catch illegal references
1897 }
1898}
1899
1900/**
1901 * Free single container item and associated storage
1902 */
1903
1904VOID FreeCnrItem(HWND hwnd, PCNRITEM pci)
1905{
1906 // DbgMsg(pszSrcFile, __LINE__, "FreeCnrItem hwnd %x pci %p", hwnd, pci);
1907
1908 FreeCnrItemData(pci);
1909
1910 if (!WinSendMsg(hwnd, CM_FREERECORD, MPFROMP(&pci), MPFROMSHORT(1))) {
1911 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,
1912 "CM_FREERECORD hwnd %x pci %p file %s",
1913 hwnd, pci,
1914 pci && pci->pszFileName ? pci->pszFileName : "n/a");
1915 }
1916}
1917
1918/**
1919 * Free container item list and associated storage
1920 */
1921
1922VOID FreeCnrItemList(HWND hwnd, PCNRITEM pciFirst)
1923{
1924 PCNRITEM pci = pciFirst;
1925 PCNRITEM pciNext;
1926 USHORT usCount;
1927
1928 for (usCount = 0; pci; usCount++) {
1929 pciNext = (PCNRITEM) pci->rc.preccNextRecord;
1930 FreeCnrItemData(pci);
1931 pci = pciNext;
1932 }
1933
1934 if (usCount) {
1935 if (!WinSendMsg(hwnd, CM_FREERECORD, MPFROMP(&pci), MPFROMSHORT(usCount))) {
1936 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_FREERECORD hwnd %x pci %p cnt %u", hwnd, pci, usCount);
1937 }
1938 }
1939}
1940
1941/**
1942 * Remove item(s) from container and free associated storage if requested
1943 * @param pciFirst points to first item to remove or NULL to remove all
1944 * @param usCnt is remove count or 0 to remove all
1945 * @returns count of items remaining in container or -1 if error
1946 */
1947
1948INT RemoveCnrItems(HWND hwnd, PCNRITEM pciFirst, USHORT usCnt, USHORT usFlags)
1949{
1950 INT remaining = usCnt;
1951 PCNRITEM pci;
1952
1953 if ((usCnt && !pciFirst) || (!usCnt && pciFirst)) {
1954 Runtime_Error(pszSrcFile, __LINE__, "pciFirst %p usCnt %u mismatch", pciFirst, usCnt);
1955 remaining = -1;
1956 }
1957 else {
1958 // Free our buffers if free requested
1959 if (usFlags & CMA_FREE) {
1960 if (pciFirst)
1961 pci = pciFirst;
1962 else {
1963 pci = (PCNRITEM)WinSendMsg(hwnd, CM_QUERYRECORD, MPVOID,
1964 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
1965 if ((INT)pci == -1) {
1966 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_QUERYRECORD");
1967 remaining = -1;
1968 pci = NULL;
1969 }
1970 }
1971 while (pci) {
1972 // 12 Sep 07 SHL dwg drivebar crash testing - ticket# ???
1973 static PCNRITEM pciLast; // 12 Sep 07 SHL
1974 ULONG ulSize = sizeof(*pci);
1975 ULONG ulAttr;
1976 APIRET apiret = DosQueryMem((PVOID)pci, &ulSize, &ulAttr);
1977 if (apiret)
1978 Dos_Error(MB_ENTER, apiret, HWND_DESKTOP, pszSrcFile, __LINE__,
1979 "DosQueryMem failed pci %p pciLast %p", pci, pciLast);
1980 FreeCnrItemData(pci);
1981 pciLast = pci;
1982 pci = (PCNRITEM)pci->rc.preccNextRecord;
1983 if (remaining && --remaining == 0)
1984 break;
1985 }
1986 }
1987 }
1988
1989 // DbgMsg(pszSrcFile, __LINE__, "RemoveCnrItems %p %u %s", pci, usCnt, pci->pszFileName);
1990
1991 if (remaining != - 1) {
1992 remaining = (INT)WinSendMsg(hwnd, CM_REMOVERECORD, MPFROMP(&pciFirst), MPFROM2SHORT(usCnt, usFlags));
1993 if (remaining == -1) {
1994 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_REMOVERECORD hwnd %x pci %p cnt %u", hwnd, pciFirst, usCnt);
1995 }
1996 }
1997
1998 return remaining;
1999}
2000
2001#pragma alloc_text(FILLDIR,FillInRecordFromFFB,FillInRecordFromFSA,IDFile)
2002#pragma alloc_text(FILLDIR1,ProcessDirectory,FillDirCnr,FillTreeCnr,FileAttrToString,StubbyScanThread)
2003#pragma alloc_text(EMPTYCNR,EmptyCnr,FreeCnrItemData,FreeCnrItem,FreeCnrItemList,RemoveCnrItems)
2004
Note: See TracBrowser for help on using the repository browser.