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
RevLine 
[395]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
[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
19#define INCL_WIN
[826]20#define INCL_DOS
21#define INCL_DOSERRORS
[841]22#define INCL_LONGLONG
[395]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
[827]32static PSZ pszSrcFile = __FILE__;
33
[850]34APIRET xDosFindFirst(PSZ pszFileSpec,
35 PHDIR phdir,
36 ULONG flAttribute,
37 PVOID pfindbuf,
38 ULONG cbBuf,
39 PULONG pcFileNames,
40 ULONG ulInfoLevel)
[838]41{
[850]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 }
[849]61 break;
[850]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 }
[849]79 break;
80 default:
[850]81 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
82 rc = ERROR_INVALID_PARAMETER;
83 } // switch
84 }
85 else
[838]86 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, pfindbuf, cbBuf,
[850]87 pcFileNames, ulInfoLevel);
88 return rc;
[838]89}
90
[850]91APIRET xDosFindNext(HDIR hDir,
92 PVOID pfindbuf,
93 ULONG cbfindbuf,
94 PULONG pcFileNames,
95 ULONG ulInfoLevel)
[838]96{
97 APIRET rc;
[849]98 if (fNoLargeFileSupport) {
[850]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
[849]135 }
136 else
[850]137 rc = DosFindNext(hDir, pfindbuf, cbfindbuf, pcFileNames);
[838]138
139 return rc;
140}
141
[827]142/**
[850]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 *
[827]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
[847]196 * @param pInfoBuf pointer to FILESTATUS3(L) or EAOP2 buffer
197 * @param ulInfoLevel FIL_STANDARD(L) or FIL_QUERYEASIZE
[827]198 * @returns Same as DosSetPathInfo
199 */
200
[841]201APIRET xDosSetPathInfo(PSZ pszPathName,
[850]202 ULONG ulInfoLevel,
[841]203 PVOID pInfoBuf,
204 ULONG cbInfoBuf,
[850]205 ULONG flOptions)
[826]206{
[850]207 FILESTATUS3 fs3;
208 FILESTATUS3 fs3_a;
209 FILESTATUS3L fs3l;
210 EAOP2 eaop2;
[849]211 APIRET rc;
[850]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 }
[827]260 default:
261 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
262 rc = ERROR_INVALID_PARAMETER;
[850]263 } // switch
264
[826]265 return rc;
266}
267
[551]268PSZ xfgets(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
269 UINT uiLineNumber)
[400]270{
[551]271 PSZ psz = fgets(pszBuf, cMaxBytes, fp);
272
[400]273 if (!psz) {
274 if (ferror(fp))
275 Runtime_Error(pszSrcFile, uiLineNumber, "fgets");
276 }
277 else {
278 size_t c = strlen(psz);
[551]279
[400]280 if (c + 1 > cMaxBytes)
281 Runtime_Error(pszSrcFile, uiLineNumber, "buffer overflow");
[551]282 else if (!c || (psz[c - 1] != '\n' && psz[c - 1] != '\r'))
[400]283 Runtime_Error(pszSrcFile, uiLineNumber, "missing EOL");
284 }
285 return psz;
286}
287
[551]288PSZ xfgets_bstripcr(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
289 UINT uiLineNumber)
[400]290{
[551]291 PSZ psz = xfgets(pszBuf, cMaxBytes, fp, pszSrcFile, uiLineNumber);
292
[400]293 if (psz)
294 bstripcr(psz);
295 return psz;
296}
297
[551]298FILE *xfopen(PCSZ pszFileName, PCSZ pszMode, PCSZ pszSrcFile,
299 UINT uiLineNumber)
[395]300{
[551]301 FILE *fp = fopen(pszFileName, pszMode);
302
[395]303 if (!fp)
304 Runtime_Error(pszSrcFile, uiLineNumber, "fopen");
305 return fp;
306}
307
[551]308FILE *xfsopen(PCSZ pszFileName, PCSZ pszMode, INT fSharemode, PCSZ pszSrcFile,
309 UINT uiLineNumber)
[395]310{
[551]311 FILE *fp = _fsopen((PSZ) pszFileName, (PSZ) pszMode, fSharemode);
312
[395]313 if (!fp)
314 Runtime_Error(pszSrcFile, uiLineNumber, "_fsopen");
315 return fp;
316}
317
318//== xfree - safe free ==
319
[551]320VOID xfree(PVOID pv)
[395]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)
[551]333 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]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)
[551]345 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]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)
[551]359 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]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)
[551]372 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]373
374 return psz;
375}
[794]376
377#pragma alloc_text(WRAPPERS1,xfree,xfopen,xfsopen,xmalloc,xrealloc, xstrdup)
[841]378#pragma alloc_text(WRAPPERS2,xDosSetPathInfo,xDosFindFirst,xDosFindNext)
Note: See TracBrowser for help on using the repository browser.