source: trunk/dll/filldir.c@ 1459

Last change on this file since 1459 was 1459, checked in by Steven Levine, 16 years ago

Show rescan progress while filling container, ticket #291

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