阅读:2836回复:5
对WORD文档(.DOC )的写控制
请教高手:
我在filemon中对IRP_MJ_WRITE进行处理,可控制用记事本打开的TXT文件, 同样在IRP_MJ_WRITE中却不能控制WORD打开的.DOC 文档。观察了一下filemon, 感觉WORD 保存文件时,会产生临时文件,先将数据写入临时文件中成功后再进行改名操作 , 但同样的 我在IRP_MJ_SET_INFORMATION中控制改名操作,WORD 同样可以对写入的内容进行保存。 所以我现在无法控制WORD 的写操作。 我想请问各位高手如何实现对WORD文档只能读取但是不能修改其中的内容。 望各位高手能解答!!!! |
|
最新喜欢:ljmmar... |
沙发#
发布于:2003-12-15 21:08
我也遇到了这个问题!!那位高手知道呢???
|
|
板凳#
发布于:2003-12-16 21:23
文件系统版块,也讨论过,不过好象没什么效果。。。。。。
|
|
|
地板#
发布于:2003-12-17 13:50
word文档用的是重命名方式进行保存操作。所以还要判断IRP_MJ_SET_INFORMATION里的FileRenameInformation,它的目的文件是不是你要禁止写的文件。IRP_MJ_WRITE最好留着,win2k上的word好像会在重命名不成功时用它来写。
另,我有一次曾让word认为打开的文件是只读文件。我觉得那样最好。但我忘了是怎么做的了。 |
|
地下室#
发布于:2003-12-17 13:59
重命名中关键在于判断目的文件名是不是你要禁止保存的word文档。
你可以试一下下面的代码。我在NT、2K上试过。可以用。 typedef struct { BOOLEAN Replace; HANDLE RootDir; ULONG FileNameLength; WCHAR FileName[1]; } FILE_RENAME_INFORMATION, *PFILE_RENAME_INFORMATION; void processSimRename(char *destname,char * filename,PIRP irp,PFILE_RENAME_INFORMATION renameInfo) { WCHAR FileNameBuffer[MAXPATHLEN]; WCHAR * NewNameBuffer; WCHAR * prefix; ULONG prefixLength; ULONG length; length = 0; mbstowcs(FileNameBuffer,filename,strlen(filename)); prefix = wcsrchr(FileNameBuffer, (int) L\'\\\\\'); if (prefix == NULL) { // strcpy(destname,\"C:\\\\\"); return; } else { length = prefixLength = ((prefix - FileNameBuffer) + 1)* sizeof(WCHAR); } length += (wcslen(renameInfo->FileName) + 1) * sizeof(WCHAR); NewNameBuffer = ExAllocatePool(PagedPool, length/*, \"tset\"*/); if (!NewNameBuffer) { // ? no memory of any type? // strcpy(destname,\"D:\\\\\"); return ; } RtlZeroMemory(NewNameBuffer, length); (void) wcsncpy(NewNameBuffer, FileNameBuffer, prefixLength); wcscat(NewNameBuffer, renameInfo->FileName); //把wchar转化为char memset(destname,0,MAXPATHLEN); wcstombs(destname,NewNameBuffer,/*wcslen(NewNameBuffer)*/MAXPATHLEN); ExFreePool(NewNameBuffer); } void processFQRename(char *destname,PIRP irp,PIO_STACK_LOCATION irpSp,PFILE_RENAME_INFORMATION renameInfo) { WCHAR * NewNameBuffer; ULONG startOffset = 0; ULONG prependChars = 0; ULONG targetLength = 0; WCHAR DriveLetter=L\'C\';//问题:怎么得到目的盘符?10月14日 char tmpbuf[MAXPATHLEN]; if (renameInfo->FileName[0] != L\'\\\\\') { destname[0]=0; return; } if (0 == _wcsnicmp(L\"\\\\DosDevices\\\\\", renameInfo->FileName, 12)) { startOffset = 12; } else { //添加于12月1日,for \"\\??\\\" if(0==_wcsnicmp(L\"\\\\??\\\\\",renameInfo->FileName,4)) startOffset=4; else // prependChars = 2; } targetLength = (renameInfo->FileNameLength/sizeof(WCHAR))-startOffset + prependChars + 1; // make room for NULL too if (targetLength < 4) { // must be at least \"D:\\\" return; } NewNameBuffer = ExAllocatePool(PagedPool, targetLength * sizeof(WCHAR), ’tset’); if (NewNameBuffer == NULL) { destname[0]=0; return ; } if (prependChars) { NewNameBuffer[0] = DriveLetter; NewNameBuffer[1] = L\':\'; } // wcsncpy(NewNameBuffer,renameInfo->FileName,renameInfo->FileNameLength/sizeof(WCHAR)); wcsncpy(NewNameBuffer, &renameInfo->FileName[startOffset],targetLength-1); //把wchar 转换为char wcstombs(tmpbuf,NewNameBuffer,targetLength-1/*MAXPATHLEN*/); tmpbuf[targetLength-1]=0; ExFreePool(NewNameBuffer); if(0==_strnicmp(\"\\\\??\\\\\",tmpbuf,4)) { strcpy(destname,tmpbuf+4); } else strcpy(destname,tmpbuf); } void GetRenameDestName(char *destname,char * fn,PIRP Irp,PIO_STACK_LOCATION irpSp) { PFILE_RENAME_INFORMATION RenameInfo; RenameInfo = (PFILE_RENAME_INFORMATION) Irp- >AssociatedIrp.SystemBuffer; if (!irpSp->Parameters.SetFile.FileObject) { processSimRename(destname,fn,Irp,RenameInfo); } else { if (RenameInfo->RootDir == NULL) { processFQRename(destname,Irp, irpSp, RenameInfo); } else { strncpy(destname,fn,3); destname[3]=0; } } } 这段代码我也是从一个老外的文章了看来的。(经过了一些改动) |
|
5楼#
发布于:2007-01-05 17:06
to:guyu_susa
这样的通用性不好吧! 我也实现了,但是不是这样实现的!思路其实已经有了,只是大家要细心的去实现. 先将起属性该为只读,然后禁止其修改只读属性. 将属性该为只读和禁止修改属性都是在IRP_MJ_SET_INFORMATION里面,大家要注意的一点是在驱动里面要修改属性,首先要触发该历程,但是在当前层只能是手动出发(勾选只读的时候出发),要想通过驱动自动触发,只能触发下层,也就要构造IRP包了!至于禁止属性修改,就是禁止手动修改,因此在当前层驱动实现即可。 |
|
|