source: trunk/dll/filldir.c@ 1831

Last change on this file since 1831 was 1814, checked in by John Small, 10 years ago

Ticket 514: Double free error fix (which also fixes a memory leak)

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