source: trunk/dll/filldir.c@ 762

Last change on this file since 762 was 762, checked in by Steven Levine, 18 years ago

Use two pass logic to free CNRITEMs and ARCITEMs
Rename pszLongname to pszLongName
More compare directories rework
Make directory sizes item draw placement deterministic - how did it ever work?

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