source: trunk/dll/filldir.c@ 1401

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

Remainder of changes to rename commafmt.h/c (Ticket 28, 82); Additional strings moved to PCSZs in init.c (Ticket 6); Added WriteDetailsSwitches used it and LoadDetailsSwitches to consolidate inline code (Ticket 343, 344)

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