source: trunk/dll/filldir.c@ 1308

Last change on this file since 1308 was 1308, checked in by Steven Levine, 17 years ago

FreeCnrItemData: optimize and always NULL pointers
StubbyScanThread: restore else - we want all drives listed
FreeCnrItemData: report double free with Runtime_Error

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