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
RevLine 
[395]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
[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)
[395]16
17***********************************************************************/
18
[907]19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22
[395]23#define INCL_WIN
[826]24#define INCL_DOS
25#define INCL_DOSERRORS
[841]26#define INCL_LONGLONG
[395]27#include <os2.h>
28
29#include "fm3dll.h"
30#include "fm3str.h"
[907]31#include "errutil.h" // Dos_Error...
32#include "strutil.h" // GetPString
[395]33
[827]34static PSZ pszSrcFile = __FILE__;
35
[850]36APIRET xDosFindFirst(PSZ pszFileSpec,
37 PHDIR phdir,
38 ULONG flAttribute,
39 PVOID pfindbuf,
40 ULONG cbBuf,
41 PULONG pcFileNames,
42 ULONG ulInfoLevel)
[838]43{
[850]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 }
[849]63 break;
[850]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 }
[849]81 break;
82 default:
[850]83 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
84 rc = ERROR_INVALID_PARAMETER;
85 } // switch
86 }
87 else
[838]88 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, pfindbuf, cbBuf,
[850]89 pcFileNames, ulInfoLevel);
90 return rc;
[838]91}
92
[850]93APIRET xDosFindNext(HDIR hDir,
94 PVOID pfindbuf,
95 ULONG cbfindbuf,
96 PULONG pcFileNames,
97 ULONG ulInfoLevel)
[838]98{
99 APIRET rc;
[849]100 if (fNoLargeFileSupport) {
[850]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
[849]137 }
138 else
[850]139 rc = DosFindNext(hDir, pfindbuf, cbfindbuf, pcFileNames);
[838]140
141 return rc;
142}
143
[827]144/**
[850]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 *
[827]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
[847]198 * @param pInfoBuf pointer to FILESTATUS3(L) or EAOP2 buffer
199 * @param ulInfoLevel FIL_STANDARD(L) or FIL_QUERYEASIZE
[827]200 * @returns Same as DosSetPathInfo
201 */
202
[841]203APIRET xDosSetPathInfo(PSZ pszPathName,
[850]204 ULONG ulInfoLevel,
[841]205 PVOID pInfoBuf,
206 ULONG cbInfoBuf,
[850]207 ULONG flOptions)
[826]208{
[850]209 FILESTATUS3 fs3;
210 FILESTATUS3 fs3_a;
211 FILESTATUS3L fs3l;
212 EAOP2 eaop2;
[849]213 APIRET rc;
[968]214 BOOL crosses = ((ULONG)pInfoBuf ^
215 ((ULONG)pInfoBuf + cbInfoBuf - 1)) &
216 ~0xffff;
[850]217
218 switch (ulInfoLevel) {
219 case FIL_STANDARD:
[975]220 if (crosses) {
[968]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);
[850]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);
[932]264 }
265 break;
[827]266 default:
267 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
268 rc = ERROR_INVALID_PARAMETER;
[850]269 } // switch
270
[826]271 return rc;
272}
273
[551]274PSZ xfgets(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
275 UINT uiLineNumber)
[400]276{
[551]277 PSZ psz = fgets(pszBuf, cMaxBytes, fp);
278
[400]279 if (!psz) {
280 if (ferror(fp))
281 Runtime_Error(pszSrcFile, uiLineNumber, "fgets");
282 }
283 else {
284 size_t c = strlen(psz);
[551]285
[400]286 if (c + 1 > cMaxBytes)
287 Runtime_Error(pszSrcFile, uiLineNumber, "buffer overflow");
[551]288 else if (!c || (psz[c - 1] != '\n' && psz[c - 1] != '\r'))
[400]289 Runtime_Error(pszSrcFile, uiLineNumber, "missing EOL");
290 }
291 return psz;
292}
293
[551]294PSZ xfgets_bstripcr(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
295 UINT uiLineNumber)
[400]296{
[551]297 PSZ psz = xfgets(pszBuf, cMaxBytes, fp, pszSrcFile, uiLineNumber);
298
[400]299 if (psz)
300 bstripcr(psz);
301 return psz;
302}
303
[551]304FILE *xfopen(PCSZ pszFileName, PCSZ pszMode, PCSZ pszSrcFile,
305 UINT uiLineNumber)
[395]306{
[551]307 FILE *fp = fopen(pszFileName, pszMode);
308
[395]309 if (!fp)
310 Runtime_Error(pszSrcFile, uiLineNumber, "fopen");
311 return fp;
312}
313
[551]314FILE *xfsopen(PCSZ pszFileName, PCSZ pszMode, INT fSharemode, PCSZ pszSrcFile,
315 UINT uiLineNumber)
[395]316{
[551]317 FILE *fp = _fsopen((PSZ) pszFileName, (PSZ) pszMode, fSharemode);
318
[395]319 if (!fp)
320 Runtime_Error(pszSrcFile, uiLineNumber, "_fsopen");
321 return fp;
322}
323
324//== xfree - safe free ==
325
[551]326VOID xfree(PVOID pv)
[395]327{
[963]328 if (pv && pv != NullStr)
[395]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)
[551]339 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]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)
[551]351 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]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{
[963]362 if (pvIn != NullStr) {
363 PVOID pv = realloc(pvIn, cBytes);
[395]364
[963]365 if (!pv && cBytes)
366 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]367
[963]368 return pv;
369 }
370 else
371 return xmalloc(cBytes, pszSrcFile, uiLineNumber);
[395]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)
[551]381 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]382
383 return psz;
384}
[794]385
386#pragma alloc_text(WRAPPERS1,xfree,xfopen,xfsopen,xmalloc,xrealloc, xstrdup)
[841]387#pragma alloc_text(WRAPPERS2,xDosSetPathInfo,xDosFindFirst,xDosFindNext)
Note: See TracBrowser for help on using the repository browser.