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
RevLine 
[145]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
[907]9 Copyright (c) 2005, 2008 Steven H. Levine
[145]10
11 24 May 05 SHL Rework Win_Error usage
[166]12 25 May 05 SHL Rework for ProcessDirectory
[284]13 28 May 05 SHL Clean while reading code
14 24 Oct 05 SHL Delete obsolete code
[340]15 22 Jul 06 SHL Check more run time errors
[515]16 19 Oct 06 SHL Stubby - correct . and .. detect
[574]17 22 Mar 07 GKY Use QWL_USER
[751]18 01 Aug 07 SHL Sync with CNRITEM mods
[775]19 06 Aug 07 GKY Reduce DosSleep times (ticket 148)
[793]20 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
[985]21 29 Feb 08 GKY Use xfree where appropriate
[1299]22 24 Nov 08 GKY remove redundant code and minor speed up of Stubby
[1358]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.
[145]26
27***********************************************************************/
28
[907]29#include <stdlib.h>
30#include <string.h>
31#include <ctype.h>
32
[2]33#define INCL_DOS
34#define INCL_DOSERRORS
35#define INCL_WIN
[907]36#define INCL_LONGLONG // dircnrs.h
[2]37
[1177]38#include "fm3dll.h"
[1207]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)
[907]44#include "fm3str.h"
45#include "filldir.h" // FileAttrToString...
46#include "errutil.h" // Dos_Error...
47#include "strutil.h" // GetPString
[1155]48#include "flesh.h"
49#include "valid.h" // IsValidDir
50#include "misc.h" // LoadLibPath
[1177]51#include "findrec.h" // FindCnrRecord
52#include "notify.h" // Notify
53#include "wrappers.h" // xfree
[1354]54#include "excputil.h" // xbeginthread
[2]55
[1207]56// Data definitions
[2]57#pragma data_seg(DATA1)
[340]58
59static PSZ pszSrcFile = __FILE__;
60
[1207]61#pragma data_seg(GLOBAL1)
62ULONG NoBrokenNotify;
63BOOL fFilesInTree;
64
[551]65BOOL FleshEnv(HWND hwndCnr, PCNRITEM pciParent)
[175]66{
[551]67 PCNRITEM pciL;
[2]68 DIRCNRDATA *dcd;
[551]69 CHAR path[CCHMAXPATH + 12],
70 fullpath[CCHMAXPATH + 12], *env, *p, *pp, *var = NULL;
[2]71
[551]72 if (!pciParent || (INT) pciParent == -1 || !hwndCnr)
[2]73 return FALSE;
[574]74 dcd = (DIRCNRDATA *) WinQueryWindowPtr(hwndCnr, QWL_USER);
[551]75 if (!dcd)
[2]76 return FALSE;
77
[730]78 strcpy(path, pciParent->pszFileName + 1);
[551]79 if (stricmp(path, GetPString(IDS_ENVVARSTEXT) + 1))
80 UnFlesh(hwndCnr, pciParent);
81 if (*path) {
[2]82 path[strlen(path) - 1] = 0;
[551]83 if (!stricmp(path, "LIBPATH")) {
84 var = xmalloc(65536, pszSrcFile, __LINE__);
85 if (var)
86 LoadLibPath(var, 65536);
[2]87 env = var;
88 }
89 else
90 env = getenv(path);
[551]91 if (env && *env) {
[2]92 p = env;
[551]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) {
[2]123
[551]124 RECORDINSERT ri;
[2]125
[551]126 pciL = WinSendMsg(hwndCnr,
127 CM_ALLOCRECORD,
[751]128 MPFROMLONG(EXTRA_RECORD_BYTES),
[551]129 MPFROMLONG(1));
130 if (pciL) {
[730]131 pciL->pszFileName = xstrdup(fullpath, pszSrcFile, __LINE__);
[751]132 pciL->rc.pszIcon = pciL->pszFileName;
[551]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;
[751]141 pciL->pszDispAttr = FileAttrToString(pciL->attrFile);
[551]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)))
[751]151 FreeCnrItem(hwndCnr, pciL);
[551]152 }
153 }
154 }
155 }
[2]156 }
157 }
[1009]158 xfree(var, pszSrcFile, __LINE__);
[551]159 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
160 CM_QUERYRECORD,
161 MPFROMP(pciParent),
162 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
163 while (pciL && (INT) pciL != -1) {
[2]164 pciL->flags |= (RECFLAGS_NODRAG | RECFLAGS_UNDERENV);
165 WinSendMsg(hwndCnr,
[551]166 CM_INVALIDATERECORD, MPFROMP(&pciL), MPFROM2SHORT(1, 0));
[2]167 pciL = WinSendMsg(hwndCnr,
[551]168 CM_QUERYRECORD,
169 MPFROMP(pciL), MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
[2]170 }
171 }
172 return TRUE;
173}
174
[551]175BOOL Flesh(HWND hwndCnr, PCNRITEM pciParent)
[166]176{
[551]177 PCNRITEM pciL;
[2]178 DIRCNRDATA *dcd;
[551]179 BOOL includefiles = fFilesInTree;
[2]180
[551]181 if (!pciParent || (INT) pciParent == -1 || !hwndCnr)
[2]182 return FALSE;
[551]183 pciL = (PCNRITEM) WinSendMsg(hwndCnr,
184 CM_QUERYRECORD,
185 MPFROMP(pciParent),
186 MPFROM2SHORT(CMA_FIRSTCHILD, CMA_ITEMORDER));
[730]187 if (!pciL || !*pciL->pszFileName) {
[751]188 if (pciL && (INT) pciL != -1)
189 RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
[2]190 dcd = INSTDATA(hwndCnr);
[166]191 if (dcd && dcd->size != sizeof(DIRCNRDATA))
[2]192 dcd = NULL;
[730]193 if (driveflags[toupper(*pciParent->pszFileName) - 'A'] &
[551]194 DRIVE_INCLUDEFILES)
[2]195 includefiles = TRUE;
[1354]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 }
[2]234 }
[1354]235 driveflags[*pciParent->pszFileName - 'A'] |= DRIVE_RSCANNED;
[2]236 return TRUE;
237}
238
[551]239BOOL UnFlesh(HWND hwndCnr, PCNRITEM pciParent)
[175]240{
[551]241 BOOL ret = FALSE;
[2]242 PCNRITEM pciL;
243
[175]244 if (!pciParent || !hwndCnr)
[2]245 return FALSE;
[551]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) {
[2]252 ret = TRUE;
[751]253 RemoveCnrItems(hwndCnr, pciL, 1, CMA_FREE);
[2]254 }
255 else
256 break;
257 }
[551]258 if (ret) {
[2]259 WinSendMsg(hwndCnr,
[551]260 CM_INVALIDATERECORD,
261 MPFROMP(&pciParent),
262 MPFROM2SHORT(1, CMA_ERASE | CMA_REPOSITION));
[175]263 }
[2]264 return ret;
265}
266
267#define DDEPTH 16
268
[551]269BOOL Stubby(HWND hwndCnr, PCNRITEM pciParent)
[175]270{
[2]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
[551]277 BOOL ret = FALSE;
[847]278 FILEFINDBUF3 ffb[DDEPTH];
279 PFILEFINDBUF3 pffb;
[551]280 HDIR hDir = HDIR_CREATE;
[761]281 ULONG nm, ulM = 1, total = 0, fl = MUST_HAVE_DIRECTORY;
[551]282 CHAR str[CCHMAXPATH];
283 register INT len;
284 APIRET rc, prc;
285 BOOL isadir = FALSE, isremote = FALSE, includefiles = fFilesInTree;
[761]286 ULONG ddepth = 3;
[1299]287 ULONG drvNum;
288 ULONG flags;
[551]289 static BOOL brokenlan = FALSE, isbroken = FALSE;
[2]290
[730]291 if (!pciParent || !*pciParent->pszFileName || !hwndCnr)
[2]292 return FALSE;
293
[730]294 len = strlen(pciParent->pszFileName);
295 memcpy(str, pciParent->pszFileName, len + 1);
[551]296 if (str[len - 1] != '\\')
[2]297 str[len++] = '\\';
298 str[len++] = '*';
299 str[len] = 0;
300
[551]301 if (!isalpha(*str) || str[1] != ':' || str[2] != '\\')
[2]302 MakeFullName(str);
303
[1299]304 drvNum = toupper(*pciParent->pszFileName) - 'A';
305 flags = driveflags[drvNum];
[551]306 if (!isalpha(*str) ||
307 str[1] != ':' ||
[1299]308 str[2] != '\\' || ((flags & DRIVE_IGNORE)))
[2]309 return FALSE;
310
[1299]311 //if (isalpha(*str) && // redundant check GKY 11/24/08
312 if (flags & DRIVE_INCLUDEFILES)
[2]313 includefiles = TRUE;
314
[1353]315#if 0
316 if (!isalpha(*str) || // redundant check GKY 11/24/08
[551]317 str[1] != ':' ||
[1353]318 str[2] != '\\' ||
319#endif
[1299]320 if (flags & DRIVE_REMOTE)
[2]321 isremote = TRUE;
322
[551]323 if (isremote) {
[2]324 ddepth = 14;
[551]325 if (fRemoteBug) {
326 if (brokenlan) {
327 ddepth = (ULONG) - 1;
328 ddepth--;
[2]329 }
[761]330 ulM = 1;
[2]331 }
332 }
[551]333 else if (isbroken)
[2]334 ddepth = 14;
335
[551]336 if (!isremote || !fRemoteBug)
[847]337 ulM = (ddepth < 16) ? ddepth : 1;
[2]338
339 nm = ulM;
340
341 DosError(FERR_DISABLEHARDERR);
[551]342 if (includefiles)
[2]343 fl = FILE_DIRECTORY;
[847]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);
[761]350 if (ulM == 1 && !rc) {
[2]351 do {
352 pffb = &ffb[0];
[551]353 if (!includefiles && !(pffb->attrFile & FILE_DIRECTORY) && !brokenlan) {
354 brokenlan = TRUE;
[847]355 ddepth = (ULONG) - 1;
[551]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));
[847]367 NoBrokenNotify = 255;
[551]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 }
[2]381 }
[515]382 if (*pffb->achName &&
[551]383 (includefiles || (pffb->attrFile & FILE_DIRECTORY)) &&
[515]384 // Skip . and ..
[551]385 (pffb->achName[0] != '.' ||
[515]386 (pffb->achName[1] &&
[551]387 (pffb->achName[1] != '.' || pffb->achName[2])))) {
388 DosFindClose(hDir);
389 isadir = TRUE;
390 goto Interruptus;
[2]391 }
[761]392 nm = 1;
[2]393 DosError(FERR_DISABLEHARDERR);
[847]394 } while (++total < ddepth && !(rc = (DosFindNext(hDir,
395 &ffb,
396 sizeof(FILEFINDBUF3),
397 &nm))));
[2]398 DosFindClose(hDir);
[730]399 if (toupper(*pciParent->pszFileName) > 'B' &&
[751]400 (*(pciParent->pszFileName + 1)) == ':' &&
[730]401 (*(pciParent->pszFileName + 2)) == '\\' && !(*(pciParent->pszFileName + 3))) {
[2]402
403 CHAR s[132];
404 sprintf(s,
[551]405 GetPString(IDS_NOSUBDIRSTEXT),
[730]406 total, toupper(*pciParent->pszFileName));
[551]407 if (rc && rc != ERROR_NO_MORE_FILES)
408 sprintf(&s[strlen(s)], GetPString(IDS_SEARCHERRORTEXT), rc, str);
[847]409 else if (ddepth < 16)
[551]410 brokenlan = TRUE;
[2]411 Notify(s);
412 }
413 goto None;
414 }
415
[551]416 if (!rc) {
[2]417 DosFindClose(hDir);
[551]418 if (nm) {
[1353]419 PBYTE fb = (PBYTE)&ffb[0];
[551]420 for (len = 0; len < nm; len++) {
[847]421 pffb = (PFILEFINDBUF3) fb;
[551]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));
[847]438 NoBrokenNotify = 255;
[551]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)) &&
[515]456 // Skip . and ..
[551]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;
[1353]464 } // for
[2]465
[551]466 Interruptus:
[2]467
[551]468 if (isadir) {
[2]469
[1299]470 PCNRITEM pci;
[2]471
[1299]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;
[1353]490 ri.cRecordsInsert = 1;
[1299]491 ri.fInvalidateRecord = TRUE;
[1354]492 //DbgMsg(pszSrcFile, __LINE__, "Stubby %p CM_INSERTRECORD \"%s\" %.255s", hwndCnr, pci->pszFileName, pffb->achName); // 18 Dec 08 SHL fixme debug
[1299]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)) {
[1354]498 //DbgMsg(pszSrcFile, __LINE__, "Stubby %p CM_INSERTRECORD %s", hwndCnr, pci->pszFileName); // 18 Dec 08 SHL fixme debug
[1299]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 }
[2]513 }
[551]514 else if (toupper(*str) > 'B' && str[1] == ':' && str[2] == '\\' &&
515 !str[3]) {
[2]516
[551]517 CHAR s[162];
[2]518
[551]519 sprintf(s,
520 GetPString(IDS_NOSUBDIRS2TEXT),
521 nm,
[730]522 toupper(*pciParent->pszFileName),
[551]523 (isremote) ? GetPString(IDS_NOSUBDIRS3TEXT) : NullStr);
524 Notify(s);
[2]525 }
526 }
527 }
[551]528 else if (toupper(*str) > 'B' && rc != ERROR_NO_MORE_FILES) {
[2]529
530 CHAR s[CCHMAXPATH + 80];
531
[551]532 sprintf(s, GetPString(IDS_SEARCHERRORTEXT), rc, str);
[2]533 Notify(s);
534 }
535
536None:
537
538 DosError(FERR_DISABLEHARDERR);
539 return ret;
540}
[793]541
[1353]542#pragma alloc_text(FLESH,Flesh,FleshEnv,UnFlesh,Stubby)
Note: See TracBrowser for help on using the repository browser.