LoadLibrary error 487 (was Re: Please test latest developer snapshot)
Corinna Vinschen
corinna-cygwin@cygwin.com
Sat Feb 26 21:42:00 GMT 2011
On Feb 26 21:26, Corinna Vinschen wrote:
> On Feb 26 19:45, Corinna Vinschen wrote:
> > On Feb 26 19:43, Corinna Vinschen wrote:
> > > On Feb 26 13:23, Christopher Faylor wrote:
> > > > The other thing we could do is add a flag to thd dll_info struct which says
> > > > "Use DONT_RESOLVE_DLL_REFERENCES" either in the forkee or always depending
> > > > on what works for winm.dll.
> > >
> > > That's what I meant above. It would require a new LoadDLLfuncEx4,
> > > wouldn't it? OTOH, LoadDLLfuncEx3 is only referred to via the
> > > definition of LoadDLLfuncEx2, so it should be simple to redefine.
> >
> > Btw., what is the "fn" argument to LoadDLLfuncEx3 good for? Given that
> > it's always 0 it seems pretty useless right now...
>
> Erm... I don't know what fn is supposed to do, but right now it's
> value is simply used for the error code. In LoadDLLprime it's put
> into the upper 8 bytes of the decoration:
>
> .long (" #n "+" #notimp ") | (((" #err ") & 0xff) <<16) | (((" #fn ") & 0xff) << 24)
>
> And in noload it's simply returned together with the err value:
>
> [...]
> andl $0xffff0000,%eax# upper word
> [...]
> pushl %eax # Save for later
> [...]
> popl %eax # Get back argument
> sarl $16,%eax # return value in high order word
> jmp *%edx # Return
>
> My question is, shouldn't there be an additional
>
> andl $0x000000ff,%eax
>
> right before the jmp? This would also allow to use the fn value
> for the purpose discussed above.
Here's my final patch, assuming I got that right with LoadDLLfuncEx3 and
err and fn. I'm using the fn parameter to LoadDLLfuncEx3 as an 8 bit
flag value now. std_dll_init checks if the lowest bit is set, and only
then it calls LoadLibraryExW. Is that ok?
Corinna
* autoload.cc (noload): Only use the 8 err bits from decoration
as return value.
(std_dll_init): If LoadLibraryW returns with ERROR_INVALID_ADDRESS
and function is marked, try to load module with LoadLibraryExW with
DONT_RESOLVE_DLL_REFERENCES flag set. Add longish comment.
(LoadDllFuncMM): Define to call LoadDLLfuncEx3 with LSB in fn set.
Use to define winmm functions throughout.
Index: autoload.cc
===================================================================
RCS file: /cvs/src/src/winsup/cygwin/autoload.cc,v
retrieving revision 1.184
diff -u -p -r1.184 autoload.cc
--- autoload.cc 26 Feb 2011 20:47:56 -0000 1.184
+++ autoload.cc 26 Feb 2011 21:40:01 -0000
@@ -135,7 +135,7 @@ noload: \n\
decl %eax # Yes. This is the # of bytes + 1 \n\
popl %edx # Caller's caller \n\
addl %eax,%esp # Pop off bytes \n\
- andl $0xffff0000,%eax# upper word \n\
+ andl $0x00ff0000,%eax# low byte from upper word is retval \n\
subl %eax,%esp # adjust for possible return value \n\
pushl %eax # Save for later \n\
movl $127,%eax # ERROR_PROC_NOT_FOUND \n\
@@ -237,10 +237,27 @@ std_dll_init ()
/* If loading the library succeeds, just leave the loop. */
if ((dll->handle = LoadLibraryW (dll_path)) != NULL)
break;
- /* Otherwise check error code returned by LoadLibrary. If the
- error code is neither NOACCESS nor DLL_INIT_FAILED, break out
- of the loop. */
+ /* Otherwise check error code returned by LoadLibrary. */
err = GetLastError ();
+ /* If the error code is INVALID_ADDRESS, we're stumbling over a
+ problem with loading winmm.dll from a forked process under some
+ not really clear circumstances. This has been observed on XP
+ only so far. Apparently there's a bug in older versions of the
+ winmm DLL. It calls FreeLibrary in DllMain, which is a no-no
+ per MSDN. For some reason it helps to load the library with
+ the DONT_RESOLVE_DLL_REFERENCES flag, even though this should
+ result in a non-working DLL in memory. */
+ if (err == ERROR_INVALID_ADDRESS && in_forkee
+ && ((func->decoration >> 24) & 1))
+ {
+ if ((dll->handle = LoadLibraryExW (dll_path, 0,
+ DONT_RESOLVE_DLL_REFERENCES))
+ != NULL)
+ break;
+ err = GetLastError ();
+ }
+ /* Otherwise, if the error code is neither NOACCESS nor
+ DLL_INIT_FAILED, break out of the loop. */
if (err != ERROR_NOACCESS && err != ERROR_DLL_INIT_FAILED)
break;
if (i < RETRY_COUNT)
@@ -435,27 +452,31 @@ LoadDLLfunc (SetProcessWindowStation, 4,
LoadDLLfunc (SetThreadDesktop, 4, user32)
LoadDLLfunc (ShowWindowAsync, 8, user32)
-LoadDLLfunc (timeBeginPeriod, 4, winmm)
-LoadDLLfunc (timeEndPeriod, 4, winmm)
-LoadDLLfunc (timeGetDevCaps, 8, winmm)
-LoadDLLfunc (timeGetTime, 0, winmm)
-LoadDLLfunc (waveInAddBuffer, 12, winmm)
-LoadDLLfunc (waveInClose, 4, winmm)
-LoadDLLfunc (waveInGetNumDevs, 0, winmm)
-LoadDLLfunc (waveInOpen, 24, winmm)
-LoadDLLfunc (waveInPrepareHeader, 12, winmm)
-LoadDLLfunc (waveInReset, 4, winmm)
-LoadDLLfunc (waveInStart, 4, winmm)
-LoadDLLfunc (waveInUnprepareHeader, 12, winmm)
-LoadDLLfunc (waveOutClose, 4, winmm)
-LoadDLLfunc (waveOutGetNumDevs, 0, winmm)
-LoadDLLfunc (waveOutGetVolume, 8, winmm)
-LoadDLLfunc (waveOutOpen, 24, winmm)
-LoadDLLfunc (waveOutPrepareHeader, 12, winmm)
-LoadDLLfunc (waveOutReset, 4, winmm)
-LoadDLLfunc (waveOutSetVolume, 8, winmm)
-LoadDLLfunc (waveOutUnprepareHeader, 12, winmm)
-LoadDLLfunc (waveOutWrite, 12, winmm)
+/* Fatal error if loading fails, error code doesn't matter, Mark as DLL
+ which might fail with ERROR_INVALID_ADDRESS. See std_dll_init(). */
+#define LoadDllFuncMM(name, n, dllname) \
+ LoadDLLfuncEx3 (name, n, dllname, 0, 0, 1)
+LoadDllFuncMM (timeBeginPeriod, 4, winmm)
+LoadDllFuncMM (timeEndPeriod, 4, winmm)
+LoadDllFuncMM (timeGetDevCaps, 8, winmm)
+LoadDllFuncMM (timeGetTime, 0, winmm)
+LoadDllFuncMM (waveInAddBuffer, 12, winmm)
+LoadDllFuncMM (waveInClose, 4, winmm)
+LoadDllFuncMM (waveInGetNumDevs, 0, winmm)
+LoadDllFuncMM (waveInOpen, 24, winmm)
+LoadDllFuncMM (waveInPrepareHeader, 12, winmm)
+LoadDllFuncMM (waveInReset, 4, winmm)
+LoadDllFuncMM (waveInStart, 4, winmm)
+LoadDllFuncMM (waveInUnprepareHeader, 12, winmm)
+LoadDllFuncMM (waveOutClose, 4, winmm)
+LoadDllFuncMM (waveOutGetNumDevs, 0, winmm)
+LoadDllFuncMM (waveOutGetVolume, 8, winmm)
+LoadDllFuncMM (waveOutOpen, 24, winmm)
+LoadDllFuncMM (waveOutPrepareHeader, 12, winmm)
+LoadDllFuncMM (waveOutReset, 4, winmm)
+LoadDllFuncMM (waveOutSetVolume, 8, winmm)
+LoadDllFuncMM (waveOutUnprepareHeader, 12, winmm)
+LoadDllFuncMM (waveOutWrite, 12, winmm)
LoadDLLfunc (accept, 12, ws2_32)
LoadDLLfunc (bind, 12, ws2_32)
--
Corinna Vinschen Please, send mails regarding Cygwin to
Cygwin Project Co-Leader cygwin AT cygwin DOT com
Red Hat
More information about the Cygwin-developers
mailing list