source: trunk/dll/wrappers.c@ 1844

Last change on this file since 1844 was 1839, checked in by Steven Levine, 10 years ago

xDosGetInfoBlocks

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