source: trunk/dll/wrappers.c@ 1008

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

Comments

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.5 KB
RevLine 
[395]1
2/***********************************************************************
3
4 $Id: wrappers.c 1008 2008-05-06 23:56:00Z stevenhl $
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"
31#include "fm3str.h"
[907]32#include "errutil.h" // Dos_Error...
33#include "strutil.h" // GetPString
[395]34
[1005]35#include "fortify.h" // GetPString
36
[827]37static PSZ pszSrcFile = __FILE__;
38
[850]39APIRET xDosFindFirst(PSZ pszFileSpec,
40 PHDIR phdir,
41 ULONG flAttribute,
42 PVOID pfindbuf,
43 ULONG cbBuf,
44 PULONG pcFileNames,
45 ULONG ulInfoLevel)
[838]46{
[850]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 }
[849]66 break;
[850]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 }
[849]84 break;
85 default:
[850]86 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
87 rc = ERROR_INVALID_PARAMETER;
88 } // switch
89 }
90 else
[838]91 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, pfindbuf, cbBuf,
[850]92 pcFileNames, ulInfoLevel);
93 return rc;
[838]94}
95
[850]96APIRET xDosFindNext(HDIR hDir,
97 PVOID pfindbuf,
98 ULONG cbfindbuf,
99 PULONG pcFileNames,
100 ULONG ulInfoLevel)
[838]101{
102 APIRET rc;
[849]103 if (fNoLargeFileSupport) {
[850]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
[849]140 }
141 else
[850]142 rc = DosFindNext(hDir, pfindbuf, cbfindbuf, pcFileNames);
[838]143
144 return rc;
145}
146
[827]147/**
[850]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 *
[827]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
[847]201 * @param pInfoBuf pointer to FILESTATUS3(L) or EAOP2 buffer
202 * @param ulInfoLevel FIL_STANDARD(L) or FIL_QUERYEASIZE
[827]203 * @returns Same as DosSetPathInfo
204 */
205
[841]206APIRET xDosSetPathInfo(PSZ pszPathName,
[850]207 ULONG ulInfoLevel,
[841]208 PVOID pInfoBuf,
209 ULONG cbInfoBuf,
[850]210 ULONG flOptions)
[826]211{
[850]212 FILESTATUS3 fs3;
213 FILESTATUS3 fs3_a;
214 FILESTATUS3L fs3l;
215 EAOP2 eaop2;
[849]216 APIRET rc;
[968]217 BOOL crosses = ((ULONG)pInfoBuf ^
218 ((ULONG)pInfoBuf + cbInfoBuf - 1)) &
219 ~0xffff;
[850]220
221 switch (ulInfoLevel) {
222 case FIL_STANDARD:
[975]223 if (crosses) {
[968]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);
[850]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);
[932]267 }
268 break;
[827]269 default:
270 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
271 rc = ERROR_INVALID_PARAMETER;
[850]272 } // switch
273
[826]274 return rc;
275}
276
[551]277PSZ xfgets(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
278 UINT uiLineNumber)
[400]279{
[551]280 PSZ psz = fgets(pszBuf, cMaxBytes, fp);
281
[400]282 if (!psz) {
283 if (ferror(fp))
284 Runtime_Error(pszSrcFile, uiLineNumber, "fgets");
285 }
286 else {
287 size_t c = strlen(psz);
[551]288
[400]289 if (c + 1 > cMaxBytes)
290 Runtime_Error(pszSrcFile, uiLineNumber, "buffer overflow");
[551]291 else if (!c || (psz[c - 1] != '\n' && psz[c - 1] != '\r'))
[400]292 Runtime_Error(pszSrcFile, uiLineNumber, "missing EOL");
293 }
294 return psz;
295}
296
[551]297PSZ xfgets_bstripcr(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
298 UINT uiLineNumber)
[400]299{
[551]300 PSZ psz = xfgets(pszBuf, cMaxBytes, fp, pszSrcFile, uiLineNumber);
301
[400]302 if (psz)
303 bstripcr(psz);
304 return psz;
305}
306
[551]307FILE *xfopen(PCSZ pszFileName, PCSZ pszMode, PCSZ pszSrcFile,
308 UINT uiLineNumber)
[395]309{
[551]310 FILE *fp = fopen(pszFileName, pszMode);
311
[395]312 if (!fp)
313 Runtime_Error(pszSrcFile, uiLineNumber, "fopen");
314 return fp;
315}
316
[551]317FILE *xfsopen(PCSZ pszFileName, PCSZ pszMode, INT fSharemode, PCSZ pszSrcFile,
318 UINT uiLineNumber)
[395]319{
[551]320 FILE *fp = _fsopen((PSZ) pszFileName, (PSZ) pszMode, fSharemode);
321
[395]322 if (!fp)
323 Runtime_Error(pszSrcFile, uiLineNumber, "_fsopen");
324 return fp;
325}
326
327//== xfree - safe free ==
328
[551]329VOID xfree(PVOID pv)
[395]330{
[963]331 if (pv && pv != NullStr)
[395]332 free(pv);
333}
334
335//== xmalloc() malloc with error checking ==
336
337PVOID xmalloc(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
338{
[1006]339# ifdef FORTIFY
340 PVOID pv = Fortify_malloc(cBytes, pszSrcFile, uiLineNumber);
341# else
[395]342 PVOID pv = malloc(cBytes);
[1006]343# endif
[395]344
345 if (!pv)
[551]346 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]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)
[551]358 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]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{
[963]369 if (pvIn != NullStr) {
370 PVOID pv = realloc(pvIn, cBytes);
[395]371
[963]372 if (!pv && cBytes)
373 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]374
[963]375 return pv;
376 }
377 else
378 return xmalloc(cBytes, pszSrcFile, uiLineNumber);
[395]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)
[551]388 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]389
390 return psz;
391}
[794]392
393#pragma alloc_text(WRAPPERS1,xfree,xfopen,xfsopen,xmalloc,xrealloc, xstrdup)
[841]394#pragma alloc_text(WRAPPERS2,xDosSetPathInfo,xDosFindFirst,xDosFindNext)
Note: See TracBrowser for help on using the repository browser.