source: trunk/dll/filldir.c@ 1505

Last change on this file since 1505 was 1498, checked in by Gregg Young, 16 years ago

Changes to get FM2 to compile with the latest watcom 1.9 beta (mostly type casts of CHAR CONSTANT * to CHAR *). Changes to get the environment settings working everywhere again (broken by the change that moved commands to the INI); Added an environment size variable (set to 2048 which was the largest I found hard coded). Still need to find everywhere the environment size is set and use this variable.

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