source: trunk/dll/wrappers.c@ 1860

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

Rework FlesWaitForWorkListEmpty to support wait for parents of path
Add more wrappers for mutex and event semaphores
Clean up some obsolete code

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