source: trunk/dll/flesh.c@ 1832

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

Presumptive fix for Stubby trap which fits what appeared to be happening in the .trp file and follows the pattern of 2 other recent traps. Ticket 534

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