Archive: RegDLL issue


RegDLL issue
Hi all,

I need some clarification here regarding the workings of the function RegDLL. I'm using NSIS 1.98 btw.

My software has 2 dlls, say A and B. A contains a COM object and requires registration whereas B is simply a dll containing a number of export functions. However, A depends on B.

In the install script, I first unpack the files into the target dir (using file) after which I call RegDLL on A. At this point, I get an error msg saying that dll B cannot be found. I believe this is because dll B is not on the search path nor the current working dir.

2 question:

1) How can I change the working directory of the installer?
2) How does it load and call DllRegisterServer exactly? I'm asking this becuz I've actually written code in DLL A's DLLMain to set the working dir (using SetCurrentDir()) to where dll A is located. However, it appears that RegDLL does not even call DLLMain.

Any help will be appreciated.

Cheers


You can't change the working directory in NSIS 1.98. It's possible using SetOutPath in the latest beta version of NSIS 2.

DllMain should be called because NSIS uses LoadLibrary and not LoadLibraryEx with the LOAD_LIBRARY_AS_DATAFILE flag. If dll A depends on dll B statically then Windows itself will look for the DLL before DllMain is called. If Windows can't find dll B it won't call DllMain. Is dll B statically or dynamically linked to dll A?


Checked a little more and according to this quote from MSDN DllMain might be called before it loads dll B:

It is safe to call other functions in Kernel32.dll, because this DLL is guaranteed to be loaded in the process address space when the entry-point function is called. It is common for the entry-point function to create synchronization objects such as critical sections and mutexes, and use TLS. Do not call the registry functions, because they are located in Advapi32.dll. If you are dynamically linking with the C run-time library, do not call malloc; instead, call HeapAlloc.
I guess it would later call DllMain with DETACH flag if it did call it before all of the DLLs loaded and later failed to load all of the DLLs. I have never seen this happen, but if Microsoft say... :)

Just in case you were wondering, SetCurrentDirectory is in Kernel32.dll.

Thats weird. Cuz I tried it with RegSvr32 (outside of the dll paths) and it works like a charm. However, RegDll still fails. :(


Maybe RegSvr32 changes the working directory.


Nope, regsvr32 didn't but I did. I've placed code to change the current working dir in the DLLMain function.

Apparently, regsvr32 calls DLLMain but RegDLL doesn't! Thats what puzzling me.


Is dll B statically or dynamically linked?


correct me if i'm wrong, but i've always thought that statically linked libraries gets compiled into the module hence you will not have to distribute them? i.e. in my case, it will be dynamically linked cuz I have to distribute dll B along with my dll A.

Are u referring to load-time dynamic linking (i.e. linking with the import lib) vs run-time dynamic linking (i.e. using LoadLibrary)? FYI, i am using load-time dynamic linking.


Sorry, wrong terms, you're right. I did mean to ask if you're loading it at run-time or load-time.

I'll have a deeper look at this, but in the mean time you can use b3 and SetOutPath to set the working directory.


I have tested this on Windows 98 and XP and nither regsvr32 nor RegDLL have called DllMain when the linked DLL could not be found. I have also checked regsvr32 and according to all of the sources I have found regsvr32 does only one action on top of what RegDLL does and this action has nothing to do with this case.

What version of Windows are you using?

BTW, to make sure that DllMain is not called I have used FatalAppExit in it.


I've tried it on both WinXP and Win95. BTW, I've just tried using regsvr32 again on my dll with the SetCurrentDirectory code taken out and it still works! (??) I'm guessing that regsvr32 internally switches the working directory to that of the dll.

Anyhow, here's the exact step I've tried:

In my dll (assume its called mydll.dll)'s DllMain, I've put in code to prompt a messagebox (duh!)

Next I place the dll and the linked dll into a folder called c:\testing

finally I run regsvr32 as follows (notice that the working dir is outside c:\testing):

c:\regsvr32 .\testing\mydll.dll


After moving DLL B to the same folder as DLL A RegSvr32 started working, yet RegDLL failed. I have absolutely no idea why this happens. I can't find anything about RegSvr32 doing more... I have also tried adding the one function that RegSvr32 uses and NSIS doesn't, which has nothing to do with LoadLibrary, and it still failed. I have even tried using SearchPath to see if RegSvr32 somehow changes the PATH enviornment variable or the current directory but SearchPath, which has the exact search pattern as LoadLibrary, failed to find the file.

You would have to set the current directory using a simple plug-in or move to NSIS 2 and use SetOutPath. In any case, do not call RegSvr32 to do this because it doesn't exist on Windows 95.

BTW, calling MessageBox from DllMain is not a good idea according to that MSDN quote I have pasted above.


You would have to set the current directory using a simple plug-in or move to NSIS 2 and use SetOutPath. In any case, do not call RegSvr32 to do this because it doesn't exist on Windows 95.
RegSvr32 does exist on windows 95 (I've tested it on win95 remember?), just that its not in the System32 folder :)

BTW, calling MessageBox from DllMain is not a good idea according to that MSDN quote I have pasted above.
Yep. I read. I was just doing that for testing purposes.

I can't find anything official from Microsoft (why am I not surprised?) but according to Joost, some news posts I have found using Google and the fact that other installers don't use RegSvr32 and RegSvr32 being available for download on the Microsoft website RegSvr32 is not included in the first versions of Windows 95.


ah... you might be right there.. I was testing in Win95 OSR2