source: trunk/dll/filldir.c@ 1250

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

Scan drives in 4 passes to speed up tree scans (Ticket 25)

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