source: trunk/dll/filldir.c@ 1154

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

Correct FreeCnrItemData pszDisplayName pointer overlap check

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