source: trunk/dll/filldir.c@ 1502

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

Changes to get FM2 to compile with the latest watcom 1.9 beta (mostly type casts of CHAR CONSTANT * to CHAR *). Changes to get the environment settings working everywhere again (broken by the change that moved commands to the INI); Added an environment size variable (set to 2048 which was the largest I found hard coded). Still need to find everywhere the environment size is set and use this variable.

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