source: trunk/dll/filldir.c@ 1080

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

More Fortify infrastructure enhancements
Rework Fortify_SetOwner
Add Fortify_BecomeOwner
Avoid more spurious leak reports

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