source: trunk/dll/wrappers.c@ 932

Last change on this file since 932 was 932, checked in by Gregg Young, 18 years ago

Fix spurious error message that breaks editing of subjucts directly in containers

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.1 KB
Line 
1
2/***********************************************************************
3
4 $Id: wrappers.c 932 2008-01-19 19:17:47Z gyoung $
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
215 switch (ulInfoLevel) {
216 case FIL_STANDARD:
217 rc = DosSetPathInfo(pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf, flOptions);
218 if (rc == ERROR_INVALID_NAME) {
219 // fixme to validate counts?
220 fs3 = *(PFILESTATUS3)pInfoBuf; // Copy to buffer that does not cross
221 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3, sizeof(fs3), flOptions);
222 }
223 break;
224
225 case FIL_STANDARDL:
226 if (fNoLargeFileSupport) {
227 ulInfoLevel = FIL_STANDARD;
228 fs3 = *(PFILESTATUS3)pInfoBuf; // Copy aligned data
229 // Check size too big to handle
230 if (((PFILESTATUS3L)pInfoBuf)->cbFile >= 1LL << 32 ||
231 ((PFILESTATUS3L)pInfoBuf)->cbFileAlloc >= 2LL << 32)
232 {
233 rc = ERROR_INVALID_PARAMETER;
234 }
235 else {
236 fs3.cbFile = ((PFILESTATUS3L)pInfoBuf)->cbFile; // Copy unaligned data
237 fs3.cbFileAlloc = ((PFILESTATUS3L)pInfoBuf)->cbFileAlloc;
238 fs3.attrFile = ((PFILESTATUS3L)pInfoBuf)->attrFile;
239 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3, sizeof(fs3), flOptions);
240 }
241 if (rc == ERROR_INVALID_NAME) {
242 // fixme to validate counts?
243 fs3_a = fs3; // Copy to buffer that does not cross
244 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3_a, sizeof(fs3_a), flOptions);
245 }
246 }
247 else {
248 rc = DosSetPathInfo(pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf, flOptions);
249 if (rc == ERROR_INVALID_NAME) {
250 fs3l = *(PFILESTATUS3L)pInfoBuf; // Copy to buffer that does not cross
251 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3l, sizeof(fs3l), flOptions);
252 }
253 }
254 break;
255 case FIL_QUERYEASIZE:
256 rc = DosSetPathInfo(pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf, flOptions);
257 if (rc == ERROR_INVALID_NAME) {
258 // fixme to validate counts?
259 eaop2 = *(PEAOP2)pInfoBuf; // Copy to buffer that does not cross
260 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &eaop2, sizeof(eaop2), flOptions);
261 }
262 break;
263 default:
264 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
265 rc = ERROR_INVALID_PARAMETER;
266 } // switch
267
268 return rc;
269}
270
271PSZ xfgets(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
272 UINT uiLineNumber)
273{
274 PSZ psz = fgets(pszBuf, cMaxBytes, fp);
275
276 if (!psz) {
277 if (ferror(fp))
278 Runtime_Error(pszSrcFile, uiLineNumber, "fgets");
279 }
280 else {
281 size_t c = strlen(psz);
282
283 if (c + 1 > cMaxBytes)
284 Runtime_Error(pszSrcFile, uiLineNumber, "buffer overflow");
285 else if (!c || (psz[c - 1] != '\n' && psz[c - 1] != '\r'))
286 Runtime_Error(pszSrcFile, uiLineNumber, "missing EOL");
287 }
288 return psz;
289}
290
291PSZ xfgets_bstripcr(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
292 UINT uiLineNumber)
293{
294 PSZ psz = xfgets(pszBuf, cMaxBytes, fp, pszSrcFile, uiLineNumber);
295
296 if (psz)
297 bstripcr(psz);
298 return psz;
299}
300
301FILE *xfopen(PCSZ pszFileName, PCSZ pszMode, PCSZ pszSrcFile,
302 UINT uiLineNumber)
303{
304 FILE *fp = fopen(pszFileName, pszMode);
305
306 if (!fp)
307 Runtime_Error(pszSrcFile, uiLineNumber, "fopen");
308 return fp;
309}
310
311FILE *xfsopen(PCSZ pszFileName, PCSZ pszMode, INT fSharemode, PCSZ pszSrcFile,
312 UINT uiLineNumber)
313{
314 FILE *fp = _fsopen((PSZ) pszFileName, (PSZ) pszMode, fSharemode);
315
316 if (!fp)
317 Runtime_Error(pszSrcFile, uiLineNumber, "_fsopen");
318 return fp;
319}
320
321//== xfree - safe free ==
322
323VOID xfree(PVOID pv)
324{
325 if (pv)
326 free(pv);
327}
328
329//== xmalloc() malloc with error checking ==
330
331PVOID xmalloc(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
332{
333 PVOID pv = malloc(cBytes);
334
335 if (!pv)
336 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
337
338 return pv;
339}
340
341//== xmallocz() malloc and zero with error checking ==
342
343PVOID xmallocz(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
344{
345 PVOID pv = malloc(cBytes);
346
347 if (!pv)
348 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
349 else
350 memset(pv, 0, cBytes);
351
352 return pv;
353}
354
355//== xrealloc() realloc with error checking ==
356
357PVOID xrealloc(PVOID pvIn, size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
358{
359 PVOID pv = realloc(pvIn, cBytes);
360
361 if (!pv && cBytes)
362 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
363
364 return pv;
365
366}
367
368//== xstrdup() strdup with error checking ==
369
370PVOID xstrdup(PCSZ pszIn, PCSZ pszSrcFile, UINT uiLineNumber)
371{
372 PSZ psz = strdup(pszIn);
373
374 if (!psz)
375 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
376
377 return psz;
378}
379
380#pragma alloc_text(WRAPPERS1,xfree,xfopen,xfsopen,xmalloc,xrealloc, xstrdup)
381#pragma alloc_text(WRAPPERS2,xDosSetPathInfo,xDosFindFirst,xDosFindNext)
Note: See TracBrowser for help on using the repository browser.