source: trunk/dll/flesh.c@ 1354

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

Added driveflags to over ride write verify for USB removable drives that fail when it is on (Ticket 323); A flag to prevent directory name from being broadcast to drives in the tree cnr prior to a recursive scan of the drive (causes dbl directory names Ticket 321) Add option for multithreaded recursive scan of user selected drives at startup (Ticket 322).

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