source: trunk/dll/filldir.c@ 1567

Last change on this file since 1567 was 1567, checked in by Steven Levine, 14 years ago

Disable antique debug code in RemoveCnrItems - really speeds up container close

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