source: trunk/dll/filldir.c@ 1099

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

Remove redundent strcpys from fill dir inner loop

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