source: trunk/dll/filldir.c@ 1395

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

Allow user to turn off alert and/or error beeps in settings notebook. Ticket 341 Move repeated strings to PCSZs. Ticket 6 Add *DateFormat functions to format dates based on locale Ticket 28 Eliminate Win_Error2 by moving function names to PCSZs used in Win_Error Ticket 6

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