source: trunk/dll/filldir.c@ 1159

Last change on this file since 1159 was 1159, checked in by John Small, 17 years ago

Ticket 187: Draft 1: Functions only

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