FltSetInformationFile succeeded but no hard link created

Hi guys,

I wrote a mini filter driver in Win 7 to redirect file I/Os from "C:" to “D:\Vm\C” directory, everything worked just fine, until yesterday I encountered a failure(STATUS_NAME_NOT_FOUND) during installing Windows update KB file . However, the kb file could be installed correctly if my driver was unloaded.

After debugging I found that it’s the “TrustInstaller.exe” in Win 7, which was responsible for installing the kb file, returned the STATUS_NAME_NOT_FOUND error. Its workflow was as following:

  1. Do someting necessary to verify KB and extract the dll files to “C:\Windows\WinSxS” folder;
  2. Create a hard link named ?c:\windows\system32\api-ms-win-core-file-l1-2-0.dll ? to file “C:\Windows\WinSxS\amd64_3ware.inf.resources_31bf3856ad364e35_6.3.9600.16384_en-us_36411501bece1b66\api-ms-win-core-file-l1-2-0.dll”.

------> It eventually called ZwSetInformationFile with FileLinkInformation class, the call returned STATUS_SUCCESS;

  1. Open the hard link ?c:\windows\system32\api-ms-win-core-file-l1-2-0.dll ? (return STATUS_SUCCESS).

The above process worked if my driver was unloaded. However, with my driver loaded, the workflow would be:

  1. Do someting necessary to verify KB and extract the dll files to “D:\Vm\C\Windows\WinSxS” folder;
  2. Create a hardlink named ?D:\Vm\C\windows\system32\api-ms-win-core-file-l1-2-0.dll ? to file “D:\Vm\C\Windows\WinSxS\amd64_3ware.inf.resources_31bf3856ad364e35_6.3.9600.16384_en-us_36411501bece1b66\api-ms-win-core-file-l1-2-0.dll”;

------> It eventually called FltSetInformationFile with FileLinkInformation class, and since I have munged the hard link name in LinkInfo structure from C:\xxx to D:\Vm\C\xxx,
the FltSetInformationFile call would return STATUS_SUCCESS. However, the hard link ?D:\Vm\C\windows\system32\api-ms-win-core-file-l1-2-0.dll ? was not created as expected.

  1. Open the hard link ?D:\Vm\C\windows\system32\api-ms-win-core-file-l1-2-0.dll ? (It returned STATUS_NAME_NOT_FOUND -----> Error).

More weird is, with my driver loaded, I could create the hard link successfully by run “mklink /h C:\Windows\xxx C:\Windows\WinSxS\xxx” in cmd.exe, which followed the same workflow as above(that is, munged “C:\xxx” to “D:\Vm\C\xxx”). I also checked all parameters in FltSetInformationFile with WinDbg, they were the same.

My code snippet was posted below:

FLT_PREOP_CALLBACK_STATUS
PreSetLinkInformation (
Inout PFLT_CALLBACK_DATA Data,
In PCFLT_RELATED_OBJECTS FltObjects,
Flt_CompletionContext_Outptr PVOID *CompletionContext
)
{

// If the file was in our mapping
if(FilePath.InMapping) {

Status = NcConstructPath( PagedPool,
&HostLinkFilePath,
&MungedLinkFilePath,
);

if (!NT_SUCCESS( Status )) {
ReturnValue = FLT_PREOP_COMPLETE;
goto PreSetLinkInformationCleanup;
}
MungedLinkInfoSize = sizeof(FILE_LINK_INFORMATION) + MungedLinkFilePath.Length;
PMungedLinkInfo = ExAllocatePoolWithTag( PagedPool,
MungedLinkInfoSize,
NC_SET_LINK_BUFFER_TAG );

PMungedLinkInfo->ReplaceIfExists = OriginalLinkInfo->ReplaceIfExists;
PMungedLinkInfo->RootDirectory = NULL;
PMungedLinkInfo->FileNameLength = MungedLinkFilePath.Length;

RtlCopyMemory( &PMungedLinkInfo->FileName, MungedLinkFilePath.Buffer, MungedLinkFilePath.Length );

Status = FltSetInformationFile( FltObjects->Instance,
FltObjects->FileObject,
PMungedLinkInfo,
MungedLinkInfoSize,
FileLinkInformation );

if(!NT_SUCCESS(Status)) {
DbgPrint(“PreLink(%wZ -> %wZ) failed with 0x%x\n”,
&FltObjects->FileObject->FileName,
&MungedName,
Status);
}

ReturnValue = FLT_PREOP_COMPLETE;
goto PreSetLinkInformationCleanup;

//
}

So my question is, why the hard link was not created, even the FltSetInformationFile returned STATUS_SUCCESS?

Any help will be highly appreciated, Thanks!

Jason

SWAG: Are you handling transactions? A lot f the hard link work is done
under transactional control.

No, I just prepared callbacks for IRJ_CREATE_FILE, IRJ_SET_INFORMATION, …
So do you mean that even FltSetInformationFile for hard link returned success, but it failed somewhere later, and then roll back the transaction (remove the hard link created)?
What should I do to check whether it’s a transaction or not?

PS: The ProcMon captured below logs:

TrustedInstaller.exe (create hardlink. C:\Windows\System32\xxx.dll -> C:\Windows\WinSxS\xxx\xxx.dll)

  1. With my driver unloaded

CreateFile C:\Windows\WinSxS\xxx\xxx.dll Success Desired Access: Write Attributes
CreateFile C:\Windows\System32 Success Desired Access: Write Data/List Directory
QueryBasicInformation C:\Windows\WinSxS\xxx\xxx.dll Success CreateTime:xxx …
SetInformationFile C:\Windows\WinSxS\xxx\xxx.dll Success FileLinkInformation, ReplaceIfExists = True, ??\C:\Windows\System32\xxx.dll
CreateFile C:\Windows\System32\xxx.dll Success Desired Access:Read Attributes …

  1. With my driver loaded

CreateFile D:\Vm\C\Windows\WinSxS\xxx\xxx.dll Success Desired Access: Write Attributes
CreateFile D:\Vm\C\Windows\System32 Success Desired Access: Write Data/List Directory
QueryBasicInformation D:\Vm\C\Windows\WinSxS\xxx\xxx.dll Success CreateTime:xxx …
SetInformationFile D:\Vm\C\Windows\WinSxS\xxx\xxx.dll Success FileLinkInformation, ReplaceIfExists = True, ??\D:\Vm\C\Windows\System32\xxx.dll

CreateFile D:\Vm\C\Windows\System32\xxx.dll NAME_NOT_FOUND … <------ Failure here

if I run “mklink /h C:\Windows\System32\xxx.dll C:\Windows\WinSxS\xxx\xxx.dll” in cmd.exe to create hard link, the last action above would return Success

CreateFile D:\Vm\C\Windows\System32\xxx.dll Success …

Thanks,

Jason

> So do you mean that even FltSetInformationFile for hard link returned

success, but it failed somewhere later, and then roll back the
transaction (remove the hard link created)?

Or some such - the possibilities are endless.

What should I do to check whether it’s a transaction or not?

FltObjects carries some transactional information during (at least Create)
and I’m pretty sure that there is an Io call to get the transaction from the
FILE_OBJECT.

/R

Rod, you are right ! there is a transaction object in FltObjects->Transaction. However, I don’t know how to get the reason why the transaction failed? will keep root-causing…

Thanks,
Jason