source: trunk/dll/filldir.c@ 1873

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

Adjustments to ShowTreeRec to eliminate failures and reduce retries and container noise on tree switches. Remove fInitialDriveScan code. Changes to speed up ExpandAll. WaitFleshWorkListEmpty now gives error message and returns if semaphore request fails more than 5 consecutive times.

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