source: trunk/dll/filldir.c@ 1194

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

Ticket 187: Draft 2: Move remaining function declarations

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