source: trunk/dll/wrappers.c@ 1036

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

More fortify changes eliminated the leave scope wrapper except in mainwnd.c Wrapper only unlaods stuuff (archivers, commands, etc

  • 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 1036 2008-07-01 22:53:51Z 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 return ret;
421}
422# endif
423
424#pragma alloc_text(WRAPPERS1,xfree,xfopen,xfsopen,xmalloc,xrealloc,xstrdup)
425#pragma alloc_text(WRAPPERS2,xDosSetPathInfo,xDosFindFirst,xDosFindNext,xFortify_LeaveScope)
Note: See TracBrowser for help on using the repository browser.