source: trunk/dll/filldir.c@ 1146

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

Fixes strrchr trap in FreeCnrItemData when pci->pszFileName is NULL (Ticket 278)

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