source: trunk/dll/wrappers.c@ 1845

Last change on this file since 1845 was 1845, checked in by John Small, 10 years ago

Ticket #524: Ensure no "highmem-unsafe" functions are called directly
1) New functions have been added
2) Code for unsafe-but-not-yet-used-by-FM/2 has been added in an

"#if 0" block in wrappers.c for quick implementation should FM/2 start to use them.
Among these. xDosOpenL and xWinUpper still need work. The rest are ready for use.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.6 KB
Line 
1
2/***********************************************************************
3
4 $Id: wrappers.c 1845 2015-08-12 19:54:49Z jbs $
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 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 12 Aug 15 JBS Ticket #524: Ensure no "highmem-unsafe" functions are called directly
26 1) New functions have been added
27 2) Code for unsafe-but-not-yet-used-by-FM/2 has been added in an
28 "#if 0" block for quick implementation should FM/2 start to use them.
29 Among these. xDosOpenL and xWinUpper still need work. The rest are ready for use.
30
31***********************************************************************/
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <ctype.h>
37
38#define INCL_WIN
39#define INCL_DOS
40#define INCL_DOSERRORS
41#define INCL_LONGLONG
42#include <os2.h>
43
44#include "fm3dll.h"
45#include "init.h" // Data declaration(s)
46#include "wrappers.h"
47#include "fm3str.h"
48#include "errutil.h" // Dos_Error...
49#include "strutil.h" // GetPString
50#include "command.h"
51#include "tools.h"
52#include "avl.h"
53#include "strips.h" // bstrip
54
55#include "fortify.h" // GetPString
56#include "info.h" // driveflags
57#include "notebook.h" // fVerify
58#include "pathutil.h" // MaxComLineStrg
59
60// Data definitions
61static PSZ pszSrcFile = __FILE__;
62
63#pragma data_seg(GLOBAL1)
64BOOL fNoLargeFileSupport;
65
66APIRET xDosDupHandle(HFILE hFile,
67 PHFILE phFile)
68{
69 APIRET rc;
70 HFILE hFileLow = *phFile;
71
72 rc = DosDupHandle(hFile, &hFileLow);
73 *phFile = hFileLow;
74 return rc;
75}
76
77APIRET xDosForceDelete(PSZ pszFileName)
78{
79 APIRET rc;
80 CHAR szFileNameLow[CCHMAXPATH];
81
82 strcpy(szFileNameLow, pszFileName);
83 rc = DosForceDelete(szFileNameLow);
84 return rc;
85}
86
87APIRET xDosQueryAppType(PCSZ pszName,
88 PULONG pFlags)
89{
90 APIRET rc;
91 ULONG ulFlagsLow;
92 CHAR szPgm[CCHMAXPATH];
93
94 strcpy(szPgm, pszName);
95 rc = DosQueryAppType(szPgm, &ulFlagsLow);
96 *pFlags = ulFlagsLow;
97 return rc;
98}
99
100APIRET xDosQueryHType(HFILE hFile,
101 PULONG pulType,
102 PULONG pulAttr)
103{
104 APIRET rc;
105 ULONG ulTypeLow, ulAttrLow;
106
107 rc = DosQueryHType(hFile, &ulTypeLow, &ulAttrLow);
108 *pulType = ulTypeLow;
109 *pulAttr = ulAttrLow;
110 return rc;
111}
112
113APIRET xDosStartSession(PSTARTDATA psd,
114 PULONG pulSessionID,
115 PPID ppid)
116{
117 APIRET rc;
118 ULONG ulSessionIDLow;
119 PID pidLow;
120 PSTARTDATA psdLow;
121 CHAR *pbSafe;
122 size_t cbSafe = sizeof(STARTDATA);
123 UINT ul0, ul1, ul2, ul3, ul4, ul5;
124
125 if (HIGH_MEMORY_ADDRESS(psd->PgmTitle))
126 {
127 ul0 = strlen((const char *)psd->PgmTitle) + 1;
128 cbSafe += ul0;
129 }
130 else
131 ul0 = 0;
132 if (HIGH_MEMORY_ADDRESS(psd->PgmName))
133 {
134 ul1 = strlen((const char *)psd->PgmName) + 1;
135 cbSafe += ul1;
136 }
137 else
138 ul1 = 0;
139 if (HIGH_MEMORY_ADDRESS(psd->TermQ))
140 {
141 ul2 = strlen((const char *)psd->TermQ) + 1;
142 cbSafe += ul2;
143 }
144 else
145 ul2 = 0;
146 if (HIGH_MEMORY_ADDRESS(psd->PgmInputs))
147 {
148 ul3 = strlen((const char *)psd->PgmInputs) + 1;
149 cbSafe += ul3;
150 }
151 else
152 ul3= 0;
153 if (HIGH_MEMORY_ADDRESS(psd->Environment))
154 {
155 const char *psz = (const char *)psd->Environment;
156 while (*psz)
157 psz = strchr(psz, '\0') + 1;
158 ul4 = (unsigned int *)psz - (unsigned int *)psd->Environment + 1;
159 cbSafe += ul4;
160 }
161 else
162 ul4 = 0;
163 if (HIGH_MEMORY_ADDRESS(psd->IconFile))
164 {
165 ul5 = strlen((const char *)psd->IconFile) + 1;
166 cbSafe += ul5;
167 }
168 else
169 ul5 = 0;
170 if (HIGH_MEMORY_ADDRESS(psd->ObjectBuffer) && psd->ObjectBuffLen)
171 cbSafe += psd->ObjectBuffLen;
172
173 rc = xDosAllocMemLow((void *)&psdLow,
174 cbSafe,
175 pszSrcFile,
176 __LINE__);
177 if (rc)
178 return ERROR_NOT_ENOUGH_MEMORY;
179
180 memcpy((PVOID)psdLow, (PVOID)psd, sizeof(STARTDATA));
181 pbSafe = (CHAR *)psdLow + sizeof(STARTDATA);
182 if (ul0)
183 {
184 memcpy(pbSafe, psd->PgmTitle, ul0);
185 psdLow->PgmTitle = pbSafe;
186 pbSafe += ul0;
187 }
188 if (ul1)
189 {
190 memcpy(pbSafe, psd->PgmName, ul1);
191 psdLow->PgmName = pbSafe;
192 pbSafe += ul1;
193 }
194 if (ul2)
195 {
196 memcpy(pbSafe, psd->TermQ, ul2);
197 psdLow->TermQ = (UCHAR *)pbSafe;
198 pbSafe += ul2;
199 }
200 if (ul3)
201 {
202 memcpy(pbSafe, psd->PgmInputs, ul3);
203 psdLow->PgmInputs = (UCHAR *)pbSafe;
204 pbSafe += ul3;
205 }
206 if (ul4)
207 {
208 memcpy(pbSafe, psd->Environment, ul4);
209 psdLow->Environment = (UCHAR *)pbSafe;
210 pbSafe += ul4;
211 }
212 if (ul5)
213 {
214 memcpy(pbSafe, psd->IconFile, ul5);
215 psdLow->IconFile = pbSafe;
216 pbSafe += ul5;
217 }
218 if (HIGH_MEMORY_ADDRESS(psd->ObjectBuffer) && psd->ObjectBuffLen)
219 psdLow->ObjectBuffer = pbSafe;
220
221 rc = DosStartSession(psdLow,
222 pulSessionID ? &ulSessionIDLow : NULL,
223 ppid ? &pidLow : NULL);
224
225 /* Set return values */
226 if (HIGH_MEMORY_ADDRESS(psd->ObjectBuffer) && psd->ObjectBuffLen)
227 memcpy(psd->ObjectBuffer, psdLow->ObjectBuffer, psd->ObjectBuffLen);
228 if (pulSessionID)
229 *pulSessionID = ulSessionIDLow;
230 if (ppid)
231 *ppid = pidLow;
232
233 /* cleanup and return. */
234 xfree(psdLow, pszSrcFile, __LINE__);
235 return rc;
236}
237
238
239//
240// "Other" wrapper functions
241//
242/**
243 * xDosAllocSharedMem uses OBJ_ANY on systems that support high memory use
244 * and falls back to low memory allocation where it is not supported.
245 * Flags are hard coded PAG_COMMIT | OBJ_GIVEABLE | PAG_READ | PAG_WRITE
246 * The wrapper provides error checking.
247 */
248
249APIRET xDosAllocSharedMem(PPVOID ppb,
250 PSZ pszName,
251 ULONG cb,
252 PCSZ pszSrcFile,
253 UINT uiLineNumber)
254{
255 APIRET rc;
256
257 rc = DosAllocSharedMem(ppb, pszName, cb,
258 PAG_COMMIT | OBJ_GIVEABLE | PAG_READ | PAG_WRITE | OBJ_ANY);
259 //DbgMsg(pszSrcFile, __LINE__, "ppb %p", *ppb);
260 if (rc)
261 rc = DosAllocSharedMem(ppb, pszName, cb, PAG_COMMIT | OBJ_GIVEABLE | PAG_READ | PAG_WRITE);
262 if (rc)
263 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
264 return rc;
265}
266
267/**
268 * xDosAllocMem uses OBJ_ANY on systems that support high memory use
269 * and falls back to low memory allocation where it is not supported.
270 * Flags are hard coded PAG_COMMIT | PAG_READ | PAG_WRITE.
271 * The wrapper provides error checking.
272 */
273
274APIRET xDosAllocMem(PPVOID ppb,
275 ULONG cb,
276 PCSZ pszSrcFile,
277 UINT uiLineNumber)
278{
279 APIRET rc;
280
281 rc = DosAllocMem(ppb, cb, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_ANY);
282 //DbgMsg(pszSrcFile, uiLineNumber, "ppb %p %x", *ppb, rc);
283 if (rc)
284 rc = DosAllocMem(ppb, cb, PAG_COMMIT | PAG_READ | PAG_WRITE);
285 if (rc)
286 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
287 //DbgMsg(pszSrcFile, uiLineNumber, "ppb %p", *ppb);
288 return rc;
289}
290
291/**
292 * xDosAllocMemLow doesn't use OBJ_ANY. It should be used when the buffer
293 * is going to be used by 16 functions that fail to thunk high memory addresses properly
294 * such as DosQueryAppType, DosOpenL, DosGetMessage and DosReadQueue (probably others)
295 * Flags are hard coded PAG_COMMIT | PAG_READ | PAG_WRITE.
296 * The wrapper provides error checking.
297 */
298
299APIRET xDosAllocMemLow(PPVOID ppb,
300 ULONG cb,
301 PCSZ pszSrcFile,
302 UINT uiLineNumber)
303{
304 APIRET rc;
305
306 rc = DosAllocMem(ppb, cb, PAG_COMMIT | PAG_READ | PAG_WRITE);
307 if (rc)
308 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
309 //DbgMsg(pszSrcFile, uiLineNumber, "ppb %p", *ppb);
310 return rc;
311}
312
313APIRET xDosGetInfoBlocks(PTIB *pptib,
314 PPIB *pppib)
315{
316 APIRET apiret = DosGetInfoBlocks(pptib, pppib);
317
318 if (apiret) {
319 Dos_Error(MB_CANCEL, apiret, HWND_DESKTOP, pszSrcFile, __LINE__,
320 PCSZ_DOSGETINFOBLOCKS);
321 *pppib = 0;
322 *pptib = 0;
323 }
324 return apiret;
325}
326
327APIRET xDosFindFirst(PSZ pszFileSpec,
328 PHDIR phdir,
329 ULONG flAttribute,
330 PVOID pfindbuf,
331 ULONG cbBuf,
332 PULONG pcFileNames,
333 ULONG ulInfoLevel)
334{
335 APIRET rc;
336 if (fNoLargeFileSupport) {
337 switch (ulInfoLevel) {
338 case FIL_STANDARDL:
339 {
340 FILEFINDBUF3 ffb3;
341 ulInfoLevel = FIL_STANDARD;
342 *pcFileNames = 1; // fixme to support larger counts
343 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, &ffb3, sizeof(ffb3),
344 pcFileNames, ulInfoLevel);
345 if (!rc) {
346 *(PFILEFINDBUF3)pfindbuf = ffb3; // Copy aligned data
347 ((PFILEFINDBUF3L)pfindbuf)->cbFile = ffb3.cbFile; // Copy unaligned data
348 ((PFILEFINDBUF3L)pfindbuf)->cbFileAlloc = ffb3.cbFileAlloc;
349 ((PFILEFINDBUF3L)pfindbuf)->attrFile = ffb3.attrFile;
350 ((PFILEFINDBUF3L)pfindbuf)->cchName = ffb3.cchName;
351 memcpy(((PFILEFINDBUF3L)pfindbuf)->achName, ffb3.achName, ffb3.cchName + 1);
352 }
353 }
354 break;
355 case FIL_QUERYEASIZEL:
356 {
357 FILEFINDBUF4 ffb4;
358 *pcFileNames = 1; // fixme to support larger counts
359 ulInfoLevel = FIL_QUERYEASIZE;
360 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, &ffb4, sizeof(ffb4),
361 pcFileNames, ulInfoLevel);
362 if (!rc) {
363 *(PFILEFINDBUF4)pfindbuf = ffb4; // Copy aligned data
364 ((PFILEFINDBUF4L)pfindbuf)->cbFile = ffb4.cbFile; // Copy unaligned data
365 ((PFILEFINDBUF4L)pfindbuf)->cbFileAlloc = ffb4.cbFileAlloc;
366 ((PFILEFINDBUF4L)pfindbuf)->attrFile = ffb4.attrFile;
367 ((PFILEFINDBUF4L)pfindbuf)->cbList = ffb4.cbList;
368 ((PFILEFINDBUF4L)pfindbuf)->cchName = ffb4.cchName;
369 memcpy(((PFILEFINDBUF4L)pfindbuf)->achName, ffb4.achName, ffb4.cchName + 1);
370 }
371 }
372 break;
373 default:
374 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
375 rc = ERROR_INVALID_PARAMETER;
376 } // switch
377 }
378 else
379 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, pfindbuf, cbBuf,
380 pcFileNames, ulInfoLevel);
381 return rc;
382}
383
384APIRET xDosFindNext(HDIR hDir,
385 PVOID pfindbuf,
386 ULONG cbfindbuf,
387 PULONG pcFileNames,
388 ULONG ulInfoLevel)
389{
390 APIRET rc;
391 if (fNoLargeFileSupport) {
392 switch (ulInfoLevel) {
393 case FIL_STANDARDL:
394 {
395 FILEFINDBUF3 ffb3;
396 *pcFileNames = 1; // fixme to support larger counts
397 rc = DosFindNext(hDir, &ffb3, sizeof(ffb3), pcFileNames);
398 if (!rc) {
399 *(PFILEFINDBUF3)pfindbuf = ffb3; // Copy aligned data
400 ((PFILEFINDBUF3L)pfindbuf)->cbFile = ffb3.cbFile; // Copy unaligned data
401 ((PFILEFINDBUF3L)pfindbuf)->cbFileAlloc = ffb3.cbFileAlloc;
402 ((PFILEFINDBUF3L)pfindbuf)->attrFile = ffb3.attrFile;
403 ((PFILEFINDBUF3L)pfindbuf)->cchName = ffb3.cchName;
404 memcpy(((PFILEFINDBUF3L)pfindbuf)->achName, ffb3.achName, ffb3.cchName + 1);
405 }
406 }
407 break;
408 case FIL_QUERYEASIZEL:
409 {
410 FILEFINDBUF4 ffb4;
411 *pcFileNames = 1; // fixme to support larger counts
412 rc = DosFindNext(hDir, &ffb4, sizeof(ffb4), pcFileNames);
413 if (!rc) {
414 *(PFILEFINDBUF4)pfindbuf = ffb4; // Copy aligned data
415 ((PFILEFINDBUF4L)pfindbuf)->cbFile = ffb4.cbFile; // Copy unaligned data
416 ((PFILEFINDBUF4L)pfindbuf)->cbFileAlloc = ffb4.cbFileAlloc;
417 ((PFILEFINDBUF4L)pfindbuf)->attrFile = ffb4.attrFile;
418 ((PFILEFINDBUF4L)pfindbuf)->cbList = ffb4.cbList;
419 ((PFILEFINDBUF4L)pfindbuf)->cchName = ffb4.cchName;
420 memcpy(((PFILEFINDBUF4L)pfindbuf)->achName, ffb4.achName, ffb4.cchName + 1);
421 }
422 }
423 break;
424 default:
425 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
426 rc = ERROR_INVALID_PARAMETER;
427 } // switch
428 }
429 else
430 rc = DosFindNext(hDir, pfindbuf, cbfindbuf, pcFileNames);
431
432 return rc;
433}
434
435/**
436 * DosQueryPathInfo wrapper
437 * Translate request for systems without large file support
438 */
439
440APIRET xDosQueryPathInfo (PSZ pszPathName, ULONG ulInfoLevel, PVOID pInfoBuf, ULONG cbInfoBuf)
441{
442 FILESTATUS3 fs3;
443 FILESTATUS4 fs4;
444 APIRET rc;
445
446 if (fNoLargeFileSupport) {
447 switch (ulInfoLevel) {
448 case FIL_STANDARDL:
449 rc = DosQueryPathInfo(pszPathName, ulInfoLevel, &fs3, sizeof(fs3));
450 if (!rc) {
451 *(PFILESTATUS3)pInfoBuf = fs3; // Copy aligned data
452 ((PFILESTATUS3L)pInfoBuf)->cbFile = fs3.cbFile; // Copy unaligned data
453 ((PFILESTATUS3L)pInfoBuf)->cbFileAlloc = fs3.cbFileAlloc;
454 ((PFILESTATUS3L)pInfoBuf)->attrFile = fs3.attrFile;
455 }
456 break;
457 case FIL_QUERYEASIZEL:
458 rc = DosQueryPathInfo(pszPathName, ulInfoLevel, &fs4, sizeof(fs4));
459 if (!rc) {
460 *(PFILESTATUS4)pInfoBuf = fs4; // Copy aligned data
461 ((PFILESTATUS4L)pInfoBuf)->cbFile = fs4.cbFile; // Copy unaligned data
462 ((PFILESTATUS4L)pInfoBuf)->cbFileAlloc = fs4.cbFileAlloc;
463 ((PFILESTATUS4L)pInfoBuf)->attrFile = fs4.attrFile;
464 ((PFILESTATUS4L)pInfoBuf)->cbList = fs4.cbList;
465 }
466 break;
467 default:
468 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
469 rc = ERROR_INVALID_PARAMETER;
470 } // switch
471 }
472 else
473 rc = DosQueryPathInfo (pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf);
474
475 return rc;
476}
477
478/**
479 * Wrap DosSetPathInfo to avoid spurious ERROR_INVALID_NAME returns and
480 * support systems without large file support
481 *
482 * Some kernels do not correctly handle FILESTATUS3 and PEAOP2 buffers
483 * that cross a 64K boundary.
484 * When this occurs, they return ERROR_INVALID_NAME.
485 *
486 * This code works around the problem because if the passed buffer crosses
487 * the boundary the alternate buffer will not because both are on the stack
488 * and we don't put enough additional data on the stack for this to occur.
489 *
490 * It is caller's responsitibility to report errors
491 * @param pInfoBuf pointer to FILESTATUS3(L) or EAOP2 buffer
492 * @param ulInfoLevel FIL_STANDARD(L) or FIL_QUERYEASIZE
493 * @returns Same as DosSetPathInfo
494 */
495
496APIRET xDosSetPathInfo(PSZ pszPathName,
497 ULONG ulInfoLevel,
498 PVOID pInfoBuf,
499 ULONG cbInfoBuf,
500 ULONG flOptions)
501{
502 FILESTATUS3 fs3;
503 FILESTATUS3 fs3_a;
504 FILESTATUS3L fs3l;
505 EAOP2 eaop2;
506 APIRET rc;
507 BOOL crosses = ((ULONG)pInfoBuf ^
508 ((ULONG)pInfoBuf + cbInfoBuf - 1)) & ~0xffff;
509 BOOL fResetVerify = FALSE;
510
511 if (fVerify && driveflags[toupper(*pszPathName) - 'A'] & DRIVE_WRITEVERIFYOFF) {
512 DosSetVerify(FALSE);
513 fResetVerify = TRUE;
514 }
515 switch (ulInfoLevel) {
516 case FIL_STANDARD:
517 if (crosses) {
518 fs3 = *(PFILESTATUS3)pInfoBuf; // Copy to buffer that does not cross 64K boundary
519 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3, cbInfoBuf, flOptions);
520 }
521 else
522 rc = DosSetPathInfo(pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf, flOptions);
523 break;
524
525 case FIL_STANDARDL:
526 if (fNoLargeFileSupport) {
527 ulInfoLevel = FIL_STANDARD;
528 fs3 = *(PFILESTATUS3)pInfoBuf; // Copy aligned data
529 // Check size too big to handle
530 if (((PFILESTATUS3L)pInfoBuf)->cbFile >= 1LL << 32 ||
531 ((PFILESTATUS3L)pInfoBuf)->cbFileAlloc >= 2LL << 32)
532 {
533 rc = ERROR_INVALID_PARAMETER;
534 }
535 else {
536 fs3.cbFile = ((PFILESTATUS3L)pInfoBuf)->cbFile; // Copy unaligned data
537 fs3.cbFileAlloc = ((PFILESTATUS3L)pInfoBuf)->cbFileAlloc;
538 fs3.attrFile = ((PFILESTATUS3L)pInfoBuf)->attrFile;
539 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3, sizeof(fs3), flOptions);
540 }
541 if (rc == ERROR_INVALID_NAME) {
542 // fixme to validate counts?
543 fs3_a = fs3; // Copy to buffer that does not cross
544 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3_a, sizeof(fs3_a), flOptions);
545 }
546 }
547 else {
548 rc = DosSetPathInfo(pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf, flOptions);
549 if (rc == ERROR_INVALID_NAME) {
550 fs3l = *(PFILESTATUS3L)pInfoBuf; // Copy to buffer that does not cross
551 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3l, sizeof(fs3l), flOptions);
552 }
553 }
554 break;
555 case FIL_QUERYEASIZE:
556 rc = DosSetPathInfo(pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf, flOptions);
557 if (rc == ERROR_INVALID_NAME) {
558 // fixme to validate counts?
559 eaop2 = *(PEAOP2)pInfoBuf; // Copy to buffer that does not cross
560 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &eaop2, sizeof(eaop2), flOptions);
561 }
562 break;
563 default:
564 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
565 rc = ERROR_INVALID_PARAMETER;
566 } // switch
567 if (fResetVerify) {
568 DosSetVerify(fVerify);
569 fResetVerify = FALSE;
570 }
571 return rc;
572}
573
574PSZ xfgets(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
575 UINT uiLineNumber)
576{
577 PSZ psz = fgets(pszBuf, cMaxBytes, fp);
578
579 if (!psz) {
580 if (ferror(fp))
581 Runtime_Error(pszSrcFile, uiLineNumber, "fgets");
582 }
583 else {
584 size_t c = strlen(psz);
585
586 if (c + 1 > cMaxBytes)
587 Runtime_Error(pszSrcFile, uiLineNumber, "buffer overflow");
588 else if (!c || (psz[c - 1] != '\n' && psz[c - 1] != '\r'))
589 Runtime_Error(pszSrcFile, uiLineNumber, "missing EOL");
590 }
591 return psz;
592}
593
594PSZ xfgets_bstripcr(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
595 UINT uiLineNumber)
596{
597 PSZ psz = xfgets(pszBuf, cMaxBytes, fp, pszSrcFile, uiLineNumber);
598
599 if (psz)
600 bstripcr(psz);
601 return psz;
602}
603
604/**
605 * Wrapper for fopen it works around DosOpenL's failure to
606 * thunk properly so that fm2 can be loaded in high memory
607 * It also gives the option of reporting file open errors
608 * If fSilent is TRUE it fails silently; if FALSE it produces a
609 * runtime error dialog. Note pszMode must be passed on the stack
610 * to xfopen to avoid the thunking problem.
611 */
612
613FILE *xfopen(PCSZ pszFileName, PCSZ pszMode, PCSZ pszSrcFile,
614 UINT uiLineNumber, BOOL fSilent)
615{
616 CHAR FileName[CCHMAXPATH];
617 FILE *fp;
618
619 strcpy(FileName, pszFileName);
620 fp = fopen(FileName, pszMode);
621
622 if (!fp && !fSilent)
623 Runtime_Error(pszSrcFile, uiLineNumber, "fopen");
624 return fp;
625}
626
627/**
628 * Wrapper for _fsopen it works around DosOpenL's failure to
629 * thunk properly so that fm2 can be loaded in high memory
630 * It also gives the option of reporting file open errors
631 * If fSilent is TRUE it fails silently; if FALSE it produces a
632 * runtime error dialog. Note pszMode must be passed on the stack
633 * to xfopen to avoid the thunking problem
634 */
635
636FILE *xfsopen(PCSZ pszFileName, PCSZ pszMode, INT fSharemode, PCSZ pszSrcFile,
637 UINT uiLineNumber, BOOL fSilent)
638{
639 CHAR FileName[CCHMAXPATH];
640 FILE *fp;
641
642 strcpy(FileName, pszFileName);
643 fp = _fsopen(FileName, pszMode, fSharemode);
644 if (!fp && !strcmp(pszMode, "r+") && !fSilent)
645 fp = _fsopen(FileName, "w+", fSharemode);
646
647 if (!fp && !fSilent)
648 Runtime_Error(pszSrcFile, uiLineNumber, "_fsopen");
649 return fp;
650}
651
652//== xfree - safe free ==
653
654VOID xfree(PVOID pv, PCSZ pszSrcFile, UINT uiLineNumber)
655{
656 if (pv && pv != NullStr) {
657# ifdef FORTIFY
658 Fortify_free(pv, pszSrcFile, uiLineNumber);
659# else
660 free(pv);
661# endif
662
663 }
664}
665
666//== xmalloc() malloc with error checking ==
667
668PVOID xmalloc(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
669{
670# ifdef FORTIFY
671 PVOID pv = Fortify_malloc(cBytes, pszSrcFile, uiLineNumber);
672# else
673 PVOID pv = malloc(cBytes);
674# endif
675
676 if (!pv)
677 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
678
679 return pv;
680}
681
682//== xmallocz() malloc and zero with error checking ==
683
684PVOID xmallocz(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
685{
686 PVOID pv = xmalloc(cBytes, pszSrcFile, uiLineNumber);
687
688 if (pv)
689 memset(pv, 0, cBytes);
690
691 return pv;
692}
693
694//== xrealloc() realloc with error checking ==
695
696PVOID xrealloc(PVOID pvIn, size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
697{
698 if (pvIn != NullStr) {
699# ifdef FORTIFY
700 PVOID pv = Fortify_realloc(pvIn, cBytes, pszSrcFile, uiLineNumber);
701# else
702 PVOID pv = realloc(pvIn, cBytes);
703# endif
704
705 if (!pv && cBytes)
706 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
707
708 return pv;
709 }
710 else
711 return xmalloc(cBytes, pszSrcFile, uiLineNumber);
712}
713
714//== xstrdup() strdup with error checking ==
715
716PVOID xstrdup(PCSZ pszIn, PCSZ pszSrcFile, UINT uiLineNumber)
717{
718# ifdef FORTIFY
719 PSZ psz = Fortify_strdup(pszIn, pszSrcFile, uiLineNumber);
720# else
721 PSZ psz = strdup(pszIn);
722# endif
723
724 if (!psz)
725 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
726
727 return psz;
728}
729
730#if 0
731/*
732 * JBS: Wrappers for functions which...
733 * - are identified by klibc as "highmem-unsafe"
734 * - not yet used by FM/2
735 */
736
737// .H code for these functions
738// The following are ready to go.
739APIRET xDosCreatePipe(PHFILE phfReadHandle,
740 PHFILE phfWriteHandle,
741 ULONG ulPipeSize);
742
743APIRET xDosQueryFHState(HFILE hFile,
744 PULONG pulMode);
745
746#ifdef INCL_DOSNMPIPES
747APIRET xDosQueryNPHState(HPIPE hpipe,
748 PULONG pulState);
749#endif
750
751APIRET xDosSetDateTime(DATETIME *pdt);
752
753APIRET xDosSetFilePtr(HFILE hFile,
754 LONG lOffset,
755 ULONG ulOrigin,
756 PULONG pulPos);
757
758APIRET xDosSetFilePtrL(HFILE hFile,
759 LONGLONG llOffset,
760 ULONG ulOrigin,
761 PLONGLONG pllPos);
762
763#ifdef INCL_DOSPROCESS
764APIRET xDosWaitChild(ULONG ulAction,
765 ULONG ulWait,
766 PRESULTCODES pReturnCodes,
767 PPID ppidOut,
768 PID pidIn);
769#endif
770
771APIRET xDosWaitNPipe(PCSZ pszName,
772 ULONG ulTimeout);
773
774// The following functions still need work
775ULONG xWinUpper(HAB hab,
776 ULONG idcp,
777 ULONG idcc,
778 PSZ psz);
779
780APIRET xDosOpenL(PCSZ pszFileName,
781 PHFILE phFile,
782 PULONG pulAction,
783 LONGLONG llFileSize,
784 ULONG ulAttribute,
785 ULONG ulOpenFlags,
786 ULONG ulOpenMode,
787 PEAOP2 pEABuf);
788
789
790
791// .C code for the functions above
792APIRET xDosCreatePipe(PHFILE phfReadHandle,
793 PHFILE phfWriteHandle,
794 ULONG ulPipeSize)
795{
796 APIRET rc;
797 HFILE h1, h2;
798 PHFILE ph1 = NULL;
799 PHFILE ph2 = NULL;
800
801 if (phfReadHandle)
802 {
803 h1 = *phfReadHandle;
804 ph1 = &h1;
805 }
806 if (phfWriteHandle)
807 {
808 h2 = *phfWriteHandle;
809 ph2 = &h2;
810 }
811
812 rc = DosCreatePipe(ph1, ph2, ulPipeSize);
813
814 if (phfReadHandle)
815 *phfReadHandle = h1;
816 if (phfWriteHandle)
817 *phfWriteHandle = h2;
818 return rc;
819}
820
821// Code pEABuf
822APIRET xDosOpenL(PCSZ pszFileName,
823 PHFILE phFile,
824 PULONG pulAction,
825 LONGLONG llFileSize,
826 ULONG ulAttribute,
827 ULONG ulOpenFlags,
828 ULONG ulOpenMode,
829 PEAOP2 pEABuf)
830{
831 APIRET rc;
832 ULONG ul1;
833 PULONG pul1 = NULL;
834 HFILE hf1;
835 PHFILE phf1 = NULL;
836 char szFileNameLow[CCHMAXPATH];
837
838 strcpy(szFileNameLow, pszFileName);
839
840 if (phFile)
841 {
842 hf1 = *phFile;
843 phf1 = &hf1;
844 }
845 if (pulAction)
846 {
847 ul1 = *pulAction;
848 pul1 = &ul1;
849 }
850
851/** @todo pEABuf */
852
853 rc = DosOpenL(szFileNameLow, phf1, pul1, llFileSize, ulAttribute,
854 ulOpenFlags, ulOpenMode, pEABuf);
855
856 if (phFile)
857 *phFile = hf1;
858 if (pulAction)
859 *pulAction = ul1;
860
861 return rc;
862}
863
864APIRET xDosQueryNPHState(HPIPE hpipe,
865 PULONG pulState)
866{
867 APIRET rc;
868 ULONG ul1;
869 PULONG pul1 = NULL;
870
871 if (pulState)
872 {
873 ul1 = *pulState;
874 pul1 = &ul1;
875 }
876
877 rc = DosQueryNPHState(hpipe, pul1);
878
879 if (pulState)
880 *pulState = ul1;
881 return rc;
882}
883
884APIRET xDosQueryFHState(HFILE hFile,
885 PULONG pulMode)
886{
887 APIRET rc;
888 ULONG ul1;
889 PULONG pul1 = NULL;
890
891 if (pulMode)
892 {
893 ul1 = *pulMode;
894 pul1 = &ul1;
895 }
896
897 rc = DosQueryFHState(hFile, pul1);
898
899 if (pulMode)
900 *pulMode = ul1;
901
902 return rc;
903}
904
905APIRET xDosSetDateTime(DATETIME *pdt)
906{
907 APIRET rc;
908 DATETIME dt1;
909 PDATETIME pdt1 = NULL;
910
911 if (pdt)
912 {
913 dt1 = *pdt;
914 pdt1 = &dt1;
915 }
916
917 rc = DosSetDateTime(pdt1);
918
919 return rc;
920}
921
922APIRET xDosSetFilePtr(HFILE hFile,
923 LONG lOffset,
924 ULONG ulOrigin,
925 PULONG pulPos)
926{
927 APIRET rc;
928 ULONG ul1;
929 PULONG pul1 = NULL;
930
931 if (pulPos)
932 {
933 ul1 = *pulPos;
934 pul1 = &ul1;
935 }
936
937 rc = DosSetFilePtr(hFile, lOffset, ulOrigin, pul1);
938
939 if (pulPos)
940 *pulPos = ul1;
941
942 return rc;
943}
944
945APIRET xDosSetFilePtrL(HFILE hFile,
946 LONGLONG llOffset,
947 ULONG ulOrigin,
948 PLONGLONG pllPos)
949{
950 APIRET rc;
951 LONGLONG ll1;
952 PLONGLONG pll1 = NULL;
953
954 if (pllPos)
955 {
956 ll1 = *pllPos;
957 pll1 = &ll1;
958 }
959
960 rc = DosSetFilePtrL(hFile, llOffset, ulOrigin, pll1);
961
962 if (pllPos)
963 *pllPos = ll1;
964
965 return rc;
966}
967
968APIRET xDosWaitChild(ULONG ulAction,
969 ULONG ulWait,
970 PRESULTCODES pReturnCodes,
971 PPID ppidOut,
972 PID pidIn)
973{
974 APIRET rc;
975 RESULTCODES res;
976 PRESULTCODES pres = NULL;
977 PID pid;
978 PPID ppid = NULL;
979
980 if (pReturnCodes)
981 {
982 res = *pReturnCodes;
983 pres = &res;
984 }
985 if (ppidOut)
986 {
987 pid = *ppidOut;
988 ppid = &pid;
989 }
990
991 rc = DosWaitChild(ulAction, ulWait, pres, ppid, pidIn);
992
993 if (pReturnCodes)
994 *pReturnCodes = res;
995 if (ppidOut)
996 *ppidOut = pid;
997
998 return rc;
999}
1000
1001APIRET xDosWaitNPipe(PCSZ pszName,
1002 ULONG ulTimeout)
1003{
1004 APIRET rc;
1005 char szNameLow[CCHMAXPATH];
1006
1007 strcpy(szNameLow, pszName);
1008 rc = DosWaitNPipe(szNameLow, ulTimeout);
1009 return rc;
1010}
1011
1012ULONG xWinUpper(HAB hab,
1013 ULONG idcp,
1014 ULONG idcc,
1015 PSZ psz)
1016{
1017 ULONG rc;
1018
1019 if (!HIGH_MEMORY_ADDRESS(psz))
1020 rc = WinUpper(hab, idcp, idcc, psz);
1021 else {
1022 size_t cch = strlen(psz);
1023 char *pszTmp = xmalloc(cch + 3, pszSrcFile, __LINE__);
1024 if (pszTmp)
1025 {
1026 memcpy(pszTmp, psz, cch + 1);
1027 pszTmp[cch + 1] = '\0';
1028 pszTmp[cch + 2] = '\0';
1029 rc = WinUpper(hab, idcp, idcc, pszTmp);
1030 if (rc > 0)
1031 memcpy(psz, pszTmp, rc <= cch ? rc + 1 : rc);
1032 xfree(pszTmp, pszSrcFile, __LINE__);
1033 }
1034 else
1035 {
1036 PSZ pszStart = psz;
1037 PSZ pszNext;
1038 while (*psz)
1039 {
1040 pszNext = (PSZ)WinNextChar(hab, idcp, idcc, psz);
1041 if (pszNext - psz == 1)
1042 *psz = WinUpperChar(hab, idcp, idcc, *psz);
1043 else if (pszNext - psz == 2)
1044 *(PUSHORT)psz = WinUpperChar(hab, idcp, idcc, *(PUSHORT)psz); /* a wild guess. */
1045 else
1046 break;
1047 psz = (char *)pszNext;
1048 }
1049 rc = psz - pszStart;
1050 }
1051 }
1052 return rc;
1053}
1054
1055#endif
1056
1057
1058#pragma alloc_text(WRAPPERS1,xfree,xfopen,xfsopen,xmalloc,xrealloc,xstrdup)
1059#pragma alloc_text(WRAPPERS2,xDosSetPathInfo,xDosFindFirst,xDosFindNext)
Note: See TracBrowser for help on using the repository browser.