source: trunk/dll/wrappers.c@ 1006

Last change on this file since 1006 was 1006, checked in by Steven Levine, 17 years ago

Tweak xmalloc to use callers file/line when FORTIFIED

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.5 KB
Line 
1
2/***********************************************************************
3
4 $Id: wrappers.c 1006 2008-05-06 03:20:07Z stevenhl $
5
6 Wrappers with error checking
7
8 Copyright (c) 2006 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 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)
330{
331 if (pv && pv != NullStr)
332 free(pv);
333}
334
335//== xmalloc() malloc with error checking ==
336
337PVOID xmalloc(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
338{
339# ifdef FORTIFY
340 PVOID pv = Fortify_malloc(cBytes, pszSrcFile, uiLineNumber);
341# else
342 PVOID pv = malloc(cBytes);
343# endif
344
345 if (!pv)
346 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
347
348 return pv;
349}
350
351//== xmallocz() malloc and zero with error checking ==
352
353PVOID xmallocz(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
354{
355 PVOID pv = malloc(cBytes);
356
357 if (!pv)
358 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
359 else
360 memset(pv, 0, cBytes);
361
362 return pv;
363}
364
365//== xrealloc() realloc with error checking ==
366
367PVOID xrealloc(PVOID pvIn, size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
368{
369 if (pvIn != NullStr) {
370 PVOID pv = realloc(pvIn, cBytes);
371
372 if (!pv && cBytes)
373 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
374
375 return pv;
376 }
377 else
378 return xmalloc(cBytes, pszSrcFile, uiLineNumber);
379}
380
381//== xstrdup() strdup with error checking ==
382
383PVOID xstrdup(PCSZ pszIn, PCSZ pszSrcFile, UINT uiLineNumber)
384{
385 PSZ psz = strdup(pszIn);
386
387 if (!psz)
388 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
389
390 return psz;
391}
392
393#pragma alloc_text(WRAPPERS1,xfree,xfopen,xfsopen,xmalloc,xrealloc, xstrdup)
394#pragma alloc_text(WRAPPERS2,xDosSetPathInfo,xDosFindFirst,xDosFindNext)
Note: See TracBrowser for help on using the repository browser.