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
RevLine 
[395]1
2/***********************************************************************
3
4 $Id: wrappers.c 1439 2009-07-12 21:57:04Z 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
[1439]19 12 Jul 09 GKY Add xDosQueryAppType and xDoxAlloc... to allow FM/2 to load in high memory
[395]20
21***********************************************************************/
22
[907]23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
[1354]26#include <ctype.h>
[907]27
[395]28#define INCL_WIN
[826]29#define INCL_DOS
30#define INCL_DOSERRORS
[841]31#define INCL_LONGLONG
[395]32#include <os2.h>
33
34#include "fm3dll.h"
[1215]35#include "init.h" // Data declaration(s)
[1182]36#include "wrappers.h"
[395]37#include "fm3str.h"
[907]38#include "errutil.h" // Dos_Error...
39#include "strutil.h" // GetPString
[1032]40#include "command.h"
41#include "tools.h"
42#include "avl.h"
[1182]43#include "strips.h" // bstrip
[395]44
[1005]45#include "fortify.h" // GetPString
[1354]46#include "info.h" // driveflags
47#include "notebook.h" // fVerify
[1439]48#include "pathutil.h" // MaxComLineStrg
[1005]49
[1215]50// Data definitions
[827]51static PSZ pszSrcFile = __FILE__;
52
[1215]53#pragma data_seg(GLOBAL1)
54BOOL fNoLargeFileSupport;
55
[1439]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
[1438]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);
[1439]88 //DbgMsg(pszSrcFile, __LINE__, "ppb %p", *ppb);
[1438]89 if (rc)
90 rc = DosAllocSharedMem(ppb, pszName, cb, flag);
91 return rc;
92}
93
94APIRET xDosAllocMem(PPVOID ppb,
95 ULONG cb,
[1439]96 ULONG flag,
97 PCSZ pszSrcFile,
98 UINT uiLineNumber)
[1438]99{
100 APIRET rc;
101
102 rc = DosAllocMem(ppb, cb, flag | OBJ_ANY);
[1439]103 //DbgMsg(pszSrcFile, uiLineNumber, "ppb %p %x", *ppb, rc);
[1438]104 if (rc)
105 rc = DosAllocMem(ppb, cb, flag);
[1439]106 //DbgMsg(pszSrcFile, uiLineNumber, "ppb %p", *ppb);
[1438]107 return rc;
108}
109
[850]110APIRET xDosFindFirst(PSZ pszFileSpec,
111 PHDIR phdir,
112 ULONG flAttribute,
113 PVOID pfindbuf,
114 ULONG cbBuf,
115 PULONG pcFileNames,
116 ULONG ulInfoLevel)
[838]117{
[850]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 }
[849]137 break;
[850]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 }
[849]155 break;
156 default:
[850]157 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
158 rc = ERROR_INVALID_PARAMETER;
159 } // switch
160 }
161 else
[838]162 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, pfindbuf, cbBuf,
[850]163 pcFileNames, ulInfoLevel);
164 return rc;
[838]165}
166
[850]167APIRET xDosFindNext(HDIR hDir,
168 PVOID pfindbuf,
169 ULONG cbfindbuf,
170 PULONG pcFileNames,
171 ULONG ulInfoLevel)
[838]172{
173 APIRET rc;
[849]174 if (fNoLargeFileSupport) {
[850]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
[849]211 }
212 else
[850]213 rc = DosFindNext(hDir, pfindbuf, cbfindbuf, pcFileNames);
[838]214
215 return rc;
216}
217
[827]218/**
[850]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
[1432]256 rc = DosQueryPathInfo (pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf);
[850]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 *
[827]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
[847]272 * @param pInfoBuf pointer to FILESTATUS3(L) or EAOP2 buffer
273 * @param ulInfoLevel FIL_STANDARD(L) or FIL_QUERYEASIZE
[827]274 * @returns Same as DosSetPathInfo
275 */
276
[841]277APIRET xDosSetPathInfo(PSZ pszPathName,
[850]278 ULONG ulInfoLevel,
[841]279 PVOID pInfoBuf,
280 ULONG cbInfoBuf,
[850]281 ULONG flOptions)
[826]282{
[850]283 FILESTATUS3 fs3;
284 FILESTATUS3 fs3_a;
285 FILESTATUS3L fs3l;
286 EAOP2 eaop2;
[849]287 APIRET rc;
[968]288 BOOL crosses = ((ULONG)pInfoBuf ^
[1354]289 ((ULONG)pInfoBuf + cbInfoBuf - 1)) & ~0xffff;
290 BOOL fResetVerify = FALSE;
[850]291
[1354]292 if (fVerify && driveflags[toupper(*pszPathName) - 'A'] & DRIVE_WRITEVERIFYOFF) {
293 DosSetVerify(FALSE);
294 fResetVerify = TRUE;
295 }
[850]296 switch (ulInfoLevel) {
297 case FIL_STANDARD:
[975]298 if (crosses) {
[968]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);
[850]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);
[932]342 }
343 break;
[827]344 default:
345 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
346 rc = ERROR_INVALID_PARAMETER;
[850]347 } // switch
[1354]348 if (fResetVerify) {
349 DosSetVerify(fVerify);
350 fResetVerify = FALSE;
351 }
[826]352 return rc;
353}
354
[551]355PSZ xfgets(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
356 UINT uiLineNumber)
[400]357{
[551]358 PSZ psz = fgets(pszBuf, cMaxBytes, fp);
359
[400]360 if (!psz) {
361 if (ferror(fp))
362 Runtime_Error(pszSrcFile, uiLineNumber, "fgets");
363 }
364 else {
365 size_t c = strlen(psz);
[551]366
[400]367 if (c + 1 > cMaxBytes)
368 Runtime_Error(pszSrcFile, uiLineNumber, "buffer overflow");
[551]369 else if (!c || (psz[c - 1] != '\n' && psz[c - 1] != '\r'))
[400]370 Runtime_Error(pszSrcFile, uiLineNumber, "missing EOL");
371 }
372 return psz;
373}
374
[551]375PSZ xfgets_bstripcr(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
376 UINT uiLineNumber)
[400]377{
[551]378 PSZ psz = xfgets(pszBuf, cMaxBytes, fp, pszSrcFile, uiLineNumber);
379
[400]380 if (psz)
381 bstripcr(psz);
382 return psz;
383}
384
[551]385FILE *xfopen(PCSZ pszFileName, PCSZ pszMode, PCSZ pszSrcFile,
386 UINT uiLineNumber)
[395]387{
[551]388 FILE *fp = fopen(pszFileName, pszMode);
389
[395]390 if (!fp)
391 Runtime_Error(pszSrcFile, uiLineNumber, "fopen");
392 return fp;
393}
394
[551]395FILE *xfsopen(PCSZ pszFileName, PCSZ pszMode, INT fSharemode, PCSZ pszSrcFile,
396 UINT uiLineNumber)
[395]397{
[1398]398 FILE *fp = _fsopen(pszFileName, pszMode, fSharemode);
[551]399
[395]400 if (!fp)
401 Runtime_Error(pszSrcFile, uiLineNumber, "_fsopen");
402 return fp;
403}
404
405//== xfree - safe free ==
406
[1009]407VOID xfree(PVOID pv, PCSZ pszSrcFile, UINT uiLineNumber)
[395]408{
[1009]409 if (pv && pv != NullStr) {
[1063]410# ifdef FORTIFY
[1009]411 Fortify_free(pv, pszSrcFile, uiLineNumber);
[1063]412# else
[395]413 free(pv);
[1063]414# endif
[1009]415
416 }
[395]417}
418
419//== xmalloc() malloc with error checking ==
420
421PVOID xmalloc(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
422{
[1006]423# ifdef FORTIFY
424 PVOID pv = Fortify_malloc(cBytes, pszSrcFile, uiLineNumber);
[1011]425# else
[395]426 PVOID pv = malloc(cBytes);
[1063]427# endif
[395]428
429 if (!pv)
[551]430 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]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{
[1011]439 PVOID pv = xmalloc(cBytes, pszSrcFile, uiLineNumber);
[395]440
[1011]441 if (pv)
[395]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{
[963]451 if (pvIn != NullStr) {
[1063]452# ifdef FORTIFY
453 PVOID pv = Fortify_realloc(pvIn, cBytes, pszSrcFile, uiLineNumber);
454# else
455 PVOID pv = realloc(pvIn, cBytes);
456# endif
[395]457
[963]458 if (!pv && cBytes)
459 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]460
[963]461 return pv;
462 }
463 else
464 return xmalloc(cBytes, pszSrcFile, uiLineNumber);
[395]465}
466
467//== xstrdup() strdup with error checking ==
468
469PVOID xstrdup(PCSZ pszIn, PCSZ pszSrcFile, UINT uiLineNumber)
470{
[1009]471# ifdef FORTIFY
472 PSZ psz = Fortify_strdup(pszIn, pszSrcFile, uiLineNumber);
[1011]473# else
[395]474 PSZ psz = strdup(pszIn);
[1063]475# endif
[395]476
477 if (!psz)
[551]478 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]479
480 return psz;
481}
[794]482
[1032]483
484#pragma alloc_text(WRAPPERS1,xfree,xfopen,xfsopen,xmalloc,xrealloc,xstrdup)
[1037]485#pragma alloc_text(WRAPPERS2,xDosSetPathInfo,xDosFindFirst,xDosFindNext)
Note: See TracBrowser for help on using the repository browser.