source: trunk/dll/wrappers.c@ 907

Last change on this file since 907 was 907, checked in by Steven Levine, 18 years ago

Avoid out of memory traps in Compare Directories
Rework Compare Directories progress display for 2 second update rate
Start refactoring to reduce dependence on fm3dll.h
Add timer services (IsITimerExpired etc.)

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