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
Line 
1
2/***********************************************************************
3
4 $Id: wrappers.c 1432 2009-06-18 01:35:27Z stevenhl $
5
6 Wrappers with error checking
7
8 Copyright (c) 2006, 2008 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 05 May 08 SHL Add FORTIFY support
17 25 Dec 08 GKY Add code to allow write verify to be turned off on a per drive basis
18 17 Jun 09 SHL Correct missing rc set
19
20***********************************************************************/
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <ctype.h>
26
27#define INCL_WIN
28#define INCL_DOS
29#define INCL_DOSERRORS
30#define INCL_LONGLONG
31#include <os2.h>
32
33#include "fm3dll.h"
34#include "init.h" // Data declaration(s)
35#include "wrappers.h"
36#include "fm3str.h"
37#include "errutil.h" // Dos_Error...
38#include "strutil.h" // GetPString
39#include "command.h"
40#include "tools.h"
41#include "avl.h"
42#include "strips.h" // bstrip
43
44#include "fortify.h" // GetPString
45#include "info.h" // driveflags
46#include "notebook.h" // fVerify
47
48// Data definitions
49static PSZ pszSrcFile = __FILE__;
50
51#pragma data_seg(GLOBAL1)
52BOOL fNoLargeFileSupport;
53
54APIRET xDosFindFirst(PSZ pszFileSpec,
55 PHDIR phdir,
56 ULONG flAttribute,
57 PVOID pfindbuf,
58 ULONG cbBuf,
59 PULONG pcFileNames,
60 ULONG ulInfoLevel)
61{
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 }
81 break;
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 }
99 break;
100 default:
101 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
102 rc = ERROR_INVALID_PARAMETER;
103 } // switch
104 }
105 else
106 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, pfindbuf, cbBuf,
107 pcFileNames, ulInfoLevel);
108 return rc;
109}
110
111APIRET xDosFindNext(HDIR hDir,
112 PVOID pfindbuf,
113 ULONG cbfindbuf,
114 PULONG pcFileNames,
115 ULONG ulInfoLevel)
116{
117 APIRET rc;
118 if (fNoLargeFileSupport) {
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
155 }
156 else
157 rc = DosFindNext(hDir, pfindbuf, cbfindbuf, pcFileNames);
158
159 return rc;
160}
161
162/**
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
200 rc = DosQueryPathInfo (pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf);
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 *
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
216 * @param pInfoBuf pointer to FILESTATUS3(L) or EAOP2 buffer
217 * @param ulInfoLevel FIL_STANDARD(L) or FIL_QUERYEASIZE
218 * @returns Same as DosSetPathInfo
219 */
220
221APIRET xDosSetPathInfo(PSZ pszPathName,
222 ULONG ulInfoLevel,
223 PVOID pInfoBuf,
224 ULONG cbInfoBuf,
225 ULONG flOptions)
226{
227 FILESTATUS3 fs3;
228 FILESTATUS3 fs3_a;
229 FILESTATUS3L fs3l;
230 EAOP2 eaop2;
231 APIRET rc;
232 BOOL crosses = ((ULONG)pInfoBuf ^
233 ((ULONG)pInfoBuf + cbInfoBuf - 1)) & ~0xffff;
234 BOOL fResetVerify = FALSE;
235
236 if (fVerify && driveflags[toupper(*pszPathName) - 'A'] & DRIVE_WRITEVERIFYOFF) {
237 DosSetVerify(FALSE);
238 fResetVerify = TRUE;
239 }
240 switch (ulInfoLevel) {
241 case FIL_STANDARD:
242 if (crosses) {
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);
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);
286 }
287 break;
288 default:
289 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
290 rc = ERROR_INVALID_PARAMETER;
291 } // switch
292 if (fResetVerify) {
293 DosSetVerify(fVerify);
294 fResetVerify = FALSE;
295 }
296 return rc;
297}
298
299PSZ xfgets(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
300 UINT uiLineNumber)
301{
302 PSZ psz = fgets(pszBuf, cMaxBytes, fp);
303
304 if (!psz) {
305 if (ferror(fp))
306 Runtime_Error(pszSrcFile, uiLineNumber, "fgets");
307 }
308 else {
309 size_t c = strlen(psz);
310
311 if (c + 1 > cMaxBytes)
312 Runtime_Error(pszSrcFile, uiLineNumber, "buffer overflow");
313 else if (!c || (psz[c - 1] != '\n' && psz[c - 1] != '\r'))
314 Runtime_Error(pszSrcFile, uiLineNumber, "missing EOL");
315 }
316 return psz;
317}
318
319PSZ xfgets_bstripcr(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
320 UINT uiLineNumber)
321{
322 PSZ psz = xfgets(pszBuf, cMaxBytes, fp, pszSrcFile, uiLineNumber);
323
324 if (psz)
325 bstripcr(psz);
326 return psz;
327}
328
329FILE *xfopen(PCSZ pszFileName, PCSZ pszMode, PCSZ pszSrcFile,
330 UINT uiLineNumber)
331{
332 FILE *fp = fopen(pszFileName, pszMode);
333
334 if (!fp)
335 Runtime_Error(pszSrcFile, uiLineNumber, "fopen");
336 return fp;
337}
338
339FILE *xfsopen(PCSZ pszFileName, PCSZ pszMode, INT fSharemode, PCSZ pszSrcFile,
340 UINT uiLineNumber)
341{
342 FILE *fp = _fsopen(pszFileName, pszMode, fSharemode);
343
344 if (!fp)
345 Runtime_Error(pszSrcFile, uiLineNumber, "_fsopen");
346 return fp;
347}
348
349//== xfree - safe free ==
350
351VOID xfree(PVOID pv, PCSZ pszSrcFile, UINT uiLineNumber)
352{
353 if (pv && pv != NullStr) {
354# ifdef FORTIFY
355 Fortify_free(pv, pszSrcFile, uiLineNumber);
356# else
357 free(pv);
358# endif
359
360 }
361}
362
363//== xmalloc() malloc with error checking ==
364
365PVOID xmalloc(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
366{
367# ifdef FORTIFY
368 PVOID pv = Fortify_malloc(cBytes, pszSrcFile, uiLineNumber);
369# else
370 PVOID pv = malloc(cBytes);
371# endif
372
373 if (!pv)
374 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
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{
383 PVOID pv = xmalloc(cBytes, pszSrcFile, uiLineNumber);
384
385 if (pv)
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{
395 if (pvIn != NullStr) {
396# ifdef FORTIFY
397 PVOID pv = Fortify_realloc(pvIn, cBytes, pszSrcFile, uiLineNumber);
398# else
399 PVOID pv = realloc(pvIn, cBytes);
400# endif
401
402 if (!pv && cBytes)
403 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
404
405 return pv;
406 }
407 else
408 return xmalloc(cBytes, pszSrcFile, uiLineNumber);
409}
410
411//== xstrdup() strdup with error checking ==
412
413PVOID xstrdup(PCSZ pszIn, PCSZ pszSrcFile, UINT uiLineNumber)
414{
415# ifdef FORTIFY
416 PSZ psz = Fortify_strdup(pszIn, pszSrcFile, uiLineNumber);
417# else
418 PSZ psz = strdup(pszIn);
419# endif
420
421 if (!psz)
422 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
423
424 return psz;
425}
426
427
428#pragma alloc_text(WRAPPERS1,xfree,xfopen,xfsopen,xmalloc,xrealloc,xstrdup)
429#pragma alloc_text(WRAPPERS2,xDosSetPathInfo,xDosFindFirst,xDosFindNext)
Note: See TracBrowser for help on using the repository browser.