source: trunk/dll/filldir.c@ 1083

Last change on this file since 1083 was 1083, checked in by John Small, 17 years ago

Ticket 114: Support user-selectable env. strings in Tree container.

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