source: trunk/dll/filldir.c@ 1316

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

Code clean up -- remove redundant code; move code to match openwatcom requirements etc.

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