source: trunk/dll/filldir.c@ 1644

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

Fix the code that assigns icons. Earlier change to support 4 letter extensions would fail to recognize some 3 letter extensions.

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