source: trunk/dll/filldir.c@ 1863

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

Remove recurse scan code; fix A:\ drive not ready error caused by not moving the cursor from drive A:\ fast enough. Have Flesh remove pcis that have NullStr FileNames.

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