This exception occurs when you try to save changes in the Control Panel\System and Security\File History\Exclude Folders.
Let’s display information about the exception, the version of the faulting module and then change the context to the context of the exception.
0:033> !analyze -v ... FAULTING_IP: fhcfg!CDpScopeIterator::GetItem+78 00007ff9`05c18148 4883791808 cmp qword ptr [rcx+18h],8 EXCEPTION_RECORD: ffffffffffffffff -- (.exr 0xffffffffffffffff) ExceptionAddress: 00007ff905c18148 (fhcfg!CDpScopeIterator::GetItem+0x0000000000000078) ExceptionCode: c0000005 (Access violation) ... MODULE_NAME: fhcfg IMAGE_NAME: fhcfg.dll ...
0:033> lmvm fhcfg Image path: C:\Windows\System32\fhcfg.dll Image name: fhcfg.dll Timestamp: Sat Feb 22 12:17:32 2014 (5308793C) CheckSum: 000ADCA8 ImageSize: 000AE000 File version: 6.3.9600.17031 Product version: 6.3.9600.17031 File flags: 0 (Mask 3F) File OS: 40004 NT Win32 File type: 2.0 Dll File date: 00000000.00000000 Translations: 0409.04b0 CompanyName: Microsoft Corporation ProductName: Microsoft® Windows® Operating System InternalName: fhcfg.dll OriginalFilename: fhcfg.dll ProductVersion: 6.3.9600.17031 FileVersion: 6.3.9600.17031 (winblue_gdr.140221-1952) FileDescription: File History Configuration Manager LegalCopyright: © Microsoft Corporation. All rights reserved.
0:033> .ecxr rax=0055005c003a0043 rbx=0000000000000000 rcx=0055005c003a0053 rdx=0000000004ece070 rsi=0000000004ece0a8 rdi=0000000004ece070 rip=00007ff905c18148 rsp=0000000004ecdff0 rbp=0000000000000000 r8=0000000000000000 r9=0000000000000006 r10=0000000000000080 r11=0000000004ecdf30 r12=0000000000000000 r13=0000000000040001 r14=0000000000040000 r15=0000000000000007 iopl=0 nv up ei pl nz na pe nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202 fhcfg!CDpScopeIterator::GetItem+0x78: 00007ff9`05c18148 4883791808 cmp qword ptr [rcx+18h],8 ds:0055005c`003a006b=????????????????
Now we can walk back to the beginning of the method to find out where rcx came from.
0:033> ? @rcx-10 Evaluate expression: 23925768161198147 = 0055005c`003a0043 0:033> u fhcfg!CDpScopeIterator::GetItem fhcfg!CDpScopeIterator::GetItem+0x78 fhcfg!CDpScopeIterator::GetItem: 00007ff9`05c180d0 48895c2408 mov qword ptr [rsp+8],rbx 00007ff9`05c180d5 57 push rdi 00007ff9`05c180d6 4883ec20 sub rsp,20h 00007ff9`05c180da 33db xor ebx,ebx 00007ff9`05c180dc 488bfa mov rdi,rdx 00007ff9`05c180df 4885d2 test rdx,rdx 00007ff9`05c180e2 753a jne fhcfg!CDpScopeIterator::GetItem+0x4e (00007ff9`05c1811e) 00007ff9`05c180e4 488b0d5d9f0400 mov rcx,qword ptr [fhcfg!WPP_GLOBAL_Control (00007ff9`05c62048)] 00007ff9`05c180eb 488d05569f0400 lea rax,[fhcfg!WPP_GLOBAL_Control (00007ff9`05c62048)] 00007ff9`05c180f2 483bc8 cmp rcx,rax 00007ff9`05c180f5 7420 je fhcfg!CDpScopeIterator::GetItem+0x47 (00007ff9`05c18117) 00007ff9`05c180f7 f6411c01 test byte ptr [rcx+1Ch],1 00007ff9`05c180fb 741a je fhcfg!CDpScopeIterator::GetItem+0x47 (00007ff9`05c18117) 00007ff9`05c180fd 488b4910 mov rcx,qword ptr [rcx+10h] 00007ff9`05c18101 8d5742 lea edx,[rdi+42h] 00007ff9`05c18104 4c8d0dd5f0faff lea r9,[fhcfg!`string' (00007ff9`05bc71e0)] 00007ff9`05c1810b 4c8d054ef6faff lea r8,[fhcfg!WPP_60d49f496dd11a03f0fd8e5dc827deca_Traceguids (00007ff9`05bc7760)] 00007ff9`05c18112 e871deffff call fhcfg!WPP_SF_s (00007ff9`05c15f88) 00007ff9`05c18117 b857000780 mov eax,80070057h 00007ff9`05c1811c eb4a jmp fhcfg!CDpScopeIterator::GetItem+0x98 (00007ff9`05c18168) 00007ff9`05c1811e 395960 cmp dword ptr [rcx+60h],ebx 00007ff9`05c18121 7410 je fhcfg!CDpScopeIterator::GetItem+0x63 (00007ff9`05c18133) 00007ff9`05c18123 488b4140 mov rax,qword ptr [rcx+40h] 00007ff9`05c18127 483b4148 cmp rax,qword ptr [rcx+48h] 00007ff9`05c1812b 7410 je fhcfg!CDpScopeIterator::GetItem+0x6d (00007ff9`05c1813d) 00007ff9`05c1812d 488d4838 lea rcx,[rax+38h] 00007ff9`05c18131 eb15 jmp fhcfg!CDpScopeIterator::GetItem+0x78 (00007ff9`05c18148) 00007ff9`05c18133 488b4150 mov rax,qword ptr [rcx+50h] 00007ff9`05c18137 483b4158 cmp rax,qword ptr [rcx+58h] 00007ff9`05c1813b 7507 jne fhcfg!CDpScopeIterator::GetItem+0x74 (00007ff9`05c18144) 00007ff9`05c1813d bb90040780 mov ebx,80070490h 00007ff9`05c18142 eb22 jmp fhcfg!CDpScopeIterator::GetItem+0x96 (00007ff9`05c18166) 00007ff9`05c18144 488d4810 lea rcx,[rax+10h] <<<< rcx-10 == rax 00007ff9`05c18148 4883791808 cmp qword ptr [rcx+18h],8
Now we know that rcx was changed just once at the 00007ff9`05c18144 address. If we’ll examine the caller of this method we’ll see that rcx was populated from the stack with the pointer to an object of the IFhScopeIterator interface.
0:033> ub fhcpl!AddListItemsToExcludes+0x15a fhcpl!AddListItemsToExcludes+0x142: 00007ff9`196cb812 8bd8 mov ebx,eax 00007ff9`196cb814 85c0 test eax,eax 00007ff9`196cb816 7858 js fhcpl!AddListItemsToExcludes+0x1a0 (00007ff9`196cb870) 00007ff9`196cb818 754b jne fhcpl!AddListItemsToExcludes+0x195 (00007ff9`196cb865) 00007ff9`196cb81a 488b4c2440 mov rcx,qword ptr [rsp+40h] 00007ff9`196cb81f 488d542450 lea rdx,[rsp+50h] 00007ff9`196cb824 488b01 mov rax,qword ptr [rcx] 00007ff9`196cb827 ff5020 call qword ptr [rax+20h]
0:033> k L4 # Child-SP RetAddr Call Site 00 00000000`04ecdff0 00007ff9`196cb82a fhcfg!CDpScopeIterator::GetItem+0x78 01 00000000`04ece020 00007ff9`196cc30e fhcpl!AddListItemsToExcludes+0x15a 02 00000000`04ece060 00007ff9`196cd00a fhcpl!CExcludeFoldersPage::OnEvent+0x146 03 00000000`04ece0a0 00007ff9`1d1ec3c6 fhcpl!CHistoryVaultPage::OnEvent+0x26 ...
0:033> dps poi(00000000`04ece020+40) 00000000`106fc790 00007ff9`05bc2c88 fhcfg!ATL::CComObject<CDpScopeIterator>::`vftable' 00000000`106fc798 00000000`00000001 00000000`106fc7a0 ffffffff`ffffffff 00000000`106fc7a8 00000000`ffffffff 00000000`106fc7b0 00000000`00000000 00000000`106fc7b8 00000000`00000000 00000000`106fc7c0 00000000`020007d0 00000000`106fc7c8 00000000`10790001 00000000`106fc7d0 00000000`00000000 00000000`106fc7d8 00000000`00000000 00000000`106fc7e0 0055005c`003a0043 <<<< rcx+50 00000000`106fc7e8 00000000`106dc1c0 00000000`106fc7f0 00000000`00000000 00000000`106fc7f8 80002200`4cb849aa 00000000`106fc800 00000000`106fcaa0 00000000`106fc808 00000000`106fcb80
To see what data should be in [rcx+50] location, let’s launch debugger and set a breakpoint on fhcpl!AddListItemsToExcludes+0x11c function.
0:011> bp fhcpl!AddListItemsToExcludes+0x11c fhcpl!AddListItemsToExcludes+0x11c: 00007ffe`045cb7ec 48895c2410 mov qword ptr [rsp+10h],rbx ss:00000000`02cae258=0000000005421c60 00007ffe`045cb7f1 55 push rbp 00007ffe`045cb7f2 56 push rsi 00007ffe`045cb7f3 57 push rdi 00007ffe`045cb7f4 4883ec20 sub rsp,20h 00007ffe`045cb7f8 488bf1 mov rsi,rcx 00007ffe`045cb7fb 488b09 mov rcx,qword ptr [rcx] ds:00000000`02cae298=0000000000aba960 00007ffe`045cb7fe 8bfa mov edi,edx 00007ffe`045cb800 488b01 mov rax,qword ptr [rcx] ds:00000000`00aba960={fhcfg!ATL::CComObject<CDpConfigMgr>::`vftable' (00007ffd`ef502a78)} 00007ffe`045cb803 448bc2 mov r8d,edx 00007ffe`045cb806 4c8d4c2440 lea r9,[rsp+40h] <<<< Will hold the pointer to an object of the IFhScopeIterator interface 00007ffe`045cb80b 33d2 xor edx,edx 00007ffe`045cb80d ff5038 call qword ptr [rax+38h] ds:00007ffd`ef502ab0={fhcfg!CDpConfigMgr::GetIncludeExcludeRules (00007ffd`ef558cfc)} 00007ffe`045cb810 33ed xor ebp,ebp 0:004> dps poi(@rsp+40) 00000000`04c64ba0 00007ffd`ef502c88 fhcfg!ATL::CComObject<CDpScopeIterator>::`vftable' 00000000`04c64ba8 00000000`00000001 00000000`04c64bb0 ffffffff`ffffffff 00000000`04c64bb8 00000000`ffffffff 00000000`04c64bc0 00000000`00000000 00000000`04c64bc8 00000000`00000000 00000000`04c64bd0 00000000`020007d0 00000000`04c64bd8 00000000`04c60001 00000000`04c64be0 00000000`00000000 00000000`04c64be8 00000000`00000000 00000000`04c64bf0 00000000`04c61700 <<<< This is the head of the doubly linked list of the excluded libraries (LIST_ENTRY structure). 00000000`04c64bf8 00000000`04c616c0 00000000`04c64c00 00000000`00000000 00000000`04c64c08 80002100`354bc912 00000000`04c64c10 00000000`04c649e0 00000000`04c64c18 00000000`04c64740 0:004> dl poi(poi(@rsp+40)+50) 10 2 <<<< The linked list. 00000000`04c61700 00000000`04c61b00 00000000`04c616c0 00000000`04c61b00 00000000`04c61400 00000000`04c61700 00000000`04c61400 00000000`04c61680 00000000`04c61b00 00000000`04c61680 00000000`04c616c0 00000000`04c61400 00000000`04c616c0 00000000`04c61700 00000000`04c61680 0:004> !list -x "du poi(@$extret+10)" poi(poi(@rsp+40)+50) <<<< GUIDs of the libraries in the list. 00000000`04c63940 "*7b0db17d-9cd2-4a93-9733-46cc890" 00000000`04c63980 "22e7c" 00000000`04c639a0 "*2112ab0a-c86a-4ffe-a368-0de96e4" 00000000`04c639e0 "7012e" 00000000`04c63a00 "*a990ae9f-a03b-4e80-94bc-9912d75" 00000000`04c63a40 "04104" 00000000`04c63a60 "*491e922f-5643-4af4-a7eb-4e7a138" 00000000`04c63aa0 "d8174" 0068006f`004a005c "????????????????????????????????"
Let's set a breakpoint for write access on the head of the list. The breakpoint hit in the fhcfg!CDpScopeIterator::MoveToNextItem method but we can see that this method is not a culprit because it takes the wrong value from the first entry of the linked list and saves it into the head of the list.
0:004> ba w8 poi(@rsp+40)+50 0:004> ub . fhcfg!CDpScopeIterator::MoveToNextItem+0x50: 00007ffd`ef558098 7508 jne fhcfg!CDpScopeIterator::MoveToNextItem+0x5a (00007ffd`ef5580a2) 00007ffd`ef55809a 41b890040780 mov r8d,80070490h 00007ffd`ef5580a0 eb23 jmp fhcfg!CDpScopeIterator::MoveToNextItem+0x7d (00007ffd`ef5580c5) 00007ffd`ef5580a2 488b4150 mov rax,qword ptr [rcx+50h] 00007ffd`ef5580a6 418bd0 mov edx,r8d 00007ffd`ef5580a9 41b890040780 mov r8d,80070490h 00007ffd`ef5580af 488b08 mov rcx,qword ptr [rax] 00007ffd`ef5580b2 49894950 mov qword ptr [r9+50h],rcx 0:004> r rax=0000000004c61700 rbx=0000000000000000 rcx=0055005c003a0043 rdx=0000000000000000 rsi=0000000002cae298 rdi=0000000000000001 rip=00007ffdef5580b6 rsp=0000000002cae208 rbp=0000000000000000 r8=0000000080070490 r9=0000000004c64ba0 r10=00007ffe1e8538d0 r11=0000000002cae120 r12=0000000000000000 r13=0000000000040001 r14=0000000000040000 r15=0000000000000007 iopl=0 nv up ei pl nz na pe nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202 fhcfg!CDpScopeIterator::MoveToNextItem+0x6e: 00007ffd`ef5580b6 498b4958 mov rcx,qword ptr [r9+58h] ds:00000000`04c64bf8=0000000004c616c0 0:004> dps 0000000004c64ba0 00000000`04c64ba0 00007ffd`ef502c88 fhcfg!ATL::CComObject<CDpScopeIterator>::`vftable' 00000000`04c64ba8 00000000`00000001 00000000`04c64bb0 ffffffff`ffffffff 00000000`04c64bb8 00000000`ffffffff 00000000`04c64bc0 00000000`00000000 00000000`04c64bc8 00000000`00000000 00000000`04c64bd0 00000000`020007d0 00000000`04c64bd8 00000000`04c60001 00000000`04c64be0 00000000`00000000 00000000`04c64be8 00000000`00000000 00000000`04c64bf0 0055005c`003a0043 <<<< r9+50h 00000000`04c64bf8 00000000`04c616c0 00000000`04c64c00 00000000`00000000 00000000`04c64c08 88002100`354bc912 00000000`04c64c10 00000000`04c62550 00000000`04c64c18 00000000`04c64200 0:004> k L4 Child-SP RetAddr Call Site 00000000`02cae208 00007ffe`045cb854 fhcfg!CDpScopeIterator::MoveToNextItem+0x6e 00000000`02cae210 00007ffe`045cc30e fhcpl!AddListItemsToExcludes+0x184 00000000`02cae250 00007ffe`045cd00a fhcpl!CExcludeFoldersPage::OnEvent+0x146 00000000`02cae290 00007ffe`1a14c3c6 fhcpl!CHistoryVaultPage::OnEvent+0x26
Now let’s set a breakpoint for write access on the first entry in the list.
0:004> ba w8 poi(poi(@rsp+40)+50) 0:004> dps poi(@rsp+40) 00000000`05523ef0 00007ffd`ef502c88 fhcfg!ATL::CComObject<CDpScopeIterator>::`vftable' 00000000`05523ef8 00000000`00000001 00000000`05523f00 ffffffff`ffffffff 00000000`05523f08 00000000`ffffffff 00000000`05523f10 00000000`00000000 00000000`05523f18 00000000`00000000 00000000`05523f20 00000000`020007d0 00000000`05523f28 00000000`05520001 00000000`05523f30 00000000`00000000 00000000`05523f38 00000000`00000000 00000000`05523f40 00000000`05521600 00000000`05523f48 00000000`05521b00 00000000`05523f50 00000001`00000000 00000000`05523f58 80000400`4ddf0f31 00000000`05523f60 00000000`05523f60 00000000`05523f68 00000000`05523f60 0:004> g Breakpoint 1 hit fhcfg!std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >::_Copy+0x146: 00007ffd`ef560a42 4883c460 add rsp,60h 0:004> ub . fhcfg!std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >::_Copy+0x125: 00007ffd`ef560a21 488b0b mov rcx,qword ptr [rbx] 00007ffd`ef560a24 ff15467e0400 call qword ptr [fhcfg!_imp_??3YAXPEAXZ (00007ffd`ef5a8870)] 00007ffd`ef560a2a 4c8933 mov qword ptr [rbx],r14 00007ffd`ef560a2d 48897b18 mov qword ptr [rbx+18h],rdi 00007ffd`ef560a31 4c897b10 mov qword ptr [rbx+10h],r15 00007ffd`ef560a35 4883ff08 cmp rdi,8 00007ffd`ef560a39 490f43de cmovae rbx,r14 00007ffd`ef560a3d 664289347b mov word ptr [rbx+r15*2],si 0:004> r rax=0000000005521600 rbx=0000000005521600 rcx=0000000000000200 rdx=0000000000060011 rsi=0000000000000000 rdi=0000000000000017 rip=00007ffdef560a42 rsp=000000000310db00 rbp=0000000000000000 r8=0000000000000005 r9=0000000000000007 r10=00000000055213b0 r11=0000000000000000 r12=00000000055222e8 r13=000000000310dcf0 r14=0000000005521600 r15=0000000000000000 iopl=0 nv up ei pl nz ac po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000216 fhcfg!std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >::_Copy+0x146: 00007ffd`ef560a42 4883c460 add rsp,60h 0:004> k Child-SP RetAddr Call Site 00000000`0310db00 00007ffd`ef5607d8 fhcfg!std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >::_Copy+0x146 00000000`0310db90 00007ffd`ef576846 fhcfg!std::basic_string<unsigned short,std::char_traits<unsigned short>,std::allocator<unsigned short> >::assign+0x84 00000000`0310dbd0 00007ffd`ef572526 fhcfg!DpConfigHelper::AddFolder+0x12e 00000000`0310dcb0 00007ffd`ef5729fb fhcfg!DpConfigHelper::AddExcludeFolder+0x106 00000000`0310dd50 00007ffd`ef55c933 fhcfg!DpConfigHelper::RefreshCurrentExcludes+0xef 00000000`0310de40 00007ffd`ef558c8a fhcfg!CDpConfigMgr::AddRemoveLibraryExclude+0x97 00000000`0310de70 00007ffe`045cb7ac fhcfg!CDpConfigMgr::AddRemoveExcludeRule+0x1e6 00000000`0310df00 00007ffe`045cc32d fhcpl!AddListItemsToExcludes+0xdc 00000000`0310e1d0 00007ffe`045cd00a fhcpl!CExcludeFoldersPage::OnEvent+0x165 00000000`0310e210 00007ffe`1a14c3c6 fhcpl!CHistoryVaultPage::OnEvent+0x26
Someone freed the memory of the item because the fhcfg!std::basic_string method simply copies the string into the memory allocated at the same address. Here is the method that freed the memory.
0:004> uf /c fhcfg!CDpConfigMgr::AddRemoveLibraryExclude fhcfg!CDpConfigMgr::AddRemoveLibraryExclude (00007ffd`ef55c89c) fhcfg!CDpConfigMgr::AddRemoveLibraryExclude+0x28 (00007ffd`ef55c8c4): call to fhcfg!DpConfigHelper::AddExcludeLibrary (00007ffd`ef57262c) fhcfg!CDpConfigMgr::AddRemoveLibraryExclude+0x5f (00007ffd`ef55c8fb): call to fhcfg!DpConfigHelper::RemoveExcludeLibrary (00007ffd`ef572794) fhcfg!CDpConfigMgr::AddRemoveLibraryExclude+0x92 (00007ffd`ef55c92e): call to fhcfg!DpConfigHelper::RefreshCurrentExcludes (00007ffd`ef57290c) fhcfg!CDpConfigMgr::AddRemoveLibraryExclude+0xcd (00007ffd`ef55c969): call to fhcfg!WPP_SF_d (00007ffd`ef555f04)
So, the File History APIs work correctly and the flaw is in the fhcpl!AddListItemsToExcludes+0x11c function which removes items from an exclusion list. That's how the function removes items:
#include <fhcfg.h> VOID RemoveAllRules( IFhConfigMgr *ConfigMgr, FH_PROTECTED_ITEM_CATEGORY Category ) { HRESULT hr; IFhScopeIterator *ScopeIterator = NULL; hr = ConfigMgr->GetIncludeExcludeRules(FALSE, Category, &ScopeIterator); if (SUCCEEDED(hr)) { BSTR Item = NULL; do { // // Get the name of the item. // Here will be an access violation exception after one or more iterations. // Wrong pointer in the list head (LIST_ENTRY.Flink) in the ScopeIterator object. // hr = ScopeIterator->GetItem(&Item); if (SUCCEEDED(hr)) { // // 1. Removes the item from the doubly linked list // 2. Frees the memory of the item. // 3. Allocates new memory for its own use (sometimes memory is allocated at the same // address where was the removed item) // 4. Overwrites the old data. // hr = ConfigMgr->AddRemoveExcludeRule(FALSE, Category, Item); if (SUCCEEDED(hr)) { // // Takes the wrong pointer from the LIST_ENTRY.Flink of the removed item and // saves it in the list head (LIST_ENTRY.Flink) in the ScopeIterator object. // hr = ScopeIterator->MoveToNextItem(); } SysFreeString(Item); } } while (SUCCEEDED(hr)); ScopeIterator->Release(); } } int _tmain(int argc, _TCHAR* argv[]) { HRESULT hr; IFhConfigMgr *ConfigMgr = NULL; CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); hr = CoCreateInstance(__uuidof(FhConfigMgr), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&ConfigMgr)); if (SUCCEEDED(hr)) { hr = ConfigMgr->LoadConfiguration(); if (SUCCEEDED(hr)) { RemoveAllRules(ConfigMgr, FH_FOLDER); RemoveAllRules(ConfigMgr, FH_LIBRARY); //AddListItemsToExcludes(...); ConfigMgr->SaveConfiguration(); } ConfigMgr->Release(); } CoUninitialize(); return 0; }
As a temporary solution, I wrote a tool for adding to or removing from Excluded folders and libraries. You can download it from here.