Archive: installing an older version of a system DLL?


installing an older version of a system DLL?
I am trying to find a way to get NSIS to install an older version of a system DLL. The reason is that DirectShow's latest debug DLLs do not match the versions of the DLLs in XP SP2. I have found an article explaining how to manually disable WFP so that these DLLs can be replaced but I would rather have an installer do it.

Deleting the file manually and having an NSIS installer uninstall it with doesn't work because of WFP.

Here is the command I tried:

!insertmacro InstallLib REGDLL NOTSHARED REBOOT_NOTPROTECTED debug\quartz.dll $SYSDIR\quartz.dll $SYSDIR

but this doesn't work because the current version is newer.

I found the information on the ability to call a system DLL in the Help file and found some information about disabling WFP here:

http://www.bitsum.com/aboutwfp.asp

Is there a way to use System::Call to call:

SetSfcFileException(0, L"c:\\windows\\system32\quartz.dll",-1);

is SFC_OS.DLL?

I noticed that the System:Call docs talk about strings as parameters but not wide strings. It would obviously be better if the Windows system path used $SYSDIR instead of being hard coded.

Or maybe there is a better technique than using SFC_OS?

Thanks.


You can start introducing stability problems in the target system if you start messing with system DLL's. This is the whole reason behind Windows' system file protection in the first place.

But, even though you might not be able to replace the system DLL, you may be able to include the old DLL in the same folder as the software's EXE.

Here's a link from Microsoft that offers a few such tricks. (There's a section called "private dlls" that I found especially interesting...):

http://msdn.microsoft.com/library/de...dlldanger1.asp


Thanks for the response.

I understand the risks of replacing system DLLs. The quartz.dll is not an essential component for Windows boot and there are advantages to having the debug DLL there.

I don't think the private DLL approach will work in this case because quartz.dll is a COM DLL and, AFAIK, there can only be one registered version on the system.

In any case, I'm interested in bypassing WFP. This is not for a customer deliverable installer. The reason is that I would rather have an installer that turns off WFP temporarily for this one file instead of disabling and enabling it entirely. This will make it easier to install and uninstall the debug DLL.


I did some more research on the subject. Alas, it appears as if Microsoft has disabled WFP on XP service pack 2.

But, I did find at least one article from a 3rd party site explaining how to hack the setting, but in involves manually editing the sfc_os.dll file with a hex editor:
http://www.windowsnetworking.com/art...ction-SP2.html

USE AT YOUR OWN RISK! :eek:


In my original post, I linked to a site that explains WFP and how the SFC_OS.DLL has to be hacked to disable it. They even have a tool to do it:

http://www.bitsum.com/index.asp#WfpAdmin

But what I am asking is how to replace a system DLL with an older version in an NSIS installer. That is why I am posting on this forum.


Very sorry--I missed that first link.
Unfortunatley, making system calls is one thing that I still haven't played with much. :(

You have striked my interest however, so I may try to play with it some just to see if I can do it.

(Sorry I couldn't be more help...)


I appreciate your efforts :) It seems MS has gone to great lengths to stop us from doing disabling WFP but in this case it is necessary to install the debug DLL.

One thing that is not clear to me is if the call to SetSfcFileException can be made successfully from an installer.

A problem I forsee is that there doesn't seem to be a facility to pass a wide char string into NSIS's System:Call.


System::Call accepts wide char strings. Simply use the w type. There is an example usage in the readme that retrieves the current wallpaper. It uses a wide char string:

System::Call "$0->4(w .r2, i ${NSIS_MAX_STRLEN}, i 0)"

Thanks Kichik. The docs I saw for System::Call didn't mention the 'w' type.

Can you show me how to translate the following into a NSIS code with a System:Call using the SYSDIR variable for the path to quartz.dll? I find the syntax for this feature confusing and since I don't know if the call will work anyway it will be hard to debug.

SetSfcFileException(0, "c:\\windows\\system32\quartz.dll",-1);

the system DLL is SFC_OS.DLL.


Take a look at the updated System documentation. If you don't have it at Contrib\System\System.html becuase you're using an old version, you can view it at:

http://cvs.sourceforge.net/viewcvs.p...em/System.html


Thanks for the pointer. I hadn't seen that document. This is what I have in my installer:

System::Call 'SFC_OS::SetSfcFileException(i 0, w "c:\windows\system32\quartz.dll", i -1)'

Delete $SYSDIR\quartz.dll

!insertmacro InstallLib REGDLL NOTSHARED REBOOT_NOTPROTECTED XPSP1\quartz.dll $SYSDIR\quartz.dll $SYSDIR

I can see that the quartz.dll is getting replaced with the older one but before five seconds have elapsed WFP is putting the old one back.

Can you see anything obviously wrong or think of another way of achieving this?

I appreciate the help.


"I can see that the quartz.dll is getting replaced with the older one but before five seconds have elapsed WFP is putting the old one back."

By "old one back" I mean WFP is replacing the older DLL with the SP2 dll.


Get SetSfcFileException's return value and check if it failed or not.


System::Call "SFC_OS::SetSfcFileException(i 0, w '%SystemRoot%/system32/quartz.dll', i 600000000) .r0"

MessageBox MB_OK|MB_ICONINFORMATION "Return value from SFC_OS: $0"

I've tried a bunch of things including changing the path. Whe message box returns $0 as the text 'Error'.

Does this mean that it couldn't call SetSfcFileException at all?

Is there anything I need to do before using System::Call with it?


1. I noticed that the original article I pointed to had both SfcFileException and SetSfcFileException. I believe the former is correct but it may have been taken out of SP2's sfc_os.dll... I can't find it with a hex editor :(

2. I have found the SfcIsFileProtected call and it works. (returns 1 if it is protected and 0 if you pass in an unprotected file). This may be useful to others. Unfortunately it doesn't solve the problem I'm facing.

Problems:

SfcFileException is still returning "error" in the code $1


System::Call "SFC_OS::SfcIsFileProtected(i 0, w 'c:\windows\system32\quartz.dll') i.r2"
MessageBox MB_OK|MB_ICONINFORMATION "Return value from SFC_OS: $2"

System::Call "SFC_OS::SfcFileException(i 0, w 'c:\windows\system32\quartz.dll', i -1) i.r2"
MessageBox MB_OK|MB_ICONINFORMATION "Return value from SFC_OS: $2"


You don't search for exported functions using a hex editor. That's what Dependency Walker for. If SfcFileException and SetSfcFileException don't show in the exported functions list of SFC_OS, that would be the problem. In a basic System::Call usage, like in your case, that's the only possible cause for "error" to be returned.


Thanks for the tip :) I have used Depends to see dependent DLLs of a program before but didn't realize it showed the exported functions from a DLL.

As you wrote, SfcFileException is no longer available. Probably viewed as a security hole by MS.


Sorry, my English is very very poor.

I found something may useful at here.

Maybe some program master want to transform that code into an pug-in dll or an uneful function?

Thanks for that.