source: trunk/dll/filldir.c@ 763

Last change on this file since 763 was 763, checked in by Gregg Young, 18 years ago

Replaced sprintf path building with BldFullPathName at functions for quoting path and file names

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