source: trunk/dll/filldir.c@ 975

Last change on this file since 975 was 924, checked in by Steven Levine, 18 years ago

Avoid error reports for R/O FAT directories (ticket #116)
Change Config->Edit and Config->Palette menus to have no default
Move SpecialSelect to comp.c

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