source: trunk/dll/wrappers.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: 12.3 KB
Line 
1
2/***********************************************************************
3
4 $Id: wrappers.c 1354 2008-12-25 22:43:34Z gyoung $
5
6 Wrappers with error checking
7
8 Copyright (c) 2006, 2008 Steven H.Levine
9
10 22 Jul 06 SHL Baseline
11 29 Jul 06 SHL Add xgets_stripped
12 18 Aug 06 SHL Correct Runtime_Error line number report
13 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
14 01 Sep 07 GKY Add xDosSetPathInfo to fix case where FS3 buffer crosses 64k boundry
15 06 Oct 07 SHL Add xDos...() wrappers to support systems wo/large file support (Gregg, Steven)
16 05 May 08 SHL Add FORTIFY support
17
18***********************************************************************/
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <ctype.h>
24
25#define INCL_WIN
26#define INCL_DOS
27#define INCL_DOSERRORS
28#define INCL_LONGLONG
29#include <os2.h>
30
31#include "fm3dll.h"
32#include "init.h" // Data declaration(s)
33#include "wrappers.h"
34#include "fm3str.h"
35#include "errutil.h" // Dos_Error...
36#include "strutil.h" // GetPString
37#include "command.h"
38#include "tools.h"
39#include "avl.h"
40#include "strips.h" // bstrip
41
42#include "fortify.h" // GetPString
43#include "info.h" // driveflags
44#include "notebook.h" // fVerify
45
46// Data definitions
47static PSZ pszSrcFile = __FILE__;
48
49#pragma data_seg(GLOBAL1)
50BOOL fNoLargeFileSupport;
51
52APIRET xDosFindFirst(PSZ pszFileSpec,
53 PHDIR phdir,
54 ULONG flAttribute,
55 PVOID pfindbuf,
56 ULONG cbBuf,
57 PULONG pcFileNames,
58 ULONG ulInfoLevel)
59{
60 APIRET rc;
61 if (fNoLargeFileSupport) {
62 switch (ulInfoLevel) {
63 case FIL_STANDARDL:
64 {
65 FILEFINDBUF3 ffb3;
66 ulInfoLevel = FIL_STANDARD;
67 *pcFileNames = 1; // fixme to support larger counts
68 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, &ffb3, sizeof(ffb3),
69 pcFileNames, ulInfoLevel);
70 if (!rc) {
71 *(PFILEFINDBUF3)pfindbuf = ffb3; // Copy aligned data
72 ((PFILEFINDBUF3L)pfindbuf)->cbFile = ffb3.cbFile; // Copy unaligned data
73 ((PFILEFINDBUF3L)pfindbuf)->cbFileAlloc = ffb3.cbFileAlloc;
74 ((PFILEFINDBUF3L)pfindbuf)->attrFile = ffb3.attrFile;
75 ((PFILEFINDBUF3L)pfindbuf)->cchName = ffb3.cchName;
76 memcpy(((PFILEFINDBUF3L)pfindbuf)->achName, ffb3.achName, ffb3.cchName + 1);
77 }
78 }
79 break;
80 case FIL_QUERYEASIZEL:
81 {
82 FILEFINDBUF4 ffb4;
83 *pcFileNames = 1; // fixme to support larger counts
84 ulInfoLevel = FIL_QUERYEASIZE;
85 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, &ffb4, sizeof(ffb4),
86 pcFileNames, ulInfoLevel);
87 if (!rc) {
88 *(PFILEFINDBUF4)pfindbuf = ffb4; // Copy aligned data
89 ((PFILEFINDBUF4L)pfindbuf)->cbFile = ffb4.cbFile; // Copy unaligned data
90 ((PFILEFINDBUF4L)pfindbuf)->cbFileAlloc = ffb4.cbFileAlloc;
91 ((PFILEFINDBUF4L)pfindbuf)->attrFile = ffb4.attrFile;
92 ((PFILEFINDBUF4L)pfindbuf)->cbList = ffb4.cbList;
93 ((PFILEFINDBUF4L)pfindbuf)->cchName = ffb4.cchName;
94 memcpy(((PFILEFINDBUF4L)pfindbuf)->achName, ffb4.achName, ffb4.cchName + 1);
95 }
96 }
97 break;
98 default:
99 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
100 rc = ERROR_INVALID_PARAMETER;
101 } // switch
102 }
103 else
104 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, pfindbuf, cbBuf,
105 pcFileNames, ulInfoLevel);
106 return rc;
107}
108
109APIRET xDosFindNext(HDIR hDir,
110 PVOID pfindbuf,
111 ULONG cbfindbuf,
112 PULONG pcFileNames,
113 ULONG ulInfoLevel)
114{
115 APIRET rc;
116 if (fNoLargeFileSupport) {
117 switch (ulInfoLevel) {
118 case FIL_STANDARDL:
119 {
120 FILEFINDBUF3 ffb3;
121 *pcFileNames = 1; // fixme to support larger counts
122 rc = DosFindNext(hDir, &ffb3, sizeof(ffb3), pcFileNames);
123 if (!rc) {
124 *(PFILEFINDBUF3)pfindbuf = ffb3; // Copy aligned data
125 ((PFILEFINDBUF3L)pfindbuf)->cbFile = ffb3.cbFile; // Copy unaligned data
126 ((PFILEFINDBUF3L)pfindbuf)->cbFileAlloc = ffb3.cbFileAlloc;
127 ((PFILEFINDBUF3L)pfindbuf)->attrFile = ffb3.attrFile;
128 ((PFILEFINDBUF3L)pfindbuf)->cchName = ffb3.cchName;
129 memcpy(((PFILEFINDBUF3L)pfindbuf)->achName, ffb3.achName, ffb3.cchName + 1);
130 }
131 }
132 break;
133 case FIL_QUERYEASIZEL:
134 {
135 FILEFINDBUF4 ffb4;
136 *pcFileNames = 1; // fixme to support larger counts
137 rc = DosFindNext(hDir, &ffb4, sizeof(ffb4), pcFileNames);
138 if (!rc) {
139 *(PFILEFINDBUF4)pfindbuf = ffb4; // Copy aligned data
140 ((PFILEFINDBUF4L)pfindbuf)->cbFile = ffb4.cbFile; // Copy unaligned data
141 ((PFILEFINDBUF4L)pfindbuf)->cbFileAlloc = ffb4.cbFileAlloc;
142 ((PFILEFINDBUF4L)pfindbuf)->attrFile = ffb4.attrFile;
143 ((PFILEFINDBUF4L)pfindbuf)->cbList = ffb4.cbList;
144 ((PFILEFINDBUF4L)pfindbuf)->cchName = ffb4.cchName;
145 memcpy(((PFILEFINDBUF4L)pfindbuf)->achName, ffb4.achName, ffb4.cchName + 1);
146 }
147 }
148 break;
149 default:
150 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
151 rc = ERROR_INVALID_PARAMETER;
152 } // switch
153 }
154 else
155 rc = DosFindNext(hDir, pfindbuf, cbfindbuf, pcFileNames);
156
157 return rc;
158}
159
160/**
161 * DosQueryPathInfo wrapper
162 * Translate request for systems without large file support
163 */
164
165APIRET xDosQueryPathInfo (PSZ pszPathName, ULONG ulInfoLevel, PVOID pInfoBuf, ULONG cbInfoBuf)
166{
167 FILESTATUS3 fs3;
168 FILESTATUS4 fs4;
169 APIRET rc;
170
171 if (fNoLargeFileSupport) {
172 switch (ulInfoLevel) {
173 case FIL_STANDARDL:
174 rc = DosQueryPathInfo(pszPathName, ulInfoLevel, &fs3, sizeof(fs3));
175 if (!rc) {
176 *(PFILESTATUS3)pInfoBuf = fs3; // Copy aligned data
177 ((PFILESTATUS3L)pInfoBuf)->cbFile = fs3.cbFile; // Copy unaligned data
178 ((PFILESTATUS3L)pInfoBuf)->cbFileAlloc = fs3.cbFileAlloc;
179 ((PFILESTATUS3L)pInfoBuf)->attrFile = fs3.attrFile;
180 }
181 break;
182 case FIL_QUERYEASIZEL:
183 rc = DosQueryPathInfo(pszPathName, ulInfoLevel, &fs4, sizeof(fs4));
184 if (!rc) {
185 *(PFILESTATUS4)pInfoBuf = fs4; // Copy aligned data
186 ((PFILESTATUS4L)pInfoBuf)->cbFile = fs4.cbFile; // Copy unaligned data
187 ((PFILESTATUS4L)pInfoBuf)->cbFileAlloc = fs4.cbFileAlloc;
188 ((PFILESTATUS4L)pInfoBuf)->attrFile = fs4.attrFile;
189 ((PFILESTATUS4L)pInfoBuf)->cbList = fs4.cbList;
190 }
191 break;
192 default:
193 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
194 rc = ERROR_INVALID_PARAMETER;
195 } // switch
196 }
197 else
198 DosQueryPathInfo (pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf);
199
200 return rc;
201}
202
203/**
204 * Wrap DosSetPathInfo to avoid spurious ERROR_INVALID_NAME returns and
205 * support systems without large file support
206 *
207 * Some kernels to do not correctly handle FILESTATUS3 and PEAOP2 buffers
208 * that cross a 64K boundary.
209 * When this occurs, they return ERROR_INVALID_NAME.
210 * This code works around the problem because if the passed buffer crosses
211 * the boundary the alternate buffer will not because both are on the stack
212 * and we don't put enough additional data on the stack for this to occur.
213 * It is caller's responsitibility to report errors
214 * @param pInfoBuf pointer to FILESTATUS3(L) or EAOP2 buffer
215 * @param ulInfoLevel FIL_STANDARD(L) or FIL_QUERYEASIZE
216 * @returns Same as DosSetPathInfo
217 */
218
219APIRET xDosSetPathInfo(PSZ pszPathName,
220 ULONG ulInfoLevel,
221 PVOID pInfoBuf,
222 ULONG cbInfoBuf,
223 ULONG flOptions)
224{
225 FILESTATUS3 fs3;
226 FILESTATUS3 fs3_a;
227 FILESTATUS3L fs3l;
228 EAOP2 eaop2;
229 APIRET rc;
230 BOOL crosses = ((ULONG)pInfoBuf ^
231 ((ULONG)pInfoBuf + cbInfoBuf - 1)) & ~0xffff;
232 BOOL fResetVerify = FALSE;
233
234 if (fVerify && driveflags[toupper(*pszPathName) - 'A'] & DRIVE_WRITEVERIFYOFF) {
235 DosSetVerify(FALSE);
236 fResetVerify = TRUE;
237 }
238 switch (ulInfoLevel) {
239 case FIL_STANDARD:
240 if (crosses) {
241 fs3 = *(PFILESTATUS3)pInfoBuf; // Copy to buffer that does not cross 64K boundary
242 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3, cbInfoBuf, flOptions);
243 }
244 else
245 rc = DosSetPathInfo(pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf, flOptions);
246 break;
247
248 case FIL_STANDARDL:
249 if (fNoLargeFileSupport) {
250 ulInfoLevel = FIL_STANDARD;
251 fs3 = *(PFILESTATUS3)pInfoBuf; // Copy aligned data
252 // Check size too big to handle
253 if (((PFILESTATUS3L)pInfoBuf)->cbFile >= 1LL << 32 ||
254 ((PFILESTATUS3L)pInfoBuf)->cbFileAlloc >= 2LL << 32)
255 {
256 rc = ERROR_INVALID_PARAMETER;
257 }
258 else {
259 fs3.cbFile = ((PFILESTATUS3L)pInfoBuf)->cbFile; // Copy unaligned data
260 fs3.cbFileAlloc = ((PFILESTATUS3L)pInfoBuf)->cbFileAlloc;
261 fs3.attrFile = ((PFILESTATUS3L)pInfoBuf)->attrFile;
262 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3, sizeof(fs3), flOptions);
263 }
264 if (rc == ERROR_INVALID_NAME) {
265 // fixme to validate counts?
266 fs3_a = fs3; // Copy to buffer that does not cross
267 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3_a, sizeof(fs3_a), flOptions);
268 }
269 }
270 else {
271 rc = DosSetPathInfo(pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf, flOptions);
272 if (rc == ERROR_INVALID_NAME) {
273 fs3l = *(PFILESTATUS3L)pInfoBuf; // Copy to buffer that does not cross
274 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3l, sizeof(fs3l), flOptions);
275 }
276 }
277 break;
278 case FIL_QUERYEASIZE:
279 rc = DosSetPathInfo(pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf, flOptions);
280 if (rc == ERROR_INVALID_NAME) {
281 // fixme to validate counts?
282 eaop2 = *(PEAOP2)pInfoBuf; // Copy to buffer that does not cross
283 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &eaop2, sizeof(eaop2), flOptions);
284 }
285 break;
286 default:
287 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
288 rc = ERROR_INVALID_PARAMETER;
289 } // switch
290 if (fResetVerify) {
291 DosSetVerify(fVerify);
292 fResetVerify = FALSE;
293 }
294 return rc;
295}
296
297PSZ xfgets(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
298 UINT uiLineNumber)
299{
300 PSZ psz = fgets(pszBuf, cMaxBytes, fp);
301
302 if (!psz) {
303 if (ferror(fp))
304 Runtime_Error(pszSrcFile, uiLineNumber, "fgets");
305 }
306 else {
307 size_t c = strlen(psz);
308
309 if (c + 1 > cMaxBytes)
310 Runtime_Error(pszSrcFile, uiLineNumber, "buffer overflow");
311 else if (!c || (psz[c - 1] != '\n' && psz[c - 1] != '\r'))
312 Runtime_Error(pszSrcFile, uiLineNumber, "missing EOL");
313 }
314 return psz;
315}
316
317PSZ xfgets_bstripcr(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
318 UINT uiLineNumber)
319{
320 PSZ psz = xfgets(pszBuf, cMaxBytes, fp, pszSrcFile, uiLineNumber);
321
322 if (psz)
323 bstripcr(psz);
324 return psz;
325}
326
327FILE *xfopen(PCSZ pszFileName, PCSZ pszMode, PCSZ pszSrcFile,
328 UINT uiLineNumber)
329{
330 FILE *fp = fopen(pszFileName, pszMode);
331
332 if (!fp)
333 Runtime_Error(pszSrcFile, uiLineNumber, "fopen");
334 return fp;
335}
336
337FILE *xfsopen(PCSZ pszFileName, PCSZ pszMode, INT fSharemode, PCSZ pszSrcFile,
338 UINT uiLineNumber)
339{
340 FILE *fp = _fsopen((PSZ) pszFileName, (PSZ) pszMode, fSharemode);
341
342 if (!fp)
343 Runtime_Error(pszSrcFile, uiLineNumber, "_fsopen");
344 return fp;
345}
346
347//== xfree - safe free ==
348
349VOID xfree(PVOID pv, PCSZ pszSrcFile, UINT uiLineNumber)
350{
351 if (pv && pv != NullStr) {
352# ifdef FORTIFY
353 Fortify_free(pv, pszSrcFile, uiLineNumber);
354# else
355 free(pv);
356# endif
357
358 }
359}
360
361//== xmalloc() malloc with error checking ==
362
363PVOID xmalloc(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
364{
365# ifdef FORTIFY
366 PVOID pv = Fortify_malloc(cBytes, pszSrcFile, uiLineNumber);
367# else
368 PVOID pv = malloc(cBytes);
369# endif
370
371 if (!pv)
372 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
373
374 return pv;
375}
376
377//== xmallocz() malloc and zero with error checking ==
378
379PVOID xmallocz(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
380{
381 PVOID pv = xmalloc(cBytes, pszSrcFile, uiLineNumber);
382
383 if (pv)
384 memset(pv, 0, cBytes);
385
386 return pv;
387}
388
389//== xrealloc() realloc with error checking ==
390
391PVOID xrealloc(PVOID pvIn, size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
392{
393 if (pvIn != NullStr) {
394# ifdef FORTIFY
395 PVOID pv = Fortify_realloc(pvIn, cBytes, pszSrcFile, uiLineNumber);
396# else
397 PVOID pv = realloc(pvIn, cBytes);
398# endif
399
400 if (!pv && cBytes)
401 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
402
403 return pv;
404 }
405 else
406 return xmalloc(cBytes, pszSrcFile, uiLineNumber);
407}
408
409//== xstrdup() strdup with error checking ==
410
411PVOID xstrdup(PCSZ pszIn, PCSZ pszSrcFile, UINT uiLineNumber)
412{
413# ifdef FORTIFY
414 PSZ psz = Fortify_strdup(pszIn, pszSrcFile, uiLineNumber);
415# else
416 PSZ psz = strdup(pszIn);
417# endif
418
419 if (!psz)
420 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
421
422 return psz;
423}
424
425
426#pragma alloc_text(WRAPPERS1,xfree,xfopen,xfsopen,xmalloc,xrealloc,xstrdup)
427#pragma alloc_text(WRAPPERS2,xDosSetPathInfo,xDosFindFirst,xDosFindNext)
Note: See TracBrowser for help on using the repository browser.