source: trunk/dll/wrappers.c@ 1432

Last change on this file since 1432 was 1432, checked in by Steven Levine, 16 years ago

Correct missing rc set

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