source: trunk/dll/flesh.c@ 1856

Last change on this file since 1856 was 1856, checked in by Steven Levine, 10 years ago

Rework Flesh/Stubby etc. to avoid running on thread 1
Should be ready for release after spurious traps resolved
DbgMsg calls retained - delete/disable before release

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.1 KB
RevLine 
[145]1
2/***********************************************************************
3
4 $Id: flesh.c 1856 2015-08-18 17:12:52Z stevenhl $
5
[1856]6 Drive tree container management
[145]7
8 Copyright (c) 1993-98 M. Kimes
[1856]9 Copyright (c) 2005-2015 Steven H. Levine
[145]10
11 24 May 05 SHL Rework Win_Error usage
[166]12 25 May 05 SHL Rework for ProcessDirectory
[284]13 28 May 05 SHL Clean while reading code
14 24 Oct 05 SHL Delete obsolete code
[340]15 22 Jul 06 SHL Check more run time errors
[515]16 19 Oct 06 SHL Stubby - correct . and .. detect
[574]17 22 Mar 07 GKY Use QWL_USER
[751]18 01 Aug 07 SHL Sync with CNRITEM mods
[775]19 06 Aug 07 GKY Reduce DosSleep times (ticket 148)
[793]20 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
[985]21 29 Feb 08 GKY Use xfree where appropriate
[1299]22 24 Nov 08 GKY remove redundant code and minor speed up of Stubby
[1358]23 25 Dec 08 GKY Add ProcessDirectoryThread to allow optional recursive drive scan at startup.
24 25 Dec 08 GKY Add DRIVE_RSCANNED flag to monitor for the first recursive drive scan per session
[1471]25 to prevent duplicate directory names in tree following a copy before initial scan.
[1400]26 08 Mar 09 GKY Additional strings move to PCSZs in init.c
[1482]27 13 Dec 09 GKY Fixed separate paramenters. Please note that appname should be used in
[1856]28 profile calls for user settings that work and are setable in more than one
29 miniapp; FM3Str should be used for setting only relavent to FM/2 or that
30 aren't user settable; realappname should be used for setting applicable to
31 one or more miniapp but not to FM/2
[1662]32 17 Jan 10 GKY Changes to get working with Watcom 1.9 Beta (1/16/10). Mostly cast CHAR CONSTANT * as CHAR *.
33 04 Aug 12 GKY Fix trap on close during drive scan
[1837]34 02 Aug 15 GKY Fix trap in Stubby
[1856]35 03 Aug 15 SHL Document Stubby a bit better
36 07 Aug 15 SHL Rework to use AddFleshWorkRequest rather than direct calls to Stubby/Flesh/Unflesh
[145]37
38***********************************************************************/
39
[907]40#include <stdlib.h>
41#include <string.h>
42#include <ctype.h>
[1831]43//#include <malloc.h>
[907]44
[2]45#define INCL_DOS
46#define INCL_DOSERRORS
47#define INCL_WIN
[907]48#define INCL_LONGLONG // dircnrs.h
[2]49
[1177]50#include "fm3dll.h"
[1207]51#include "draglist.h" // Data declaration(s)
52#include "notebook.h" // Data declaration(s)
53#include "info.h" // Data declaration(s)
54#include "init.h" // Data declaration(s)
55#include "mainwnd.h" // Data declaration(s)
[907]56#include "fm3str.h"
57#include "filldir.h" // FileAttrToString...
58#include "errutil.h" // Dos_Error...
59#include "strutil.h" // GetPString
[1155]60#include "flesh.h"
61#include "valid.h" // IsValidDir
[1856]62#include "misc.h" // LoadLibPath GetTidForThread
[1177]63#include "findrec.h" // FindCnrRecord
64#include "notify.h" // Notify
65#include "wrappers.h" // xfree
[1354]66#include "excputil.h" // xbeginthread
[1856]67#include "listutil.h" // List...
68#include "common.h" // IncrThreadUsage DecrThreadUsage
69
[1831]70#if 0
71#define __PMPRINTF__
72#include "PMPRINTF.H"
73#endif
[2]74
[1207]75// Data definitions
[2]76#pragma data_seg(DATA1)
[340]77
78static PSZ pszSrcFile = __FILE__;
79
[1856]80
81static INT tidFleshWorkListThread = -1; // 2015-08-08 SHL
82
83static CHAR chFleshFocusDrive; // 2015-08-16 SHL A..Z or 0
84
85
86BOOL fNoFleshDbgMsg; // 2015-08-09 SHL FIXME to be gone
87
[1207]88#pragma data_seg(GLOBAL1)
89ULONG NoBrokenNotify;
90BOOL fFilesInTree;
91
[1856]92BOOL Flesh(HWND hwndCnr, PCNRITEM pciParent);
93
94BOOL Stubby(HWND hwndCnr, PCNRITEM pciParent);
95BOOL FleshEnv(HWND hwndCnr, PCNRITEM pciParent);
96BOOL UnFlesh(HWND hwndCnr, PCNRITEM pciParent);
97
98/**
99 * Insert CNRITEMs for members of PATH-like environment variable
100 * @param hwndCnr is the container to be populated
101 * @param pciParent is CNRITEM defining PATH-like environment variable
102 * @return TRUE if OK, FALSE is error detected
103 */
104
[551]105BOOL FleshEnv(HWND hwndCnr, PCNRITEM pciParent)
[175]106{
[551]107 PCNRITEM pciL;
[2]108 DIRCNRDATA *dcd;
[551]109 CHAR path[CCHMAXPATH + 12],
110 fullpath[CCHMAXPATH + 12], *env, *p, *pp, *var = NULL;
[2]111
[551]112 if (!pciParent || (INT) pciParent == -1 || !hwndCnr)
[2]113 return FALSE;
[1856]114
[574]115 dcd = (DIRCNRDATA *) WinQueryWindowPtr(hwndCnr, QWL_USER);
[551]116 if (!dcd)
[2]117 return FALSE;
118
[730]119 strcpy(path, pciParent->pszFileName + 1);
[551]120 if (stricmp(path, GetPString(IDS_ENVVARSTEXT) + 1))
121 UnFlesh(hwndCnr, pciParent);
122 if (*path) {
[2]123 path[strlen(path) - 1] = 0;
[1400]124 if (!stricmp(path, PCSZ_LIBPATH)) {
[551]125 var = xmalloc(65536, pszSrcFile, __LINE__);
126 if (var)
127 LoadLibPath(var, 65536);
[2]128 env = var;
129 }
130 else
131 env = getenv(path);
[551]132 if (env && *env) {
[2]133 p = env;
[551]134 while (*p) {
135 pp = path;
136 while (*p == ';')
137 p++;
138 while (*p && *p != ';') {
139 *pp = *p;
140 p++;
141 pp++;
142 }
143 *pp = 0;
144 if (*path &&
145 strcmp(path, ".") &&
146 strcmp(path, ".\\") &&
147 strcmp(path, "..") &&
148 strcmp(path, "..\\") &&
149 strncmp(path, ".\\", 2) && strncmp(path, "..\\", 3)) {
150 if (!DosQueryPathInfo(path,
151 FIL_QUERYFULLNAME,
152 fullpath,
153 sizeof(fullpath)) && IsValidDir(fullpath)) {
154 pciL = FindCnrRecord(hwndCnr,
155 fullpath, pciParent, FALSE, FALSE, FALSE);
156 if (pciL) {
157 while (pciL && pciL != (PCNRITEM) - 1 && pciL != pciParent)
158 pciL = WinSendMsg(hwndCnr,
159 CM_QUERYRECORD,
160 MPFROMP(pciL),
161 MPFROM2SHORT(CMA_PARENT, CMA_ITEMORDER));
162 }
163 if (!pciL) {
[2]164
[551]165 RECORDINSERT ri;
[2]166
[551]167 pciL = WinSendMsg(hwndCnr,
168 CM_ALLOCRECORD,
[751]169 MPFROMLONG(EXTRA_RECORD_BYTES),
[551]170 MPFROMLONG(1));
171 if (pciL) {
[730]172 pciL->pszFileName = xstrdup(fullpath, pszSrcFile, __LINE__);
[751]173 pciL->rc.pszIcon = pciL->pszFileName;
[551]174 if (!fNoIconsDirs &&
175 (!isalpha(*fullpath) ||
176 !(driveflags[toupper(*fullpath) - 'A'] &
177 DRIVE_NOLOADICONS)))
178 pciL->rc.hptrIcon = WinLoadFileIcon(fullpath, FALSE);
179 if (!pciL->rc.hptrIcon)
180 pciL->rc.hptrIcon = hptrDir;
181 pciL->attrFile = FILE_DIRECTORY;
[751]182 pciL->pszDispAttr = FileAttrToString(pciL->attrFile);
[551]183 memset(&ri, 0, sizeof(ri));
184 ri.cb = sizeof(ri);
185 ri.pRecordOrder = (PRECORDCORE) CMA_END;
186 ri.pRecordParent = (PRECORDCORE) pciParent;
187 ri.zOrder = (ULONG) CMA_TOP;
188 ri.cRecordsInsert = 1;
189 ri.fInvalidateRecord = FALSE;
190 if (!WinSendMsg(hwndCnr,
191 CM_INSERTRECORD, MPFROMP(pciL), MPFROMP(&ri)))
[751]192 FreeCnrItem(hwndCnr, pciL);
[551]193 }
194 }
195 }
196 }
[2]197 }
198 }
[1009]199 xfree(var, pszSrcFile, __LINE__);
[551]200 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
201 CM_QUERYRECORD,
202 MPFROMP(pciParent),
203 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
204 while (pciL && (INT) pciL != -1) {
[2]205 pciL->flags |= (RECFLAGS_NODRAG | RECFLAGS_UNDERENV);
206 WinSendMsg(hwndCnr,
[551]207 CM_INVALIDATERECORD, MPFROMP(&pciL), MPFROM2SHORT(1, 0));
[2]208 pciL = WinSendMsg(hwndCnr,
[551]209 CM_QUERYRECORD,
210 MPFROMP(pciL), MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
[2]211 }
212 }
213 return TRUE;
214}
215
[1856]216/**
217 * Insert CNRITEMs for all children of pciParent
218 * @param hwnCnr is container to receive CNRITEMs
219 * @param pciParent is CNRITEM to have children inserted
220 * @return TRUE if OK, FALSE is error detected
221 */
222
[551]223BOOL Flesh(HWND hwndCnr, PCNRITEM pciParent)
[166]224{
[551]225 PCNRITEM pciL;
[2]226 DIRCNRDATA *dcd;
[1856]227 BOOL includefiles;
[2]228
[1856]229 if (!pciParent || (INT)pciParent == -1 || !hwndCnr)
[2]230 return FALSE;
[1856]231
232 // 2015-08-13 SHL FIXME to optimize
233 if (fAmClosing) {
234 // Can jiggle - see MainWndProc WM_CLOSE
235 DosSleep(100);
236 if (fAmClosing)
237 return FALSE; // time to die
238 }
239
240 // 2015-08-03 SHL FIXME debug
241 if (!fNoFleshDbgMsg) {
242 DbgMsg(pszSrcFile, __LINE__, "Flesh %s pciParent %p pszFileName %p",
243 pciParent && (INT)pciParent != -1 && pciParent->pszFileName ?
244 pciParent->pszFileName : "(null)",
245 pciParent,
246 pciParent && (INT)pciParent != -1 ? pciParent->pszFileName : (PVOID)-1); // 2015-08-03 SHL FIXME debug
247 }
248
249 pciL = (PCNRITEM)WinSendMsg(hwndCnr,
250 CM_QUERYRECORD,
251 MPFROMP(pciParent),
252 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
253
254 // 2015-08-06 SHL allow pciL -1
255 if (!pciL || (INT)pciL == -1 || !*pciL->pszFileName) {
256
257 // No children or filename null
258 // 2015-08-06 SHL FIXME to know how this can happen
259 if (pciL && (INT)pciL != -1) {
260 // 2015-08-06 SHL FIXME to loop and timeout if Stubby threads working
261 if (!fNoFleshDbgMsg)
262 DbgMsg(pszSrcFile, __LINE__, "Flesh RemoveCnrItems() pciL %p", pciL); // 2015-08-04 SHL FIXME debug
[1651]263 RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
[1856]264 }
265
[1651]266 dcd = INSTDATA(hwndCnr);
267 if (dcd && dcd->size != sizeof(DIRCNRDATA))
268 dcd = NULL;
[1856]269
270 // DbgMsg(pszSrcFile, __LINE__, "Flesh %s dcd %p called by %s#%u", pciParent->pszFileName, dcd, pszSrcFile_, uSrcLineNo_); // 2015-08-03 SHL FIXME debug
271
272 // 2015-08-06 SHL FIXME to not trap here
273 includefiles =
274 driveflags[toupper(*pciParent->pszFileName) - 'A'] & DRIVE_INCLUDEFILES ?
275 TRUE : fFilesInTree;
276
[1662]277 ProcessDirectory(hwndCnr,
[1856]278 pciParent,
279 pciParent->pszFileName,
280 includefiles, // filestoo
281 TRUE, // recurse
282 TRUE, // partial
283 NULL, // stop flag
284 dcd,
285 NULL, // total files
286 NULL); // total bytes
[1662]287 if (pciParent && pciParent->pszFileName && !(driveflags[toupper(*pciParent->pszFileName) - 'A'] & DRIVE_RSCANNED))
288 driveflags[toupper(*pciParent->pszFileName) - 'A'] |= DRIVE_RSCANNED;
[1655]289 return TRUE;
[1651]290 }
[1856]291
[1655]292 return FALSE;
[2]293}
294
[1856]295// 2015-08-06 SHL FIXME to be VOID
296
[551]297BOOL UnFlesh(HWND hwndCnr, PCNRITEM pciParent)
[175]298{
[1856]299 BOOL removed = FALSE;
[2]300 PCNRITEM pciL;
301
[175]302 if (!pciParent || !hwndCnr)
[2]303 return FALSE;
[1856]304
305 if (!fNoFleshDbgMsg)
306 DbgMsg(pszSrcFile, __LINE__, "UnFlesh pciParent %p pszFileName %s", pciParent, pciParent->pszFileName ? pciParent->pszFileName : "(null)"); // 2015-08-03 SHL FIXME debug
307
[551]308 for (;;) {
309 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
310 CM_QUERYRECORD,
311 MPFROMP(pciParent),
312 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
[1856]313 if (!pciL || (INT)pciL == -1)
314 break; // Done
315
316 if (!fNoFleshDbgMsg)
317 DbgMsg(pszSrcFile, __LINE__, "UnFlesh RemoveCnrItems() pciL %p %s", pciL, pciL->pszFileName ? pciL->pszFileName : "(null)"); // 2015-08-03 SHL FIXME debug
318 RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
319 removed = TRUE;
320 } // for
321
322 if (removed) {
[2]323 WinSendMsg(hwndCnr,
[551]324 CM_INVALIDATERECORD,
325 MPFROMP(&pciParent),
326 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
[175]327 }
[1856]328 return removed;
[2]329}
330
[1482]331#define DDEPTH 64
[2]332
[1471]333/**
[1856]334 * Insert CNRITEM for 1st subdirectory [or file] of pciParent
335 * @param hwdCnr is container to be filled
336 * @param pciParent is CNRITEM to receive child record
337 * @return TRUE if record inserted, else FALSE
338 * Ensures that expand/collapse button displays if directory has children
339 * Secondary purpose is to detect broken LANs and inaccesible mapped drives
[1471]340 */
341
[551]342BOOL Stubby(HWND hwndCnr, PCNRITEM pciParent)
[175]343{
[1409]344 /**
[2]345 * this code is full of workarounds for screwed up LANs.
346 * let's hope all the current LAN programmers fall into
347 * a black hole and make way for people who can get it right...
348 */
349
[1471]350 BOOL ok = FALSE;
[847]351 FILEFINDBUF3 ffb[DDEPTH];
352 PFILEFINDBUF3 pffb;
[551]353 HDIR hDir = HDIR_CREATE;
[1856]354 ULONG nm, ulM = 1, total = 0, fl;
[551]355 CHAR str[CCHMAXPATH];
356 register INT len;
357 APIRET rc, prc;
[1856]358 BOOL isadir = FALSE, isremote, includefiles;
[1482]359 ULONG ddepth = DDEPTH;
[1299]360 ULONG drvNum;
361 ULONG flags;
[551]362 static BOOL brokenlan = FALSE, isbroken = FALSE;
[2]363
[1837]364 if (!pciParent || (INT) pciParent == -1 || !*pciParent->pszFileName
[1832]365 || pciParent->pszFileName == NullStr || !hwndCnr)
[2]366 return FALSE;
[1856]367
368 if (!fNoFleshDbgMsg)
369 DbgMsg(pszSrcFile, __LINE__, "Stubby pciParent %p pszFileName %s", pciParent, pciParent->pszFileName); // 2015-08-03 SHL FIXME debug
370
371 // Build wildcard
[730]372 len = strlen(pciParent->pszFileName);
373 memcpy(str, pciParent->pszFileName, len + 1);
[551]374 if (str[len - 1] != '\\')
[2]375 str[len++] = '\\';
376 str[len++] = '*';
377 str[len] = 0;
378
[551]379 if (!isalpha(*str) || str[1] != ':' || str[2] != '\\')
[2]380 MakeFullName(str);
381
[1299]382 drvNum = toupper(*pciParent->pszFileName) - 'A';
383 flags = driveflags[drvNum];
[551]384 if (!isalpha(*str) ||
385 str[1] != ':' ||
[1299]386 str[2] != '\\' || ((flags & DRIVE_IGNORE)))
[1856]387 return FALSE; // Not a directory or ignore requested
[2]388
[1856]389 includefiles = flags & DRIVE_INCLUDEFILES ? TRUE : fFilesInTree;
[2]390
[1856]391 isremote = flags & DRIVE_REMOTE ? TRUE : FALSE;
[2]392
[551]393 if (isremote) {
394 if (fRemoteBug) {
395 if (brokenlan) {
396 ddepth = (ULONG) - 1;
397 ddepth--;
[2]398 }
[761]399 ulM = 1;
[2]400 }
401 }
[551]402 else if (isbroken)
[2]403 ddepth = 14;
404
[1482]405 if (!fRemoteBug)
[1856]406 ulM = ddepth <= DDEPTH ? ddepth : 1;
[2]407
408 nm = ulM;
409
410 DosError(FERR_DISABLEHARDERR);
[1856]411
412 fl = includefiles ? FILE_DIRECTORY : MUST_HAVE_DIRECTORY;
413
[847]414 rc = DosFindFirst(str,
415 &hDir,
416 FILE_NORMAL | fl |
417 FILE_READONLY | FILE_ARCHIVED |
418 FILE_SYSTEM | FILE_HIDDEN,
419 &ffb, ulM * sizeof(FILEFINDBUF3), &nm, FIL_STANDARD);
[761]420 if (ulM == 1 && !rc) {
[1856]421 // Loop looking for 1st directory (or file)
[2]422 do {
423 pffb = &ffb[0];
[551]424 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY) && !brokenlan) {
[1856]425 // Find returned file when only directories requested
[551]426 brokenlan = TRUE;
[847]427 ddepth = (ULONG) - 1;
[551]428 ddepth--;
429 if (!NoBrokenNotify) {
430 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
431 HWND_DESKTOP,
432 GetPString(IDS_LANERRORTITLETEXT),
433 GetPString(IDS_LANERRORTEXT));
434 if (prc == MBID_NO) {
435 saymsg(MB_ENTER,
436 HWND_DESKTOP,
437 GetPString(IDS_LANERROR2TITLETEXT),
438 GetPString(IDS_LANERROR2TEXT));
[847]439 NoBrokenNotify = 255;
[1505]440 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]441 &NoBrokenNotify, sizeof(ULONG));
442 }
443 }
444 else {
445 NoBrokenNotify--;
[1505]446 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]447 &NoBrokenNotify, sizeof(ULONG));
448 }
[2]449 }
[1856]450
[515]451 if (*pffb->achName &&
[551]452 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
453 (pffb->achName[0] != '.' ||
[515]454 (pffb->achName[1] &&
[551]455 (pffb->achName[1] != '.' || pffb->achName[2])))) {
[1856]456 // Got directory other than . or .. (or a file)
[551]457 DosFindClose(hDir);
458 isadir = TRUE;
459 goto Interruptus;
[2]460 }
[761]461 nm = 1;
[2]462 DosError(FERR_DISABLEHARDERR);
[1856]463 } while (++total < ddepth && !(rc = (DosFindNext(hDir,
464 &ffb,
465 sizeof(FILEFINDBUF3),
466 &nm))));
467 DosFindClose(hDir);
468
[730]469 if (toupper(*pciParent->pszFileName) > 'B' &&
[751]470 (*(pciParent->pszFileName + 1)) == ':' &&
[730]471 (*(pciParent->pszFileName + 2)) == '\\' && !(*(pciParent->pszFileName + 3))) {
[2]472
[1856]473 // Searching root of hard or remote drive and find reported error
[2]474 CHAR s[132];
475 sprintf(s,
[551]476 GetPString(IDS_NOSUBDIRSTEXT),
[730]477 total, toupper(*pciParent->pszFileName));
[551]478 if (rc && rc != ERROR_NO_MORE_FILES)
479 sprintf(&s[strlen(s)], GetPString(IDS_SEARCHERRORTEXT), rc, str);
[847]480 else if (ddepth < 16)
[551]481 brokenlan = TRUE;
[2]482 Notify(s);
483 }
[1856]484 goto None; // Done
[2]485 }
[1856]486
[551]487 if (!rc) {
[2]488 DosFindClose(hDir);
[551]489 if (nm) {
[1353]490 PBYTE fb = (PBYTE)&ffb[0];
[551]491 for (len = 0; len < nm; len++) {
[847]492 pffb = (PFILEFINDBUF3) fb;
[551]493 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY)) {
[1856]494 // Got file(s), but did not ask for files
[551]495 if (!isbroken) {
496 isbroken = TRUE;
497 if (!NoBrokenNotify) {
498 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
499 HWND_DESKTOP,
500 GetPString(IDS_FSDERRORTITLETEXT),
501 GetPString(IDS_FSDERRORTEXT),
[1471]502 isremote ? GetPString(IDS_REMOTETEXT) :
503 GetPString(IDS_LOCALTEXT),
504 *str);
[551]505 if (prc == MBID_NO) {
506 saymsg(MB_ENTER,
507 HWND_DESKTOP,
508 GetPString(IDS_FSDERROR2TITLETEXT),
509 GetPString(IDS_FSDERROR2TEXT));
[847]510 NoBrokenNotify = 255;
[1505]511 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]512 &NoBrokenNotify, sizeof(ULONG));
513 }
514 }
515 else {
516 NoBrokenNotify--;
[1505]517 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]518 &NoBrokenNotify, sizeof(ULONG));
519 }
[1856]520 } // if !broken
521 } // if !directory
522
[551]523 if (*pffb->achName &&
524 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
[1856]525 ((pffb->achName[0] && pffb->achName[0] != '.') ||
526 (pffb->achName[1] &&
527 (pffb->achName[1] != '.' || pffb->achName[2]))))
528 {
529 // Got directory other than . or .. (or a file)
[551]530 isadir = TRUE;
531 break;
532 }
533 fb += pffb->oNextEntryOffset;
[1353]534 } // for
[2]535
[551]536 Interruptus:
[2]537
[551]538 if (isadir) {
[2]539
[1856]540 // Insert CNRITEM for selected directory (or file)
[1471]541 PCNRITEM pci;
[2]542
[1471]543 if (WinIsWindow((HAB)0, hwndCnr)) {
544 pci = WinSendMsg(hwndCnr,
545 CM_ALLOCRECORD,
546 MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(1));
547 if (!pci) {
548 Win_Error(hwndCnr, HWND_DESKTOP, __FILE__, __LINE__,
549 GetPString(IDS_RECORDALLOCFAILEDTEXT));
550 }
551 else {
552 RECORDINSERT ri;
553 pci->pszFileName = NullStr;
554 pci->pszDisplayName = pci->pszFileName;
555 pci->rc.pszIcon = pci->pszDisplayName;
556 memset(&ri, 0, sizeof(RECORDINSERT));
557 ri.cb = sizeof(RECORDINSERT);
558 ri.pRecordOrder = (PRECORDCORE) CMA_END;
559 ri.pRecordParent = (PRECORDCORE) pciParent;
560 ri.zOrder = (ULONG) CMA_TOP;
561 ri.cRecordsInsert = 1;
[1856]562 ri.fInvalidateRecord = TRUE;
563 // DbgMsg(pszSrcFile, __LINE__, "Stubby CM_INSERTRECORD %p \"%s\" %.255s", pci, pci->pszFileName, pffb->achName); // 2015-08-03 SHL FIXME debug
[1471]564 if (!WinSendMsg(hwndCnr,
565 CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
[1856]566 // Assume busy and try again
[1471]567 DosSleep(50); //05 Aug 07 GKY 100
[1856]568 WinSetFocus(HWND_DESKTOP, hwndCnr);
569 if (WinIsWindow((HAB)0, hwndCnr)) {
570 if (!fNoFleshDbgMsg)
571 DbgMsg(pszSrcFile, __LINE__, "Stubby CM_INSERTRECORD pci %p pszFileName %s", pci, pci->pszFileName); // 2015-08-03 SHL FIXME debug
[1471]572 if (!WinSendMsg(hwndCnr,
573 CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
574 Win_Error(hwndCnr, HWND_DESKTOP, __FILE__, __LINE__,
575 GetPString(IDS_RECORDINSERTFAILEDTEXT));
576 FreeCnrItem(hwndCnr, pci);
577 }
578 else
579 ok = TRUE;
580 }
581 }
582 else
[1856]583 ok = TRUE;
[1471]584 }
585 }
[1856]586 } // if isadir
[551]587 else if (toupper(*str) > 'B' && str[1] == ':' && str[2] == '\\' &&
588 !str[3]) {
[2]589
[1856]590 // Is root and no subdirectories
[551]591 CHAR s[162];
592 sprintf(s,
593 GetPString(IDS_NOSUBDIRS2TEXT),
594 nm,
[730]595 toupper(*pciParent->pszFileName),
[1856]596 isremote ? GetPString(IDS_NOSUBDIRS3TEXT) : NullStr);
[551]597 Notify(s);
[2]598 }
599 }
600 }
[551]601 else if (toupper(*str) > 'B' && rc != ERROR_NO_MORE_FILES) {
[1856]602 // Find for remote or hard drive failed with error
[2]603 CHAR s[CCHMAXPATH + 80];
[551]604 sprintf(s, GetPString(IDS_SEARCHERRORTEXT), rc, str);
[2]605 Notify(s);
606 }
607
608None:
609
610 DosError(FERR_DISABLEHARDERR);
[1471]611 return ok;
[1856]612} // Stubby
613
614// Stubby/Flesh/Unflesh work list item
615
616typedef struct {
617 LIST2 list;
618 HWND hwndCnr;
619 PCNRITEM pci;
620 FLESHWORKACTION action;
621} FLESHWORKITEM;
622typedef FLESHWORKITEM *PFLESHWORKITEM;
623
624// Stubby/Flesh/Unflesh work list
625LIST2 FleshWorkList;
626
627HMTX hmtxFleshWork;
628HEV hevFleshWorkListChanged;
629
630/**
631 * Check pci matches
632 */
633
634BOOL WorkListItemMatches(PLIST2 item, PVOID data)
635{
636 return ((PFLESHWORKITEM)data)->pci == ((PFLESHWORKITEM)item)->pci;
[2]637}
[793]638
[1856]639/**
640 * Delete stale items from flesh queue
641 */
642
643VOID DeleteStaleFleshWorkListItems(PCNRITEM pci)
644{
645 FLESHWORKITEM match;
646 PLIST2 item;
647
648 match.pci = pci;
649
650 for (;;) {
651 item = List2Search(&FleshWorkList, WorkListItemMatches, &match);
652 if (!item)
653 break;
654 DbgMsg(pszSrcFile, __LINE__, "DeleteStaleFleshWorkListItems deleting %p %s", pci, pci->pszFileName ? pci->pszFileName : "(null)"); // 2015-08-03 SHL FIXME debug
655 List2Delete(&FleshWorkList, item);
656 xfree(item, pszSrcFile, __LINE__);
657 }
658}
659
660/**
661 * Add item to flesh work list
662 * eUnFlesh requests get special handling
663 * eFlesh etc. items for the same CNRITEM are considered stale and are
664 * deleted because eUnFlesh will free the CNRITEM associated with the item
665 * before the work list item is processed
666 */
667
668#if 0 // 2015-08-03 SHL FIXME debug
669BOOL AddFleshWorkRequest(HWND hwndCnr, PCNRITEM pci, FLESHWORKACTION action)
670#else
671BOOL AddFleshWorkRequestDbg(HWND hwndCnr, PCNRITEM pci, FLESHWORKACTION action, PCSZ pszSrcFile_, UINT uSrcLineNo)
672#endif
673{
674 APIRET rc;
675
676 PFLESHWORKITEM item = xmallocz(sizeof(FLESHWORKITEM), pszSrcFile, __LINE__);
677 item->hwndCnr = hwndCnr;
678 item->pci = pci;
679 item->action= action;
680
681 if (fAmClosing) {
682 // Can jiggle - see MainWndProc WM_CLOSE
683 DosSleep(100);
684 if (fAmClosing)
685 return FALSE;
686 }
687
688 // 2015-08-03 SHL FIXME debug
689 {
690#if 0 // 2015-08-13 SHL FIXME to be gone
691 static PSZ itemNames[] = {
692 "eStubby", "eFlesh", "eFleshEnv", "eUnFlesh"
693 };
694
695# ifdef AddFleshWorkRequest
696 if (!pci || (INT)pci == -1) {
697 Runtime_Error(pszSrcFile, __LINE__, "AddFleshWorkRequest called with action %s pci %p by %s:%u",
698 itemNames[item->action],
699 pci,
700 pszSrcFile_, uSrcLineNo); // 2015-08-03 SHL FIXME debug
701 }
702 else if (!pci->pszFileName) {
703 Runtime_Error(pszSrcFile, __LINE__, "AddFleshWorkRequest call with action %s pci %p pszFileName (null) by %s:%u",
704 itemNames[item->action],
705 pci,
706 pszSrcFile_, uSrcLineNo); // 2015-08-03 SHL FIXME debug
707 }
708 else if (!fNoFleshDbgMsg) {
709 DbgMsg(pszSrcFile, __LINE__, "AddFleshWorkRequest called with action %s pci %p pszFileName %s by %s:%u",
710 itemNames[item->action],
711 pci,
712 pci->pszFileName,
713 pszSrcFile_, uSrcLineNo); // 2015-08-03 SHL FIXME debug
714 }
715#else
716 if (!pci || (INT)pci == -1) {
717 Runtime_Error(pszSrcFile, __LINE__, "AddFleshWorkRequest call with action %s pci %p",
718 itemNames[item->action],
719 pci); // 2015-08-03 SHL FIXME debug
720 }
721 else if (!pci->pszFileName) {
722 Runtime_Error(pszSrcFile, __LINE__, "AddFleshWorkRequest called with action %s pci %p pszFileName (null)",
723 itemNames[item->action],
724 pci); // 2015-08-03 SHL FIXME debug
725 }
726 else if (!fNoFleshDbgMsg) {
727 DbgMsg(pszSrcFile, __LINE__, "AddFleshWorkRequest action %s pci %p pszFileName %s",
728 itemNames[item->action],
729 pci,
730 pci->pszFileName); // 2015-08-03 SHL FIXME debug
731 }
732#endif
733#endif
734 }
735
736 rc = DosRequestMutexSem(hmtxFleshWork, SEM_INDEFINITE_WAIT);
737 if (rc)
738 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__, "DosRequestMutexSem");
739
740 // 2015-08-13 SHL FIXME to be done
741 // Delete stale requests
742 if (item->action == eUnFlesh) {
743 DeleteStaleFleshWorkListItems(pci);
744 }
745
746 List2Append(&FleshWorkList, (PLIST2)item);
747
748 rc = DosReleaseMutexSem(hmtxFleshWork);
749 if (rc)
750 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__, "DosReleaseMutexSem");
751
752 rc = DosPostEventSem(hevFleshWorkListChanged);
753 if (rc && rc != ERROR_ALREADY_POSTED)
754 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__, "DosPostEventSem");
755
756 return TRUE;
757}
758
759/**
760 * Return TRUE if work list empty
761 * Advisory only
762 */
763
764BOOL IsFleshWorkListEmpty()
765{
766 return FleshWorkList.next == NULL;
767}
768
769/**
770 * Wait until work list empty
771 * Advisory only
772 */
773
774#if 0 // 2015-08-03 SHL FIXME debug
775VOID WaitFleshWorkListEmpty()
776#else
777VOID WaitFleshWorkListEmptyDbg(PCSZ pszSrcFile_, UINT uSrcLineNo_)
778#endif
779{
780 INT tid = GetTidForThread();
781
782 if (tid == 1 || tid == tidFleshWorkListThread) {
783# ifdef WaitFleshWorkListEmpty
784 Runtime_Error(pszSrcFile, __LINE__, "WaitFleshWorkListEmpty called with worklist %sempty by tid %u at %s:%u", IsFleshWorkListEmpty() ? "" : "not ", tid, pszSrcFile_, uSrcLineNo_);
785# else
786 Runtime_Error(pszSrcFile, __LINE__, "WaitFleshWorkListEmpty called by tid %u", tid);
787# endif
788 return; // Avoid hang
789 }
790 else if (IsFleshWorkListEmpty()) {
791# ifdef WaitFleshWorkListEmpty
792 DbgMsg(pszSrcFile, __LINE__, "WaitFleshWorkListEmpty called with worklist empty by tid %u at %s:%u", tid, pszSrcFile_, uSrcLineNo_);
793# else
794 DbgMsg(pszSrcFile, __LINE__, "WaitFleshWorkListEmpty called with work list empty by tid %u", tid);
795# endif
796 }
797
798 // Can not wait if call from thread 1 or FleshWorkListThread
799 while (!IsFleshWorkListEmpty()) {
800# ifdef WaitFleshWorkListEmpty
801 if (!fNoFleshDbgMsg)
802 // DbgMsg(pszSrcFile, __LINE__, "WaitFleshWorkListEmpty called with work list not empty by %s:%u", pszSrcFile_, uSrcLineNo_); // 2015-08-07 SHL FIXME debug
803# else
804 if (!fNoFleshDbgMsg)
805 // DbgMsg(pszSrcFile, __LINE__, "WaitFleshWorkListEmpty called with work list not empty"); // 2015-08-07 SHL FIXME debug
806# endif
807 // 2015-08-13 SHL FIXME to optimize
808 if (fAmClosing) {
809 // Can jiggle - see MainWndProc WM_CLOSE
810 DosSleep(100);
811 if (fAmClosing)
812 return;
813 }
814 DosSleep(250);
815 }
816}
817
818/**
819 * Set focus drive to optimize work list processing
820 * @param chDriveLetter is upper case drive letter (A-Z)
821 */
822
823VOID SetFleshFocusDrive(CHAR chDriveLetter) {
824 chFleshFocusDrive = chDriveLetter;
825 DbgMsg(pszSrcFile, __LINE__, "SetFleshFocusDrive focus drive set to %c", chFleshFocusDrive); // 2015-08-03 SHL FIXME debug
826
827}
828
829/**
830 * Check pci pathname matches focus drive
831 * @param data is uppercase drive letter mapped to PVOID
832 * @return TRUE if drive letter matches
833 */
834
835BOOL MatchesFocusDrive(PLIST2 item, PVOID data)
836{
837 if (!((PFLESHWORKITEM)item)->pci->pszFileName) {
838 Runtime_Error(pszSrcFile, __LINE__, "MatchesFocusDrive called with pci %p pszFileName (null) by %s:%u", ((PFLESHWORKITEM)item)->pci);
839 return FALSE;
840 }
841 return ((PFLESHWORKITEM)item)->pci->pszFileName[0] == (CHAR)data;
842}
843
844/**
845 * Run Flesh, UnFlesh, FleshEnv, Stubby for directory for items in work list
846 */
847
848VOID FleshWorkThread(PVOID arg)
849{
850 HAB thab;
851 HMQ hmq = (HMQ)0;
852 APIRET rc;
853
854 // 2015-08-07 SHL FIXME to be gone
855 static INT ProcessDirCount = 0;
856
857 DosError(FERR_DISABLEHARDERR);
858
859# ifdef FORTIFY
860 Fortify_EnterScope();
861# endif
862
863 thab = WinInitialize(0);
864 if (thab) {
865 hmq = WinCreateMsgQueue(thab, 0);
866 if (hmq) {
867 IncrThreadUsage();
868 priority_normal();
869
870 // 2015-08-07 SHL FIXME to know when to terminate
871 // process list entries forever
872 for (;;) {
873
874 PFLESHWORKITEM item;
875
876 // 2015-08-13 SHL FIXME to optimize
877 if (fAmClosing) {
878 // Can jiggle - see MainWndProc WM_CLOSE
879 DosSleep(100);
880 if (fAmClosing)
881 break; // time to die
882 }
883
884 // 2015-08-07 SHL FIXME to use SMPSafe...
885 rc = DosRequestMutexSem(hmtxFleshWork, SEM_INDEFINITE_WAIT);
886 if (rc)
887 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__, "DosRequestMutexSem");
888
889 // 2015-08-14 SHL
890 // Get next work list item and remove from list
891 // If focus drive known, process items for focus drive first
892 if (chFleshFocusDrive) {
893 item = (PFLESHWORKITEM)List2Search(&FleshWorkList, MatchesFocusDrive, (PVOID)chFleshFocusDrive);
894 if (!item)
895 chFleshFocusDrive = 0; // Revert to normal
896 else
897 List2Delete(&FleshWorkList, (PLIST2)item);
898 }
899 else
900 item = NULL;
901
902 if (!item)
903 item = (PFLESHWORKITEM)List2DeleteFirst(&FleshWorkList);
904
905 rc = DosReleaseMutexSem(hmtxFleshWork);
906 if (rc)
907 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__, "DosReleaseMutexSem");
908
909 // 2015-08-07 SHL FIXME to have event sem
910 if (!item) {
911 ULONG ul;
912 if (!fNoFleshDbgMsg)
913 DbgMsg(pszSrcFile, __LINE__, "FleshWorkThread work list empty - waiting"); // 2015-08-03 SHL FIXME debug
914 rc = DosWaitEventSem(hevFleshWorkListChanged, SEM_INDEFINITE_WAIT);
915 if (rc)
916 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__, "DosWaitEventSem");
917 rc = DosResetEventSem(hevFleshWorkListChanged, &ul);
918 if (rc)
919 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__, "DosResetEventSem");
920 if (!fNoFleshDbgMsg)
921 DbgMsg(pszSrcFile, __LINE__, "FleshWorkThread work hev posted"); // 2015-08-03 SHL FIXME debug
922 continue;
923 }
924
925 if (WinIsWindow((HAB)0, item->hwndCnr)) {
926
927 ULONG flags;
928
929#if 0 // 2015-08-07 SHL FIXME debug
930 // 2015-08-03 SHL FIXME debug
931 {
932 static PSZ itemNames[] = {
933 "eStubby", "eFlesh", "eFleshEnv", "eUnFlesh"
934 };
935
936 PCNRITEM pci = item->pci;
937 if (!fNoFleshDbgMsg) {
938 DbgMsg(pszSrcFile, __LINE__, "FleshWorkThread action %s pci %p pszFileName %s",
939 itemNames[item->action],
940 pci,
941 pci && (INT)pci != -1 ?
942 (pci->pszFileName ? pci->pszFileName : "(nullname)") :
943 "(nullpci)"); // 2015-08-03 SHL FIXME debug
944 }
945 }
946#endif
947
948 switch (item->action) {
949 case eUnFlesh:
950 UnFlesh(item->hwndCnr, item->pci);
951 break;
952 case eFleshEnv:
953 FleshEnv(item->hwndCnr, item->pci);
954 break;
955 case eFillDir:
956 case eStubby:
957 // DbgMsg(pszSrcFile, __LINE__, "FleshWorkThread pci %p pszFileName %s", stubbyArgs->pci, stubbyArgs->pci->pszFileName); // 2015-08-03 SHL FIXME debug
958 flags = driveflags[toupper(*item->pci->pszFileName) - 'A'];
959
960#if 0 // 2015-08-07 SHL FIXME to be gone
961 if (flags & DRIVE_LOCALHD) {
962 // Serialize to prevent head thrashing
963 rc = DosRequestMutexSem(hmtxScanningLocalHD, SEM_INDEFINITE_WAIT);
964 if (rc)
965 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__, "DosRequestMutexSem");
966 }
967#endif
968
969#if 1
970 if (item->action == eFillDir) {
971 // eFillDir maps to eFlesh or eStubby depending on fRScan.. settings
972 if (((fRScanLocal && flags & DRIVE_LOCALHD) ||
973 (fRScanRemote && flags & DRIVE_REMOTE) ||
974 (fRScanVirtual && flags & DRIVE_VIRTUAL)) &&
975 (!(flags & ((fRScanNoWrite ? 0 : DRIVE_NOTWRITEABLE) |
976 (fRScanSlow ? 0 : DRIVE_SLOW)))))
977 {
978 item->action = eFlesh;
979 }
980 else
981 item->action = eStubby;
982 }
983#else
984 wantFlesh = ((fRScanLocal && flags & DRIVE_LOCALHD ) ||
985 (fRScanRemote && flags & DRIVE_REMOTE) ||
986 (fRScanVirtual && flags & DRIVE_VIRTUAL)) &&
987 // 2015-08-11 SHL typo - should not be local or
988 (!(flags & ((fRScanNoWrite ? 0 : DRIVE_NOTWRITEABLE) ||
989 (fRScanSlow ? 0 : DRIVE_SLOW))));
990#endif
991 if (item->action == eStubby) {
992 Stubby(item->hwndCnr, item->pci);
993 break;
994 }
995 // Drop through to eFlesh
996
997
998#if 0 // 2015-08-07 SHL FIXME to be gone
999 if (flags & DRIVE_LOCALHD) {
1000 rc = DosReleaseMutexSem(hmtxScanningLocalHD);
1001 if (rc) {
1002 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
1003 "DosReleaseMutexSem(hmtxScanningLocalHD)");
1004 }
1005 }
1006#endif // 2015-08-07 SHL FIXME to be gone
1007
1008 // Drop through
1009 case eFlesh:
1010 if (Flesh(item->hwndCnr, item->pci)) {
1011 // 2015-08-06 SHL FIXME to report?
1012 }
1013 break;
1014 default:
1015 Runtime_Error(pszSrcFile, __LINE__, "item %u unexpected", item->action);
1016 } // switch
1017
1018
1019 } // if window
1020
1021 xfree(item, pszSrcFile, __LINE__);
1022
1023 } // for
1024
1025 WinDestroyMsgQueue(hmq);
1026 }
1027 DecrThreadUsage();
1028 WinTerminate(thab);
1029 }
1030
1031 ProcessDirCount++;
1032 // DbgMsg(pszSrcFile, __LINE__, "ProcessDirCount %i FixedVolume %i", ProcessDirCount, FixedVolume);
1033 if (ProcessDirCount >= FixedVolume) {
1034
1035#if 0 // 2015-08-04 SHL FIXME to be gone
1036 rc = DosReleaseMutexSem(hmtxScanning);
1037 if (rc)
1038 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__, "DosReleaseMutexSem");
1039#endif // 2015-08-04 SHL FIXME to be gone
1040
1041#if 0 // 2015-08-04 SHL FIXME to be gone
1042 rc = DosPostEventSem(hevTreeCnrScanComplete);
1043 if (rc && rc != ERROR_ALREADY_POSTED)
1044 Dos_Error(MB_ENTER, rc, HWND_DESKTOP, pszSrcFile, __LINE__, "DosPostEventSem");
1045#endif // 2015-08-04 SHL FIXME to be gone
1046
1047 ProcessDirCount = 0;
1048 FixedVolume = 0;
1049 }
1050
1051# ifdef FORTIFY
1052 Fortify_LeaveScope();
1053# endif
1054
1055}
1056
1057/**
1058 * Allocate resources and start FleshWorkThread
1059 * @return TRUE if OK
1060 */
1061
1062BOOL StartFleshWorkThread()
1063{
1064 APIRET rc = DosCreateMutexSem(NULL, &hmtxFleshWork, 0L /* Not shared */, FALSE /* Not owned */);
1065 if (rc) {
1066 Dos_Error(MB_CANCEL, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
1067 PCSZ_DOSCREATEMUTEXSEM);
1068 return FALSE;
1069 }
1070
1071 rc = DosCreateEventSem(NULL, &hevFleshWorkListChanged, 0 /* Not shared */, FALSE /* Reset */);
1072 if (rc) {
1073 Dos_Error(MB_CANCEL, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
1074 PCSZ_DOSCREATEEVENTSEM);
1075 return FALSE;
1076 }
1077
1078 /* DbgMsg is time consuming
1079 define FM2_NO_FLESH_DBGMSG to suppress
1080 2015-08-09 SHL FIXME to be gone
1081 */
1082
1083 fNoFleshDbgMsg = getenv("FM2_NO_FLESH_DBGMSG") != NULL;
1084
1085 tidFleshWorkListThread = xbeginthread(FleshWorkThread,
1086 65536,
1087 NULL,
1088 pszSrcFile, __LINE__);
1089 return tidFleshWorkListThread != -1;
1090
1091}
1092
1093#pragma alloc_text(FLESH,Flesh,FleshEnv,UnFlesh,Stubby,FleshWorkThread,StartFleshWorkThread,AddFleshWorkRequest)
Note: See TracBrowser for help on using the repository browser.