source: trunk/dll/wrappers.c@ 975

Last change on this file since 975 was 975, checked in by John Small, 18 years ago

Changed cod eto conform to coding style.

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