source: trunk/dll/filldir.c@ 1358

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

Comments for CS 1354/55

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