能力值:
( LV2,RANK:10 )
|
-
-
2 楼
用FltCreateFile / FltReadFIle / FltWriteFile
|
能力值:
( LV3,RANK:20 )
|
-
-
3 楼
tsoo
用FltCreateFile / FltReadFIle / FltWriteFile
我用的就是这呀
|
能力值:
( LV3,RANK:20 )
|
-
-
4 楼
VOID StartThread1(COPYTHREAD Copy)
{
NTSTATUS status = STATUS_SUCCESS;
HANDLE hThread = NULL;
KEVENT kEvent = {0};
// KdPrint(("jinle \n"));
//初始化参数
KeInitializeEvent(&kEvent,SynchronizationEvent,FALSE);
Copy.PKE = &kEvent;
// KdPrint(("Copy.PKE \n"));
status = PsCreateSystemThread(&hThread, //创建新线程
0,
NULL,
NULL,//NtCurrentProcess(),线程所在地址空间的进程的handle
NULL,
(PKSTART_ROUTINE)ThreadProc1,
(PVOID)&Copy); //PVOID StartContext 对应ThreadProc中的参数
if (!NT_SUCCESS(status))
{
KdPrint(("创建失败 \n"));
ZwClose(hThread);
return ;
}
KdPrint(("创建成功 \n"));
//等待线程返回
KeWaitForSingleObject(&kEvent,Executive,KernelMode,FALSE,NULL);
ZwClose(hThread);
return ;
}
VOID ThreadProc1(IN PVOID pContext)
{
PCOPYTHREAD copyThread;
copyThread = (PCOPYTHREAD)pContext;
dfDeleteDirectory(copyThread->Data,copyThread->FltObjects,L"\\??\\d:\\Backup");
KeSetEvent(copyThread->PKE,IO_NO_INCREMENT,FALSE);
KdPrint(("线程函数结束\n"));
PsTerminateSystemThread(STATUS_SUCCESS);
return ;
}
NTSTATUS
dfDeleteDirectory(PFLT_CALLBACK_DATA Data,PCFLT_RELATED_OBJECTS FltObjects,const WCHAR * directory)
{
OBJECT_ATTRIBUTES objAttributes = { 0 };
IO_STATUS_BLOCK iosb = { 0 };
HANDLE handle = NULL;
FILE_DISPOSITION_INFORMATION disInfo = { 0 };
PVOID buffer = NULL;
ULONG bufferLength = 0;
BOOLEAN restartScan = FALSE;
PFILE_DIRECTORY_INFORMATION dirInfo = NULL;
PWSTR nameBuffer = NULL; //记录文件夹
UNICODE_STRING nameString = { 0 };
NTSTATUS status = 0;
LIST_ENTRY listHead = { 0 }; //链表,用来存放删除过程中的目录
PFILE_LIST_ENTRY tmpEntry = NULL; //链表结点
PFILE_LIST_ENTRY preEntry = NULL;
UNICODE_STRING uDirName = { 0 };
RtlInitUnicodeString(&uDirName, directory);
nameBuffer = (PWSTR)ExAllocatePoolWithTag(NonPagedPool, uDirName.Length + sizeof(WCHAR), 'DRID');
if (!nameBuffer)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
tmpEntry = (PFILE_LIST_ENTRY)ExAllocatePoolWithTag(NonPagedPool, sizeof(FILE_LIST_ENTRY), 'DRID');
if (!tmpEntry)
{
ExFreePool(nameBuffer);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(nameBuffer, uDirName.Buffer, uDirName.Length);
nameBuffer[uDirName.Length / sizeof(WCHAR)] = L'\0';
InitializeListHead(&listHead); //初始化链表
tmpEntry->NameBuffer = nameBuffer;
InsertHeadList(&listHead, &tmpEntry->Entry); //将要删除的文件夹首先插入链表
//listHead里初始化为要删除的文件夹。
//之后遍历文件夹下的文件和目录,判断是文件,则立即删除;判断是目录,则放进listHead里面
//每次都从listHead里拿出一个目录来处理
while (!IsListEmpty(&listHead))
{
//先将要删除的文件夹和之前打算删除的文件夹比较一下,如果从链表里取下来的还是之前的Entry,表明没有删除成功,说明里面非空
//否则,已经成功删除,不可能是它自身;或者还有子文件夹,在前面,也不可能是它自身。
tmpEntry = (PFILE_LIST_ENTRY)RemoveHeadList(&listHead);
if (preEntry == tmpEntry)
{
status = STATUS_DIRECTORY_NOT_EMPTY;
break;
}
preEntry = tmpEntry;
InsertHeadList(&listHead, &tmpEntry->Entry); //放进去,等删除了里面的内容,再移除。如果移除失败,则说明还有子文件夹或者目录非空
RtlInitUnicodeString(&nameString, tmpEntry->NameBuffer);
InitializeObjectAttributes(&objAttributes, &nameString,
OBJ_CASE_INSENSITIVE, NULL, NULL);
//打开文件夹,进行查询
status = FltCreateFile(
FltObjects->Filter,
NULL,
&handle,
DELETE, //开始写的所有会失败
&objAttributes,
&iosb,
NULL,
0,
0,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0,
0);
if (!NT_SUCCESS(status))
{
KdPrint(("2 FltCreateFile(%ws) failed(%x)\n", tmpEntry->NameBuffer, status));
// KdPrint(("2ZwCreateFilefailed(%x)\n", status));
break;
}
//从第一个扫描
restartScan = TRUE;
PFILE_OBJECT fileObject = NULL;
while (TRUE)
{
buffer = NULL;
bufferLength = 64;
status = STATUS_BUFFER_OVERFLOW;
while ((status == STATUS_BUFFER_OVERFLOW) || (status == STATUS_INFO_LENGTH_MISMATCH))
{
if (buffer)
{
ExFreePool(buffer);
}
bufferLength *= 2;
buffer = ExAllocatePoolWithTag(NonPagedPool, bufferLength, 'DRID');
if (!buffer)
{
KdPrint(("ExAllocatePool failed\n"));
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
// 通过文件句柄得到文件对象传给FltQueryDirectoryFile
status = ObReferenceObjectByHandle(handle, 0, NULL, KernelMode,
reinterpret_cast<void **>(&fileObject),
NULL);
if (!NT_SUCCESS(status)) {
KdPrint(("ObReferenceObjectByHandle 1 fail \n"));
}
status = FltQueryDirectoryFile(FltObjects->Instance,
fileObject,
buffer,
bufferLength,
FileDirectoryInformation,
FALSE,
NULL,
restartScan,
NULL);
if (fileObject) {
ObDereferenceObject(fileObject);
}
}
if (status == STATUS_NO_MORE_FILES)
{
ExFreePool(buffer);
status = STATUS_SUCCESS;
break;
}
restartScan = FALSE;
if (!NT_SUCCESS(status))
{
KdPrint(("FltQueryDirectoryFile(%ws) failed(%x),\n", tmpEntry->NameBuffer, status));
if (buffer)
{
ExFreePool(buffer);
}
break;
}
dirInfo = (PFILE_DIRECTORY_INFORMATION)buffer;
nameBuffer = (PWSTR)ExAllocatePoolWithTag( NonPagedPool,
wcslen(tmpEntry->NameBuffer) * sizeof(WCHAR) + dirInfo->FileNameLength + 4, 'DRID');
if (!nameBuffer)
{
KdPrint(("ExAllocatePool failed\n"));
ExFreePool(buffer);
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
//tmpEntry->NameBuffer是当前文件夹路径
//下面的操作在拼接文件夹下面的文件路径
RtlZeroMemory(nameBuffer, wcslen(tmpEntry->NameBuffer) * sizeof(WCHAR) + dirInfo->FileNameLength + 4);
wcscpy(nameBuffer, tmpEntry->NameBuffer);
wcscat(nameBuffer, L"\\");
RtlCopyMemory(&nameBuffer[wcslen(nameBuffer)], dirInfo->FileName, dirInfo->FileNameLength);
RtlInitUnicodeString(&nameString, nameBuffer);
if (dirInfo->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
//如果是非'.'和'..'两个特殊的目录,则将目录放入listHead
if ((dirInfo->FileNameLength == sizeof(WCHAR)) && (dirInfo->FileName[0] == L'.'))
{
}
else if ((dirInfo->FileNameLength == sizeof(WCHAR) * 2) &&
(dirInfo->FileName[0] == L'.') &&
(dirInfo->FileName[1] == L'.'))
{
}
else
{
//将文件夹插入listHead中
PFILE_LIST_ENTRY localEntry;
localEntry = (PFILE_LIST_ENTRY)ExAllocatePoolWithTag( NonPagedPool, sizeof(FILE_LIST_ENTRY), 'DRID');
if (!localEntry)
{
KdPrint(("ExAllocatePool failed\n"));
ExFreePool(buffer);
ExFreePool(nameBuffer);
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
localEntry->NameBuffer = nameBuffer;
nameBuffer = NULL;
InsertHeadList(&listHead, &localEntry->Entry); //插入头部,先把子文件夹里的删除
}
}
else
{
//文件,直接删除
// KdPrint(("文件路径:%S\n",nameBuffer));
//在删除前恢复
status = CopyFileBeforeDel(Data,FltObjects,nameBuffer);
if (!NT_SUCCESS(status))
{
KdPrint(("CopyFileBeforeDel(%wZ) failed(%x)\n", &nameString, status));
ExFreePool(buffer);
ExFreePool(nameBuffer);
break;
}
}
ExFreePool(buffer);
if (nameBuffer)
{
ExFreePool(nameBuffer);
}//继续在循环里处理下一个子文件或者子文件夹
}// while (TRUE) ,一直弄目录里的文件和文件夹
if (NT_SUCCESS(status))
{
//删除目录
/*PFILE_OBJECT fileObject1 = NULL;
status = ObReferenceObjectByHandle(handle, 0, NULL, KernelMode,
reinterpret_cast<void **>(&fileObject1),
NULL);
if (!NT_SUCCESS(status)) {
KdPrint(("ObReferenceObjectByHandle 1 fail \n"));
}
disInfo.DeleteFile = TRUE;
status = FltSetInformationFile( FltObjects->Instance,
fileObject1,
&disInfo,
sizeof(disInfo),
FileDispositionInformation);
if (NT_SUCCESS(status))
{
if (fileObject1)
{
ObDereferenceObject(fileObject1);
}
}
else {
KdPrint(("3 FltSetInformationFile(%ws) failed(%x)\n", tmpEntry->NameBuffer, status));
} */
}
FltClose(handle);
if (NT_SUCCESS(status))
{
//删除成功,从链表里移出该目录
RemoveEntryList(&tmpEntry->Entry);
ExFreePool(tmpEntry->NameBuffer);
ExFreePool(tmpEntry);
}
//如果失败,则表明在文件夹还有子文件夹,继续先删除子文件夹
}// while (!IsListEmpty(&listHead))
while (!IsListEmpty(&listHead))
{
tmpEntry = (PFILE_LIST_ENTRY)RemoveHeadList(&listHead);
ExFreePool(tmpEntry->NameBuffer);
ExFreePool(tmpEntry);
}
return status;
}
完整代码如上,第一个FltCreateFile就返回拒绝了
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
FltCreateFile 参数肯定传错了. 自己检查下.
|
能力值:
( LV3,RANK:20 )
|
-
-
6 楼
tsoo
FltCreateFile 参数肯定传错了. 自己检查下.
确实是FltCreateFile的参数传错了,第二个参数不应该写成NULL,应该写操作文件的实例。一语中的呀
|