source: trunk/dll/wrappers.c@ 1439

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

Changes to allow high mem loading of dll; Refactor .LONGNAME and .SUBJECT EA fetch to FetchCommonEAs. Add szFSType to FillInRecordFromFSA use to bypass EA scan and size formatting for tree container; Fix labels/FS type to work on scan on NOPRESCAN Drives; Fixed dbl directory names on restore of dir cnrs; (Tickets 47, 339, 363, 368, 369, 370)

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