source: trunk/dll/filldir.c@ 1120

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

Comments for CS 1113

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