source: trunk/dll/filldir.c@ 1330

Last change on this file since 1330 was 1328, checked in by Gregg Young, 17 years ago

Code cleanup replace sizeof calls for threaded drive scans

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