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
RevLine 
[395]1
2/***********************************************************************
3
4 $Id: wrappers.c 1182 2008-09-10 21:55:47Z 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"
[1182]31#include "wrappers.h"
[395]32#include "fm3str.h"
[907]33#include "errutil.h" // Dos_Error...
34#include "strutil.h" // GetPString
[1032]35#include "command.h"
36#include "tools.h"
37#include "avl.h"
[1182]38#include "strips.h" // bstrip
[395]39
[1005]40#include "fortify.h" // GetPString
41
[827]42static PSZ pszSrcFile = __FILE__;
43
[850]44APIRET xDosFindFirst(PSZ pszFileSpec,
45 PHDIR phdir,
46 ULONG flAttribute,
47 PVOID pfindbuf,
48 ULONG cbBuf,
49 PULONG pcFileNames,
50 ULONG ulInfoLevel)
[838]51{
[850]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 }
[849]71 break;
[850]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 }
[849]89 break;
90 default:
[850]91 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
92 rc = ERROR_INVALID_PARAMETER;
93 } // switch
94 }
95 else
[838]96 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, pfindbuf, cbBuf,
[850]97 pcFileNames, ulInfoLevel);
98 return rc;
[838]99}
100
[850]101APIRET xDosFindNext(HDIR hDir,
102 PVOID pfindbuf,
103 ULONG cbfindbuf,
104 PULONG pcFileNames,
105 ULONG ulInfoLevel)
[838]106{
107 APIRET rc;
[849]108 if (fNoLargeFileSupport) {
[850]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
[849]145 }
146 else
[850]147 rc = DosFindNext(hDir, pfindbuf, cbfindbuf, pcFileNames);
[838]148
149 return rc;
150}
151
[827]152/**
[850]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 *
[827]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
[847]206 * @param pInfoBuf pointer to FILESTATUS3(L) or EAOP2 buffer
207 * @param ulInfoLevel FIL_STANDARD(L) or FIL_QUERYEASIZE
[827]208 * @returns Same as DosSetPathInfo
209 */
210
[841]211APIRET xDosSetPathInfo(PSZ pszPathName,
[850]212 ULONG ulInfoLevel,
[841]213 PVOID pInfoBuf,
214 ULONG cbInfoBuf,
[850]215 ULONG flOptions)
[826]216{
[850]217 FILESTATUS3 fs3;
218 FILESTATUS3 fs3_a;
219 FILESTATUS3L fs3l;
220 EAOP2 eaop2;
[849]221 APIRET rc;
[968]222 BOOL crosses = ((ULONG)pInfoBuf ^
223 ((ULONG)pInfoBuf + cbInfoBuf - 1)) &
224 ~0xffff;
[850]225
226 switch (ulInfoLevel) {
227 case FIL_STANDARD:
[975]228 if (crosses) {
[968]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);
[850]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);
[932]272 }
273 break;
[827]274 default:
275 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
276 rc = ERROR_INVALID_PARAMETER;
[850]277 } // switch
278
[826]279 return rc;
280}
281
[551]282PSZ xfgets(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
283 UINT uiLineNumber)
[400]284{
[551]285 PSZ psz = fgets(pszBuf, cMaxBytes, fp);
286
[400]287 if (!psz) {
288 if (ferror(fp))
289 Runtime_Error(pszSrcFile, uiLineNumber, "fgets");
290 }
291 else {
292 size_t c = strlen(psz);
[551]293
[400]294 if (c + 1 > cMaxBytes)
295 Runtime_Error(pszSrcFile, uiLineNumber, "buffer overflow");
[551]296 else if (!c || (psz[c - 1] != '\n' && psz[c - 1] != '\r'))
[400]297 Runtime_Error(pszSrcFile, uiLineNumber, "missing EOL");
298 }
299 return psz;
300}
301
[551]302PSZ xfgets_bstripcr(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
303 UINT uiLineNumber)
[400]304{
[551]305 PSZ psz = xfgets(pszBuf, cMaxBytes, fp, pszSrcFile, uiLineNumber);
306
[400]307 if (psz)
308 bstripcr(psz);
309 return psz;
310}
311
[551]312FILE *xfopen(PCSZ pszFileName, PCSZ pszMode, PCSZ pszSrcFile,
313 UINT uiLineNumber)
[395]314{
[551]315 FILE *fp = fopen(pszFileName, pszMode);
316
[395]317 if (!fp)
318 Runtime_Error(pszSrcFile, uiLineNumber, "fopen");
319 return fp;
320}
321
[551]322FILE *xfsopen(PCSZ pszFileName, PCSZ pszMode, INT fSharemode, PCSZ pszSrcFile,
323 UINT uiLineNumber)
[395]324{
[551]325 FILE *fp = _fsopen((PSZ) pszFileName, (PSZ) pszMode, fSharemode);
326
[395]327 if (!fp)
328 Runtime_Error(pszSrcFile, uiLineNumber, "_fsopen");
329 return fp;
330}
331
332//== xfree - safe free ==
333
[1009]334VOID xfree(PVOID pv, PCSZ pszSrcFile, UINT uiLineNumber)
[395]335{
[1009]336 if (pv && pv != NullStr) {
[1063]337# ifdef FORTIFY
[1009]338 Fortify_free(pv, pszSrcFile, uiLineNumber);
[1063]339# else
[395]340 free(pv);
[1063]341# endif
[1009]342
343 }
[395]344}
345
346//== xmalloc() malloc with error checking ==
347
348PVOID xmalloc(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
349{
[1006]350# ifdef FORTIFY
351 PVOID pv = Fortify_malloc(cBytes, pszSrcFile, uiLineNumber);
[1011]352# else
[395]353 PVOID pv = malloc(cBytes);
[1063]354# endif
[395]355
356 if (!pv)
[551]357 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]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{
[1011]366 PVOID pv = xmalloc(cBytes, pszSrcFile, uiLineNumber);
[395]367
[1011]368 if (pv)
[395]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{
[963]378 if (pvIn != NullStr) {
[1063]379# ifdef FORTIFY
380 PVOID pv = Fortify_realloc(pvIn, cBytes, pszSrcFile, uiLineNumber);
381# else
382 PVOID pv = realloc(pvIn, cBytes);
383# endif
[395]384
[963]385 if (!pv && cBytes)
386 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]387
[963]388 return pv;
389 }
390 else
391 return xmalloc(cBytes, pszSrcFile, uiLineNumber);
[395]392}
393
394//== xstrdup() strdup with error checking ==
395
396PVOID xstrdup(PCSZ pszIn, PCSZ pszSrcFile, UINT uiLineNumber)
397{
[1009]398# ifdef FORTIFY
399 PSZ psz = Fortify_strdup(pszIn, pszSrcFile, uiLineNumber);
[1011]400# else
[395]401 PSZ psz = strdup(pszIn);
[1063]402# endif
[395]403
404 if (!psz)
[551]405 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]406
407 return psz;
408}
[794]409
[1032]410
411#pragma alloc_text(WRAPPERS1,xfree,xfopen,xfsopen,xmalloc,xrealloc,xstrdup)
[1037]412#pragma alloc_text(WRAPPERS2,xDosSetPathInfo,xDosFindFirst,xDosFindNext)
Note: See TracBrowser for help on using the repository browser.