source: trunk/dll/flesh.c@ 1330

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

Scan each drive on separate thread (added StubbyScanThread) to speed treecnr scans

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