source: trunk/dll/filldir.c@ 1358

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

Comments for CS 1354/55

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