Jump to content

WFP - app for removing individual files from monitoring


ElTorqiro

Recommended Posts

Hi,

First, since this is my first post in the forums, cheers to nuhi for creating nLite and all the other people who have contributed to the project, even just by offering info here!

I've read a heap of the WFP posts on the forums here, and gathered a lot of useful information from it, and from various other places on the web (thanks bitsum, fdv etc). Basically, I wanted to stop WFP/SFC from monitoring those files which were removed during an nLite installation, but still keep WFP monitoring the remainder. Even though I notice nLite tries to do this and rebuilds the sfcfiles.dll during the build process, it doesn't seem to catch all the missing files (in fact it seems to catch very few). Please don't take this as undue criticism, just an observation.

Anyway, I discovered that every time I'd try to install a driver etc in Windows after an nLite'd install I'd get the WFP popup asking for the CD. Even after inserting it (or if it was left inserted all the time), no files were actually copied off the disk (presumably because they weren't there - nLite had removed them as requested in my build), the only successful access was for the tag file in the root of the CD. I know this has been brought up many times in the forums, but none of the recommended options or suggesting solutions worked the way I wanted. I know I can use a hacked sfc_os.dll to enable the "no-popup" feature, but I'd rather WFP never even looked for the excluded files in the first place.

Doing a bit of research I found a few methods (many of them listed in these forums) for disabling WFP, or filtering the file list in sfcfiles.dll. One of the methods mentioned involves 00'ing out the first byte of any of the Unicode filenames in sfcfiles.dll that I wanted to remove from the list. I found that this disables WFP altogether, with SFC reporting inability to load the relevant RPC server - I gather this is because the sfcgetfiles() expects to find a valid path (or at least one that is searchable by whatever checking function it uses) at the specific location 00'd out in sfcfiles.dll and upon finding an empty string crashes without proper error handling. Either way, it stops WFP working. So, I tried doing it the way nLite seems to currently do it, which is to leave the path behind, but 00 out the first letter of the filename part of the path in sfcfiles.dll. This works a treat, WFP runs properly and excludes those files I want to exclude. However, because paths are left behind, the directory change event that WFP uses to monitor file changes is still bound to the path-without-filename in sfcfiles.dll so it when doing something like an sfc /scannow it spams a gazillion events in the event log complaining about being unable to copy the path into dllcache :) At least it doesn't make you click Cancel/Yes each time, it just handles the failure it automatically, but it's annoying as it makes a big mess of the event log.

So, I tried a lot of different methods and finally came up with one that doesn't seem to have any adverse affects. Instead of 00'ing out the first letter of each entry I want to exlude in sfcfiles.dll I put a \ instead - i.e. because it's unicode I actually write byte[] {(byte)'\\', 0, 0, 0} (i.e. a backslash followed by zero-termination for end of string)

This method does two good things - first, whatever function WFP uses to check for the existence of the path succeeds (or at least doesn't crash - maybe it checks for existence of %systemroot%\ when given "\" as a path), but the directory change event binding is never initiated because that function needs a fully qualified path to bind to, it doesn't automatically substitute for current drive so has nothing to bind to - this doesn't make anything crash, though. I confirmed this by checking winlogon's handles pre- and post-my fix and made sure there was no binding made to the root directory :)

Note that you can't put any old character as a substitute at the start of the entry in sfcfiles.dll; as far as I can tell it must be a path that can be checked for existence. If you give a path that doesn't exist, that's ok, but without changing the entry size you'd need to make it a pretty small path, so "\" is perfect. You can't just use something like "-" or " " (a space), though, it needs to be a path or file that can be checked. Actually, you might be able to use a space, as you can make files that are just called " ", but I didn't check that - better to use "\". I know a lot of people have written that using 00 is possible, but I found it just doesn't work for me, it prevents WFP/SFC from working altogether.

So, I've now written a console app that will parse a vanilla WinXP Pro x86 SP2 sfcfiles.dll (which I use) will gather the list of files/paths and check if they exist on my system (including ExpandEnvironmentVariables) - if they don't, it replaces the start of the entry with the byte sequence I referred to above '\\',0,0,0 to satisfy the Unicode requirement. I then use ModifyPE (or similar tool as referenced in the forums here) to fix the checksum of sfcfiles.dll. Unfortunately, I then have to reboot in safe mode or use a replace-at-next-boot tool like MoveLatr as provided by bitsum) to replace the file, but that's ok for now.

One other thing I've written into my app is the ability to pass it a directory to search for files, in which case it will check that path for each entry in a given sfcfiles.dll, checking either the original filename or the filename.xx_ equivalent. I can thus run it on the i386 directory of an nLite build prior to burning to CD and then I can put my modified makecab'd sfcfiles.dll into the build CD. Not sure how reliable this is as a method since things like leaving the iis component included in your build, but then selecting it for non-installation during the Windows install may mean files aren't actually on your disk, I dunno, haven't tested that. It also can't check through the CABs so it would need to be done before the CABs are recompressed, if nuhi puts this into nLite itself.

