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
RevLine 
[395]1
2/***********************************************************************
3
4 $Id: wrappers.c 1845 2015-08-12 19:54:49Z jbs $
5
6 Wrappers with error checking
7
[1845]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
[1476]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
[1627]21 26 Aug 11 GKY Add a low mem version of xDosAlloc* wrappers; move error checking into all the
[1839]22 xDosAlloc* wrappers.
[1639]23 09 Oct 11 GKY Modify xfsopen so it doesn't fail when called with r+ because the file doesn't exist.
[1839]24 We should be creating the file unless it is set to fail silently.
[1845]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.
[395]30
31***********************************************************************/
32
[907]33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
[1354]36#include <ctype.h>
[907]37
[395]38#define INCL_WIN
[826]39#define INCL_DOS
40#define INCL_DOSERRORS
[841]41#define INCL_LONGLONG
[395]42#include <os2.h>
43
44#include "fm3dll.h"
[1215]45#include "init.h" // Data declaration(s)
[1182]46#include "wrappers.h"
[395]47#include "fm3str.h"
[907]48#include "errutil.h" // Dos_Error...
49#include "strutil.h" // GetPString
[1032]50#include "command.h"
51#include "tools.h"
52#include "avl.h"
[1182]53#include "strips.h" // bstrip
[395]54
[1005]55#include "fortify.h" // GetPString
[1354]56#include "info.h" // driveflags
57#include "notebook.h" // fVerify
[1439]58#include "pathutil.h" // MaxComLineStrg
[1005]59
[1215]60// Data definitions
[827]61static PSZ pszSrcFile = __FILE__;
62
[1215]63#pragma data_seg(GLOBAL1)
64BOOL fNoLargeFileSupport;
65
[1845]66APIRET xDosDupHandle(HFILE hFile,
67 PHFILE phFile)
[1439]68{
[1845]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{
[1439]90 APIRET rc;
[1845]91 ULONG ulFlagsLow;
[1476]92 CHAR szPgm[CCHMAXPATH];
[1439]93
[1476]94 strcpy(szPgm, pszName);
[1845]95 rc = DosQueryAppType(szPgm, &ulFlagsLow);
96 *pFlags = ulFlagsLow;
[1439]97 return rc;
98}
99
[1845]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//
[1628]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
[1438]249APIRET xDosAllocSharedMem(PPVOID ppb,
[1839]250 PSZ pszName,
251 ULONG cb,
252 PCSZ pszSrcFile,
253 UINT uiLineNumber)
[1438]254{
[1845]255 APIRET rc;
[1438]256
[1628]257 rc = DosAllocSharedMem(ppb, pszName, cb,
[1839]258 PAG_COMMIT | OBJ_GIVEABLE | PAG_READ | PAG_WRITE | OBJ_ANY);
[1439]259 //DbgMsg(pszSrcFile, __LINE__, "ppb %p", *ppb);
[1438]260 if (rc)
[1628]261 rc = DosAllocSharedMem(ppb, pszName, cb, PAG_COMMIT | OBJ_GIVEABLE | PAG_READ | PAG_WRITE);
[1627]262 if (rc)
263 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[1438]264 return rc;
265}
266
[1628]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
[1438]274APIRET xDosAllocMem(PPVOID ppb,
[1839]275 ULONG cb,
276 PCSZ pszSrcFile,
277 UINT uiLineNumber)
[1438]278{
279 APIRET rc;
280
[1628]281 rc = DosAllocMem(ppb, cb, PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_ANY);
[1439]282 //DbgMsg(pszSrcFile, uiLineNumber, "ppb %p %x", *ppb, rc);
[1438]283 if (rc)
[1628]284 rc = DosAllocMem(ppb, cb, PAG_COMMIT | PAG_READ | PAG_WRITE);
[1627]285 if (rc)
286 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[1439]287 //DbgMsg(pszSrcFile, uiLineNumber, "ppb %p", *ppb);
[1438]288 return rc;
289}
290
[1628]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
[1627]299APIRET xDosAllocMemLow(PPVOID ppb,
[1839]300 ULONG cb,
301 PCSZ pszSrcFile,
302 UINT uiLineNumber)
[1627]303{
304 APIRET rc;
305
[1628]306 rc = DosAllocMem(ppb, cb, PAG_COMMIT | PAG_READ | PAG_WRITE);
[1627]307 if (rc)
308 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
309 //DbgMsg(pszSrcFile, uiLineNumber, "ppb %p", *ppb);
310 return rc;
311}
312
[1839]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
[850]327APIRET xDosFindFirst(PSZ pszFileSpec,
328 PHDIR phdir,
329 ULONG flAttribute,
330 PVOID pfindbuf,
331 ULONG cbBuf,
332 PULONG pcFileNames,
333 ULONG ulInfoLevel)
[838]334{
[850]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 }
[849]354 break;
[850]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 }
[849]372 break;
373 default:
[850]374 Runtime_Error(pszSrcFile, __LINE__, "ulInfoLevel %u unexpected", ulInfoLevel);
375 rc = ERROR_INVALID_PARAMETER;
376 } // switch
377 }
378 else
[838]379 rc = DosFindFirst(pszFileSpec, phdir, flAttribute, pfindbuf, cbBuf,
[850]380 pcFileNames, ulInfoLevel);
381 return rc;
[838]382}
383
[850]384APIRET xDosFindNext(HDIR hDir,
385 PVOID pfindbuf,
386 ULONG cbfindbuf,
387 PULONG pcFileNames,
388 ULONG ulInfoLevel)
[838]389{
390 APIRET rc;
[849]391 if (fNoLargeFileSupport) {
[850]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
[849]428 }
429 else
[850]430 rc = DosFindNext(hDir, pfindbuf, cbfindbuf, pcFileNames);
[838]431
432 return rc;
433}
434
[827]435/**
[850]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
[1432]473 rc = DosQueryPathInfo (pszPathName, ulInfoLevel, pInfoBuf, cbInfoBuf);
[850]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 *
[1627]482 * Some kernels do not correctly handle FILESTATUS3 and PEAOP2 buffers
[827]483 * that cross a 64K boundary.
484 * When this occurs, they return ERROR_INVALID_NAME.
[1845]485 *
[827]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.
[1845]489 *
[827]490 * It is caller's responsitibility to report errors
[847]491 * @param pInfoBuf pointer to FILESTATUS3(L) or EAOP2 buffer
492 * @param ulInfoLevel FIL_STANDARD(L) or FIL_QUERYEASIZE
[827]493 * @returns Same as DosSetPathInfo
494 */
495
[841]496APIRET xDosSetPathInfo(PSZ pszPathName,
[850]497 ULONG ulInfoLevel,
[841]498 PVOID pInfoBuf,
499 ULONG cbInfoBuf,
[850]500 ULONG flOptions)
[826]501{
[1845]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;
[850]510
[1845]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;
[850]524
[1845]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;
[850]534 }
535 else {
[1845]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);
[850]540 }
541 if (rc == ERROR_INVALID_NAME) {
542 // fixme to validate counts?
[1845]543 fs3_a = fs3; // Copy to buffer that does not cross
544 rc = DosSetPathInfo(pszPathName, ulInfoLevel, &fs3_a, sizeof(fs3_a), flOptions);
[1839]545 }
[1845]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;
[826]572}
573
[551]574PSZ xfgets(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
575 UINT uiLineNumber)
[400]576{
[551]577 PSZ psz = fgets(pszBuf, cMaxBytes, fp);
578
[400]579 if (!psz) {
580 if (ferror(fp))
581 Runtime_Error(pszSrcFile, uiLineNumber, "fgets");
582 }
583 else {
584 size_t c = strlen(psz);
[551]585
[400]586 if (c + 1 > cMaxBytes)
587 Runtime_Error(pszSrcFile, uiLineNumber, "buffer overflow");
[551]588 else if (!c || (psz[c - 1] != '\n' && psz[c - 1] != '\r'))
[400]589 Runtime_Error(pszSrcFile, uiLineNumber, "missing EOL");
590 }
591 return psz;
592}
593
[551]594PSZ xfgets_bstripcr(PSZ pszBuf, size_t cMaxBytes, FILE * fp, PCSZ pszSrcFile,
595 UINT uiLineNumber)
[400]596{
[551]597 PSZ psz = xfgets(pszBuf, cMaxBytes, fp, pszSrcFile, uiLineNumber);
598
[400]599 if (psz)
600 bstripcr(psz);
601 return psz;
602}
603
[1544]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
[551]613FILE *xfopen(PCSZ pszFileName, PCSZ pszMode, PCSZ pszSrcFile,
[1544]614 UINT uiLineNumber, BOOL fSilent)
[395]615{
[1544]616 CHAR FileName[CCHMAXPATH];
617 FILE *fp;
[551]618
[1544]619 strcpy(FileName, pszFileName);
620 fp = fopen(FileName, pszMode);
621
622 if (!fp && !fSilent)
[395]623 Runtime_Error(pszSrcFile, uiLineNumber, "fopen");
624 return fp;
625}
626
[1544]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
[551]636FILE *xfsopen(PCSZ pszFileName, PCSZ pszMode, INT fSharemode, PCSZ pszSrcFile,
[1839]637 UINT uiLineNumber, BOOL fSilent)
[395]638{
[1544]639 CHAR FileName[CCHMAXPATH];
640 FILE *fp;
[551]641
[1544]642 strcpy(FileName, pszFileName);
643 fp = _fsopen(FileName, pszMode, fSharemode);
[1639]644 if (!fp && !strcmp(pszMode, "r+") && !fSilent)
645 fp = _fsopen(FileName, "w+", fSharemode);
[1544]646
647 if (!fp && !fSilent)
[395]648 Runtime_Error(pszSrcFile, uiLineNumber, "_fsopen");
649 return fp;
650}
651
652//== xfree - safe free ==
653
[1009]654VOID xfree(PVOID pv, PCSZ pszSrcFile, UINT uiLineNumber)
[395]655{
[1009]656 if (pv && pv != NullStr) {
[1063]657# ifdef FORTIFY
[1009]658 Fortify_free(pv, pszSrcFile, uiLineNumber);
[1063]659# else
[395]660 free(pv);
[1063]661# endif
[1009]662
663 }
[395]664}
665
666//== xmalloc() malloc with error checking ==
667
668PVOID xmalloc(size_t cBytes, PCSZ pszSrcFile, UINT uiLineNumber)
669{
[1006]670# ifdef FORTIFY
671 PVOID pv = Fortify_malloc(cBytes, pszSrcFile, uiLineNumber);
[1011]672# else
[395]673 PVOID pv = malloc(cBytes);
[1063]674# endif
[395]675
676 if (!pv)
[551]677 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]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{
[1011]686 PVOID pv = xmalloc(cBytes, pszSrcFile, uiLineNumber);
[395]687
[1011]688 if (pv)
[395]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{
[963]698 if (pvIn != NullStr) {
[1063]699# ifdef FORTIFY
700 PVOID pv = Fortify_realloc(pvIn, cBytes, pszSrcFile, uiLineNumber);
701# else
702 PVOID pv = realloc(pvIn, cBytes);
703# endif
[395]704
[963]705 if (!pv && cBytes)
706 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]707
[963]708 return pv;
709 }
710 else
711 return xmalloc(cBytes, pszSrcFile, uiLineNumber);
[395]712}
713
714//== xstrdup() strdup with error checking ==
715
716PVOID xstrdup(PCSZ pszIn, PCSZ pszSrcFile, UINT uiLineNumber)
717{
[1009]718# ifdef FORTIFY
719 PSZ psz = Fortify_strdup(pszIn, pszSrcFile, uiLineNumber);
[1011]720# else
[395]721 PSZ psz = strdup(pszIn);
[1063]722# endif
[395]723
724 if (!psz)
[551]725 Runtime_Error(pszSrcFile, uiLineNumber, GetPString(IDS_OUTOFMEMORY));
[395]726
727 return psz;
728}
[794]729
[1845]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 */
[1032]736
[1845]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
[1032]1058#pragma alloc_text(WRAPPERS1,xfree,xfopen,xfsopen,xmalloc,xrealloc,xstrdup)
[1037]1059#pragma alloc_text(WRAPPERS2,xDosSetPathInfo,xDosFindFirst,xDosFindNext)
Note: See TracBrowser for help on using the repository browser.