source: trunk/dll/filldir.c@ 1308

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

FreeCnrItemData: optimize and always NULL pointers
StubbyScanThread: restore else - we want all drives listed
FreeCnrItemData: report double free with Runtime_Error

  • 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 1308 2008-11-30 23:40:08Z stevenhl $
5
6 Fill Directory Tree Containers
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2001, 2008 Steven H. Levine
10
11 10 Jan 04 SHL ProcessDirectory: avoid most large drive failures
12 24 May 05 SHL Rework Win_Error usage
13 24 May 05 SHL Rework for CNRITEM.szSubject
14 25 May 05 SHL Rework for ULONGLONG
15 25 May 05 SHL Rework FillInRecordFromFFB
16 25 May 05 SHL Rework FillTreeCnr
17 28 May 05 SHL Drop stale debug code
18 05 Jun 05 SHL Comments
19 09 Jun 05 SHL Rework WinLoadFileIcon enables
20 09 Jun 05 SHL Rework IDFile
21 13 Aug 05 SHL Renames
22 24 Oct 05 SHL FillInRecordFromFFB: correct longname display enable
23 24 Oct 05 SHL FillInRecordFromFSA: correct longname display enable
24 24 Oct 05 SHL Drop obsolete code
25 22 Jul 06 SHL Check more run time errors
26 20 Oct 06 SHL Sync . .. check code
27 22 Oct 06 GKY Add NDFS32 support
28 17 Feb 07 GKY Additional archive and image file tyoes identifed by extension
29 17 Feb 07 GKY Add more drive types
30 09 Mar 07 GKY Use SelectDriveIcon
31 20 Mar 07 GKY Increase extention check to 4 letters for icon selections
32 23 Jun 07 GKY Fixed ram disk without a directory not appearing on states drive list
33 23 Jul 07 SHL Sync with CNRITEM updates (ticket#24)
34 29 Jul 07 SHL Add CNRITEM free and remove support (ticket#24)
35 02 Aug 07 SHL Add FileAttrToString
36 03 Aug 07 GKY Enlarged and made setable everywhere Findbuf (speed file loading)
37 04 Aug 07 SHL Update #pragma alloc_test for new functions
38 06 Aug 07 GKY Reduce DosSleep times (ticket 148)
39 13 Aug 07 SHL Sync code with other FilesToGet usage and optimize
40 13 Aug 07 SHL Move #pragma alloc_text to end for OpenWatcom compat
41 04 Nov 07 GKY Use commaFmtULL to display large file sizes
42 29 Feb 08 GKY Use xfree where appropriate
43 07 Jul 08 SHL Use NULL rather than NullStr in FreeCnrItemData
44 16 JUL 08 GKY Use TMP directory for temp files
45 20 Jul 08 JBS Ticket 114: Support user-selectable env. strings in Tree container.
46 21 Jul 08 JBS Ticket 114: Change env var separator from blank to semicolon
47 02 Aug 08 GKY Remove redundant strcpys from inner loop
48 23 Aug 08 GKY Free pszDisplayName when appropriate
49 01 Sep 08 GKY Updated FreeCnrItemData to prevent trap in strrchr if pci->pszFileName is NULL.
50 05 Sep 08 SHL Correct FreeCnrItemData pszDisplayName pointer overlap check
51 08 Sep 08 SHL Remove extra pszLongName logic in FreeCnrItemData
52 18 Oct 08 GKY Scan drives in 4 passes (local, virtual, remote, flagged slow) to speed tree scans
53 19 Nov 08 SHL Correct and sanitize 4 pass scan logic
54 21 Nov 08 SHL FillTreeCnr: ensure any unchecked drives checked in pass 4
55 24 Nov 08 GKY Add StubyScanThread to treecnr scan/rescan drives all on separate threads
56 24 Nov 08 GKY Replace 4 pass drive scan code with StubyScanThread multithread scan
57 28 Nov 08 SHL FreeCnrItemData: optimize and always NULL pointers
58 28 Nov 08 SHL StubbyScanThread: add else lost in translation
59 30 Nov 08 SHL StubbyScanThread: restore else - we want all drives listed
60 30 Nov 08 SHL FreeCnrItemData: report double free with Runtime_Error
61
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 =
997 !fSyncUpdates && dcd && dcd->type == DIR_FRAME ?
998 FALSE : TRUE;
999 if (!WinSendMsg(hwndCnr,
1000 CM_INSERTRECORD,
1001 MPFROMP(pciFirst), MPFROMP(&ri))) {
1002 DosSleep(10); // Give GUI time to work
1003 WinSetFocus(HWND_DESKTOP, hwndCnr);
1004 if (!WinSendMsg(hwndCnr,
1005 CM_INSERTRECORD,
1006 MPFROMP(pciFirst), MPFROMP(&ri))) {
1007 Win_Error2(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1008 IDS_CMINSERTERRTEXT);
1009 ok = FALSE;
1010 ullTotalBytes = 0;
1011 if (WinIsWindow((HAB) 0, hwndCnr))
1012 FreeCnrItemList(hwndCnr, pciFirst);
1013 }
1014 // }
1015 }
1016 }
1017 if (ok) {
1018 ullReturnBytes += ullTotalBytes;
1019 ulReturnFiles += ulSelCnt;
1020 }
1021 } // if sync updates
1022 else {
1023 // Append newly selected entries to aggregate list
1024 paffbTemp = xrealloc(paffbTotal,
1025 sizeof(FILEFINDBUF4L) * (ulSelCnt + ulTotal),
1026 pszSrcFile, __LINE__);
1027 if (paffbTemp) {
1028 // 13 Aug 07 SHL fixme to optimize copy
1029 paffbTotal = paffbTemp;
1030 for (x = 0; x < ulSelCnt; x++)
1031 paffbTotal[x + ulTotal] = *papffbSelected[x];
1032 ulTotal += ulSelCnt;
1033 }
1034 else {
1035 saymsg(MB_ENTER,
1036 HWND_DESKTOP,
1037 GetPString(IDS_ERRORTEXT), GetPString(IDS_OUTOFMEMORY));
1038 break;
1039 }
1040 }
1041 } // if entries selected
1042 if (stopflag && *stopflag)
1043 goto Abort;
1044 DosError(FERR_DISABLEHARDERR);
1045 ulFindCnt = ulFindMax;
1046 rc = xDosFindNext(hdir, paffbFound, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZEL);
1047 priority_normal();
1048 if (rc)
1049 DosError(FERR_DISABLEHARDERR);
1050 } while (!rc);
1051
1052 DosFindClose(hdir);
1053 xfree(paffbFound, pszSrcFile, __LINE__);
1054 paffbFound = NULL;
1055 xfree(papffbSelected, pszSrcFile, __LINE__);
1056 papffbSelected = NULL;
1057
1058 if (ulTotal && paffbTotal) {
1059
1060 if (stopflag && *stopflag)
1061 goto Abort;
1062
1063 pciFirst = WinSendMsg(hwndCnr, CM_ALLOCRECORD,
1064 MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(ulTotal));
1065 if (!pciFirst) {
1066 Win_Error2(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1067 IDS_CMALLOCRECERRTEXT);
1068 ok = FALSE;
1069 ullTotalBytes = 0;
1070 }
1071 else {
1072 // 04 Jan 08 SHL fixme like comp.c to handle less than ulSelCnt records
1073 pci = pciFirst;
1074 ullTotalBytes = 0;
1075 pffbFile = paffbTotal;
1076 for (x = 0; x < ulTotal; x++) {
1077 ullBytes = FillInRecordFromFFB(hwndCnr, pci, pszFileSpec,
1078 pffbFile, partial, dcd);
1079 pci = (PCNRITEM) pci->rc.preccNextRecord;
1080 ullTotalBytes += ullBytes;
1081 // Can not use offset since we have merged lists - this should be equivalent
1082 pffbFile = (PFILEFINDBUF4L)((PBYTE)pffbFile + sizeof(FILEFINDBUF4L));
1083 }
1084 if (ulTotal) {
1085 memset(&ri, 0, sizeof(RECORDINSERT));
1086 ri.cb = sizeof(RECORDINSERT);
1087 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1088 ri.pRecordParent = (PRECORDCORE) pciParent;
1089 ri.zOrder = (ULONG) CMA_TOP;
1090 ri.cRecordsInsert = ulTotal;
1091 ri.fInvalidateRecord = (!fSyncUpdates && dcd &&
1092 dcd->type == DIR_FRAME) ? FALSE : TRUE;
1093 if (!WinSendMsg(hwndCnr, CM_INSERTRECORD,
1094 MPFROMP(pciFirst), MPFROMP(&ri))) {
1095 DosSleep(10); // Give GUI time to work
1096 WinSetFocus(HWND_DESKTOP, hwndCnr);
1097 if (!WinSendMsg(hwndCnr, CM_INSERTRECORD,
1098 MPFROMP(pciFirst), MPFROMP(&ri))) {
1099 Win_Error2(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1100 IDS_CMINSERTERRTEXT);
1101 ok = FALSE;
1102 ullTotalBytes = 0;
1103 if (WinIsWindow((HAB) 0, hwndCnr))
1104 FreeCnrItemList(hwndCnr, pciFirst);
1105 }
1106 }
1107 }
1108 }
1109 if (ok) {
1110 ullReturnBytes += ullTotalBytes;
1111 ulReturnFiles += ulFindCnt;
1112 }
1113 }
1114 }
1115
1116 /**
1117 * DosFind for subdirectories of a read-only directory on a FAT volume
1118 * returns path not found if there are no subdirectories
1119 * FAT FS seems to ignore . and .. in this case
1120 * Map to no more files
1121 * We could verify that directory is marked read-only, it's probably not
1122 * worth the extra code since we do verify 2 out of 3 prerequisites
1123 * 15 Jan 08 SHL
1124 */
1125 if (rc == ERROR_PATH_NOT_FOUND && !filestoo) {
1126 ULONG ulDriveType = 0;
1127 CHAR szFSType[CCHMAXPATH];
1128 INT removable = CheckDrive(*pszFileSpec, szFSType, &ulDriveType);
1129 if (removable != -1 && strcmp(szFSType, "FAT") == 0)
1130 rc = ERROR_NO_MORE_FILES;
1131 }
1132
1133 if (rc && rc != ERROR_NO_MORE_FILES) {
1134 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
1135 GetPString(IDS_CANTFINDDIRTEXT), pszFileSpec);
1136 }
1137
1138 if (!fSyncUpdates && dcd && dcd->type == DIR_FRAME)
1139 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPVOID,
1140 MPFROM2SHORT(0, CMA_ERASE));
1141 }
1142Abort:
1143 xfree(paffbTotal, pszSrcFile, __LINE__);
1144 xfree(pszFileSpec, pszSrcFile, __LINE__);
1145 xfree(paffbFound, pszSrcFile, __LINE__);
1146 xfree(papffbSelected, pszSrcFile, __LINE__);
1147
1148 if (recurse) {
1149 pci = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pciParent),
1150 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
1151 while (pci && (INT)pci != -1) {
1152 if (pci->attrFile & FILE_DIRECTORY)
1153 Stubby(hwndCnr, pci);
1154 pci = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
1155 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1156 }
1157 }
1158
1159 if (pulTotalFiles)
1160 *pulTotalFiles = ulReturnFiles;
1161
1162 if (pullTotalBytes)
1163 *pullTotalBytes = ullReturnBytes;
1164
1165} // ProcessDirectory
1166
1167VOID FillDirCnr(HWND hwndCnr,
1168 CHAR * pszDirectory,
1169 DIRCNRDATA * dcd,
1170 PULONGLONG pullTotalBytes)
1171{
1172 ProcessDirectory(hwndCnr,
1173 (PCNRITEM)NULL,
1174 pszDirectory,
1175 TRUE, // filestoo
1176 FALSE, // recurse
1177 TRUE, // partial
1178 dcd ? &dcd->stopflag : NULL,
1179 dcd,
1180 NULL, // total files
1181 pullTotalBytes);
1182 DosPostEventSem(CompactSem);
1183
1184#if 0 // fixme to be gone or to be configurable
1185 {
1186 int state = _heapchk();
1187 if (state != _HEAPOK)
1188 Runtime_Error(pszSrcFile, __LINE__, "heap corrupted %d", state);
1189 else
1190 DbgMsg(pszSrcFile, __LINE__, "_memavl %u", _memavl());
1191 }
1192#endif
1193
1194} // FillDirCnr
1195
1196VOID FillTreeCnr(HWND hwndCnr, HWND hwndParent)
1197{
1198 ULONG ulCurDriveNum, ulDriveMap, numtoinsert = 0;
1199 ULONG ulDriveType;
1200 PCNRITEM pci, pciFirst = NULL, pciNext, pciParent = NULL;
1201 INT x, removable;
1202 CHAR suggest[32];
1203 CHAR szDrive[] = " :\\";
1204 CHAR szFSType[CCHMAXPATH];
1205 FILESTATUS4L fsa4;
1206 APIRET rc;
1207 BOOL drivesbuilt = FALSE;
1208 ULONG startdrive = 3;
1209 static BOOL didonce = FALSE;
1210
1211 fDummy = TRUE;
1212 *suggest = 0;
1213 for (x = 0; x < 26; x++) {
1214 driveflags[x] &= (DRIVE_IGNORE | DRIVE_NOPRESCAN | DRIVE_NOLOADICONS |
1215 DRIVE_NOLOADSUBJS | DRIVE_NOLOADLONGS |
1216 DRIVE_INCLUDEFILES | DRIVE_SLOW | DRIVE_NOSTATS);
1217 }
1218 memset(driveserial, -1, sizeof(driveserial));
1219
1220 DosError(FERR_DISABLEHARDERR);
1221 if (!DosQuerySysInfo(QSV_BOOT_DRIVE,
1222 QSV_BOOT_DRIVE,
1223 (PVOID) &startdrive,
1224 (ULONG) sizeof(ULONG)) &&
1225 startdrive)
1226 {
1227 driveflags[startdrive - 1] |= DRIVE_BOOT;
1228 }
1229
1230 DosError(FERR_DISABLEHARDERR);
1231 rc = DosQCurDisk(&ulCurDriveNum, &ulDriveMap);
1232 if (rc) {
1233 Dos_Error(MB_CANCEL,
1234 rc,
1235 HWND_DESKTOP,
1236 pszSrcFile, __LINE__, GetPString(IDS_FILLDIRQCURERRTEXT));
1237 exit(0);
1238 }
1239
1240 // Calc number of drive items to create
1241 for (x = 0; x < 26; x++) {
1242 if ((ulDriveMap & (1L << x)) && !(driveflags[x] & DRIVE_IGNORE))
1243 numtoinsert++;
1244 }
1245
1246 if (numtoinsert) {
1247 pciFirst = WinSendMsg(hwndCnr,
1248 CM_ALLOCRECORD,
1249 MPFROMLONG(EXTRA_RECORD_BYTES),
1250 MPFROMLONG((ULONG) numtoinsert));
1251 }
1252
1253 if (!pciFirst) {
1254 Win_Error2(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__, IDS_CMALLOCRECERRTEXT);
1255 // 04 Jan 08 SHL fixme not just up and die
1256 exit(0);
1257 }
1258
1259 // 04 Jan 08 SHL fixme like comp.c to handle less than ulSelCnt records
1260 pci = pciFirst;
1261 for (x = 0; x < 26; x++) {
1262 if ((ulDriveMap & (1L << x)) && !(driveflags[x] & DRIVE_IGNORE)) {
1263
1264 CHAR s[80];
1265 ULONG flags = 0;
1266 ULONG size = sizeof(ULONG);
1267
1268 *szDrive = (CHAR)x + 'A'; // Build path spec
1269
1270 sprintf(s, "%c.DriveFlags", toupper(*szDrive));
1271 if (PrfQueryProfileData(fmprof, appname, s, &flags, &size) &&
1272 size == sizeof(ULONG)) {
1273 driveflags[toupper(*szDrive) - 'A'] |= flags;
1274 }
1275
1276 if (x > 1) {
1277 // Hard drive (2..N)
1278 if (!(driveflags[x] & DRIVE_NOPRESCAN)) {
1279 *szFSType = 0;
1280 ulDriveType = 0;
1281 removable = CheckDrive(*szDrive, szFSType, &ulDriveType);
1282 driveserial[x] = -1;
1283 if (removable != -1) {
1284 struct {
1285 ULONG serial;
1286 CHAR volumelength;
1287 CHAR volumelabel[CCHMAXPATH];
1288 } volser;
1289
1290 DosError(FERR_DISABLEHARDERR);
1291 if (!DosQueryFSInfo((ULONG) x,
1292 FSIL_VOLSER, &volser, sizeof(volser))) {
1293 driveserial[x] = volser.serial;
1294 }
1295 }
1296 else
1297 driveflags[x] |= DRIVE_INVALID;
1298
1299 memset(&fsa4, 0, sizeof(FILESTATUS4L));
1300 driveflags[x] |= removable == -1 || removable == 1 ?
1301 DRIVE_REMOVABLE : 0;
1302 if (ulDriveType & DRIVE_REMOTE)
1303 driveflags[x] |= DRIVE_REMOTE;
1304 if (!stricmp(szFSType,RAMFS)) {
1305 driveflags[x] |= DRIVE_RAMDISK;
1306 driveflags[x] &= ~DRIVE_REMOTE;
1307 }
1308 if (!stricmp(szFSType,NDFS32)) {
1309 driveflags[x] |= DRIVE_VIRTUAL;
1310 driveflags[x] &= ~DRIVE_REMOTE;
1311 }
1312 if (!stricmp(szFSType,NTFS))
1313 driveflags[x] |= DRIVE_NOTWRITEABLE;
1314 if (strcmp(szFSType, HPFS) &&
1315 strcmp(szFSType, JFS) &&
1316 strcmp(szFSType, ISOFS) &&
1317 strcmp(szFSType, CDFS) &&
1318 strcmp(szFSType, FAT32) &&
1319 strcmp(szFSType, NDFS32) &&
1320 strcmp(szFSType, RAMFS) &&
1321 strcmp(szFSType, NTFS) &&
1322 strcmp(szFSType, HPFS386)) {
1323 driveflags[x] |= DRIVE_NOLONGNAMES;
1324 }
1325
1326 if (!strcmp(szFSType, CDFS) || !strcmp(szFSType,ISOFS)) {
1327 removable = 1;
1328 driveflags[x] |= DRIVE_REMOVABLE | DRIVE_NOTWRITEABLE |
1329 DRIVE_CDROM;
1330 }
1331 else if (!stricmp(szFSType, CBSIFS)) {
1332 driveflags[x] |= DRIVE_ZIPSTREAM;
1333 driveflags[x] &= ~DRIVE_REMOTE;
1334 if (ulDriveType & DRIVE_REMOVABLE)
1335 driveflags[x] |= DRIVE_REMOVABLE;
1336 if (!(ulDriveType & DRIVE_NOLONGNAMES))
1337 driveflags[x] &= ~DRIVE_NOLONGNAMES;
1338 }
1339
1340 pci->rc.flRecordAttr |= CRA_RECORDREADONLY;
1341 // if ((ULONG) (toupper(*pci->pszFileName) - '@') == ulCurDriveNum) // 23 Jul 07 SHL
1342 if ((ULONG)(toupper(*szDrive) - '@') == ulCurDriveNum)
1343 pci->rc.flRecordAttr |= (CRA_CURSORED | CRA_SELECTED);
1344
1345 if (removable == 0) {
1346 // Fixed volume
1347 pci->attrFile |= FILE_DIRECTORY;
1348 DosError(FERR_DISABLEHARDERR);
1349 rc = DosQueryPathInfo(szDrive,
1350 FIL_QUERYEASIZEL,
1351 &fsa4, (ULONG) sizeof(FILESTATUS4L));
1352 // ERROR_BAD_NET_RSP = 58
1353 if (rc == 58) {
1354 DosError(FERR_DISABLEHARDERR);
1355 rc = DosQueryPathInfo(szDrive,
1356 FIL_STANDARDL,
1357 &fsa4, (ULONG) sizeof(FILESTATUS4L));
1358 fsa4.cbList = 0;
1359 }
1360 if (rc && !didonce) {
1361 // Guess drive letter
1362 if (!*suggest) {
1363 *suggest = '/';
1364 suggest[1] = 0;
1365 }
1366 sprintf(suggest + strlen(suggest), "%c" , toupper(*szDrive));
1367 pci->pszFileName = xstrdup(szDrive, pszSrcFile, __LINE__);
1368 //strcpy(pci->pszFileName, szDrive);
1369 pci->pszDisplayName = pci->pszFileName;
1370 pci->rc.pszIcon = pci->pszDisplayName;
1371 pci->attrFile = FILE_DIRECTORY;
1372 pci->pszDispAttr = FileAttrToString(pci->attrFile);
1373 driveserial[x] = -1;
1374 }
1375 else
1376 FillInRecordFromFSA(hwndCnr, pci, szDrive, &fsa4, TRUE, NULL);
1377 }
1378 else {
1379 // Removable volume
1380 pci->pszFileName = xstrdup(szDrive, pszSrcFile, __LINE__);
1381 //strcpy(pci->pszFileName, szDrive);
1382 pci->pszDisplayName = pci->pszFileName;
1383 pci->rc.pszIcon = pci->pszDisplayName;
1384 pci->attrFile = FILE_DIRECTORY;
1385 pci->pszDispAttr = FileAttrToString(pci->attrFile);
1386 }
1387 SelectDriveIcon(pci);
1388# ifdef FORTIFY
1389 // Will be freed by TreeCnrWndProc WM_DESTROY
1390 Fortify_SetScope(pci->pszFileName, 2);
1391# endif
1392 }
1393 else {
1394 pci->rc.hptrIcon = hptrDunno;
1395 pci->pszFileName = xstrdup(szDrive, pszSrcFile, __LINE__);
1396 // strcpy(pci->pszFileName, szDrive); // 22 Jul 08 SHL No need to do this twice
1397# ifdef FORTIFY
1398 // Will be freed by TreeCnrWndProc WM_DESTROY
1399 Fortify_SetScope(pci->pszFileName, 2);
1400# endif
1401 pci->pszDisplayName = pci->pszFileName;
1402 pci->rc.pszIcon = pci->pszFileName;
1403 pci->attrFile = FILE_DIRECTORY;
1404 pci->pszDispAttr = FileAttrToString(pci->attrFile);
1405 driveserial[x] = -1;
1406 }
1407 }
1408 else {
1409 // diskette drive (A or B)
1410 pci->rc.hptrIcon = hptrFloppy;
1411 pci->pszFileName = xstrdup(szDrive, pszSrcFile, __LINE__);
1412 //strcpy(pci->pszFileName, szDrive);
1413 pci->pszDisplayName = pci->pszFileName;
1414 pci->rc.pszIcon = pci->pszDisplayName;
1415 pci->attrFile = FILE_DIRECTORY;
1416 pci->pszDispAttr = FileAttrToString(pci->attrFile);
1417 driveflags[x] |= (DRIVE_REMOVABLE | DRIVE_NOLONGNAMES);
1418 driveserial[x] = -1;
1419 }
1420 pci->rc.flRecordAttr |= CRA_RECORDREADONLY;
1421 pci = (PCNRITEM) pci->rc.preccNextRecord; // next rec
1422 }
1423 else if (!(ulDriveMap & (1L << x)))
1424 driveflags[x] |= DRIVE_INVALID;
1425 } // for drives
1426
1427 PostMsg(hwndMain, UM_BUILDDRIVEBAR, MPVOID, MPVOID);
1428 drivesbuilt = TRUE;
1429
1430 // insert the drives
1431 if (numtoinsert && pciFirst) {
1432 RECORDINSERT ri;
1433
1434 memset(&ri, 0, sizeof(RECORDINSERT));
1435 ri.cb = sizeof(RECORDINSERT);
1436 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1437 ri.pRecordParent = (PRECORDCORE) NULL;
1438 ri.zOrder = (ULONG) CMA_TOP;
1439 ri.cRecordsInsert = numtoinsert;
1440 ri.fInvalidateRecord = FALSE;
1441 if (!WinSendMsg(hwndCnr,
1442 CM_INSERTRECORD, MPFROMP(pciFirst), MPFROMP(&ri)))
1443 {
1444 Win_Error2(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1445 IDS_CMINSERTERRTEXT);
1446 }
1447 }
1448
1449 // move cursor onto the default drive rather than the first drive
1450 if (!fSwitchTree) {
1451 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1452 CM_QUERYRECORD,
1453 MPVOID,
1454 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
1455 while (pci && (INT)pci != -1) {
1456 if ((ULONG) (toupper(*pci->pszFileName) - '@') == ulCurDriveNum) {
1457 WinSendMsg(hwndCnr,
1458 CM_SETRECORDEMPHASIS,
1459 MPFROMP(pci), MPFROM2SHORT(TRUE, CRA_CURSORED));
1460 break;
1461 }
1462 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1463 CM_QUERYRECORD,
1464 MPFROMP(pci),
1465 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1466 }
1467 }
1468
1469 if (hwndParent) {
1470 WinSendMsg(WinWindowFromID(WinQueryWindow(hwndParent, QW_PARENT),
1471 MAIN_DRIVELIST),
1472 LM_DELETEALL, MPVOID, MPVOID);
1473 }
1474
1475 if (fShowEnv) {
1476 RECORDINSERT ri;
1477
1478 pciParent = WinSendMsg(hwndCnr,
1479 CM_ALLOCRECORD,
1480 MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(1));
1481 if (pciParent) {
1482 pciParent->flags |= RECFLAGS_ENV;
1483 pciParent->pszFileName = xstrdup(GetPString(IDS_ENVVARSTEXT), pszSrcFile, __LINE__);
1484 //strcpy(pciParent->pszFileName, GetPString(IDS_ENVVARSTEXT));
1485 pciParent->pszDisplayName = pciParent->pszFileName; // 03 Aug 07 SHL
1486 pciParent->rc.hptrIcon = hptrEnv;
1487 pciParent->rc.pszIcon = pciParent->pszFileName;
1488 pciParent->pszDispAttr = FileAttrToString(0);
1489 memset(&ri, 0, sizeof(RECORDINSERT));
1490 ri.cb = sizeof(RECORDINSERT);
1491 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1492 ri.pRecordParent = (PRECORDCORE) NULL;
1493 ri.zOrder = (ULONG) CMA_TOP;
1494 ri.cRecordsInsert = 1;
1495 ri.fInvalidateRecord = FALSE;
1496 if (WinSendMsg(hwndCnr,
1497 CM_INSERTRECORD, MPFROMP(pciParent), MPFROMP(&ri))) {
1498
1499 char *p, *pp;
1500
1501 p = pszTreeEnvVarList;
1502 while (*p == ';')
1503 p++;
1504 while (*p) {
1505 *szFSType = 0;
1506 pp = szFSType;
1507 while (*p && *p != ';')
1508 *pp++ = *p++;
1509 *pp = 0;
1510 while (*p == ';')
1511 p++;
1512 if (*szFSType &&
1513 (!stricmp(szFSType, "LIBPATH") || getenv(szFSType))) {
1514 pci = WinSendMsg(hwndCnr,
1515 CM_ALLOCRECORD,
1516 MPFROMLONG(EXTRA_RECORD_BYTES),
1517 MPFROMLONG(1));
1518 if (pci) {
1519 CHAR fname[CCHMAXPATH];
1520 pci->flags |= RECFLAGS_ENV;
1521 sprintf(fname, "%%%s%%", szFSType);
1522 pci->pszFileName = xstrdup(fname, pszSrcFile, __LINE__);
1523 pci->rc.hptrIcon = hptrEnv;
1524 pci->rc.pszIcon = pci->pszFileName;
1525 pci->pszDispAttr = FileAttrToString(0);
1526 memset(&ri, 0, sizeof(RECORDINSERT));
1527 ri.cb = sizeof(RECORDINSERT);
1528 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1529 ri.pRecordParent = (PRECORDCORE) pciParent;
1530 ri.zOrder = (ULONG) CMA_TOP;
1531 ri.cRecordsInsert = 1;
1532 ri.fInvalidateRecord = FALSE;
1533 if (!WinSendMsg(hwndCnr,
1534 CM_INSERTRECORD,
1535 MPFROMP(pci), MPFROMP(&ri))) {
1536 Win_Error2(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1537 IDS_CMINSERTERRTEXT);
1538 FreeCnrItem(hwndCnr, pci);
1539 }
1540 }
1541 }
1542 }
1543 WinSendMsg(hwndCnr,
1544 CM_INVALIDATERECORD,
1545 MPFROMP(&pciParent),
1546 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
1547 }
1548 else
1549 FreeCnrItem(hwndCnr, pciParent);
1550 }
1551 } // if show env
1552 {
1553 STUBBYSCAN *StubbyScan;
1554 HWND hwndDrivesList = WinWindowFromID(WinQueryWindow(hwndParent, QW_PARENT),
1555 MAIN_DRIVELIST);
1556
1557 //AddDrive = TRUE;
1558 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1559 CM_QUERYRECORD,
1560 MPVOID,
1561 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
1562
1563 while (pci && (INT)pci != -1) {
1564 StubbyScan = xmallocz(sizeof(STUBBYSCAN), pszSrcFile, __LINE__);
1565 if (!StubbyScan)
1566 break;
1567 StubbyScan->pci = pci;
1568 StubbyScan->hwndCnr = hwndCnr;
1569 StubbyScan->hwndDrivesList = hwndDrivesList;
1570 StubbyScan->RamDrive = FALSE;
1571 pciNext = (PCNRITEM) WinSendMsg(hwndCnr,
1572 CM_QUERYRECORD,
1573 MPFROMP(pci),
1574 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1575 if (~pci->flags & RECFLAGS_ENV) {
1576 ULONG drvNum = toupper(*pci->pszFileName) - 'A'; // 0..25
1577 if (drvNum == ulCurDriveNum || drvNum >= 2) {
1578 ULONG flags = driveflags[drvNum]; // Speed up
1579 if (~flags & DRIVE_INVALID &&
1580 ~flags & DRIVE_NOPRESCAN &&
1581 (!fNoRemovableScan || ~flags & DRIVE_REMOVABLE))
1582 {
1583 if (DRIVE_RAMDISK)
1584 StubbyScan->RamDrive = TRUE;
1585 rc = _beginthread(StubbyScanThread, NULL, 65536, StubbyScan);
1586 if (rc == -1)
1587 Runtime_Error(pszSrcFile, __LINE__,
1588 GetPString(IDS_COULDNTSTARTTHREADTEXT));
1589 } // if drive for scanning
1590 else
1591 WinSendMsg(hwndDrivesList,
1592 LM_INSERTITEM,
1593 MPFROM2SHORT(LIT_SORTASCENDING, 0),
1594 MPFROMP(pci->pszFileName));
1595 }
1596 else {
1597 WinSendMsg(hwndCnr,
1598 CM_INVALIDATERECORD,
1599 MPFROMP(&pci),
1600 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
1601 WinSendMsg(hwndDrivesList,
1602 LM_INSERTITEM,
1603 MPFROM2SHORT(LIT_SORTASCENDING, 0),
1604 MPFROMP(pci->pszFileName));
1605 }
1606 }
1607 pci = pciNext;
1608 } // while
1609 }
1610 if (hwndParent)
1611 WinSendMsg(WinWindowFromID(WinQueryWindow(hwndParent, QW_PARENT),
1612 MAIN_DRIVELIST), LM_SELECTITEM,
1613 MPFROM2SHORT(0, 0), MPFROMLONG(TRUE));
1614
1615 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1616 CM_QUERYRECORD,
1617 MPVOID,
1618 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
1619 while (pci && (INT)pci != -1) {
1620 pciNext = (PCNRITEM) WinSendMsg(hwndCnr,
1621 CM_QUERYRECORD,
1622 MPFROMP(pci),
1623 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1624 if (pci->flags & RECFLAGS_ENV) {
1625 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1626 CM_QUERYRECORD,
1627 MPFROMP(pci),
1628 MPFROM2SHORT(CMA_FIRSTCHILD,
1629 CMA_ITEMORDER));
1630 while (pci && (INT)pci != -1) {
1631 if (pci->flags & RECFLAGS_ENV)
1632 FleshEnv(hwndCnr, pci);
1633 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1634 CM_QUERYRECORD,
1635 MPFROMP(pci),
1636 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1637 }
1638 break;
1639 }
1640 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1641 CM_QUERYRECORD,
1642 MPFROMP(pci),
1643 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1644 }
1645
1646 if (!drivesbuilt && hwndMain)
1647 PostMsg(hwndMain, UM_BUILDDRIVEBAR, MPVOID, MPVOID);
1648 DosSleep(16); // 05 Aug 07 GKY 33
1649 fDummy = FALSE;
1650 DosPostEventSem(CompactSem);
1651
1652 {
1653 BYTE info;
1654 BOOL includesyours = FALSE;
1655
1656 // 10 Jan 08 SHL fixme to understand fFirstTime
1657 if (*suggest || (!(driveflags[1] & DRIVE_IGNORE) && fFirstTime)) {
1658 if (!DosDevConfig(&info, DEVINFO_FLOPPY) && info == 1) {
1659 if (!*suggest) {
1660 *suggest = '/';
1661 suggest[1] = 0;
1662 }
1663 else
1664 memmove(suggest + 2, suggest + 1, strlen(suggest));
1665 suggest[1] = 'B';
1666 }
1667 }
1668 if (*suggest) {
1669 for (x = 2; x < 26; x++) {
1670 if (driveflags[x] & DRIVE_IGNORE) {
1671 includesyours = TRUE;
1672 sprintf(suggest + strlen(suggest), "%c", (char)(x + 'A'));
1673 }
1674 }
1675 strcat(suggest, " %*");
1676 if (saymsg(MB_YESNO | MB_ICONEXCLAMATION,
1677 (hwndParent) ? hwndParent : hwndCnr,
1678 GetPString(IDS_SUGGESTTITLETEXT),
1679 GetPString(IDS_SUGGEST1TEXT),
1680 (includesyours) ? GetPString(IDS_SUGGEST2TEXT) : NullStr,
1681 suggest) == MBID_YES) {
1682 char s[64];
1683
1684 sprintf(s, "PARAMETERS=%s", suggest);
1685 WinCreateObject(WPProgram, "FM/2", s, FM3Folder, CO_UPDATEIFEXISTS);
1686 WinCreateObject(WPProgram,
1687 "FM/2 Lite", s, FM3Folder, CO_UPDATEIFEXISTS);
1688 WinCreateObject(WPProgram,
1689 "Archive Viewer/2", s, FM3Tools, CO_UPDATEIFEXISTS);
1690 WinCreateObject(WPProgram,
1691 "Dir Sizes", s, FM3Tools, CO_UPDATEIFEXISTS);
1692 WinCreateObject(WPProgram,
1693 "Visual Tree", s, FM3Tools, CO_UPDATEIFEXISTS);
1694 WinCreateObject(WPProgram,
1695 "Visual Directory", s, FM3Tools, CO_UPDATEIFEXISTS);
1696 WinCreateObject(WPProgram,
1697 "Global File Viewer", s, FM3Tools, CO_UPDATEIFEXISTS);
1698 WinCreateObject(WPProgram, "Databar", s, FM3Tools, CO_UPDATEIFEXISTS);
1699 }
1700 }
1701 }
1702
1703 didonce = TRUE;
1704
1705} // FillTreeCnr
1706
1707
1708/**
1709 * Empty all records from a container and free associated storage and
1710 * Free up field infos
1711 */
1712
1713VOID EmptyCnr(HWND hwnd)
1714{
1715 PFIELDINFO pfi;
1716
1717#if 0 // fixme to be gone or to be configurable
1718 {
1719 int state = _heapchk();
1720 if (state != _HEAPOK)
1721 Runtime_Error(pszSrcFile, __LINE__, "heap corrupted %d", state);
1722 }
1723#endif
1724
1725 // Remove all records
1726 RemoveCnrItems(hwnd, NULL, 0, CMA_FREE);
1727
1728 // Remove field info descriptors
1729 pfi = (PFIELDINFO) WinSendMsg(hwnd, CM_QUERYDETAILFIELDINFO, MPVOID,
1730 MPFROMSHORT(CMA_FIRST));
1731 if (pfi &&
1732 (INT)WinSendMsg(hwnd, CM_REMOVEDETAILFIELDINFO, MPVOID,
1733 MPFROM2SHORT(0, CMA_FREE)) == -1) {
1734 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_REMOVEDETAILFIELDINFO hwnd %x", hwnd);
1735 }
1736}
1737
1738/**
1739 * Free storage associated with container item
1740 */
1741
1742VOID FreeCnrItemData(PCNRITEM pci)
1743{
1744 if (pci->pszSubject) {
1745 if (pci->pszSubject != NullStr)
1746 free(pci->pszSubject);
1747 pci->pszSubject = NULL; // Catch illegal references
1748 }
1749
1750 // 08 Sep 08 SHL Remove excess logic
1751 if (pci->pszLongName) {
1752 if (pci->pszLongName != NullStr)
1753 free(pci->pszLongName);
1754 pci->pszLongName = NULL; // Catch illegal references
1755 }
1756
1757 // Bypass free if pszDisplayName points into pszFileName buffer
1758 // 05 Sep 08 SHL Correct pointer overlap compare logic
1759 if (pci->pszDisplayName) {
1760 if (pci->pszDisplayName != NullStr) {
1761 if (!pci->pszFileName ||
1762 pci->pszDisplayName < pci->pszFileName ||
1763 pci->pszDisplayName >= pci->pszFileName + _msize(pci->pszFileName))
1764 {
1765 free(pci->pszDisplayName);
1766 }
1767 }
1768 pci->pszDisplayName = NULL; // Catch illegal references
1769 }
1770
1771 if (!pci->pszFileName)
1772 Runtime_Error(pszSrcFile, __LINE__, "FreeCnrItemData attempting free %p data twice", pci);
1773 else {
1774 if (pci->pszFileName != NullStr)
1775 free(pci->pszFileName);
1776 pci->pszFileName = NULL; // Catch illegal references
1777 }
1778
1779 // 08 Sep 08 SHL Remove excess logic
1780 if (pci->pszLongName) {
1781 if (pci->pszLongName != NullStr)
1782 free(pci->pszLongName);
1783 pci->pszLongName = NULL; // Catch illegal references
1784 }
1785
1786 if (pci->pszFmtFileSize) {
1787 if (pci->pszFmtFileSize != NullStr)
1788 free(pci->pszFmtFileSize);
1789 pci->pszFmtFileSize = NULL; // Catch illegal references
1790 }
1791}
1792
1793/**
1794 * Free single container item and associated storage
1795 */
1796
1797VOID FreeCnrItem(HWND hwnd, PCNRITEM pci)
1798{
1799 // DbgMsg(pszSrcFile, __LINE__, "FreeCnrItem hwnd %x pci %p", hwnd, pci);
1800
1801 FreeCnrItemData(pci);
1802
1803 if (!WinSendMsg(hwnd, CM_FREERECORD, MPFROMP(&pci), MPFROMSHORT(1))) {
1804 // Win_Error2(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,IDS_CMFREEERRTEXT);
1805 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,
1806 "CM_FREERECORD hwnd %x pci %p file %s",
1807 hwnd, pci,
1808 pci && pci->pszFileName ? pci->pszFileName : "n/a");
1809 }
1810}
1811
1812/**
1813 * Free container item list and associated storage
1814 */
1815
1816VOID FreeCnrItemList(HWND hwnd, PCNRITEM pciFirst)
1817{
1818 PCNRITEM pci = pciFirst;
1819 PCNRITEM pciNext;
1820 USHORT usCount;
1821
1822 for (usCount = 0; pci; usCount++) {
1823 pciNext = (PCNRITEM) pci->rc.preccNextRecord;
1824 FreeCnrItemData(pci);
1825 pci = pciNext;
1826 }
1827
1828 if (usCount) {
1829 if (!WinSendMsg(hwnd, CM_FREERECORD, MPFROMP(&pci), MPFROMSHORT(usCount))) {
1830 // Win_Error2(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,IDS_CMFREEERRTEXT);
1831 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_FREERECORD hwnd %x pci %p cnt %u", hwnd, pci, usCount);
1832 }
1833 }
1834}
1835
1836/**
1837 * Remove item(s) from container and free associated storage if requested
1838 * @param pciFirst points to first item to remove or NULL to remove all
1839 * @param usCnt is remove count or 0 to remove all
1840 * @returns count of items remaining in container or -1 if error
1841 */
1842
1843INT RemoveCnrItems(HWND hwnd, PCNRITEM pciFirst, USHORT usCnt, USHORT usFlags)
1844{
1845 INT remaining = usCnt;
1846 PCNRITEM pci;
1847
1848 if ((usCnt && !pciFirst) || (!usCnt && pciFirst)) {
1849 Runtime_Error(pszSrcFile, __LINE__, "pciFirst %p usCnt %u mismatch", pciFirst, usCnt);
1850 remaining = -1;
1851 }
1852 else {
1853 // Free our buffers if free requested
1854 if (usFlags & CMA_FREE) {
1855 if (pciFirst)
1856 pci = pciFirst;
1857 else {
1858 pci = (PCNRITEM)WinSendMsg(hwnd, CM_QUERYRECORD, MPVOID,
1859 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
1860 if ((INT)pci == -1) {
1861 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_QUERYRECORD");
1862 remaining = -1;
1863 pci = NULL;
1864 }
1865 }
1866 while (pci) {
1867 // 12 Sep 07 SHL dwg drivebar crash testing - ticket# ???
1868 static PCNRITEM pciLast; // 12 Sep 07 SHL
1869 ULONG ulSize = sizeof(*pci);
1870 ULONG ulAttr;
1871 APIRET apiret = DosQueryMem((PVOID)pci, &ulSize, &ulAttr);
1872 if (apiret)
1873 Dos_Error(MB_ENTER, apiret, HWND_DESKTOP, pszSrcFile, __LINE__,
1874 "DosQueryMem failed pci %p pciLast %p", pci, pciLast);
1875 FreeCnrItemData(pci);
1876 pciLast = pci;
1877 pci = (PCNRITEM)pci->rc.preccNextRecord;
1878 if (remaining && --remaining == 0)
1879 break;
1880 }
1881 }
1882 }
1883
1884 // DbgMsg(pszSrcFile, __LINE__, "RemoveCnrItems %p %u %s", pci, usCnt, pci->pszFileName);
1885
1886 if (remaining != - 1) {
1887 remaining = (INT)WinSendMsg(hwnd, CM_REMOVERECORD, MPFROMP(&pciFirst), MPFROM2SHORT(usCnt, usFlags));
1888 if (remaining == -1) {
1889 // Win_Error2(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,IDS_CMREMOVEERRTEXT);
1890 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_REMOVERECORD hwnd %x pci %p cnt %u", hwnd, pciFirst, usCnt);
1891 }
1892 }
1893
1894 return remaining;
1895}
1896
1897#pragma alloc_text(FILLDIR,FillInRecordFromFFB,FillInRecordFromFSA,IDFile)
1898#pragma alloc_text(FILLDIR1,ProcessDirectory,FillDirCnr,FillTreeCnr,FileAttrToString,StubbyScanThread)
1899#pragma alloc_text(EMPTYCNR,EmptyCnr,FreeCnrItemData,FreeCnrItem,FreeCnrItemList,RemoveCnrItems)
1900
Note: See TracBrowser for help on using the repository browser.