So, now I have WFP running properly and without the popup appearing every time an app or driver is installed. The only thing I get when doing sfc /scannow is a complaint about syssetup.dll and sfcfiles.dll having bad signatures (so it asks for the CD twice during the sfc /scannow process but cancelling is ok). Occasionally during /scannow it puts an entry in the event log (but doesn't pop up a message) about not being able to copy ntoskrnl.exe or ntkrnlpa.exe into the dllcache but I can't pin down what causes that yet. I never use sfc /scannow in real life anyway so will probably never bother looking into these two. The files are already in dllcache and they get replaced properly if I try to delete/modify/rename either of them. Anyway, despite those two things, I am satisfied my original need was met since the popup when installing drivers no longer appears, and I can still use nLite's remove component function and retain popupless WFP. Hurrah!

Sorry for the massive post - if anyone wants the source to my app I've written it in C# and posted it below here (attachment wouldn't work for me for some reason), but from the description above any programmer will be able to knock up something really simple in any language. I did it in C# hoping that nuhi could use the code somehow in nLite itself at some point. It could be done as a runonce thing I think, which is actually safer as then you know 100% if the system has the specified files, but then the app couldn't be in a .NET 2.0 language in case user hasn't got it installed.

I'm not going to provide a binary because too many (with respect) noobs may download and use it without understanding what's going on, and I don't want to be blamed if people stuff up their system somehow.

REMEMBER - if you use it, don't forget to fix the checksum before putting it into your system! Use modifype.exe or similar to do that manually. If you want to keep the log, pipe the output to a text file (e.g. modsfcfiles sfcfiles.tmp > log.txt) Also use this method (or pipe to nul) if you want to make it run quicker. Without text output it runs in under a second on my machine, but with text output it takes ages due to screen update inefficiency. So modsfcfiles sfcfiles.tmp > nul if you don't want to keep the log or see it in any way :)

Edited by nuhi
Link to comment
Share on other sites


A couple of people have PM'd in another forum whinging about not providing a binary etc, and even some saying I was nasty for making only Visual Studio owners able to use it. WTF! Well, I gave my reasons, and I don't think it's prohibitive to make your own from the source code. Since my app has hardcoded entry points for the sfcfiles list text segments ONLY for WinXP Pro SP2 x86, I didn't want people downloading a binary and running it on some other system and thus stuffing their sfcfiles.dll completely.

If you understand and still would like to compile it for use on your system, the tools are available for free, and are quite small.

1.> You need .Net 2.0 for this to work. You can get it for free from the MS web site (and presumably a million other places). If you are using nLite, you have this already.

2.> I don't use Visual Studio, I use the free, open source SharpDevelop IDE for writing .Net apps. You can download it from http://sharpdevelop.net/OpenSource/SD/Default.aspx

3.> You don't need the .Net 2.0 SDK but if you plan on developing or debugging .Net apps it helps save some time. You can get it from the MS web site too and SharpDevelop will integrate it into itself. It's about 350mb, though, so if all you want to do is compile my source and maybe tinker a tiny bit, don't bother.

This was the first .Net app I wrote, and did it in a couple of hours, so you can tell it's not too hard :)

Link to comment
Share on other sites

Hi,

thanks for the contribution.

Now just so you know nLite already does that for a year or so (check the sfcfiles.dll, maybe I made some mistake) but the thing is that SFC still popups for some files due to the broken signatures of certain INF files. Also Front Page extension (even if not removed) is most often in my tests to be prompted by SFC, beats me why...probably signatures again.

Link to comment
Share on other sites

