source: trunk/dll/filldir.c@ 1891

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

Rework FreeCnrItem to ensure all CNRITEMs deleted.
Use WinSendMsg CMA_NEXT.
Was using preccNextRecord which is not recommended because control does
not maintain linkage after inserts and deletes.
Note: arccnrs.c still needs to be reworked to use common functions from filldir.c.

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