source: trunk/dll/filldir.c@ 1290

Last change on this file since 1290 was 1290, checked in by Steven Levine, 17 years ago

FillTreeCnr: ensure any unchecked drives checked in pass 4

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