source: trunk/dll/wrappers.c@ 1357

Last change on this file since 1357 was 1354, checked in by Gregg Young, 17 years ago

Added driveflags to over ride write verify for USB removable drives that fail when it is on (Ticket 323); A flag to prevent directory name from being broadcast to drives in the tree cnr prior to a recursive scan of the drive (causes dbl directory names Ticket 321) Add option for multithreaded recursive scan of user selected drives at startup (Ticket 322).

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