source: trunk/dll/filldir.c@ 751

Last change on this file since 751 was 751, checked in by Steven Levine, 18 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.