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
Line 
1
2/***********************************************************************
3
4 $Id: wrappers.c 1476 2009-11-15 22:11:36Z gyoung $
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 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
21
22***********************************************************************/
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <ctype.h>
28
29#define INCL_WIN
30#define INCL_DOS
31#define INCL_DOSERRORS
32#define INCL_LONGLONG
33#include <os2.h>
34
35#include "fm3dll.h"
36#include "init.h" // Data declaration(s)
37#include "wrappers.h"
38#include "fm3str.h"
39#include "errutil.h" // Dos_Error...
40#include "strutil.h" // GetPString
41#include "command.h"
42#include "tools.h"
43#include "avl.h"
44#include "strips.h" // bstrip
45
46#include "fortify.h" // GetPString
47#include "info.h" // driveflags
48#include "notebook.h" // fVerify
49#include "pathutil.h" // MaxComLineStrg
50
51// Data definitions
52static PSZ pszSrcFile = __FILE__;
53
54#pragma data_seg(GLOBAL1)
55BOOL fNoLargeFileSupport;
56
57APIRET xDosQueryAppType(PCSZ pszName, PULONG pFlags)
58{
59 APIRET rc;
60 CHAR szPgm[CCHMAXPATH];
61
62 strcpy(szPgm, pszName);
63 rc = DosQueryAppType(szPgm, pFlags);
64 return rc;
65}
66
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);
75 //DbgMsg(pszSrcFile, __LINE__, "ppb %p", *ppb);
76 if (rc)
77 rc = DosAllocSharedMem(ppb, pszName, cb, flag);
78 return rc;
79}
80
81APIRET xDosAllocMem(PPVOID ppb,
82 ULONG cb,
83 ULONG flag,
84 PCSZ pszSrcFile,
85 UINT uiLineNumber)
86{
87 APIRET rc;
88
89 rc = DosAllocMem(ppb, cb, flag | OBJ_ANY);
90 //DbgMsg(pszSrcFile, uiLineNumber, "ppb %p %x", *ppb, rc);
91 if (rc)
92 rc = DosAllocMem(ppb, cb, flag);
93 //DbgMsg(pszSrcFile, uiLineNumber, "ppb %p", *ppb);
94 return rc;
95}
96
97APIRET xDosFindFirst(PSZ pszFileSpec,
98 PHDIR phdir,
99 ULONG flAttribute,
100 PVOID pfindbuf,
101 ULONG cbBuf,
102 PULONG pcFileNames,
103 ULONG ulInfoLevel)
104{
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 }
124 break;
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 }
142 break;
143 default:
144 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
145 rc = ERROR_INVALID_PARAMETER;
146 } // switch
147 }
148 else
149 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, pfindbuf, cbBuf,
150 pcFileNames, ulInfoLevel);
151 return rc;
152}
153
154APIRET xDosFindNext(HDIR hDir,
155 PVOID pfindbuf,
156 ULONG cbfindbuf,
157 PULONG pcFileNames,
158 ULONG ulInfoLevel)
159{
160 APIRET rc;
161 if (fNoLargeFileSupport) {
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
198 }
199 else
200 rc = DosFindNext(hDir, pfindbuf, cbfindbuf, pcFileNames);
201
202 return rc;
203}
204
205/**
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
243 rc = DosQueryPathInfo (pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf);
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 *
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
259 * @param pInfoBuf pointer to FILESTATUS3(L) or EAOP2 buffer
260 * @param ulInfoLevel FIL_STANDARD(L) or FIL_QUERYEASIZE
261 * @returns Same as DosSetPathInfo
262 */
263
264APIRET xDosSetPathInfo(PSZ pszPathName,
265 ULONG ulInfoLevel,
266 PVOID pInfoBuf,
267 ULONG cbInfoBuf,
268 ULONG flOptions)
269{
270 FILESTATUS3 fs3;
271 FILESTATUS3 fs3_a;
272 FILESTATUS3L fs3l;
273 EAOP2 eaop2;
274 APIRET rc;
275 BOOL crosses = ((ULONG)pInfoBuf ^
276 ((ULONG)pInfoBuf + cbInfoBuf - 1)) & ~0xffff;
277 BOOL fResetVerify = FALSE;
278
279 if (fVerify && driveflags[toupper(*pszPathName) - 'A'] & DRIVE_WRITEVERIFYOFF) {
280 DosSetVerify(FALSE);
281 fResetVerify = TRUE;
282 }
283 switch (ulInfoLevel) {
284 case FIL_STANDARD:
285 if (crosses) {
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);
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);
329 }
330 break;
331 default:
332 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
333 rc = ERROR_INVALID_PARAMETER;
334 } // switch
335 if (fResetVerify) {
336 DosSetVerify(fVerify);
337 fResetVerify = FALSE;
338 }
339 return rc;
340}
341
342PSZ xfgets(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
343 UINT uiLineNumber)
344{
345 PSZ psz = fgets(pszBuf, cMaxBytes, fp);
346
347 if (!psz) {
348 if (ferror(fp))
349 Runtime_Error(pszSrcFile, uiLineNumber, "fgets");
350 }
351 else {
352 size_t c = strlen(psz);
353
354 if (c + 1 > cMaxBytes)
355 Runtime_Error(pszSrcFile, uiLineNumber, "buffer overflow");
356 else if (!c || (psz[c - 1] != '\n' && psz[c - 1] != '\r'))
357 Runtime_Error(pszSrcFile, uiLineNumber, "missing EOL");
358 }
359 return psz;
360}
361
362PSZ xfgets_bstripcr(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
363 UINT uiLineNumber)
364{
365 PSZ psz = xfgets(pszBuf, cMaxBytes, fp, pszSrcFile, uiLineNumber);
366
367 if (psz)
368 bstripcr(psz);
369 return psz;
370}
371
372FILE *xfopen(PCSZ pszFileName, PCSZ pszMode, PCSZ pszSrcFile,
373 UINT uiLineNumber)
374{
375 FILE *fp = fopen(pszFileName, pszMode);
376
377 if (!fp)
378 Runtime_Error(pszSrcFile, uiLineNumber, "fopen");
379 return fp;
380}
381
382FILE *xfsopen(PCSZ pszFileName, PCSZ pszMode, INT fSharemode, PCSZ pszSrcFile,
383 UINT uiLineNumber)
384{
385 FILE *fp = _fsopen(pszFileName, pszMode, fSharemode);
386
387 if (!fp)
388 Runtime_Error(pszSrcFile, uiLineNumber, "_fsopen");
389 return fp;
390}
391
392//== xfree - safe free ==
393
394VOID xfree(PVOID pv, PCSZ pszSrcFile, UINT uiLineNumber)
395{
396 if (pv && pv != NullStr) {
397# ifdef FORTIFY
398 Fortify_free(pv, pszSrcFile, uiLineNumber);
399# else
400 free(pv);
401# endif
402
403 }
404}
405
406//== xmalloc() malloc with error checking ==
407
408PVOID xmalloc(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
409{
410# ifdef FORTIFY
411 PVOID pv = Fortify_malloc(cBytes, pszSrcFile, uiLineNumber);
412# else
413 PVOID pv = malloc(cBytes);
414# endif
415
416 if (!pv)
417 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
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{
426 PVOID pv = xmalloc(cBytes, pszSrcFile, uiLineNumber);
427
428 if (pv)
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{
438 if (pvIn != NullStr) {
439# ifdef FORTIFY
440 PVOID pv = Fortify_realloc(pvIn, cBytes, pszSrcFile, uiLineNumber);
441# else
442 PVOID pv = realloc(pvIn, cBytes);
443# endif
444
445 if (!pv && cBytes)
446 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
447
448 return pv;
449 }
450 else
451 return xmalloc(cBytes, pszSrcFile, uiLineNumber);
452}
453
454//== xstrdup() strdup with error checking ==
455
456PVOID xstrdup(PCSZ pszIn, PCSZ pszSrcFile, UINT uiLineNumber)
457{
458# ifdef FORTIFY
459 PSZ psz = Fortify_strdup(pszIn, pszSrcFile, uiLineNumber);
460# else
461 PSZ psz = strdup(pszIn);
462# endif
463
464 if (!psz)
465 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
466
467 return psz;
468}
469
470
471#pragma alloc_text(WRAPPERS1,xfree,xfopen,xfsopen,xmalloc,xrealloc,xstrdup)
472#pragma alloc_text(WRAPPERS2,xDosSetPathInfo,xDosFindFirst,xDosFindNext)
Note: See TracBrowser for help on using the repository browser.