source: trunk/dll/filldir.c@ 1299

Last change on this file since 1299 was 1299, checked in by Gregg Young, 17 years ago

Scan each drive on separate thread (added StubbyScanThread) to speed treecnr scans

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