source: trunk/dll/flesh.c@ 1358

Last change on this file since 1358 was 1358, checked in by Gregg Young, 17 years ago

Comments for CS 1354/55

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