source: trunk/dll/filldir.c@ 1284

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

Correct and sanitize 4 pass scan logic

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