nLite already does that for a year or so (check the sfcfiles.dll

It does the backslash option? The nlite-modified sfcfiles.dll I tested from an nLite 1.3.5 build had used the 00 method for the first letter of each filename (not path) for each entry. This does avoid sfc popups for the corrected entries, but it spams the heck out of the event log with "unable to copy to dllcache" information notices when running sfc /scannow. setuperr.log is also full of these notices if SFC is enabled during Windows installation. nLite is also missing some entries that need to be corrected, such as the frontpage extensions you mentioned. Using the \ method at the start of the entry it no longer fills up the event log, and no longer causes any warnings.

I don't know enough about the nLite processing to determine if you can inject the \ method into nLite or not :( But, I have found with my builds the only reliable way to completely satisfy SFC on an nLited install (apart from signature errors on a couple of files like uxtheme.dll and sfcfiles.dll itself, which are unavoidable) is to take a vanilla sfcfiles.dll and process it in my app after Windows installation, then copy this modified sfcfiles.dll over the proper one in system32. This is the only way I can tell to guarantee that the file actually exists or not on the system, and thus whether the entry should be set to \ in sfcfiles.dll. Otherwise, with any nLite build, I get either SFC not working at all, maybe because of a misplaced 00, or getting lots of SFC popups.

I know you've said before you never use SFC, but as a test to see what I mean, do an nLite build and just remove a few random things. Leave SFC enabled. Then install the build and try either installing a driver (like plug a USB external drive in or something), or run sfc /scannow and you'll see what I mean. The first will cause a popup, the second will cause a few popups and also a tonne of entries in the event log because of orphaned paths in sfcfiles.dll due to the 00 method. Now try taking a vanilla sfcfiles.dll and modify it using my method, put it in system32 in safe mode, then try the same actions - you'll see no popups for driver installs, and only a couple of popups & entries in the event log for signatures, none at all for missing files or orphaned paths.

Edited by ElTorqiro
Link to comment
Share on other sites

Oh so you say \ instead of empty...great at least some hope, will try that and read your post in more detail when I'm at it, thanks.

Yeah, the main thing is that instead of emptying out the first letter of the filename with 00, what you do instead is put a \ (plus a 00 to terminate the string) at the start of the entry (not the start of the filename part, the start of the whole entry).

e.g. (for unicode I'm using _ to indiate where 00 should be)

%_s_y_s_t_e_m_r_o_o_t_%_\_s_y_s_t_e_m_3_2_\_s_t_u_f_f_._d_l_l__

becomes

\__y_s_t_e_m_r_o_o_t_%_\_s_y_s_t_e_m_3_2_\_s_t_u_f_f_._d_l_l__

so you basically have a backslash and a 00 terminator, so you are replacing 2 characters at the start of the string. This satisfies the "file exists" part of the sfcgetfiles() but also prevents it binding a directorychangenotification event to the path, and also prevents it silently complaining about not being able to copy files into dllcache.

Good luck with it, if you have any questions or want any examples please let me know :)

Link to comment
Share on other sites

Folks, even though everyone has been polite on this forum, on another forum I've had some headaches from people about the code I posted. So I've removed the code part from my original post. Note that I have left all the other info, so from the concept you should be able to make your own pretty easily.

If you want the code I originally posted, please leave me a PM and I'll send it to you, at this stage it seems somehow dangerous to leave it available as people are completely ignoring my warnings and destroying their sfcfiles.dll (without making a backup first) and blaming me. While I don't accept the blame, it seems safer to avoid possible angst and protect people from themselves somewhat.

So let me know if you want it.

Cheers!

Link to comment
Share on other sites

@ElTorqiro

Nice find! :)

Though when Nuhi will have tested and integrated your idea in nlite your program might prove to be mostly unneeded, if I may, I would suggest to NOT "abandon it, but rather enhance it.

What if some features are added to it, something like:

1) Backup sfcfiles.dll to sfcfiles%date%%time%.old

2) Make a list of files from current sfcfiles.dll dynamically (i.e. without having an hardcoded set of files linked to a certain version of scfiles.dll)

3) Let the user choose from the list (maybe with a multi-page/multi-selection) which files he wants WFP disabled for

4) have an option to restore a previously backed up sfcfiles%date%%time%.old to sfcfiles.dll

This way even the n00b could use the app in a relatively safe manner....

Cheers,

jaclaz

Link to comment
Share on other sites

Hi jaclaz, thanks for your reply.

The code I posted was never intended to be a long term solution, it was just to demonstrate the proof of concept. That's why I refrained from posting binaries. Anyone can then make an app they want to use. Even without the code, the method for removing entries is explained so people can write whatever app they like using any language the are familiar with.

So it's not a case of abandoning anything, as I wasn't trying to release an app for people to use, but thanks for the encouragement :)

The main reason I refrained from posting a binary, however, is that my code is hardcoded with locations in the sfcfiles.dll to find the lists of entries, and those are hardcoded locations taken from a vanilla WinXP Pro SP2 x86 version of sfcfiles.dll. There are many versions of Windows out there, but I only have that one. If someone directly took my code or a binary I made from that code and used it on some other form of Windows then it would make a complete mess of their sfcfiles.dll :) I'm not interested in coding checks for various versions etc into an app, I am relying on people who have a need for this kind of thing being able to adapt the method to their own uses.

If anyone is interested but has no coding experience, there are free (and easy) tools for making apps like this, and if you have nLite you already have part of it (the .Net 2.0 redistributable). Then all you need is an IDE like Visual Studio, or if you want a good free one try SharpDevelop. You can also get the .Net 2.0 SDK free from the Microsoft site (search their site for it or google it). I had never used .Net before I wrote my code for this particular problem, and I did that in a day so anyone should be able to pick it up pretty quickly. As I mentioned earlier, if anyone is interested in making an app based on my code, feel free! Just let me know if you want it, no strings attached.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...