diff --git a/lib2ine.c b/lib2ine.c index b1191cc..3fd77f0 100644 --- a/lib2ine.c +++ b/lib2ine.c @@ -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; diff --git a/lib2ine.h b/lib2ine.h index 6cf2aae..6f0957b 100644 --- a/lib2ine.h +++ b/lib2ine.h @@ -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); diff --git a/lx_loader.c b/lx_loader.c index 1cdd4e6..11666d7 100644 --- a/lx_loader.c +++ b/lx_loader.c @@ -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; diff --git a/native/doscalls-lx.h b/native/doscalls-lx.h index 8c01448..fadcef2 100644 --- a/native/doscalls-lx.h +++ b/native/doscalls-lx.h @@ -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), diff --git a/native/doscalls.c b/native/doscalls.c index 77045d6..7c71c96 100644 --- a/native/doscalls.c +++ b/native/doscalls.c @@ -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 } diff --git a/native/doscalls.h b/native/doscalls.h index f356eb4..53e497d 100644 --- a/native/doscalls.h +++ b/native/doscalls.h @@ -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 diff --git a/native/nls-lx.h b/native/nls-lx.h index c10fe2f..78e5756 100644 --- a/native/nls-lx.h +++ b/native/nls-lx.h @@ -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) diff --git a/native/nls.c b/native/nls.c index e79923c..f217b8d 100644 --- a/native/nls.c +++ b/native/nls.c @@ -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. diff --git a/native/nls.h b/native/nls.h index f981de4..1fb9cfa 100644 --- a/native/nls.h +++ b/native/nls.h @@ -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