X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=os2%2Fdl_os2.c;h=76fa9dc42d9ceff37ef98aaa0f5cefefc9563eaa;hb=a4d60858fc3c717ec83cbdceb029a69fc535e3f8;hp=aaeeb580f4b713b4cf06a30468e7404ed0db7fa1;hpb=9fed8b87f0e66c26a1acaf42431d99e8f98aed9b;p=p5sagit%2Fp5-mst-13.2.git diff --git a/os2/dl_os2.c b/os2/dl_os2.c index aaeeb58..76fa9dc 100644 --- a/os2/dl_os2.c +++ b/os2/dl_os2.c @@ -4,25 +4,120 @@ #define INCL_BASE #include +#include +#include static ULONG retcode; static char fail[300]; +static ULONG dllHandle; +static int handle_found; +static int handle_loaded; +#ifdef PERL_CORE + +#include "EXTERN.h" +#include "perl.h" + +#else + char *os2error(int rc); +#endif + +#ifdef DLOPEN_INITTERM +unsigned long _DLL_InitTerm(unsigned long modHandle, unsigned long flag) +{ + switch (flag) { + case 0: /* INIT */ + /* Save handle */ + dllHandle = modHandle; + handle_found = 1; + return TRUE; + + case 1: /* TERM */ + handle_found = 0; + dllHandle = (unsigned long)NULLHANDLE; + return TRUE; + } + + return FALSE; +} + +#endif + +HMODULE +find_myself(void) +{ + + static APIRET APIENTRY (*pDosQueryModFromEIP) (HMODULE * hmod, ULONG * obj, ULONG BufLen, PCHAR Buf, + ULONG * Offset, ULONG Address); + HMODULE doscalls_h, mod; + static int failed; + ULONG obj, offset, rc; + char buf[260]; + + if (failed) + return 0; + failed = 1; + doscalls_h = (HMODULE)dlopen("DOSCALLS",0); + if (!doscalls_h) + return 0; +/* {&doscalls_handle, NULL, 360}, */ /* DosQueryModFromEIP */ + rc = DosQueryProcAddr(doscalls_h, 360, 0, (PFN*)&pDosQueryModFromEIP); + if (rc) + return 0; + rc = pDosQueryModFromEIP(&mod, &obj, sizeof(buf), buf, &offset, (ULONG)dlopen); + if (rc) + return 0; + failed = 0; + handle_found = 1; + dllHandle = mod; + return mod; +} + void * -dlopen(char *path, int mode) +dlopen(const char *path, int mode) { HMODULE handle; - char tmp[260], *beg, *dot; + char tmp[260]; + const char *beg, *dot; ULONG rc; + unsigned fpflag = _control87(0,0); fail[0] = 0; - if ((rc = DosLoadModule(fail, sizeof fail, path, &handle)) == 0) - return (void *)handle; + if (!path) { /* Our own handle. */ + if (handle_found || find_myself()) { + char dllname[260]; + + if (handle_loaded) + return (void*)dllHandle; + rc = DosQueryModuleName(dllHandle, sizeof(dllname), dllname); + if (rc) { + strcpy(fail, "can't find my DLL name by the handle"); + retcode = rc; + return 0; + } + rc = DosLoadModule(fail, sizeof fail, dllname, &handle); + if (rc) { + strcpy(fail, "can't load my own DLL"); + retcode = rc; + return 0; + } + handle_loaded = 1; + goto ret; + } + retcode = ERROR_MOD_NOT_FOUND; + strcpy(fail, "can't load from myself: compiled without -DDLOPEN_INITTERM"); + return 0; + } + if ((rc = DosLoadModule(fail, sizeof fail, (char*)path, &handle)) == 0) + goto ret; retcode = rc; + if (strlen(path) >= sizeof(tmp)) + return NULL; + /* Not found. Check for non-FAT name and try truncated name. */ /* Don't know if this helps though... */ for (beg = dot = path + strlen(path); @@ -32,17 +127,23 @@ dlopen(char *path, int mode) dot = beg; if (dot - beg > 8) { int n = beg+8-path; + memmove(tmp, path, n); memmove(tmp+n, dot, strlen(dot)+1); if (DosLoadModule(fail, sizeof fail, tmp, &handle) == 0) - return (void *)handle; + goto ret; } + handle = 0; - return NULL; + ret: + _control87(fpflag, MCW_EM); /* Some modules reset FP flags on load */ + return (void *)handle; } +#define ERROR_WRONG_PROCTYPE 0xffffffff + void * -dlsym(void *handle, char *symbol) +dlsym(void *handle, const char *symbol) { ULONG rc, type; PFN addr; @@ -53,7 +154,7 @@ dlsym(void *handle, char *symbol) rc = DosQueryProcType((HMODULE)handle, 0, symbol, &type); if (rc == 0 && type == PT_32BIT) return (void *)addr; - rc = ERROR_CALL_NOT_IMPLEMENTED; + rc = ERROR_WRONG_PROCTYPE; } retcode = rc; return NULL; @@ -68,12 +169,15 @@ dlerror(void) if (retcode == 0) return NULL; - err = os2error(retcode); + if (retcode == ERROR_WRONG_PROCTYPE) + err = "Wrong procedure type"; + else + err = os2error(retcode); len = strlen(err); if (len > sizeof(buf) - 1) len = sizeof(buf) - 1; strncpy(buf, err, len+1); - if (fail[0] && len < 300) + if (fail[0] && len + strlen(fail) < sizeof(buf) - 100) sprintf(buf + len, ", possible problematic module: '%s'", fail); retcode = 0; return buf;