X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=os2%2Fdl_os2.c;h=76fa9dc42d9ceff37ef98aaa0f5cefefc9563eaa;hb=9483776f29dbf67c9f5f68dcc7dd77bf0eb0eeb5;hp=5c8b6e687165f34a7ec5200134ffaf321e694e53;hpb=35bc1fdc44cabda9b94bf3b2cbffe0be67fef25d;p=p5sagit%2Fp5-mst-13.2.git diff --git a/os2/dl_os2.c b/os2/dl_os2.c index 5c8b6e6..76fa9dc 100644 --- a/os2/dl_os2.c +++ b/os2/dl_os2.c @@ -4,22 +4,114 @@ #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(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 (!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) - return (void *)handle; + goto ret; retcode = rc; @@ -39,12 +131,17 @@ dlopen(const char *path, int mode) 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, const char *symbol) { @@ -57,7 +154,7 @@ dlsym(void *handle, const 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; @@ -72,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;