source: trunk/dll/wrappers.c@ 1011

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

Fortify updates to get it working everywhere

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