source: trunk/dll/filldir.c@ 1754

Last change on this file since 1754 was 1754, checked in by Gregg Young, 12 years ago

!didone for fFirstTime so the suggest code works again. Also clear out the garbage that was appearing in the string. Ticket 527.

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