source: trunk/dll/filldir.c@ 1008

Last change on this file since 1008 was 985, checked in by Gregg Young, 18 years ago

Update sizes dialog (ticket 44); Make max command line length user settable (ticket 199); use xfree for free in most cases (ticket 212); initial code to check for valid ini file (ticket 102); Some additional refactoring and structure rework; Some documentation updates;

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