source: trunk/dll/filldir.c@ 1860

Last change on this file since 1860 was 1856, checked in by Steven Levine, 10 years ago

Rework Flesh/Stubby etc. to avoid running on thread 1
Should be ready for release after spurious traps resolved
DbgMsg calls retained - delete/disable before release

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