悲剧膜拜一句话刷新缓存
前两天苦恼于如何刷新缓存,本来打算按照正常思路直接找CcFlushxx和MmFlushXX的参数,也就是遍历CcVACBs,尚未尝试不知是否可行之际无意发现Azy大牛博客上最后一篇文章写得一句话刷新缓存。膜拜之,我思路还是太窄了~
HANDLE hFile = CreateFile(L"\\\\.\\C:", GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
先用sudami的工具在磁盘级删除了一个文件,然后运行以下代码
HANDLE hFile = CreateFile(L"\\\\.\\C:", GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
printf("Finish! handle is 0x%x\n",hFile);
printf("%d\n",GetLastError());
运行后明显停滞了一会儿,然后返回错误码
ERROR_SHARING_VIOLATION 32
The process cannot access the file because it is being used by another process.
D:\WinDDK\6001.18002\Tools\other\i386>winERROR 32
32 ERROR_SHARING_VIOLATION <--> 0xc0000043 STATUS_SHARING_VIOLATION
再用资源管理器一看,文件果然没了~~
弱小的心灵受到了严重打击。于是研究了一下。
把上面代码加上FILE_SHARE_WRITE标记,就刷不上了,看来问题就是在dwShareMode这个参数上。
CreateFile的流程前两天记录过了。。从CreateFile一路检查到IopParseDevice,都没发现对dwShareMode有任何处理,先是openPacket->ShareAccess = (USHORT) ShareAccess 进入对象管理器,
然后跟着 irpSp->Parameters.Create.ShareAccess = op->ShareAccess; 发出Irp
前两天苦恼于如何刷新缓存,本来打算按照正常思路直接找CcFlushxx和MmFlushXX的参数,也就是遍历CcVACBs,尚未尝试不知是否可行之际无意发现Azy大牛博客上最后一篇文章写得一句话刷新缓存。膜拜之,我思路还是太窄了~
HANDLE hFile = CreateFile(L"\\\\.\\C:", GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
先用sudami的工具在磁盘级删除了一个文件,然后运行以下代码
HANDLE hFile = CreateFile(L"\\\\.\\C:", GENERIC_WRITE|GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
printf("Finish! handle is 0x%x\n",hFile);
printf("%d\n",GetLastError());
运行后明显停滞了一会儿,然后返回错误码
ERROR_SHARING_VIOLATION 32
The process cannot access the file because it is being used by another process.
D:\WinDDK\6001.18002\Tools\other\i386>winERROR 32
32 ERROR_SHARING_VIOLATION <--> 0xc0000043 STATUS_SHARING_VIOLATION
再用资源管理器一看,文件果然没了~~
弱小的心灵受到了严重打击。于是研究了一下。
把上面代码加上FILE_SHARE_WRITE标记,就刷不上了,看来问题就是在dwShareMode这个参数上。
CreateFile的流程前两天记录过了。。从CreateFile一路检查到IopParseDevice,都没发现对dwShareMode有任何处理,先是openPacket->ShareAccess = (USHORT) ShareAccess 进入对象管理器,
然后跟着 irpSp->Parameters.Create.ShareAccess = op->ShareAccess; 发出Irp
从NT4 的NTFS中可以看到,(注释翻译的很矬。。)
NtfsFsdCreate:
if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_DASD_OPEN )) {
Status = NtfsCommonVolumeOpen( IrpContext, Irp );
NtfsCommonVolumeOpen:
if (!FlagOn( IrpSp->Parameters.Create.ShareAccess,
FILE_SHARE_WRITE | FILE_SHARE_DELETE ))
{
//
// Do a quick test of the volume cleanup count if this opener won't
// share with anyone. We can safely examine the cleanup count without
// further synchronization because we are guaranteed to have the
// Vcb exclusive at this point.
//
//没有设置写和删除的共享位,要快速检测卷的CleanupCount
//我们不需要同步处理就可以安全测试这个计数,因为在这时我们能保证VBP独占?
//CleanupCount 是未清理的句柄计数,如果有的话表明被别人打开了。
if (!FlagOn( IrpSp->Parameters.Create.ShareAccess, FILE_SHARE_READ) &&
Vcb->CleanupCount != 0)
{
//没有共享读,直接返回STATUS_SHARING_VIOLATION
try_return( Status = STATUS_SHARING_VIOLATION );
}
//
// Go ahead and flush and purge the volume. Then test to see if all
// of the user file objects were closed.
//
//刷新卷,测试是否所有的用户态文件对象都关闭了
Status = NtfsFlushVolume( IrpContext, Vcb, TRUE, TRUE, TRUE, FALSE );
//
// If the flush and purge was successful but there are still file objects
// that block this open it is possible that the FspClose thread is
// blocked behind the Vcb. Drop the Fcb and Vcb to allow this thread
// to get in and then reacquire them. This will give this Dasd open
// another chance to succeed on the first try.
//
//如果刷新 清理卷 依然后文件对象阻碍我们打开,FIXME:可能是 FspClose 线程在VCB之后被阻碍?
//释放FCB VCB ,执行线程并重新获得XCB。这回有第二次机会去打开?
SharingViolation = FALSE;
if (FlagOn( IrpSp->Parameters.Create.ShareAccess, FILE_SHARE_READ)) {
if (Vcb->ReadOnlyCloseCount != (Vcb->CloseCount - Vcb->SystemFileCloseCount)) {
SharingViolation = TRUE;
}
} else if (Vcb->CloseCount != Vcb->SystemFileCloseCount) {
SharingViolation = TRUE;
}
。。。。
后面还有一大堆操作来尝试让这次irp成功,当然了,是成功不了的。。
在这里调用了NtfsFlushVolume,晕,以前我都没发现这个函数。。XP下似乎复杂了,不过从IDA来看 ,对于dwShareMode的检查和调用NtfsFlushVolume并没有变咧。。
额~~~去搞Hard Link 和Junction去了….