source: trunk/dll/filldir.c@ 1323

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

Use event semaphore to prevent rescan of drives while StubbySacnTreads are still running; code cleanup.

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