Using the CorrectFilePaths Shim to Redirect Files on Windows Vista

The last time around, I suggested that you avoid using the acredir.dll shims – RedirectRegistry and RedirectFiles. As alternatives, I recommended VirtualRegistry and CorrectFilePaths.

Of course, I have already gone into some details on how to use VirtualRegistry to achieve that, but I haven’t gone in to any details on CorrectFilePaths yet. And, unfortunately, the documentation isn’t much help as of the 5.0.1 release (as I said – stay tuned to the documentation for future releases, as this is something we are working on). In fact, here is all that the documentation tells you:

“Corrects file paths that changed between Windows 95 or Windows 98 and Windows XP Professional. This compatibility fix works by converting the file paths to the correct location for Windows XP Professional in the APIs. For example, a Windows 95 path of C:WindowsWrite.exe is converted to C:WindowsSystem32Write.exe.”

While this is true, it is not comprehensive (and is, therefore, not as helpful as you probably want it to be). You see, CorrectFilePaths does apply a number of default corrections, but the real power is your ability to add additional corrections. (You can also configure the shim to not apply the default corrections, using the -b switch.The b stands for base, or bare, or whatever helps you to remember it.)

To add additional paths to correct, you once again have to go into the parameters dialog box. For this, once you have selected (and checked off) the CorrectFilePaths shim, you then need to click the Parameters button. Then, at the command line, you can enter the pairs of file paths you would like to have corrected, using the syntax “old path;new path”.

The quotes I have used are not accidental. You see, part of mastering the use of shims on Windows is learning the intricacies of the command lines, and the person who developers each shim is responsible for parsing that command line. In this instance, the command line happens to be space delimited. So, if your paths contain spaces, you’ll want to quote them. However, you don’t want to quote each path (which is probably what I would have guessed), so “old path”;”new path” is wrong. Rather, you want to quote the entire pair, and repeat this for each individual pair if you want to correct more than one path.

Here is an example command line from a redirection that I applied, to illustrate:

“C:WindowsDownloaded Program FilesStockViewer.ini;%userappdata%StockViewer.ini”

Now, one thing you may have noticed is that I have used what appears to be an environment variable. Let’s talk about that.

There are a couple of reasons why we anticipated having to use CorrectFilePaths: hard coded file paths, and permissions issues. We either want to redirect a hard coded path, or we want to redirect from a location where a standard user won’t have permissions to write to one where they do. (An aside about that: you may be asking why we would need to do this, given that File and Registry Virtualization in Windows Vista will redirect from per-machine locations to per-user locations. Well, we only correct the directories Program Files, ProgramData, and Windows. There are still plenty of applications out there who feel that they are “too important” to be lumped in with the other applications you have installed under Program Files, so they install in the root of the drive. We don’t redirect for arbitrary directories, just for these three, so applications like this are going to need a big of a nudge from you.)

Clearly, with hard coded paths being one thing we’re trying to fix, we don’t want you to have to include hard coded paths in your command line, so we added the ability to get at known locations without that. But, since all you get is a command line, we didn’t want to limit you just to environment variables, so we give you a slight variation that lets you get at the value from either an API or a known folder. Specifically, you can choose to use the following variables:

%windir% = value from GetWindowsDirectoryW
%systemroot% = value from GetWindowsDirectoryW
%systemdrive% = first two characters from GetWindowsDirectoryW
%systemdir% = value from GetSystemDirectoryW
%username% = value from GetUserNameW
%programfiles% = value from ShGetFolderPathW(…, CSIDL_PROGRAM_FILES, …)
%userstartmenu% = value from ShGetFolderPathW(…, CSIDL_STARTMENU, …)
%allstartmenu% = value from ShGetFolderPathW(…, CSIDL_COMMON_STARTMENU, …)
%userdesktop% = value from ShGetFolderPathW(…, CSIDL_DESKTOPDIRECTORY, …)
%alldesktop% = value from ShGetFolderPathW(…, CSIDL_COMMON_DESKTOPDIRECTORY, …)
%userfavorites% = value from ShGetFolderPathW(…, CSIDL_FAVORITES, …)
%allfavorites% = value from ShGetFolderPathW(…, CSIDL_COMMON_FAVORITES, …)
%userappdata% = value from ShGetFolderPathW(…, CSIDL_APPDATA, …)
%allappdata% = value from ShGetFolderPathW(…, CSIDL_COMMON_APPDATA, …)
%allusersprofile% = value from GetAllUsersProfileDirectoryW
%userprofile% = value from GetUserProfileDirectoryW
%appexedir% = value from GetModuleFileNameW

