source: trunk/dll/filldir.c@ 1814

Last change on this file since 1814 was 1814, checked in by John Small, 10 years ago

Ticket 514: Double free error fix (which also fixes a memory leak)

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