source: trunk/dll/filldir.c@ 1570

Last change on this file since 1570 was 1570, checked in by Gregg Young, 14 years ago

Added IdleIfNeeded to place load and free loops to idle priority when dealing with large numbers of items. Used SleepIfNeeded more places for a similar purpose.

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