source: trunk/dll/filldir.c@ 1444

Last change on this file since 1444 was 1444, checked in by Gregg Young, 16 years ago

Rework of drivebar to rescan all drives and refresh media buttons and menu items grey out inappropriate menu items. Streamline Tree scan code and use semaphores to serialize access. Add NOEASUPPORT and LOCALHD driveflag; .LONGNAME usage fixes; (Tickets 377-386)

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