您的位置:首页 > 其它

文件系统驱动开发实例

2009-09-18 16:26 253 查看
文件系统驱动开发实例
本文将介绍一个文件系统开发的实例,这个实例的功能比较简单,仅供个人娱乐之用,请高手们笑而置之。
本例的基本功能是对目录的保护,就是对一个目录设置密码,使之不让访问,不过实现的方法是在底层判断,还是调试了好久呢。程序模块分为上层应用程序和下层驱动程序,上层是对一些设置数据的保存,下层就是过滤和判断。为了让程序再重启之后还有效,特意又加了一个服务来load设置。下面就来分享一下底层的code。
写过驱动的朋友都知道IRP_MJ_DEVICE_CONTROL吧,这里是上层对下层的一些设置,主要就是文件名,目录名,密码之类的。
NTSTATUS DeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);

NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
//ULONG OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
PSFILTER_DEVICE_EXTENSION DevExt = (PSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if(g_DeviceObject != DeviceObject)
{

IrpStack = IoGetCurrentIrpStackLocation(Irp);
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver( DevExt->NLExtHeader.AttachedToDeviceObject, Irp);
}

switch( IrpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_SETFILES:
{
PFILE_ELEMENT Buffer = (PFILE_ELEMENT)Irp->AssociatedIrp.SystemBuffer;
ULONG InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
PFILE_LIST pdElement;
PLIST_ENTRY pListEntry;
BOOLEAN bNewElement=TRUE;
if( (Buffer==0) || (InputLength < sizeof(FILE_ELEMENT)))
{
status = STATUS_INVALID_PARAMETER;
break;
}

if(!IsListEmpty(&FilterFileListHead))
for (pListEntry = FilterFileListHead.Flink; pListEntry != &FilterFileListHead; pListEntry = pListEntry->Flink)
{

pdElement = CONTAINING_RECORD(pListEntry, FILE_LIST, linkfield);
if (_wcsicmp(pdElement->fileElement.szFileName,Buffer->szFileName)==0)
{
bNewElement=FALSE;

break;
}

}
if (bNewElement)
{
PFILE_LIST pdElement = (PFILE_LIST) ExAllocatePool(NonPagedPool, sizeof(FILE_LIST));
RtlCopyMemory(&pdElement->fileElement,Buffer,sizeof(FILE_ELEMENT));
InsertTailList(&FilterFileListHead, &pdElement->linkfield);
KdPrint(("IOCTL_SETFILES--:%wZ",Buffer->szFileName));

}

status = STATUS_SUCCESS;
break;
}
case IOCTL_DELFILES:
{
PFILE_ELEMENT Buffer = (PFILE_ELEMENT)Irp->AssociatedIrp.SystemBuffer;
ULONG InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
PFILE_LIST pdElement;
PLIST_ENTRY pListEntry;
if( (Buffer==0) || (InputLength < sizeof(FILE_ELEMENT)))
{
status = STATUS_INVALID_PARAMETER;
break;
}

if(!IsListEmpty(&FilterFileListHead))
for (pListEntry = FilterFileListHead.Flink; pListEntry != &FilterFileListHead; pListEntry = pListEntry->Flink)
{

pdElement = CONTAINING_RECORD(pListEntry, FILE_LIST, linkfield);
if (_wcsicmp(pdElement->fileElement.szFileName,Buffer->szFileName)==0)
{
RemoveEntryList(pListEntry);
ExFreePool(pdElement);
break;
}
}
status = STATUS_SUCCESS;
break;
}
case IOCTL_SETFOLDERS:
{
PFILE_ELEMENT Buffer = (PFILE_ELEMENT)Irp->AssociatedIrp.SystemBuffer;
ULONG InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
PFILE_LIST pdElement;
PLIST_ENTRY pListEntry;
BOOLEAN bNewElement=TRUE;
if( (Buffer==0) || (InputLength < sizeof(FILE_ELEMENT)))
{
status = STATUS_INVALID_PARAMETER;
break;
}

if(!IsListEmpty(&FilterFolderListHead))
for (pListEntry = FilterFolderListHead.Flink; pListEntry != &FilterFolderListHead; pListEntry = pListEntry->Flink)
{

pdElement = CONTAINING_RECORD(pListEntry, FILE_LIST, linkfield);
if (_wcsicmp(pdElement->fileElement.szFileName,Buffer->szFileName)==0)
{
bNewElement=FALSE;
break;
}

}
if (bNewElement)
{
PFILE_LIST pdElement = (PFILE_LIST) ExAllocatePool(NonPagedPool, sizeof(FILE_LIST));
RtlCopyMemory(&pdElement->fileElement,Buffer,sizeof(FILE_ELEMENT));
InsertTailList(&FilterFolderListHead, &pdElement->linkfield);

status = STATUS_SUCCESS;
break;
}
case IOCTL_DELFOLDERS:
{
PFILE_ELEMENT Buffer = (PFILE_ELEMENT)Irp->AssociatedIrp.SystemBuffer;
ULONG InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
PFILE_LIST pdElement;
PLIST_ENTRY pListEntry;
if( (Buffer==0) || (InputLength < sizeof(FILE_ELEMENT)))
{
status = STATUS_INVALID_PARAMETER;
break;
}

if(!IsListEmpty(&FilterFolderListHead))
for (pListEntry = FilterFolderListHead.Flink; pListEntry != &FilterFolderListHead; pListEntry = pListEntry->Flink)
{

pdElement = CONTAINING_RECORD(pListEntry, FILE_LIST, linkfield);
if (_wcsicmp(pdElement->fileElement.szFileName,Buffer->szFileName)==0)
{
RemoveEntryList(pListEntry);
ExFreePool(pdElement);
break;
}
}
status = STATUS_SUCCESS;
break;
}
case IOCTL_TEMPDEFILES:
{
ULONG InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
TEMPDECODE *Code = (TEMPDECODE*)Irp->AssociatedIrp.SystemBuffer;
if( (Code==0) || (InputLength < sizeof(TEMPDECODE)))
{
status = STATUS_INVALID_PARAMETER;
break;
}
wcscpy(TempCode.szFileName,Code->szFileName);
wcscpy(TempCode.szPwsd,Code->szPwsd);
status = STATUS_SUCCESS;
break;

}

default:
status = STATUS_INVALID_DEVICE_REQUEST;
}

Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return status;

}
对文件的拦截主要是下面的code:
NTSTATUS
SfCreate (
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp
){
/*省略*/
if(FileObject->FileName.Buffer!=NULL)
{
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
PLIST_ENTRY pListEntry;
PFILE_LIST pdElement;
UNICODE_STRING DosName;
UNICODE_STRING Path;
WCHAR TempBuf[256];
WCHAR szPath[256]=L"";
if(!IsListEmpty(&FilterFileListHead))
{
if (FileObject->DeviceObject!=NULL)
{
IoVolumeDeviceToDosName(FileObject->DeviceObject,&DosName);
RtlInitEmptyUnicodeString(&Path,TempBuf,256*sizeof(WCHAR));
RtlCopyUnicodeString(&Path,&DosName);
RtlAppendUnicodeStringToString(&Path,&FileObject->FileName);
wcscpy(szPath,Path.Buffer);
// KdPrint(("%wZ",&(FileObject->FileName)));
{
ULONG CreateDisposition = (irpSp->Parameters.Create.Options>> 24) & 0x000000ff;
if((CreateDisposition==FILE_OPEN||CreateDisposition==FILE_OPEN_IF
||CreateDisposition==FILE_OVERWRITE))
{

}
}

{
for (pListEntry = FilterFileListHead.Flink; pListEntry != &FilterFileListHead; pListEntry = pListEntry->Flink)
{
pdElement = CONTAINING_RECORD(pListEntry, FILE_LIST, linkfield);
if (_wcsicmp(pdElement->fileElement.szFileName,szPath)==0)
{

{
if((!(FILE_DELETE_ON_CLOSE&irpSp->Parameters.Create.Options)||
!(FILE_OPEN_REPARSE_POINT&irpSp->Parameters.Create.Options)))
{
if (_wcsicmp(pdElement->fileElement.szFileName,TempCode.szFileName)==0&&
_wcsicmp(pdElement->fileElement.szPwsd,TempCode.szPwsd)==0)
{
LARGE_INTEGER duetime;
KdPrint(("KeSetTimer"));

duetime.QuadPart = -10000*1000*10;
// duetime=RtlConvertLongToLargeInteger(100*-50);
KeSetTimer(&Timer, duetime,&Dpc);

break;
}
if (DosName.Buffer!=NULL)
ExFreePool(DosName.Buffer);
Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;

}
}

}
}

}//endif
if (DosName.Buffer!=NULL)
ExFreePool(DosName.Buffer);
}
}

}
}
还有就是对目录的过滤部分,其实和文件的是一样的,由于代码太长就不再写了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: