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
RevLine 
[395]1
2/***********************************************************************
3
4 $Id: wrappers.c 1215 2008-09-13 06:54:03Z jbs $
5
6 Wrappers with error checking
7
[1008]8 Copyright (c) 2006, 2008 Steven H.Levine
[395]9
10 22 Jul 06 SHL Baseline
[400]11 29 Jul 06 SHL Add xgets_stripped
[438]12 18 Aug 06 SHL Correct Runtime_Error line number report
[794]13 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
[826]14 01 Sep 07 GKY Add xDosSetPathInfo to fix case where FS3 buffer crosses 64k boundry
[850]15 06 Oct 07 SHL Add xDos...() wrappers to support systems wo/large file support (Gregg, Steven)
[1008]16 05 May 08 SHL Add FORTIFY support
[395]17
18***********************************************************************/
19
[907]20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
[395]24#define INCL_WIN
[826]25#define INCL_DOS
26#define INCL_DOSERRORS
[841]27#define INCL_LONGLONG
[395]28#include <os2.h>
29
30#include "fm3dll.h"
[1215]31#include "init.h" // Data declaration(s)
[1182]32#include "wrappers.h"
[395]33#include "fm3str.h"
[907]34#include "errutil.h" // Dos_Error...
35#include "strutil.h" // GetPString
[1032]36#include "command.h"
37#include "tools.h"
38#include "avl.h"
[1182]39#include "strips.h" // bstrip
[395]40
[1005]41#include "fortify.h" // GetPString
42
[1215]43// Data definitions
[827]44static PSZ pszSrcFile = __FILE__;
45
[1215]46#pragma data_seg(GLOBAL1)
47BOOL fNoLargeFileSupport;
48
[850]49APIRET xDosFindFirst(PSZ pszFileSpec,
50 PHDIR phdir,
51 ULONG flAttribute,
52 PVOID pfindbuf,
53 ULONG cbBuf,
54 PULONG pcFileNames,
55 ULONG ulInfoLevel)
[838]56{
[850]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 }
[849]76 break;
[850]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 }
[849]94 break;
95 default:
[850]96 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
97 rc = ERROR_INVALID_PARAMETER;
98 } // switch
99 }
100 else
[838]101 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, pfindbuf, cbBuf,
[850]102 pcFileNames, ulInfoLevel);
103 return rc;
[838]104}
105
[850]106APIRET xDosFindNext(HDIR hDir,
107 PVOID pfindbuf,
108 ULONG cbfindbuf,
109 PULONG pcFileNames,
110 ULONG ulInfoLevel)
[838]111{
112 APIRET rc;
[849]113 if (fNoLargeFileSupport) {
[850]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
[849]150 }
151 else
[850]152 rc = DosFindNext(hDir, pfindbuf, cbfindbuf, pcFileNames);
[838]153
154 return rc;
155}
156
[827]157/**
[850]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 *
[827]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
[847]211 * @param pInfoBuf pointer to FILESTATUS3(L) or EAOP2 buffer
212 * @param ulInfoLevel FIL_STANDARD(L) or FIL_QUERYEASIZE
[827]213 * @returns Same as DosSetPathInfo
214 */
215
[841]216APIRET xDosSetPathInfo(PSZ pszPathName,
[850]217 ULONG ulInfoLevel,
[841]218 PVOID pInfoBuf,
219 ULONG cbInfoBuf,
[850]220 ULONG flOptions)
[826]221{
[850]222 FILESTATUS3 fs3;
223 FILESTATUS3 fs3_a;
224 FILESTATUS3L fs3l;
225 EAOP2 eaop2;
[849]226 APIRET rc;
[968]227 BOOL crosses = ((ULONG)pInfoBuf ^
228 ((ULONG)pInfoBuf + cbInfoBuf - 1)) &
229 ~0xffff;
[850]230
231 switch (ulInfoLevel) {
232 case FIL_STANDARD:
[975]233 if (crosses) {
[968]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);
[850]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);
[932]277 }
278 break;
[827]279 default:
280 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
281 rc = ERROR_INVALID_PARAMETER;
[850]282 } // switch
283
[826]284 return rc;
285}
286
[551]287PSZ xfgets(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
288 UINT uiLineNumber)
[400]289{
[551]290 PSZ psz = fgets(pszBuf, cMaxBytes, fp);
291
[400]292 if (!psz) {
293 if (ferror(fp))
294 Runtime_Error(pszSrcFile, uiLineNumber, "fgets");
295 }
296 else {
297 size_t c = strlen(psz);
[551]298
[400]299 if (c + 1 > cMaxBytes)
300 Runtime_Error(pszSrcFile, uiLineNumber, "buffer overflow");
[551]301 else if (!c || (psz[c - 1] != '\n' && psz[c - 1] != '\r'))
[400]302 Runtime_Error(pszSrcFile, uiLineNumber, "missing EOL");
303 }
304 return psz;
305}
306
[551]307PSZ xfgets_bstripcr(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
308 UINT uiLineNumber)
[400]309{
[551]310 PSZ psz = xfgets(pszBuf, cMaxBytes, fp, pszSrcFile, uiLineNumber);
311
[400]312 if (psz)
313 bstripcr(psz);
314 return psz;
315}
316
[551]317FILE *xfopen(PCSZ pszFileName, PCSZ pszMode, PCSZ pszSrcFile,
318 UINT uiLineNumber)
[395]319{
[551]320 FILE *fp = fopen(pszFileName, pszMode);
321
[395]322 if (!fp)
323 Runtime_Error(pszSrcFile, uiLineNumber, "fopen");
324 return fp;
325}
326
[551]327FILE *xfsopen(PCSZ pszFileName, PCSZ pszMode, INT fSharemode, PCSZ pszSrcFile,
328 UINT uiLineNumber)
[395]329{
[551]330 FILE *fp = _fsopen((PSZ) pszFileName, (PSZ) pszMode, fSharemode);
331
[395]332 if (!fp)
333 Runtime_Error(pszSrcFile, uiLineNumber, "_fsopen");
334 return fp;
335}
336
337//== xfree - safe free ==
338
[1009]339VOID xfree(PVOID pv, PCSZ pszSrcFile, UINT uiLineNumber)
[395]340{
[1009]341 if (pv && pv != NullStr) {
[1063]342# ifdef FORTIFY
[1009]343 Fortify_free(pv, pszSrcFile, uiLineNumber);
[1063]344# else
[395]345 free(pv);
[1063]346# endif
[1009]347
348 }
[395]349}
350
351//== xmalloc() malloc with error checking ==
352
353PVOID xmalloc(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
354{
[1006]355# ifdef FORTIFY
356 PVOID pv = Fortify_malloc(cBytes, pszSrcFile, uiLineNumber);
[1011]357# else
[395]358 PVOID pv = malloc(cBytes);
[1063]359# endif
[395]360
361 if (!pv)
[551]362 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]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{
[1011]371 PVOID pv = xmalloc(cBytes, pszSrcFile, uiLineNumber);
[395]372
[1011]373 if (pv)
[395]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{
[963]383 if (pvIn != NullStr) {
[1063]384# ifdef FORTIFY
385 PVOID pv = Fortify_realloc(pvIn, cBytes, pszSrcFile, uiLineNumber);
386# else
387 PVOID pv = realloc(pvIn, cBytes);
388# endif
[395]389
[963]390 if (!pv && cBytes)
391 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]392
[963]393 return pv;
394 }
395 else
396 return xmalloc(cBytes, pszSrcFile, uiLineNumber);
[395]397}
398
399//== xstrdup() strdup with error checking ==
400
401PVOID xstrdup(PCSZ pszIn, PCSZ pszSrcFile, UINT uiLineNumber)
402{
[1009]403# ifdef FORTIFY
404 PSZ psz = Fortify_strdup(pszIn, pszSrcFile, uiLineNumber);
[1011]405# else
[395]406 PSZ psz = strdup(pszIn);
[1063]407# endif
[395]408
409 if (!psz)
[551]410 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]411
412 return psz;
413}
[794]414
[1032]415
416#pragma alloc_text(WRAPPERS1,xfree,xfopen,xfsopen,xmalloc,xrealloc,xstrdup)
[1037]417#pragma alloc_text(WRAPPERS2,xDosSetPathInfo,xDosFindFirst,xDosFindNext)
Note: See TracBrowser for help on using the repository browser.