source: trunk/dll/filldir.c

Last change on this file was 1916, checked in by Gregg Young, 9 days ago

Fix easize so that EAs larger than 32767 show their actual size instead of 32767

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