source: trunk/dll/filldir.c@ 1459

Last change on this file since 1459 was 1459, checked in by Steven Levine, 16 years ago

Show rescan progress while filling container, ticket #291

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