source: trunk/dll/filldir.c@ 1644

Last change on this file since 1644 was 1644, checked in by Gregg Young, 14 years ago

Fix the code that assigns icons. Earlier change to support 4 letter extensions would fail to recognize some 3 letter extensions.

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