source: trunk/dll/filldir.c@ 1643

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

Removed UnFlesh call from StubbyScanThread; This seems to significantly cut load times.

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