source: trunk/dll/filldir.c@ 1440

Last change on this file since 1440 was 1440, checked in by Steven Levine, 16 years ago

Avoid trap in FillInRecordFromFSA if pszFSType NULL

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