source: trunk/dll/filldir.c@ 1069

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

Fixes trap on viewing multiple files from an archive Ticket 248. Also includes initial code for using TMP directory for Temp files.

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