source: trunk/dll/wrappers.c@ 1215

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

Ticket 187: Move data declarations/definitions out of fm3dll.h

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