source: trunk/dll/filldir.c@ 1355

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

Minor update to write verify fix for USB removables

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