source: trunk/dll/filldir.c@ 1113

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

Use pszDisplayName for display in dirsize.c change free code to free it; fix memory leak in dirsize. (Ticket 269)

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