source: trunk/dll/filldir.c@ 1063

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

Fortify ifdef reformat

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