Bunch of work on getting java.exe to start up. Not there yet.
Lots of fixes, improvements, and a few more APIs implemented.
This commit is contained in:
1 parent
411c204ccb
commit
2481f59a28
8 files changed
+306
-55
No files matched your search
+48
-10
@@ -1470,10 +1470,18 @@ static LxModule *loadLxModule(const char *fname, uint8 *exe, uint32 exelen, int
|
||||
*(ptr++) = 0x90; // nop
|
||||
} // if
|
||||
|
||||
// !!! FIXME: hack for Java that fails to mark a code page as executable
|
||||
// !!! FIXME: (on 386 machines, read implies execute, so this error could go unnoticed).
|
||||
uint32 object_flags = obj->object_flags;
|
||||
if ((i == 4) && (strcasecmp(modname, "HPI") == 0)) {
|
||||
fprintf(stderr, "fixed page permissions to workaround bug in Java DLL\n");
|
||||
object_flags |= 0x4;
|
||||
} // if
|
||||
|
||||
// Now set all the pages of this object to the proper final permissions...
|
||||
const int prot = ((obj->object_flags & 0x1) ? PROT_READ : 0) |
|
||||
((obj->object_flags & 0x2) ? PROT_WRITE : 0) |
|
||||
((obj->object_flags & 0x4) ? PROT_EXEC : 0);
|
||||
const int prot = ((object_flags & 0x1) ? PROT_READ : 0) |
|
||||
((object_flags & 0x2) ? PROT_WRITE : 0) |
|
||||
((object_flags & 0x4) ? PROT_EXEC : 0);
|
||||
|
||||
if (mprotect(retval->mmaps[i].mapped, retval->mmaps[i].size, prot) == -1) {
|
||||
fprintf(stderr, "mprotect(%p, %u, %s%s%s, ANON|PRIVATE|FIXED, -1, 0) failed (%d): %s\n",
|
||||
@@ -1692,12 +1700,15 @@ static void initPib(LxPIB *pib, const int argc, char **argv, char **envp)
|
||||
exit(1);
|
||||
} // if
|
||||
|
||||
const char *libpath = NULL;
|
||||
char *ptr = env;
|
||||
for (int i = 0; envp[i]; i++) {
|
||||
const char *str = envp[i];
|
||||
if (strncmp(str, "PATH=", 5) == 0) {
|
||||
if (!GLoaderState->subprocess)
|
||||
str = default_os2path;
|
||||
} else if (strncmp(str, "LIBPATH=", 8) == 0) {
|
||||
libpath = str + 8;
|
||||
} else if (strncmp(str, "IS_2INE=", 8) == 0) {
|
||||
continue;
|
||||
} // if
|
||||
@@ -1707,6 +1718,15 @@ static void initPib(LxPIB *pib, const int argc, char **argv, char **envp)
|
||||
}
|
||||
*(ptr++) = '\0';
|
||||
|
||||
// we keep a copy of LIBPATH for undocumented API
|
||||
// DosQueryHandleInfo(..., QHINF_LIBPATH, ...). I guess in case the app
|
||||
// has changed the environment var after start? Java uses this.
|
||||
if (libpath == NULL)
|
||||
libpath = "";
|
||||
|
||||
GLoaderState->libpath = strdup(libpath);
|
||||
GLoaderState->libpathlen = strlen(libpath) + 1;
|
||||
|
||||
// put the exe name between the environment and the command line.
|
||||
strcpy(ptr, argv[0]);
|
||||
ptr += strlen(argv[0]) + 1;
|
||||
@@ -1758,6 +1778,23 @@ static LxModule *loadLxModuleByModuleName(const char *modname)
|
||||
return loadLxModuleByModuleNameInternal(modname, 0);
|
||||
} // loadLxModuleByModuleName
|
||||
|
||||
static LxModule *loadLxModuleByPathOrModuleName(const char *modname)
|
||||
{
|
||||
LxModule *retval = NULL;
|
||||
// !!! FIXME: can a module name be specified as "NAME.DLL" and not be considered a filename?
|
||||
if (strrchr(modname, '.') == NULL) {
|
||||
retval = loadLxModuleByModuleName(modname);
|
||||
} else {
|
||||
uint32 err = 0;
|
||||
char *path = makeUnixPath(modname, &err);
|
||||
if (!path)
|
||||
return NULL;
|
||||
retval = loadLxModuleByPath(path);
|
||||
free(path);
|
||||
} // else
|
||||
return retval;
|
||||
} // loadLxModuleByPathOrModuleName
|
||||
|
||||
static __attribute__((noreturn)) void handleThreadLocalStorageAccess(const int slot, ucontext_t *uctx)
|
||||
{
|
||||
greg_t *gregs = uctx->uc_mcontext.gregs;
|
||||
@@ -1775,7 +1812,7 @@ static __attribute__((noreturn)) void handleThreadLocalStorageAccess(const int s
|
||||
uint32 *tls = (uint32 *) (ptib2 + 1); // The thread's TLS data is stored right after its TIB2 struct.
|
||||
tls += slot;
|
||||
|
||||
printf("We wanted to access thread %p TLS slot %d (currently holds %u)\n", tls - slot, slot, (uint) *tls);
|
||||
//printf("We wanted to access thread %p TLS slot %d (currently holds %u)\n", tls - slot, slot, (uint) *tls);
|
||||
|
||||
static const int x86RegisterToUContextEnum[] = {
|
||||
REG_EAX, REG_ECX, REG_EDX, REG_EBX, REG_ESP, REG_EBP, REG_ESI, REG_EDI
|
||||
@@ -1786,19 +1823,19 @@ static __attribute__((noreturn)) void handleThreadLocalStorageAccess(const int s
|
||||
uint8 *eip = (void *) (size_t) gregs[REG_EIP]; // program counter at point of segfault.
|
||||
switch (eip[0]) {
|
||||
case 0xC7: // mov imm16/32 -> r/m
|
||||
printf("setting TLS slot %d to imm %u.\n", slot, (uint) *((uint32 *) (eip + 2)));
|
||||
//printf("setting TLS slot %d to imm %u.\n", slot, (uint) *((uint32 *) (eip + 2)));
|
||||
*tls = *((uint32 *) (eip + 2)); // !!! FIXME: verify it's a imm32, not 16
|
||||
gregs[REG_EIP] += 6;
|
||||
break;
|
||||
|
||||
case 0x89: // mov r -> r/m
|
||||
printf("setting TLS slot %d to reg %d (%u).\n", slot, x86RegisterToUContextEnum[eip[1] >> 3], (uint) gregs[x86RegisterToUContextEnum[eip[1] >> 3]]);
|
||||
//printf("setting TLS slot %d to reg %d (%u).\n", slot, x86RegisterToUContextEnum[eip[1] >> 3], (uint) gregs[x86RegisterToUContextEnum[eip[1] >> 3]]);
|
||||
*tls = (uint32) gregs[x86RegisterToUContextEnum[eip[1] >> 3]];
|
||||
gregs[REG_EIP] += 2;
|
||||
break;
|
||||
|
||||
case 0x8B: // mov r/m -> r
|
||||
printf("setting to reg %d to TLS slot %d (%u).\n", (uint) x86RegisterToUContextEnum[eip[1] >> 3], slot, *tls);
|
||||
//printf("setting reg %d to TLS slot %d (%u).\n", (uint) x86RegisterToUContextEnum[eip[1] >> 3], slot, *tls);
|
||||
gregs[x86RegisterToUContextEnum[eip[1] >> 3]] = (greg_t) *tls;
|
||||
gregs[REG_EIP] += 2;
|
||||
break;
|
||||
@@ -1813,7 +1850,7 @@ static __attribute__((noreturn)) void handleThreadLocalStorageAccess(const int s
|
||||
} else {
|
||||
// drop out of signal handler to (hopefully) next instruction in the app,
|
||||
// as if it accessed the TLS slot normally and none of this ever happened.
|
||||
printf("TLS access handler jumping back into app at %p...\n", (void *) gregs[REG_EIP]); fflush(stdout);
|
||||
//printf("TLS access handler jumping back into app at %p...\n", (void *) gregs[REG_EIP]); fflush(stdout);
|
||||
setcontext(uctx);
|
||||
fprintf(stderr, "panic: setcontext() failed in the TLS access handler! Aborting! (%s)\n", strerror(errno));
|
||||
} // else
|
||||
@@ -1841,6 +1878,7 @@ static void segfault_catcher(int sig, siginfo_t *info, void *ctx)
|
||||
// !!! FIXME: case #1 should be a much more detailed crash dump.
|
||||
case 1: fprintf(stderr, "SIGSEGV at addr=%p (eip=%p)\n", addr, (void *) ((ucontext_t *) ctx)->uc_mcontext.gregs[REG_EIP]); break;
|
||||
case 2: write(2, "SIGSEGV, aborting.\n", 19); break;
|
||||
default: break;
|
||||
} // switch
|
||||
|
||||
abort(); // cash out.
|
||||
@@ -1855,7 +1893,7 @@ static int installSignalHandlers(void)
|
||||
action.sa_flags = SA_NODEFER | SA_SIGINFO;
|
||||
|
||||
if (sigaction(SIGSEGV, &action, NULL) == -1) {
|
||||
fprintf(stderr, "Couldn't install signal handler! (%s)\n", strerror(errno));
|
||||
fprintf(stderr, "Couldn't install SIGSEGV handler! (%s)\n", strerror(errno));
|
||||
return 0;
|
||||
} // if
|
||||
|
||||
@@ -1890,7 +1928,7 @@ int main(int argc, char **argv, char **envp)
|
||||
GLoaderState->findSelector = findSelector;
|
||||
GLoaderState->freeSelector = freeSelector;
|
||||
GLoaderState->convert1616to32 = convert1616to32;
|
||||
GLoaderState->loadModule = loadLxModuleByModuleName;
|
||||
GLoaderState->loadModule = loadLxModuleByPathOrModuleName;
|
||||
GLoaderState->locatePathCaseInsensitive = locatePathCaseInsensitive;
|
||||
GLoaderState->makeUnixPath = makeUnixPath;
|
||||
GLoaderState->makeOS2Path = makeOS2Path;
|
||||
|
||||
@@ -215,6 +215,8 @@ typedef struct LxLoaderState
|
||||
uint16 original_ss;
|
||||
uint16 original_ds;
|
||||
uint32 ldt[8192];
|
||||
char *libpath;
|
||||
uint32 libpathlen;
|
||||
uint32 *tlspage;
|
||||
uint32 tlsmask; // one bit for each TLS slot in use.
|
||||
uint8 tlsallocs[32]; // number of TLS slots allocated in one block, indexed by starting block (zero if not the starting block).
|
||||
|
||||
+164
-16
@@ -14,7 +14,28 @@
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
static LxLoaderState *GLoaderState = NULL;
|
||||
// DosQueryHeaderInfo() is an undocumented OS/2 API that is exported from DOSCALLS. Java uses it.
|
||||
// This isn't mentioned in the docs or the SDK (beyond the ordinal being listed). I got the basic details
|
||||
// from Odin32, which lists it in their os2newapi.h header.
|
||||
enum
|
||||
{
|
||||
QHINF_EXEINFO = 1,
|
||||
QHINF_READRSRCTBL,
|
||||
QHINF_READFILE,
|
||||
QHINF_LIBPATHLENGTH,
|
||||
QHINF_LIBPATH,
|
||||
QHINF_FIXENTRY,
|
||||
QHINF_STE,
|
||||
QHINF_MAPSEL
|
||||
};
|
||||
APIRET OS2API DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction);
|
||||
|
||||
// This is also undocumented (thanks, EDM/2!). Of course, Java uses it.
|
||||
APIRET OS2API DosQuerySysState(ULONG func, ULONG arg1, ULONG pid, ULONG _res_, PVOID buf, ULONG bufsz);
|
||||
|
||||
// This is also undocumented (no idea about this at all, including function params). Of course, Java uses it.
|
||||
APIRET DosR3ExitAddr(void);
|
||||
|
||||
|
||||
static pthread_mutex_t GMutexDosCalls;
|
||||
|
||||
@@ -54,9 +75,10 @@ enum {
|
||||
|
||||
typedef struct HFileInfo
|
||||
{
|
||||
int fd;
|
||||
ULONG type;
|
||||
ULONG attr;
|
||||
int fd; // unix file descriptor.
|
||||
ULONG type; // file, pipe, device, etc.
|
||||
ULONG attr; // for character devices, DAW_*
|
||||
ULONG flags; // OPEN_FLAGS_*
|
||||
} HFileInfo;
|
||||
|
||||
static HFileInfo *HFiles = NULL;
|
||||
@@ -95,11 +117,6 @@ typedef struct
|
||||
static DirFinder GHDir1;
|
||||
|
||||
|
||||
// !!! FIXME:
|
||||
#undef TRACE_NATIVE
|
||||
#define TRACE_NATIVE(...) do { if (GLoaderState->trace_native) { fprintf(stderr, "2INE TRACE [%lu]: ", (unsigned long) pthread_self()); fprintf(stderr, __VA_ARGS__); fprintf(stderr, ";\n"); } } while (0)
|
||||
|
||||
|
||||
LX_NATIVE_MODULE_DEINIT({
|
||||
ExitListItem *next = GExitList;
|
||||
GExitList = NULL;
|
||||
@@ -118,14 +135,10 @@ LX_NATIVE_MODULE_DEINIT({
|
||||
MaxHFiles = 0;
|
||||
|
||||
pthread_mutex_destroy(&GMutexDosCalls);
|
||||
|
||||
GLoaderState = NULL;
|
||||
})
|
||||
|
||||
static int initDoscalls(LxLoaderState *lx_state)
|
||||
static int initDoscalls(void)
|
||||
{
|
||||
GLoaderState = lx_state;
|
||||
|
||||
if (pthread_mutex_init(&GMutexDosCalls, NULL) == -1) {
|
||||
fprintf(stderr, "pthread_mutex_init failed!\n");
|
||||
return 0;
|
||||
@@ -143,6 +156,7 @@ static int initDoscalls(LxLoaderState *lx_state)
|
||||
info->fd = -1;
|
||||
info->type = 0;
|
||||
info->attr = 0;
|
||||
info->flags = 0;
|
||||
} // for
|
||||
|
||||
// launching a Hello World program from CMD.EXE seems to inherit several
|
||||
@@ -164,7 +178,8 @@ static int initDoscalls(LxLoaderState *lx_state)
|
||||
return 1;
|
||||
} // initDoscalls
|
||||
|
||||
LX_NATIVE_MODULE_INIT({ if (!initDoscalls(lx_state)) return NULL; })
|
||||
LX_NATIVE_MODULE_INIT({ if (!initDoscalls()) return NULL; })
|
||||
LX_NATIVE_EXPORT(DosSetMaxFH, 209),
|
||||
LX_NATIVE_EXPORT(DosSetPathInfo, 219),
|
||||
LX_NATIVE_EXPORT(DosQueryPathInfo, 223),
|
||||
LX_NATIVE_EXPORT(DosQueryHType, 224),
|
||||
@@ -183,6 +198,7 @@ LX_NATIVE_MODULE_INIT({ if (!initDoscalls(lx_state)) return NULL; })
|
||||
LX_NATIVE_EXPORT(DosOpen, 273),
|
||||
LX_NATIVE_EXPORT(DosQueryCurrentDir, 274),
|
||||
LX_NATIVE_EXPORT(DosQueryCurrentDisk, 275),
|
||||
LX_NATIVE_EXPORT(DosQueryFHState, 276),
|
||||
LX_NATIVE_EXPORT(DosQueryFileInfo, 279),
|
||||
LX_NATIVE_EXPORT(DosWaitChild, 280),
|
||||
LX_NATIVE_EXPORT(DosRead, 281),
|
||||
@@ -214,6 +230,7 @@ LX_NATIVE_MODULE_INIT({ if (!initDoscalls(lx_state)) return NULL; })
|
||||
LX_NATIVE_EXPORT(DosSubFreeMem, 346),
|
||||
LX_NATIVE_EXPORT(DosQuerySysInfo, 348),
|
||||
LX_NATIVE_EXPORT(DosSetExceptionHandler, 354),
|
||||
LX_NATIVE_EXPORT(DosQuerySysState, 368),
|
||||
LX_NATIVE_EXPORT(DosSetSignalExceptionFocus, 378),
|
||||
LX_NATIVE_EXPORT(DosEnterMustComplete, 380),
|
||||
LX_NATIVE_EXPORT(DosExitMustComplete, 381),
|
||||
@@ -221,6 +238,10 @@ LX_NATIVE_MODULE_INIT({ if (!initDoscalls(lx_state)) return NULL; })
|
||||
LX_NATIVE_EXPORT(DosFlatToSel, 425),
|
||||
LX_NATIVE_EXPORT(DosAllocThreadLocalMemory, 454),
|
||||
LX_NATIVE_EXPORT(DosFreeThreadLocalMemory, 455),
|
||||
LX_NATIVE_EXPORT(DosR3ExitAddr, 553),
|
||||
LX_NATIVE_EXPORT(DosQueryHeaderInfo, 582),
|
||||
LX_NATIVE_EXPORT(DosQueryExtLIBPATH, 874),
|
||||
LX_NATIVE_EXPORT(DosQueryThreadContext, 877),
|
||||
LX_NATIVE_EXPORT(DosOpenL, 981)
|
||||
LX_NATIVE_MODULE_INIT_END()
|
||||
|
||||
@@ -364,7 +385,7 @@ APIRET DosQueryModuleName(HMODULE hmod, ULONG buflen, PCHAR buf)
|
||||
|
||||
const LxModule *lxmod = (LxModule *) hmod;
|
||||
// !!! FIXME: error 6 ERROR_INVALID_HANDLE
|
||||
if (strlen(lxmod->os2path) <= buflen)
|
||||
if (strlen(lxmod->os2path) >= buflen)
|
||||
return ERROR_BAD_LENGTH;
|
||||
strcpy(buf, lxmod->os2path);
|
||||
return NO_ERROR;
|
||||
@@ -683,6 +704,7 @@ APIRET DosSetRelMaxFH(PLONG pincr, PULONG pcurrent)
|
||||
info->fd = -1;
|
||||
info->type = 0;
|
||||
info->attr = 0;
|
||||
info->flags = 0;
|
||||
} // for
|
||||
MaxHFiles += incr;
|
||||
} // if
|
||||
@@ -955,6 +977,8 @@ static APIRET doDosOpen(PSZ pszFileName, PHFILE pHf, PULONG pulAction, LONGLONG
|
||||
__builtin_unreachable();
|
||||
} // if
|
||||
|
||||
info->flags = fsOpenFlags;
|
||||
|
||||
if (isReplacing)
|
||||
*pulAction = FILE_TRUNCATED;
|
||||
else if (existed)
|
||||
@@ -1244,6 +1268,12 @@ static APIRET queryPathInfo(PSZ unixPath, ULONG ulInfoLevel, PVOID pInfoBuf, ULO
|
||||
case FIL_STANDARD: return queryPathInfoStandard(unixPath, pInfoBuf, cbInfoBuf);
|
||||
case FIL_QUERYEASIZE: return queryPathInfoEaSize(unixPath, pInfoBuf, cbInfoBuf);
|
||||
case FIL_QUERYEASFROMLIST: return queryPathInfoEasFromList(unixPath, pInfoBuf, cbInfoBuf);
|
||||
|
||||
// OS/2 has an undocumented info level, 7, that appears to return a case-corrected version
|
||||
// of the path. (FIL_QUERYFULLNAME doesn't correct the case of what the app queries on
|
||||
// OS/2). Since we have to case-correct for a Unix filesystem anyhow, we just use the
|
||||
// usual FIL_QUERYFULLNAME to handle the undocumented level. Java uses this level.
|
||||
case 7:
|
||||
case FIL_QUERYFULLNAME: return queryPathInfoFullName(unixPath, pInfoBuf, cbInfoBuf);
|
||||
default: break;
|
||||
} // switch
|
||||
@@ -2707,5 +2737,123 @@ APIRET DosFreeThreadLocalMemory(ULONG *p)
|
||||
return retval;
|
||||
} // DosFreeThreadLocalMemory
|
||||
|
||||
APIRET DosQueryFHState(HFILE hFile, PULONG pMode)
|
||||
{
|
||||
TRACE_NATIVE("DosQueryFHState(%u, %p)", (uint) hFile, pMode);
|
||||
|
||||
APIRET retval = NO_ERROR;
|
||||
ULONG tmp = 0;
|
||||
if (!pMode)
|
||||
pMode = &tmp;
|
||||
|
||||
grabLock(&GMutexDosCalls);
|
||||
if ((hFile < MaxHFiles) && (HFiles[hFile].fd != -1))
|
||||
*pMode = HFiles[hFile].flags;
|
||||
else
|
||||
retval = ERROR_INVALID_HANDLE;
|
||||
ungrabLock(&GMutexDosCalls);
|
||||
|
||||
return retval;
|
||||
} // DosQueryFHState
|
||||
|
||||
APIRET DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction)
|
||||
{
|
||||
TRACE_NATIVE("DosQueryHeaderInfo(%u, %u, %p, %u, %u)", (uint) hmod, (uint) ulIndex, pvBuffer, (uint) cbBuffer, (uint) ulSubFunction);
|
||||
|
||||
switch (ulSubFunction) {
|
||||
//case QHINF_EXEINFO:
|
||||
//case QHINF_READRSRCTBL:
|
||||
//case QHINF_READFILE:
|
||||
|
||||
case QHINF_LIBPATHLENGTH:
|
||||
if (cbBuffer < sizeof (ULONG))
|
||||
return ERROR_BUFFER_OVERFLOW;
|
||||
*((ULONG *) pvBuffer) = GLoaderState->libpathlen;
|
||||
return NO_ERROR;
|
||||
|
||||
case QHINF_LIBPATH:
|
||||
if (cbBuffer < GLoaderState->libpathlen)
|
||||
return ERROR_BUFFER_OVERFLOW;
|
||||
strcpy((char *) pvBuffer, GLoaderState->libpath);
|
||||
return NO_ERROR;
|
||||
|
||||
//case QHINF_FIXENTRY:
|
||||
//case QHINF_STE:
|
||||
//case QHINF_MAPSEL:
|
||||
|
||||
default: FIXME("I don't know what this query wants"); break;
|
||||
} // switch
|
||||
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
} // DosQueryHeaderInfo
|
||||
|
||||
APIRET OS2API DosQueryExtLIBPATH(PSZ pszExtLIBPATH, ULONG flags)
|
||||
{
|
||||
TRACE_NATIVE("DosQueryExtLIBPATH('%s', %u)", pszExtLIBPATH, (uint) flags);
|
||||
|
||||
// !!! FIXME: this is mostly a stub for now.
|
||||
|
||||
if ((flags != BEGIN_LIBPATH) && (flags != END_LIBPATH))
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if (pszExtLIBPATH)
|
||||
*pszExtLIBPATH = '\0';
|
||||
|
||||
return NO_ERROR;
|
||||
} // DosQueryExtLIBPATH
|
||||
|
||||
APIRET DosSetMaxFH(ULONG cFH)
|
||||
{
|
||||
grabLock(&GMutexDosCalls);
|
||||
|
||||
if (cFH < MaxHFiles) {
|
||||
ungrabLock(&GMutexDosCalls);
|
||||
return ERROR_INVALID_PARAMETER; // strictly speaking, we could shrink, but I'm not doing it.
|
||||
} // if
|
||||
|
||||
if (cFH == MaxHFiles) {
|
||||
ungrabLock(&GMutexDosCalls);
|
||||
return NO_ERROR;
|
||||
} // if
|
||||
|
||||
HFileInfo *info = (HFileInfo *) realloc(HFiles, sizeof (HFileInfo) * (cFH));
|
||||
if (info != NULL) {
|
||||
HFiles = info;
|
||||
info += MaxHFiles;
|
||||
for (ULONG i = MaxHFiles; i < cFH; i++, info++) {
|
||||
info->fd = -1;
|
||||
info->type = 0;
|
||||
info->attr = 0;
|
||||
info->flags = 0;
|
||||
} // for
|
||||
MaxHFiles = cFH;
|
||||
} // if
|
||||
|
||||
ungrabLock(&GMutexDosCalls);
|
||||
|
||||
return NO_ERROR;
|
||||
} // DosSetMaxFH
|
||||
|
||||
APIRET DosQuerySysState(ULONG func, ULONG arg1, ULONG pid, ULONG _res_, PVOID buf, ULONG bufsz)
|
||||
{
|
||||
TRACE_NATIVE("DosQuerySysState(%u, %u, %u, %u, %p, %u)", (uint) func, (uint) arg1, (uint) pid, (uint) _res_, buf, (uint) bufsz);
|
||||
FIXME("implement me");
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
} // DosQuerySysState
|
||||
|
||||
APIRET DosR3ExitAddr(void)
|
||||
{
|
||||
TRACE_NATIVE("DosR3ExitAddr()");
|
||||
FIXME("I have no idea what this is"); // but...JAVA USES IT.
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
} // DosR3ExitAddr
|
||||
|
||||
APIRET DosQueryThreadContext(TID tid, ULONG level, PCONTEXTRECORD pcxt)
|
||||
{
|
||||
TRACE_NATIVE("DosQueryThreadContext(%u, %u, %p)", (uint) tid, (uint) level, pcxt);
|
||||
FIXME("Need to be able to suspend threads first");
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
} // DosQueryThreadContext
|
||||
|
||||
// end of doscalls.c ...
|
||||
|
||||
@@ -371,6 +371,13 @@ enum
|
||||
FAPPTYP_32BIT = 0x4000
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BEGIN_LIBPATH = 1,
|
||||
END_LIBPATH = 2
|
||||
};
|
||||
|
||||
typedef void *PCONTEXTRECORD; // !!! FIXME
|
||||
|
||||
// !!! FIXME: these should probably get sorted alphabetically and/or grouped
|
||||
// !!! FIXME: into areas of functionality, but for now, I'm just listing them
|
||||
@@ -434,6 +441,10 @@ APIRET OS2API DosResetBuffer(HFILE hFile);
|
||||
APIRET OS2API DosQueryAppType(PSZ pszName, PULONG pFlags);
|
||||
APIRET OS2API DosAllocThreadLocalMemory(ULONG cb, PULONG *p);
|
||||
APIRET OS2API DosFreeThreadLocalMemory(ULONG *p);
|
||||
APIRET OS2API DosQueryFHState(HFILE hFile, PULONG pMode);
|
||||
APIRET OS2API DosQueryExtLIBPATH(PSZ pszExtLIBPATH, ULONG flags);
|
||||
APIRET OS2API DosSetMaxFH(ULONG cFH);
|
||||
APIRET OS2API DosQueryThreadContext(TID tid, ULONG level, PCONTEXTRECORD pcxt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+10
-3
@@ -16,8 +16,11 @@
|
||||
#include "os2errors.h"
|
||||
#include "../lx_loader.h"
|
||||
|
||||
#if 0
|
||||
#define TRACE_NATIVE(...) do { fprintf(stderr, "2INE TRACE [%lu]: ", (unsigned long) pthread_self()); fprintf(stderr, __VA_ARGS__); fprintf(stderr, ";\n"); } while (0)
|
||||
// note that this is defined in _every_ module that includes this file!
|
||||
static LxLoaderState *GLoaderState = NULL;
|
||||
|
||||
#if 1
|
||||
#define TRACE_NATIVE(...) do { if (GLoaderState->trace_native) { fprintf(stderr, "2INE TRACE [%lu]: ", (unsigned long) pthread_self()); fprintf(stderr, __VA_ARGS__); fprintf(stderr, ";\n"); } } while (0)
|
||||
#else
|
||||
#define TRACE_NATIVE(...) do {} while (0)
|
||||
#endif
|
||||
@@ -26,10 +29,14 @@ OS2EXPORT const LxExport * lxNativeModuleInit(LxLoaderState *lx_state, uint32 *l
|
||||
void OS2EXPORT lxNativeModuleDeinit(void);
|
||||
|
||||
#define LX_NATIVE_MODULE_DEINIT(deinitcode) \
|
||||
void lxNativeModuleDeinit(void) { deinitcode; }
|
||||
void lxNativeModuleDeinit(void) { \
|
||||
deinitcode; \
|
||||
GLoaderState = NULL; \
|
||||
}
|
||||
|
||||
#define LX_NATIVE_MODULE_INIT(initcode) \
|
||||
const LxExport *lxNativeModuleInit(LxLoaderState *lx_state, uint32 *lx_num_exports) { \
|
||||
GLoaderState = lx_state; \
|
||||
initcode; \
|
||||
static const LxExport lx_native_exports[] = {
|
||||
|
||||
|
||||
+4
-10
@@ -6,7 +6,6 @@
|
||||
// !!! FIXME: _lots_ of macro salsa in here.
|
||||
|
||||
#define LX_NATIVE_MODULE_16BIT_SUPPORT() \
|
||||
static LxLoaderState *GLoaderState = NULL; \
|
||||
static LxMmaps obj16;
|
||||
|
||||
// These are the 16-bit entry points, which are exported to the LX loader
|
||||
@@ -26,11 +25,8 @@
|
||||
obj16.mapped = obj16.addr = NULL; \
|
||||
obj16.size = 0; \
|
||||
obj16.alias = 0xFFFF; \
|
||||
GLoaderState = NULL;
|
||||
|
||||
#define LX_NATIVE_MODULE_INIT_16BIT_SUPPORT() \
|
||||
GLoaderState = lx_state; \
|
||||
\
|
||||
obj16.mapped = obj16.addr = NULL; \
|
||||
obj16.size = 0; \
|
||||
obj16.alias = 0xFFFF; \
|
||||
@@ -39,7 +35,6 @@
|
||||
void *mmapaddr = mmap(NULL, vsize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); \
|
||||
if (mmapaddr == ((void *) MAP_FAILED)) { \
|
||||
fprintf(stderr, "mmap(NULL, 0x20000, RW-, ANON|PRIVATE, -1, 0) failed (%d): %s\n", errno, strerror(errno)); \
|
||||
GLoaderState = NULL; \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
@@ -62,7 +57,6 @@
|
||||
obj16.mapped = obj16.addr = NULL; \
|
||||
obj16.size = 0; \
|
||||
obj16.alias = 0xFFFF; \
|
||||
GLoaderState = NULL; \
|
||||
return 0; \
|
||||
} \
|
||||
assert(offset == 0); \
|
||||
@@ -115,7 +109,7 @@ MOV SP, BX
|
||||
RETF 0x22 ; ...and back to the (far) caller, clearing the args (Pascal calling convention!) with retval in AX.
|
||||
*/
|
||||
|
||||
#define LX_NATIVE_INIT_16BIT_BRIDGE(fn, argbytes) \
|
||||
#define LX_NATIVE_INIT_16BIT_BRIDGE(fn, argbytes) { \
|
||||
fn##16 = ptr; \
|
||||
\
|
||||
/* instructions are in Intel syntax here, not AT&T. */ \
|
||||
@@ -192,9 +186,9 @@ RETF 0x22 ; ...and back to the (far) caller, clearing the args (Pascal calling
|
||||
*(ptr++) = 0xCA; /* retf 0x22... */ \
|
||||
const uint16 argbytecount = argbytes; \
|
||||
memcpy(ptr, &argbytecount, 2); ptr += 2; \
|
||||
}
|
||||
|
||||
|
||||
#define LX_NATIVE_MODULE_INIT_16BIT_SUPPORT_END() \
|
||||
#define LX_NATIVE_MODULE_INIT_16BIT_SUPPORT_END() { \
|
||||
assert((((uint32)ptr) - ((uint32)mmapaddr)) < 0x10000); /* don't be more than 64k. */ \
|
||||
if (mprotect(obj16.mapped, vsize, PROT_READ | PROT_EXEC) == -1) { \
|
||||
fprintf(stderr, "mprotect() failed for 16-bit bridge code!\n"); \
|
||||
@@ -203,9 +197,9 @@ RETF 0x22 ; ...and back to the (far) caller, clearing the args (Pascal calling
|
||||
obj16.mapped = obj16.addr = NULL; \
|
||||
obj16.size = 0; \
|
||||
obj16.alias = 0xFFFF; \
|
||||
GLoaderState = NULL; \
|
||||
return 0; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define LX_NATIVE_EXPORT16(fn, ord) { ord, #fn, &fn##16, &obj16 }
|
||||
|
||||
|
||||
+66
-16
@@ -1,23 +1,35 @@
|
||||
#include "os2native16.h"
|
||||
#include "viocalls.h"
|
||||
|
||||
LX_NATIVE_MODULE_16BIT_SUPPORT()
|
||||
LX_NATIVE_MODULE_16BIT_API(VioGetMode)
|
||||
LX_NATIVE_MODULE_16BIT_SUPPORT_END()
|
||||
|
||||
// !!! FIXME:
|
||||
#undef TRACE_NATIVE
|
||||
#define TRACE_NATIVE(...) do { if (GLoaderState->trace_native) { fprintf(stderr, "2INE TRACE [%lu]: ", (unsigned long) pthread_self()); fprintf(stderr, __VA_ARGS__); fprintf(stderr, ";\n"); } } while (0)
|
||||
|
||||
LX_NATIVE_MODULE_DEINIT({
|
||||
LX_NATIVE_MODULE_DEINIT_16BIT_SUPPORT();
|
||||
})
|
||||
|
||||
APIRET16 VioGetMode(PVIOMODEINFO pvioModeInfo, HVIO hvio)
|
||||
{
|
||||
TRACE_NATIVE("VioGetMode(%p, %u)", pvioModeInfo, (uint) hvio);
|
||||
FIXME("write me");
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
if (hvio != 0)
|
||||
return ERROR_VIO_INVALID_HANDLE; // !!! FIXME: can be non-zero when VioCreatePS() is implemented.
|
||||
else if (pvioModeInfo == NULL)
|
||||
return ERROR_VIO_INVALID_PARMS;
|
||||
else if (pvioModeInfo->cb != sizeof (*pvioModeInfo))
|
||||
return ERROR_VIO_INVALID_LENGTH;
|
||||
|
||||
memset(pvioModeInfo, '\0', sizeof (*pvioModeInfo));
|
||||
pvioModeInfo->cb = sizeof (*pvioModeInfo);
|
||||
pvioModeInfo->fbType = VGMT_OTHER;
|
||||
pvioModeInfo->color = 8; // bits?
|
||||
pvioModeInfo->col = 80;
|
||||
pvioModeInfo->row = 25;
|
||||
FIXME("I don't know what most of these fields do");
|
||||
//pvioModeInfo->hres = 640;
|
||||
//pvioModeInfo->vres = 480;
|
||||
//UCHAR fmt_ID;
|
||||
//UCHAR attrib;
|
||||
//ULONG buf_addr;
|
||||
//ULONG buf_length;
|
||||
//ULONG full_length;
|
||||
//ULONG partial_length;
|
||||
//PCHAR ext_data_addr;
|
||||
|
||||
return NO_ERROR;
|
||||
} // VioGetMode
|
||||
|
||||
static APIRET16 bridge16to32_VioGetMode(uint8 *args)
|
||||
@@ -27,15 +39,53 @@ static APIRET16 bridge16to32_VioGetMode(uint8 *args)
|
||||
return VioGetMode(pvmi, hvio);
|
||||
} // bridge16to32_VioGetMode
|
||||
|
||||
static int initViocalls(LxLoaderState *lx_state)
|
||||
|
||||
APIRET16 VioGetCurPos(PUSHORT pusRow, PUSHORT pusColumn, HVIO hvio)
|
||||
{
|
||||
TRACE_NATIVE("VioGetCurPos(%p, %p, %u)", pusRow, pusColumn, (uint) hvio);
|
||||
|
||||
if (hvio != 0)
|
||||
return ERROR_VIO_INVALID_HANDLE; // !!! FIXME: can be non-zero when VioCreatePS() is implemented.
|
||||
|
||||
FIXME("write me");
|
||||
if (pusRow)
|
||||
*pusRow = 0;
|
||||
if (pusColumn)
|
||||
*pusColumn = 0;
|
||||
|
||||
return NO_ERROR;
|
||||
} // VioGetCurPos
|
||||
|
||||
static APIRET16 bridge16to32_VioGetCurPos(uint8 *args)
|
||||
{
|
||||
const HVIO hvio = *((HVIO *) args); args += 2;
|
||||
PUSHORT pusRow = GLoaderState->convert1616to32(*((uint32*) args)); args += 4;
|
||||
PUSHORT pusColumn = GLoaderState->convert1616to32(*((uint32*) args)); args += 4;
|
||||
return VioGetCurPos(pusRow, pusColumn, hvio);
|
||||
} // bridge16to32_VioGetCurPos
|
||||
|
||||
|
||||
|
||||
LX_NATIVE_MODULE_16BIT_SUPPORT()
|
||||
LX_NATIVE_MODULE_16BIT_API(VioGetCurPos)
|
||||
LX_NATIVE_MODULE_16BIT_API(VioGetMode)
|
||||
LX_NATIVE_MODULE_16BIT_SUPPORT_END()
|
||||
|
||||
LX_NATIVE_MODULE_DEINIT({
|
||||
LX_NATIVE_MODULE_DEINIT_16BIT_SUPPORT();
|
||||
})
|
||||
|
||||
static int initViocalls(void)
|
||||
{
|
||||
LX_NATIVE_MODULE_INIT_16BIT_SUPPORT()
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(VioGetCurPos, 6)
|
||||
LX_NATIVE_INIT_16BIT_BRIDGE(VioGetMode, 6)
|
||||
LX_NATIVE_MODULE_INIT_16BIT_SUPPORT_END()
|
||||
return 1;
|
||||
} // initViocalls
|
||||
|
||||
LX_NATIVE_MODULE_INIT({ if (!initViocalls(lx_state)) return NULL; })
|
||||
LX_NATIVE_MODULE_INIT({ if (!initViocalls()) return NULL; })
|
||||
LX_NATIVE_EXPORT16(VioGetCurPos, 9),
|
||||
LX_NATIVE_EXPORT16(VioGetMode, 21)
|
||||
LX_NATIVE_MODULE_INIT_END()
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ enum
|
||||
};
|
||||
|
||||
APIRET16 OS2API16 VioGetMode(PVIOMODEINFO pvioModeInfo, HVIO hvio);
|
||||
APIRET16 OS2API16 VioGetCurPos(PUSHORT pusRow, PUSHORT pusColumn, HVIO hvio);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user