source: trunk/dll/filldir.c@ 1844

Last change on this file since 1844 was 1838, checked in by Gregg Young, 10 years ago

Serialize local hard drive scanning to reduce drive thrashing continue to scan all other drive types in separate threads. Ticket [561] Remove unneed SubbyScan code and improve suppression of blank lines and duplicate subdirectory name caused by running Stubby in worker threads.

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