source: trunk/dll/filldir.c@ 1430

Last change on this file since 1430 was 1430, checked in by Gregg Young, 16 years ago

Additional comments

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