source: trunk/dll/filldir.c@ 1354

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

Added driveflags to over ride write verify for USB removable drives that fail when it is on (Ticket 323); A flag to prevent directory name from being broadcast to drives in the tree cnr prior to a recursive scan of the drive (causes dbl directory names Ticket 321) Add option for multithreaded recursive scan of user selected drives at startup (Ticket 322).

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