source: trunk/dll/filldir.c@ 1344

Last change on this file since 1344 was 1335, checked in by Steven Levine, 17 years ago

Ticket 26: Add exception handlers to all threads using xbeginthread

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