source: trunk/dll/filldir.c@ 1867

Last change on this file since 1867 was 1865, checked in by Steven Levine, 10 years ago

Correct WaitFleshWorkListEmpty typo that could corrupt heap
Protect some read-only strings from overwriting

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