source: trunk/dll/filldir.c@ 1868

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

Remove obsolete code fDontAsk?zip and fDummy

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 63.9 KB
RevLine 
[31]1
2/***********************************************************************
3
4 $Id: filldir.c 1868 2015-08-24 20:51:17Z 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
[1865]98 responsiveness when closing containers with large numbers of items
[1570]99 12 Jun 11 GKY Replaced SleepIfNeeded with IdleIfNeeded in the container loade loop
[1856]100 22 Oct 11 GKY Removing unneeded UnFlesh call from StubbyThread appears to significantly speed opening of FM/2
[1754]101 02 Mar 14 GKY !didone for fFirstTime so the suggest code works again. Also clear out the
[1865]102 garbage that was appearing in the string.
[1756]103 02 Mar 14 GKY Speed up intial drive scans Ticket 528
[1759]104 19 Mar 14 SHL RemoveCnrItems: clean up odd code
[1763]105 22 Mar 14 GKY Reverted some code from the RemoveCnrItems changes adding a previously
[1865]106 missing break and comments explaining the code structure.
[1780]107 28 Jun 14 GKY Fix errors identified with CPPCheck
[1789]108 30 Aug 14 GKY Use saymsg2 for Suggest dialog
[1836]109 14 Jun 15 GKY Changes to prevent trap in Filter, heap corruption and traps associated with it
[1814]110 19 Jun 15 JBS Ticket 514: Double free fix (which also fixes a memory leak)
[1838]111 02 Aug 15 GKY Serialize local hard drive scanning to reduce drive thrashing continue to scan
[1865]112 all other drive types in separate threads.
[1856]113 02 Aug 15 GKY Remove unneeded SubbyScan code and improve suppression of blank lines and
[1865]114 duplicate subdirectory name caused by running Stubby in worker threads.
[1856]115 04 Aug 15 SHL Comments
116 04 Aug 15 SHL Move StubbyThread to flesh.c
117 07 Aug 15 SHL Rework to use AddFleshWorkRequest rather than direct calls to Stubby/Flesh/Unflesh
[1863]118 22 Aug 15 GKY Remove recurse scan code.
119 22 Aug 15 GKY Minimize the occurence of an A:\ Drive not ready error by moving the cursor
[1865]120 to the default drive.
[1868]121 24 AUG 15 GKY Remove fDummy code
[31]122
123***********************************************************************/
124
[2]125#include <stdlib.h>
126#include <string.h>
[1154]127#include <malloc.h> // _msize _heapchk
[2]128#include <ctype.h>
[1564]129#include <limits.h>
[1335]130// #include <process.h> // _beginthread
[763]131
[907]132#define INCL_DOS
133#define INCL_WIN
134#define INCL_DOSERRORS
135#define INCL_LONGLONG
136
[1182]137#include "fm3dll.h"
[1223]138#include "fm3dll2.h" // #define's for UM_*, control id's, etc.
[1207]139#include "draglist.h" // Data declaration(s)
140#include "treecnr.h" // Data declaration(s)
141#include "info.h" // Data declaration(s)
142#include "newview.h" // Data declaration(s)
[1471]143#include "mainwnd.h" // hwndDrivelist
[907]144#include "fm3str.h"
145#include "filldir.h"
146#include "errutil.h" // Dos_Error...
147#include "strutil.h" // GetPString
[1078]148#include "misc.h" // GetTidForWindow
149#include "fortify.h" // 06 May 08 SHL
[1083]150#include "notebook.h" // INI file fields
[1856]151#include "flesh.h" // AddFleshWorkRequest
[1159]152#include "update.h" // SelectDriveIcon
[1182]153#include "valid.h" // CheckDrive
154#include "filter.h" // Filter
155#include "subj.h" // Subject
[1459]156#include "grep.h" // hwndStatus
[1182]157#include "copyf.h" // unlinkf
158#include "literal.h" // wildcard
[1400]159#include "i18nutil.h" // CommaFmtULL
[1182]160#include "wrappers.h" // xDosFindNext
[1856]161#include "init.h"
162#include "common.h"
[1335]163#include "excputil.h" // xbeginthread
[1459]164#include "fm3dlg.h" // INFO_LABEL
165#include "pathutil.h" // AddBackslashToPath
[1564]166#include "tmrsvcs.h" // ITIMER_DESC
[1836]167#if 0
168#define __PMPRINTF__
169#include "PMPRINTF.H"
170#endif
[2]171
[1207]172// Data definitions
[359]173static PSZ pszSrcFile = __FILE__;
[1550]174INT FixedVolume = 0;
[359]175
[1207]176#pragma data_seg(GLOBAL1)
177HPOINTER hptrEnv;
178HPOINTER hptrHidden;
179HPOINTER hptrReadonly;
180HPOINTER hptrSystem;
181
182#pragma data_seg(GLOBAL2)
[1459]183PCSZ FM3Tools = "<FM3_Tools>";
184PCSZ WPProgram = "WPProgram";
[1207]185
[751]186/**
187 * Return display string given standard file attribute mask
188 * @param fileAttr attribute mask in FILEFINDBUF format
189 * @return fixed length string for display
190 */
191
192const PSZ FileAttrToString(ULONG fileAttr)
193{
194 // From os2win.h
195 // FILE_ATTRIBUTE_READONLY 0x00000001
196 // FILE_ATTRIBUTE_HIDDEN 0x00000002
197 // FILE_ATTRIBUTE_SYSTEM 0x00000004
198 // 0x00000008
199 // FILE_ATTRIBUTE_DIRECTORY 0x00000010
200 // FILE_ATTRIBUTE_ARCHIVE 0x00000020
201
202 static CHAR *apszAttrString[] = {
203 // RHSDA
204 "-----",
205 "R----",
206 "-H---",
207 "RH---",
208 "--S--",
209 "R-S--",
210 "-HS--",
211 "RHS--",
212 "---D-",
213 "R--D-",
214 "-H-D-",
215 "RH-D-",
216 "--SD-",
217 "R-SD-",
218 "-HSD-",
219 "RHSD-",
220 "----A",
221 "R---A",
222 "-H--A",
223 "RH--A",
224 "--S-A",
225 "R-S-A",
226 "-HS-A",
227 "RHS-A",
228 "---DA",
229 "R--DA",
230 "-H-DA",
231 "RH-DA",
232 "--SDA",
233 "R-SDA",
234 "-HSDA",
235 "RHSDA"
236 };
237
238 fileAttr = ((fileAttr & 0x30) >> 1) | (fileAttr & 7); // Drop don't care bit from index
239
240 return apszAttrString[fileAttr];
241
242}
243
[214]244static HPOINTER IDFile(PSZ p)
[90]245{
[2]246 HPOINTER hptr;
[551]247 ULONG cmp;
[1780]248 CHAR cmps[6];
[2]249
[551]250 p = strrchr(p, '.');
[1644]251 if (p) {
[214]252 cmps[0] = '.';
253 cmps[1] = toupper(p[1]);
254 cmps[2] = toupper(p[2]);
255 cmps[3] = toupper(p[3]);
[1644]256 if (p[4]) {
257 cmps[4] = toupper(p[4]);
258 cmps[5] = 0;
259 }
260 else
261 cmps[4] = 0;
[214]262
[551]263 cmp = *(ULONG *) cmps;
[214]264
[1398]265 if (cmp == *(ULONG *) PCSZ_DOTEXE || cmp == *(ULONG *) PCSZ_DOTCMD ||
[1459]266 cmp == *(ULONG *) PCSZ_DOTBAT || cmp == *(ULONG *) PCSZ_DOTCOM ||
267 cmp == *(ULONG *) PCSZ_DOTBTM)
[214]268 hptr = hptrApp;
[551]269 else if (cmp == *(ULONG *) ".ZIP" || cmp == *(ULONG *) ".LZH" ||
270 cmp == *(ULONG *) ".ARJ" || cmp == *(ULONG *) ".ARC" ||
[552]271 cmp == *(ULONG *) ".ZOO" || cmp == *(ULONG *) ".RAR" ||
272 cmp == *(ULONG *) ".TAR" || cmp == *(ULONG *) ".TGZ" ||
[1398]273 cmp == *(ULONG *) ".GZ" || cmp == *(ULONG *) ".Z" ||
[1759]274 cmp == *(ULONG *) ".CAB" || cmp == *(ULONG *) ".BZ2" ||
275 cmp == *(ULONG *) ".WPI" || cmp == *(ULONG *) ".7Z")
[214]276 hptr = hptrArc;
[1398]277 else if (cmp == *(ULONG *) PCSZ_DOTBMP ||
[1459]278 cmp == *(ULONG *) PCSZ_DOTICO ||
279 cmp == *(ULONG *) PCSZ_DOTPTR ||
280 cmp == *(ULONG *) PCSZ_DOTJPEG ||
281 cmp == *(ULONG *) PCSZ_DOTJPG ||
282 cmp == *(ULONG *) ".GIF" ||
[551]283 cmp == *(ULONG *) ".TIF" || cmp == *(ULONG *) ".PCX" ||
[552]284 cmp == *(ULONG *) ".TGA" || cmp == *(ULONG *) ".XBM" ||
285 cmp == *(ULONG *) ".PNG" || cmp == *(ULONG *) ".PSD" ||
286 cmp == *(ULONG *) ".LGO" || cmp == *(ULONG *) ".EPS" ||
287 cmp == *(ULONG *) ".RLE" || cmp == *(ULONG *) ".RAS" ||
288 cmp == *(ULONG *) ".PLC" || cmp == *(ULONG *) ".MSP" ||
289 cmp == *(ULONG *) ".IFF" || cmp == *(ULONG *) ".FIT" ||
290 cmp == *(ULONG *) ".DCX" || cmp == *(ULONG *) ".MAC" ||
291 cmp == *(ULONG *) ".SFF" || cmp == *(ULONG *) ".SGI" ||
292 cmp == *(ULONG *) ".XWD" || cmp == *(ULONG *) ".XPM" ||
293 cmp == *(ULONG *) ".WPG" || cmp == *(ULONG *) ".CUR" ||
294 cmp == *(ULONG *) ".PNM" || cmp == *(ULONG *) ".PPM" ||
295 cmp == *(ULONG *) ".PGM" || cmp == *(ULONG *) ".PBM")
[214]296 hptr = hptrArt;
297 else
[551]298 hptr = (HPOINTER) 0;
[214]299 }
300 else
[551]301 hptr = (HPOINTER) 0;
[214]302
[2]303 return hptr;
304}
305
[214]306static BOOL IsDefaultIcon(HPOINTER hptr)
307{
308 HPOINTER hptr2;
309 HPOINTER hptr3;
310 UINT u;
311
312 static HPOINTER hptrPMFile;
313 static HPOINTER hptrWPSFile;
314
[551]315 if (!hptrPMFile) {
316 hptrPMFile = WinQuerySysPointer(HWND_DESKTOP, SPTR_FILE, FALSE);
[214]317 }
318
319 // try to guess WPS default file icon
[551]320 hptr2 = (HPOINTER) 0;
321 for (u = 0; !hptrWPSFile && u < 10; u++) {
[214]322 char szFileName[CCHMAXPATH];
323 char *psz;
324
[1076]325 if (pTmpDir) {
[1069]326 psz = pTmpDir;
[214]327 strcpy(szFileName, psz);
328 psz = szFileName + strlen(szFileName) - 1;
[551]329 if (*psz != '\\') {
[214]330 psz++;
331 *psz++ = '\\';
332 }
333 }
334 else
335 psz = szFileName;
336
[551]337 sprintf(psz, "%08x.%03x", rand() & 0xffffffff, rand() & 0xfff);
338 if (IsFile(szFileName) != 1) {
[1544]339 FILE *fp;
340 CHAR *modew = "w";
[551]341
[1544]342 fp = xfopen(szFileName, modew, pszSrcFile, __LINE__, TRUE);
343
[551]344 if (fp) {
[214]345 fclose(fp);
346 hptr3 = WinLoadFileIcon(szFileName, FALSE);
[1402]347 unlinkf(szFileName);
[214]348 if (!hptr2)
349 hptr2 = hptr3;
[551]350 else if (hptr3 == hptr3) {
[214]351 hptrWPSFile = hptr3; // Got same icon twice
352 break;
353 }
354 }
355 }
356 DosSleep(rand() % 100);
357
[731]358 } // for
[214]359
360 return hptr == hptrPMFile || hptr == hptrWPSFile;
361
[731]362} // IsDefaultIcon
[214]363
[1439]364static VOID FetchCommonEAs(PCNRITEM pci)
365{
366 ULONG flags = driveflags[toupper(*pci->pszFileName) - 'A'];
367 BOOL fLoadSubjectForDrive = fLoadSubject && ~flags & DRIVE_NOLOADSUBJS;
[1444]368 BOOL fLoadLongNameForDrive = fLoadLongnames && //~flags & DRIVE_NOLONGNAMES &&
[1865]369 ~flags & DRIVE_NOLOADLONGS;
[1439]370 if (fLoadSubjectForDrive || fLoadLongNameForDrive) {
371 // Allocate space to hold GEA2s and .SUBJECT and .LONGNAME strings
[1836]372 PGEA2LIST pgealist = xmallocz(sizeof(GEA2LIST) + (sizeof(GEA2) * 2) + 32,
[1865]373 pszSrcFile, __LINE__);
[1439]374 if (pgealist) {
375 APIRET rc;
376 PFEA2LIST pfealist;
377 ULONG offset;
378 PGEA2 pgeaPrev = NULL;
379 PGEA2 pgea = pgealist->list; // Point at first available
380 EAOP2 eaop;
381 UINT state;
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
[1865]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
[1865]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))
[1865]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))
[1865]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;
[1865]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;
[1865]937 if (fSyncUpdates) {
938 if (!WinIsWindow(WinQueryAnchorBlock(hwndCnr), hwndCnr)) {
939 ok = FALSE;
[1836]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++) {
[1865]958 pffbFile = papffbSelected[x];
[551]959 ullBytes = FillInRecordFromFFB(hwndCnr, pci, pszFileSpec,
[1865]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;
[1865]992 ulReturnFiles += ulSelCnt;
993 DosRequestMutexSem(hmtxFiltering, SEM_INDEFINITE_WAIT);
[1459]994 if (dcd) {
995 dcd->totalfiles += ulSelCnt;
996 dcd->ullTotalBytes += ullTotalBytes;
[1865]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];
[1865]1012 ullTotalBytes += papffbSelected[x]->cbFile;
[1459]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
[1865]1053 if (pci ==NULL) {
1054 if (!WinIsWindow(WinQueryAnchorBlock(hwndCnr), hwndCnr)) {
1055 ok = FALSE;
[1836]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
[1865]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 }
[1865]1080 }
[1567]1081 ullBytes = FillInRecordFromFFB(hwndCnr, pci, pszFileSpec,
[1865]1082 pffbFile, partial, dcd);
[1567]1083 pci = (PCNRITEM) pci->rc.preccNextRecord;
1084 ullTotalBytes += ullBytes;
[1865]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;
[1865]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
[1865]1095 if (!IdleIfNeeded(&itdSleep, 30)) {
1096 for (x = x+1; x < cAffbTotal; x++) {
[1759]1097 ullBytes = FillInRecordFromFFB(hwndCnr, pci, pszFileSpec,
[1865]1098 pffbFile, partial, dcd);
[1759]1099 pci = (PCNRITEM) pci->rc.preccNextRecord;
[1865]1100 ullTotalBytes += ullBytes;
1101 DosRequestMutexSem(hmtxFiltering, SEM_INDEFINITE_WAIT);
[1759]1102 if (dcd) {
[1865]1103 dcd->totalfiles = x;
1104 dcd->ullTotalBytes = ullTotalBytes;
1105 }
1106 DosReleaseMutexSem(hmtxFiltering);
1107 pffbFile = (PFILEFINDBUF4L)((PBYTE)pffbFile + sizeof(FILEFINDBUF4L));
[1759]1108 if (pci == NULL) {
[1865]1109 priority_normal();
1110 InitITimer(&itdSleep, 500);
1111 break;
[1759]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)) {
[1865]1191 // 2015-08-23 SHL FIXME debug
1192 DbgMsg(pszSrcFile, __LINE__, "ProcessDirectory pci %p pci->pszFileName %p %s",
1193 pci, pci->pszFileName,
1194 pci->pszFileName == NullStr ? "NullStr" : "NULL");
1195 Runtime_Error(pszSrcFile, __LINE__, "pci->pszFileName NULL for %p", pci);
1196 return;
[1838]1197 }
[1354]1198 if ((pci->attrFile & FILE_DIRECTORY))
[1865]1199 AddFleshWorkRequest(hwndCnr, pci, eStubby);
[2]1200 pci = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
[1865]1201 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
[2]1202 }
1203 }
1204
[1459]1205 // Reset counts in case errors occurred after initially counted
[167]1206 if (pulTotalFiles)
1207 *pulTotalFiles = ulReturnFiles;
[2]1208
[167]1209 if (pullTotalBytes)
1210 *pullTotalBytes = ullReturnBytes;
[2]1211
[731]1212} // ProcessDirectory
[167]1213
1214VOID FillDirCnr(HWND hwndCnr,
[551]1215 CHAR * pszDirectory,
[924]1216 DIRCNRDATA * dcd,
1217 PULONGLONG pullTotalBytes)
[90]1218{
[167]1219 ProcessDirectory(hwndCnr,
[924]1220 (PCNRITEM)NULL,
[167]1221 pszDirectory,
[737]1222 TRUE, // filestoo
1223 FALSE, // recurse
[1459]1224 TRUE, // partial
1225 dcd ? &dcd->stopflag : NULL,
1226 dcd,
[924]1227 NULL, // total files
[737]1228 pullTotalBytes);
[2]1229 DosPostEventSem(CompactSem);
1230
[1856]1231#if 0 // 2011-05-31 SHL FIXME to be gone or to be configurable
[751]1232 {
1233 int state = _heapchk();
1234 if (state != _HEAPOK)
1235 Runtime_Error(pszSrcFile, __LINE__, "heap corrupted %d", state);
[763]1236 else
1237 DbgMsg(pszSrcFile, __LINE__, "_memavl %u", _memavl());
[751]1238 }
1239#endif
1240
[731]1241} // FillDirCnr
[2]1242
[1471]1243/**
1244 * Fill tree container and drives list
1245 * Offer to update command line options if not already done and not suppressed
1246 */
1247
[551]1248VOID FillTreeCnr(HWND hwndCnr, HWND hwndParent)
[90]1249{
[1471]1250 ULONG ulCurDriveNum;
1251 ULONG ulDriveMap;
1252 ULONG numtoinsert = 0;
[924]1253 ULONG ulDriveType;
[1471]1254 PCNRITEM pci, pciFirst = NULL;
1255 PCNRITEM pciNext;
1256 PCNRITEM pciParent = NULL;
1257 UINT iDrvNum;
1258 ULONG ulDriveMapMask;
[1754]1259 CHAR szSuggest[32] = {0}; // Suggested startup command line parameters
[1865]1260 CHAR szDrive[CCHMAXPATH] = " :\\";
[1440]1261 CHAR szFSType[CCHMAXPATH];
[841]1262 FILESTATUS4L fsa4;
[551]1263 APIRET rc;
[739]1264 ULONG startdrive = 3;
[1471]1265 HWND hwndDrivelist;
1266
[1439]1267 static BOOL didonce;
[1471]1268 static ULONG ulLastDriveMap;
[2]1269
[1856]1270 DbgMsg(pszSrcFile, __LINE__, "FillTreeCnr hwndCnr %x hwndParent %x", hwndCnr, hwndParent); // 2015-08-03 SHL FIXME debug
1271
[1471]1272 *szSuggest = 0;
1273 for (iDrvNum = 0; iDrvNum < 26; iDrvNum++) {
1274 driveflags[iDrvNum] &= (DRIVE_IGNORE | DRIVE_NOPRESCAN | DRIVE_NOLOADICONS |
[214]1275 DRIVE_NOLOADSUBJS | DRIVE_NOLOADLONGS |
[1459]1276 DRIVE_INCLUDEFILES | DRIVE_SLOW | DRIVE_NOSTATS |
1277 DRIVE_WRITEVERIFYOFF);
[689]1278 }
[551]1279 memset(driveserial, -1, sizeof(driveserial));
[739]1280
1281 DosError(FERR_DISABLEHARDERR);
1282 if (!DosQuerySysInfo(QSV_BOOT_DRIVE,
1283 QSV_BOOT_DRIVE,
1284 (PVOID) &startdrive,
1285 (ULONG) sizeof(ULONG)) &&
1286 startdrive)
[2]1287 {
[739]1288 driveflags[startdrive - 1] |= DRIVE_BOOT;
1289 }
[2]1290
1291 DosError(FERR_DISABLEHARDERR);
[731]1292 rc = DosQCurDisk(&ulCurDriveNum, &ulDriveMap);
[551]1293 if (rc) {
[2]1294 Dos_Error(MB_CANCEL,
[214]1295 rc,
1296 HWND_DESKTOP,
[1440]1297 pszSrcFile, __LINE__, PCSZ_FILLDIRQCURERRTEXT);
[2]1298 exit(0);
1299 }
[739]1300
[1471]1301 // Find drive list combobox if it exists
1302 if (hwndParent) {
1303 hwndDrivelist = WinWindowFromID(WinQueryWindow(hwndParent, QW_PARENT),
1304 MAIN_DRIVELIST);
1305 }
1306 else
1307 hwndDrivelist = NULLHANDLE;
1308
1309 // Calc number of top level drive tree items to create
1310 for (iDrvNum = 0; iDrvNum < 26; iDrvNum++) {
1311 if ((ulDriveMap & (1L << iDrvNum)) && ~driveflags[iDrvNum] & DRIVE_IGNORE)
[2]1312 numtoinsert++;
[689]1313 }
[739]1314
[689]1315 if (numtoinsert) {
[2]1316 pciFirst = WinSendMsg(hwndCnr,
[214]1317 CM_ALLOCRECORD,
[751]1318 MPFROMLONG(EXTRA_RECORD_BYTES),
[551]1319 MPFROMLONG((ULONG) numtoinsert));
[689]1320 }
[739]1321
[359]1322 if (!pciFirst) {
[1395]1323 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__, GetPString(IDS_CMALLOCRECERRTEXT));
[1856]1324 // 04 Jan 08 SHL FIXME not just up and die
[359]1325 exit(0);
1326 }
[689]1327
[1856]1328 // 04 Jan 08 SHL FIXME like comp.c to handle less than ulSelCnt records
[739]1329 pci = pciFirst;
[1471]1330 for (iDrvNum = 0; iDrvNum < 26; iDrvNum++) {
1331 ulDriveMapMask = 1L << iDrvNum;
1332 if (ulDriveMap & ulDriveMapMask && ~driveflags[iDrvNum] & DRIVE_IGNORE) {
[739]1333 CHAR s[80];
1334 ULONG flags = 0;
[1328]1335 ULONG size = sizeof(ULONG);
[1424]1336 struct {
[1471]1337 ULONG serial;
1338 CHAR volumelength;
1339 CHAR volumelabel[CCHMAXPATH];
1340 } volser;
[2]1341
[1471]1342 *szDrive = (CHAR)iDrvNum + 'A'; // Stuff drive letter - assume already have rest of path
[731]1343
[739]1344 sprintf(s, "%c.DriveFlags", toupper(*szDrive));
[1328]1345 if (PrfQueryProfileData(fmprof, appname, s, &flags, &size)) {
[1471]1346 driveflags[iDrvNum] |= flags;
[739]1347 }
[2]1348
[1471]1349 if (iDrvNum > 1) {
[1856]1350 // Hard drive, 2..N, C:..Z:
[1471]1351 if (~driveflags[iDrvNum] & DRIVE_NOPRESCAN) {
[924]1352 *szFSType = 0;
[1459]1353 ulDriveType = 0;
1354 memset(&volser, 0, sizeof(volser));
[1471]1355 DriveFlagsOne(iDrvNum, szFSType, &volser);
1356 driveserial[iDrvNum] = volser.serial;
[841]1357 memset(&fsa4, 0, sizeof(FILESTATUS4L));
[1471]1358 if (!fVerifyOffChecked[iDrvNum]) {
1359 if (driveflags[iDrvNum] & DRIVE_REMOVABLE)
1360 driveflags[iDrvNum] |= DRIVE_WRITEVERIFYOFF;
1361 if (~driveflags[iDrvNum] & DRIVE_INVALID) {
[1440]1362 CHAR Key[80];
[2]1363
[1471]1364 sprintf(Key, "%c.VerifyOffChecked", (CHAR) (iDrvNum + 'A'));
1365 fVerifyOffChecked[iDrvNum] = TRUE;
1366 PrfWriteProfileData(fmprof, appname, Key, &fVerifyOffChecked[iDrvNum], sizeof(BOOL));
[1440]1367 }
1368 }
[1478]1369 if (fShowDriveLabelInTree && stricmp(volser.volumelabel, NullStr) != 0)
[1440]1370 strcpy(szFSType, volser.volumelabel);
[739]1371 pci->rc.flRecordAttr |= CRA_RECORDREADONLY;
1372 if ((ULONG)(toupper(*szDrive) - '@') == ulCurDriveNum)
1373 pci->rc.flRecordAttr |= (CRA_CURSORED | CRA_SELECTED);
[2]1374
[1471]1375 if (~driveflags[iDrvNum] & DRIVE_REMOVABLE) {
[1567]1376 // Fixed volume
1377 if (~flags & DRIVE_INVALID && ~flags & DRIVE_NOPRESCAN)
1378 FixedVolume++;
[739]1379 pci->attrFile |= FILE_DIRECTORY;
1380 DosError(FERR_DISABLEHARDERR);
1381 rc = DosQueryPathInfo(szDrive,
[841]1382 FIL_QUERYEASIZEL,
1383 &fsa4, (ULONG) sizeof(FILESTATUS4L));
[1439]1384 if (rc == ERROR_BAD_NET_RESP) {
[214]1385 DosError(FERR_DISABLEHARDERR);
1386 rc = DosQueryPathInfo(szDrive,
[841]1387 FIL_STANDARDL,
[847]1388 &fsa4, (ULONG) sizeof(FILESTATUS4L));
[739]1389 fsa4.cbList = 0;
1390 }
1391 if (rc && !didonce) {
1392 // Guess drive letter
[1471]1393 if (!*szSuggest) {
1394 *szSuggest = '/';
1395 szSuggest[1] = 0;
[1440]1396 }
[1424]1397
[1471]1398 sprintf(szSuggest + strlen(szSuggest), "%c" , toupper(*szDrive));
[1440]1399 pci->pszFileName = xstrdup(szDrive, pszSrcFile, __LINE__);
[1471]1400 if (fShowFSTypeInTree || fShowDriveLabelInTree)
1401 sprintf(szDrive + strlen(szDrive), " [%s]", szFSType);
[1424]1402 pci->pszDisplayName = xstrdup(szDrive, pszSrcFile, __LINE__);
[1471]1403 szDrive[3] = 0; // Restore nul
[739]1404 pci->rc.pszIcon = pci->pszDisplayName;
[214]1405 pci->attrFile = FILE_DIRECTORY;
[751]1406 pci->pszDispAttr = FileAttrToString(pci->attrFile);
[1471]1407 driveserial[iDrvNum] = -1;
[731]1408 }
[1440]1409 else
1410 FillInRecordFromFSA(hwndCnr, pci, szDrive, &fsa4, TRUE, szFSType, NULL);
[214]1411 }
[551]1412 else {
[1440]1413 // Removable volume
1414 pci->pszFileName = xstrdup(szDrive, pszSrcFile, __LINE__);
[1471]1415 if (fShowFSTypeInTree || fShowDriveLabelInTree)
1416 sprintf(szDrive + strlen(szDrive), " [%s]", szFSType);
[1424]1417 pci->pszDisplayName = xstrdup(szDrive, pszSrcFile, __LINE__);
[1471]1418 szDrive[3] = 0; // Restore nul
[739]1419 pci->rc.pszIcon = pci->pszDisplayName;
[214]1420 pci->attrFile = FILE_DIRECTORY;
[751]1421 pci->pszDispAttr = FileAttrToString(pci->attrFile);
[214]1422 }
[1284]1423 SelectDriveIcon(pci);
[1250]1424# ifdef FORTIFY
1425 // Will be freed by TreeCnrWndProc WM_DESTROY
1426 Fortify_SetScope(pci->pszFileName, 2);
1427# endif
[214]1428 }
[1284]1429 else {
[1439]1430 *szFSType = 0;
[1440]1431 pci->rc.hptrIcon = hptrDunno;
1432 pci->pszFileName = xstrdup(szDrive, pszSrcFile, __LINE__);
[1471]1433 if (fShowFSTypeInTree || fShowDriveLabelInTree)
[1440]1434 strcat(szDrive, " [?]");
[1424]1435 pci->pszDisplayName = xstrdup(szDrive, pszSrcFile, __LINE__);
[1440]1436 szDrive[3] = 0;
[1154]1437# ifdef FORTIFY
1438 // Will be freed by TreeCnrWndProc WM_DESTROY
1439 Fortify_SetScope(pci->pszFileName, 2);
1440# endif
[1424]1441 pci->rc.pszIcon = pci->pszDisplayName;
[214]1442 pci->attrFile = FILE_DIRECTORY;
[751]1443 pci->pszDispAttr = FileAttrToString(pci->attrFile);
[1471]1444 driveserial[iDrvNum] = -1;
[214]1445 }
[1856]1446 } // if not diskette
[739]1447 else {
1448 // diskette drive (A or B)
[1440]1449 pci->rc.hptrIcon = hptrFloppy;
1450 pci->pszFileName = xstrdup(szDrive, pszSrcFile, __LINE__);
1451 if (fShowFSTypeInTree || fShowDriveLabelInTree)
1452 strcat(szDrive, " [Floppy]");
[1424]1453 pci->pszDisplayName = xstrdup(szDrive, pszSrcFile, __LINE__);
[1440]1454 szDrive[3] = 0;
[739]1455 pci->rc.pszIcon = pci->pszDisplayName;
1456 pci->attrFile = FILE_DIRECTORY;
[751]1457 pci->pszDispAttr = FileAttrToString(pci->attrFile);
[1471]1458 driveflags[iDrvNum] |= (DRIVE_REMOVABLE | DRIVE_NOLONGNAMES);
1459 driveserial[iDrvNum] = -1;
[739]1460 }
1461 pci->rc.flRecordAttr |= CRA_RECORDREADONLY;
[783]1462 pci = (PCNRITEM) pci->rc.preccNextRecord; // next rec
[739]1463 }
[1471]1464 else if (~ulDriveMap & ulDriveMapMask)
1465 driveflags[iDrvNum] |= DRIVE_INVALID;
1466
1467 // Update drives list dropdown
1468 if ((ulDriveMap ^ ulLastDriveMap) & ulDriveMapMask) {
1469 if (ulDriveMap & ulDriveMapMask) {
1470 WinSendMsg(hwndDrivelist,
1471 LM_INSERTITEM,
1472 MPFROM2SHORT(LIT_SORTASCENDING, 0),
1473 MPFROMP(szDrive));
1474 }
1475 else {
1476 // Drive went away
1477 SHORT sSelect = (SHORT)WinSendMsg(hwndDrivelist,
1478 LM_SEARCHSTRING,
1479 MPFROM2SHORT(0, LIT_FIRST),
1480 MPFROMP(szDrive));
1481 if (sSelect >= 0)
1482 WinSendMsg(hwndDrivelist, LM_DELETEITEM, MPFROMSHORT(sSelect), MPVOID);
1483 }
1484 }
[739]1485 } // for drives
[689]1486
[1865]1487 ulLastDriveMap = ulDriveMap;
[2]1488
[1856]1489 // insert the drives in container
[739]1490 if (numtoinsert && pciFirst) {
1491 RECORDINSERT ri;
1492
1493 memset(&ri, 0, sizeof(RECORDINSERT));
1494 ri.cb = sizeof(RECORDINSERT);
1495 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1496 ri.pRecordParent = (PRECORDCORE) NULL;
1497 ri.zOrder = (ULONG) CMA_TOP;
1498 ri.cRecordsInsert = numtoinsert;
1499 ri.fInvalidateRecord = FALSE;
1500 if (!WinSendMsg(hwndCnr,
1501 CM_INSERTRECORD, MPFROMP(pciFirst), MPFROMP(&ri)))
1502 {
[1395]1503 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
[1440]1504 GetPString(IDS_CMINSERTERRTEXT));
[2]1505 }
[739]1506 }
[689]1507
[783]1508 // move cursor onto the default drive rather than the first drive
[1863]1509 pci = (PCNRITEM) WinSendMsg(hwndCnr,
[1865]1510 CM_QUERYRECORD,
1511 MPVOID,
1512 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
[1863]1513 while (pci && (INT)pci != -1) {
1514 if ((ULONG) (toupper(*pci->pszFileName) - '@') == ulCurDriveNum) {
1515 WinSendMsg(hwndCnr,
[1865]1516 CM_SETRECORDEMPHASIS,
1517 MPFROMP(pci), MPFROM2SHORT(TRUE, CRA_CURSORED));
[1863]1518 break;
1519 }
[739]1520 pci = (PCNRITEM) WinSendMsg(hwndCnr,
[1865]1521 CM_QUERYRECORD,
1522 MPFROMP(pci),
1523 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
[739]1524 }
[2]1525
[739]1526 if (fShowEnv) {
1527 RECORDINSERT ri;
[2]1528
[739]1529 pciParent = WinSendMsg(hwndCnr,
1530 CM_ALLOCRECORD,
[751]1531 MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(1));
[739]1532 if (pciParent) {
1533 pciParent->flags |= RECFLAGS_ENV;
[773]1534 pciParent->pszFileName = xstrdup(GetPString(IDS_ENVVARSTEXT), pszSrcFile, __LINE__);
[1865]1535 pciParent->pszDisplayName = pciParent->pszFileName;
[739]1536 pciParent->rc.hptrIcon = hptrEnv;
1537 pciParent->rc.pszIcon = pciParent->pszFileName;
[751]1538 pciParent->pszDispAttr = FileAttrToString(0);
[739]1539 memset(&ri, 0, sizeof(RECORDINSERT));
1540 ri.cb = sizeof(RECORDINSERT);
1541 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1542 ri.pRecordParent = (PRECORDCORE) NULL;
1543 ri.zOrder = (ULONG) CMA_TOP;
1544 ri.cRecordsInsert = 1;
1545 ri.fInvalidateRecord = FALSE;
1546 if (WinSendMsg(hwndCnr,
1547 CM_INSERTRECORD, MPFROMP(pciParent), MPFROMP(&ri))) {
[2]1548
[739]1549 char *p, *pp;
[2]1550
[1154]1551 p = pszTreeEnvVarList;
[1090]1552 while (*p == ';')
[739]1553 p++;
1554 while (*p) {
[924]1555 *szFSType = 0;
1556 pp = szFSType;
[1090]1557 while (*p && *p != ';')
[739]1558 *pp++ = *p++;
1559 *pp = 0;
[1090]1560 while (*p == ';')
[214]1561 p++;
[924]1562 if (*szFSType &&
[1400]1563 (!stricmp(szFSType, PCSZ_LIBPATH) || getenv(szFSType))) {
[739]1564 pci = WinSendMsg(hwndCnr,
1565 CM_ALLOCRECORD,
[751]1566 MPFROMLONG(EXTRA_RECORD_BYTES),
[739]1567 MPFROMLONG(1));
1568 if (pci) {
1569 CHAR fname[CCHMAXPATH];
1570 pci->flags |= RECFLAGS_ENV;
[924]1571 sprintf(fname, "%%%s%%", szFSType);
[739]1572 pci->pszFileName = xstrdup(fname, pszSrcFile, __LINE__);
1573 pci->rc.hptrIcon = hptrEnv;
1574 pci->rc.pszIcon = pci->pszFileName;
[751]1575 pci->pszDispAttr = FileAttrToString(0);
[739]1576 memset(&ri, 0, sizeof(RECORDINSERT));
1577 ri.cb = sizeof(RECORDINSERT);
1578 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1579 ri.pRecordParent = (PRECORDCORE) pciParent;
1580 ri.zOrder = (ULONG) CMA_TOP;
1581 ri.cRecordsInsert = 1;
1582 ri.fInvalidateRecord = FALSE;
1583 if (!WinSendMsg(hwndCnr,
1584 CM_INSERTRECORD,
1585 MPFROMP(pci), MPFROMP(&ri))) {
[1395]1586 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1587 GetPString(IDS_CMINSERTERRTEXT));
[751]1588 FreeCnrItem(hwndCnr, pci);
[214]1589 }
1590 }
1591 }
1592 }
[739]1593 WinSendMsg(hwndCnr,
1594 CM_INVALIDATERECORD,
1595 MPFROMP(&pciParent),
1596 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
[2]1597 }
[739]1598 else
[751]1599 FreeCnrItem(hwndCnr, pciParent);
[739]1600 }
1601 } // if show env
[1299]1602
[1856]1603 // Run Stubby on each hard drive to ensure expand/collapse buttons correct
1604 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1605 CM_QUERYRECORD,
1606 MPVOID,
1607 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
1608 while (pci && (INT)pci != -1) {
1609 pciNext = (PCNRITEM) WinSendMsg(hwndCnr,
1610 CM_QUERYRECORD,
1611 MPFROMP(pci),
1612 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1613 if (~pci->flags & RECFLAGS_ENV) {
1614 iDrvNum = toupper(*pci->pszFileName) - 'A'; // 0..25
1615 if (iDrvNum == ulCurDriveNum || iDrvNum >= 2) {
1616 // Hard drive or current drive
1617 ULONG flags = driveflags[iDrvNum]; // Speed up
1618 if (~flags & DRIVE_INVALID &&
1619 ~flags & DRIVE_NOPRESCAN &&
1620 (!fNoRemovableScan || ~flags & DRIVE_REMOVABLE)) {
[1863]1621 AddFleshWorkRequest(hwndCnr, pci, eStubby);
[1856]1622 } // if drive needs to be scanned
[739]1623 }
[1856]1624 else {
1625 // Diskette or not current drive
1626 WinSendMsg(hwndCnr,
1627 CM_INVALIDATERECORD,
1628 MPFROMP(&pci),
1629 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
1630 }
1631 }
1632 pci = pciNext;
1633 } // while pci
[2]1634
[1856]1635 // Deselect all
[1471]1636 if (hwndDrivelist)
1637 WinSendMsg(hwndDrivelist, LM_SELECTITEM, MPFROM2SHORT(0, 0), MPFROMLONG(TRUE));
1638
[1856]1639 // Fill in environment CNRITEMs, if any
[739]1640 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1641 CM_QUERYRECORD,
1642 MPVOID,
1643 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
[762]1644 while (pci && (INT)pci != -1) {
[739]1645 pciNext = (PCNRITEM) WinSendMsg(hwndCnr,
[551]1646 CM_QUERYRECORD,
1647 MPFROMP(pci),
[739]1648 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1649 if (pci->flags & RECFLAGS_ENV) {
[551]1650 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1651 CM_QUERYRECORD,
1652 MPFROMP(pci),
[739]1653 MPFROM2SHORT(CMA_FIRSTCHILD,
1654 CMA_ITEMORDER));
[762]1655 while (pci && (INT)pci != -1) {
[739]1656 if (pci->flags & RECFLAGS_ENV)
[1856]1657 AddFleshWorkRequest(hwndCnr, pci, eFleshEnv);
[739]1658 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1659 CM_QUERYRECORD,
1660 MPFROMP(pci),
1661 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
1662 }
1663 break;
[2]1664 }
[739]1665 pci = (PCNRITEM) WinSendMsg(hwndCnr,
1666 CM_QUERYRECORD,
1667 MPFROMP(pci),
1668 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
[1778]1669 } // while pci
[2]1670
[1446]1671 if (hwndMain)
[551]1672 PostMsg(hwndMain, UM_BUILDDRIVEBAR, MPVOID, MPVOID);
[1856]1673
1674 DosSleep(16);
1675
[1756]1676 fInitialDriveScan = FALSE;
[1856]1677 DbgMsg(pszSrcFile, __LINE__, "fInitialDriveScan now FALSE"); // 2015-08-03 SHL FIXME debug
[2]1678 DosPostEventSem(CompactSem);
[739]1679
[1522]1680 if (!fDontSuggestAgain) {
[2]1681 BYTE info;
1682 BOOL includesyours = FALSE;
1683
[1754]1684 // 02 Mar 14 GKY !didone for fFirstTime so it works again
1685 if (*szSuggest || ~driveflags[1] & DRIVE_IGNORE && !didonce) {
[551]1686 if (!DosDevConfig(&info, DEVINFO_FLOPPY) && info == 1) {
[1471]1687 if (!*szSuggest) {
1688 *szSuggest = '/';
1689 szSuggest[1] = 0;
[214]1690 }
1691 else
[1471]1692 memmove(szSuggest + 2, szSuggest + 1, strlen(szSuggest));
1693 szSuggest[1] = 'B';
[2]1694 }
1695 }
[1856]1696 // DbgMsg(pszSrcFile, __LINE__, "szSuggest %x info %x", *szSuggest, info);
[1471]1697 if (*szSuggest) {
[1522]1698 APIRET rc;
[1471]1699 for (iDrvNum = 2; iDrvNum < 26; iDrvNum++) {
1700 if (driveflags[iDrvNum] & DRIVE_IGNORE) {
[214]1701 includesyours = TRUE;
[1471]1702 sprintf(szSuggest + strlen(szSuggest), "%c", (char)(iDrvNum + 'A'));
[214]1703 }
[2]1704 }
[1471]1705 strcat(szSuggest, " %*");
[1789]1706 rc = saymsg2(NULL, 3, HWND_DESKTOP,
[1865]1707 GetPString(IDS_SUGGESTTITLETEXT),
1708 GetPString(IDS_SUGGEST1TEXT),
1709 (includesyours) ? GetPString(IDS_SUGGEST2TEXT) : NullStr,
[1789]1710 szSuggest);
1711 if (rc == SM2_YES || rc == SM2_DONTASK) {
[1567]1712 HOBJECT hFM2Object;
[214]1713 char s[64];
[1471]1714 sprintf(s, "PARAMETERS=%s", szSuggest);
[1567]1715 hFM2Object = WinQueryObject("<FM/2>");
1716 if (hFM2Object) {
1717 rc = WinSetObjectData(hFM2Object, (PSZ)s);
1718 }
1719 hFM2Object = WinQueryObject("<FM/2 LITE>");
1720 if (hFM2Object) {
1721 rc = WinSetObjectData(hFM2Object, (PSZ)s);
1722 }
1723 hFM2Object = WinQueryObject("<FM/2_AV/2>");
1724 if (hFM2Object) {
1725 rc = WinSetObjectData(hFM2Object, (PSZ)s);
1726 }
1727 hFM2Object = WinQueryObject("<FM/2_DIRSIZE>");
1728 if (hFM2Object) {
1729 rc = WinSetObjectData(hFM2Object, (PSZ)s);
1730 }
1731 hFM2Object = WinQueryObject("<FM/2_VTREE>");
1732 if (hFM2Object) {
1733 rc = WinSetObjectData(hFM2Object, (PSZ)s);
1734 }
1735 hFM2Object = WinQueryObject("<FM/2_VDIR>");
1736 if (hFM2Object) {
1737 rc = WinSetObjectData(hFM2Object, (PSZ)s);
1738 }
1739 hFM2Object = WinQueryObject("<FM/2_SEEALL>");
1740 if (hFM2Object) {
1741 rc = WinSetObjectData(hFM2Object, (PSZ)s);
1742 }
1743 hFM2Object = WinQueryObject("<FM/2_DATABAR>");
1744 if (hFM2Object) {
1745 rc = WinSetObjectData(hFM2Object, (PSZ)s);
1746 }
[2]1747 }
[1789]1748 if (rc == SM2_NO || rc == SM2_DONTASK) {
[1459]1749 fDontSuggestAgain = TRUE;
[1865]1750 PrfWriteProfileData(fmprof, FM3Str, "DontSuggestAgain",
1751 &fDontSuggestAgain, sizeof(BOOL));
[1451]1752 }
[1471]1753 } // if suggest
[1522]1754 } // if !fDontSuggestAgain
[2]1755 didonce = TRUE;
[1856]1756
1757 DbgMsg(pszSrcFile, __LINE__, "FillTreeCnr finished"); // 2015-08-03 SHL FIXME debug
1758
[731]1759} // FillTreeCnr
[743]1760
1761
1762/**
1763 * Empty all records from a container and free associated storage and
1764 * Free up field infos
1765 */
1766
1767VOID EmptyCnr(HWND hwnd)
1768{
1769 PFIELDINFO pfi;
1770
[762]1771#if 0 // fixme to be gone or to be configurable
[751]1772 {
1773 int state = _heapchk();
1774 if (state != _HEAPOK)
1775 Runtime_Error(pszSrcFile, __LINE__, "heap corrupted %d", state);
1776 }
1777#endif
1778
[743]1779 // Remove all records
1780 RemoveCnrItems(hwnd, NULL, 0, CMA_FREE);
1781
1782 // Remove field info descriptors
1783 pfi = (PFIELDINFO) WinSendMsg(hwnd, CM_QUERYDETAILFIELDINFO, MPVOID,
1784 MPFROMSHORT(CMA_FIRST));
[745]1785 if (pfi &&
1786 (INT)WinSendMsg(hwnd, CM_REMOVEDETAILFIELDINFO, MPVOID,
1787 MPFROM2SHORT(0, CMA_FREE)) == -1) {
1788 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_REMOVEDETAILFIELDINFO hwnd %x", hwnd);
1789 }
[743]1790}
1791
1792/**
1793 * Free storage associated with container item
1794 */
1795
[751]1796VOID FreeCnrItemData(PCNRITEM pci)
[743]1797{
[1865]1798
1799 // 2015-08-23 SHL FIXME debug
1800 if ((pci->pszSubject && (ULONG)pci->pszSubject < 0x10000) ||
1801 (pci->pszLongName && (ULONG)pci->pszLongName < 0x10000) ||
1802 (pci->pszDisplayName && (ULONG)pci->pszDisplayName < 0x10000) ||
1803 (pci->pszFileName && (ULONG)pci->pszFileName < 0x10000) ||
1804 (pci->pszLongName && (ULONG)pci->pszLongName < 0x10000) ||
1805 (pci->pszFmtFileSize && (ULONG)pci->pszFmtFileSize < 0x10000))
1806 {
1807 Runtime_Error(pszSrcFile, __LINE__, "FreeCnrItemData attempting to free bogus %p", pci);
1808 }
1809
[1308]1810 if (pci->pszSubject) {
1811 if (pci->pszSubject != NullStr)
1812 free(pci->pszSubject);
[1174]1813 pci->pszSubject = NULL; // Catch illegal references
[762]1814 }
[1865]1815
[1308]1816 if (pci->pszLongName) {
1817 if (pci->pszLongName != NullStr)
1818 free(pci->pszLongName);
[1174]1819 pci->pszLongName = NULL; // Catch illegal references
[762]1820 }
[1865]1821
[1154]1822 // Bypass free if pszDisplayName points into pszFileName buffer
[1308]1823 if (pci->pszDisplayName) {
1824 if (pci->pszDisplayName != NullStr) {
1825 if (!pci->pszFileName ||
1826 pci->pszDisplayName < pci->pszFileName ||
1827 pci->pszDisplayName >= pci->pszFileName + _msize(pci->pszFileName))
1828 {
[1865]1829 free(pci->pszDisplayName);
[1308]1830 }
[1154]1831 }
[1308]1832 pci->pszDisplayName = NULL; // Catch illegal references
[1154]1833 }
[1113]1834
[1865]1835#if 1 // 2009-09-26 SHL FIXME debug dup free complaints
[1836]1836 if (!pci->pszFileName)
1837 Runtime_Error(pszSrcFile, __LINE__, "FreeCnrItemData attempting to free %p data twice", pci);
1838 else {
1839 if (pci->pszFileName != NullStr)
[1308]1840 free(pci->pszFileName);
[1836]1841 pci->pszFileName = NULL; // Catch illegal references
1842 }
1843#else
1844 {
[1865]1845 // 2015-08-23 SHL FIXME to work again now that Flesh/Stubby on thread
[1836]1846 #define HIST_COUNT 50
1847 static struct {
1848 PCNRITEM pci;
1849 PSZ pszFileName;
1850 } history[HIST_COUNT];
1851 static volatile UINT iHistNdx;
1852 UINT i;
1853
1854 if (!pci->pszFileName) {
1855 // Looks like pci was already freed
1856 // Try to locate original file name in history buffer
1857 for (i = 0; i < HIST_COUNT && pci != history[i].pci; i++) { } // Scan
1858 if (i < HIST_COUNT) {
1859 Runtime_Error(pszSrcFile, __LINE__, "FreeCnrItemData attempting to free %p data twice, fileName was %.260s",
1860 pci, history[i].pszFileName);
1861 } else {
1862 Runtime_Error(pszSrcFile, __LINE__, "FreeCnrItemData attempting to free %p data twice", pci);
1863 }
[1471]1864 }
[1836]1865 else {
1866 PSZ psz;
1867 PSZ *ppsz;
1868 // Grab a history slot
1869 // This should work well enoungh to prevent MT/SMP conflicts
1870 for (;;) {
1871 i = iHistNdx;
1872 if (++i >= HIST_COUNT)
1873 i = 0;
1874 if (++iHistNdx >= HIST_COUNT)
1875 iHistNdx = 0;
1876 if (i == iHistNdx) break;
1877 }
1878 ppsz = &history[iHistNdx].pszFileName;
1879 psz = *ppsz;
1880 if (psz)
1881 free(psz);
1882 if (pci->pszFileName && pci->pszFileName != NullStr)
1883 *ppsz = strdup(pci->pszFileName);
1884 else
1885 *ppsz = NULL;
1886 history[iHistNdx].pci = pci;
1887 if (pci->pszFileName != NullStr)
1888 free(pci->pszFileName);
1889 pci->pszFileName = NULL; // Catch illegal references and dup free attempts
1890 }
[1471]1891 }
1892
[1865]1893#endif // FIXME debug dup free
[1836]1894
[1308]1895 if (pci->pszLongName) {
1896 if (pci->pszLongName != NullStr)
1897 free(pci->pszLongName);
[1299]1898 pci->pszLongName = NULL; // Catch illegal references
1899 }
[1174]1900
[1308]1901 if (pci->pszFmtFileSize) {
1902 if (pci->pszFmtFileSize != NullStr)
1903 free(pci->pszFmtFileSize);
[1174]1904 pci->pszFmtFileSize = NULL; // Catch illegal references
[857]1905 }
[743]1906}
1907
1908/**
[762]1909 * Free single container item and associated storage
[743]1910 */
1911
[762]1912VOID FreeCnrItem(HWND hwnd, PCNRITEM pci)
[743]1913{
[745]1914 // DbgMsg(pszSrcFile, __LINE__, "FreeCnrItem hwnd %x pci %p", hwnd, pci);
1915
[743]1916 FreeCnrItemData(pci);
1917
[762]1918 if (!WinSendMsg(hwnd, CM_FREERECORD, MPFROMP(&pci), MPFROMSHORT(1))) {
[773]1919 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,
1920 "CM_FREERECORD hwnd %x pci %p file %s",
[783]1921 hwnd, pci,
[773]1922 pci && pci->pszFileName ? pci->pszFileName : "n/a");
[743]1923 }
1924}
1925
1926/**
[751]1927 * Free container item list and associated storage
[743]1928 */
1929
[751]1930VOID FreeCnrItemList(HWND hwnd, PCNRITEM pciFirst)
[743]1931{
[751]1932 PCNRITEM pci = pciFirst;
1933 PCNRITEM pciNext;
[762]1934 USHORT usCount;
[1564]1935 ITIMER_DESC itdSleep = { 0 }; // 30 May 11 GKY
[751]1936
[1564]1937 InitITimer(&itdSleep, 500);
[762]1938 for (usCount = 0; pci; usCount++) {
[751]1939 pciNext = (PCNRITEM) pci->rc.preccNextRecord;
[762]1940 FreeCnrItemData(pci);
[751]1941 pci = pciNext;
[1570]1942 if (!IdleIfNeeded(&itdSleep, 30)) {
1943 for (usCount = usCount + 1; pci; usCount++) {
[1759]1944 pciNext = (PCNRITEM) pci->rc.preccNextRecord;
1945 FreeCnrItemData(pci);
1946 pci = pciNext;
[1570]1947 }
1948 break;
1949 }
[751]1950 }
[1570]1951 priority_normal();
1952 DosPostEventSem(CompactSem);
[762]1953 if (usCount) {
1954 if (!WinSendMsg(hwnd, CM_FREERECORD, MPFROMP(&pci), MPFROMSHORT(usCount))) {
1955 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_FREERECORD hwnd %x pci %p cnt %u", hwnd, pci, usCount);
1956 }
1957 }
[751]1958}
1959
1960/**
1961 * Remove item(s) from container and free associated storage if requested
[762]1962 * @param pciFirst points to first item to remove or NULL to remove all
1963 * @param usCnt is remove count or 0 to remove all
[751]1964 * @returns count of items remaining in container or -1 if error
1965 */
1966
[762]1967INT RemoveCnrItems(HWND hwnd, PCNRITEM pciFirst, USHORT usCnt, USHORT usFlags)
[751]1968{
[762]1969 INT remaining = usCnt;
[1836]1970 BOOL bIdlePrioritySet = FALSE;
[1865]1971 // #define RCI_ITEMS_PER_TIMER_CHECK (10)
1972 // 10 seems a very conservative number
1973 // USHORT usTimerCheckCountdown = RCI_ITEMS_PER_TIMER_CHECK;
[762]1974 PCNRITEM pci;
[1564]1975 ITIMER_DESC itdSleep = { 0 }; // 30 May 11 GKY
[751]1976
[762]1977 if ((usCnt && !pciFirst) || (!usCnt && pciFirst)) {
1978 Runtime_Error(pszSrcFile, __LINE__, "pciFirst %p usCnt %u mismatch", pciFirst, usCnt);
[751]1979 remaining = -1;
[762]1980 }
1981 else {
1982 // Free our buffers if free requested
1983 if (usFlags & CMA_FREE) {
1984 if (pciFirst)
1985 pci = pciFirst;
1986 else {
[743]1987 pci = (PCNRITEM)WinSendMsg(hwnd, CM_QUERYRECORD, MPVOID,
[744]1988 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
[762]1989 if ((INT)pci == -1) {
[744]1990 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_QUERYRECORD");
[751]1991 remaining = -1;
[762]1992 pci = NULL;
1993 }
1994 }
[1564]1995 InitITimer(&itdSleep, 500);
[762]1996 while (pci) {
[1865]1997 FreeCnrItemData(pci);
[1836]1998 pci = (PCNRITEM)pci->rc.preccNextRecord;
1999 if (!pci)
2000 break;
[1865]2001 if (remaining && --remaining == 0)
2002 break;
2003 if (!bIdlePrioritySet /* && --usTimerCheckCountdown == 0 */) {
2004 bIdlePrioritySet = !IdleIfNeeded(&itdSleep, 30);
2005 // usTimerCheckCountdown = RCI_ITEMS_PER_TIMER_CHECK;
2006 }
[1759]2007 } // while
[1836]2008 if (bIdlePrioritySet)
[1865]2009 priority_normal();
[1836]2010
[1570]2011 DosPostEventSem(CompactSem);
[743]2012 }
2013 }
[745]2014
[1836]2015 // DbgMsg(pszSrcFile, __LINE__, "RemoveCnrItems %p %u %s", pci, usCnt, pci->pszFileName);
2016
[762]2017 if (remaining != - 1) {
2018 remaining = (INT)WinSendMsg(hwnd, CM_REMOVERECORD, MPFROMP(&pciFirst), MPFROM2SHORT(usCnt, usFlags));
[751]2019 if (remaining == -1) {
[762]2020 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_REMOVERECORD hwnd %x pci %p cnt %u", hwnd, pciFirst, usCnt);
[743]2021 }
2022 }
[1836]2023
[751]2024 return remaining;
[743]2025}
2026
[783]2027#pragma alloc_text(FILLDIR,FillInRecordFromFFB,FillInRecordFromFSA,IDFile)
[1856]2028#pragma alloc_text(FILLDIR1,ProcessDirectory,FillDirCnr,FillTreeCnr,FileAttrToString)
[783]2029#pragma alloc_text(EMPTYCNR,EmptyCnr,FreeCnrItemData,FreeCnrItem,FreeCnrItemList,RemoveCnrItems)
2030
Note: See TracBrowser for help on using the repository browser.