source: trunk/dll/filldir.c@ 1892

Last change on this file since 1892 was 1892, checked in by Steven Levine, 6 years ago

Rework RemoveCnrItems to avoid possible traps on bad input.
Rework RemoveArcItems like RemoveCnrItems.
Sync source with standards.

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