阅读:3930回复:19
高人们请进来,看看如何删除一个文件夹
我知道删除一个文件夹或者文件,可以通过发Irp或者ZwDeleteFile,但对于文件夹来说,只有空文件夹发Irp才可以删除,如果文件夹下有其他文件或者文件夹,发Irp删不掉啊,如何删除文件夹不管是不是空文件夹,有人知道吗?指点一下??
|
|
|
沙发#
发布于:2007-07-19 17:14
自己枚举删除,考虑到内核栈空间有限,尽量不要用递归,把栈转换成堆处理。
|
|
|
板凳#
发布于:2007-07-19 18:55
wowocock能否举个例子说明一下怎么把递归转换成非递归的处理。
我也遇到了这个难题。 |
|
地板#
发布于:2007-07-19 20:00
有一个很简单的办法,作一个扫描列表,可以说是一个队列也行
扫描时,扫描一个目录,把需要扫描的子目录放到这个队列. 每扫完一个目录,就把这个目录从除列去掉或作标志,这样就可以把递归变成线线的了 |
|
|
地下室#
发布于:2007-07-20 08:46
都是牛人进来了,长见识了
|
|
|
5楼#
发布于:2007-07-20 09:40
这个楚狂人最有发言权了,:-)
|
|
|
6楼#
发布于:2007-07-20 12:33
引用第3楼znsoft于2007-07-19 20:00发表的 : 这方法不错。 |
|
7楼#
发布于:2007-07-24 17:07
这是我实现的删除目录的代码。欢迎大家指正错误。
NTSTATUS SfDeleteFile( IN PUNICODE_STRING FileName ) { OBJECT_ATTRIBUTES objAttributes; IO_STATUS_BLOCK iosb; HANDLE handle; FILE_DISPOSITION_INFORMATION disInfo; NTSTATUS status; InitializeObjectAttributes(&objAttributes, FileName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); status = ZwCreateFile(&handle, SYNCHRONIZE | FILE_WRITE_DATA | DELETE, &objAttributes, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_DELETE_ON_CLOSE, NULL, 0); if (!NT_SUCCESS(status)) { if (status == STATUS_ACCESS_DENIED) { status = ZwCreateFile(&handle, SYNCHRONIZE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, &objAttributes, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (NT_SUCCESS(status)) { FILE_BASIC_INFORMATION basicInfo = {0}; status = ZwQueryInformationFile(handle, &iosb, &basicInfo, sizeof(basicInfo), FileBasicInformation); if (!NT_SUCCESS(status)) { KdPrint(("ptfilter!SfDeleteFile: ZwQueryInformationFile(%wZ) failed(%x)\n", FileName, status)); } basicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; status = ZwSetInformationFile(handle, &iosb, &basicInfo, sizeof(basicInfo), FileBasicInformation); if (!NT_SUCCESS(status)) { KdPrint(("ptfilter!SfDeleteFile: ZwSetInformationFile(%wZ) failed(%x)\n", FileName, status)); } ZwClose(handle); status = ZwCreateFile(&handle, SYNCHRONIZE | FILE_WRITE_DATA | DELETE, &objAttributes, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_DELETE_ON_CLOSE, NULL, 0); } } if (!NT_SUCCESS(status)) { KdPrint(("ptfilter!SfDeleteFile: ZwCreateFile(%wZ) failed(%x)\n", FileName, status)); return status; } } disInfo.DeleteFile = TRUE; status = ZwSetInformationFile(handle, &iosb, &disInfo, sizeof(disInfo), FileDispositionInformation); if (!NT_SUCCESS(status)) { KdPrint(("ptfilter!SfDeleteFile: ZwSetInformationFile(%wZ) failed(%x)\n", FileName, status)); } ZwClose(handle); return status; } typedef struct _FILE_LIST_ENTRY { LIST_ENTRY Entry; PWSTR NameBuffer; } FILE_LIST_ENTRY, *PFILE_LIST_ENTRY; NTSTATUS SfDeleteDirectory( IN PUNICODE_STRING FileName ) { OBJECT_ATTRIBUTES objAttributes; IO_STATUS_BLOCK iosb; HANDLE handle; FILE_DISPOSITION_INFORMATION disInfo; PVOID buffer; ULONG bufferLength; BOOLEAN restartScan; PFILE_DIRECTORY_INFORMATION dirInfo; PWSTR nameBuffer; UNICODE_STRING nameString; NTSTATUS status; LIST_ENTRY listHead; PFILE_LIST_ENTRY tmpEntry; PFILE_LIST_ENTRY preEntry = NULL; nameBuffer = (PWSTR) ExAllocatePool(PagedPool, FileName->Length + sizeof(WCHAR)); if (!nameBuffer) { return STATUS_INSUFFICIENT_RESOURCES; } tmpEntry = (PFILE_LIST_ENTRY) ExAllocatePool(PagedPool, sizeof(FILE_LIST_ENTRY)); if (!tmpEntry) { ExFreePool(nameBuffer); return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyMemory(nameBuffer, FileName->Buffer, FileName->Length); nameBuffer[FileName->Length / sizeof(WCHAR)] = L'\0'; InitializeListHead(&listHead); tmpEntry->NameBuffer = nameBuffer; InsertHeadList(&listHead, &tmpEntry->Entry); while (!IsListEmpty(&listHead)) { 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 = ZwCreateFile(&handle, FILE_ALL_ACCESS, &objAttributes, &iosb, NULL, 0, 0, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (!NT_SUCCESS(status)) { KdPrint(("ptfilter!SfDeleteDirectory: ZwCreateFile(%ws) failed(%x)\n", tmpEntry->NameBuffer, status)); break; } restartScan = TRUE; 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 = ExAllocatePool(PagedPool, bufferLength); if (!buffer) { KdPrint(("ptfilter!SfDeleteDirectory: ExAllocatePool failed\n")); status = STATUS_INSUFFICIENT_RESOURCES; break; } status = ZwQueryDirectoryFile(handle, NULL, NULL, NULL, &iosb, buffer, bufferLength, FileDirectoryInformation, FALSE, NULL, restartScan); } if (status == STATUS_NO_MORE_FILES) { ExFreePool(buffer); status = STATUS_SUCCESS; break; } restartScan = FALSE; if (!NT_SUCCESS(status)) { KdPrint(("ptfilter!SfDeleteDirectory: ZwQueryDirectoryFile(%ws) failed(%x)\n", tmpEntry->NameBuffer, status)); if (buffer) { ExFreePool(buffer); } break; } dirInfo = (PFILE_DIRECTORY_INFORMATION) buffer; nameBuffer = (PWSTR) ExAllocatePool(PagedPool, wcslen(tmpEntry->NameBuffer) * sizeof(WCHAR) + dirInfo->FileNameLength + 4); if (!nameBuffer) { KdPrint(("ptfilter!SfDeleteDirectory: ExAllocatePool failed\n")); ExFreePool(buffer); status = STATUS_INSUFFICIENT_RESOURCES; break; } 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) { 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 { PFILE_LIST_ENTRY localEntry; localEntry = (PFILE_LIST_ENTRY) ExAllocatePool(PagedPool, sizeof(FILE_LIST_ENTRY)); if (!localEntry) { KdPrint(("ptfilter!SfDeleteDirectory: ExAllocatePool failed\n")); ExFreePool(buffer); ExFreePool(nameBuffer); status = STATUS_INSUFFICIENT_RESOURCES; break; } localEntry->NameBuffer = nameBuffer; nameBuffer = NULL; InsertHeadList(&listHead, &localEntry->Entry); } } else { status = SfDeleteFile(&nameString); if (!NT_SUCCESS(status)) { KdPrint(("ptfilter!SfDeleteDirectory: PmDeleteFile(%wZ) failed(%x)\n", &nameString, status)); ExFreePool(buffer); ExFreePool(nameBuffer); break; } } ExFreePool(buffer); if (nameBuffer) { ExFreePool(nameBuffer); } } if (NT_SUCCESS(status)) { disInfo.DeleteFile = TRUE; status = ZwSetInformationFile(handle, &iosb, &disInfo, sizeof(disInfo), FileDispositionInformation); if (!NT_SUCCESS(status)) { KdPrint(("ptfilter!ZwSetInformationFile(%ws) failed(%x)\n", tmpEntry->NameBuffer, status)); } } ZwClose(handle); if (NT_SUCCESS(status)) { RemoveEntryList(&tmpEntry->Entry); ExFreePool(tmpEntry->NameBuffer); ExFreePool(tmpEntry); } } while (!IsListEmpty(&listHead)) { tmpEntry = (PFILE_LIST_ENTRY) RemoveHeadList(&listHead); ExFreePool(tmpEntry->NameBuffer); ExFreePool(tmpEntry); } return status; } |
|
8楼#
发布于:2007-07-24 17:16
不错,赞一个
|
|
|
9楼#
发布于:2007-07-24 17:19
|
|
|
10楼#
发布于:2007-07-24 17:28
|
|
|
11楼#
发布于:2007-07-24 17:46
高人们都进来了,楼主面子大。
|
|
12楼#
发布于:2007-07-24 18:27
都是高人。俺先感谢,再学习。
|
|
|
13楼#
发布于:2007-07-24 19:29
呵呵,不错啊。
|
|
14楼#
发布于:2007-07-24 23:21
有高人的地方风景真好。
|
|
15楼#
发布于:2007-07-25 08:52
呵呵,一个帖子招来这么多牛人,不错啊。
|
|
|
16楼#
发布于:2007-07-25 10:13
漫天都是勋章,闪亮闪亮的
|
|
17楼#
发布于:2007-08-03 19:41
俺还以为高人都忙着嫌M$去了呢!
|
|
18楼#
发布于:2008-04-10 10:32
试了你的代码:删除这个文件夹"C:\Documents and Settings\All Users\「开始」菜单\程序\启动".可文件夹下的文件没有被删除.而"启动"文件夹名字被改成了"程序",期望改进和各位指点
|
|
19楼#
发布于:2008-04-10 15:11
还有一个方法 也比较简单,就是不要使用队列 或者链表什么的!就是把当前扫描的路径放到一个动态增加的字符串数组里面,它的子文件夹,就添加到这个字符串后面,这样就形成一个当前扫描的文件夹或者文件的全路径,从后面往前删除。 tooflat的实现是从根目录往子目录删除,这个方法是从子目录忘根目录删除。少用了内存,但是多用了cpu执行的时间
|
|