source: trunk/dll/wrappers.c@ 1034

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

More fortify changes

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