source: trunk/dll/filldir.c@ 1317

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

Add an event semaphore to prevent duplicate directory names in tree caused by RestoreDirCnrState running concurrently with the StubbyThread for the same drive. (Ticket 25)

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