source: trunk/dll/wrappers.c@ 1182

Last change on this file since 1182 was 1182, checked in by John Small, 17 years ago

Ticket 187: Draft 2: Move remaining function declarations

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