source: trunk/dll/filldir.c@ 1036

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

Fortify updates including a leave scope wrapper which frees and in some cases reloads commands, archivers, association, etc.

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