source: trunk/dll/filldir.c@ 1871

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

Create CollapseAll and modify ExpandAll to reduce code overhead both to try and speed drive expansion. Change ExpandAll to allow it to loop in UM_EXPAND until until drive is completely expanded. Changes were need to work with Flesh, Stubby and UnFlesh being moved to a thread. Add code for Flesh to skip the directory entry added by Stubby (eliminate use of NULL/Nullstr pszFileNames by Stubby). Add code in Stubby to insert a complete container item. Add a flag to indicate when a directory needed to be Fleshed. Get expand and switch code to work with Flesh, UnFlesh and Stubby running on a thread. Loop and idle ExpandAll; Move tree expand to a thread; Have ShowTreeRec wait for the Flesh thread. Add a correction factor so directories don't get placed above the top of the tree container when a large drive has been expanded. Debug is mostly still in but all turned off.

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