source: trunk/dll/wrappers.c@ 1438

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

Improved drivebar changes; Added AddBackslashToPath() to remove repeatative code. replaced "
" with PCSZ variable; ANY_OBJ added the DosAlloc... (experimental)

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