source: trunk/dll/filldir.c@ 1444

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

Rework of drivebar to rescan all drives and refresh media buttons and menu items grey out inappropriate menu items. Streamline Tree scan code and use semaphores to serialize access. Add NOEASUPPORT and LOCALHD driveflag; .LONGNAME usage fixes; (Tickets 377-386)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 57.4 KB
Line 
1
2/***********************************************************************
3
4 $Id: filldir.c 1444 2009-07-22 23:24:23Z 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 if (rc) {
464 CHAR s[80];
465 sprintf(s, "%s %s",PCSZ_DOSQUERYPATHINFO, "%s");
466 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
467 s, pci->pszFileName);
468 }
469 //DbgMsg(pszSrcFile, __LINE__, "DosQueryPathInfo %s failed with rc %u ", pci->pszFileName, rc);
470 else {
471 PFEA2 pfea = eaop.fpFEA2List->list;
472 while (pfea) {
473 if (pfea->cbValue) {
474 CHAR *achValue = pfea->szName + pfea->cbName + 1;
475 if (*(USHORT *)achValue != EAT_ASCII)
476 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
477 GetPString(IDS_ERROREATYPETEXT),
478 achValue, pfea->cbName, pfea->szName);
479 //DbgMsg(pszSrcFile, __LINE__, "EA type 0x%x unexpected for %.*s", achValue, pfea->cbName, pfea->szName);
480 else {
481 CHAR ch = achValue[pfea->cbValue];
482 PSZ pszValue;
483 achValue[pfea->cbValue] = 0;
484 pszValue = xstrdup(achValue + (sizeof(USHORT) * 2), pszSrcFile, __LINE__);
485 achValue[pfea->cbValue] = ch;
486 //DbgMsg(pszSrcFile, __LINE__, "pfea %p %.*s cbValue %u %s", pfea, pfea->cbName, pfea->szName, pfea->cbValue, pszValue);
487 if (strncmp(pfea->szName, LONGNAME, pfea->cbName) == 0)
488 pci->pszLongName = pszValue;
489 else if (strncmp(pfea->szName, SUBJECT, pfea->cbName) == 0)
490 pci->pszSubject = pszValue;
491 else
492 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
493 GetPString(IDS_ERROREATYPETEXT), pfea, pfea->cbName, pfea->szName);
494 //DbgMsg(pszSrcFile, __LINE__, "pfea %p EA %.*s unexpected", pfea, pfea->cbName, pfea->szName);
495 }
496 }
497 if (!pfea->oNextEntryOffset)
498 break;
499 pfea = (PFEA2)((PSZ)pfea + pfea->oNextEntryOffset);
500 } // while
501 }
502 free(pfealist);
503 }
504 free(pgealist);
505 }
506 }
507} // FetchCommonEAs
508
509ULONGLONG FillInRecordFromFFB(HWND hwndCnr,
510 PCNRITEM pci,
511 const PSZ pszDirectory,
512 const PFILEFINDBUF4L pffb,
513 const BOOL partial,
514 DIRCNRDATA *dcd)
515{
516 // fill in a container record from a FILEFINDBUF4L structure
517
518 CHAR *p;
519 HPOINTER hptr;
520 ULONG flags;
521
522 pci->hwndCnr = hwndCnr;
523
524 /* note that we cheat below, and accept the full pathname in pszDirectory
525 if !*pffb->achName. This speeds up and simplifies processing elsewhere
526 (like in update.c)
527 */
528 if (!*pffb->achName) {
529 pci->pszFileName = xstrdup(pszDirectory, pszSrcFile, __LINE__);
530 //strcpy(pci->pszFileName, pszDirectory);
531 }
532 else {
533 INT c = strlen(pszDirectory);
534 INT c2 = pffb->cchName + 1;
535 if (pszDirectory[c - 1] != '\\')
536 c2++;
537 pci->pszFileName = xmalloc(c + c2, pszSrcFile, __LINE__);
538# ifdef FORTIFY
539 {
540 if (dcd->type != TREE_FRAME)
541 Fortify_ChangeScope(pci->pszFileName, -1);
542 else {
543 Fortify_SetOwner(pci->pszFileName, 1);
544 Fortify_SetScope(pci->pszFileName, 2);
545 }
546 }
547# endif
548 memcpy(pci->pszFileName, pszDirectory, c + 1);
549 p = pci->pszFileName + c - 1;
550 if (*p != '\\') {
551 p++;
552 *p = '\\';
553 }
554 p++;
555 memcpy(p, pffb->achName, pffb->cchName + 1);
556 }
557
558 // load Subject and/or Longname EAs, if required and have EAs
559 if (pffb->cbList > 4L && dcd &&
560 !(driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_NOEASUPPORT))
561 FetchCommonEAs(pci);
562
563 if (!pci->pszSubject)
564 pci->pszSubject = NullStr;
565
566 // load the object's longname
567 if (!pci->pszLongName)
568 pci->pszLongName = NullStr;
569
570 // do anything required to case of filename
571 if (fForceUpper)
572 strupr(pci->pszFileName);
573 else if (fForceLower)
574 strlwr(pci->pszFileName);
575
576 flags = driveflags[toupper(*pci->pszFileName) - 'A'];
577
578 // get an icon to use with it
579 if (pffb->attrFile & FILE_DIRECTORY) {
580 // is directory
581 if (fNoIconsDirs ||
582 (flags & DRIVE_NOLOADICONS) ||
583 !isalpha(*pci->pszFileName)) {
584 hptr = (HPOINTER) 0;
585 }
586 else
587 hptr = WinLoadFileIcon(pci->pszFileName, FALSE);
588 }
589 else {
590 // is file
591 if (fNoIconsFiles ||
592 (flags & DRIVE_NOLOADICONS) ||
593 !isalpha(*pci->pszFileName)) {
594 hptr = (HPOINTER) 0;
595 }
596 else
597 hptr = WinLoadFileIcon(pci->pszFileName, FALSE);
598
599 if (!hptr || IsDefaultIcon(hptr))
600 hptr = IDFile(pci->pszFileName);
601 }
602
603 if (!hptr) {
604 hptr = pffb->attrFile & FILE_DIRECTORY ?
605 hptrDir : pffb->attrFile & FILE_SYSTEM ?
606 hptrSystem : pffb->attrFile & FILE_HIDDEN ?
607 hptrHidden : pffb->attrFile & FILE_READONLY ?
608 hptrReadonly : hptrFile;
609 }
610
611 // Tell container what part of pathname to display
612 if (partial) {
613 p = strrchr(pci->pszFileName, '\\');
614 if (!p) {
615 p = strrchr(pci->pszFileName, ':');
616 if (!p)
617 p = pci->pszFileName;
618 else
619 p++;
620 }
621 else if ((dcd && dcd->type == TREE_FRAME) ||
622 (!(pffb->attrFile & FILE_DIRECTORY) || !*(p + 1))) {
623 p++;
624 }
625 if (!*p)
626 p = pci->pszFileName;
627 }
628 else
629 p = pci->pszFileName;
630 pci->pszDisplayName = p;
631
632 //comma format the file size for large file support
633 {
634 CHAR szBuf[30];
635 CommaFmtULL(szBuf, sizeof(szBuf), pffb->cbFile, ' ');
636 pci->pszFmtFileSize = xstrdup(szBuf, pszSrcFile, __LINE__);
637# ifdef FORTIFY
638 {
639 unsigned tid = GetTidForWindow(hwndCnr);
640 if (tid == 1)
641 Fortify_ChangeScope(pci->pszFmtFileSize, -1);
642 else
643 Fortify_SetOwner(pci->pszFmtFileSize, 1);
644 }
645# endif
646 }
647
648 // now fill the darned thing in...
649 pci->date.day = pffb->fdateLastWrite.day;
650 pci->date.month = pffb->fdateLastWrite.month;
651 pci->date.year = pffb->fdateLastWrite.year + 1980;
652 pci->time.seconds = pffb->ftimeLastWrite.twosecs * 2;
653 pci->time.minutes = pffb->ftimeLastWrite.minutes;
654 pci->time.hours = pffb->ftimeLastWrite.hours;
655 pci->ladate.day = pffb->fdateLastAccess.day;
656 pci->ladate.month = pffb->fdateLastAccess.month;
657 pci->ladate.year = pffb->fdateLastAccess.year + 1980;
658 pci->latime.seconds = pffb->ftimeLastAccess.twosecs * 2;
659 pci->latime.minutes = pffb->ftimeLastAccess.minutes;
660 pci->latime.hours = pffb->ftimeLastAccess.hours;
661 pci->crdate.day = pffb->fdateCreation.day;
662 pci->crdate.month = pffb->fdateCreation.month;
663 pci->crdate.year = pffb->fdateCreation.year + 1980;
664 pci->crtime.seconds = pffb->ftimeCreation.twosecs * 2;
665 pci->crtime.minutes = pffb->ftimeCreation.minutes;
666 pci->crtime.hours = pffb->ftimeCreation.hours;
667 pci->easize = CBLIST_TO_EASIZE(pffb->cbList);
668 pci->cbFile = pffb->cbFile;
669 pci->attrFile = pffb->attrFile;
670 pci->pszDispAttr = FileAttrToString(pci->attrFile);
671 pci->rc.pszIcon = pci->pszDisplayName;
672 pci->rc.hptrIcon = hptr;
673
674 // check to see if record should be visible
675 if (dcd && (*dcd->mask.szMask || dcd->mask.antiattr ||
676 ((dcd->mask.attrFile &
677 (FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY | FILE_ARCHIVED))
678 !=
679 (FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY | FILE_ARCHIVED))))
680 {
681 if (*dcd->mask.szMask || dcd->mask.antiattr) {
682 if (!Filter((PMINIRECORDCORE) pci, (PVOID) & dcd->mask))
683 pci->rc.flRecordAttr |= CRA_FILTERED;
684 }
685 else if ((!(dcd->mask.attrFile & FILE_HIDDEN) &&
686 (pci->attrFile & FILE_HIDDEN)) ||
687 (!(dcd->mask.attrFile & FILE_SYSTEM) &&
688 (pci->attrFile & FILE_SYSTEM)) ||
689 (!(dcd->mask.attrFile & FILE_READONLY) &&
690 (pci->attrFile & FILE_READONLY)) ||
691 (!(dcd->mask.attrFile & FILE_ARCHIVED) &&
692 (pci->attrFile & FILE_ARCHIVED))) {
693 pci->rc.flRecordAttr |= CRA_FILTERED;
694 }
695 }
696
697 return pffb->cbFile + pci->easize;
698
699} // FillInRecordFromFFB
700
701ULONGLONG FillInRecordFromFSA(HWND hwndCnr,
702 PCNRITEM pci,
703 const PSZ pszFileName,
704 const PFILESTATUS4L pfsa4,
705 const BOOL partial,
706 CHAR *pszFSType, // Optional
707 DIRCNRDATA *dcd) // Optional
708{
709 HPOINTER hptr;
710 ULONG flags;
711 CHAR *p;
712 CHAR szBuf[80];
713
714 // fill in a container record from a FILESTATUS4L structure
715
716 pci->hwndCnr = hwndCnr;
717 pci->pszFileName = xstrdup(pszFileName, pszSrcFile, __LINE__);
718
719 // 13 Jul 09 SHL fixme to know if fetch can be bypassed if pszFSType already filled
720 // If FSType not supplied, assume don't need EAs either
721 if (pfsa4->cbList > 4L && dcd &&
722 !(driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_NOEASUPPORT))
723 FetchCommonEAs(pci);
724
725 if (!pci->pszSubject)
726 pci->pszSubject = NullStr;
727 if (!pci->pszLongName)
728 pci->pszLongName = NullStr;
729
730 if (fForceUpper)
731 strupr(pci->pszFileName);
732 else if (fForceLower)
733 strlwr(pci->pszFileName);
734
735 flags = driveflags[toupper(*pci->pszFileName) - 'A'];
736
737 if (pfsa4->attrFile & FILE_DIRECTORY) {
738 if (fNoIconsDirs ||
739 (flags & DRIVE_NOLOADICONS) ||
740 !isalpha(*pci->pszFileName)) {
741 hptr = (HPOINTER) 0;
742 }
743 else
744 hptr = WinLoadFileIcon(pci->pszFileName, FALSE);
745 }
746 else {
747 if (fNoIconsFiles ||
748 (flags & DRIVE_NOLOADICONS) ||
749 !isalpha(*pci->pszFileName)) {
750 hptr = IDFile(pci->pszFileName);
751 }
752 else
753 hptr = WinLoadFileIcon(pci->pszFileName, FALSE);
754 }
755 if (!hptr) {
756 hptr = pfsa4->attrFile & FILE_DIRECTORY ?
757 hptrDir :
758 pfsa4->attrFile & FILE_SYSTEM ?
759 hptrSystem :
760 pfsa4->attrFile & FILE_HIDDEN ?
761 hptrHidden : pfsa4->attrFile & FILE_READONLY ? hptrReadonly : hptrFile;
762 }
763
764 // Tell container what part of pathname to display
765 if (partial) {
766 p = strrchr(pci->pszFileName, '\\');
767 if (!p) {
768 p = strrchr(pci->pszFileName, ':');
769 if (!p)
770 p = pci->pszFileName;
771 else
772 p++;
773 }
774 else if ((dcd && dcd->type == TREE_FRAME) ||
775 !(pfsa4->attrFile & FILE_DIRECTORY) || !*(p + 1))
776 p++;
777 if (!*p)
778 p = pci->pszFileName;
779 }
780 else
781 p = pci->pszFileName;
782 if (pszFSType && (fShowFSTypeInTree || fShowDriveLabelInTree)) {
783 strcpy(szBuf, p);
784 strcat(szBuf, " [");
785 strcat(szBuf, pszFSType);
786 strcat(szBuf, "]");
787 pci->pszDisplayName = xstrdup(szBuf, pszSrcFile, __LINE__);
788 }
789 else
790 pci->pszDisplayName = p;
791
792 // 13 Jul 09 SHL fixme to know why pszFSType check needed
793 // comma format the file size for large file support
794 if (!pszFSType || *pszFSType == 0) {
795 CHAR szBuf[30];
796 CommaFmtULL(szBuf, sizeof(szBuf), pfsa4->cbFile, ' ');
797 pci->pszFmtFileSize = xstrdup(szBuf, pszSrcFile, __LINE__);
798# ifdef FORTIFY
799 {
800 if (dcd && dcd->type == TREE_FRAME) {
801 // Will be freed in TreeCnrWndProc WM_DESTROY
802 // Fortify_SetOwner(pci->pszFmtFileSize, 1);
803 Fortify_SetScope(pci->pszFmtFileSize, 2);
804 }
805 }
806# endif
807 }
808 else {
809 pci->pszFmtFileSize = NullStr;
810 //DbgMsg(pszSrcFile, __LINE__, "Bypassed Format size %s", pci->pszDisplayName);
811 }
812 pci->date.day = pfsa4->fdateLastWrite.day;
813 pci->date.month = pfsa4->fdateLastWrite.month;
814 pci->date.year = pfsa4->fdateLastWrite.year + 1980;
815 pci->time.seconds = pfsa4->ftimeLastWrite.twosecs * 2;
816 pci->time.minutes = pfsa4->ftimeLastWrite.minutes;
817 pci->time.hours = pfsa4->ftimeLastWrite.hours;
818 pci->ladate.day = pfsa4->fdateLastAccess.day;
819 pci->ladate.month = pfsa4->fdateLastAccess.month;
820 pci->ladate.year = pfsa4->fdateLastAccess.year + 1980;
821 pci->latime.seconds = pfsa4->ftimeLastAccess.twosecs * 2;
822 pci->latime.minutes = pfsa4->ftimeLastAccess.minutes;
823 pci->latime.hours = pfsa4->ftimeLastAccess.hours;
824 pci->crdate.day = pfsa4->fdateCreation.day;
825 pci->crdate.month = pfsa4->fdateCreation.month;
826 pci->crdate.year = pfsa4->fdateCreation.year + 1980;
827 pci->crtime.seconds = pfsa4->ftimeCreation.twosecs * 2;
828 pci->crtime.minutes = pfsa4->ftimeCreation.minutes;
829 pci->crtime.hours = pfsa4->ftimeCreation.hours;
830 pci->easize = CBLIST_TO_EASIZE(pfsa4->cbList);
831 pci->cbFile = pfsa4->cbFile;
832 pci->attrFile = pfsa4->attrFile;
833 pci->pszDispAttr = FileAttrToString(pci->attrFile);
834 pci->rc.pszIcon = pci->pszDisplayName;
835 pci->rc.hptrIcon = hptr;
836
837 if (dcd &&
838 (*dcd->mask.szMask || dcd->mask.antiattr ||
839 ((dcd->mask.attrFile &
840 (FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY | FILE_ARCHIVED)) !=
841 (FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY | FILE_ARCHIVED)))) {
842 if (*dcd->mask.szMask || dcd->mask.antiattr) {
843 if (!Filter((PMINIRECORDCORE) pci, (PVOID) & dcd->mask))
844 pci->rc.flRecordAttr |= CRA_FILTERED;
845 }
846 else if ((!(dcd->mask.attrFile & FILE_HIDDEN) &&
847 (pci->attrFile & FILE_HIDDEN)) ||
848 (!(dcd->mask.attrFile & FILE_SYSTEM) &&
849 (pci->attrFile & FILE_SYSTEM)) ||
850 (!(dcd->mask.attrFile & FILE_READONLY) &&
851 (pci->attrFile & FILE_READONLY)) ||
852 (!(dcd->mask.attrFile & FILE_ARCHIVED) &&
853 (pci->attrFile & FILE_ARCHIVED)))
854 pci->rc.flRecordAttr |= CRA_FILTERED;
855 }
856
857 return pfsa4->cbFile + pci->easize;
858
859} // FillInRecordFromFSA
860
861VOID ProcessDirectory(const HWND hwndCnr,
862 const PCNRITEM pciParent,
863 const CHAR *szDirBase,
864 const BOOL filestoo,
865 const BOOL recurse,
866 const BOOL partial,
867 CHAR *stopflag,
868 DIRCNRDATA *dcd, // Optional
869 ULONG *pulTotalFiles, // Optional
870 PULONGLONG pullTotalBytes) // Optional
871{
872 /* put all the directories (and files if filestoo is TRUE) from a
873 * directory into the container. recurse through subdirectories if
874 * recurse is TRUE.
875 */
876
877 PSZ pszFileSpec;
878 //INT t;
879 PFILEFINDBUF4L paffbFound;
880 PFILEFINDBUF4L *papffbSelected;
881 PFILEFINDBUF4L pffbFile;
882 PFILEFINDBUF4L paffbTotal = NULL;
883 PFILEFINDBUF4L paffbTemp;
884 HDIR hdir = HDIR_CREATE;
885 ULONG ulFindCnt;
886 ULONG ulFindMax;
887 ULONG ulSelCnt;
888 ULONG ulTotal = 0;
889 ULONGLONG ullBytes;
890 ULONGLONG ullTotalBytes;
891 ULONG ulReturnFiles = 0;
892 ULONGLONG ullReturnBytes = 0;
893 //PCH pchEndPath;
894 APIRET rc;
895 PCNRITEM pci;
896 PCNRITEM pciFirst;
897 RECORDINSERT ri;
898 BOOL ok = TRUE;
899 ULONG ulBufBytes;
900 ULONG x;
901
902 if (isalpha(*szDirBase) && szDirBase[1] == ':' && szDirBase[2] == '\\') {
903 if ((driveflags[toupper(*szDirBase) - 'A'] & DRIVE_REMOTE) && fRemoteBug)
904 ulFindMax = 1; // file system gets confused
905 else if (driveflags[toupper(*szDirBase) - 'A'] & DRIVE_ZIPSTREAM)
906 ulFindMax = min(FilesToGet, 225); // anything more is wasted
907 else
908 ulFindMax = FilesToGet; // full-out
909 }
910 else
911 ulFindMax = FilesToGet;
912
913 if (OS2ver[0] == 20 && OS2ver[1] < 30)
914 ulFindMax = min(ulFindMax, (65535 / sizeof(FILEFINDBUF4L)));
915
916 ulBufBytes = ulFindMax * sizeof(FILEFINDBUF4L);
917
918 pszFileSpec = xmalloc(CCHMAXPATH + 2, pszSrcFile, __LINE__);
919 paffbFound = xmalloc(ulBufBytes, pszSrcFile, __LINE__);
920 papffbSelected = xmalloc(sizeof(PFILEFINDBUF4L) * ulFindMax, pszSrcFile, __LINE__);
921
922 if (paffbFound && papffbSelected && pszFileSpec) {
923 //t = strlen(szDirBase);
924 strcpy(pszFileSpec, szDirBase);
925 AddBackslashToPath(pszFileSpec);
926 //pchEndPath = pszFileSpec + t;
927 //if (*(pchEndPath - 1) != '\\') {
928 // memcpy(pchEndPath, "\\", 2);
929 // pchEndPath++;
930 //}
931 strcat(pszFileSpec, "*");
932 DosError(FERR_DISABLEHARDERR);
933 ulFindCnt = ulFindMax;
934 rc = xDosFindFirst(pszFileSpec,
935 &hdir,
936 FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED |
937 FILE_SYSTEM | FILE_HIDDEN |
938 (filestoo ? FILE_DIRECTORY : MUST_HAVE_DIRECTORY),
939 paffbFound,
940 ulBufBytes,
941 &ulFindCnt,
942 FIL_QUERYEASIZEL);
943 priority_normal();
944 pszFileSpec[strlen(pszFileSpec) - 1] = 0; // Chop off wildcard
945 //*pchEndPath = 0;
946 if (!rc) {
947 do {
948 /*
949 * remove . and .. from list if present
950 * also counter file system bugs that sometimes
951 * allows normal files to slip through when
952 * only directories should appear (only a few
953 * network file systems exhibit such a problem).
954 */
955
956 if (stopflag && *stopflag)
957 goto Abort;
958 pffbFile = paffbFound;
959 ulSelCnt = 0;
960 for (;;) {
961 if (!*pffbFile->achName ||
962 (!filestoo && ~pffbFile->attrFile & FILE_DIRECTORY) ||
963 (pffbFile->attrFile & FILE_DIRECTORY &&
964 pffbFile->achName[0] == '.' &&
965 (!pffbFile->achName[1] ||
966 (pffbFile->achName[1] == '.' && !pffbFile->achName[2])))) {
967 // ulFindCnt--; // Got . or .. or file to be skipped
968 }
969 else
970 papffbSelected[ulSelCnt++] = pffbFile; // Remember selected file
971 if (!pffbFile->oNextEntryOffset) {
972 // ulFindCnt = ulSelCnt; // Remember number selected
973 break;
974 }
975 pffbFile = (PFILEFINDBUF4L)((PBYTE)pffbFile + pffbFile->oNextEntryOffset);
976 } // for
977 if (ulSelCnt) {
978 // One or more entries selected
979 if (stopflag && *stopflag)
980 goto Abort;
981 if (fSyncUpdates) {
982 pciFirst = WinSendMsg(hwndCnr, CM_ALLOCRECORD,
983 MPFROMLONG(EXTRA_RECORD_BYTES),
984 MPFROMLONG(ulSelCnt));
985 if (!pciFirst) {
986 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
987 GetPString(IDS_CMALLOCRECERRTEXT));
988 ok = FALSE;
989 ullTotalBytes = 0;
990 }
991 else {
992 // 04 Jan 08 SHL fixme like comp.c to handle less than ulSelCnt records
993 pci = pciFirst;
994 ullTotalBytes = 0;
995 // Insert selected in container
996 for (x = 0; x < ulSelCnt; x++) {
997 pffbFile = papffbSelected[x];
998 ullBytes = FillInRecordFromFFB(hwndCnr, pci, pszFileSpec,
999 pffbFile, partial, dcd);
1000 pci = (PCNRITEM) pci->rc.preccNextRecord;
1001 ullTotalBytes += ullBytes;
1002 } // for
1003 memset(&ri, 0, sizeof(RECORDINSERT));
1004 ri.cb = sizeof(RECORDINSERT);
1005 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1006 ri.pRecordParent = (PRECORDCORE) pciParent;
1007 ri.zOrder = (ULONG) CMA_TOP;
1008 ri.cRecordsInsert = ulSelCnt;
1009 ri.fInvalidateRecord = TRUE;
1010 // !fSyncUpdates && dcd && dcd->type == DIR_FRAME ? FALSE : TRUE; //fSyncUpdates always TRUE 12-1-08 GKY
1011 if (!WinSendMsg(hwndCnr,
1012 CM_INSERTRECORD,
1013 MPFROMP(pciFirst), MPFROMP(&ri))) {
1014 DosSleep(10); // Give GUI time to work
1015 WinSetFocus(HWND_DESKTOP, hwndCnr);
1016 if (!WinSendMsg(hwndCnr,
1017 CM_INSERTRECORD,
1018 MPFROMP(pciFirst), MPFROMP(&ri))) {
1019 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1020 GetPString(IDS_CMINSERTERRTEXT));
1021 ok = FALSE;
1022 ullTotalBytes = 0;
1023 if (WinIsWindow((HAB) 0, hwndCnr))
1024 FreeCnrItemList(hwndCnr, pciFirst);
1025 }
1026 // }
1027 }
1028 }
1029 if (ok) {
1030 ullReturnBytes += ullTotalBytes;
1031 ulReturnFiles += ulSelCnt;
1032 }
1033 } // if sync updates
1034 else {
1035 // Append newly selected entries to aggregate list
1036 paffbTemp = xrealloc(paffbTotal,
1037 sizeof(FILEFINDBUF4L) * (ulSelCnt + ulTotal),
1038 pszSrcFile, __LINE__);
1039 if (paffbTemp) {
1040 // 13 Aug 07 SHL fixme to optimize copy
1041 paffbTotal = paffbTemp;
1042 for (x = 0; x < ulSelCnt; x++)
1043 paffbTotal[x + ulTotal] = *papffbSelected[x];
1044 ulTotal += ulSelCnt;
1045 }
1046 else {
1047 saymsg(MB_ENTER,
1048 HWND_DESKTOP,
1049 GetPString(IDS_ERRORTEXT), GetPString(IDS_OUTOFMEMORY));
1050 break;
1051 }
1052 }
1053 } // if entries selected
1054 if (stopflag && *stopflag)
1055 goto Abort;
1056 DosError(FERR_DISABLEHARDERR);
1057 ulFindCnt = ulFindMax;
1058 rc = xDosFindNext(hdir, paffbFound, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZEL);
1059 priority_normal();
1060 if (rc)
1061 DosError(FERR_DISABLEHARDERR);
1062 } while (!rc);
1063
1064 DosFindClose(hdir);
1065 xfree(paffbFound, pszSrcFile, __LINE__);
1066 paffbFound = NULL;
1067 xfree(papffbSelected, pszSrcFile, __LINE__);
1068 papffbSelected = NULL;
1069
1070 if (ulTotal && paffbTotal) {
1071
1072 if (stopflag && *stopflag)
1073 goto Abort;
1074
1075 pciFirst = WinSendMsg(hwndCnr, CM_ALLOCRECORD,
1076 MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(ulTotal));
1077 if (!pciFirst) {
1078 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1079 GetPString(IDS_CMALLOCRECERRTEXT));
1080 ok = FALSE;
1081 ullTotalBytes = 0;
1082 }
1083 else {
1084 // 04 Jan 08 SHL fixme like comp.c to handle less than ulSelCnt records
1085 pci = pciFirst;
1086 ullTotalBytes = 0;
1087 pffbFile = paffbTotal;
1088 for (x = 0; x < ulTotal; x++) {
1089 ullBytes = FillInRecordFromFFB(hwndCnr, pci, pszFileSpec,
1090 pffbFile, partial, dcd);
1091 pci = (PCNRITEM) pci->rc.preccNextRecord;
1092 ullTotalBytes += ullBytes;
1093 // Can not use offset since we have merged lists - this should be equivalent
1094 pffbFile = (PFILEFINDBUF4L)((PBYTE)pffbFile + sizeof(FILEFINDBUF4L));
1095 }
1096 if (ulTotal) {
1097 memset(&ri, 0, sizeof(RECORDINSERT));
1098 ri.cb = sizeof(RECORDINSERT);
1099 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1100 ri.pRecordParent = (PRECORDCORE) pciParent;
1101 ri.zOrder = (ULONG) CMA_TOP;
1102 ri.cRecordsInsert = ulTotal;
1103 ri.fInvalidateRecord = (!fSyncUpdates && dcd &&
1104 dcd->type == DIR_FRAME) ? FALSE : TRUE;
1105 if (!WinSendMsg(hwndCnr, CM_INSERTRECORD,
1106 MPFROMP(pciFirst), MPFROMP(&ri))) {
1107 DosSleep(10); // Give GUI time to work
1108 WinSetFocus(HWND_DESKTOP, hwndCnr);
1109 if (!WinSendMsg(hwndCnr, CM_INSERTRECORD,
1110 MPFROMP(pciFirst), MPFROMP(&ri))) {
1111 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1112 GetPString(IDS_CMINSERTERRTEXT));
1113 ok = FALSE;
1114 ullTotalBytes = 0;
1115 if (WinIsWindow((HAB) 0, hwndCnr))
1116 FreeCnrItemList(hwndCnr, pciFirst);
1117 }
1118 }
1119 }
1120 }
1121 if (ok) {
1122 ullReturnBytes += ullTotalBytes;
1123 ulReturnFiles += ulFindCnt;
1124 }
1125 }
1126 }
1127
1128 /**
1129 * DosFind for subdirectories of a read-only directory on a FAT volume
1130 * returns path not found if there are no subdirectories
1131 * FAT FS seems to ignore . and .. in this case
1132 * Map to no more files
1133 * We could verify that directory is marked read-only, it's probably not
1134 * worth the extra code since we do verify 2 out of 3 prerequisites
1135 * 15 Jan 08 SHL
1136 */
1137 if (rc == ERROR_PATH_NOT_FOUND && !filestoo) {
1138 ULONG ulDriveType = 0;
1139 CHAR szFSType[CCHMAXPATH];
1140 INT removable = CheckDrive(*pszFileSpec, szFSType, &ulDriveType);
1141 if (removable != -1 && strcmp(szFSType, "FAT") == 0)
1142 rc = ERROR_NO_MORE_FILES;
1143 }
1144
1145 if (rc && rc != ERROR_NO_MORE_FILES) {
1146 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
1147 GetPString(IDS_CANTFINDDIRTEXT), pszFileSpec);
1148 }
1149
1150 if (!fSyncUpdates && dcd && dcd->type == DIR_FRAME)
1151 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPVOID,
1152 MPFROM2SHORT(0, CMA_ERASE));
1153 }
1154Abort:
1155 xfree(paffbTotal, pszSrcFile, __LINE__);
1156 xfree(pszFileSpec, pszSrcFile, __LINE__);
1157 xfree(paffbFound, pszSrcFile, __LINE__);
1158 xfree(papffbSelected, pszSrcFile, __LINE__);
1159
1160 if (recurse) {
1161 pci = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pciParent),
1162 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
1163 while (pci && (INT)pci != -1) {
1164 if ((pci->attrFile & FILE_DIRECTORY))
1165 Stubby(hwndCnr, pci);
1166 pci = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
1167 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1168 }
1169 }
1170
1171 if (pulTotalFiles)
1172 *pulTotalFiles = ulReturnFiles;
1173
1174 if (pullTotalBytes)
1175 *pullTotalBytes = ullReturnBytes;
1176
1177} // ProcessDirectory
1178
1179VOID FillDirCnr(HWND hwndCnr,
1180 CHAR * pszDirectory,
1181 DIRCNRDATA * dcd,
1182 PULONGLONG pullTotalBytes)
1183{
1184 ProcessDirectory(hwndCnr,
1185 (PCNRITEM)NULL,
1186 pszDirectory,
1187 TRUE, // filestoo
1188 FALSE, // recurse
1189 TRUE, // partial
1190 dcd ? &dcd->stopflag : NULL,
1191 dcd,
1192 NULL, // total files
1193 pullTotalBytes);
1194 DosPostEventSem(CompactSem);
1195
1196#if 0 // fixme to be gone or to be configurable
1197 {
1198 int state = _heapchk();
1199 if (state != _HEAPOK)
1200 Runtime_Error(pszSrcFile, __LINE__, "heap corrupted %d", state);
1201 else
1202 DbgMsg(pszSrcFile, __LINE__, "_memavl %u", _memavl());
1203 }
1204#endif
1205
1206} // FillDirCnr
1207
1208VOID FillTreeCnr(HWND hwndCnr, HWND hwndParent)
1209{
1210 ULONG ulCurDriveNum, ulDriveMap, numtoinsert = 0;
1211 ULONG ulDriveType;
1212 PCNRITEM pci, pciFirst = NULL, pciNext, pciParent = NULL;
1213 INT x;// removable;
1214 CHAR suggest[32];
1215 CHAR szDrive[] = " :\\";
1216 CHAR szFSType[CCHMAXPATH];
1217 FILESTATUS4L fsa4;
1218 APIRET rc;
1219 BOOL drivesbuilt = FALSE;
1220 ULONG startdrive = 3;
1221 static BOOL didonce;
1222
1223 fDummy = TRUE;
1224 *suggest = 0;
1225 for (x = 0; x < 26; x++) {
1226 driveflags[x] &= (DRIVE_IGNORE | DRIVE_NOPRESCAN | DRIVE_NOLOADICONS |
1227 DRIVE_NOLOADSUBJS | DRIVE_NOLOADLONGS |
1228 DRIVE_INCLUDEFILES | DRIVE_SLOW | DRIVE_NOSTATS |
1229 DRIVE_WRITEVERIFYOFF);
1230 }
1231 memset(driveserial, -1, sizeof(driveserial));
1232
1233 DosError(FERR_DISABLEHARDERR);
1234 if (!DosQuerySysInfo(QSV_BOOT_DRIVE,
1235 QSV_BOOT_DRIVE,
1236 (PVOID) &startdrive,
1237 (ULONG) sizeof(ULONG)) &&
1238 startdrive)
1239 {
1240 driveflags[startdrive - 1] |= DRIVE_BOOT;
1241 }
1242
1243 DosError(FERR_DISABLEHARDERR);
1244 rc = DosQCurDisk(&ulCurDriveNum, &ulDriveMap);
1245 if (rc) {
1246 Dos_Error(MB_CANCEL,
1247 rc,
1248 HWND_DESKTOP,
1249 pszSrcFile, __LINE__, PCSZ_FILLDIRQCURERRTEXT);
1250 exit(0);
1251 }
1252
1253 // Calc number of drive items to create
1254 for (x = 0; x < 26; x++) {
1255 if ((ulDriveMap & (1L << x)) && !(driveflags[x] & DRIVE_IGNORE))
1256 numtoinsert++;
1257 }
1258
1259 if (numtoinsert) {
1260 pciFirst = WinSendMsg(hwndCnr,
1261 CM_ALLOCRECORD,
1262 MPFROMLONG(EXTRA_RECORD_BYTES),
1263 MPFROMLONG((ULONG) numtoinsert));
1264 }
1265
1266 if (!pciFirst) {
1267 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__, GetPString(IDS_CMALLOCRECERRTEXT));
1268 // 04 Jan 08 SHL fixme not just up and die
1269 exit(0);
1270 }
1271
1272 // 04 Jan 08 SHL fixme like comp.c to handle less than ulSelCnt records
1273 pci = pciFirst;
1274 for (x = 0; x < 26; x++) {
1275 if ((ulDriveMap & (1L << x)) && !(driveflags[x] & DRIVE_IGNORE)) {
1276
1277 CHAR s[80];
1278 ULONG flags = 0;
1279 ULONG size = sizeof(ULONG);
1280 struct {
1281 ULONG serial;
1282 CHAR volumelength;
1283 CHAR volumelabel[CCHMAXPATH];
1284 } volser;
1285
1286 *szDrive = (CHAR)x + 'A'; // Build path spec
1287
1288 sprintf(s, "%c.DriveFlags", toupper(*szDrive));
1289 if (PrfQueryProfileData(fmprof, appname, s, &flags, &size)) {
1290 driveflags[toupper(*szDrive) - 'A'] |= flags;
1291 }
1292
1293 if (x > 1) {
1294 // Hard drive (2..N)
1295 if (!(driveflags[x] & DRIVE_NOPRESCAN)) {
1296 *szFSType = 0;
1297 ulDriveType = 0;
1298 memset(&volser, 0, sizeof(volser));
1299 DriveFlagsOne(x, szFSType, &volser);
1300 driveserial[x] = volser.serial;
1301 memset(&fsa4, 0, sizeof(FILESTATUS4L));
1302 if (!fVerifyOffChecked[x]) {
1303 if (driveflags[x] & DRIVE_REMOVABLE)
1304 driveflags[x] |= DRIVE_WRITEVERIFYOFF;
1305 if (!(driveflags[x] & DRIVE_INVALID)) {
1306 CHAR Key[80];
1307
1308 sprintf(Key, "%c.VerifyOffChecked", (CHAR) (x + 'A'));
1309 fVerifyOffChecked[x] = TRUE;
1310 PrfWriteProfileData(fmprof, appname, Key, &fVerifyOffChecked[x], sizeof(BOOL));
1311 }
1312 }
1313 if (stricmp(volser.volumelabel, NullStr) != 0 && fShowDriveLabelInTree)
1314 strcpy(szFSType, volser.volumelabel);
1315 pci->rc.flRecordAttr |= CRA_RECORDREADONLY;
1316 if ((ULONG)(toupper(*szDrive) - '@') == ulCurDriveNum)
1317 pci->rc.flRecordAttr |= (CRA_CURSORED | CRA_SELECTED);
1318
1319 if (!(driveflags[x] & DRIVE_REMOVABLE)) {
1320 // Fixed volume
1321 pci->attrFile |= FILE_DIRECTORY;
1322 DosError(FERR_DISABLEHARDERR);
1323 rc = DosQueryPathInfo(szDrive,
1324 FIL_QUERYEASIZEL,
1325 &fsa4, (ULONG) sizeof(FILESTATUS4L));
1326 if (rc == ERROR_BAD_NET_RESP) {
1327 DosError(FERR_DISABLEHARDERR);
1328 rc = DosQueryPathInfo(szDrive,
1329 FIL_STANDARDL,
1330 &fsa4, (ULONG) sizeof(FILESTATUS4L));
1331 fsa4.cbList = 0;
1332 }
1333 if (rc && !didonce) {
1334 // Guess drive letter
1335 if (!*suggest) {
1336 *suggest = '/';
1337 suggest[1] = 0;
1338 }
1339
1340 sprintf(suggest + strlen(suggest), "%c" , toupper(*szDrive));
1341 pci->pszFileName = xstrdup(szDrive, pszSrcFile, __LINE__);
1342 if (fShowFSTypeInTree || fShowDriveLabelInTree) {
1343 strcat(szDrive, " [");
1344 strcat(szDrive, szFSType);
1345 strcat(szDrive, "]");
1346 }
1347 pci->pszDisplayName = xstrdup(szDrive, pszSrcFile, __LINE__);
1348 szDrive[3] = 0;
1349 pci->rc.pszIcon = pci->pszDisplayName;
1350 pci->attrFile = FILE_DIRECTORY;
1351 pci->pszDispAttr = FileAttrToString(pci->attrFile);
1352 driveserial[x] = -1;
1353 }
1354 else
1355 FillInRecordFromFSA(hwndCnr, pci, szDrive, &fsa4, TRUE, szFSType, NULL);
1356 }
1357 else {
1358 // Removable volume
1359 pci->pszFileName = xstrdup(szDrive, pszSrcFile, __LINE__);
1360 if (fShowFSTypeInTree || fShowDriveLabelInTree) {
1361 strcat(szDrive, " [");
1362 strcat(szDrive, szFSType);
1363 strcat(szDrive, "]");
1364 }
1365 pci->pszDisplayName = xstrdup(szDrive, pszSrcFile, __LINE__);
1366 szDrive[3] = 0;
1367 pci->rc.pszIcon = pci->pszDisplayName;
1368 pci->attrFile = FILE_DIRECTORY;
1369 pci->pszDispAttr = FileAttrToString(pci->attrFile);
1370 }
1371 SelectDriveIcon(pci);
1372# ifdef FORTIFY
1373 // Will be freed by TreeCnrWndProc WM_DESTROY
1374 Fortify_SetScope(pci->pszFileName, 2);
1375# endif
1376 }
1377 else {
1378 *szFSType = 0;
1379 pci->rc.hptrIcon = hptrDunno;
1380 pci->pszFileName = xstrdup(szDrive, pszSrcFile, __LINE__);
1381 if (fShowFSTypeInTree || fShowDriveLabelInTree) {
1382 strcat(szDrive, " [?]");
1383 }
1384 pci->pszDisplayName = xstrdup(szDrive, pszSrcFile, __LINE__);
1385 szDrive[3] = 0;
1386# ifdef FORTIFY
1387 // Will be freed by TreeCnrWndProc WM_DESTROY
1388 Fortify_SetScope(pci->pszFileName, 2);
1389# endif
1390 pci->rc.pszIcon = pci->pszDisplayName;
1391 pci->attrFile = FILE_DIRECTORY;
1392 pci->pszDispAttr = FileAttrToString(pci->attrFile);
1393 driveserial[x] = -1;
1394 }
1395 }
1396 else {
1397 // diskette drive (A or B)
1398 pci->rc.hptrIcon = hptrFloppy;
1399 pci->pszFileName = xstrdup(szDrive, pszSrcFile, __LINE__);
1400 if (fShowFSTypeInTree || fShowDriveLabelInTree)
1401 strcat(szDrive, " [Floppy]");
1402 pci->pszDisplayName = xstrdup(szDrive, pszSrcFile, __LINE__);
1403 szDrive[3] = 0;
1404 pci->rc.pszIcon = pci->pszDisplayName;
1405 pci->attrFile = FILE_DIRECTORY;
1406 pci->pszDispAttr = FileAttrToString(pci->attrFile);
1407 driveflags[x] |= (DRIVE_REMOVABLE | DRIVE_NOLONGNAMES);
1408 driveserial[x] = -1;
1409 }
1410 pci->rc.flRecordAttr |= CRA_RECORDREADONLY;
1411 pci = (PCNRITEM) pci->rc.preccNextRecord; // next rec
1412 }
1413 else if (!(ulDriveMap & (1L << x)))
1414 driveflags[x] |= DRIVE_INVALID;
1415 } // for drives
1416
1417 PostMsg(hwndMain, UM_BUILDDRIVEBAR, MPVOID, MPVOID);
1418 drivesbuilt = TRUE;
1419
1420 // insert the drives
1421 if (numtoinsert && pciFirst) {
1422 RECORDINSERT ri;
1423
1424 memset(&ri, 0, sizeof(RECORDINSERT));
1425 ri.cb = sizeof(RECORDINSERT);
1426 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1427 ri.pRecordParent = (PRECORDCORE) NULL;
1428 ri.zOrder = (ULONG) CMA_TOP;
1429 ri.cRecordsInsert = numtoinsert;
1430 ri.fInvalidateRecord = FALSE;
1431 if (!WinSendMsg(hwndCnr,
1432 CM_INSERTRECORD, MPFROMP(pciFirst), MPFROMP(&ri)))
1433 {
1434 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1435 GetPString(IDS_CMINSERTERRTEXT));
1436 }
1437 }
1438
1439 // move cursor onto the default drive rather than the first drive
1440 if (!fSwitchTree) {
1441 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1442 CM_QUERYRECORD,
1443 MPVOID,
1444 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
1445 while (pci && (INT)pci != -1) {
1446 if ((ULONG) (toupper(*pci->pszFileName) - '@') == ulCurDriveNum) {
1447 WinSendMsg(hwndCnr,
1448 CM_SETRECORDEMPHASIS,
1449 MPFROMP(pci), MPFROM2SHORT(TRUE, CRA_CURSORED));
1450 break;
1451 }
1452 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1453 CM_QUERYRECORD,
1454 MPFROMP(pci),
1455 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1456 }
1457 }
1458
1459 if (hwndParent) {
1460 WinSendMsg(WinWindowFromID(WinQueryWindow(hwndParent, QW_PARENT),
1461 MAIN_DRIVELIST),
1462 LM_DELETEALL, MPVOID, MPVOID);
1463 }
1464
1465 if (fShowEnv) {
1466 RECORDINSERT ri;
1467
1468 pciParent = WinSendMsg(hwndCnr,
1469 CM_ALLOCRECORD,
1470 MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(1));
1471 if (pciParent) {
1472 pciParent->flags |= RECFLAGS_ENV;
1473 pciParent->pszFileName = xstrdup(GetPString(IDS_ENVVARSTEXT), pszSrcFile, __LINE__);
1474 pciParent->pszDisplayName = pciParent->pszFileName; // 03 Aug 07 SHL
1475 pciParent->rc.hptrIcon = hptrEnv;
1476 pciParent->rc.pszIcon = pciParent->pszFileName;
1477 pciParent->pszDispAttr = FileAttrToString(0);
1478 memset(&ri, 0, sizeof(RECORDINSERT));
1479 ri.cb = sizeof(RECORDINSERT);
1480 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1481 ri.pRecordParent = (PRECORDCORE) NULL;
1482 ri.zOrder = (ULONG) CMA_TOP;
1483 ri.cRecordsInsert = 1;
1484 ri.fInvalidateRecord = FALSE;
1485 if (WinSendMsg(hwndCnr,
1486 CM_INSERTRECORD, MPFROMP(pciParent), MPFROMP(&ri))) {
1487
1488 char *p, *pp;
1489
1490 p = pszTreeEnvVarList;
1491 while (*p == ';')
1492 p++;
1493 while (*p) {
1494 *szFSType = 0;
1495 pp = szFSType;
1496 while (*p && *p != ';')
1497 *pp++ = *p++;
1498 *pp = 0;
1499 while (*p == ';')
1500 p++;
1501 if (*szFSType &&
1502 (!stricmp(szFSType, PCSZ_LIBPATH) || getenv(szFSType))) {
1503 pci = WinSendMsg(hwndCnr,
1504 CM_ALLOCRECORD,
1505 MPFROMLONG(EXTRA_RECORD_BYTES),
1506 MPFROMLONG(1));
1507 if (pci) {
1508 CHAR fname[CCHMAXPATH];
1509 pci->flags |= RECFLAGS_ENV;
1510 sprintf(fname, "%%%s%%", szFSType);
1511 pci->pszFileName = xstrdup(fname, pszSrcFile, __LINE__);
1512 pci->rc.hptrIcon = hptrEnv;
1513 pci->rc.pszIcon = pci->pszFileName;
1514 pci->pszDispAttr = FileAttrToString(0);
1515 memset(&ri, 0, sizeof(RECORDINSERT));
1516 ri.cb = sizeof(RECORDINSERT);
1517 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1518 ri.pRecordParent = (PRECORDCORE) pciParent;
1519 ri.zOrder = (ULONG) CMA_TOP;
1520 ri.cRecordsInsert = 1;
1521 ri.fInvalidateRecord = FALSE;
1522 if (!WinSendMsg(hwndCnr,
1523 CM_INSERTRECORD,
1524 MPFROMP(pci), MPFROMP(&ri))) {
1525 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1526 GetPString(IDS_CMINSERTERRTEXT));
1527 FreeCnrItem(hwndCnr, pci);
1528 }
1529 }
1530 }
1531 }
1532 WinSendMsg(hwndCnr,
1533 CM_INVALIDATERECORD,
1534 MPFROMP(&pciParent),
1535 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
1536 }
1537 else
1538 FreeCnrItem(hwndCnr, pciParent);
1539 }
1540 } // if show env
1541 {
1542 STUBBYSCAN *stubbyScan;
1543 HWND hwndDrivesList = WinWindowFromID(WinQueryWindow(hwndParent, QW_PARENT),
1544 MAIN_DRIVELIST);
1545
1546 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1547 CM_QUERYRECORD,
1548 MPVOID,
1549 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
1550 while (pci && (INT)pci != -1) {
1551 stubbyScan = xmallocz(sizeof(STUBBYSCAN), pszSrcFile, __LINE__);
1552 if (!stubbyScan)
1553 break;
1554 stubbyScan->pci = pci;
1555 stubbyScan->hwndCnr = hwndCnr;
1556 stubbyScan->hwndDrivesList = hwndDrivesList;
1557 pciNext = (PCNRITEM) WinSendMsg(hwndCnr,
1558 CM_QUERYRECORD,
1559 MPFROMP(pci),
1560 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1561 if (~pci->flags & RECFLAGS_ENV) {
1562 ULONG drvNum = toupper(*pci->pszFileName) - 'A'; // 0..25
1563 if (drvNum == ulCurDriveNum || drvNum >= 2) {
1564 ULONG flags = driveflags[drvNum]; // Speed up
1565 if (~flags & DRIVE_INVALID &&
1566 ~flags & DRIVE_NOPRESCAN &&
1567 (!fNoRemovableScan || ~flags & DRIVE_REMOVABLE))
1568 {
1569 if (xbeginthread(StubbyScanThread,
1570 65536,
1571 stubbyScan,
1572 pszSrcFile,
1573 __LINE__) == -1)
1574 {
1575 xfree(stubbyScan, pszSrcFile, __LINE__);
1576 }
1577 } // if drive for scanning
1578 else
1579 WinSendMsg(hwndDrivesList,
1580 LM_INSERTITEM,
1581 MPFROM2SHORT(LIT_SORTASCENDING, 0),
1582 MPFROMP(pci->pszFileName));
1583 }
1584 else {
1585 WinSendMsg(hwndCnr,
1586 CM_INVALIDATERECORD,
1587 MPFROMP(&pci),
1588 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
1589 WinSendMsg(hwndDrivesList,
1590 LM_INSERTITEM,
1591 MPFROM2SHORT(LIT_SORTASCENDING, 0),
1592 MPFROMP(pci->pszFileName));
1593 }
1594 }
1595 pci = pciNext;
1596 } // while
1597 }
1598 if (hwndParent)
1599 WinSendMsg(WinWindowFromID(WinQueryWindow(hwndParent, QW_PARENT),
1600 MAIN_DRIVELIST), LM_SELECTITEM,
1601 MPFROM2SHORT(0, 0), MPFROMLONG(TRUE));
1602
1603 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1604 CM_QUERYRECORD,
1605 MPVOID,
1606 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
1607 while (pci && (INT)pci != -1) {
1608 pciNext = (PCNRITEM) WinSendMsg(hwndCnr,
1609 CM_QUERYRECORD,
1610 MPFROMP(pci),
1611 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1612 if (pci->flags & RECFLAGS_ENV) {
1613 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1614 CM_QUERYRECORD,
1615 MPFROMP(pci),
1616 MPFROM2SHORT(CMA_FIRSTCHILD,
1617 CMA_ITEMORDER));
1618 while (pci && (INT)pci != -1) {
1619 if (pci->flags & RECFLAGS_ENV)
1620 FleshEnv(hwndCnr, pci);
1621 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1622 CM_QUERYRECORD,
1623 MPFROMP(pci),
1624 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1625 }
1626 break;
1627 }
1628 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1629 CM_QUERYRECORD,
1630 MPFROMP(pci),
1631 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1632 }
1633
1634 if (!drivesbuilt && hwndMain)
1635 PostMsg(hwndMain, UM_BUILDDRIVEBAR, MPVOID, MPVOID);
1636 DosSleep(16); // 05 Aug 07 GKY 33
1637 fDummy = FALSE;
1638 DosPostEventSem(CompactSem);
1639
1640 {
1641 BYTE info;
1642 BOOL includesyours = FALSE;
1643
1644 // 10 Jan 08 SHL fixme to understand fFirstTime
1645 if (*suggest || (!(driveflags[1] & DRIVE_IGNORE) && fFirstTime)) {
1646 if (!DosDevConfig(&info, DEVINFO_FLOPPY) && info == 1) {
1647 if (!*suggest) {
1648 *suggest = '/';
1649 suggest[1] = 0;
1650 }
1651 else
1652 memmove(suggest + 2, suggest + 1, strlen(suggest));
1653 suggest[1] = 'B';
1654 }
1655 }
1656 if (*suggest) {
1657 for (x = 2; x < 26; x++) {
1658 if (driveflags[x] & DRIVE_IGNORE) {
1659 includesyours = TRUE;
1660 sprintf(suggest + strlen(suggest), "%c", (char)(x + 'A'));
1661 }
1662 }
1663 strcat(suggest, " %*");
1664 if (saymsg(MB_YESNO | MB_ICONEXCLAMATION,
1665 (hwndParent) ? hwndParent : hwndCnr,
1666 GetPString(IDS_SUGGESTTITLETEXT),
1667 GetPString(IDS_SUGGEST1TEXT),
1668 (includesyours) ? GetPString(IDS_SUGGEST2TEXT) : NullStr,
1669 suggest) == MBID_YES) {
1670 char s[64];
1671
1672 sprintf(s, "PARAMETERS=%s", suggest);
1673 WinCreateObject(WPProgram, "FM/2", s, FM3Folder, CO_UPDATEIFEXISTS);
1674 WinCreateObject(WPProgram,
1675 "FM/2 Lite", s, FM3Folder, CO_UPDATEIFEXISTS);
1676 WinCreateObject(WPProgram,
1677 "Archive Viewer/2", s, FM3Tools, CO_UPDATEIFEXISTS);
1678 WinCreateObject(WPProgram,
1679 "Dir Sizes", s, FM3Tools, CO_UPDATEIFEXISTS);
1680 WinCreateObject(WPProgram,
1681 "Visual Tree", s, FM3Tools, CO_UPDATEIFEXISTS);
1682 WinCreateObject(WPProgram,
1683 "Visual Directory", s, FM3Tools, CO_UPDATEIFEXISTS);
1684 WinCreateObject(WPProgram,
1685 "Global File Viewer", s, FM3Tools, CO_UPDATEIFEXISTS);
1686 WinCreateObject(WPProgram, "Databar", s, FM3Tools, CO_UPDATEIFEXISTS);
1687 }
1688 }
1689 }
1690 didonce = TRUE;
1691} // FillTreeCnr
1692
1693
1694/**
1695 * Empty all records from a container and free associated storage and
1696 * Free up field infos
1697 */
1698
1699VOID EmptyCnr(HWND hwnd)
1700{
1701 PFIELDINFO pfi;
1702
1703#if 0 // fixme to be gone or to be configurable
1704 {
1705 int state = _heapchk();
1706 if (state != _HEAPOK)
1707 Runtime_Error(pszSrcFile, __LINE__, "heap corrupted %d", state);
1708 }
1709#endif
1710
1711 // Remove all records
1712 RemoveCnrItems(hwnd, NULL, 0, CMA_FREE);
1713
1714 // Remove field info descriptors
1715 pfi = (PFIELDINFO) WinSendMsg(hwnd, CM_QUERYDETAILFIELDINFO, MPVOID,
1716 MPFROMSHORT(CMA_FIRST));
1717 if (pfi &&
1718 (INT)WinSendMsg(hwnd, CM_REMOVEDETAILFIELDINFO, MPVOID,
1719 MPFROM2SHORT(0, CMA_FREE)) == -1) {
1720 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_REMOVEDETAILFIELDINFO hwnd %x", hwnd);
1721 }
1722}
1723
1724/**
1725 * Free storage associated with container item
1726 */
1727
1728VOID FreeCnrItemData(PCNRITEM pci)
1729{
1730 if (pci->pszSubject) {
1731 if (pci->pszSubject != NullStr)
1732 free(pci->pszSubject);
1733 pci->pszSubject = NULL; // Catch illegal references
1734 }
1735
1736 // 08 Sep 08 SHL Remove excess logic
1737 if (pci->pszLongName) {
1738 if (pci->pszLongName != NullStr)
1739 free(pci->pszLongName);
1740 pci->pszLongName = NULL; // Catch illegal references
1741 }
1742
1743 // Bypass free if pszDisplayName points into pszFileName buffer
1744 // 05 Sep 08 SHL Correct pointer overlap compare logic
1745 if (pci->pszDisplayName) {
1746 if (pci->pszDisplayName != NullStr) {
1747 if (!pci->pszFileName ||
1748 pci->pszDisplayName < pci->pszFileName ||
1749 pci->pszDisplayName >= pci->pszFileName + _msize(pci->pszFileName))
1750 {
1751 free(pci->pszDisplayName);
1752 }
1753 }
1754 pci->pszDisplayName = NULL; // Catch illegal references
1755 }
1756
1757 if (!pci->pszFileName)
1758 Runtime_Error(pszSrcFile, __LINE__, "FreeCnrItemData attempting free %p data twice", pci);
1759 else {
1760 if (pci->pszFileName != NullStr)
1761 free(pci->pszFileName);
1762 pci->pszFileName = NULL; // Catch illegal references
1763 }
1764
1765 // 08 Sep 08 SHL Remove excess logic
1766 if (pci->pszLongName) {
1767 if (pci->pszLongName != NullStr)
1768 free(pci->pszLongName);
1769 pci->pszLongName = NULL; // Catch illegal references
1770 }
1771
1772 if (pci->pszFmtFileSize) {
1773 if (pci->pszFmtFileSize != NullStr)
1774 free(pci->pszFmtFileSize);
1775 pci->pszFmtFileSize = NULL; // Catch illegal references
1776 }
1777}
1778
1779/**
1780 * Free single container item and associated storage
1781 */
1782
1783VOID FreeCnrItem(HWND hwnd, PCNRITEM pci)
1784{
1785 // DbgMsg(pszSrcFile, __LINE__, "FreeCnrItem hwnd %x pci %p", hwnd, pci);
1786
1787 FreeCnrItemData(pci);
1788
1789 if (!WinSendMsg(hwnd, CM_FREERECORD, MPFROMP(&pci), MPFROMSHORT(1))) {
1790 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,
1791 "CM_FREERECORD hwnd %x pci %p file %s",
1792 hwnd, pci,
1793 pci && pci->pszFileName ? pci->pszFileName : "n/a");
1794 }
1795}
1796
1797/**
1798 * Free container item list and associated storage
1799 */
1800
1801VOID FreeCnrItemList(HWND hwnd, PCNRITEM pciFirst)
1802{
1803 PCNRITEM pci = pciFirst;
1804 PCNRITEM pciNext;
1805 USHORT usCount;
1806
1807 for (usCount = 0; pci; usCount++) {
1808 pciNext = (PCNRITEM) pci->rc.preccNextRecord;
1809 FreeCnrItemData(pci);
1810 pci = pciNext;
1811 }
1812
1813 if (usCount) {
1814 if (!WinSendMsg(hwnd, CM_FREERECORD, MPFROMP(&pci), MPFROMSHORT(usCount))) {
1815 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_FREERECORD hwnd %x pci %p cnt %u", hwnd, pci, usCount);
1816 }
1817 }
1818}
1819
1820/**
1821 * Remove item(s) from container and free associated storage if requested
1822 * @param pciFirst points to first item to remove or NULL to remove all
1823 * @param usCnt is remove count or 0 to remove all
1824 * @returns count of items remaining in container or -1 if error
1825 */
1826
1827INT RemoveCnrItems(HWND hwnd, PCNRITEM pciFirst, USHORT usCnt, USHORT usFlags)
1828{
1829 INT remaining = usCnt;
1830 PCNRITEM pci;
1831
1832 if ((usCnt && !pciFirst) || (!usCnt && pciFirst)) {
1833 Runtime_Error(pszSrcFile, __LINE__, "pciFirst %p usCnt %u mismatch", pciFirst, usCnt);
1834 remaining = -1;
1835 }
1836 else {
1837 // Free our buffers if free requested
1838 if (usFlags & CMA_FREE) {
1839 if (pciFirst)
1840 pci = pciFirst;
1841 else {
1842 pci = (PCNRITEM)WinSendMsg(hwnd, CM_QUERYRECORD, MPVOID,
1843 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
1844 if ((INT)pci == -1) {
1845 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_QUERYRECORD");
1846 remaining = -1;
1847 pci = NULL;
1848 }
1849 }
1850 while (pci) {
1851 // 12 Sep 07 SHL dwg drivebar crash testing - ticket# ???
1852 static PCNRITEM pciLast; // 12 Sep 07 SHL
1853 ULONG ulSize = sizeof(*pci);
1854 ULONG ulAttr;
1855 APIRET apiret = DosQueryMem((PVOID)pci, &ulSize, &ulAttr);
1856 if (apiret)
1857 Dos_Error(MB_ENTER, apiret, HWND_DESKTOP, pszSrcFile, __LINE__,
1858 "DosQueryMem failed pci %p pciLast %p", pci, pciLast);
1859 FreeCnrItemData(pci);
1860 pciLast = pci;
1861 pci = (PCNRITEM)pci->rc.preccNextRecord;
1862 if (remaining && --remaining == 0)
1863 break;
1864 }
1865 }
1866 }
1867
1868 // DbgMsg(pszSrcFile, __LINE__, "RemoveCnrItems %p %u %s", pci, usCnt, pci->pszFileName);
1869
1870 if (remaining != - 1) {
1871 remaining = (INT)WinSendMsg(hwnd, CM_REMOVERECORD, MPFROMP(&pciFirst), MPFROM2SHORT(usCnt, usFlags));
1872 if (remaining == -1) {
1873 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_REMOVERECORD hwnd %x pci %p cnt %u", hwnd, pciFirst, usCnt);
1874 }
1875 }
1876
1877 return remaining;
1878}
1879
1880#pragma alloc_text(FILLDIR,FillInRecordFromFFB,FillInRecordFromFSA,IDFile)
1881#pragma alloc_text(FILLDIR1,ProcessDirectory,FillDirCnr,FillTreeCnr,FileAttrToString,StubbyScanThread)
1882#pragma alloc_text(EMPTYCNR,EmptyCnr,FreeCnrItemData,FreeCnrItem,FreeCnrItemList,RemoveCnrItems)
1883
Note: See TracBrowser for help on using the repository browser.