source: trunk/dll/filldir.c@ 1223

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

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