source: trunk/dll/filldir.c@ 1319

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

Part of 1318 Event seamphore code.

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