Implemented some file i/o APIs and stubbed some threading primitives.
Now EMX's build of cpp.exe (GNU's C preprocessor) runs on Linux...granted, it picks up the Linux /usr/include headers, but this is still a triumph!
This commit is contained in:
1 parent
086e05dd0c
commit
b4d0e571e7
4 files changed
+405
-12
No files matched your search
+323
-11
@@ -11,6 +11,7 @@
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "os2native.h"
|
||||
#include "doscalls.h"
|
||||
@@ -111,11 +112,16 @@ static int initDoscalls(LxLoaderState *lx_state)
|
||||
} // initDoscalls
|
||||
|
||||
LX_NATIVE_MODULE_INIT({ if (!initDoscalls(lx_state)) return NULL; })
|
||||
LX_NATIVE_EXPORT(DosQueryPathInfo, 223),
|
||||
LX_NATIVE_EXPORT(DosQueryHType, 224),
|
||||
LX_NATIVE_EXPORT(DosScanEnv, 227),
|
||||
LX_NATIVE_EXPORT(DosGetDateTime, 230),
|
||||
LX_NATIVE_EXPORT(DosExit, 234),
|
||||
LX_NATIVE_EXPORT(DosSetFilePtr, 256),
|
||||
LX_NATIVE_EXPORT(DosClose, 257),
|
||||
LX_NATIVE_EXPORT(DosOpen, 273),
|
||||
LX_NATIVE_EXPORT(DosQueryFileInfo, 279),
|
||||
LX_NATIVE_EXPORT(DosRead, 281),
|
||||
LX_NATIVE_EXPORT(DosWrite, 282),
|
||||
LX_NATIVE_EXPORT(DosExitList, 296),
|
||||
LX_NATIVE_EXPORT(DosAllocMem, 299),
|
||||
@@ -124,28 +130,44 @@ LX_NATIVE_MODULE_INIT({ if (!initDoscalls(lx_state)) return NULL; })
|
||||
LX_NATIVE_EXPORT(DosQueryModuleName, 320),
|
||||
LX_NATIVE_EXPORT(DosCreateEventSem, 324),
|
||||
LX_NATIVE_EXPORT(DosCreateMutexSem, 331),
|
||||
LX_NATIVE_EXPORT(DosRequestMutexSem, 334),
|
||||
LX_NATIVE_EXPORT(DosReleaseMutexSem, 335),
|
||||
LX_NATIVE_EXPORT(DosSubSetMem, 344),
|
||||
LX_NATIVE_EXPORT(DosSubAllocMem, 345),
|
||||
LX_NATIVE_EXPORT(DosQuerySysInfo, 348),
|
||||
LX_NATIVE_EXPORT(DosSetExceptionHandler, 354),
|
||||
LX_NATIVE_EXPORT(DosSetSignalExceptionFocus, 378),
|
||||
LX_NATIVE_EXPORT(DosEnterMustComplete, 380),
|
||||
LX_NATIVE_EXPORT(DosExitMustComplete, 381),
|
||||
LX_NATIVE_EXPORT(DosSetRelMaxFH, 382),
|
||||
LX_NATIVE_EXPORT(DosFlatToSel, 425)
|
||||
LX_NATIVE_MODULE_INIT_END()
|
||||
|
||||
|
||||
static PTIB2 getTib2(void)
|
||||
{
|
||||
// just read the FS register, since we have to stick it there anyhow...
|
||||
PTIB2 ptib2;
|
||||
__asm__ __volatile__ ( "movl %%fs:0xC, %0 \n\t" : "=r" (ptib2) );
|
||||
return ptib2;
|
||||
} // getTib2
|
||||
|
||||
static PTIB getTib(void)
|
||||
{
|
||||
// we store the TIB2 struct right after the TIB struct on the stack,
|
||||
// so get the TIB2's linear address from %fs:0xC, then step back
|
||||
// to the TIB's linear address.
|
||||
uint8 *ptib2 = (uint8 *) getTib2();
|
||||
return (PTIB) (ptib2 - sizeof (TIB));
|
||||
} // getTib
|
||||
|
||||
|
||||
APIRET DosGetInfoBlocks(PTIB *pptib, PPIB *pppib)
|
||||
{
|
||||
TRACE_NATIVE("DosGetInfoBlocks(%p, %p)", pptib, pppib);
|
||||
|
||||
if (pptib != NULL) {
|
||||
// just read the FS register, since we have to stick it there anyhow...
|
||||
uint8 *ptib2;
|
||||
__asm__ __volatile__ ( "movl %%fs:0xC, %0 \n\t" : "=r" (ptib2) );
|
||||
// we store the TIB2 struct right after the TIB struct on the stack,
|
||||
// so get the TIB2's linear address from %fs:0xC, then step back
|
||||
// to the TIB's linear address.
|
||||
*pptib = (PTIB) (ptib2 - sizeof (TIB));
|
||||
*pptib = getTib();
|
||||
} // if
|
||||
|
||||
if (pppib != NULL) {
|
||||
@@ -571,12 +593,12 @@ APIRET DosGetDateTime(PDATETIME pdt)
|
||||
// !!! FIXNE: length can change!
|
||||
static int locateOneElement(char *buf)
|
||||
{
|
||||
if (access(buf, F_OK))
|
||||
if (access(buf, F_OK) == 0)
|
||||
return 1; // quick rejection: exists in current case.
|
||||
|
||||
DIR *dirp;
|
||||
char *ptr = strrchr(buf, '/'); // find entry at end of path.
|
||||
if (ptr == NULL) {
|
||||
if ((ptr == NULL) || (ptr == buf)) {
|
||||
dirp = opendir("/");
|
||||
ptr = buf;
|
||||
} else {
|
||||
@@ -607,7 +629,7 @@ int locatePathCaseInsensitive(char *buf)
|
||||
if (*ptr == '\0')
|
||||
return 0; // Uh...I guess that's success?
|
||||
|
||||
if (access(buf, F_OK))
|
||||
if (access(buf, F_OK) == 0)
|
||||
return 0; // quick rejection: exists in current case.
|
||||
|
||||
while ( (ptr = strchr(ptr + 1, '/')) != NULL ) {
|
||||
@@ -771,7 +793,7 @@ APIRET DosOpen(PSZ pszFileName, PHFILE pHf, PULONG pulAction, ULONG cbFile, ULON
|
||||
return err;
|
||||
} // if
|
||||
|
||||
printf("DosOpen: converted '%s' to '%s'\n", pszFileName, unixpath);
|
||||
if (strcmp(pszFileName, unixpath) != 0) { printf("DosOpen: converted '%s' to '%s'\n", pszFileName, unixpath); }
|
||||
|
||||
info->fd = open(unixpath, flags, mode);
|
||||
|
||||
@@ -840,5 +862,295 @@ APIRET DosOpen(PSZ pszFileName, PHFILE pHf, PULONG pulAction, ULONG cbFile, ULON
|
||||
return NO_ERROR;
|
||||
} // DosOpen
|
||||
|
||||
APIRET DosRequestMutexSem(HMTX hmtx, ULONG ulTimeout)
|
||||
{
|
||||
TRACE_NATIVE("DosRequestMutexSem(%u, %u)", (uint) hmtx, (uint) ulTimeout);
|
||||
FIXME("implement this when we can spin threads");
|
||||
return NO_ERROR;
|
||||
} // DosRequestMutexSem
|
||||
|
||||
APIRET DosReleaseMutexSem(HMTX hmtx)
|
||||
{
|
||||
TRACE_NATIVE("DosReleaseMutexSem(%u)", (uint) hmtx);
|
||||
FIXME("implement this when we can spin threads");
|
||||
return NO_ERROR;
|
||||
} // DosReleaseMutexSem
|
||||
|
||||
APIRET DosSetFilePtr(HFILE hFile, LONG ib, ULONG method, PULONG ibActual)
|
||||
{
|
||||
TRACE_NATIVE("DosSetFilePtr(%u, %d, %u, %p)", (uint) hFile, (int) ib, (uint) method, ibActual);
|
||||
|
||||
int whence;
|
||||
switch (method) {
|
||||
case FILE_BEGIN: whence = SEEK_SET; break;
|
||||
case FILE_CURRENT: whence = SEEK_CUR; break;
|
||||
case FILE_END: whence = SEEK_END; break;
|
||||
default: return ERROR_INVALID_FUNCTION;
|
||||
} // switch
|
||||
|
||||
if ((hFile >= MaxHFiles) || (HFiles[hFile].fd == -1))
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
const off_t pos = lseek(HFiles[hFile].fd, (off_t) ib, whence);
|
||||
if (pos == -1) {
|
||||
if (errno == EINVAL)
|
||||
return ERROR_NEGATIVE_SEEK;
|
||||
return ERROR_INVALID_FUNCTION; // !!! FIXME: ?
|
||||
} // if
|
||||
|
||||
if (ibActual)
|
||||
*ibActual = (ULONG) pos;
|
||||
|
||||
return NO_ERROR;
|
||||
} // DosSetFilePtr
|
||||
|
||||
APIRET DosRead(HFILE hFile, PVOID pBuffer, ULONG cbRead, PULONG pcbActual)
|
||||
{
|
||||
TRACE_NATIVE("DosRead(%u, %p, %u, %p)", (uint) hFile, pBuffer, (uint) cbRead, pcbActual);
|
||||
|
||||
if ((hFile >= MaxHFiles) || (HFiles[hFile].fd == -1))
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
const ssize_t br = read(HFiles[hFile].fd, pBuffer, cbRead);
|
||||
if (br == -1)
|
||||
return ERROR_INVALID_FUNCTION; // !!! FIXME: ?
|
||||
|
||||
if (pcbActual)
|
||||
*pcbActual = (ULONG) br;
|
||||
|
||||
return NO_ERROR;
|
||||
} // DosRead
|
||||
|
||||
APIRET DosClose(HFILE hFile)
|
||||
{
|
||||
TRACE_NATIVE("DosClose(%u)", (uint) hFile);
|
||||
|
||||
if ((hFile >= MaxHFiles) || (HFiles[hFile].fd == -1))
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
const int rc = close(HFiles[hFile].fd);
|
||||
if (rc == -1)
|
||||
return ERROR_ACCESS_DENIED; // !!! FIXME: ?
|
||||
|
||||
HFiles[hFile].fd = -1;
|
||||
HFiles[hFile].type = 0;
|
||||
HFiles[hFile].attr = 0;
|
||||
return NO_ERROR;
|
||||
} // DosClose
|
||||
|
||||
APIRET DosEnterMustComplete(PULONG pulNesting)
|
||||
{
|
||||
TRACE_NATIVE("DosEnterMustComplete(%p)", pulNesting);
|
||||
|
||||
PTIB2 tib2 = getTib2();
|
||||
if (tib2->tib2_usMCCount == 0xFFFF) {
|
||||
return ERROR_NESTING_TOO_DEEP;
|
||||
} else if (tib2->tib2_usMCCount == 0) {
|
||||
FIXME("block signals here");
|
||||
}
|
||||
|
||||
tib2->tib2_usMCCount++;
|
||||
|
||||
if (pulNesting)
|
||||
*pulNesting = tib2->tib2_usMCCount;
|
||||
|
||||
return NO_ERROR;
|
||||
} // DosEnterMustComplete
|
||||
|
||||
APIRET DosExitMustComplete(PULONG pulNesting)
|
||||
{
|
||||
TRACE_NATIVE("DosExitMustComplete(%p)", pulNesting);
|
||||
|
||||
PTIB2 tib2 = getTib2();
|
||||
if (tib2->tib2_usMCCount == 0) {
|
||||
return ERROR_ALREADY_RESET;
|
||||
} else if (tib2->tib2_usMCCount == 1) {
|
||||
FIXME("unblock signals here");
|
||||
}
|
||||
|
||||
tib2->tib2_usMCCount--;
|
||||
|
||||
if (pulNesting)
|
||||
*pulNesting = tib2->tib2_usMCCount;
|
||||
|
||||
return NO_ERROR;
|
||||
} // DosExitMustComplete
|
||||
|
||||
static void unixTimeToOs2(const time_t unixtime, FDATE *os2date, FTIME *os2time)
|
||||
{
|
||||
struct tm lt;
|
||||
localtime_r(&unixtime, <);
|
||||
os2date->day = (USHORT) lt.tm_mday;
|
||||
os2date->month = (USHORT) (lt.tm_mon + 1);
|
||||
os2date->year = (USHORT) (lt.tm_year - 80); // wants years since 1980, apparently.
|
||||
os2time->twosecs = (USHORT) (lt.tm_sec / 2);
|
||||
os2time->minutes = (USHORT) lt.tm_min;
|
||||
os2time->hours = (USHORT) lt.tm_hour;
|
||||
} // unixTimeToOs2
|
||||
|
||||
static APIRET queryFileInfoStandardFromStat(const struct stat *statbuf, PVOID pInfoBuf, ULONG cbInfoBuf)
|
||||
{
|
||||
FILESTATUS3 *st = (FILESTATUS3 *) pInfoBuf;
|
||||
memset(st, '\0', sizeof (*st));
|
||||
|
||||
// we don't store creation date on Unix. OS/2 zeroes out fields that aren't
|
||||
// appropriate to FAT file systems, but I don't want to risk apps using
|
||||
// zeroes to decide a file in on a FAT disk and reducing features,
|
||||
// shrinking filenames to 8.3, etc.
|
||||
st->fdateCreation.day = 1;
|
||||
st->fdateCreation.month = 1;
|
||||
st->fdateCreation.year = 0; // years since 1980, apparently.
|
||||
st->ftimeCreation.twosecs = 0;
|
||||
st->ftimeCreation.minutes = 0;
|
||||
st->ftimeCreation.hours = 0;
|
||||
|
||||
unixTimeToOs2(statbuf->st_atime, &st->fdateLastAccess, &st->ftimeLastAccess);
|
||||
unixTimeToOs2(statbuf->st_mtime, &st->fdateLastWrite, &st->ftimeLastWrite);
|
||||
|
||||
st->cbFile = (ULONG) statbuf->st_size;
|
||||
st->cbFileAlloc = (ULONG) (statbuf->st_blocks * 512);
|
||||
|
||||
if (S_ISDIR(statbuf->st_mode))
|
||||
st->attrFile |= FILE_DIRECTORY;
|
||||
if (statbuf->st_mode & ~S_IRUSR) // !!! FIXME: not accurate...?
|
||||
st->attrFile |= FILE_READONLY;
|
||||
|
||||
return NO_ERROR;
|
||||
} // queryFileInfoStandardFromStat
|
||||
|
||||
static APIRET queryPathInfoStandard(PSZ unixPath, PVOID pInfoBuf, ULONG cbInfoBuf)
|
||||
{
|
||||
if (cbInfoBuf < sizeof (FILESTATUS3))
|
||||
return ERROR_BUFFER_OVERFLOW;
|
||||
|
||||
struct stat statbuf;
|
||||
if (stat(unixPath, &statbuf) == -1) {
|
||||
return ERROR_PATH_NOT_FOUND; // !!! FIXME
|
||||
}
|
||||
|
||||
return queryFileInfoStandardFromStat(&statbuf, pInfoBuf, cbInfoBuf);
|
||||
} // queryPathInfoStandard
|
||||
|
||||
static APIRET queryPathInfoEaSize(PSZ unixPath, PVOID pInfoBuf, ULONG cbInfoBuf)
|
||||
{
|
||||
if (cbInfoBuf < sizeof (FILESTATUS4))
|
||||
return ERROR_BUFFER_OVERFLOW;
|
||||
const APIRET rc = queryPathInfoStandard(unixPath, pInfoBuf, cbInfoBuf);
|
||||
if (rc != NO_ERROR)
|
||||
return rc;
|
||||
|
||||
FILESTATUS4 *st = (FILESTATUS4 *) pInfoBuf;
|
||||
FIXME("write me");
|
||||
st->cbList = 0;
|
||||
return NO_ERROR;
|
||||
} // queryPathInfoEaSize
|
||||
|
||||
static APIRET queryPathInfoFullName(PSZ unixPath, PVOID pInfoBuf, ULONG cbInfoBuf)
|
||||
{
|
||||
char *real = realpath(unixPath, NULL);
|
||||
if (real == NULL)
|
||||
return ERROR_NOT_ENOUGH_MEMORY; // !!! FIXME: no
|
||||
|
||||
if ((strlen(real) + 3) < cbInfoBuf) {
|
||||
free(real);
|
||||
return ERROR_BUFFER_OVERFLOW;
|
||||
} // if
|
||||
|
||||
char *dst = (char *) pInfoBuf;
|
||||
*(dst++) = 'C';
|
||||
*(dst++) = ':';
|
||||
strcpy(dst, real);
|
||||
free(real);
|
||||
|
||||
while (*dst) {
|
||||
if (*dst == '/')
|
||||
*dst = '\\';
|
||||
dst++;
|
||||
} // while
|
||||
|
||||
return NO_ERROR;
|
||||
} // queryPathInfoFullName
|
||||
|
||||
static APIRET queryPathInfoEasFromList(PSZ unixPath, PVOID pInfoBuf, ULONG cbInfoBuf)
|
||||
{
|
||||
FIXME("write me");
|
||||
return ERROR_INVALID_LEVEL;
|
||||
} // queryPathInfoEasFromList
|
||||
|
||||
static APIRET queryPathInfo(PSZ unixPath, ULONG ulInfoLevel, PVOID pInfoBuf, ULONG cbInfoBuf)
|
||||
{
|
||||
switch (ulInfoLevel) {
|
||||
case FIL_STANDARD: return queryPathInfoStandard(unixPath, pInfoBuf, cbInfoBuf);
|
||||
case FIL_QUERYEASIZE: return queryPathInfoEaSize(unixPath, pInfoBuf, cbInfoBuf);
|
||||
case FIL_QUERYEASFROMLIST: return queryPathInfoEasFromList(unixPath, pInfoBuf, cbInfoBuf);
|
||||
case FIL_QUERYFULLNAME: return queryPathInfoFullName(unixPath, pInfoBuf, cbInfoBuf);
|
||||
default: break;
|
||||
} // switch
|
||||
|
||||
return ERROR_INVALID_LEVEL;
|
||||
} // queryPathInfo
|
||||
|
||||
APIRET DosQueryPathInfo(PSZ pszPathName, ULONG ulInfoLevel, PVOID pInfoBuf, ULONG cbInfoBuf)
|
||||
{
|
||||
TRACE_NATIVE("DosQueryPathInfo('%s', %u, %p, %u)", pszPathName, (uint) ulInfoLevel, pInfoBuf, (uint) cbInfoBuf);
|
||||
|
||||
APIRET err = NO_ERROR;
|
||||
char *unixPath = makeUnixPath(pszPathName, &err);
|
||||
if (!unixPath)
|
||||
return err;
|
||||
err = queryPathInfo(unixPath, ulInfoLevel, pInfoBuf, cbInfoBuf);
|
||||
free(unixPath);
|
||||
return err;
|
||||
} // DosQueryPathInfo
|
||||
|
||||
static APIRET queryFileInfoStandard(const struct stat *statbuf, PVOID pInfoBuf, ULONG cbInfoBuf)
|
||||
{
|
||||
if (cbInfoBuf < sizeof (FILESTATUS3))
|
||||
return ERROR_BUFFER_OVERFLOW;
|
||||
return queryFileInfoStandardFromStat(statbuf, pInfoBuf, cbInfoBuf);
|
||||
} // queryFileInfoStandard
|
||||
|
||||
static APIRET queryFileInfoEaSize(const struct stat *statbuf, PVOID pInfoBuf, ULONG cbInfoBuf)
|
||||
{
|
||||
if (cbInfoBuf < sizeof (FILESTATUS4))
|
||||
return ERROR_BUFFER_OVERFLOW;
|
||||
const APIRET rc = queryFileInfoStandard(statbuf, pInfoBuf, cbInfoBuf);
|
||||
if (rc != NO_ERROR)
|
||||
return rc;
|
||||
|
||||
FILESTATUS4 *st = (FILESTATUS4 *) pInfoBuf;
|
||||
FIXME("write me");
|
||||
st->cbList = 0;
|
||||
return NO_ERROR;
|
||||
} // queryFileInfoEaSize
|
||||
|
||||
static APIRET queryFileInfoEasFromList(const struct stat *statbuf, PVOID pInfoBuf, ULONG cbInfoBuf)
|
||||
{
|
||||
FIXME("write me");
|
||||
return ERROR_INVALID_LEVEL;
|
||||
} // queryFileInfoEasFromList
|
||||
|
||||
|
||||
APIRET DosQueryFileInfo(HFILE hf, ULONG ulInfoLevel, PVOID pInfo, ULONG cbInfoBuf)
|
||||
{
|
||||
TRACE_NATIVE("DosQueryFileInfo(%u, %u, %p, %u)", (uint) hf, (uint) ulInfoLevel, pInfo, (uint) cbInfoBuf);
|
||||
|
||||
if ((hf >= MaxHFiles) || (HFiles[hf].fd == -1))
|
||||
return ERROR_INVALID_HANDLE;
|
||||
|
||||
struct stat statbuf;
|
||||
if (fstat(HFiles[hf].fd, &statbuf) == -1)
|
||||
return ERROR_INVALID_HANDLE; // !!! FIXME: ...?
|
||||
|
||||
switch (ulInfoLevel) {
|
||||
case FIL_STANDARD: return queryFileInfoStandard(&statbuf, pInfo, cbInfoBuf);
|
||||
case FIL_QUERYEASIZE: return queryFileInfoEaSize(&statbuf, pInfo, cbInfoBuf);
|
||||
case FIL_QUERYEASFROMLIST: return queryFileInfoEasFromList(&statbuf, pInfo, cbInfoBuf);
|
||||
default: break;
|
||||
} // switch
|
||||
|
||||
return ERROR_INVALID_LEVEL;
|
||||
} // DosQueryFileInfo
|
||||
|
||||
// end of doscalls.c ...
|
||||
|
||||
@@ -166,6 +166,61 @@ enum
|
||||
OPEN_FLAGS_PROTECTED_HANDLE = 0x40000000
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FILE_BEGIN,
|
||||
FILE_CURRENT,
|
||||
FILE_END
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
FIL_STANDARD = 1,
|
||||
FIL_QUERYEASIZE = 2,
|
||||
FIL_QUERYEASFROMLIST = 3,
|
||||
FIL_QUERYFULLNAME = 5
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
USHORT day : 5;
|
||||
USHORT month : 4;
|
||||
USHORT year : 7;
|
||||
} FDATE, *PFDATE;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
USHORT twosecs : 5;
|
||||
USHORT minutes : 6;
|
||||
USHORT hours : 5;
|
||||
} FTIME, *PFTIME;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FDATE fdateCreation;
|
||||
FTIME ftimeCreation;
|
||||
FDATE fdateLastAccess;
|
||||
FTIME ftimeLastAccess;
|
||||
FDATE fdateLastWrite;
|
||||
FTIME ftimeLastWrite;
|
||||
ULONG cbFile;
|
||||
ULONG cbFileAlloc;
|
||||
ULONG attrFile;
|
||||
} FILESTATUS3, *PFILESTATUS3;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FDATE fdateCreation;
|
||||
FTIME ftimeCreation;
|
||||
FDATE fdateLastAccess;
|
||||
FTIME ftimeLastAccess;
|
||||
FDATE fdateLastWrite;
|
||||
FTIME ftimeLastWrite;
|
||||
ULONG cbFile;
|
||||
ULONG cbFileAlloc;
|
||||
ULONG attrFile;
|
||||
ULONG cbList;
|
||||
} FILESTATUS4, *PFILESTATUS4;
|
||||
|
||||
// !!! FIXME: these should probably get sorted alphabetically and/or grouped
|
||||
// !!! FIXME: into areas of functionality, but for now, I'm just listing them
|
||||
@@ -191,6 +246,15 @@ APIRET OS2API DosQueryHType(HFILE hFile, PULONG pType, PULONG pAttr);
|
||||
APIRET OS2API DosSetMem(PVOID pb, ULONG cb, ULONG flag);
|
||||
APIRET OS2API DosGetDateTime(PDATETIME pdt);
|
||||
APIRET OS2API DosOpen(PSZ pszFileName, PHFILE pHf, PULONG pulAction, ULONG cbFile, ULONG ulAttribute, ULONG fsOpenFlags, ULONG fsOpenMode, PEAOP2 peaop2);
|
||||
APIRET OS2API DosRequestMutexSem(HMTX hmtx, ULONG ulTimeout);
|
||||
APIRET OS2API DosReleaseMutexSem(HMTX hmtx);
|
||||
APIRET OS2API DosSetFilePtr(HFILE hFile, LONG ib, ULONG method, PULONG ibActual);
|
||||
APIRET OS2API DosRead(HFILE hFile, PVOID pBuffer, ULONG cbRead, PULONG pcbActual);
|
||||
APIRET OS2API DosClose(HFILE hFile);
|
||||
APIRET OS2API DosEnterMustComplete(PULONG pulNesting);
|
||||
APIRET OS2API DosExitMustComplete(PULONG pulNesting);
|
||||
APIRET OS2API DosQueryPathInfo(PSZ pszPathName, ULONG ulInfoLevel, PVOID pInfoBuf, ULONG cbInfoBuf);
|
||||
APIRET OS2API DosQueryFileInfo(HFILE hf, ULONG ulInfoLevel, PVOID pInfo, ULONG cbInfoBuf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+17
-1
@@ -11,8 +11,24 @@ APIRET DosQueryDBCSEnv(ULONG buflen, PCOUNTRYCODE pcc, PCHAR buf)
|
||||
return NO_ERROR;
|
||||
} // DosQueryDBCSEnv
|
||||
|
||||
APIRET DosMapCase(ULONG cb, PCOUNTRYCODE pcc, PCHAR pch)
|
||||
{
|
||||
// !!! FIXME: implement this for real.
|
||||
TRACE_NATIVE("DosMapCase(%u, %p, %p)", (uint) cb, pcc, pch);
|
||||
if ((pcc->country != 0) || (pcc->codepage != 0))
|
||||
return ERROR_CODE_PAGE_NOT_FOUND;
|
||||
|
||||
for (ULONG i = 0; i < cb; i++) {
|
||||
const CHAR ch = *pch;
|
||||
*(pch++) = ((ch >= 'A') && (ch <= 'Z')) ? ch - ('A' - 'a') : ch;
|
||||
} // for
|
||||
|
||||
return NO_ERROR;
|
||||
} // DosMapCase
|
||||
|
||||
LX_NATIVE_MODULE_INIT()
|
||||
LX_NATIVE_EXPORT(DosQueryDBCSEnv, 6)
|
||||
LX_NATIVE_EXPORT(DosQueryDBCSEnv, 6),
|
||||
LX_NATIVE_EXPORT(DosMapCase, 7)
|
||||
LX_NATIVE_MODULE_INIT_END()
|
||||
|
||||
// end of nls.c ...
|
||||
|
||||
@@ -14,6 +14,7 @@ typedef struct COUNTRYCODE
|
||||
} COUNTRYCODE, *PCOUNTRYCODE;
|
||||
|
||||
APIRET OS2API DosQueryDBCSEnv(ULONG cb, PCOUNTRYCODE pcc, PCHAR pBuf);
|
||||
APIRET OS2API DosMapCase(ULONG cb, PCOUNTRYCODE pcc, PCHAR pch);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user