source: trunk/dll/filldir.c@ 1347

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

More code cleanup

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