source: trunk/dll/filldir.c@ 1878

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

Remove debug code

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 63.7 KB
RevLine 
[31]1
2/***********************************************************************
3
4 $Id: filldir.c 1877 2015-10-11 21:43:27Z 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.
[1871]121 24 Aug 15 GKY Remove fDummy code
122 20 Sep 15 GKY Add code for Flesh to skip the directory entry added by Stubby (eliminate
123 use of NULL/Nullstr pszFileNames by Stubby). Add code to relink pci chain
124 following rename, delete, etc. Add "Expanding" window text.
[1873]125 26 Sep 15 GKY Remove fInitialDriveScan code
[31]126
127***********************************************************************/
128
[2]129#include <stdlib.h>
130#include <string.h>
[1154]131#include <malloc.h> // _msize _heapchk
[2]132#include <ctype.h>
[1564]133#include <limits.h>
[1335]134// #include <process.h> // _beginthread
[763]135
[907]136#define INCL_DOS
137#define INCL_WIN
138#define INCL_DOSERRORS
139#define INCL_LONGLONG
140
[1182]141#include "fm3dll.h"
[1223]142#include "fm3dll2.h" // #define's for UM_*, control id's, etc.
[1207]143#include "draglist.h" // Data declaration(s)
144#include "treecnr.h" // Data declaration(s)
145#include "info.h" // Data declaration(s)
146#include "newview.h" // Data declaration(s)
[1471]147#include "mainwnd.h" // hwndDrivelist
[907]148#include "fm3str.h"
149#include "filldir.h"
150#include "errutil.h" // Dos_Error...
151#include "strutil.h" // GetPString
[1078]152#include "misc.h" // GetTidForWindow
153#include "fortify.h" // 06 May 08 SHL
[1083]154#include "notebook.h" // INI file fields
[1856]155#include "flesh.h" // AddFleshWorkRequest
[1159]156#include "update.h" // SelectDriveIcon
[1182]157#include "valid.h" // CheckDrive
158#include "filter.h" // Filter
159#include "subj.h" // Subject
[1459]160#include "grep.h" // hwndStatus
[1182]161#include "copyf.h" // unlinkf
162#include "literal.h" // wildcard
[1400]163#include "i18nutil.h" // CommaFmtULL
[1182]164#include "wrappers.h" // xDosFindNext
[1856]165#include "init.h"
166#include "common.h"
[1335]167#include "excputil.h" // xbeginthread
[1459]168#include "fm3dlg.h" // INFO_LABEL
169#include "pathutil.h" // AddBackslashToPath
[1564]170#include "tmrsvcs.h" // ITIMER_DESC
[1836]171#if 0
172#define __PMPRINTF__
173#include "PMPRINTF.H"
174#endif
[2]175
[1207]176// Data definitions
[359]177static PSZ pszSrcFile = __FILE__;
[1550]178INT FixedVolume = 0;
[359]179
[1207]180#pragma data_seg(GLOBAL1)
181HPOINTER hptrEnv;
182HPOINTER hptrHidden;
183HPOINTER hptrReadonly;
184HPOINTER hptrSystem;
185
186#pragma data_seg(GLOBAL2)
[1459]187PCSZ FM3Tools = "<FM3_Tools>";
188PCSZ WPProgram = "WPProgram";
[1207]189
[751]190/**
191 * Return display string given standard file attribute mask
192 * @param fileAttr attribute mask in FILEFINDBUF format
193 * @return fixed length string for display
194 */
195
196const PSZ FileAttrToString(ULONG fileAttr)
197{
198 // From os2win.h
199 // FILE_ATTRIBUTE_READONLY 0x00000001
200 // FILE_ATTRIBUTE_HIDDEN 0x00000002
201 // FILE_ATTRIBUTE_SYSTEM 0x00000004
202 // 0x00000008
203 // FILE_ATTRIBUTE_DIRECTORY 0x00000010
204 // FILE_ATTRIBUTE_ARCHIVE 0x00000020
205
206 static CHAR *apszAttrString[] = {
207 // RHSDA
208 "-----",
209 "R----",
210 "-H---",
211 "RH---",
212 "--S--",
213 "R-S--",
214 "-HS--",
215 "RHS--",
216 "---D-",
217 "R--D-",
218 "-H-D-",
219 "RH-D-",
220 "--SD-",
221 "R-SD-",
222 "-HSD-",
223 "RHSD-",
224 "----A",
225 "R---A",
226 "-H--A",
227 "RH--A",
228 "--S-A",
229 "R-S-A",
230 "-HS-A",
231 "RHS-A",
232 "---DA",
233 "R--DA",
234 "-H-DA",
235 "RH-DA",
236 "--SDA",
237 "R-SDA",
238 "-HSDA",
239 "RHSDA"
240 };
241
242 fileAttr = ((fileAttr & 0x30) >> 1) | (fileAttr & 7); // Drop don't care bit from index
243
244 return apszAttrString[fileAttr];
245
246}
247
[1871]248HPOINTER IDFile(PSZ p)
[90]249{
[2]250 HPOINTER hptr;
[551]251 ULONG cmp;
[1780]252 CHAR cmps[6];
[2]253
[551]254 p = strrchr(p, '.');
[1644]255 if (p) {
[214]256 cmps[0] = '.';
257 cmps[1] = toupper(p[1]);
258 cmps[2] = toupper(p[2]);
259 cmps[3] = toupper(p[3]);
[1644]260 if (p[4]) {
261 cmps[4] = toupper(p[4]);
262 cmps[5] = 0;
263 }
264 else
265 cmps[4] = 0;
[214]266
[551]267 cmp = *(ULONG *) cmps;
[214]268
[1398]269 if (cmp == *(ULONG *) PCSZ_DOTEXE || cmp == *(ULONG *) PCSZ_DOTCMD ||
[1459]270 cmp == *(ULONG *) PCSZ_DOTBAT || cmp == *(ULONG *) PCSZ_DOTCOM ||
271 cmp == *(ULONG *) PCSZ_DOTBTM)
[214]272 hptr = hptrApp;
[551]273 else if (cmp == *(ULONG *) ".ZIP" || cmp == *(ULONG *) ".LZH" ||
274 cmp == *(ULONG *) ".ARJ" || cmp == *(ULONG *) ".ARC" ||
[552]275 cmp == *(ULONG *) ".ZOO" || cmp == *(ULONG *) ".RAR" ||
276 cmp == *(ULONG *) ".TAR" || cmp == *(ULONG *) ".TGZ" ||
[1398]277 cmp == *(ULONG *) ".GZ" || cmp == *(ULONG *) ".Z" ||
[1759]278 cmp == *(ULONG *) ".CAB" || cmp == *(ULONG *) ".BZ2" ||
279 cmp == *(ULONG *) ".WPI" || cmp == *(ULONG *) ".7Z")
[214]280 hptr = hptrArc;
[1398]281 else if (cmp == *(ULONG *) PCSZ_DOTBMP ||
[1459]282 cmp == *(ULONG *) PCSZ_DOTICO ||
283 cmp == *(ULONG *) PCSZ_DOTPTR ||
284 cmp == *(ULONG *) PCSZ_DOTJPEG ||
285 cmp == *(ULONG *) PCSZ_DOTJPG ||
286 cmp == *(ULONG *) ".GIF" ||
[551]287 cmp == *(ULONG *) ".TIF" || cmp == *(ULONG *) ".PCX" ||
[552]288 cmp == *(ULONG *) ".TGA" || cmp == *(ULONG *) ".XBM" ||
289 cmp == *(ULONG *) ".PNG" || cmp == *(ULONG *) ".PSD" ||
290 cmp == *(ULONG *) ".LGO" || cmp == *(ULONG *) ".EPS" ||
291 cmp == *(ULONG *) ".RLE" || cmp == *(ULONG *) ".RAS" ||
292 cmp == *(ULONG *) ".PLC" || cmp == *(ULONG *) ".MSP" ||
293 cmp == *(ULONG *) ".IFF" || cmp == *(ULONG *) ".FIT" ||
294 cmp == *(ULONG *) ".DCX" || cmp == *(ULONG *) ".MAC" ||
295 cmp == *(ULONG *) ".SFF" || cmp == *(ULONG *) ".SGI" ||
296 cmp == *(ULONG *) ".XWD" || cmp == *(ULONG *) ".XPM" ||
297 cmp == *(ULONG *) ".WPG" || cmp == *(ULONG *) ".CUR" ||
298 cmp == *(ULONG *) ".PNM" || cmp == *(ULONG *) ".PPM" ||
299 cmp == *(ULONG *) ".PGM" || cmp == *(ULONG *) ".PBM")
[214]300 hptr = hptrArt;
301 else
[551]302 hptr = (HPOINTER) 0;
[214]303 }
304 else
[551]305 hptr = (HPOINTER) 0;
[214]306
[2]307 return hptr;
308}
309
[1871]310BOOL IsDefaultIcon(HPOINTER hptr)
[214]311{
312 HPOINTER hptr2;
313 HPOINTER hptr3;
314 UINT u;
315
316 static HPOINTER hptrPMFile;
317 static HPOINTER hptrWPSFile;
318
[551]319 if (!hptrPMFile) {
320 hptrPMFile = WinQuerySysPointer(HWND_DESKTOP, SPTR_FILE, FALSE);
[214]321 }
322
323 // try to guess WPS default file icon
[551]324 hptr2 = (HPOINTER) 0;
325 for (u = 0; !hptrWPSFile && u < 10; u++) {
[214]326 char szFileName[CCHMAXPATH];
327 char *psz;
328
[1076]329 if (pTmpDir) {
[1069]330 psz = pTmpDir;
[214]331 strcpy(szFileName, psz);
332 psz = szFileName + strlen(szFileName) - 1;
[551]333 if (*psz != '\\') {
[214]334 psz++;
335 *psz++ = '\\';
336 }
337 }
338 else
339 psz = szFileName;
340
[551]341 sprintf(psz, "%08x.%03x", rand() & 0xffffffff, rand() & 0xfff);
342 if (IsFile(szFileName) != 1) {
[1544]343 FILE *fp;
344 CHAR *modew = "w";
[551]345
[1544]346 fp = xfopen(szFileName, modew, pszSrcFile, __LINE__, TRUE);
347
[551]348 if (fp) {
[214]349 fclose(fp);
350 hptr3 = WinLoadFileIcon(szFileName, FALSE);
[1402]351 unlinkf(szFileName);
[214]352 if (!hptr2)
353 hptr2 = hptr3;
[551]354 else if (hptr3 == hptr3) {
[214]355 hptrWPSFile = hptr3; // Got same icon twice
356 break;
357 }
358 }
359 }
360 DosSleep(rand() % 100);
361
[731]362 } // for
[214]363
364 return hptr == hptrPMFile || hptr == hptrWPSFile;
365
[731]366} // IsDefaultIcon
[214]367
[1439]368static VOID FetchCommonEAs(PCNRITEM pci)
369{
370 ULONG flags = driveflags[toupper(*pci->pszFileName) - 'A'];
371 BOOL fLoadSubjectForDrive = fLoadSubject && ~flags & DRIVE_NOLOADSUBJS;
[1444]372 BOOL fLoadLongNameForDrive = fLoadLongnames && //~flags & DRIVE_NOLONGNAMES &&
[1865]373 ~flags & DRIVE_NOLOADLONGS;
[1439]374 if (fLoadSubjectForDrive || fLoadLongNameForDrive) {
375 // Allocate space to hold GEA2s and .SUBJECT and .LONGNAME strings
[1836]376 PGEA2LIST pgealist = xmallocz(sizeof(GEA2LIST) + (sizeof(GEA2) * 2) + 32,
[1865]377 pszSrcFile, __LINE__);
[1439]378 if (pgealist) {
379 APIRET rc;
380 PFEA2LIST pfealist;
381 ULONG offset;
382 PGEA2 pgeaPrev = NULL;
383 PGEA2 pgea = pgealist->list; // Point at first available
384 EAOP2 eaop;
385 UINT state;
386 for (state = 0; state < 2; state++) {
387 PCSZ pcsz;
388 switch (state) {
389 case 0:
390 pcsz = fLoadSubjectForDrive ? SUBJECT : NULL;
391 break;
392 case 1:
393 pcsz = fLoadLongNameForDrive ? LONGNAME : NULL;
394 break;
395 }
396 if (pcsz) {
397 if (pgeaPrev) {
398 pgeaPrev->oNextEntryOffset = (PSZ)pgea - (PSZ)pgeaPrev;
399 }
400 strcpy(pgea->szName, pcsz);
401 pgea->cbName = strlen(pgea->szName);
402 pgea->oNextEntryOffset = 0;
403 offset = sizeof(GEA2) + pgea->cbName; // Calc length including null
404 offset = (offset + 3) & ~3; // Doubleword align
405 pgeaPrev = pgea;
406 pgea = (PGEA2)((PSZ)pgea + offset); // Point at next available
407 }
408 } // for
409 pgealist->cbList = (PSZ)pgea - (PSZ)pgealist;
[1836]410 pfealist = xmallocz(65536, pszSrcFile, __LINE__);
[1439]411 if (pfealist) {
[1836]412 pfealist->cbList = 65536;
[1439]413 eaop.fpGEA2List = pgealist;
414 eaop.fpFEA2List = pfealist;
415 eaop.oError = 0;
416 rc = DosQueryPathInfo(pci->pszFileName, FIL_QUERYEASFROMLIST,
[1459]417 (PVOID) &eaop, (ULONG) sizeof(EAOP2));
418 // Prevent this error from occuring when scanning a directory
419 // that contains a locked data file
420 if (rc && rc != ERROR_SHARING_VIOLATION) {
421 CHAR s[80];
422 sprintf(s, "%s %s",PCSZ_DOSQUERYPATHINFO, "%s");
423 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
424 s, pci->pszFileName);
425 }
[1439]426 else {
427 PFEA2 pfea = eaop.fpFEA2List->list;
428 while (pfea) {
429 if (pfea->cbValue) {
430 CHAR *achValue = pfea->szName + pfea->cbName + 1;
[1459]431 if (*(USHORT *)achValue != EAT_ASCII)
432 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
433 GetPString(IDS_ERROREATYPETEXT),
434 achValue, pfea->cbName, pfea->szName);
[1439]435 else {
436 CHAR ch = achValue[pfea->cbValue];
437 PSZ pszValue;
438 achValue[pfea->cbValue] = 0;
439 pszValue = xstrdup(achValue + (sizeof(USHORT) * 2), pszSrcFile, __LINE__);
440 achValue[pfea->cbValue] = ch;
441 if (strncmp(pfea->szName, LONGNAME, pfea->cbName) == 0)
442 pci->pszLongName = pszValue;
443 else if (strncmp(pfea->szName, SUBJECT, pfea->cbName) == 0)
444 pci->pszSubject = pszValue;
[1459]445 else
446 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
447 GetPString(IDS_ERROREATYPETEXT), pfea, pfea->cbName, pfea->szName);
[1439]448 }
449 }
450 if (!pfea->oNextEntryOffset)
451 break;
452 pfea = (PFEA2)((PSZ)pfea + pfea->oNextEntryOffset);
453 } // while
[1865]454 }
[1439]455 free(pfealist);
456 }
457 free(pgealist);
458 }
459 }
460} // FetchCommonEAs
461
[731]462ULONGLONG FillInRecordFromFFB(HWND hwndCnr,
463 PCNRITEM pci,
[551]464 const PSZ pszDirectory,
[841]465 const PFILEFINDBUF4L pffb,
[1459]466 const BOOL partial,
[737]467 DIRCNRDATA *dcd)
[31]468{
[841]469 // fill in a container record from a FILEFINDBUF4L structure
[2]470
[551]471 CHAR *p;
472 HPOINTER hptr;
[1326]473 ULONG flags;
[2]474
475 pci->hwndCnr = hwndCnr;
[731]476
[1673]477 /**
478 * note that we cheat below, and accept the full pathname in pszDirectory
479 * if !*pffb->achName. This speeds up and simplifies processing elsewhere
480 * (like in update.c)
[551]481 */
[1673]482
[763]483 if (!*pffb->achName) {
[773]484 pci->pszFileName = xstrdup(pszDirectory, pszSrcFile, __LINE__);
[763]485 }
[731]486 else {
487 INT c = strlen(pszDirectory);
488 INT c2 = pffb->cchName + 1;
489 if (pszDirectory[c - 1] != '\\')
490 c2++;
[773]491 pci->pszFileName = xmalloc(c + c2, pszSrcFile, __LINE__);
[1078]492# ifdef FORTIFY
493 {
[1154]494 if (dcd->type != TREE_FRAME)
[1078]495 Fortify_ChangeScope(pci->pszFileName, -1);
[1154]496 else {
[1078]497 Fortify_SetOwner(pci->pszFileName, 1);
[1154]498 Fortify_SetScope(pci->pszFileName, 2);
499 }
[1078]500 }
501# endif
[731]502 memcpy(pci->pszFileName, pszDirectory, c + 1);
503 p = pci->pszFileName + c - 1;
[167]504 if (*p != '\\') {
[2]505 p++;
506 *p = '\\';
507 }
508 p++;
[551]509 memcpy(p, pffb->achName, pffb->cchName + 1);
[2]510 }
511
[1439]512 // load Subject and/or Longname EAs, if required and have EAs
[1444]513 if (pffb->cbList > 4L && dcd &&
514 !(driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_NOEASUPPORT))
[1439]515 FetchCommonEAs(pci);
516
[731]517 if (!pci->pszSubject)
[751]518 pci->pszSubject = NullStr;
[731]519
[783]520 // load the object's longname
[762]521 if (!pci->pszLongName)
522 pci->pszLongName = NullStr;
[731]523
[783]524 // do anything required to case of filename
[167]525 if (fForceUpper)
[730]526 strupr(pci->pszFileName);
[167]527 else if (fForceLower)
[730]528 strlwr(pci->pszFileName);
[2]529
[1439]530 flags = driveflags[toupper(*pci->pszFileName) - 'A'];
531
[783]532 // get an icon to use with it
[551]533 if (pffb->attrFile & FILE_DIRECTORY) {
[214]534 // is directory
535 if (fNoIconsDirs ||
[1326]536 (flags & DRIVE_NOLOADICONS) ||
[730]537 !isalpha(*pci->pszFileName)) {
[551]538 hptr = (HPOINTER) 0;
[214]539 }
540 else
[730]541 hptr = WinLoadFileIcon(pci->pszFileName, FALSE);
[2]542 }
[551]543 else {
[214]544 // is file
545 if (fNoIconsFiles ||
[1326]546 (flags & DRIVE_NOLOADICONS) ||
[730]547 !isalpha(*pci->pszFileName)) {
[551]548 hptr = (HPOINTER) 0;
[167]549 }
[42]550 else
[730]551 hptr = WinLoadFileIcon(pci->pszFileName, FALSE);
[167]552
[214]553 if (!hptr || IsDefaultIcon(hptr))
[730]554 hptr = IDFile(pci->pszFileName);
[2]555 }
[214]556
[551]557 if (!hptr) {
[214]558 hptr = pffb->attrFile & FILE_DIRECTORY ?
[1335]559 hptrDir : pffb->attrFile & FILE_SYSTEM ?
560 hptrSystem : pffb->attrFile & FILE_HIDDEN ?
561 hptrHidden : pffb->attrFile & FILE_READONLY ?
[1326]562 hptrReadonly : hptrFile;
[167]563 }
[2]564
[737]565 // Tell container what part of pathname to display
[551]566 if (partial) {
[730]567 p = strrchr(pci->pszFileName, '\\');
[551]568 if (!p) {
[730]569 p = strrchr(pci->pszFileName, ':');
[167]570 if (!p)
[730]571 p = pci->pszFileName;
[2]572 else
[214]573 p++;
[2]574 }
[167]575 else if ((dcd && dcd->type == TREE_FRAME) ||
[551]576 (!(pffb->attrFile & FILE_DIRECTORY) || !*(p + 1))) {
[2]577 p++;
[167]578 }
579 if (!*p)
[730]580 p = pci->pszFileName;
[2]581 }
582 else
[730]583 p = pci->pszFileName;
[737]584 pci->pszDisplayName = p;
585
[1865]586 // Comma format the file size for large file support
[859]587 {
[1078]588 CHAR szBuf[30];
[856]589 CommaFmtULL(szBuf, sizeof(szBuf), pffb->cbFile, ' ');
590 pci->pszFmtFileSize = xstrdup(szBuf, pszSrcFile, __LINE__);
[1078]591# ifdef FORTIFY
592 {
[1856]593 UINT tid = GetTidForWindow(hwndCnr);
[1078]594 if (tid == 1)
595 Fortify_ChangeScope(pci->pszFmtFileSize, -1);
596 else
597 Fortify_SetOwner(pci->pszFmtFileSize, 1);
598 }
599# endif
[856]600 }
601
[783]602 // now fill the darned thing in...
[551]603 pci->date.day = pffb->fdateLastWrite.day;
604 pci->date.month = pffb->fdateLastWrite.month;
605 pci->date.year = pffb->fdateLastWrite.year + 1980;
606 pci->time.seconds = pffb->ftimeLastWrite.twosecs * 2;
607 pci->time.minutes = pffb->ftimeLastWrite.minutes;
608 pci->time.hours = pffb->ftimeLastWrite.hours;
609 pci->ladate.day = pffb->fdateLastAccess.day;
610 pci->ladate.month = pffb->fdateLastAccess.month;
611 pci->ladate.year = pffb->fdateLastAccess.year + 1980;
[2]612 pci->latime.seconds = pffb->ftimeLastAccess.twosecs * 2;
613 pci->latime.minutes = pffb->ftimeLastAccess.minutes;
[551]614 pci->latime.hours = pffb->ftimeLastAccess.hours;
615 pci->crdate.day = pffb->fdateCreation.day;
616 pci->crdate.month = pffb->fdateCreation.month;
617 pci->crdate.year = pffb->fdateCreation.year + 1980;
[2]618 pci->crtime.seconds = pffb->ftimeCreation.twosecs * 2;
619 pci->crtime.minutes = pffb->ftimeCreation.minutes;
[551]620 pci->crtime.hours = pffb->ftimeCreation.hours;
621 pci->easize = CBLIST_TO_EASIZE(pffb->cbList);
622 pci->cbFile = pffb->cbFile;
623 pci->attrFile = pffb->attrFile;
[751]624 pci->pszDispAttr = FileAttrToString(pci->attrFile);
[739]625 pci->rc.pszIcon = pci->pszDisplayName;
[551]626 pci->rc.hptrIcon = hptr;
[2]627
[1836]628
[783]629 // check to see if record should be visible
[1836]630 DosRequestMutexSem(hmtxFiltering, SEM_INDEFINITE_WAIT);
[167]631 if (dcd && (*dcd->mask.szMask || dcd->mask.antiattr ||
[551]632 ((dcd->mask.attrFile &
633 (FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY | FILE_ARCHIVED))
[1836]634 != (FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY | FILE_ARCHIVED)))) {
[551]635 if (*dcd->mask.szMask || dcd->mask.antiattr) {
636 if (!Filter((PMINIRECORDCORE) pci, (PVOID) & dcd->mask))
[1865]637 pci->rc.flRecordAttr |= CRA_FILTERED;
[2]638 }
[551]639 else if ((!(dcd->mask.attrFile & FILE_HIDDEN) &&
640 (pci->attrFile & FILE_HIDDEN)) ||
641 (!(dcd->mask.attrFile & FILE_SYSTEM) &&
642 (pci->attrFile & FILE_SYSTEM)) ||
643 (!(dcd->mask.attrFile & FILE_READONLY) &&
644 (pci->attrFile & FILE_READONLY)) ||
645 (!(dcd->mask.attrFile & FILE_ARCHIVED) &&
646 (pci->attrFile & FILE_ARCHIVED))) {
[2]647 pci->rc.flRecordAttr |= CRA_FILTERED;
[167]648 }
[2]649 }
[1836]650 DosReleaseMutexSem(hmtxFiltering);
[2]651
652 return pffb->cbFile + pci->easize;
653
[731]654} // FillInRecordFromFFB
[2]655
[1154]656ULONGLONG FillInRecordFromFSA(HWND hwndCnr,
657 PCNRITEM pci,
[907]658 const PSZ pszFileName,
659 const PFILESTATUS4L pfsa4,
[1459]660 const BOOL partial,
661 CHAR *pszFSType, // Optional
[1154]662 DIRCNRDATA *dcd) // Optional
[31]663{
[551]664 HPOINTER hptr;
[1439]665 ULONG flags;
[731]666 CHAR *p;
[1478]667 CHAR szBuf[CCHMAXPATH];
[2]668
[841]669 // fill in a container record from a FILESTATUS4L structure
[2]670
671 pci->hwndCnr = hwndCnr;
[773]672 pci->pszFileName = xstrdup(pszFileName, pszSrcFile, __LINE__);
[2]673
[1856]674 // 13 Jul 09 SHL FIXME to know if fetch can be bypassed if pszFSType already filled
[1440]675 // If FSType not supplied, assume don't need EAs either
[1444]676 if (pfsa4->cbList > 4L && dcd &&
677 !(driveflags[toupper(*pci->pszFileName) - 'A'] & DRIVE_NOEASUPPORT))
[1439]678 FetchCommonEAs(pci);
679
[731]680 if (!pci->pszSubject)
[751]681 pci->pszSubject = NullStr;
[762]682 if (!pci->pszLongName)
683 pci->pszLongName = NullStr;
[731]684
[167]685 if (fForceUpper)
[730]686 strupr(pci->pszFileName);
[167]687 else if (fForceLower)
[730]688 strlwr(pci->pszFileName);
[2]689
[1439]690 flags = driveflags[toupper(*pci->pszFileName) - 'A'];
691
[551]692 if (pfsa4->attrFile & FILE_DIRECTORY) {
[214]693 if (fNoIconsDirs ||
[1326]694 (flags & DRIVE_NOLOADICONS) ||
[730]695 !isalpha(*pci->pszFileName)) {
[551]696 hptr = (HPOINTER) 0;
[214]697 }
698 else
[730]699 hptr = WinLoadFileIcon(pci->pszFileName, FALSE);
[2]700 }
[551]701 else {
[214]702 if (fNoIconsFiles ||
[1326]703 (flags & DRIVE_NOLOADICONS) ||
[730]704 !isalpha(*pci->pszFileName)) {
705 hptr = IDFile(pci->pszFileName);
[2]706 }
[214]707 else
[730]708 hptr = WinLoadFileIcon(pci->pszFileName, FALSE);
[2]709 }
[551]710 if (!hptr) {
[214]711 hptr = pfsa4->attrFile & FILE_DIRECTORY ?
[551]712 hptrDir :
713 pfsa4->attrFile & FILE_SYSTEM ?
714 hptrSystem :
715 pfsa4->attrFile & FILE_HIDDEN ?
716 hptrHidden : pfsa4->attrFile & FILE_READONLY ? hptrReadonly : hptrFile;
[214]717 }
[2]718
[737]719 // Tell container what part of pathname to display
[551]720 if (partial) {
[730]721 p = strrchr(pci->pszFileName, '\\');
[167]722 if (!p) {
[730]723 p = strrchr(pci->pszFileName, ':');
[167]724 if (!p)
[730]725 p = pci->pszFileName;
[2]726 else
[214]727 p++;
[2]728 }
[167]729 else if ((dcd && dcd->type == TREE_FRAME) ||
[551]730 !(pfsa4->attrFile & FILE_DIRECTORY) || !*(p + 1))
[2]731 p++;
[167]732 if (!*p)
[730]733 p = pci->pszFileName;
[2]734 }
735 else
[730]736 p = pci->pszFileName;
[1440]737 if (pszFSType && (fShowFSTypeInTree || fShowDriveLabelInTree)) {
[1424]738 strcpy(szBuf, p);
739 strcat(szBuf, " [");
[1440]740 strcat(szBuf, pszFSType);
[1424]741 strcat(szBuf, "]");
742 pci->pszDisplayName = xstrdup(szBuf, pszSrcFile, __LINE__);
743 }
744 else
745 pci->pszDisplayName = p;
[737]746
[1856]747 // 13 Jul 09 SHL FIXME to know why pszFSType check needed
[1440]748 // comma format the file size for large file support
749 if (!pszFSType || *pszFSType == 0) {
[1154]750 CHAR szBuf[30];
[856]751 CommaFmtULL(szBuf, sizeof(szBuf), pfsa4->cbFile, ' ');
752 pci->pszFmtFileSize = xstrdup(szBuf, pszSrcFile, __LINE__);
[1154]753# ifdef FORTIFY
754 {
755 if (dcd && dcd->type == TREE_FRAME) {
756 // Will be freed in TreeCnrWndProc WM_DESTROY
757 // Fortify_SetOwner(pci->pszFmtFileSize, 1);
758 Fortify_SetScope(pci->pszFmtFileSize, 2);
759 }
760 }
761# endif
[856]762 }
[1444]763 else {
[1439]764 pci->pszFmtFileSize = NullStr;
[1444]765 }
[551]766 pci->date.day = pfsa4->fdateLastWrite.day;
767 pci->date.month = pfsa4->fdateLastWrite.month;
768 pci->date.year = pfsa4->fdateLastWrite.year + 1980;
769 pci->time.seconds = pfsa4->ftimeLastWrite.twosecs * 2;
770 pci->time.minutes = pfsa4->ftimeLastWrite.minutes;
771 pci->time.hours = pfsa4->ftimeLastWrite.hours;
772 pci->ladate.day = pfsa4->fdateLastAccess.day;
773 pci->ladate.month = pfsa4->fdateLastAccess.month;
774 pci->ladate.year = pfsa4->fdateLastAccess.year + 1980;
[2]775 pci->latime.seconds = pfsa4->ftimeLastAccess.twosecs * 2;
776 pci->latime.minutes = pfsa4->ftimeLastAccess.minutes;
[551]777 pci->latime.hours = pfsa4->ftimeLastAccess.hours;
778 pci->crdate.day = pfsa4->fdateCreation.day;
779 pci->crdate.month = pfsa4->fdateCreation.month;
780 pci->crdate.year = pfsa4->fdateCreation.year + 1980;
[2]781 pci->crtime.seconds = pfsa4->ftimeCreation.twosecs * 2;
782 pci->crtime.minutes = pfsa4->ftimeCreation.minutes;
[551]783 pci->crtime.hours = pfsa4->ftimeCreation.hours;
784 pci->easize = CBLIST_TO_EASIZE(pfsa4->cbList);
785 pci->cbFile = pfsa4->cbFile;
786 pci->attrFile = pfsa4->attrFile;
[751]787 pci->pszDispAttr = FileAttrToString(pci->attrFile);
[739]788 pci->rc.pszIcon = pci->pszDisplayName;
[551]789 pci->rc.hptrIcon = hptr;
[2]790
[1836]791 DosRequestMutexSem(hmtxFiltering, SEM_INDEFINITE_WAIT);
[167]792 if (dcd &&
793 (*dcd->mask.szMask || dcd->mask.antiattr ||
794 ((dcd->mask.attrFile &
[551]795 (FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY | FILE_ARCHIVED)) !=
796 (FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY | FILE_ARCHIVED)))) {
797 if (*dcd->mask.szMask || dcd->mask.antiattr) {
798 if (!Filter((PMINIRECORDCORE) pci, (PVOID) & dcd->mask))
[1865]799 pci->rc.flRecordAttr |= CRA_FILTERED;
[2]800 }
[167]801 else if ((!(dcd->mask.attrFile & FILE_HIDDEN) &&
[214]802 (pci->attrFile & FILE_HIDDEN)) ||
803 (!(dcd->mask.attrFile & FILE_SYSTEM) &&
804 (pci->attrFile & FILE_SYSTEM)) ||
805 (!(dcd->mask.attrFile & FILE_READONLY) &&
806 (pci->attrFile & FILE_READONLY)) ||
807 (!(dcd->mask.attrFile & FILE_ARCHIVED) &&
808 (pci->attrFile & FILE_ARCHIVED)))
[2]809 pci->rc.flRecordAttr |= CRA_FILTERED;
810 }
[1836]811 DosReleaseMutexSem(hmtxFiltering);
[2]812
813 return pfsa4->cbFile + pci->easize;
814
[731]815} // FillInRecordFromFSA
[2]816
[737]817VOID ProcessDirectory(const HWND hwndCnr,
818 const PCNRITEM pciParent,
819 const CHAR *szDirBase,
820 const BOOL filestoo,
821 const BOOL recurse,
822 const BOOL partial,
[1871]823 CHAR *stopflag,
[1459]824 DIRCNRDATA *dcd, // Optional
825 ULONG *pulTotalFiles, // Optional
[1871]826 PULONGLONG pullTotalBytes, // Optional
827 CHAR *LoadedFirstChild) // Optional
[31]828{
[1673]829 /**
830 * put all the directories (and files if filestoo is TRUE) from a
[2]831 * directory into the container. recurse through subdirectories if
832 * recurse is TRUE.
833 */
834
[551]835 PSZ pszFileSpec;
[841]836 PFILEFINDBUF4L paffbFound;
837 PFILEFINDBUF4L *papffbSelected;
838 PFILEFINDBUF4L pffbFile;
839 PFILEFINDBUF4L paffbTotal = NULL;
840 PFILEFINDBUF4L paffbTemp;
[551]841 HDIR hdir = HDIR_CREATE;
[783]842 ULONG ulFindCnt;
843 ULONG ulFindMax;
844 ULONG ulSelCnt;
[1459]845 ULONG cAffbTotal = 0;
[551]846 ULONGLONG ullBytes;
847 ULONGLONG ullTotalBytes;
848 ULONG ulReturnFiles = 0;
849 ULONGLONG ullReturnBytes = 0;
850 APIRET rc;
851 PCNRITEM pci;
852 PCNRITEM pciFirst;
[1871]853 PCNRITEM pciNext;
[551]854 RECORDINSERT ri;
855 BOOL ok = TRUE;
[783]856 ULONG ulBufBytes;
857 ULONG x;
[1564]858 ITIMER_DESC itdSleep = { 0 }; // 30 May 11 GKY
[2]859
[551]860 if (isalpha(*szDirBase) && szDirBase[1] == ':' && szDirBase[2] == '\\') {
[167]861 if ((driveflags[toupper(*szDirBase) - 'A'] & DRIVE_REMOTE) && fRemoteBug)
[1174]862 ulFindMax = 1; // file system gets confused
[167]863 else if (driveflags[toupper(*szDirBase) - 'A'] & DRIVE_ZIPSTREAM)
[783]864 ulFindMax = min(FilesToGet, 225); // anything more is wasted
[2]865 else
[783]866 ulFindMax = FilesToGet; // full-out
[2]867 }
[924]868 else
[783]869 ulFindMax = FilesToGet;
[924]870
[167]871 if (OS2ver[0] == 20 && OS2ver[1] < 30)
[841]872 ulFindMax = min(ulFindMax, (65535 / sizeof(FILEFINDBUF4L)));
[2]873
[841]874 ulBufBytes = ulFindMax * sizeof(FILEFINDBUF4L);
[783]875
[551]876 pszFileSpec = xmalloc(CCHMAXPATH + 2, pszSrcFile, __LINE__);
[783]877 paffbFound = xmalloc(ulBufBytes, pszSrcFile, __LINE__);
[841]878 papffbSelected = xmalloc(sizeof(PFILEFINDBUF4L) * ulFindMax, pszSrcFile, __LINE__);
[783]879
[167]880 if (paffbFound && papffbSelected && pszFileSpec) {
[1438]881 strcpy(pszFileSpec, szDirBase);
882 AddBackslashToPath(pszFileSpec);
883 strcat(pszFileSpec, "*");
[2]884 DosError(FERR_DISABLEHARDERR);
[783]885 ulFindCnt = ulFindMax;
[838]886 rc = xDosFindFirst(pszFileSpec,
887 &hdir,
888 FILE_NORMAL | FILE_READONLY | FILE_ARCHIVED |
889 FILE_SYSTEM | FILE_HIDDEN |
890 (filestoo ? FILE_DIRECTORY : MUST_HAVE_DIRECTORY),
891 paffbFound,
892 ulBufBytes,
893 &ulFindCnt,
[841]894 FIL_QUERYEASIZEL);
[1570]895 priority_normal();
[1471]896 pszFileSpec[strlen(pszFileSpec) - 1] = 0; // Chop off wildcard
[551]897 if (!rc) {
[1564]898 InitITimer(&itdSleep, 500);
[783]899 do {
[1673]900 /**
[1873]901 * remove . and .. and directories already added
902 * by Stubby from list if present
[214]903 * also counter file system bugs that sometimes
904 * allows normal files to slip through when
905 * only directories should appear (only a few
906 * network file systems exhibit such a problem).
907 */
[2]908
[214]909 if (stopflag && *stopflag)
910 goto Abort;
[783]911 pffbFile = paffbFound;
912 ulSelCnt = 0;
[1871]913 for (;;) {
[214]914 if (!*pffbFile->achName ||
[783]915 (!filestoo && ~pffbFile->attrFile & FILE_DIRECTORY) ||
916 (pffbFile->attrFile & FILE_DIRECTORY &&
[1838]917 !pffbFile->achName[0] || pffbFile->achName[0] == '.' &&
[534]918 (!pffbFile->achName[1] ||
[1871]919 (pffbFile->achName[1] == '.' && !pffbFile->achName[2])) ||
920 (LoadedFirstChild && !stricmp(LoadedFirstChild, pffbFile->achName)))) {
[783]921 // ulFindCnt--; // Got . or .. or file to be skipped
[174]922 }
[214]923 else
[783]924 papffbSelected[ulSelCnt++] = pffbFile; // Remember selected file
[551]925 if (!pffbFile->oNextEntryOffset) {
[783]926 // ulFindCnt = ulSelCnt; // Remember number selected
[214]927 break;
928 }
[841]929 pffbFile = (PFILEFINDBUF4L)((PBYTE)pffbFile + pffbFile->oNextEntryOffset);
[763]930 } // for
[783]931 if (ulSelCnt) {
932 // One or more entries selected
[214]933 if (stopflag && *stopflag)
934 goto Abort;
[1865]935 if (fSyncUpdates) {
936 if (!WinIsWindow(WinQueryAnchorBlock(hwndCnr), hwndCnr)) {
937 ok = FALSE;
[1836]938 ullTotalBytes = 0;
939 break;
940 }
[214]941 pciFirst = WinSendMsg(hwndCnr, CM_ALLOCRECORD,
[783]942 MPFROMLONG(EXTRA_RECORD_BYTES),
943 MPFROMLONG(ulSelCnt));
[359]944 if (!pciFirst) {
[1395]945 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
[1459]946 GetPString(IDS_CMALLOCRECERRTEXT));
[359]947 ok = FALSE;
948 ullTotalBytes = 0;
949 }
950 else {
[1856]951 // 04 Jan 08 SHL FIXME like comp.c to handle less than ulSelCnt records
[214]952 pci = pciFirst;
953 ullTotalBytes = 0;
[1459]954 // Finish filling pci items
[783]955 for (x = 0; x < ulSelCnt; x++) {
[1865]956 pffbFile = papffbSelected[x];
[551]957 ullBytes = FillInRecordFromFFB(hwndCnr, pci, pszFileSpec,
[1865]958 pffbFile, partial, dcd);
[1871]959 pciNext = pci;
960 pci = (PCNRITEM) pci->rc.preccNextRecord;
961 if (pci && (INT) pci != -1)
962 pci->pciPrevious = pciNext;
[214]963 ullTotalBytes += ullBytes;
[731]964 } // for
[1459]965 // Insert selected in container
[783]966 memset(&ri, 0, sizeof(RECORDINSERT));
967 ri.cb = sizeof(RECORDINSERT);
968 ri.pRecordOrder = (PRECORDCORE) CMA_END;
969 ri.pRecordParent = (PRECORDCORE) pciParent;
970 ri.zOrder = (ULONG) CMA_TOP;
971 ri.cRecordsInsert = ulSelCnt;
[1316]972 ri.fInvalidateRecord = TRUE;
[783]973 if (!WinSendMsg(hwndCnr,
974 CM_INSERTRECORD,
975 MPFROMP(pciFirst), MPFROMP(&ri))) {
976 DosSleep(10); // Give GUI time to work
977 WinSetFocus(HWND_DESKTOP, hwndCnr);
[1672]978 // Retry
[214]979 if (!WinSendMsg(hwndCnr,
980 CM_INSERTRECORD,
[551]981 MPFROMP(pciFirst), MPFROMP(&ri))) {
[1395]982 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
983 GetPString(IDS_CMINSERTERRTEXT));
[783]984 ok = FALSE;
985 ullTotalBytes = 0;
986 if (WinIsWindow((HAB) 0, hwndCnr))
[1335]987 FreeCnrItemList(hwndCnr, pciFirst);
[214]988 }
989 }
990 }
[551]991 if (ok) {
[214]992 ullReturnBytes += ullTotalBytes;
[1865]993 ulReturnFiles += ulSelCnt;
994 DosRequestMutexSem(hmtxFiltering, SEM_INDEFINITE_WAIT);
[1459]995 if (dcd) {
996 dcd->totalfiles += ulSelCnt;
997 dcd->ullTotalBytes += ullTotalBytes;
[1865]998 }
999 DosReleaseMutexSem(hmtxFiltering);
[1335]1000 }
[783]1001 } // if sync updates
[551]1002 else {
[783]1003 // Append newly selected entries to aggregate list
[359]1004 paffbTemp = xrealloc(paffbTotal,
[1459]1005 sizeof(FILEFINDBUF4L) * (ulSelCnt + cAffbTotal),
[551]1006 pszSrcFile, __LINE__);
1007 if (paffbTemp) {
[1856]1008 // 13 Aug 07 SHL FIXME to optimize copy
[214]1009 paffbTotal = paffbTemp;
[1459]1010 ullTotalBytes = 0; // 15 Sep 09 SHL
1011 for (x = 0; x < ulSelCnt; x++) {
1012 paffbTotal[x + cAffbTotal] = *papffbSelected[x];
[1865]1013 ullTotalBytes += papffbSelected[x]->cbFile;
[1459]1014 }
1015 cAffbTotal += ulSelCnt;
[214]1016 }
[551]1017 else {
[214]1018 saymsg(MB_ENTER,
1019 HWND_DESKTOP,
[551]1020 GetPString(IDS_ERRORTEXT), GetPString(IDS_OUTOFMEMORY));
[214]1021 break;
1022 }
1023 }
[783]1024 } // if entries selected
[214]1025 if (stopflag && *stopflag)
[551]1026 goto Abort;
[214]1027 DosError(FERR_DISABLEHARDERR);
[783]1028 ulFindCnt = ulFindMax;
[850]1029 rc = xDosFindNext(hdir, paffbFound, ulBufBytes, &ulFindCnt, FIL_QUERYEASIZEL);
[1570]1030 priority_normal();
[214]1031 if (rc)
[1567]1032 DosError(FERR_DISABLEHARDERR);
1033 SleepIfNeeded(&itdSleep, 1);
[783]1034 } while (!rc);
1035
[2]1036 DosFindClose(hdir);
[1009]1037 xfree(paffbFound, pszSrcFile, __LINE__);
[985]1038 paffbFound = NULL;
[1009]1039 xfree(papffbSelected, pszSrcFile, __LINE__);
[985]1040 papffbSelected = NULL;
[2]1041
[1459]1042 if (cAffbTotal && paffbTotal) {
1043 // Not fSyncUpdates and have work
[214]1044 if (stopflag && *stopflag)
1045 goto Abort;
[167]1046
[1759]1047 InitITimer(&itdSleep, 500);
[1567]1048 pci = NULL;
1049 ullTotalBytes = 0;
1050 pffbFile = paffbTotal;
1051 for (x = 0; x < cAffbTotal; x++) {
1052 ULONG ulRecsToInsert;
[1459]1053
[1871]1054 if (pci == NULL) {
[1865]1055 if (!WinIsWindow(WinQueryAnchorBlock(hwndCnr), hwndCnr)) {
1056 ok = FALSE;
[1836]1057 ullTotalBytes = 0;
1058 break;
1059 }
[1567]1060 ulRecsToInsert = cAffbTotal - x < USHRT_MAX ? cAffbTotal - x : USHRT_MAX;
1061 pciFirst = WinSendMsg(hwndCnr, CM_ALLOCRECORD,
1062 MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(ulRecsToInsert));
[1564]1063
[1865]1064 if (!pciFirst) {
1065 //ERRORID erridErrorCode = WinGetLastError(WinQueryAnchorBlock(hwndCnr));
1066 //PmpfF(("Allocation failed %i", erridErrorCode));
[1567]1067 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1068 GetPString(IDS_CMALLOCRECERRTEXT));
1069 ok = FALSE;
1070 ullTotalBytes = 0;
1071 break;
1072 }
1073 else {
[1856]1074 // 04 Jan 08 SHL FIXME like comp.c to handle less than ulSelCnt records
[1871]1075 if (hwndStatus && dcd && dcd->hwndFrame ==
1076 WinQueryActiveWindow(dcd->hwndParent)) {
1077 WinSetWindowText(hwndStatus, (CHAR *) GetPString(LoadedFirstChild ?
1078 IDS_PLEASEWAITEXPANDINGTEXT :
1079 IDS_PLEASEWAITCOUNTINGTEXT));
[1567]1080 }
1081 pci = pciFirst;
1082 }
[1865]1083 }
[1567]1084 ullBytes = FillInRecordFromFFB(hwndCnr, pci, pszFileSpec,
[1871]1085 pffbFile, partial, dcd);
1086 pciNext = pci;
1087 pci = (PCNRITEM) pci->rc.preccNextRecord;
1088 if (pci && (INT) pci != -1)
1089 pci->pciPrevious = pciNext;
[1567]1090 ullTotalBytes += ullBytes;
[1865]1091 // 15 Sep 09 SHL allow timed updates to see
1092 DosRequestMutexSem(hmtxFiltering, SEM_INDEFINITE_WAIT);
[1567]1093 if (dcd) {
1094 dcd->totalfiles = x;
1095 dcd->ullTotalBytes = ullTotalBytes;
[1865]1096 }
1097 DosReleaseMutexSem(hmtxFiltering);
[1567]1098 // Can not use offset since we have merged lists - this should be equivalent
1099 pffbFile = (PFILEFINDBUF4L)((PBYTE)pffbFile + sizeof(FILEFINDBUF4L));
[1564]1100
[1865]1101 if (!IdleIfNeeded(&itdSleep, 30)) {
1102 for (x = x+1; x < cAffbTotal; x++) {
[1759]1103 ullBytes = FillInRecordFromFFB(hwndCnr, pci, pszFileSpec,
[1865]1104 pffbFile, partial, dcd);
[1759]1105 pci = (PCNRITEM) pci->rc.preccNextRecord;
[1865]1106 ullTotalBytes += ullBytes;
1107 DosRequestMutexSem(hmtxFiltering, SEM_INDEFINITE_WAIT);
[1759]1108 if (dcd) {
[1865]1109 dcd->totalfiles = x;
1110 dcd->ullTotalBytes = ullTotalBytes;
1111 }
1112 DosReleaseMutexSem(hmtxFiltering);
1113 pffbFile = (PFILEFINDBUF4L)((PBYTE)pffbFile + sizeof(FILEFINDBUF4L));
[1759]1114 if (pci == NULL) {
[1865]1115 priority_normal();
1116 InitITimer(&itdSleep, 500);
1117 break;
[1759]1118 }
1119 }
1120 }
[1570]1121
[1567]1122 if (pci == NULL && ulRecsToInsert) {
[551]1123 memset(&ri, 0, sizeof(RECORDINSERT));
1124 ri.cb = sizeof(RECORDINSERT);
1125 ri.pRecordOrder = (PRECORDCORE) CMA_END;
1126 ri.pRecordParent = (PRECORDCORE) pciParent;
1127 ri.zOrder = (ULONG) CMA_TOP;
[1564]1128 ri.cRecordsInsert = ulRecsToInsert;
[551]1129 ri.fInvalidateRecord = (!fSyncUpdates && dcd &&
1130 dcd->type == DIR_FRAME) ? FALSE : TRUE;
1131 if (!WinSendMsg(hwndCnr, CM_INSERTRECORD,
1132 MPFROMP(pciFirst), MPFROMP(&ri))) {
[783]1133 DosSleep(10); // Give GUI time to work
[1672]1134 // Retry
[551]1135 WinSetFocus(HWND_DESKTOP, hwndCnr);
1136 if (!WinSendMsg(hwndCnr, CM_INSERTRECORD,
1137 MPFROMP(pciFirst), MPFROMP(&ri))) {
[1395]1138 Win_Error(hwndCnr, HWND_DESKTOP, pszSrcFile, __LINE__,
1139 GetPString(IDS_CMINSERTERRTEXT));
[214]1140 ok = FALSE;
1141 ullTotalBytes = 0;
[751]1142 if (WinIsWindow((HAB) 0, hwndCnr))
[1567]1143 FreeCnrItemList(hwndCnr, pciFirst);
1144 pciFirst = NULL;
1145 break;
[214]1146 }
1147 }
[1567]1148 }
[1570]1149 //SleepIfNeeded(&itdSleep, 1);
[1759]1150 }
1151 priority_normal();
[551]1152 if (ok) {
[214]1153 ullReturnBytes += ullTotalBytes;
[783]1154 ulReturnFiles += ulFindCnt;
[214]1155 }
[2]1156 }
1157 }
1158
[924]1159 /**
1160 * DosFind for subdirectories of a read-only directory on a FAT volume
1161 * returns path not found if there are no subdirectories
1162 * FAT FS seems to ignore . and .. in this case
1163 * Map to no more files
1164 * We could verify that directory is marked read-only, it's probably not
1165 * worth the extra code since we do verify 2 out of 3 prerequisites
1166 * 15 Jan 08 SHL
1167 */
1168 if (rc == ERROR_PATH_NOT_FOUND && !filestoo) {
1169 ULONG ulDriveType = 0;
1170 CHAR szFSType[CCHMAXPATH];
1171 INT removable = CheckDrive(*pszFileSpec, szFSType, &ulDriveType);
1172 if (removable != -1 && strcmp(szFSType, "FAT") == 0)
1173 rc = ERROR_NO_MORE_FILES;
1174 }
1175
[1856]1176 // 13 Oct 09 SHL FIXME to be saymsg if ERROR_NOT_READY and first try on volume
[1873]1177 if (rc && rc != ERROR_NO_MORE_FILES && fDontSuggestAgain) {
[783]1178 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
1179 GetPString(IDS_CANTFINDDIRTEXT), pszFileSpec);
1180 }
1181
[167]1182 if (!fSyncUpdates && dcd && dcd->type == DIR_FRAME)
[551]1183 WinSendMsg(hwndCnr, CM_INVALIDATERECORD, MPVOID,
1184 MPFROM2SHORT(0, CMA_ERASE));
[2]1185 }
1186Abort:
[1009]1187 xfree(paffbTotal, pszSrcFile, __LINE__);
1188 xfree(pszFileSpec, pszSrcFile, __LINE__);
1189 xfree(paffbFound, pszSrcFile, __LINE__);
1190 xfree(papffbSelected, pszSrcFile, __LINE__);
[783]1191
[551]1192 if (recurse) {
[2]1193 pci = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pciParent),
[214]1194 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
[762]1195 while (pci && (INT)pci != -1) {
[1838]1196 if (!pci->pszFileName || !strcmp(pci->pszFileName, NullStr)) {
[1865]1197 Runtime_Error(pszSrcFile, __LINE__, "pci->pszFileName NULL for %p", pci);
1198 return;
[1838]1199 }
[1354]1200 if ((pci->attrFile & FILE_DIRECTORY))
[1871]1201 AddFleshWorkRequest(hwndCnr, pci, eStubby);
[2]1202 pci = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
[1865]1203 MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
[2]1204 }
1205 }
1206
[1459]1207 // Reset counts in case errors occurred after initially counted
[167]1208 if (pulTotalFiles)
1209 *pulTotalFiles = ulReturnFiles;
[2]1210
[167]1211 if (pullTotalBytes)
1212 *pullTotalBytes = ullReturnBytes;
[2]1213
[731]1214} // ProcessDirectory
[167]1215
1216VOID FillDirCnr(HWND hwndCnr,
[551]1217 CHAR * pszDirectory,
[924]1218 DIRCNRDATA * dcd,
1219 PULONGLONG pullTotalBytes)
[90]1220{
[167]1221 ProcessDirectory(hwndCnr,
[924]1222 (PCNRITEM)NULL,
[167]1223 pszDirectory,
[737]1224 TRUE, // filestoo
1225 FALSE, // recurse
[1459]1226 TRUE, // partial
1227 dcd ? &dcd->stopflag : NULL,
1228 dcd,
[924]1229 NULL, // total files
[1871]1230 pullTotalBytes,
1231 0);
[2]1232 DosPostEventSem(CompactSem);
1233
[1856]1234#if 0 // 2011-05-31 SHL FIXME to be gone or to be configurable
[751]1235 {
1236 int state = _heapchk();
1237 if (state != _HEAPOK)
1238 Runtime_Error(pszSrcFile, __LINE__, "heap corrupted %d", state);
[763]1239 else
1240 DbgMsg(pszSrcFile, __LINE__, "_memavl %u", _memavl());
[751]1241 }
1242#endif
1243
[731]1244} // FillDirCnr
[2]1245
[1471]1246/**
1247 * Fill tree container and drives list
1248 * Offer to update command line options if not already done and not suppressed
1249 */
1250
[551]1251VOID FillTreeCnr(HWND hwndCnr, HWND hwndParent)
[90]1252{
[1471]1253 ULONG ulCurDriveNum;
1254 ULONG ulDriveMap;
1255 ULONG numtoinsert = 0;
[924]1256 ULONG ulDriveType;
[1471]1257 PCNRITEM pci, pciFirst = NULL;
1258 PCNRITEM pciNext;
1259 PCNRITEM pciParent = NULL;
1260 UINT iDrvNum;
1261 ULONG ulDriveMapMask;
[1754]1262 CHAR szSuggest[32] = {0}; // Suggested startup command line parameters
[1865]1263 CHAR szDrive[CCHMAXPATH] = " :\\";
[1440]1264 CHAR szFSType[CCHMAXPATH];
[841]1265 FILESTATUS4L fsa4;
[551]1266 APIRET rc;
[739]1267 ULONG startdrive = 3;
[1471]1268 HWND hwndDrivelist;
[1439]1269 static BOOL didonce;
[1471]1270 static ULONG ulLastDriveMap;
[2]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);
[2]1675 DosPostEventSem(CompactSem);
[739]1676
[1522]1677 if (!fDontSuggestAgain) {
[2]1678 BYTE info;
1679 BOOL includesyours = FALSE;
1680
[1873]1681 // 02 Mar 14 GKY !didonce for fFirstTime so it works again
[1754]1682 if (*szSuggest || ~driveflags[1] & DRIVE_IGNORE && !didonce) {
[551]1683 if (!DosDevConfig(&info, DEVINFO_FLOPPY) && info == 1) {
[1471]1684 if (!*szSuggest) {
1685 *szSuggest = '/';
1686 szSuggest[1] = 0;
[214]1687 }
1688 else
[1471]1689 memmove(szSuggest + 2, szSuggest + 1, strlen(szSuggest));
1690 szSuggest[1] = 'B';
[2]1691 }
1692 }
[1471]1693 if (*szSuggest) {
[1522]1694 APIRET rc;
[1471]1695 for (iDrvNum = 2; iDrvNum < 26; iDrvNum++) {
1696 if (driveflags[iDrvNum] & DRIVE_IGNORE) {
[214]1697 includesyours = TRUE;
[1471]1698 sprintf(szSuggest + strlen(szSuggest), "%c", (char)(iDrvNum + 'A'));
[214]1699 }
[2]1700 }
[1471]1701 strcat(szSuggest, " %*");
[1789]1702 rc = saymsg2(NULL, 3, HWND_DESKTOP,
[1865]1703 GetPString(IDS_SUGGESTTITLETEXT),
1704 GetPString(IDS_SUGGEST1TEXT),
1705 (includesyours) ? GetPString(IDS_SUGGEST2TEXT) : NullStr,
[1789]1706 szSuggest);
1707 if (rc == SM2_YES || rc == SM2_DONTASK) {
[1567]1708 HOBJECT hFM2Object;
[214]1709 char s[64];
[1471]1710 sprintf(s, "PARAMETERS=%s", szSuggest);
[1567]1711 hFM2Object = WinQueryObject("<FM/2>");
1712 if (hFM2Object) {
1713 rc = WinSetObjectData(hFM2Object, (PSZ)s);
1714 }
1715 hFM2Object = WinQueryObject("<FM/2 LITE>");
1716 if (hFM2Object) {
1717 rc = WinSetObjectData(hFM2Object, (PSZ)s);
1718 }
1719 hFM2Object = WinQueryObject("<FM/2_AV/2>");
1720 if (hFM2Object) {
1721 rc = WinSetObjectData(hFM2Object, (PSZ)s);
1722 }
1723 hFM2Object = WinQueryObject("<FM/2_DIRSIZE>");
1724 if (hFM2Object) {
1725 rc = WinSetObjectData(hFM2Object, (PSZ)s);
1726 }
1727 hFM2Object = WinQueryObject("<FM/2_VTREE>");
1728 if (hFM2Object) {
1729 rc = WinSetObjectData(hFM2Object, (PSZ)s);
1730 }
1731 hFM2Object = WinQueryObject("<FM/2_VDIR>");
1732 if (hFM2Object) {
1733 rc = WinSetObjectData(hFM2Object, (PSZ)s);
1734 }
1735 hFM2Object = WinQueryObject("<FM/2_SEEALL>");
1736 if (hFM2Object) {
1737 rc = WinSetObjectData(hFM2Object, (PSZ)s);
1738 }
1739 hFM2Object = WinQueryObject("<FM/2_DATABAR>");
1740 if (hFM2Object) {
1741 rc = WinSetObjectData(hFM2Object, (PSZ)s);
1742 }
[2]1743 }
[1789]1744 if (rc == SM2_NO || rc == SM2_DONTASK) {
[1459]1745 fDontSuggestAgain = TRUE;
[1865]1746 PrfWriteProfileData(fmprof, FM3Str, "DontSuggestAgain",
1747 &fDontSuggestAgain, sizeof(BOOL));
[1451]1748 }
[1471]1749 } // if suggest
[1522]1750 } // if !fDontSuggestAgain
[2]1751 didonce = TRUE;
[731]1752} // FillTreeCnr
[743]1753
1754
1755/**
1756 * Empty all records from a container and free associated storage and
1757 * Free up field infos
1758 */
1759
1760VOID EmptyCnr(HWND hwnd)
1761{
1762 PFIELDINFO pfi;
1763
[762]1764#if 0 // fixme to be gone or to be configurable
[751]1765 {
1766 int state = _heapchk();
1767 if (state != _HEAPOK)
1768 Runtime_Error(pszSrcFile, __LINE__, "heap corrupted %d", state);
1769 }
1770#endif
1771
[743]1772 // Remove all records
1773 RemoveCnrItems(hwnd, NULL, 0, CMA_FREE);
1774
1775 // Remove field info descriptors
1776 pfi = (PFIELDINFO) WinSendMsg(hwnd, CM_QUERYDETAILFIELDINFO, MPVOID,
1777 MPFROMSHORT(CMA_FIRST));
[745]1778 if (pfi &&
1779 (INT)WinSendMsg(hwnd, CM_REMOVEDETAILFIELDINFO, MPVOID,
1780 MPFROM2SHORT(0, CMA_FREE)) == -1) {
1781 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_REMOVEDETAILFIELDINFO hwnd %x", hwnd);
1782 }
[743]1783}
1784
1785/**
1786 * Free storage associated with container item
1787 */
1788
[751]1789VOID FreeCnrItemData(PCNRITEM pci)
[743]1790{
[1865]1791
1792 // 2015-08-23 SHL FIXME debug
1793 if ((pci->pszSubject && (ULONG)pci->pszSubject < 0x10000) ||
1794 (pci->pszLongName && (ULONG)pci->pszLongName < 0x10000) ||
1795 (pci->pszDisplayName && (ULONG)pci->pszDisplayName < 0x10000) ||
1796 (pci->pszFileName && (ULONG)pci->pszFileName < 0x10000) ||
1797 (pci->pszLongName && (ULONG)pci->pszLongName < 0x10000) ||
1798 (pci->pszFmtFileSize && (ULONG)pci->pszFmtFileSize < 0x10000))
1799 {
1800 Runtime_Error(pszSrcFile, __LINE__, "FreeCnrItemData attempting to free bogus %p", pci);
1801 }
1802
[1308]1803 if (pci->pszSubject) {
1804 if (pci->pszSubject != NullStr)
1805 free(pci->pszSubject);
[1174]1806 pci->pszSubject = NULL; // Catch illegal references
[762]1807 }
[1865]1808
[1308]1809 if (pci->pszLongName) {
1810 if (pci->pszLongName != NullStr)
1811 free(pci->pszLongName);
[1174]1812 pci->pszLongName = NULL; // Catch illegal references
[762]1813 }
[1865]1814
[1154]1815 // Bypass free if pszDisplayName points into pszFileName buffer
[1308]1816 if (pci->pszDisplayName) {
1817 if (pci->pszDisplayName != NullStr) {
1818 if (!pci->pszFileName ||
1819 pci->pszDisplayName < pci->pszFileName ||
1820 pci->pszDisplayName >= pci->pszFileName + _msize(pci->pszFileName))
1821 {
[1865]1822 free(pci->pszDisplayName);
[1308]1823 }
[1154]1824 }
[1308]1825 pci->pszDisplayName = NULL; // Catch illegal references
[1154]1826 }
[1113]1827
[1865]1828#if 1 // 2009-09-26 SHL FIXME debug dup free complaints
[1836]1829 if (!pci->pszFileName)
1830 Runtime_Error(pszSrcFile, __LINE__, "FreeCnrItemData attempting to free %p data twice", pci);
1831 else {
1832 if (pci->pszFileName != NullStr)
[1308]1833 free(pci->pszFileName);
[1836]1834 pci->pszFileName = NULL; // Catch illegal references
1835 }
1836#else
1837 {
[1865]1838 // 2015-08-23 SHL FIXME to work again now that Flesh/Stubby on thread
[1836]1839 #define HIST_COUNT 50
1840 static struct {
1841 PCNRITEM pci;
1842 PSZ pszFileName;
1843 } history[HIST_COUNT];
1844 static volatile UINT iHistNdx;
1845 UINT i;
1846
1847 if (!pci->pszFileName) {
1848 // Looks like pci was already freed
1849 // Try to locate original file name in history buffer
1850 for (i = 0; i < HIST_COUNT && pci != history[i].pci; i++) { } // Scan
1851 if (i < HIST_COUNT) {
1852 Runtime_Error(pszSrcFile, __LINE__, "FreeCnrItemData attempting to free %p data twice, fileName was %.260s",
1853 pci, history[i].pszFileName);
1854 } else {
1855 Runtime_Error(pszSrcFile, __LINE__, "FreeCnrItemData attempting to free %p data twice", pci);
1856 }
[1471]1857 }
[1836]1858 else {
1859 PSZ psz;
1860 PSZ *ppsz;
1861 // Grab a history slot
1862 // This should work well enoungh to prevent MT/SMP conflicts
1863 for (;;) {
1864 i = iHistNdx;
1865 if (++i >= HIST_COUNT)
1866 i = 0;
1867 if (++iHistNdx >= HIST_COUNT)
1868 iHistNdx = 0;
1869 if (i == iHistNdx) break;
1870 }
1871 ppsz = &history[iHistNdx].pszFileName;
1872 psz = *ppsz;
1873 if (psz)
1874 free(psz);
1875 if (pci->pszFileName && pci->pszFileName != NullStr)
1876 *ppsz = strdup(pci->pszFileName);
1877 else
1878 *ppsz = NULL;
1879 history[iHistNdx].pci = pci;
1880 if (pci->pszFileName != NullStr)
1881 free(pci->pszFileName);
1882 pci->pszFileName = NULL; // Catch illegal references and dup free attempts
1883 }
[1471]1884 }
1885
[1865]1886#endif // FIXME debug dup free
[1836]1887
[1308]1888 if (pci->pszLongName) {
1889 if (pci->pszLongName != NullStr)
1890 free(pci->pszLongName);
[1299]1891 pci->pszLongName = NULL; // Catch illegal references
1892 }
[1174]1893
[1308]1894 if (pci->pszFmtFileSize) {
1895 if (pci->pszFmtFileSize != NullStr)
1896 free(pci->pszFmtFileSize);
[1174]1897 pci->pszFmtFileSize = NULL; // Catch illegal references
[857]1898 }
[743]1899}
1900
1901/**
[762]1902 * Free single container item and associated storage
[743]1903 */
1904
[762]1905VOID FreeCnrItem(HWND hwnd, PCNRITEM pci)
[743]1906{
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;
[1865]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;
[1871]1966 PCNRITEM pciPrevious;
[1564]1967 ITIMER_DESC itdSleep = { 0 }; // 30 May 11 GKY
[751]1968
[762]1969 if ((usCnt && !pciFirst) || (!usCnt && pciFirst)) {
1970 Runtime_Error(pszSrcFile, __LINE__, "pciFirst %p usCnt %u mismatch", pciFirst, usCnt);
[751]1971 remaining = -1;
[762]1972 }
1973 else {
1974 // Free our buffers if free requested
1975 if (usFlags & CMA_FREE) {
1976 if (pciFirst)
1977 pci = pciFirst;
1978 else {
[743]1979 pci = (PCNRITEM)WinSendMsg(hwnd, CM_QUERYRECORD, MPVOID,
[744]1980 MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
[762]1981 if ((INT)pci == -1) {
[744]1982 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_QUERYRECORD");
[751]1983 remaining = -1;
[762]1984 pci = NULL;
1985 }
1986 }
[1564]1987 InitITimer(&itdSleep, 500);
[762]1988 while (pci) {
[1871]1989 FreeCnrItemData(pci);
1990 if (usCnt > 0)
1991 pciPrevious = pci;
1992 pci = (PCNRITEM)pci->rc.preccNextRecord;
[1836]1993 if (!pci)
[1871]1994 break;
1995 if (usCnt > 0 && pciPrevious && pciPrevious->pciPrevious) {
1996 pciPrevious->pciPrevious->rc.preccNextRecord = (MINIRECORDCORE *) pci;
1997 pci->pciPrevious = pciPrevious->pciPrevious;
1998 pciPrevious->pciPrevious = NULL;
1999 pciPrevious->rc.preccNextRecord = NULL;
2000 }
[1865]2001 if (remaining && --remaining == 0)
2002 break;
[1877]2003 if (!bIdlePrioritySet) {
[1865]2004 bIdlePrioritySet = !IdleIfNeeded(&itdSleep, 30);
2005 }
[1759]2006 } // while
[1836]2007 if (bIdlePrioritySet)
[1865]2008 priority_normal();
[1836]2009
[1570]2010 DosPostEventSem(CompactSem);
[743]2011 }
2012 }
[762]2013 if (remaining != - 1) {
2014 remaining = (INT)WinSendMsg(hwnd, CM_REMOVERECORD, MPFROMP(&pciFirst), MPFROM2SHORT(usCnt, usFlags));
[751]2015 if (remaining == -1) {
[762]2016 Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_REMOVERECORD hwnd %x pci %p cnt %u", hwnd, pciFirst, usCnt);
[743]2017 }
2018 }
[1836]2019
[751]2020 return remaining;
[743]2021}
2022
[783]2023#pragma alloc_text(FILLDIR,FillInRecordFromFFB,FillInRecordFromFSA,IDFile)
[1856]2024#pragma alloc_text(FILLDIR1,ProcessDirectory,FillDirCnr,FillTreeCnr,FileAttrToString)
[783]2025#pragma alloc_text(EMPTYCNR,EmptyCnr,FreeCnrItemData,FreeCnrItem,FreeCnrItemList,RemoveCnrItems)
2026
Note: See TracBrowser for help on using the repository browser.