source: trunk/dll/filldir.c @ 751

Last change on this file since 751 was 751, checked in by Steven Levine, 13 years ago

Sync rest of code with CNRITEM mods
Sync code with ARCITEM mods
Get compare dialog working
Still some issues with status display
Still some issues with directory sizes tree display
Heap check diagnostic code mostly enabled

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