source: trunk/dll/wrappers.c@ 1476

Last change on this file since 1476 was 1476, checked in by Gregg Young, 16 years ago

Rework xDosQueryAppType to remove HIMEM ifdef

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