source: trunk/dll/wrappers.c@ 1387

Last change on this file since 1387 was 1358, checked in by Gregg Young, 17 years ago

Comments for CS 1354/55

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.4 KB
RevLine 
[395]1
2/***********************************************************************
3
4 $Id: wrappers.c 1358 2008-12-27 00:03:08Z gyoung $
5
6 Wrappers with error checking
7
[1008]8 Copyright (c) 2006, 2008 Steven H.Levine
[395]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)
[1008]16 05 May 08 SHL Add FORTIFY support
[1358]17 25 Dec 08 GKY Add code to allow write verify to be turned off on a per drive basis
[395]18
19***********************************************************************/
20
[907]21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
[1354]24#include <ctype.h>
[907]25
[395]26#define INCL_WIN
[826]27#define INCL_DOS
28#define INCL_DOSERRORS
[841]29#define INCL_LONGLONG
[395]30#include <os2.h>
31
32#include "fm3dll.h"
[1215]33#include "init.h" // Data declaration(s)
[1182]34#include "wrappers.h"
[395]35#include "fm3str.h"
[907]36#include "errutil.h" // Dos_Error...
37#include "strutil.h" // GetPString
[1032]38#include "command.h"
39#include "tools.h"
40#include "avl.h"
[1182]41#include "strips.h" // bstrip
[395]42
[1005]43#include "fortify.h" // GetPString
[1354]44#include "info.h" // driveflags
45#include "notebook.h" // fVerify
[1005]46
[1215]47// Data definitions
[827]48static PSZ pszSrcFile = __FILE__;
49
[1215]50#pragma data_seg(GLOBAL1)
51BOOL fNoLargeFileSupport;
52
[850]53APIRET xDosFindFirst(PSZ pszFileSpec,
54 PHDIR phdir,
55 ULONG flAttribute,
56 PVOID pfindbuf,
57 ULONG cbBuf,
58 PULONG pcFileNames,
59 ULONG ulInfoLevel)
[838]60{
[850]61 APIRET rc;
62 if (fNoLargeFileSupport) {
63 switch (ulInfoLevel) {
64 case FIL_STANDARDL:
65 {
66 FILEFINDBUF3 ffb3;
67 ulInfoLevel = FIL_STANDARD;
68 *pcFileNames = 1; // fixme to support larger counts
69 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, &ffb3, sizeof(ffb3),
70 pcFileNames, ulInfoLevel);
71 if (!rc) {
72 *(PFILEFINDBUF3)pfindbuf = ffb3; // Copy aligned data
73 ((PFILEFINDBUF3L)pfindbuf)->cbFile = ffb3.cbFile; // Copy unaligned data
74 ((PFILEFINDBUF3L)pfindbuf)->cbFileAlloc = ffb3.cbFileAlloc;
75 ((PFILEFINDBUF3L)pfindbuf)->attrFile = ffb3.attrFile;
76 ((PFILEFINDBUF3L)pfindbuf)->cchName = ffb3.cchName;
77 memcpy(((PFILEFINDBUF3L)pfindbuf)->achName, ffb3.achName, ffb3.cchName + 1);
78 }
79 }
[849]80 break;
[850]81 case FIL_QUERYEASIZEL:
82 {
83 FILEFINDBUF4 ffb4;
84 *pcFileNames = 1; // fixme to support larger counts
85 ulInfoLevel = FIL_QUERYEASIZE;
86 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, &ffb4, sizeof(ffb4),
87 pcFileNames, ulInfoLevel);
88 if (!rc) {
89 *(PFILEFINDBUF4)pfindbuf = ffb4; // Copy aligned data
90 ((PFILEFINDBUF4L)pfindbuf)->cbFile = ffb4.cbFile; // Copy unaligned data
91 ((PFILEFINDBUF4L)pfindbuf)->cbFileAlloc = ffb4.cbFileAlloc;
92 ((PFILEFINDBUF4L)pfindbuf)->attrFile = ffb4.attrFile;
93 ((PFILEFINDBUF4L)pfindbuf)->cbList = ffb4.cbList;
94 ((PFILEFINDBUF4L)pfindbuf)->cchName = ffb4.cchName;
95 memcpy(((PFILEFINDBUF4L)pfindbuf)->achName, ffb4.achName, ffb4.cchName + 1);
96 }
97 }
[849]98 break;
99 default:
[850]100 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
101 rc = ERROR_INVALID_PARAMETER;
102 } // switch
103 }
104 else
[838]105 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, pfindbuf, cbBuf,
[850]106 pcFileNames, ulInfoLevel);
107 return rc;
[838]108}
109
[850]110APIRET xDosFindNext(HDIR hDir,
111 PVOID pfindbuf,
112 ULONG cbfindbuf,
113 PULONG pcFileNames,
114 ULONG ulInfoLevel)
[838]115{
116 APIRET rc;
[849]117 if (fNoLargeFileSupport) {
[850]118 switch (ulInfoLevel) {
119 case FIL_STANDARDL:
120 {
121 FILEFINDBUF3 ffb3;
122 *pcFileNames = 1; // fixme to support larger counts
123 rc = DosFindNext(hDir, &ffb3, sizeof(ffb3), pcFileNames);
124 if (!rc) {
125 *(PFILEFINDBUF3)pfindbuf = ffb3; // Copy aligned data
126 ((PFILEFINDBUF3L)pfindbuf)->cbFile = ffb3.cbFile; // Copy unaligned data
127 ((PFILEFINDBUF3L)pfindbuf)->cbFileAlloc = ffb3.cbFileAlloc;
128 ((PFILEFINDBUF3L)pfindbuf)->attrFile = ffb3.attrFile;
129 ((PFILEFINDBUF3L)pfindbuf)->cchName = ffb3.cchName;
130 memcpy(((PFILEFINDBUF3L)pfindbuf)->achName, ffb3.achName, ffb3.cchName + 1);
131 }
132 }
133 break;
134 case FIL_QUERYEASIZEL:
135 {
136 FILEFINDBUF4 ffb4;
137 *pcFileNames = 1; // fixme to support larger counts
138 rc = DosFindNext(hDir, &ffb4, sizeof(ffb4), pcFileNames);
139 if (!rc) {
140 *(PFILEFINDBUF4)pfindbuf = ffb4; // Copy aligned data
141 ((PFILEFINDBUF4L)pfindbuf)->cbFile = ffb4.cbFile; // Copy unaligned data
142 ((PFILEFINDBUF4L)pfindbuf)->cbFileAlloc = ffb4.cbFileAlloc;
143 ((PFILEFINDBUF4L)pfindbuf)->attrFile = ffb4.attrFile;
144 ((PFILEFINDBUF4L)pfindbuf)->cbList = ffb4.cbList;
145 ((PFILEFINDBUF4L)pfindbuf)->cchName = ffb4.cchName;
146 memcpy(((PFILEFINDBUF4L)pfindbuf)->achName, ffb4.achName, ffb4.cchName + 1);
147 }
148 }
149 break;
150 default:
151 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
152 rc = ERROR_INVALID_PARAMETER;
153 } // switch
[849]154 }
155 else
[850]156 rc = DosFindNext(hDir, pfindbuf, cbfindbuf, pcFileNames);
[838]157
158 return rc;
159}
160
[827]161/**
[850]162 * DosQueryPathInfo wrapper
163 * Translate request for systems without large file support
164 */
165
166APIRET xDosQueryPathInfo (PSZ pszPathName, ULONG ulInfoLevel, PVOID pInfoBuf, ULONG cbInfoBuf)
167{
168 FILESTATUS3 fs3;
169 FILESTATUS4 fs4;
170 APIRET rc;
171
172 if (fNoLargeFileSupport) {
173 switch (ulInfoLevel) {
174 case FIL_STANDARDL:
175 rc = DosQueryPathInfo(pszPathName, ulInfoLevel, &fs3, sizeof(fs3));
176 if (!rc) {
177 *(PFILESTATUS3)pInfoBuf = fs3; // Copy aligned data
178 ((PFILESTATUS3L)pInfoBuf)->cbFile = fs3.cbFile; // Copy unaligned data
179 ((PFILESTATUS3L)pInfoBuf)->cbFileAlloc = fs3.cbFileAlloc;
180 ((PFILESTATUS3L)pInfoBuf)->attrFile = fs3.attrFile;
181 }
182 break;
183 case FIL_QUERYEASIZEL:
184 rc = DosQueryPathInfo(pszPathName, ulInfoLevel, &fs4, sizeof(fs4));
185 if (!rc) {
186 *(PFILESTATUS4)pInfoBuf = fs4; // Copy aligned data
187 ((PFILESTATUS4L)pInfoBuf)->cbFile = fs4.cbFile; // Copy unaligned data
188 ((PFILESTATUS4L)pInfoBuf)->cbFileAlloc = fs4.cbFileAlloc;
189 ((PFILESTATUS4L)pInfoBuf)->attrFile = fs4.attrFile;
190 ((PFILESTATUS4L)pInfoBuf)->cbList = fs4.cbList;
191 }
192 break;
193 default:
194 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
195 rc = ERROR_INVALID_PARAMETER;
196 } // switch
197 }
198 else
199 DosQueryPathInfo (pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf);
200
201 return rc;
202}
203
204/**
205 * Wrap DosSetPathInfo to avoid spurious ERROR_INVALID_NAME returns and
206 * support systems without large file support
207 *
[827]208 * Some kernels to do not correctly handle FILESTATUS3 and PEAOP2 buffers
209 * that cross a 64K boundary.
210 * When this occurs, they return ERROR_INVALID_NAME.
211 * This code works around the problem because if the passed buffer crosses
212 * the boundary the alternate buffer will not because both are on the stack
213 * and we don't put enough additional data on the stack for this to occur.
214 * It is caller's responsitibility to report errors
[847]215 * @param pInfoBuf pointer to FILESTATUS3(L) or EAOP2 buffer
216 * @param ulInfoLevel FIL_STANDARD(L) or FIL_QUERYEASIZE
[827]217 * @returns Same as DosSetPathInfo
218 */
219
[841]220APIRET xDosSetPathInfo(PSZ pszPathName,
[850]221 ULONG ulInfoLevel,
[841]222 PVOID pInfoBuf,
223 ULONG cbInfoBuf,
[850]224 ULONG flOptions)
[826]225{
[850]226 FILESTATUS3 fs3;
227 FILESTATUS3 fs3_a;
228 FILESTATUS3L fs3l;
229 EAOP2 eaop2;
[849]230 APIRET rc;
[968]231 BOOL crosses = ((ULONG)pInfoBuf ^
[1354]232 ((ULONG)pInfoBuf + cbInfoBuf - 1)) & ~0xffff;
233 BOOL fResetVerify = FALSE;
[850]234
[1354]235 if (fVerify && driveflags[toupper(*pszPathName) - 'A'] & DRIVE_WRITEVERIFYOFF) {
236 DosSetVerify(FALSE);
237 fResetVerify = TRUE;
238 }
[850]239 switch (ulInfoLevel) {
240 case FIL_STANDARD:
[975]241 if (crosses) {
[968]242 fs3 = *(PFILESTATUS3)pInfoBuf; // Copy to buffer that does not cross 64K boundary
243 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3, cbInfoBuf, flOptions);
244 }
245 else
246 rc = DosSetPathInfo(pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf, flOptions);
[850]247 break;
248
249 case FIL_STANDARDL:
250 if (fNoLargeFileSupport) {
251 ulInfoLevel = FIL_STANDARD;
252 fs3 = *(PFILESTATUS3)pInfoBuf; // Copy aligned data
253 // Check size too big to handle
254 if (((PFILESTATUS3L)pInfoBuf)->cbFile >= 1LL << 32 ||
255 ((PFILESTATUS3L)pInfoBuf)->cbFileAlloc >= 2LL << 32)
256 {
257 rc = ERROR_INVALID_PARAMETER;
258 }
259 else {
260 fs3.cbFile = ((PFILESTATUS3L)pInfoBuf)->cbFile; // Copy unaligned data
261 fs3.cbFileAlloc = ((PFILESTATUS3L)pInfoBuf)->cbFileAlloc;
262 fs3.attrFile = ((PFILESTATUS3L)pInfoBuf)->attrFile;
263 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3, sizeof(fs3), flOptions);
264 }
265 if (rc == ERROR_INVALID_NAME) {
266 // fixme to validate counts?
267 fs3_a = fs3; // Copy to buffer that does not cross
268 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3_a, sizeof(fs3_a), flOptions);
269 }
270 }
271 else {
272 rc = DosSetPathInfo(pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf, flOptions);
273 if (rc == ERROR_INVALID_NAME) {
274 fs3l = *(PFILESTATUS3L)pInfoBuf; // Copy to buffer that does not cross
275 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3l, sizeof(fs3l), flOptions);
276 }
277 }
278 break;
279 case FIL_QUERYEASIZE:
280 rc = DosSetPathInfo(pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf, flOptions);
281 if (rc == ERROR_INVALID_NAME) {
282 // fixme to validate counts?
283 eaop2 = *(PEAOP2)pInfoBuf; // Copy to buffer that does not cross
284 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &eaop2, sizeof(eaop2), flOptions);
[932]285 }
286 break;
[827]287 default:
288 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
289 rc = ERROR_INVALID_PARAMETER;
[850]290 } // switch
[1354]291 if (fResetVerify) {
292 DosSetVerify(fVerify);
293 fResetVerify = FALSE;
294 }
[826]295 return rc;
296}
297
[551]298PSZ xfgets(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
299 UINT uiLineNumber)
[400]300{
[551]301 PSZ psz = fgets(pszBuf, cMaxBytes, fp);
302
[400]303 if (!psz) {
304 if (ferror(fp))
305 Runtime_Error(pszSrcFile, uiLineNumber, "fgets");
306 }
307 else {
308 size_t c = strlen(psz);
[551]309
[400]310 if (c + 1 > cMaxBytes)
311 Runtime_Error(pszSrcFile, uiLineNumber, "buffer overflow");
[551]312 else if (!c || (psz[c - 1] != '\n' && psz[c - 1] != '\r'))
[400]313 Runtime_Error(pszSrcFile, uiLineNumber, "missing EOL");
314 }
315 return psz;
316}
317
[551]318PSZ xfgets_bstripcr(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
319 UINT uiLineNumber)
[400]320{
[551]321 PSZ psz = xfgets(pszBuf, cMaxBytes, fp, pszSrcFile, uiLineNumber);
322
[400]323 if (psz)
324 bstripcr(psz);
325 return psz;
326}
327
[551]328FILE *xfopen(PCSZ pszFileName, PCSZ pszMode, PCSZ pszSrcFile,
329 UINT uiLineNumber)
[395]330{
[551]331 FILE *fp = fopen(pszFileName, pszMode);
332
[395]333 if (!fp)
334 Runtime_Error(pszSrcFile, uiLineNumber, "fopen");
335 return fp;
336}
337
[551]338FILE *xfsopen(PCSZ pszFileName, PCSZ pszMode, INT fSharemode, PCSZ pszSrcFile,
339 UINT uiLineNumber)
[395]340{
[551]341 FILE *fp = _fsopen((PSZ) pszFileName, (PSZ) pszMode, fSharemode);
342
[395]343 if (!fp)
344 Runtime_Error(pszSrcFile, uiLineNumber, "_fsopen");
345 return fp;
346}
347
348//== xfree - safe free ==
349
[1009]350VOID xfree(PVOID pv, PCSZ pszSrcFile, UINT uiLineNumber)
[395]351{
[1009]352 if (pv && pv != NullStr) {
[1063]353# ifdef FORTIFY
[1009]354 Fortify_free(pv, pszSrcFile, uiLineNumber);
[1063]355# else
[395]356 free(pv);
[1063]357# endif
[1009]358
359 }
[395]360}
361
362//== xmalloc() malloc with error checking ==
363
364PVOID xmalloc(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
365{
[1006]366# ifdef FORTIFY
367 PVOID pv = Fortify_malloc(cBytes, pszSrcFile, uiLineNumber);
[1011]368# else
[395]369 PVOID pv = malloc(cBytes);
[1063]370# endif
[395]371
372 if (!pv)
[551]373 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]374
375 return pv;
376}
377
378//== xmallocz() malloc and zero with error checking ==
379
380PVOID xmallocz(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
381{
[1011]382 PVOID pv = xmalloc(cBytes, pszSrcFile, uiLineNumber);
[395]383
[1011]384 if (pv)
[395]385 memset(pv, 0, cBytes);
386
387 return pv;
388}
389
390//== xrealloc() realloc with error checking ==
391
392PVOID xrealloc(PVOID pvIn, size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
393{
[963]394 if (pvIn != NullStr) {
[1063]395# ifdef FORTIFY
396 PVOID pv = Fortify_realloc(pvIn, cBytes, pszSrcFile, uiLineNumber);
397# else
398 PVOID pv = realloc(pvIn, cBytes);
399# endif
[395]400
[963]401 if (!pv && cBytes)
402 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]403
[963]404 return pv;
405 }
406 else
407 return xmalloc(cBytes, pszSrcFile, uiLineNumber);
[395]408}
409
410//== xstrdup() strdup with error checking ==
411
412PVOID xstrdup(PCSZ pszIn, PCSZ pszSrcFile, UINT uiLineNumber)
413{
[1009]414# ifdef FORTIFY
415 PSZ psz = Fortify_strdup(pszIn, pszSrcFile, uiLineNumber);
[1011]416# else
[395]417 PSZ psz = strdup(pszIn);
[1063]418# endif
[395]419
420 if (!psz)
[551]421 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]422
423 return psz;
424}
[794]425
[1032]426
427#pragma alloc_text(WRAPPERS1,xfree,xfopen,xfsopen,xmalloc,xrealloc,xstrdup)
[1037]428#pragma alloc_text(WRAPPERS2,xDosSetPathInfo,xDosFindFirst,xDosFindNext)
Note: See TracBrowser for help on using the repository browser.