source: trunk/dll/wrappers.c@ 1398

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

Move embeded strings to PCSZ variables or string table; Eliminate Error2 functions Runtime_Error with NULL format string returns "No data" error. Change declares from PSZ to PCSZ in functions where the variable isn't changed. Added btm as an executable file type in several additional places. Use fProtectOnly to prevent attempt to execute Dos and Win programs on "Protect only" installs in several additional places.

  • 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 1398 2009-02-21 17:43:00Z 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{
[1398]341 FILE *fp = _fsopen(pszFileName, pszMode, fSharemode);
[551]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.