source: trunk/dll/filldir.c@ 1544

Last change on this file since 1544 was 1544, checked in by Gregg Young, 15 years ago

Changes to fopen and _fsopen to allow FM2 to be loaded in high memory

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