source: trunk/dll/flesh.c@ 908

Last change on this file since 908 was 907, checked in by Steven Levine, 18 years ago

Avoid out of memory traps in Compare Directories
Rework Compare Directories progress display for 2 second update rate
Start refactoring to reduce dependence on fm3dll.h
Add timer services (IsITimerExpired etc.)

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