source: trunk/dll/flesh.c@ 1736

Last change on this file since 1736 was 1662, checked in by Gregg Young, 13 years ago

Fix trap on close during drive scan

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.3 KB
RevLine 
[145]1
2/***********************************************************************
3
4 $Id: flesh.c 1662 2012-08-04 21:10:30Z gyoung $
5
6 Flesh
7
8 Copyright (c) 1993-98 M. Kimes
[1662]9 Copyright (c) 2005-2012 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
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
[145]34
35***********************************************************************/
36
[907]37#include <stdlib.h>
38#include <string.h>
39#include <ctype.h>
40
[2]41#define INCL_DOS
42#define INCL_DOSERRORS
43#define INCL_WIN
[907]44#define INCL_LONGLONG // dircnrs.h
[2]45
[1177]46#include "fm3dll.h"
[1207]47#include "draglist.h" // Data declaration(s)
48#include "notebook.h" // Data declaration(s)
49#include "info.h" // Data declaration(s)
50#include "init.h" // Data declaration(s)
51#include "mainwnd.h" // Data declaration(s)
[907]52#include "fm3str.h"
53#include "filldir.h" // FileAttrToString...
54#include "errutil.h" // Dos_Error...
55#include "strutil.h" // GetPString
[1155]56#include "flesh.h"
57#include "valid.h" // IsValidDir
58#include "misc.h" // LoadLibPath
[1177]59#include "findrec.h" // FindCnrRecord
60#include "notify.h" // Notify
61#include "wrappers.h" // xfree
[1354]62#include "excputil.h" // xbeginthread
[2]63
[1207]64// Data definitions
[2]65#pragma data_seg(DATA1)
[340]66
67static PSZ pszSrcFile = __FILE__;
68
[1207]69#pragma data_seg(GLOBAL1)
70ULONG NoBrokenNotify;
71BOOL fFilesInTree;
72
[551]73BOOL FleshEnv(HWND hwndCnr, PCNRITEM pciParent)
[175]74{
[551]75 PCNRITEM pciL;
[2]76 DIRCNRDATA *dcd;
[551]77 CHAR path[CCHMAXPATH + 12],
78 fullpath[CCHMAXPATH + 12], *env, *p, *pp, *var = NULL;
[2]79
[551]80 if (!pciParent || (INT) pciParent == -1 || !hwndCnr)
[2]81 return FALSE;
[574]82 dcd = (DIRCNRDATA *) WinQueryWindowPtr(hwndCnr, QWL_USER);
[551]83 if (!dcd)
[2]84 return FALSE;
85
[730]86 strcpy(path, pciParent->pszFileName + 1);
[551]87 if (stricmp(path, GetPString(IDS_ENVVARSTEXT) + 1))
88 UnFlesh(hwndCnr, pciParent);
89 if (*path) {
[2]90 path[strlen(path) - 1] = 0;
[1400]91 if (!stricmp(path, PCSZ_LIBPATH)) {
[551]92 var = xmalloc(65536, pszSrcFile, __LINE__);
93 if (var)
94 LoadLibPath(var, 65536);
[2]95 env = var;
96 }
97 else
98 env = getenv(path);
[551]99 if (env && *env) {
[2]100 p = env;
[551]101 while (*p) {
102 pp = path;
103 while (*p == ';')
104 p++;
105 while (*p && *p != ';') {
106 *pp = *p;
107 p++;
108 pp++;
109 }
110 *pp = 0;
111 if (*path &&
112 strcmp(path, ".") &&
113 strcmp(path, ".\\") &&
114 strcmp(path, "..") &&
115 strcmp(path, "..\\") &&
116 strncmp(path, ".\\", 2) && strncmp(path, "..\\", 3)) {
117 if (!DosQueryPathInfo(path,
118 FIL_QUERYFULLNAME,
119 fullpath,
120 sizeof(fullpath)) && IsValidDir(fullpath)) {
121 pciL = FindCnrRecord(hwndCnr,
122 fullpath, pciParent, FALSE, FALSE, FALSE);
123 if (pciL) {
124 while (pciL && pciL != (PCNRITEM) - 1 && pciL != pciParent)
125 pciL = WinSendMsg(hwndCnr,
126 CM_QUERYRECORD,
127 MPFROMP(pciL),
128 MPFROM2SHORT(CMA_PARENT, CMA_ITEMORDER));
129 }
130 if (!pciL) {
[2]131
[551]132 RECORDINSERT ri;
[2]133
[551]134 pciL = WinSendMsg(hwndCnr,
135 CM_ALLOCRECORD,
[751]136 MPFROMLONG(EXTRA_RECORD_BYTES),
[551]137 MPFROMLONG(1));
138 if (pciL) {
[730]139 pciL->pszFileName = xstrdup(fullpath, pszSrcFile, __LINE__);
[751]140 pciL->rc.pszIcon = pciL->pszFileName;
[551]141 if (!fNoIconsDirs &&
142 (!isalpha(*fullpath) ||
143 !(driveflags[toupper(*fullpath) - 'A'] &
144 DRIVE_NOLOADICONS)))
145 pciL->rc.hptrIcon = WinLoadFileIcon(fullpath, FALSE);
146 if (!pciL->rc.hptrIcon)
147 pciL->rc.hptrIcon = hptrDir;
148 pciL->attrFile = FILE_DIRECTORY;
[751]149 pciL->pszDispAttr = FileAttrToString(pciL->attrFile);
[551]150 memset(&ri, 0, sizeof(ri));
151 ri.cb = sizeof(ri);
152 ri.pRecordOrder = (PRECORDCORE) CMA_END;
153 ri.pRecordParent = (PRECORDCORE) pciParent;
154 ri.zOrder = (ULONG) CMA_TOP;
155 ri.cRecordsInsert = 1;
156 ri.fInvalidateRecord = FALSE;
157 if (!WinSendMsg(hwndCnr,
158 CM_INSERTRECORD, MPFROMP(pciL), MPFROMP(&ri)))
[751]159 FreeCnrItem(hwndCnr, pciL);
[551]160 }
161 }
162 }
163 }
[2]164 }
165 }
[1009]166 xfree(var, pszSrcFile, __LINE__);
[551]167 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
168 CM_QUERYRECORD,
169 MPFROMP(pciParent),
170 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
171 while (pciL && (INT) pciL != -1) {
[2]172 pciL->flags |= (RECFLAGS_NODRAG | RECFLAGS_UNDERENV);
173 WinSendMsg(hwndCnr,
[551]174 CM_INVALIDATERECORD, MPFROMP(&pciL), MPFROM2SHORT(1, 0));
[2]175 pciL = WinSendMsg(hwndCnr,
[551]176 CM_QUERYRECORD,
177 MPFROMP(pciL), MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
[2]178 }
179 }
180 return TRUE;
181}
182
[551]183BOOL Flesh(HWND hwndCnr, PCNRITEM pciParent)
[166]184{
[551]185 PCNRITEM pciL;
[2]186 DIRCNRDATA *dcd;
[551]187 BOOL includefiles = fFilesInTree;
[2]188
[551]189 if (!pciParent || (INT) pciParent == -1 || !hwndCnr)
[2]190 return FALSE;
[551]191 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
192 CM_QUERYRECORD,
193 MPFROMP(pciParent),
194 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
[1651]195 if (!pciL || !*pciL->pszFileName) {
196 if (pciL && (INT) pciL != -1)
197 RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
198 dcd = INSTDATA(hwndCnr);
199 if (dcd && dcd->size != sizeof(DIRCNRDATA))
200 dcd = NULL;
[1662]201 if (driveflags[toupper(*pciParent->pszFileName) - 'A'] & DRIVE_INCLUDEFILES)
[1651]202 includefiles = TRUE;
[1662]203 ProcessDirectory(hwndCnr,
204 pciParent,
205 pciParent->pszFileName,
206 includefiles, // filestoo
207 TRUE, // recurse
208 TRUE, // partial
209 NULL, // stop flag
210 dcd,
211 NULL, // total files
212 NULL); // total bytes
213 if (pciParent && pciParent->pszFileName && !(driveflags[toupper(*pciParent->pszFileName) - 'A'] & DRIVE_RSCANNED))
214 driveflags[toupper(*pciParent->pszFileName) - 'A'] |= DRIVE_RSCANNED;
[1655]215 return TRUE;
[1651]216 }
[1655]217 return FALSE;
[2]218}
219
[551]220BOOL UnFlesh(HWND hwndCnr, PCNRITEM pciParent)
[175]221{
[551]222 BOOL ret = FALSE;
[2]223 PCNRITEM pciL;
224
[175]225 if (!pciParent || !hwndCnr)
[2]226 return FALSE;
[551]227 for (;;) {
228 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
229 CM_QUERYRECORD,
230 MPFROMP(pciParent),
231 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
232 if (pciL && (INT) pciL != -1) {
[2]233 ret = TRUE;
[751]234 RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
[2]235 }
236 else
237 break;
238 }
[551]239 if (ret) {
[2]240 WinSendMsg(hwndCnr,
[551]241 CM_INVALIDATERECORD,
242 MPFROMP(&pciParent),
243 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
[175]244 }
[2]245 return ret;
246}
247
[1482]248#define DDEPTH 64
[2]249
[1471]250/**
251 * Fill in drive tree subtree
252 * @return TRUE if OK, else FALSE
[1551]253 * This only scans the root directory and adds the first level directories
254 * Flesh does a recursive scan and should be used on fast hardware.
[1471]255 */
256
[551]257BOOL Stubby(HWND hwndCnr, PCNRITEM pciParent)
[175]258{
[1409]259 /**
[2]260 * this code is full of workarounds for screwed up LANs.
261 * let's hope all the current LAN programmers fall into
262 * a black hole and make way for people who can get it right...
263 */
264
[1471]265 BOOL ok = FALSE;
[847]266 FILEFINDBUF3 ffb[DDEPTH];
267 PFILEFINDBUF3 pffb;
[551]268 HDIR hDir = HDIR_CREATE;
[761]269 ULONG nm, ulM = 1, total = 0, fl = MUST_HAVE_DIRECTORY;
[551]270 CHAR str[CCHMAXPATH];
271 register INT len;
272 APIRET rc, prc;
273 BOOL isadir = FALSE, isremote = FALSE, includefiles = fFilesInTree;
[1482]274 ULONG ddepth = DDEPTH;
[1299]275 ULONG drvNum;
276 ULONG flags;
[551]277 static BOOL brokenlan = FALSE, isbroken = FALSE;
[2]278
[730]279 if (!pciParent || !*pciParent->pszFileName || !hwndCnr)
[2]280 return FALSE;
281
[730]282 len = strlen(pciParent->pszFileName);
283 memcpy(str, pciParent->pszFileName, len + 1);
[551]284 if (str[len - 1] != '\\')
[2]285 str[len++] = '\\';
286 str[len++] = '*';
287 str[len] = 0;
288
[551]289 if (!isalpha(*str) || str[1] != ':' || str[2] != '\\')
[2]290 MakeFullName(str);
291
[1299]292 drvNum = toupper(*pciParent->pszFileName) - 'A';
293 flags = driveflags[drvNum];
[551]294 if (!isalpha(*str) ||
295 str[1] != ':' ||
[1299]296 str[2] != '\\' || ((flags & DRIVE_IGNORE)))
[1471]297 return FALSE; // Not a directory
[2]298
[1299]299 if (flags & DRIVE_INCLUDEFILES)
[2]300 includefiles = TRUE;
301
[1299]302 if (flags & DRIVE_REMOTE)
[2]303 isremote = TRUE;
304
[551]305 if (isremote) {
306 if (fRemoteBug) {
307 if (brokenlan) {
308 ddepth = (ULONG) - 1;
309 ddepth--;
[2]310 }
[761]311 ulM = 1;
[2]312 }
313 }
[551]314 else if (isbroken)
[2]315 ddepth = 14;
316
[1482]317 if (!fRemoteBug)
318 ulM = (ddepth <= DDEPTH) ? ddepth : 1;
[2]319
320 nm = ulM;
321
322 DosError(FERR_DISABLEHARDERR);
[551]323 if (includefiles)
[2]324 fl = FILE_DIRECTORY;
[847]325 rc = DosFindFirst(str,
326 &hDir,
327 FILE_NORMAL | fl |
328 FILE_READONLY | FILE_ARCHIVED |
329 FILE_SYSTEM | FILE_HIDDEN,
330 &ffb, ulM * sizeof(FILEFINDBUF3), &nm, FIL_STANDARD);
[761]331 if (ulM == 1 && !rc) {
[2]332 do {
333 pffb = &ffb[0];
[551]334 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY) && !brokenlan) {
335 brokenlan = TRUE;
[847]336 ddepth = (ULONG) - 1;
[551]337 ddepth--;
338 if (!NoBrokenNotify) {
339 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
340 HWND_DESKTOP,
341 GetPString(IDS_LANERRORTITLETEXT),
342 GetPString(IDS_LANERRORTEXT));
343 if (prc == MBID_NO) {
344 saymsg(MB_ENTER,
345 HWND_DESKTOP,
346 GetPString(IDS_LANERROR2TITLETEXT),
347 GetPString(IDS_LANERROR2TEXT));
[847]348 NoBrokenNotify = 255;
[1505]349 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]350 &NoBrokenNotify, sizeof(ULONG));
351 }
352 }
353 else {
354 NoBrokenNotify--;
[1505]355 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]356 &NoBrokenNotify, sizeof(ULONG));
357 }
[2]358 }
[515]359 if (*pffb->achName &&
[551]360 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
[515]361 // Skip . and ..
[551]362 (pffb->achName[0] != '.' ||
[515]363 (pffb->achName[1] &&
[551]364 (pffb->achName[1] != '.' || pffb->achName[2])))) {
365 DosFindClose(hDir);
366 isadir = TRUE;
367 goto Interruptus;
[2]368 }
[761]369 nm = 1;
[2]370 DosError(FERR_DISABLEHARDERR);
[1482]371 }
372 while (++total < ddepth && !(rc = (DosFindNext(hDir,
373 &ffb,
374 sizeof(FILEFINDBUF3),
375 &nm))));
376 DosFindClose(hDir);
[1471]377 // If drive B:
[730]378 if (toupper(*pciParent->pszFileName) > 'B' &&
[751]379 (*(pciParent->pszFileName + 1)) == ':' &&
[730]380 (*(pciParent->pszFileName + 2)) == '\\' && !(*(pciParent->pszFileName + 3))) {
[2]381
382 CHAR s[132];
383 sprintf(s,
[551]384 GetPString(IDS_NOSUBDIRSTEXT),
[730]385 total, toupper(*pciParent->pszFileName));
[551]386 if (rc && rc != ERROR_NO_MORE_FILES)
387 sprintf(&s[strlen(s)], GetPString(IDS_SEARCHERRORTEXT), rc, str);
[847]388 else if (ddepth < 16)
[551]389 brokenlan = TRUE;
[2]390 Notify(s);
391 }
392 goto None;
393 }
394
[551]395 if (!rc) {
[2]396 DosFindClose(hDir);
[551]397 if (nm) {
[1353]398 PBYTE fb = (PBYTE)&ffb[0];
[551]399 for (len = 0; len < nm; len++) {
[847]400 pffb = (PFILEFINDBUF3) fb;
[551]401 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY)) {
402 if (!isbroken) {
403 isbroken = TRUE;
404 if (!NoBrokenNotify) {
405 prc = saymsg(MB_YESNO | MB_ICONEXCLAMATION,
406 HWND_DESKTOP,
407 GetPString(IDS_FSDERRORTITLETEXT),
408 GetPString(IDS_FSDERRORTEXT),
[1471]409 isremote ? GetPString(IDS_REMOTETEXT) :
410 GetPString(IDS_LOCALTEXT),
411 *str);
[551]412 if (prc == MBID_NO) {
413 saymsg(MB_ENTER,
414 HWND_DESKTOP,
415 GetPString(IDS_FSDERROR2TITLETEXT),
416 GetPString(IDS_FSDERROR2TEXT));
[847]417 NoBrokenNotify = 255;
[1505]418 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]419 &NoBrokenNotify, sizeof(ULONG));
420 }
421 }
422 else {
423 NoBrokenNotify--;
[1505]424 PrfWriteProfileData(fmprof, FM3Str, "NoBrokenNotify",
[551]425 &NoBrokenNotify, sizeof(ULONG));
426 }
427 }
428 }
429 if (*pffb->achName &&
430 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
[515]431 // Skip . and ..
[551]432 (pffb->achName[0] != '.' || (pffb->achName[1]
433 && (pffb->achName[1] != '.'
434 || pffb->achName[2])))) {
435 isadir = TRUE;
436 break;
437 }
438 fb += pffb->oNextEntryOffset;
[1353]439 } // for
[2]440
[551]441 Interruptus:
[2]442
[551]443 if (isadir) {
[2]444
[1471]445 PCNRITEM pci;
[2]446
[1471]447 if (WinIsWindow((HAB)0, hwndCnr)) {
448 pci = WinSendMsg(hwndCnr,
449 CM_ALLOCRECORD,
450 MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(1));
451 if (!pci) {
452 Win_Error(hwndCnr, HWND_DESKTOP, __FILE__, __LINE__,
453 GetPString(IDS_RECORDALLOCFAILEDTEXT));
454 }
455 else {
456 RECORDINSERT ri;
457 pci->pszFileName = NullStr;
458 pci->pszDisplayName = pci->pszFileName;
459 pci->rc.pszIcon = pci->pszDisplayName;
460 memset(&ri, 0, sizeof(RECORDINSERT));
461 ri.cb = sizeof(RECORDINSERT);
462 ri.pRecordOrder = (PRECORDCORE) CMA_END;
463 ri.pRecordParent = (PRECORDCORE) pciParent;
464 ri.zOrder = (ULONG) CMA_TOP;
465 ri.cRecordsInsert = 1;
466 ri.fInvalidateRecord = TRUE;
467 //DbgMsg(pszSrcFile, __LINE__, "Stubby %p CM_INSERTRECORD \"%s\" %.255s", hwndCnr, pci->pszFileName, pffb->achName); // 18 Dec 08 SHL fixme debug
468 if (!WinSendMsg(hwndCnr,
469 CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
470 DosSleep(50); //05 Aug 07 GKY 100
471 WinSetFocus(HWND_DESKTOP, hwndCnr);
472 if (WinIsWindow((HAB)0, hwndCnr)) {
473 //DbgMsg(pszSrcFile, __LINE__, "Stubby %p CM_INSERTRECORD %s", hwndCnr, pci->pszFileName); // 18 Dec 08 SHL fixme debug
474 if (!WinSendMsg(hwndCnr,
475 CM_INSERTRECORD, MPFROMP(pci), MPFROMP(&ri))) {
476 Win_Error(hwndCnr, HWND_DESKTOP, __FILE__, __LINE__,
477 GetPString(IDS_RECORDINSERTFAILEDTEXT));
478 FreeCnrItem(hwndCnr, pci);
479 }
480 else
481 ok = TRUE;
482 }
483 }
484 else
485 ok = TRUE;
486 }
487 }
[2]488 }
[551]489 else if (toupper(*str) > 'B' && str[1] == ':' && str[2] == '\\' &&
490 !str[3]) {
[2]491
[551]492 CHAR s[162];
[2]493
[551]494 sprintf(s,
495 GetPString(IDS_NOSUBDIRS2TEXT),
496 nm,
[730]497 toupper(*pciParent->pszFileName),
[551]498 (isremote) ? GetPString(IDS_NOSUBDIRS3TEXT) : NullStr);
499 Notify(s);
[2]500 }
501 }
502 }
[551]503 else if (toupper(*str) > 'B' && rc != ERROR_NO_MORE_FILES) {
[2]504 CHAR s[CCHMAXPATH + 80];
[551]505 sprintf(s, GetPString(IDS_SEARCHERRORTEXT), rc, str);
[2]506 Notify(s);
507 }
508
509None:
510
511 DosError(FERR_DISABLEHARDERR);
[1471]512 return ok;
[2]513}
[793]514
[1353]515#pragma alloc_text(FLESH,Flesh,FleshEnv,UnFlesh,Stubby)
Note: See TracBrowser for help on using the repository browser.