source: trunk/dll/flesh.c@ 1844

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

Fixed trap in Stubby Ticket [534]

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