HTTrack Website Copier
Free software offline browser - FORUM
Subject: [Windows] libhttrack.dll and LoadLibrary
Author: dbw
Date: 04/16/2004 21:07
I've encountered problems instantiating the libhttrack.dll 
dynamically, that is using the Windows LoadLibrary API and 
then trying to invoke HTTrack. Crazy enough, I can call 
hts_init, and for example hts_is_available, but as soon as 
I tried to call hts_main I get a GPF. However, when I 
statically link the DLL, there's no problem and everything 
works OK. Yet I needed the LoadLibrary functionality so 
this didn't really solve my problem.

Eventually I managed to recompile the DLL with debugging 
information, and it turned out that a simple call to 
hts_main resulted in a GPF in a function named concat 
(htslib.c). It seems to do some fancy 'strcat'-like 
mathingy I don't fully understand, but the GPF was inside 
the NOSTATIC_RESERVE macro. Anyway, after reverse-
understanding this macro I found the following in MSDN:

"If a DLL declares any nonlocal data or object as 
__declspec( thread ), it can cause a protection fault if 
dynamically loaded. After the DLL is loaded with 
LoadLibrary, it causes system failure whenever the code 
references the nonlocal __declspec( thread ) data. Because 
the global variable space for a thread is allocated at run 
time, the size of this space is based on a calculation of 
the requirements of the application plus the requirements 
of all of the DLLs that are statically linked. When you 
use LoadLibrary, there is no way to extend this space to 
allow for the thread local variables declared with 
__declspec( thread ). Use the TLS APIs, such as TlsAlloc, 
in your DLL to allocate TLS if the DLL might be loaded 
with LoadLibrary."

And that is exactly the problem: the macro uses compiler 
supported thread local storage (using __declspec(thread)) 
and this indeed causes "problems" as Microsoft 
acknowledges above.

I think I now have solved the problem (following 
Microsoft's advice) by changing the NOSTATIC_XRESERVE 
macro (htsnostatic.h) as follows:

#define NOSTATIC_XRESERVE(name,type,nelt) \
  { \
    static DWORD tlsIndex = 0; \
    static   int initValue = 0; \
    if (initValue == 0) \
    { \
      name = (type*)malloc(sizeof(type)*nelt); \
      assert(name != 0); \
      memset(name, 0, sizeof(type)*nelt); \
      tlsIndex = TlsAlloc(); \
      assert(tlsIndex != 0xFFFFFFFF); \
      TlsSetValue(tlsIndex, name); \
      initValue = 1; \
    } \
    else \
    { \
      name = TlsGetValue(tlsIndex); \
      assert(name != 0); \
    } \

Using this version of the macro I can use the DLL both in 
a static and in the dynamic way using LoadLibrary. I've 
only tested this quickly and in a rather limited scenario 
but it might be useful to incorporate this change into the 
DLL version.


All articles

Subject Author Date
[Windows] libhttrack.dll and LoadLibrary

04/16/2004 21:07
Re: [Windows] libhttrack.dll and LoadLibrary

04/17/2004 17:18
Re: [Windows] libhttrack.dll and LoadLibrary

04/17/2004 18:09
Re: [Windows] libhttrack.dll and LoadLibrary

08/18/2005 19:55


Created with FORUM 2.0.11