source: trunk/dll/flesh.c@ 1880

Last change on this file since 1880 was 1880, checked in by Gregg Young, 10 years ago

Remove dead code and comments from remaining c files. #if 0 and #if NEVER were not addressed

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.8 KB
RevLine 
[145]1
2/***********************************************************************
3
4 $Id: flesh.c 1880 2015-10-12 18:26:16Z gyoung $
5
[1856]6 Drive tree container management
[145]7
8 Copyright (c) 1993-98 M. Kimes
[1858]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
[1858]37 19 Aug 15 SHL Allow WaitFleshWorkListEmpty to wait for dependent items
[1864]38 23 Aug 15 GKY Fixed code to notify on drive with no subdirectories in first 64 entries
[1871]39 20 Sep 15 GKY Add code for Flesh to skip the directory entry added by Stubby (eliminate
40 use of NULL/Nullstr pszFileNames by Stubby). Add code in Stubby to insert a
41 complete container item. Add a flag to indicate when a directory needed to be
42 Fleshed
[1873]43 26 Sep 15 GKY Changes to speed up ExpandAll
44 26 Sep 15 GKY WaitFleshWorkListEmpty now gives error message and returns if semaphore request
45 fails more than 5 consecutive times.
[1874]46 27 Sep 15 GKY DosSleep times in WaitFleshWorkListEmpty set by caller
[1876]47 10 Oct 15 GKY Don't use Flesh thread for floppy drive scans fix them getting mistakenly identified
48 as directories and add nonexistent subdirectories.
[145]49
50***********************************************************************/
51
[907]52#include <stdlib.h>
53#include <string.h>
54#include <ctype.h>
55
[2]56#define INCL_DOS
57#define INCL_DOSERRORS
58#define INCL_WIN
[907]59#define INCL_LONGLONG // dircnrs.h
[2]60
[1177]61#include "fm3dll.h"
[1207]62#include "draglist.h" // Data declaration(s)
63#include "notebook.h" // Data declaration(s)
64#include "info.h" // Data declaration(s)
65#include "init.h" // Data declaration(s)
66#include "mainwnd.h" // Data declaration(s)
[907]67#include "fm3str.h"
68#include "filldir.h" // FileAttrToString...
69#include "errutil.h" // Dos_Error...
70#include "strutil.h" // GetPString
[1155]71#include "flesh.h"
72#include "valid.h" // IsValidDir
[1856]73#include "misc.h" // LoadLibPath GetTidForThread
[1177]74#include "findrec.h" // FindCnrRecord
75#include "notify.h" // Notify
76#include "wrappers.h" // xfree
[1354]77#include "excputil.h" // xbeginthread
[1856]78#include "listutil.h" // List...
79#include "common.h" // IncrThreadUsage DecrThreadUsage
[1871]80#include "pathutil.h"
[1873]81#include "treecnr.h" // fExpandAll
[1831]82#if 0
83#define __PMPRINTF__
84#include "PMPRINTF.H"
85#endif
[2]86
[1207]87// Data definitions
[2]88#pragma data_seg(DATA1)
[340]89
90static PSZ pszSrcFile = __FILE__;
91
[1856]92
93static INT tidFleshWorkListThread = -1; // 2015-08-08 SHL
94
[1860]95static PCSZ pszFleshFocusPath; // 2015-08-20 SHL
[1877]96
[1207]97#pragma data_seg(GLOBAL1)
98ULONG NoBrokenNotify;
99BOOL fFilesInTree;
100
[1856]101BOOL Stubby(HWND hwndCnr, PCNRITEM pciParent);
102BOOL FleshEnv(HWND hwndCnr, PCNRITEM pciParent);
103
104/**
105 * Insert CNRITEMs for members of PATH-like environment variable
106 * @param hwndCnr is the container to be populated
107 * @param pciParent is CNRITEM defining PATH-like environment variable
108 * @return TRUE if OK, FALSE is error detected
109 */
110
[551]111BOOL FleshEnv(HWND hwndCnr, PCNRITEM pciParent)
[175]112{
[551]113 PCNRITEM pciL;
[2]114 DIRCNRDATA *dcd;
[551]115 CHAR path[CCHMAXPATH + 12],
116 fullpath[CCHMAXPATH + 12], *env, *p, *pp, *var = NULL;
[2]117
[1858]118 if (!pciParent || (INT)pciParent == -1 || !hwndCnr)
[2]119 return FALSE;
[1856]120
[574]121 dcd = (DIRCNRDATA *) WinQueryWindowPtr(hwndCnr, QWL_USER);
[551]122 if (!dcd)
[2]123 return FALSE;
124
[730]125 strcpy(path, pciParent->pszFileName + 1);
[551]126 if (stricmp(path, GetPString(IDS_ENVVARSTEXT) + 1))
127 UnFlesh(hwndCnr, pciParent);
128 if (*path) {
[2]129 path[strlen(path) - 1] = 0;
[1400]130 if (!stricmp(path, PCSZ_LIBPATH)) {
[551]131 var = xmalloc(65536, pszSrcFile, __LINE__);
132 if (var)
133 LoadLibPath(var, 65536);
[2]134 env = var;
135 }
136 else
137 env = getenv(path);
[551]138 if (env && *env) {
[2]139 p = env;
[551]140 while (*p) {
141 pp = path;
142 while (*p == ';')
143 p++;
144 while (*p && *p != ';') {
145 *pp = *p;
146 p++;
147 pp++;
148 }
149 *pp = 0;
150 if (*path &&
151 strcmp(path, ".") &&
152 strcmp(path, ".\\") &&
153 strcmp(path, "..") &&
154 strcmp(path, "..\\") &&
155 strncmp(path, ".\\", 2) && strncmp(path, "..\\", 3)) {
156 if (!DosQueryPathInfo(path,
157 FIL_QUERYFULLNAME,
158 fullpath,
159 sizeof(fullpath)) && IsValidDir(fullpath)) {
160 pciL = FindCnrRecord(hwndCnr,
161 fullpath, pciParent, FALSE, FALSE, FALSE);
162 if (pciL) {
[1858]163 while (pciL && pciL != (PCNRITEM)-1 && pciL != pciParent)
[551]164 pciL = WinSendMsg(hwndCnr,
165 CM_QUERYRECORD,
166 MPFROMP(pciL),
167 MPFROM2SHORT(CMA_PARENT, CMA_ITEMORDER));
168 }
169 if (!pciL) {
[2]170
[551]171 RECORDINSERT ri;
[2]172
[551]173 pciL = WinSendMsg(hwndCnr,
174 CM_ALLOCRECORD,
[751]175 MPFROMLONG(EXTRA_RECORD_BYTES),
[551]176 MPFROMLONG(1));
177 if (pciL) {
[730]178 pciL->pszFileName = xstrdup(fullpath, pszSrcFile, __LINE__);
[751]179 pciL->rc.pszIcon = pciL->pszFileName;
[551]180 if (!fNoIconsDirs &&
181 (!isalpha(*fullpath) ||
182 !(driveflags[toupper(*fullpath) - 'A'] &
183 DRIVE_NOLOADICONS)))
184 pciL->rc.hptrIcon = WinLoadFileIcon(fullpath, FALSE);
185 if (!pciL->rc.hptrIcon)
186 pciL->rc.hptrIcon = hptrDir;
187 pciL->attrFile = FILE_DIRECTORY;
[751]188 pciL->pszDispAttr = FileAttrToString(pciL->attrFile);
[551]189 memset(&ri, 0, sizeof(ri));
190 ri.cb = sizeof(ri);
[1858]191 ri.pRecordOrder = (PRECORDCORE)CMA_END;
192 ri.pRecordParent = (PRECORDCORE)pciParent;
193 ri.zOrder = (ULONG)CMA_TOP;
[551]194 ri.cRecordsInsert = 1;
195 ri.fInvalidateRecord = FALSE;
[1871]196 if (!WinSendMsg(hwndCnr,
[551]197 CM_INSERTRECORD, MPFROMP(pciL), MPFROMP(&ri)))
[751]198 FreeCnrItem(hwndCnr, pciL);
[551]199 }
200 }
201 }
202 }
[2]203 }
204 }
[1009]205 xfree(var, pszSrcFile, __LINE__);
[1858]206 pciL = (PCNRITEM)WinSendMsg(hwndCnr,
207 CM_QUERYRECORD,
208 MPFROMP(pciParent),
209 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
210 while (pciL && (INT)pciL != -1) {
[2]211 pciL->flags |= (RECFLAGS_NODRAG | RECFLAGS_UNDERENV);
212 WinSendMsg(hwndCnr,
[551]213 CM_INVALIDATERECORD, MPFROMP(&pciL), MPFROM2SHORT(1, 0));
[2]214 pciL = WinSendMsg(hwndCnr,
[551]215 CM_QUERYRECORD,
216 MPFROMP(pciL), MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
[2]217 }
218 }
219 return TRUE;
220}
221
[1856]222/**
223 * Insert CNRITEMs for all children of pciParent
224 * @param hwnCnr is container to receive CNRITEMs
225 * @param pciParent is CNRITEM to have children inserted
226 * @return TRUE if OK, FALSE is error detected
227 */
228
[551]229BOOL Flesh(HWND hwndCnr, PCNRITEM pciParent)
[166]230{
[551]231 PCNRITEM pciL;
[2]232 DIRCNRDATA *dcd;
[1856]233 BOOL includefiles;
[2]234
[1856]235 if (!pciParent || (INT)pciParent == -1 || !hwndCnr)
[2]236 return FALSE;
[1856]237
[1858]238 // 2015-08-13 SHL
239 if (fAmQuitting)
240 return FALSE;
[1856]241
[1871]242 if (!pciParent->fleshed) {
243 pciL = (PCNRITEM)WinSendMsg(hwndCnr,
244 CM_QUERYRECORD,
245 MPFROMP(pciParent),
246 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
[1874]247 // Added by Stubby to create plus sign run Stubby on it here and skip it in ProcessDirectory
[1856]248 if (pciL && (INT)pciL != -1) {
[1871]249 AddFleshWorkRequest(hwndCnr, pciL, eStubby);
[1874]250 // 2015-08-06 SHL FIXME to ensure this can not happen
[1871]251 if (!*pciL->pszFileName || !strcmp(pciL->pszFileName, NullStr))
[1877]252 Runtime_Error(pszSrcFile, __LINE__, "Flesh called with pci %p pszFileName (null)",
253 pciL);
[1856]254 }
[1651]255 dcd = INSTDATA(hwndCnr);
256 if (dcd && dcd->size != sizeof(DIRCNRDATA))
257 dcd = NULL;
[1856]258
259 includefiles =
260 driveflags[toupper(*pciParent->pszFileName) - 'A'] & DRIVE_INCLUDEFILES ?
261 TRUE : fFilesInTree;
262
[1662]263 ProcessDirectory(hwndCnr,
[1856]264 pciParent,
265 pciParent->pszFileName,
266 includefiles, // filestoo
267 TRUE, // recurse
268 TRUE, // partial
269 NULL, // stop flag
270 dcd,
271 NULL, // total files
[1871]272 NULL, // total bytes
273 (pciL && (INT)pciL != -1) ? pciL->pszDisplayName : 0);
274 pciParent->fleshed = TRUE;
[1655]275 return TRUE;
[1651]276 }
[1856]277
[1655]278 return FALSE;
[2]279}
280
[1858]281/**
282 * Remove children from container
[1865]283 * @param pciParent is parent of children to be removed
[1858]284 */
[1856]285
[1858]286VOID UnFlesh(HWND hwndCnr, PCNRITEM pciParent)
[175]287{
[1856]288 BOOL removed = FALSE;
[2]289 PCNRITEM pciL;
290
[175]291 if (!pciParent || !hwndCnr)
[1858]292 return;
[551]293 for (;;) {
[1858]294 pciL = (PCNRITEM)WinSendMsg(hwndCnr,
295 CM_QUERYRECORD,
296 MPFROMP(pciParent),
297 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
[1856]298 if (!pciL || (INT)pciL == -1)
[1877]299 break;
[1856]300 RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
301 removed = TRUE;
302 } // for
303
304 if (removed) {
[2]305 WinSendMsg(hwndCnr,
[551]306 CM_INVALIDATERECORD,
307 MPFROMP(&pciParent),
[1871]308 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
309 pciParent->fleshed = FALSE;
310 DosSleep(1); // Let container items go away
[175]311 }
[1858]312 return;
[2]313}
314
[1482]315#define DDEPTH 64
[2]316
[1471]317/**
[1856]318 * Insert CNRITEM for 1st subdirectory [or file] of pciParent
319 * @param hwdCnr is container to be filled
320 * @param pciParent is CNRITEM to receive child record
321 * @return TRUE if record inserted, else FALSE
322 * Ensures that expand/collapse button displays if directory has children
323 * Secondary purpose is to detect broken LANs and inaccesible mapped drives
[1471]324 */
325
[551]326BOOL Stubby(HWND hwndCnr, PCNRITEM pciParent)
[175]327{
[1409]328 /**
[2]329 * this code is full of workarounds for screwed up LANs.
330 * let's hope all the current LAN programmers fall into
331 * a black hole and make way for people who can get it right...
332 */
333
[1471]334 BOOL ok = FALSE;
[847]335 FILEFINDBUF3 ffb[DDEPTH];
336 PFILEFINDBUF3 pffb;
[551]337 HDIR hDir = HDIR_CREATE;
[1856]338 ULONG nm, ulM = 1, total = 0, fl;
[1858]339 CHAR wildcard[CCHMAXPATH];
[551]340 register INT len;
341 APIRET rc, prc;
[1858]342 BOOL isadir = FALSE;
343 BOOL isremote;
344 BOOL includefiles;
[1482]345 ULONG ddepth = DDEPTH;
[1299]346 ULONG drvNum;
347 ULONG flags;
[551]348 static BOOL brokenlan = FALSE, isbroken = FALSE;
[2]349
[1858]350 if (!pciParent || (INT)pciParent == -1 || !*pciParent->pszFileName
[1832]351 || pciParent->pszFileName == NullStr || !hwndCnr)
[2]352 return FALSE;
[1856]353 // Build wildcard
[730]354 len = strlen(pciParent->pszFileName);
[1858]355 memcpy(wildcard, pciParent->pszFileName, len + 1);
356 if (wildcard[len - 1] != '\\')
357 wildcard[len++] = '\\';
358 wildcard[len++] = '*';
359 wildcard[len] = 0;
[2]360
[1858]361 // 2015-08-19 SHL FIXME to know how this can happen
362 if (!isalpha(*wildcard) || wildcard[1] != ':' || wildcard[2] != '\\') {
363 MakeFullName(wildcard);
364 }
[1299]365 drvNum = toupper(*pciParent->pszFileName) - 'A';
366 flags = driveflags[drvNum];
[1858]367 if (!isalpha(*wildcard) ||
368 wildcard[1] != ':' ||
369 wildcard[2] != '\\' || ((flags & DRIVE_IGNORE)))
[1856]370 return FALSE; // Not a directory or ignore requested
[2]371
[1856]372 includefiles = flags & DRIVE_INCLUDEFILES ? TRUE : fFilesInTree;
[2]373
[1856]374 isremote = flags & DRIVE_REMOTE ? TRUE : FALSE;
[2]375
[551]376 if (isremote) {
377 if (fRemoteBug) {
378 if (brokenlan) {
[1858]379 ddepth = (ULONG)-1;
[551]380 ddepth--;
[2]381 }
[761]382 ulM = 1;
[2]383 }
384 }
[551]385 else if (isbroken)
[2]386 ddepth = 14;
387
[1482]388 if (!fRemoteBug)
[1856]389 ulM = ddepth <= DDEPTH ? ddepth : 1;
[2]390
391 nm = ulM;
392
393 DosError(FERR_DISABLEHARDERR);
[1856]394
395 fl = includefiles ? FILE_DIRECTORY : MUST_HAVE_DIRECTORY;
[1858]396 rc = DosFindFirst(wildcard,
[847]397 &hDir,
398 FILE_NORMAL | fl |
399 FILE_READONLY | FILE_ARCHIVED |
400 FILE_SYSTEM | FILE_HIDDEN,
401 &ffb, ulM * sizeof(FILEFINDBUF3), &nm, FIL_STANDARD);
[761]402 if (ulM == 1 && !rc) {
[1856]403 // Loop looking for 1st directory (or file)
[2]404 do {
405 pffb = &ffb[0];
[551]406 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY) && !brokenlan) {
[1856]407 // Find returned file when only directories requested
[551]408 brokenlan = TRUE;
[1858]409 ddepth = (ULONG)-1;
[551]410 ddepth--;
411 if (!NoBrokenNotify) {
412 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
413 HWND_DESKTOP,
414 GetPString(IDS_LANERRORTITLETEXT),
415 GetPString(IDS_LANERRORTEXT));
416 if (prc == MBID_NO) {
417 saymsg(MB_ENTER,
418 HWND_DESKTOP,
419 GetPString(IDS_LANERROR2TITLETEXT),
420 GetPString(IDS_LANERROR2TEXT));
[847]421 NoBrokenNotify = 255;
[1505]422 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]423 &NoBrokenNotify, sizeof(ULONG));
424 }
425 }
426 else {
427 NoBrokenNotify--;
[1505]428 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]429 &NoBrokenNotify, sizeof(ULONG));
430 }
[2]431 }
[1856]432
[515]433 if (*pffb->achName &&
[551]434 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
435 (pffb->achName[0] != '.' ||
[515]436 (pffb->achName[1] &&
[551]437 (pffb->achName[1] != '.' || pffb->achName[2])))) {
[1856]438 // Got directory other than . or .. (or a file)
[551]439 DosFindClose(hDir);
440 isadir = TRUE;
441 goto Interruptus;
[2]442 }
[761]443 nm = 1;
[2]444 DosError(FERR_DISABLEHARDERR);
[1856]445 } while (++total < ddepth && !(rc = (DosFindNext(hDir,
446 &ffb,
447 sizeof(FILEFINDBUF3),
448 &nm))));
449 DosFindClose(hDir);
450
[730]451 if (toupper(*pciParent->pszFileName) > 'B' &&
[751]452 (*(pciParent->pszFileName + 1)) == ':' &&
[730]453 (*(pciParent->pszFileName + 2)) == '\\' && !(*(pciParent->pszFileName + 3))) {
[2]454
[1856]455 // Searching root of hard or remote drive and find reported error
[2]456 CHAR s[132];
457 sprintf(s,
[551]458 GetPString(IDS_NOSUBDIRSTEXT),
[730]459 total, toupper(*pciParent->pszFileName));
[551]460 if (rc && rc != ERROR_NO_MORE_FILES)
[1858]461 sprintf(&s[strlen(s)], GetPString(IDS_SEARCHERRORTEXT), rc, wildcard);
[847]462 else if (ddepth < 16)
[551]463 brokenlan = TRUE;
[2]464 Notify(s);
465 }
[1856]466 goto None; // Done
[2]467 }
[551]468 if (!rc) {
[2]469 DosFindClose(hDir);
[551]470 if (nm) {
[1353]471 PBYTE fb = (PBYTE)&ffb[0];
[551]472 for (len = 0; len < nm; len++) {
[847]473 pffb = (PFILEFINDBUF3) fb;
[551]474 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY)) {
[1856]475 // Got file(s), but did not ask for files
[551]476 if (!isbroken) {
477 isbroken = TRUE;
478 if (!NoBrokenNotify) {
479 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
480 HWND_DESKTOP,
481 GetPString(IDS_FSDERRORTITLETEXT),
482 GetPString(IDS_FSDERRORTEXT),
[1471]483 isremote ? GetPString(IDS_REMOTETEXT) :
484 GetPString(IDS_LOCALTEXT),
[1858]485 *wildcard);
[551]486 if (prc == MBID_NO) {
487 saymsg(MB_ENTER,
488 HWND_DESKTOP,
489 GetPString(IDS_FSDERROR2TITLETEXT),
490 GetPString(IDS_FSDERROR2TEXT));
[847]491 NoBrokenNotify = 255;
[1505]492 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]493 &NoBrokenNotify, sizeof(ULONG));
494 }
495 }
496 else {
497 NoBrokenNotify--;
[1505]498 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]499 &NoBrokenNotify, sizeof(ULONG));
500 }
[1856]501 } // if !broken
502 } // if !directory
503
[551]504 if (*pffb->achName &&
505 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
[1856]506 ((pffb->achName[0] && pffb->achName[0] != '.') ||
507 (pffb->achName[1] &&
508 (pffb->achName[1] != '.' || pffb->achName[2]))))
509 {
[1871]510 // Got directory other than . or .. (or a file)
[551]511 isadir = TRUE;
512 break;
513 }
514 fb += pffb->oNextEntryOffset;
[1353]515 } // for
[2]516
[551]517 Interruptus:
[2]518
[551]519 if (isadir) {
[2]520
[1856]521 // Insert CNRITEM for selected directory (or file)
[1471]522 PCNRITEM pci;
[2]523
[1471]524 if (WinIsWindow((HAB)0, hwndCnr)) {
525 pci = WinSendMsg(hwndCnr,
526 CM_ALLOCRECORD,
527 MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(1));
528 if (!pci) {
529 Win_Error(hwndCnr, HWND_DESKTOP, __FILE__, __LINE__,
530 GetPString(IDS_RECORDALLOCFAILEDTEXT));
531 }
532 else {
[1871]533 RECORDINSERT ri;
534 CHAR szBuffer[CCHMAXPATH + 14];
535 CHAR *p;
536 HPOINTER hptr;
537
538 p = strchr(wildcard, '*');
539 *p = 0;;
540 BldFullPathName(szBuffer, wildcard, pffb->achName);
[1880]541 pci->pszFileName = xstrdup(szBuffer, pszSrcFile, __LINE__);
[1871]542 p = strrchr(pci->pszFileName, '\\');
543 p++;
[1880]544 pci->pszDisplayName = p;
[1871]545 pci->rc.pszIcon = pci->pszDisplayName;
546 if (fForceUpper)
547 strupr(pci->pszFileName);
548 else if (fForceLower)
549 strlwr(pci->pszFileName);
550
551 flags = driveflags[toupper(*pci->pszFileName) - 'A'];
552
553 // get an icon to use with it
554 if (pffb->attrFile & FILE_DIRECTORY) {
555 // is directory
556 if (fNoIconsDirs ||
557 (flags & DRIVE_NOLOADICONS) ||
558 !isalpha(*pci->pszFileName)) {
559 hptr = (HPOINTER) 0;
560 }
561 else
562 hptr = WinLoadFileIcon(pci->pszFileName, FALSE);
563 }
564 else {
565 // is file
566 if (fNoIconsFiles ||
567 (flags & DRIVE_NOLOADICONS) ||
568 !isalpha(*pci->pszFileName)) {
569 hptr = (HPOINTER) 0;
570 }
571 else
572 hptr = WinLoadFileIcon(pci->pszFileName, FALSE);
573
574 if (!hptr || IsDefaultIcon(hptr))
575 hptr = IDFile(pci->pszFileName);
576 }
577
578 if (!hptr) {
579 hptr = pffb->attrFile & FILE_DIRECTORY ?
580 hptrDir : pffb->attrFile & FILE_SYSTEM ?
581 hptrSystem : pffb->attrFile & FILE_HIDDEN ?
582 hptrHidden : pffb->attrFile & FILE_READONLY ?
583 hptrReadonly : hptrFile;
584 }
585 pci->rc.hptrIcon = hptr;
[1471]586 memset(&ri, 0, sizeof(RECORDINSERT));
587 ri.cb = sizeof(RECORDINSERT);
[1858]588 ri.pRecordOrder = (PRECORDCORE)CMA_END;
589 ri.pRecordParent = (PRECORDCORE)pciParent;
590 ri.zOrder = (ULONG)CMA_TOP;
[1471]591 ri.cRecordsInsert = 1;
[1856]592 ri.fInvalidateRecord = TRUE;
[1871]593 if (!WinSendMsg(hwndCnr,
[1471]594 CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
[1856]595 // Assume busy and try again
[1877]596 DosSleep(50);
[1856]597 WinSetFocus(HWND_DESKTOP, hwndCnr);
[1871]598 if (WinIsWindow((HAB)0, hwndCnr)) {
[1471]599 if (!WinSendMsg(hwndCnr,
600 CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
601 Win_Error(hwndCnr, HWND_DESKTOP, __FILE__, __LINE__,
602 GetPString(IDS_RECORDINSERTFAILEDTEXT));
603 FreeCnrItem(hwndCnr, pci);
604 }
[1871]605 else
[1876]606 ok = TRUE;
[1471]607 }
608 }
609 else
[1856]610 ok = TRUE;
[1471]611 }
612 }
[1856]613 } // if isadir
[2]614 }
[1864]615 } // if !rc
616 else if (toupper(*wildcard) > 'B' && wildcard[1] == ':' && wildcard[2] == '\\' &&
[1865]617 wildcard[3] == '*' && !wildcard[4]) {
[1864]618 // Is root and no subdirectories
619 CHAR s[162];
[1865]620
[1864]621 sprintf(s,
[1865]622 GetPString(IDS_NOSUBDIRS2TEXT),
623 nm,
624 toupper(*pciParent->pszFileName),
625 isremote ? GetPString(IDS_NOSUBDIRS3TEXT) : NullStr);
[1864]626 Notify(s);
[2]627 }
[1858]628 else if (toupper(*wildcard) > 'B' && rc != ERROR_NO_MORE_FILES) {
[1856]629 // Find for remote or hard drive failed with error
[2]630 CHAR s[CCHMAXPATH + 80];
[1858]631 sprintf(s, GetPString(IDS_SEARCHERRORTEXT), rc, wildcard);
[2]632 Notify(s);
633 }
634
635None:
636
637 DosError(FERR_DISABLEHARDERR);
[1471]638 return ok;
[1856]639} // Stubby
640
641// Stubby/Flesh/Unflesh work list item
642
643typedef struct {
644 LIST2 list;
645 HWND hwndCnr;
646 PCNRITEM pci;
647 FLESHWORKACTION action;
648} FLESHWORKITEM;
649typedef FLESHWORKITEM *PFLESHWORKITEM;
650
651// Stubby/Flesh/Unflesh work list
652LIST2 FleshWorkList;
653
654HMTX hmtxFleshWork;
655HEV hevFleshWorkListChanged;
656
657/**
[1858]658 * Check work list item pci matches passed pci
[1856]659 */
660
661BOOL WorkListItemMatches(PLIST2 item, PVOID data)
662{
663 return ((PFLESHWORKITEM)data)->pci == ((PFLESHWORKITEM)item)->pci;
[2]664}
[793]665
[1856]666/**
667 * Delete stale items from flesh queue
668 */
669
670VOID DeleteStaleFleshWorkListItems(PCNRITEM pci)
671{
672 FLESHWORKITEM match;
673 PLIST2 item;
674
675 match.pci = pci;
676
677 for (;;) {
678 item = List2Search(&FleshWorkList, WorkListItemMatches, &match);
679 if (!item)
680 break;
681 List2Delete(&FleshWorkList, item);
682 xfree(item, pszSrcFile, __LINE__);
683 }
684}
685
686/**
687 * Add item to flesh work list
688 * eUnFlesh requests get special handling
689 * eFlesh etc. items for the same CNRITEM are considered stale and are
690 * deleted because eUnFlesh will free the CNRITEM associated with the item
691 * before the work list item is processed
692 */
693
[1877]694
[1856]695BOOL AddFleshWorkRequest(HWND hwndCnr, PCNRITEM pci, FLESHWORKACTION action)
696{
697 PFLESHWORKITEM item = xmallocz(sizeof(FLESHWORKITEM), pszSrcFile, __LINE__);
698 item->hwndCnr = hwndCnr;
699 item->pci = pci;
700 item->action= action;
701
[1858]702 if (fAmQuitting)
703 return FALSE;
[1856]704
705
[1860]706 xDosRequestMutexSem(hmtxFleshWork, SEM_INDEFINITE_WAIT);
[1856]707
708 // Delete stale requests
[1858]709 if (item->action == eUnFlesh)
[1856]710 DeleteStaleFleshWorkListItems(pci);
711
712 List2Append(&FleshWorkList, (PLIST2)item);
713
[1860]714 xDosReleaseMutexSem(hmtxFleshWork);
715 xDosPostEventSem(hevFleshWorkListChanged);
[1856]716
717 return TRUE;
718}
719
720/**
721 * Return TRUE if work list empty
722 * Advisory only
723 */
724
[1879]725BOOL IsFleshWorkListEmpty(VOID)
[1856]726{
727 return FleshWorkList.next == NULL;
728}
729
730/**
[1858]731 * Check if pci pathname is parent of child path name
732 * @param data is child path name
[1860]733 * @return TRUE if is work item path is parent of given path
[1858]734 */
735
736BOOL IsParentOfChildPath(PLIST2 item, PVOID data)
737{
738 UINT c;
739 if (!((PFLESHWORKITEM)item)->pci->pszFileName) {
[1861]740 Runtime_Error(pszSrcFile, __LINE__, "IsParentOfChildPath called with pci %p pszFileName (null)", ((PFLESHWORKITEM)item)->pci);
[1858]741 return FALSE;
742 }
743 c = strlen(((PFLESHWORKITEM)item)->pci->pszFileName);
[1865]744 return strncmp(((PFLESHWORKITEM)item)->pci->pszFileName, (PCSZ)data, c) == 0;
[1858]745}
746
747/**
748 * Wait until work list empty or until dependent items removed from list
[1856]749 * Advisory only
[1858]750 * @parse pszFileName is dependent pathName
[1856]751 */
752
[1877]753
[1874]754VOID WaitFleshWorkListEmpty(PCSZ pszDirName, ULONG ulSleep)
[1856]755{
[1858]756 APIRET rc;
757 PFLESHWORKITEM item;
[1856]758 INT tid = GetTidForThread();
[1860]759 BOOL pathSaved = FALSE;
[1867]760 BOOL waited;
[1860]761 PCSZ pszSavedFleshFocusPath;
[1873]762 INT rcCount = 0;
[1856]763
[1877]764 if (tid == 1 || tid == tidFleshWorkListThread) { // 11 Oct 15 GKY Fixme did we intend to keep this
[1856]765 Runtime_Error(pszSrcFile, __LINE__, "WaitFleshWorkListEmpty called by tid %u", tid);
766 return; // Avoid hang
767 }
768 // Can not wait if call from thread 1 or FleshWorkListThread
[1867]769 for (waited = FALSE; !IsFleshWorkListEmpty(); waited = TRUE) {
[1858]770 // 2015-08-13 SHL
771 if (fAmQuitting)
772 return;
773
[1860]774 // Just wait for dependents to be gone if path name given
775 if (pszDirName) {
776 rc = xDosRequestMutexSem(hmtxFleshWork, SEM_INDEFINITE_WAIT);
[1873]777 if (rc) {
778 rcCount++;
779 if (rcCount < 6)
780 continue; // Maybe should return ???
781 else {
782 Dos_Error(MB_CANCEL, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
783 PCSZ_DOSREQUESTMUTEXSEM);
784 return;
785 }
[1860]786
[1873]787 }
788
[1860]789 if (!pathSaved) {
790 // Give priority to work items for parents of this path
791 pathSaved = TRUE;
792 pszSavedFleshFocusPath = pszFleshFocusPath;
793 pszFleshFocusPath = pszDirName;
[1858]794 }
795
[1860]796 item = (PFLESHWORKITEM)List2Search(&FleshWorkList, IsParentOfChildPath, (PVOID)pszDirName);
[1858]797
[1860]798 xDosReleaseMutexSem(hmtxFleshWork);
[1873]799 rcCount = 0;
[1858]800
[1867]801 if (!item) {
802 if (waited)
[1874]803 DosSleep(ulSleep); // Let PM do some work
[1858]804 break; // Dependents gone from work list
[1867]805 }
[1860]806 } // if pszDirName
[1874]807 DosSleep(ulSleep);
[1867]808 } // for
[1858]809
[1865]810 if (pathSaved) {
[1860]811 xDosRequestMutexSem(hmtxFleshWork, SEM_INDEFINITE_WAIT);
812 pszFleshFocusPath = pszSavedFleshFocusPath;
813 xDosReleaseMutexSem(hmtxFleshWork);
814 }
[1858]815
[1856]816}
817
818/**
819 * Set focus drive to optimize work list processing
820 * @param chDriveLetter is upper case drive letter (A-Z)
821 */
822
[1860]823VOID SetFleshFocusPath(PCSZ pszPath) {
824 PCSZ pszOld;
825 PCSZ pszNew = strdup(pszPath);
826 xDosRequestMutexSem(hmtxFleshWork, SEM_INDEFINITE_WAIT);
827 pszOld = pszFleshFocusPath;
828 pszFleshFocusPath = pszNew;
829 xDosReleaseMutexSem(hmtxFleshWork);
830 if (pszOld)
831 xfree((PVOID)pszOld, pszSrcFile, __LINE__);
[1856]832}
833
834/**
835 * Run Flesh, UnFlesh, FleshEnv, Stubby for directory for items in work list
836 */
837
838VOID FleshWorkThread(PVOID arg)
839{
840 HAB thab;
841 HMQ hmq = (HMQ)0;
842
843 // 2015-08-07 SHL FIXME to be gone
844 static INT ProcessDirCount = 0;
845
846 DosError(FERR_DISABLEHARDERR);
847
848# ifdef FORTIFY
849 Fortify_EnterScope();
850# endif
851
852 thab = WinInitialize(0);
853 if (thab) {
854 hmq = WinCreateMsgQueue(thab, 0);
855 if (hmq) {
856 IncrThreadUsage();
857 priority_normal();
858
[1858]859 // process list entries until time to die
860 for (;!fAmQuitting;) {
[1856]861
862 PFLESHWORKITEM item;
863
864 // 2015-08-07 SHL FIXME to use SMPSafe...
[1860]865 xDosRequestMutexSem(hmtxFleshWork, SEM_INDEFINITE_WAIT);
[1856]866
867 // 2015-08-14 SHL
868 // Get next work list item and remove from list
[1860]869 // If focus path set, process parents of focus path first
870 if (pszFleshFocusPath) {
871 item = (PFLESHWORKITEM)List2Search(&FleshWorkList, IsParentOfChildPath, (PVOID)pszFleshFocusPath);
872 if (!item) {
873 xfree((PSZ)pszFleshFocusPath, pszSrcFile, __LINE__);
874 pszFleshFocusPath = NULL; // Revert to normal
875 }
[1856]876 else
877 List2Delete(&FleshWorkList, (PLIST2)item);
878 }
879 else
880 item = NULL;
881
882 if (!item)
883 item = (PFLESHWORKITEM)List2DeleteFirst(&FleshWorkList);
884
[1860]885 xDosReleaseMutexSem(hmtxFleshWork);
[1856]886
[1858]887 // Wait for new items to be added to list
[1856]888 if (!item) {
[1871]889 ULONG ul;
890 xDosWaitEventSem(hevFleshWorkListChanged, SEM_INDEFINITE_WAIT);
891 xDosResetEventSem(hevFleshWorkListChanged, &ul);
892 continue;
[1856]893 }
894
[1877]895 if (WinIsWindow((HAB)0, item->hwndCnr)) {
[1856]896
897 switch (item->action) {
[1871]898 case eUnFlesh:
899 UnFlesh(item->hwndCnr, item->pci);
[1856]900 break;
901 case eFleshEnv:
902 FleshEnv(item->hwndCnr, item->pci);
903 break;
904 case eStubby:
[1871]905 priority_bumped();
906 Stubby(item->hwndCnr, item->pci);
907 priority_normal();
[1865]908 break;
[1856]909 case eFlesh:
910 if (Flesh(item->hwndCnr, item->pci)) {
911 // 2015-08-06 SHL FIXME to report?
912 }
913 break;
914 default:
915 Runtime_Error(pszSrcFile, __LINE__, "item %u unexpected", item->action);
916 } // switch
917
918
919 } // if window
920
921 xfree(item, pszSrcFile, __LINE__);
922
923 } // for
924
925 WinDestroyMsgQueue(hmq);
926 }
927 DecrThreadUsage();
928 WinTerminate(thab);
929 }
930
931 ProcessDirCount++;
932 if (ProcessDirCount >= FixedVolume) {
933 ProcessDirCount = 0;
934 FixedVolume = 0;
935 }
936
937# ifdef FORTIFY
938 Fortify_LeaveScope();
939# endif
940
941}
942
943/**
944 * Allocate resources and start FleshWorkThread
945 * @return TRUE if OK
946 */
947
[1879]948BOOL StartFleshWorkThread(VOID)
[1856]949{
950 APIRET rc = DosCreateMutexSem(NULL, &hmtxFleshWork, 0L /* Not shared */, FALSE /* Not owned */);
951 if (rc) {
952 Dos_Error(MB_CANCEL, rc, HWND_DESKTOP, pszSrcFile, __LINE__,
953 PCSZ_DOSCREATEMUTEXSEM);
954 return FALSE;
955 }
956
[1860]957 rc = xDosCreateEventSem(NULL, &hevFleshWorkListChanged, 0 /* Not shared */, FALSE /* Reset */);
958 if (rc)
959 return FALSE; // Give up
[1856]960 tidFleshWorkListThread = xbeginthread(FleshWorkThread,
961 65536,
962 NULL,
963 pszSrcFile, __LINE__);
964 return tidFleshWorkListThread != -1;
965
966}
967
968#pragma alloc_text(FLESH,Flesh,FleshEnv,UnFlesh,Stubby,FleshWorkThread,StartFleshWorkThread,AddFleshWorkRequest)
Note: See TracBrowser for help on using the repository browser.