source: trunk/dll/wrappers.c@ 850

Last change on this file since 850 was 850, checked in by Steven Levine, 18 years ago

Rework large file support wrappers (ticket #41)
Add code to avoid NTFS driver small file read defect (ticket #159)
Add debug code to try to catch David's drive bar exception
Another attempt to correct newview fast viewer text load failure

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