source: trunk/dll/filldir.c@ 1780

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

Fixed errors found by cppcheck. Most had the potential to cause difficult to reproduce traps. Also fixed retry code for failure to create an archive work directory and the failure of the mailto code to drop trailing >.

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