source: trunk/dll/filldir.c@ 1451

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

Change WM_USER numbers to account for the fact that some values have been used by the toolkit; Fix unexpected behavior when doubleclick on dircnr dir icon; Provide option to tun off the drive exclude dialogg on startup.

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