source: trunk/dll/filldir.c@ 1796

Last change on this file since 1796 was 1789, checked in by Gregg Young, 11 years ago

Use saymsg2 for Suggest dialog Ticket [538] Add an @ to the end of the filters window label to indicate an attribute filter is set.

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