source: trunk/dll/wrappers.c@ 849

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

Initial attempt at wrapper functions for large file support. fNoLargeFileSupport is set to TRUE in init.c for testing. The code builds but isn't functional Setting fNoLargeFileSupport FALSE will yield working code.

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