source: trunk/dll/filldir.c@ 1207

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

Ticket 187: Move data declarations/definitions out of fm3dll.h

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