So, you can use CorrectFilePaths to redirect to one restricted or moved location to a better one, leveraging these variables to locate the correct spot on a particular installation.

There are some additional details on this shim and how it can be configured. Specifically, we cover a huge set of APIs, you can add some more, or turn some off. But this isn’t something you typically have to do. So, instead, I figured I’d give you the stuff you’re actually likely to need, and include the rest in the less narrative documentation.

Comments (45)

  1. scotthcw says:

    Hi Chris,

    Thanks for your post here and it helps a lot!

    However, I have a Q here:

    Would CorrectFilePaths Shim redirect all the access to the new path?

    For example, if I want to write to file "asdf.log" in "C:Program Files[Apps Folder]" which is locked, then I apply the CorrectFilePaths Shim in this case, it would redirect to the new path ("C:Users[Logon_User_Name]AppDataLocalVirtualStore") and write to it successfully.

    However, in my case, the application still need to read to "qwer.cfg" in "C:Program Files[Apps Folder]", but it try to find the "qwer.cfg" in new path.

    Do you have any idea in this case? Or am I choosing the incorrect Shim fix?

    Thank you.

  2. cjacks says:


    If the applicaiton is trying to write to %programfiles% then Windows Vista’s file and registry virtualization should fix that up without you having to manually intervene. Check out the UAC File Virtualization event log if that’s not happening.

    CorrectFilePaths is a path swapper. While virtualization is pretty sopohisticated, and does copy on write, CFP just replaces the path in the API call, whether your reading, writing, etc. You’d have to shim the specific file you want to redirect to the full path of the file in the new location to grab just a single file.


  3. Patric says:

    Hi Chris,

    Could you have more than one redirection on the command line? If so, how do you separate them? Or could you add more than one CorrectFilePaths shims but with different redirections?

    Thank you!

  4. cjacks says:

    Hi Patric,

    Separate multiple redirections with spaces. (That’s why you have to quote redirection pairs that have spaces in the path – so we don’t parse them incorrectly.)


  5. Hana says:

    Hi Chris,

    May I know if Shim can apply on installation issue?

    For example, I would like to make an application that originally installed to [Directory A], and use CorrectFilePaths Shim to make it install to [Directory B], is it possible?

    Thanks you…

  6. cjacks says:

    Hi Hana,

    Is it an exe or an msi? If it’s an exe, you can shim it up the same way you could shim up any other exe – all of that works the same. If it’s an msi, that’s a different story – the best approach would be to create an msi transform to redirect to the alternate directory.



  7. Hana says:

    Thanks Chris,

    It’s an msi, do you mean apply the Shim on msiexec.exe to redirect to the alternate directory?



  8. cjacks says:

    Hi Hana,

    No, don’t shim up msiexec, or you’ll be shimming every msi that there is (which is not a good idea). We’re tossing around the idea of allowing shims on msis but it’s not there right now.

    Since MSI is nothing more than a database, and it can be transformed, in this case it’s just easier to create an mst (MSI Transform) to redirect rather than trying to shim.


  9. Bruce Taylor says:

    Can this be used to redirect a file that is generated based on date?  We have an app that creates a c:ddmmyy.log type file (sadly) which I need to look after.  

    ACT is taking some understanding any pointer on that one?  BT.

  10. cjacks says:

    Hi Bruce,

    Unfortunately, CorrectFilePaths doesn’t have the notion of variables to take arbitrary file names from one location and use the same name in another directory, so it doesn’t help you here.

    You could redirect just the beginning of the path, but since it’s at the root, you’d be redirecting absolutely everything, which is almost guaranteed to break it worse than it’s broken now.


  11. Amit Ranjan says:

    Hi Chris

    I have shimmed an application having file path issues in vista. But when I tested that application on another Vista Machine, the patch did’nt worked. So, I want to know two things:

    1. What’s the procedure for deploying the shimmed application?

    2. As we are using sdb for keeping database of shims, So Is there any way to ship it without such files or to ship standalone shimmed executable.

    With regards

    Amit Ranjan

  12. cjacks says:

    Hi Amit,

    You deploy the fixes by installing the shim database (running sdbinst.exe against the .sdb file). You will need to install the database on the second machine before the fixes are applied. We do not modify the executables directly at any point, so you always have to deploy the sdb before the fixes will be applied.



  13. Amit Ranjan says:

    Hi Chris,

    As you told , for deploying the patched application we need to install the database first and then to run the app. I did, but its not working.Below is what I did:

    I copied the file to %WinDir%/AppPatch/Custom folder of another machine and then register it using sdbinst.exe from command line. used this sdbinst.exe c:windowsapppatchdemoApp.sdb, the message appeared database installed successfully. then I ran application… but the app crashed. it means that the patched was’nt applied properly.

    So where and what is missing…

    we are using Vista Business version 6.0(Build 6000). I am not able to figure out.


    Amit Ranjan

  14. Amit Ranjan says:

    Hi Chris,

    Also I missed one thing to tell you, I installed the database using Compatability Administrator and even after that the shim was not working. Where as it’s working on mine machine.

  15. Amit Ranjan says:

    Also, Is it possible to create our own custom shims for compatibility Administrator.

  16. cjacks says:

    Amit – you do not need to copy to %windir%apppatchcustom. When you install using sdbinst, we generate a guid and place a properly registered copy in there – you shouldn’t have to ever put something there manually.

    If it’s working shimmed on one machine, but not on another, then clearly there is a difference between the two machines that is causing the failure. Perhaps PCA has applied some other shim, perhaps the ACLs are set differently – you’ll need to research what is going on. If you’re using CorrectFilePaths, perhaps you’re redirecting to a location that doesn’t exist on that box, and it’s just causing a different failure. Try using ProcMon to see what is going on.

    You are not able to create custom shims.



  17. Amit Ranjan says:

    Hi Chris,

    One more query…Can I edit or view the parameters  added to the built-in shimmed application? Is there any way?

    This will help a lot in application fixing process.

    Thanks in advance.

    Amit Ranjan

  18. cjacks says:

    Hi Amit,

    Sure. Just start up Comptibility Administrator with the /x command line switch.



  19. Joe says:


    This information was very useful.  I fell into the trap thinking RedirectFiles was what I needed and couldn’t get it to work.  I wish there was better reference/help information on the all the shims.

    We have some apps that like to write to the Windows folder or protected areas of the registry, so that changes made by a user is seen by all user on that device.  The Vista virtualation doesn’t work because it sticks these in the users own area not accessible by others.  If I use the CorrectFilePath or the VirtualRegistry shims, where is the recommended place on Vista to redirect these if I need all users to have read/write access?



  20. cjacks says:

    Hi Joe,

    I like to summarize the principles of LUA as: you get to hose your own session and documents, but you can’t hose other people’s stuff, or the box.

    If you allow people to share write access to something, then you break out of that box and gain the ability to hose other people’s stuff.

    That being said, there are plenty of legitimate reasons to share between multiple users of the box, as long as you are sure that you need to do this. For developers, that’s where we recommend writing to ProgramData. You could do the same by redirecting to %allappdata% and then sticking things there. Just like we tell developers, you take responsibility for setting up the ACLs as you need, to grant whoever you want write access to this directory.

    Some people also just save the step of the redirect and just loosen the ACLs on the files in place, making sure that you don’t just loosen them on a whole directory (like %programfiles%) but instead just on the specific file that you need.



  21. A while back, I write about the Correct File Paths shim . Since that time, I’ve heard from a number of

  22. Mike says:

    What is the purpose of the Module information panel?  Does it need to be filled out in order to make work?

  23. cjacks says:

    Hi Mike,

    If you want to make sure that you specifically include a module (dll) that is loaded into the process with this shim, regardless of whether it is statically or dynamically loaded, then you can include that module in the module list.

    The module I most commonly find myself typing here, when I need to use it, is msvbvm60.dll – which you need for most every VB6 application you are shimming.




  24. Pmarra says:


    I’m having an issue with the CorrectFilePaths Shim.

    We are in the process of moving our apps from XP to Vista. Virtualization works, but we want to be compatible with Vista and future versions of Windows (from what I’m reading will not be supporting Virtualization). The apps I’m working on are written in VB6. One of my apps uses a 3rd party ocx that writes a temp file to Program File[appfolder]. I am using the CorrectFilePaths Shim to redirect it, the parameter is as follows: "C:Program Files[appfolder]acvTemp.wav;%userappdata%acvTemp.wav".

    When I create the shim in Compatibility Administrator and test it, it works. I save the sdb database. and use sdbinst.exe to install it. When I run the app outside of compatibility manager it doesn’t work. Ive rebooted and reran it with the same results.

    What am I missing? Is CorrectFilePaths the right shim to use? Is there any way to confirm the shim is being processed?

    I’ve also run the app through SUA; applied the mitigations; and reran it with elevate unchecked and Disable virtualization checked, but get an unhandled exception error(detailing the program needs to be elevated).

    Shouldn’t the applying the mitigations allow the program to run in an unelevated state in SUA?

    Thanks, Pete

  25. cjacks says:

    Hi Pete,

    If virtualization fixes it, I’d go ahead and let it. It’s not going away any time soon. I’m sure the folks who talk to application developers try to scare people away from using it so they do the right thing instead of depending on it, but shimming still isn’t doing the write thing. The right thing is to not try to write there in the first place. If you’re going to write there anyway, may as well take the easier of the two mitigations!

    That being said, it is the right shim to use, and you appear to have the command line configured correctly. Have you included msvbvm60.dll? If it’s VB6, you need to – the Visual Basic virtual machine lives in system 32. See

    If you’ve used mitigations from SUA, that should fix up the issues it detects. It’s possible that there are other issues detected that it’s unable to recommend a mitigation for. Oh, and if there are multiple fils, SUA does apply them as multiple CorrectFilePaths, which is incorrect. It should be a single shim entry with multiple paths on the one command line. Also, there may be additional LUA bugs that we can’t auto-mitigate.



  26. Ivan says:


    I have an application suite that contains 50 executables that all need a hard-coded paths corrected.  Do I have to create 50 shims, or is there some simple way to flag all the modules of this applications in one fix?  (I’ve tried adding matching sub files without success)


  27. cjacks says:

    Hi Ivan,

    If the applications are all launched by a single application, you can use a layer. See

    If you can launch any independently from Explorer, then you’ll need to shim up all 50 executables.



  28. Pmarra says:


    Are any event logs produced when you run an application with applied shims? I’ve tried different variations of shims trying to get the desired results with no luck. It’s probably UE, but I can’t tell if the shims are erroring out because the syntex is incorrect, the file location is wrong, or if the database is even being read. Can you help?

    Thanks, Pete

  29. cjacks says:

    Hi Pmarra,

    Yes, you can get diagnostic output. See



  30. Darryll Challis says:

    I am trying to use the CorrectFilePaths and I would like to change the files path of a file from the C: to the usersprofile, however the fix seems only to work if the directory structure exists in the users profile. Is there a way to ensure the shims destination folder is automatically created for each user that logs in.

  31. Ivan says:

    None of these SHIM’s work for the most offending applications – the 16-bit ones.  What a shame this toolset is half-baked yet again…

  32. cjacks says:

    Hi Ivan,

    The shims that begin with WOWCF are specifically designed for 16-bit applications, and some of our shims do support the old 16-bit APIs. CorrectFilePaths, for example, supports _lopen and _lcreat.

    We build shims based on actual broken applications that get bugs filed against them. So, if we don’t have a shim for a particular problem, it’s probably because we haven’t had a bug filed against it. We never set out to fix all possible problems. In fact, if we had, I am certan that we would never think of the ways that applications would break. It still surprises me what I find sometimes, and I’ve been doing this for years.

    The other aspect is that, while we introduced shims in Windows 2000, we really used them heavily in Windows XP getting consumer apps working on the NT platform. But most of the 16-bit to 32-bit migration had already happened 6 years earlier. Here we are 13 years later, and you don’t find many 16-bit applications lying around any more. Consequently, we don’t get many bugs against it.

    That doesn’t mean they don’t exist. I’ve found customers with piles of 16-bit apps still. One organization was still actively maintaining VB3 apps. But typically, when we find that with the customer, we’re thinking more along the lines of "organizational risk – get them replatformed" than "oh, let’s see if we can keep these around longer." So I have’t had a request from a customer to fix too many because when they find them, they typically aren’t keen on keeping them.

    That doesn’t mean that we don’t sometimes need a bridging solution, and there are some options. But your 16-bit apps aren’t going to work on x64 at all and we can’t do anything about that. That’s why most people, when they find it, hope to get rid of it.

    If you can tell us what you need to have, and what the impact of not having it is, then we can see what we can do, or at least incorporate the scenario to see if we can find a better solution.



  33. Ivan says:


    Thanks for responding so promptly, and sorry about the frustrated note above.  I’ve been unable to get ForceDisplayMode and CorrectFilePaths to work for 16-bit apps.  However the workaround you suggested elsewhere of using layering to cover the child processes appears to work here too if I replace the toplevel process with a 32-bit process.  Unfortunately I can’t do this in all circumstances, so I’m still not out of jail.

    I’ve been doing this for years too, and am no longer surprised at what’s out there, particularly with customers’ internally written apps.  While I agree it’s not possible to predict every bad scenario, we need a good chest of tools to be able to tackle what we do encounter.  The Application Compatibility Toolkit has been largely toothless from a corporate point of view until the recent addition of CorrectFilePaths (Yes, I’m one of the customers who was beating you up about this before).  However I’m still finding it limiting: For example, there’s not a variable that can be used to redirect files via CorrectFilePaths to the user’s %Temp% folder, and lack of 16-bit support is also very frustrating.  These are issues that I would have expected the AppCompat team to anticipate.


  34. cjacks says:

    Hi Ivan,

    I don’t think we saw when you’d want to redirect to the temp folder. If it was going to a protected area before, I don’t think we foresaw it being demoted from someplace like Program Files or Windows down to temp. I more often than not end up going to %userappdata%.

    I think it’s been "toothless" for enterprise apps more so because of lack of documentation. We released shims for customers to use kind of as an afterthought, and the tools reflect that. While some used it on XP, it’s really only been recently that we’ve had the documentation out there to enable people to be successful. Now that we have the dialog going, that’s going to drive more and more customer focus on mitigation tools, where before we were always thinking (because that’s all we ever saw) of commercial apps.

    We’re getting there, and your feedback absolutely helps. I don’t know if 16-bit stuff is going to be getting too much love, though.



  35. Ivan says:

    Thanks again for the reply.  I have multiple experiences of apps that write temp files either to their executable directory, or more commonly, to C:Temp (which does not exist under Vista).  Sometimes the temp filenames are predictable and sometimes not. A junction from C:Temp to %SystemRoot%Temp helps some, but not all of these cases.

    Appreciate that 16-bit apps are not getting any love, but it’s still tricky when I have a customer with a business-critical 16-bit app that’s a showstopper for Vista migration. So yes, as much as you and I may hate it, unfortunately they are still out there – and I’m refering to the banking and insurance industries here.

  36. cjacks says:

    Hi Ivan,

    Could you use %userprofile%appdatalocaltemp?

    Yes, I totally get that it sucks when we find gaps and you can’t fix something. If you’ve got seats you can’t deploy because of it, then send me the data (my blog name is my email alias) and I can submit to WinSE. It’s easier to get something in before we release, but since were 18 months too late for that I need evidence to build a case. Even then, no promises, but I’m happy to give it a go.



  37. Ivan says:

    Sorry Chris, last question: Where can I obtain documentation for *all* the paramters of *all* the SHIMS?  

    For example MoveIniToRegistry clearly requires parameters, but there’s no documentation defining what these are.  (Presumably this fix will apply an IniFileMapping?)

  38. cjacks says:

    Hi Ivan,

    Documentation for all parameters of all shims doesn’t exist yet. To find it, you’re going to require a time machine.

    I don’t like that answer either, that’s why I just started writing the docs. So, right now the workflow is that I write up technical docs, and hand them over to a technical writer. She cleans them up and adds them to the ACT documentation. She just released an OOB update on what we’re working on – see And if I get request for particular ones, then I move those to the front of the queue (the order right now is based on frequency of usage). Also, when I get a request, I also usually post on my blog so you don’t have to wait for the entire process to complete.

    So, I’ll have a look at that one as soon as I can and post something up here.



  39. Ivan says:


    FYI, I’ve hit a limitation with CorrectFilePaths – the maximum amount of data that can be entered in the parameter field is 512 bytes – not enough to fix more than 2 files under "Program Files" unfortunately…

  40. cjacks says:

    Hi Ivan,

    The command line is limited to MAX_PATH = 260 characters. But it’s substring replacement, so you don’t have to type the full path. I typically look for subsets of the path that would work for what I want but nothing else.

    Does file/registry virt not work for you in Program Files? I don’t run across problems here much because Vista already fixes those for me.



  41. I send out a lot of links to my articles in response to questions that come up, but the other day I had

  42. Ivan says:

    BTW, I hit the limitation above while directing files to %ProgramFiles%, not from it, so Virtualisation does not really help here. (Legacy apps hard-coded to various non-std program locations under C:)

  43. Hey,Chris – I’m at a customer site (without email) and have a question:  is it possible in any way to version-lie to an MSI?  E.g., the MSI runs and insists on a specific version of Windows.  We want to be able to get it to install anyway.


  44. cjacks says:

    LOL – too funny, Aaron. It’s not possible today (though I’ll forward this on as a feature request to numinstances++). What I typically do is edit the LaunchCondition table in a transform, since that’s where the check is typically done.