source: trunk/dll/filldir.c@ 1178

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

Remove extra pszLongName logic in FreeCnrItemData

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