source: trunk/dll/filldir.c@ 1476

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

Remember last filter mask selection
Use Ctrl-click to select state or commonly used directory quicklist entry without activating.
Use Ctrl-click to select walk dialog user list entry without activating.
Avoid drivebar MB2 exception
Remember last seek and scan mask selection across runs
Avoid traps when changing tree container display style
Restore missing drives to drive list dropdown
Minor documentation updates

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