This is the mail archive of the cygwin-developers mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: LoadLibrary error 487 (was Re: Please test latest developer snapshot)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]