source: trunk/dll/wrappers.c@ 1877

Last change on this file since 1877 was 1877, checked in by Gregg Young, 10 years ago

Remove debug code

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