Bunch more work on 16-bit entry points.
Can run testargv16.exe now. This means Watcom C startup code, and Watcom's printf(), both work.
This commit is contained in:
1 parent
36dedda17c
commit
37c3cc5a0a
9 files changed
+356
-58
No files matched your search
@@ -329,6 +329,14 @@ static char *makeUnixPath_lib2ine(const char *os2path, uint32 *err)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void *allocSegment_lib2ine(uint16 *selector, const int iscode)
|
||||
{
|
||||
if (selector) *selector = 0xFFFF;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void freeSegment_lib2ine(const uint16 selector) {}
|
||||
|
||||
static void __attribute__((noreturn)) terminate_lib2ine(const uint32 exitcode)
|
||||
{
|
||||
exit((int) exitcode); // let static constructors and atexit() run.
|
||||
@@ -348,6 +356,8 @@ LX_NATIVE_CONSTRUCTOR(lib2ine)
|
||||
GLoaderState.setOs2Tib = setOs2Tib_lib2ine;
|
||||
GLoaderState.getOs2Tib = getOs2Tib_lib2ine;
|
||||
GLoaderState.deinitOs2Tib = deinitOs2Tib_lib2ine;
|
||||
GLoaderState.allocSegment = allocSegment_lib2ine;
|
||||
GLoaderState.freeSegment = freeSegment_lib2ine;
|
||||
GLoaderState.findSelector = findSelector_lib2ine;
|
||||
GLoaderState.freeSelector = freeSelector_lib2ine;
|
||||
GLoaderState.convert1616to32 = convert1616to32_lib2ine;
|
||||
|
||||
@@ -304,6 +304,8 @@ typedef struct LxLoaderState
|
||||
uint16 (*setOs2Tib)(uint8 *tibspace);
|
||||
LxTIB *(*getOs2Tib)(void);
|
||||
void (*deinitOs2Tib)(const uint16 selector);
|
||||
void *(*allocSegment)(uint16 *selector, const int iscode);
|
||||
void (*freeSegment)(const uint16 selector);
|
||||
int (*findSelector)(const uint32 addr, uint16 *outselector, uint16 *outoffset, int iscode);
|
||||
void (*freeSelector)(const uint16 selector);
|
||||
void *(*convert1616to32)(const uint32 addr1616);
|
||||
|
||||
+45
-33
@@ -672,6 +672,41 @@ static __attribute__((noreturn)) void endLxProcess(const uint32 exitcode)
|
||||
lxTerminate(exitcode); // just in case.
|
||||
} // endLxProcess
|
||||
|
||||
static void *lxAllocSegment(uint16 *selector, const int iscode)
|
||||
{
|
||||
// These are meant to be 64k segments mapped for use by 16-bit code, which means we
|
||||
// need them under 512 megabytes so their segments can convert directly to a linear
|
||||
// address with some bit twiddling.
|
||||
static size_t baseaddr = 136 * 1024 * 1024; // just start at a random low address that (hopefully) doesn't overlap anything.
|
||||
const uint32 segmentsize = 0x10000;
|
||||
void *segment = mmap((void *) baseaddr, segmentsize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (segment == ((void *) MAP_FAILED)) {
|
||||
FIXME("This could be more robust.");
|
||||
fprintf(stderr, "Failed to mmap a 16-bit friendly memory segment.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
baseaddr += segmentsize;
|
||||
uint16 offset = 0xFFFF;
|
||||
*selector = 0xFFFF;
|
||||
lxFindSelector((uint32) segment, selector, &offset, iscode);
|
||||
assert(*selector != 0xFFFF);
|
||||
assert(offset == 0);
|
||||
//printf("lxAllocSegment: addr=%p, selector=%x\n", segment, (uint) *selector);
|
||||
return segment;
|
||||
} // lxAllocSegment
|
||||
|
||||
static void lxFreeSegment(const uint16 selector)
|
||||
{
|
||||
const uint32 addr32 = GLoaderState.ldt[selector];
|
||||
if (addr32) {
|
||||
void *addr = (void *) ((size_t) addr32);
|
||||
//printf("lxFreeSegment: addr=%p, selector=%x\n", addr, (uint) selector);
|
||||
munmap(addr, 0x10000);
|
||||
lxFreeSelector(selector);
|
||||
} // if
|
||||
} // lxFreeSegment
|
||||
|
||||
static void missingEntryPointCalled(const char *module, const char *entry)
|
||||
{
|
||||
fflush(stdout);
|
||||
@@ -732,31 +767,6 @@ static void *generateMissingTrampoline(const char *_module, const char *_entry)
|
||||
return trampoline;
|
||||
} // generateMissingTrampoline
|
||||
|
||||
|
||||
static void *mmapSegment(uint16 *selector, const int iscode)
|
||||
{
|
||||
// These are meant to be 64k segments mapped for use by 16-bit code, which means we
|
||||
// need them under 512 megabytes so their segments can convert directly to a linear
|
||||
// address with some bit twiddling.
|
||||
static size_t baseaddr = 136 * 1024 * 1024; // just start at a random low address that (hopefully) doesn't overlap anything.
|
||||
const uint32 segmentsize = 0x10000;
|
||||
void *segment = mmap((void *) baseaddr, segmentsize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (segment == ((void *) MAP_FAILED)) {
|
||||
FIXME("This could be more robust.");
|
||||
fprintf(stderr, "Failed to mmap a 16-bit friendly memory segment.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
baseaddr += segmentsize;
|
||||
uint16 offset = 0xFFFF;
|
||||
*selector = 0xFFFF;
|
||||
lxFindSelector((uint32) segment, selector, &offset, iscode);
|
||||
assert(*selector != 0xFFFF);
|
||||
assert(offset == 0);
|
||||
return segment;
|
||||
} // mmapSegment
|
||||
|
||||
|
||||
static void *generateMissingTrampoline16(const char *_module, const char *_entry, const LxExport **_lxexp)
|
||||
{
|
||||
static void *segment = NULL;
|
||||
@@ -768,7 +778,7 @@ static void *generateMissingTrampoline16(const char *_module, const char *_entry
|
||||
{
|
||||
if (segment)
|
||||
mprotect(segment, segmentsize, PROT_READ | PROT_EXEC);
|
||||
segment = mmapSegment(&selector, 1);
|
||||
segment = lxAllocSegment(&selector, 1);
|
||||
assert(segment != NULL);
|
||||
assert(selector != 0xFFFF);
|
||||
segmentused = 0;
|
||||
@@ -918,9 +928,9 @@ static __attribute__((noreturn)) void runNeModule(LxModule *lxmod)
|
||||
// so we do both.
|
||||
const uint16 stacksize = (uint16) GLoaderState.mainstacksize;
|
||||
const uint16 ss = (lxmod->esp >> 16) & 0xFFFF; // stack segment
|
||||
const uint32 env1616 = lxConvert32to1616(GLoaderState.pib.pib_pchenv); // this is meant to be aligned to a segment.
|
||||
const uint16 cmdlineoffset = env1616 & 0xFFFF;
|
||||
const uint16 envseg = (env1616 >> 16) & 0xFFFF;
|
||||
const uint32 cmd1616 = lxConvert32to1616(GLoaderState.pib.pib_pchcmd);
|
||||
const uint16 cmdlineoffset = cmd1616 & 0xFFFF;
|
||||
const uint16 envseg = (cmd1616 >> 16) & 0xFFFF;
|
||||
|
||||
uint8 *stack = (uint8 *) lxConvert1616to32(lxmod->esp);
|
||||
//printf("stack is at 32=%p 16=%x:%x\n", stack, (uint) ss, (uint) (lxmod->esp & 0xFFFF));
|
||||
@@ -932,7 +942,7 @@ static __attribute__((noreturn)) void runNeModule(LxModule *lxmod)
|
||||
stack -= 2; *((uint16 *) stack) = ss; // bottom of stack
|
||||
|
||||
uint16 selector = 0xFFFF;
|
||||
void *segment = mmapSegment(&selector, 1);
|
||||
void *segment = lxAllocSegment(&selector, 1);
|
||||
assert(segment != NULL);
|
||||
assert(selector != 0xFFFF);
|
||||
char *ptr = (char *) segment;
|
||||
@@ -2180,11 +2190,11 @@ static LxModule *loadNeModule(const char *fname, const uint8 *origexe, uint8 *ex
|
||||
//const int movable = (seg->segment_flags & 0x10) != 0;
|
||||
const int iscode = ((seg->segment_flags & 0x7) == 0) ? 1 : 0;
|
||||
uint16 selector = 0xFFFF;
|
||||
void *mmapaddr = mmapSegment(&selector, iscode);
|
||||
//printf("%s neobj #%u mmapSegment(%d) == %p (selector=0x%X)\n", retval->name, (uint) i, iscode, mmapaddr, (uint) selector);
|
||||
void *mmapaddr = lxAllocSegment(&selector, iscode);
|
||||
//printf("%s neobj #%u lxAllocSegment(%d) == %p (selector=0x%X)\n", retval->name, (uint) i, iscode, mmapaddr, (uint) selector);
|
||||
|
||||
if (mmapaddr == NULL) {
|
||||
fprintf(stderr, "mmapSegment(%d) failed\n", iscode);
|
||||
fprintf(stderr, "lxAllocSegment(%d) failed\n", iscode);
|
||||
goto loadne_failed;
|
||||
} else if (selector == 0xFFFF) {
|
||||
munmap(mmapaddr, vsize);
|
||||
@@ -2709,6 +2719,8 @@ int main(int argc, char **argv, char **envp)
|
||||
GLoaderState.setOs2Tib = lxSetOs2Tib;
|
||||
GLoaderState.getOs2Tib = lxGetOs2Tib;
|
||||
GLoaderState.deinitOs2Tib = lxDeinitOs2Tib;
|
||||
GLoaderState.allocSegment = lxAllocSegment;
|
||||
GLoaderState.freeSegment = lxFreeSegment;
|
||||
GLoaderState.findSelector = lxFindSelector;
|
||||
GLoaderState.freeSelector = lxFreeSelector;
|
||||
GLoaderState.convert1616to32 = lxConvert1616to32;
|
||||
|
||||
+68
-1
@@ -15,6 +15,24 @@ static VOID bridge16to32_Dos16Exit(uint8 *args) {
|
||||
Dos16Exit(action, result);
|
||||
}
|
||||
|
||||
static APIRET16 bridge16to32_Dos16AllocSeg(uint8 *args) {
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_ARG(USHORT, flags);
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PUSHORT, psel);
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_ARG(USHORT, size);
|
||||
return Dos16AllocSeg(size, psel, flags);
|
||||
}
|
||||
|
||||
static APIRET16 bridge16to32_Dos16ReallocSeg(uint8 *args) {
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_ARG(USHORT, sel);
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_ARG(USHORT, size);
|
||||
return Dos16ReallocSeg(size, sel);
|
||||
}
|
||||
|
||||
static APIRET16 bridge16to32_Dos16FreeSeg(uint8 *args) {
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_ARG(USHORT, sel);
|
||||
return Dos16FreeSeg(sel);
|
||||
}
|
||||
|
||||
static APIRET16 bridge16to32_Dos16GetHugeShift(uint8 *args) {
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PUSHORT, pcount);
|
||||
return Dos16GetHugeShift(pcount);
|
||||
@@ -25,16 +43,44 @@ static APIRET16 bridge16to32_Dos16GetMachineMode(uint8 *args) {
|
||||
return Dos16GetMachineMode(pmode);
|
||||
}
|
||||
|
||||
static APIRET16 bridge16to32_Dos16QHandType(uint8 *args) {
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PUSHORT, pflags);
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PUSHORT, ptype);
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_ARG(USHORT, handle);
|
||||
return Dos16QHandType(handle, ptype, pflags);
|
||||
}
|
||||
|
||||
static APIRET16 bridge16to32_Dos16GetEnv(uint8 *args) {
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PUSHORT, pcmdoffset);
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PUSHORT, psel);
|
||||
return Dos16GetEnv(psel, pcmdoffset);
|
||||
}
|
||||
|
||||
static APIRET16 bridge16to32_Dos16GetVersion(uint8 *args) {
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PUSHORT, pver);
|
||||
return Dos16GetVersion(pver);
|
||||
}
|
||||
|
||||
static APIRET16 bridge16to32_Dos16GetPID(uint8 *args) {
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PPIDINFO, ppidinfo);
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PPIDINFO16, ppidinfo);
|
||||
return Dos16GetPID(ppidinfo);
|
||||
}
|
||||
|
||||
static APIRET16 bridge16to32_Dos16GetCp(uint8 *args) {
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PUSHORT, pcCP);
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PUSHORT, arCP);
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_ARG(USHORT, cb);
|
||||
return Dos16GetCp(cb, arCP, pcCP);
|
||||
}
|
||||
|
||||
static APIRET16 bridge16to32_Dos16Write(uint8 *args) {
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PUSHORT, actual);
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_ARG(USHORT, buflen);
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PVOID, buf);
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_ARG(USHORT, h);
|
||||
return Dos16Write(h, buf, buflen, actual);
|
||||
}
|
||||
|
||||
static APIRET16 bridge16to32_DosSemRequest(uint8 *args) {
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_ARG(LONG, ms);
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PHSEM16, sem);
|
||||
@@ -59,10 +105,17 @@ static APIRET16 bridge16to32_DosSemSet(uint8 *args) {
|
||||
|
||||
LX_NATIVE_MODULE_16BIT_SUPPORT()
|
||||
LX_NATIVE_MODULE_16BIT_API(Dos16Exit)
|
||||
LX_NATIVE_MODULE_16BIT_API(Dos16AllocSeg)
|
||||
LX_NATIVE_MODULE_16BIT_API(Dos16ReallocSeg)
|
||||
LX_NATIVE_MODULE_16BIT_API(Dos16FreeSeg)
|
||||
LX_NATIVE_MODULE_16BIT_API(Dos16GetHugeShift)
|
||||
LX_NATIVE_MODULE_16BIT_API(Dos16GetMachineMode)
|
||||
LX_NATIVE_MODULE_16BIT_API(Dos16QHandType)
|
||||
LX_NATIVE_MODULE_16BIT_API(Dos16GetEnv)
|
||||
LX_NATIVE_MODULE_16BIT_API(Dos16GetVersion)
|
||||
LX_NATIVE_MODULE_16BIT_API(Dos16GetPID)
|
||||
LX_NATIVE_MODULE_16BIT_API(Dos16GetCp)
|
||||
LX_NATIVE_MODULE_16BIT_API(Dos16Write)
|
||||
LX_NATIVE_MODULE_16BIT_API(DosSemRequest)
|
||||
LX_NATIVE_MODULE_16BIT_API(DosSemClear)
|
||||
LX_NATIVE_MODULE_16BIT_API(DosSemWait)
|
||||
@@ -76,10 +129,17 @@ LX_NATIVE_MODULE_DEINIT({
|
||||
static int init16_doscalls(void) {
|
||||
LX_NATIVE_MODULE_INIT_16BIT_SUPPORT()
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(Dos16Exit, 4)
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(Dos16AllocSeg, 8)
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(Dos16ReallocSeg, 4)
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(Dos16FreeSeg, 2)
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(Dos16GetHugeShift, 4)
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(Dos16GetMachineMode, 4)
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(Dos16QHandType, 10)
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(Dos16GetEnv, 8)
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(Dos16GetVersion, 4)
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(Dos16GetPID, 4)
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(Dos16GetCp, 10)
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(Dos16Write, 12)
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(DosSemRequest, 8)
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(DosSemClear, 4)
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(DosSemWait, 8)
|
||||
@@ -90,10 +150,17 @@ static int init16_doscalls(void) {
|
||||
|
||||
LX_NATIVE_MODULE_INIT({ if (!init16_doscalls()) return 0; })
|
||||
LX_NATIVE_EXPORT16(Dos16Exit, 5),
|
||||
LX_NATIVE_EXPORT16(Dos16AllocSeg, 34),
|
||||
LX_NATIVE_EXPORT16(Dos16ReallocSeg, 38),
|
||||
LX_NATIVE_EXPORT16(Dos16FreeSeg, 39),
|
||||
LX_NATIVE_EXPORT16(Dos16GetHugeShift, 41),
|
||||
LX_NATIVE_EXPORT16(Dos16GetMachineMode, 49),
|
||||
LX_NATIVE_EXPORT16(Dos16QHandType, 77),
|
||||
LX_NATIVE_EXPORT16(Dos16GetEnv, 91),
|
||||
LX_NATIVE_EXPORT16(Dos16GetVersion, 92),
|
||||
LX_NATIVE_EXPORT16(Dos16GetPID, 94),
|
||||
LX_NATIVE_EXPORT16(Dos16GetCp, 130),
|
||||
LX_NATIVE_EXPORT16(Dos16Write, 138),
|
||||
LX_NATIVE_EXPORT16(DosSemRequest, 140),
|
||||
LX_NATIVE_EXPORT16(DosSemClear, 141),
|
||||
LX_NATIVE_EXPORT16(DosSemWait, 142),
|
||||
|
||||
+173
-17
@@ -127,6 +127,39 @@ static void timespecNowPlusMilliseconds(struct timespec *waittime, const ULONG u
|
||||
} // if
|
||||
} // timespecNowPlusMilliseconds
|
||||
|
||||
static void initHFileInfoFromUnixFd(const int fd, HFileInfo *info)
|
||||
{
|
||||
struct stat statbuf;
|
||||
if ((fd != -1) && (fstat(fd, &statbuf) == 0)) {
|
||||
ULONG type = 0;
|
||||
switch (statbuf.st_mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
type = 0;
|
||||
break;
|
||||
case S_IFBLK:
|
||||
case S_IFCHR:
|
||||
type = 1;
|
||||
break;
|
||||
case S_IFIFO:
|
||||
case S_IFSOCK:
|
||||
default:
|
||||
type = 2;
|
||||
break;
|
||||
} // switch
|
||||
info->fd = fd;
|
||||
info->type = type;
|
||||
FIXME("What should this be?");
|
||||
info->attr = DAW_STDIN | DAW_STDOUT | DAW_LEVEL1 | DAW_CHARACTER;
|
||||
info->flags = 0;
|
||||
} else {
|
||||
info->fd = -1;
|
||||
info->type = 0;
|
||||
info->attr = 0;
|
||||
info->flags = 0;
|
||||
} // else
|
||||
} // initHFileInfoFromUnixFd
|
||||
|
||||
|
||||
APIRET DosGetInfoBlocks(PTIB *pptib, PPIB *pppib)
|
||||
{
|
||||
TRACE_NATIVE("DosGetInfoBlocks(%p, %p)", pptib, pppib);
|
||||
@@ -259,11 +292,8 @@ static int getHFileUnixDescriptor(HFILE h)
|
||||
return fd;
|
||||
} // getHFileUnixDescriptor
|
||||
|
||||
|
||||
APIRET DosWrite(HFILE h, PVOID buf, ULONG buflen, PULONG actual)
|
||||
static APIRET DosWrite_implementation(HFILE h, PVOID buf, ULONG buflen, PULONG actual)
|
||||
{
|
||||
TRACE_NATIVE("DosWrite(%u, %p, %u, %p)", (uint) h, buf, (uint) buflen, actual);
|
||||
|
||||
const int fd = getHFileUnixDescriptor(h);
|
||||
if (fd == -1)
|
||||
return ERROR_INVALID_HANDLE;
|
||||
@@ -277,6 +307,12 @@ APIRET DosWrite(HFILE h, PVOID buf, ULONG buflen, PULONG actual)
|
||||
|
||||
*actual = (uint32) rc;
|
||||
return NO_ERROR;
|
||||
} // DosWrite_implementation
|
||||
|
||||
APIRET DosWrite(HFILE h, PVOID buf, ULONG buflen, PULONG actual)
|
||||
{
|
||||
TRACE_NATIVE("DosWrite(%u, %p, %u, %p)", (uint) h, buf, (uint) buflen, actual);
|
||||
return DosWrite_implementation(h, buf, buflen, actual);
|
||||
} // DosWrite
|
||||
|
||||
static void runDosExitList(const uint32 why)
|
||||
@@ -555,6 +591,7 @@ APIRET DosSetRelMaxFH(PLONG pincr, PULONG pcurrent)
|
||||
HFileInfo *info = (HFileInfo *) realloc(HFiles, sizeof (HFileInfo) * (MaxHFiles + incr));
|
||||
if (info != NULL) {
|
||||
HFiles = info;
|
||||
FIXME("this needs to initialize the end of the array, not the front");
|
||||
for (LONG i = 0; i < incr; i++, info++) {
|
||||
info->fd = -1;
|
||||
info->type = 0;
|
||||
@@ -605,10 +642,8 @@ APIRET DosSubAllocMem(PVOID pbBase, PPVOID ppb, ULONG cb)
|
||||
return NO_ERROR;
|
||||
} // DosSubAllocMem
|
||||
|
||||
APIRET DosQueryHType(HFILE hFile, PULONG pType, PULONG pAttr)
|
||||
static APIRET DosQueryHType_implementation(HFILE hFile, PULONG pType, PULONG pAttr)
|
||||
{
|
||||
TRACE_NATIVE("DosQueryHType(%u, %p, %p)", (uint) hFile, pType, pAttr);
|
||||
|
||||
APIRET retval = NO_ERROR;
|
||||
|
||||
grabLock(&GMutexDosCalls);
|
||||
@@ -622,6 +657,12 @@ APIRET DosQueryHType(HFILE hFile, PULONG pType, PULONG pAttr)
|
||||
ungrabLock(&GMutexDosCalls);
|
||||
|
||||
return retval;
|
||||
} // DosQueryHType_implementation
|
||||
|
||||
APIRET DosQueryHType(HFILE hFile, PULONG pType, PULONG pAttr)
|
||||
{
|
||||
TRACE_NATIVE("DosQueryHType(%u, %p, %p)", (uint) hFile, pType, pAttr);
|
||||
return DosQueryHType_implementation(hFile, pType, pAttr);
|
||||
} // DosQueryHType
|
||||
|
||||
APIRET DosSetMem(PVOID pb, ULONG cb, ULONG flag)
|
||||
@@ -809,7 +850,7 @@ static APIRET doDosOpen(PSZ pszFileName, PHFILE pHf, PULONG pulAction, LONGLONG
|
||||
FIXME("Replacing a file should delete all its EAs, too");
|
||||
} // if
|
||||
|
||||
info->fd = fd;
|
||||
initHFileInfoFromUnixFd(fd, info);
|
||||
|
||||
if (fd == -1) {
|
||||
switch (errno) {
|
||||
@@ -1998,7 +2039,7 @@ APIRET DosQueryCp(ULONG cb, PULONG arCP, PULONG pcCP)
|
||||
|
||||
FIXME("This is mostly a stub");
|
||||
|
||||
if (cb < sizeof (ULONG) * 2)
|
||||
if (cb < sizeof (*arCP) * 2)
|
||||
return ERROR_CPLIST_TOO_SMALL;
|
||||
|
||||
// 437 == United States codepage.
|
||||
@@ -2006,7 +2047,7 @@ APIRET DosQueryCp(ULONG cb, PULONG arCP, PULONG pcCP)
|
||||
arCP[1] = 437; // prepared system codepage
|
||||
|
||||
if (pcCP)
|
||||
*pcCP = sizeof (ULONG) * 2;
|
||||
*pcCP = sizeof (*arCP) * 2;
|
||||
|
||||
return NO_ERROR;
|
||||
} // DosQueryCp
|
||||
@@ -2890,13 +2931,21 @@ APIRET16 Dos16GetHugeShift(PUSHORT pcount)
|
||||
return NO_ERROR;
|
||||
} // Dos16GetHugeShift
|
||||
|
||||
APIRET16 Dos16GetPID(PPIDINFO ppidinfo)
|
||||
APIRET16 Dos16GetPID(PPIDINFO16 ppidinfo)
|
||||
{
|
||||
TRACE_NATIVE("Dos16GetPID(%p)", ppidinfo);
|
||||
PTIB2 tib2 = (PTIB2) LX_GETTIB2();
|
||||
ppidinfo->pid = GLoaderState.pib.pib_ulpid;
|
||||
ppidinfo->tid = tib2->tib2_ultid;
|
||||
ppidinfo->pidParent = GLoaderState.pib.pib_ulppid;
|
||||
|
||||
// note that these happen to fit Linux default PID ranges in 2018, which
|
||||
// tend to be 32768, but can be much higher by writing to
|
||||
// /proc/sys/kernel/pid_max
|
||||
assert(GLoaderState.pib.pib_ulpid <= 0xFFFF);
|
||||
assert(GLoaderState.pib.pib_ulppid <= 0xFFFF);
|
||||
assert(tib2->tib2_ultid <= 0xFFFF);
|
||||
|
||||
ppidinfo->pid = (USHORT) GLoaderState.pib.pib_ulpid;
|
||||
ppidinfo->tid = (USHORT) tib2->tib2_ultid;
|
||||
ppidinfo->pidParent = (USHORT) GLoaderState.pib.pib_ulppid;
|
||||
return NO_ERROR;
|
||||
} // Dos16GetPID
|
||||
|
||||
@@ -2906,6 +2955,114 @@ VOID Dos16Exit(USHORT action, USHORT exitcode)
|
||||
DosExit_implementation(action, exitcode);
|
||||
} // Dos16Exit
|
||||
|
||||
APIRET16 Dos16QHandType(USHORT handle, PUSHORT ptype, PUSHORT pflags)
|
||||
{
|
||||
TRACE_NATIVE("Dos16QHandType(%u, %p, %p)", (uint) handle, ptype, pflags);
|
||||
ULONG ultype, ulattr;
|
||||
const APIRET rc = DosQueryHType_implementation((HFILE) handle, &ultype, &ulattr);
|
||||
if (rc == NO_ERROR) {
|
||||
if (ptype) *ptype = (USHORT) ultype;
|
||||
if (pflags) *pflags = (USHORT) ulattr;
|
||||
} // if
|
||||
return (APIRET16) rc;
|
||||
} // Dos16QHandType
|
||||
|
||||
APIRET16 Dos16AllocSeg(USHORT size, PUSHORT psel, USHORT flags)
|
||||
{
|
||||
TRACE_NATIVE("Dos16AllocSeg(%u, %p, %u)", (uint) size, psel, (uint) flags);
|
||||
if (psel == NULL) {
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
} else if ((flags & 0xFFF0) != 0) { // these bits are reserved and must be zero.
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// we don't care about the size, we just allocate a whole 64k segment. Oh well.
|
||||
uint16 sel = 0xFFFF;
|
||||
//void *addr = GLoaderState.allocSegment(&sel, 1); // we mark these as code in case they want to do self-modifying magic, etc.
|
||||
void *addr = GLoaderState.allocSegment(&sel, 0);
|
||||
if (!addr) {
|
||||
assert(sel == 0xFFFF);
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
assert(sel != 0xFFFF);
|
||||
|
||||
if (flags & (1 << 0)) {
|
||||
FIXME("segment is meant to be shareable through Dos16GiveSeg");
|
||||
}
|
||||
|
||||
if (flags & (1 << 1)) {
|
||||
FIXME("segment is meant to be shareable through Dos16GetSeg");
|
||||
}
|
||||
|
||||
// documentation says this is a selector (specifically: a segment only on
|
||||
// DOS in the family mode API), but it looks like OS/2 wants a segment too.
|
||||
//*psel = (USHORT) sel;
|
||||
*psel = (USHORT) ((sel << 3) | 7);
|
||||
return NO_ERROR;
|
||||
} // Dos16AllocSeg
|
||||
|
||||
APIRET16 Dos16ReallocSeg(USHORT size, USHORT sel)
|
||||
{
|
||||
TRACE_NATIVE("Dos16ReallocSeg(%u, %u)", (uint) size, (uint) sel);
|
||||
|
||||
// we don't ever discard segments, and we always allocate the full 64k,
|
||||
// so we don't have to worry about resizing an existing segment.
|
||||
// But there are sharing concerns, etc.
|
||||
FIXME("this implementation is severely lacking");
|
||||
|
||||
// (we should probably make sure the selector is valid...)
|
||||
return NO_ERROR;
|
||||
} // Dos16ReallocSeg
|
||||
|
||||
APIRET16 Dos16FreeSeg(USHORT sel)
|
||||
{
|
||||
TRACE_NATIVE("Dos16FreeSeg(%u)", (uint) sel);
|
||||
FIXME("this needs to deal with reference counting and shared segments");
|
||||
// documentation says this is a selector (specifically: a segment only on
|
||||
// DOS in the family mode API), but it looks like OS/2 wants a segment too.
|
||||
GLoaderState.freeSegment(sel >> 3);
|
||||
return NO_ERROR;
|
||||
} // Dos16FreeSeg
|
||||
|
||||
APIRET16 Dos16GetCp(USHORT cb, PUSHORT arCP, PUSHORT pcCP)
|
||||
{
|
||||
TRACE_NATIVE("Dos16GetCp(%u, %p, %p)", (uint) cb, arCP, pcCP);
|
||||
|
||||
FIXME("This is mostly a stub");
|
||||
FIXME("...and mostly copy/paste from DosQueryCp()...");
|
||||
|
||||
if (cb < sizeof (*arCP) * 2)
|
||||
return ERROR_CPLIST_TOO_SMALL;
|
||||
|
||||
// 437 == United States codepage.
|
||||
arCP[0] = 437; // current process codepage
|
||||
arCP[1] = 437; // prepared system codepage
|
||||
|
||||
if (pcCP)
|
||||
*pcCP = sizeof (*arCP) * 2;
|
||||
|
||||
return NO_ERROR;
|
||||
} // Dos16GetCp
|
||||
|
||||
APIRET16 Dos16GetEnv(PUSHORT psel, PUSHORT pcmdoffset)
|
||||
{
|
||||
TRACE_NATIVE("Dos16GetEnv(%p, %p)", psel, pcmdoffset);
|
||||
const uint32 cmd1616 = GLoaderState.convert32to1616(GLoaderState.pib.pib_pchcmd);
|
||||
if (pcmdoffset) *pcmdoffset = (USHORT) (cmd1616 & 0xFFFF);
|
||||
if (psel) *psel = (USHORT) ((cmd1616 >> 16) & 0xFFFF);
|
||||
return NO_ERROR;
|
||||
} // Dos16GetEnv
|
||||
|
||||
APIRET16 Dos16Write(USHORT h, PVOID buf, USHORT buflen, PUSHORT actual)
|
||||
{
|
||||
TRACE_NATIVE("DosWrite(%u, %p, %u, %p)", (uint) h, buf, (uint) buflen, actual);
|
||||
ULONG ulactual = actual ? *actual : 0;
|
||||
APIRET rc = DosWrite_implementation(h, buf, buflen, &ulactual);
|
||||
if (actual) *actual = (USHORT) ulactual;
|
||||
return (APIRET16) rc;
|
||||
} // Dos16Write
|
||||
|
||||
|
||||
LX_NATIVE_CONSTRUCTOR(doscalls)
|
||||
{
|
||||
@@ -2942,10 +3099,9 @@ LX_NATIVE_CONSTRUCTOR(doscalls)
|
||||
// inherited from CMD.EXE or supplied by OS/2 for whatever purpose.
|
||||
// For now, we just wire up stdio.
|
||||
|
||||
FIXME("We can iterate /proc/self/fd to get all currently-open files");
|
||||
for (int i = 0; i <= 2; i++) {
|
||||
HFiles[i].fd = i;
|
||||
HFiles[i].type = 1; // !!! FIXME: could be a pipe or file.
|
||||
HFiles[i].attr = DAW_STDIN | DAW_STDOUT | DAW_LEVEL1 | DAW_CHARACTER;
|
||||
initHFileInfoFromUnixFd(i, &HFiles[i]);
|
||||
} // for
|
||||
}
|
||||
|
||||
|
||||
+14
-5
@@ -435,13 +435,22 @@ OS2EXPORT APIRET16 OS2API16 Dos16GetVersion(PUSHORT pver) OS2APIINFO(92);
|
||||
OS2EXPORT APIRET16 OS2API16 Dos16GetMachineMode(PBYTE pmode) OS2APIINFO(49);
|
||||
OS2EXPORT APIRET16 OS2API16 Dos16GetHugeShift(PUSHORT pcount) OS2APIINFO(41);
|
||||
OS2EXPORT VOID OS2API16 Dos16Exit(USHORT action, USHORT result) OS2APIINFO(5);
|
||||
OS2EXPORT APIRET16 OS2API16 Dos16QHandType(USHORT handle, PUSHORT ptype, PUSHORT pflags) OS2APIINFO(77);
|
||||
OS2EXPORT APIRET16 OS2API16 Dos16AllocSeg(USHORT size, PUSHORT psel, USHORT flags) OS2APIINFO(34);
|
||||
OS2EXPORT APIRET16 OS2API16 Dos16ReallocSeg(USHORT size, USHORT sel) OS2APIINFO(38);
|
||||
OS2EXPORT APIRET16 OS2API16 Dos16FreeSeg(USHORT sel) OS2APIINFO(39);
|
||||
|
||||
typedef struct {
|
||||
PID pid;
|
||||
TID tid;
|
||||
PID pidParent;
|
||||
} PIDINFO, *PPIDINFO;
|
||||
OS2EXPORT APIRET16 OS2API16 Dos16GetPID(PPIDINFO ppidinfo) OS2APIINFO(94);
|
||||
USHORT pid;
|
||||
USHORT tid;
|
||||
USHORT pidParent;
|
||||
} PIDINFO16, *PPIDINFO16;
|
||||
|
||||
OS2EXPORT APIRET16 OS2API16 Dos16GetPID(PPIDINFO16 ppidinfo) OS2APIINFO(94);
|
||||
OS2EXPORT APIRET16 OS2API16 Dos16GetCp(USHORT cb, PUSHORT arCP, PUSHORT pcCP) OS2APIINFO(130);
|
||||
OS2EXPORT APIRET16 OS2API16 Dos16GetEnv(PUSHORT psel, PUSHORT pcmdoffset) OS2APIINFO(91);
|
||||
OS2EXPORT APIRET16 OS2API16 Dos16Write(USHORT h, PVOID buf, USHORT buflen, PUSHORT actual) OS2APIINFO(138);
|
||||
|
||||
|
||||
|
||||
// !!! FIXME: these should probably get sorted alphabetically and/or grouped
|
||||
|
||||
+24
-1
@@ -9,7 +9,30 @@
|
||||
/* This is glue code for OS/2 binaries. Native binaries don't need this. */
|
||||
#if LX_LEGACY
|
||||
|
||||
LX_NATIVE_MODULE_INIT()
|
||||
static APIRET16 bridge16to32_Dos16GetDBCSEv(uint8 *args) {
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PCHAR, buf);
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_PTRARG(PCOUNTRYCODE16, pcc);
|
||||
LX_NATIVE_MODULE_16BIT_BRIDGE_ARG(USHORT, buflen);
|
||||
return Dos16GetDBCSEv(buflen, pcc, buf);
|
||||
}
|
||||
|
||||
LX_NATIVE_MODULE_16BIT_SUPPORT()
|
||||
LX_NATIVE_MODULE_16BIT_API(Dos16GetDBCSEv)
|
||||
LX_NATIVE_MODULE_16BIT_SUPPORT_END()
|
||||
|
||||
LX_NATIVE_MODULE_DEINIT({
|
||||
LX_NATIVE_MODULE_DEINIT_16BIT_SUPPORT();
|
||||
})
|
||||
|
||||
static int init16_nls(void) {
|
||||
LX_NATIVE_MODULE_INIT_16BIT_SUPPORT()
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(Dos16GetDBCSEv, 10)
|
||||
LX_NATIVE_MODULE_INIT_16BIT_SUPPORT_END()
|
||||
return 1;
|
||||
}
|
||||
|
||||
LX_NATIVE_MODULE_INIT({ if (!init16_nls()) return 0; })
|
||||
LX_NATIVE_EXPORT16(Dos16GetDBCSEv, 4),
|
||||
LX_NATIVE_EXPORT(DosQueryCtryInfo, 5),
|
||||
LX_NATIVE_EXPORT(DosQueryDBCSEnv, 6),
|
||||
LX_NATIVE_EXPORT(DosMapCase, 7)
|
||||
|
||||
+11
-1
@@ -6,11 +6,21 @@
|
||||
* This file written by Ryan C. Gordon.
|
||||
*/
|
||||
|
||||
#include "os2native.h"
|
||||
#include "os2native16.h"
|
||||
#include "nls.h"
|
||||
|
||||
#include "nls-lx.h"
|
||||
|
||||
APIRET16 Dos16GetDBCSEv(USHORT buflen, PCOUNTRYCODE16 pcc, PCHAR buf)
|
||||
{
|
||||
// !!! FIXME: implement this for real.
|
||||
TRACE_NATIVE("Dos16GetDBCSEv(%u, %p, %p)", (uint) buflen, pcc, buf);
|
||||
if ((pcc->country != 0) || (pcc->codepage != 0))
|
||||
return ERROR_CODE_PAGE_NOT_FOUND;
|
||||
memset(buf, '\0', buflen);
|
||||
return NO_ERROR;
|
||||
} // Dos16GetDBCSEv
|
||||
|
||||
APIRET DosQueryDBCSEnv(ULONG buflen, PCOUNTRYCODE pcc, PCHAR buf)
|
||||
{
|
||||
// !!! FIXME: implement this for real.
|
||||
|
||||
@@ -43,6 +43,15 @@ OS2EXPORT APIRET OS2API DosQueryDBCSEnv(ULONG cb, PCOUNTRYCODE pcc, PCHAR pBuf)
|
||||
OS2EXPORT APIRET OS2API DosMapCase(ULONG cb, PCOUNTRYCODE pcc, PCHAR pch) OS2APIINFO(7);
|
||||
OS2EXPORT APIRET OS2API DosQueryCtryInfo(ULONG cb, PCOUNTRYCODE pcc, PCOUNTRYINFO pci, PULONG pcbActual) OS2APIINFO(5);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
USHORT country;
|
||||
USHORT codepage;
|
||||
} COUNTRYCODE16, *PCOUNTRYCODE16;
|
||||
|
||||
OS2EXPORT APIRET16 OS2API16 Dos16GetDBCSEv(USHORT buflen, PCOUNTRYCODE16 pcc, PCHAR buf) OS2APIINFO(4);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in new issue
Block a user