linuxyf
驱动小牛
驱动小牛
  • 注册日期2007-04-03
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望162点
  • 贡献值0点
  • 好评度161点
  • 原创分1分
  • 专家分0分
阅读:3838回复:19

高人们请进来,看看如何删除一个文件夹

楼主#
更多 发布于:2007-07-19 10:43
我知道删除一个文件夹或者文件,可以通过发Irp或者ZwDeleteFile,但对于文件夹来说,只有空文件夹发Irp才可以删除,如果文件夹下有其他文件或者文件夹,发Irp删不掉啊,如何删除文件夹不管是不是空文件夹,有人知道吗?指点一下??
在孤独和无助中缓慢前行...
wowocock
VIP专家组
VIP专家组
  • 注册日期2002-04-08
  • 最后登录2016-01-09
  • 粉丝16
  • 关注2
  • 积分601分
  • 威望1651点
  • 贡献值1点
  • 好评度1227点
  • 原创分1分
  • 专家分0分
沙发#
发布于:2007-07-19 17:14
自己枚举删除,考虑到内核栈空间有限,尽量不要用递归,把栈转换成堆处理。
花开了,然后又会凋零,星星是璀璨的,可那光芒也会消失。在这样 一瞬间,人降生了,笑者,哭着,战斗,伤害,喜悦,悲伤憎恶,爱。一切都只是刹那间的邂逅,而最后都要归入死亡的永眠
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2007-07-19 18:55
wowocock能否举个例子说明一下怎么把递归转换成非递归的处理。
我也遇到了这个难题。
znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
地板#
发布于:2007-07-19 20:00
有一个很简单的办法,作一个扫描列表,可以说是一个队列也行

扫描时,扫描一个目录,把需要扫描的子目录放到这个队列. 每扫完一个目录,就把这个目录从除列去掉或作标志,这样就可以把递归变成线线的了
http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
linuxyf
驱动小牛
驱动小牛
  • 注册日期2007-04-03
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望162点
  • 贡献值0点
  • 好评度161点
  • 原创分1分
  • 专家分0分
地下室#
发布于:2007-07-20 08:46
都是牛人进来了,长见识了
在孤独和无助中缓慢前行...
devia
论坛版主
论坛版主
  • 注册日期2005-05-14
  • 最后登录2016-04-05
  • 粉丝3
  • 关注0
  • 积分1029分
  • 威望712点
  • 贡献值1点
  • 好评度555点
  • 原创分8分
  • 专家分4分
5楼#
发布于:2007-07-20 09:40
这个楚狂人最有发言权了,:-)
人总在矛盾中徘徊。。。
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2007-07-20 12:33
引用第3楼znsoft于2007-07-19 20:00发表的  :
有一个很简单的办法,作一个扫描列表,可以说是一个队列也行

扫描时,扫描一个目录,把需要扫描的子目录放到这个队列. 每扫完一个目录,就把这个目录从除列去掉或作标志,这样就可以把递归变成线线的了


这方法不错。
tooflat
论坛版主
论坛版主
  • 注册日期2002-07-08
  • 最后登录2014-03-11
  • 粉丝2
  • 关注0
  • 积分1007分
  • 威望551点
  • 贡献值3点
  • 好评度476点
  • 原创分0分
  • 专家分0分
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;
}
znsoft
管理员
管理员
  • 注册日期2001-03-23
  • 最后登录2023-10-25
  • 粉丝300
  • 关注6
  • 积分910分
  • 威望14796点
  • 贡献值7点
  • 好评度2410点
  • 原创分5分
  • 专家分100分
  • 社区居民
  • 最爱沙发
  • 社区明星
8楼#
发布于:2007-07-24 17:16
不错,赞一个
http://www.zndev.com 免费源码交换网 ----------------------------- 软件创造价值,驱动提供力量! 淡泊以明志,宁静以致远。 ---------------------------------- 勤用搜索,多查资料,先搜再问。
devia
论坛版主
论坛版主
  • 注册日期2005-05-14
  • 最后登录2016-04-05
  • 粉丝3
  • 关注0
  • 积分1029分
  • 威望712点
  • 贡献值1点
  • 好评度555点
  • 原创分8分
  • 专家分4分
9楼#
发布于:2007-07-24 17:19
人总在矛盾中徘徊。。。
我最老实
驱动小牛
驱动小牛
  • 注册日期2005-09-11
  • 最后登录2010-01-27
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望253点
  • 贡献值0点
  • 好评度189点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2007-07-24 17:28
养牛专业户
strpic
驱动小牛
驱动小牛
  • 注册日期2006-11-01
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望238点
  • 贡献值0点
  • 好评度156点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2007-07-24 17:46
高人们都进来了,楼主面子大。
zlf1110
驱动牛犊
驱动牛犊
  • 注册日期2002-11-10
  • 最后登录2016-01-09
  • 粉丝1
  • 关注0
  • 积分39分
  • 威望365点
  • 贡献值0点
  • 好评度30点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2007-07-24 18:27
都是高人。俺先感谢,再学习。
zlf1110
liyf_sz
驱动牛犊
驱动牛犊
  • 注册日期2005-04-08
  • 最后登录2008-07-11
  • 粉丝0
  • 关注0
  • 积分7分
  • 威望33点
  • 贡献值0点
  • 好评度31点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2007-07-24 19:29
呵呵,不错啊。
fazwh
驱动牛犊
驱动牛犊
  • 注册日期2005-09-11
  • 最后登录2020-11-18
  • 粉丝0
  • 关注0
  • 积分32分
  • 威望303点
  • 贡献值0点
  • 好评度48点
  • 原创分0分
  • 专家分0分
  • 社区居民
14楼#
发布于:2007-07-24 23:21
有高人的地方风景真好。
 
linuxyf
驱动小牛
驱动小牛
  • 注册日期2007-04-03
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分1000分
  • 威望162点
  • 贡献值0点
  • 好评度161点
  • 原创分1分
  • 专家分0分
15楼#
发布于:2007-07-25 08:52
呵呵,一个帖子招来这么多牛人,不错啊。
在孤独和无助中缓慢前行...
wanfustudio
驱动牛犊
驱动牛犊
  • 注册日期2006-08-09
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分720分
  • 威望73点
  • 贡献值0点
  • 好评度72点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2007-07-25 10:13
漫天都是勋章,闪亮闪亮的
wanted999
驱动牛犊
驱动牛犊
  • 注册日期2006-03-28
  • 最后登录2012-08-13
  • 粉丝0
  • 关注0
  • 积分519分
  • 威望429点
  • 贡献值0点
  • 好评度48点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2007-08-03 19:41
俺还以为高人都忙着嫌M$去了呢!
fresharplite
驱动牛犊
驱动牛犊
  • 注册日期2005-08-23
  • 最后登录2013-09-06
  • 粉丝0
  • 关注0
  • 积分3分
  • 威望39点
  • 贡献值0点
  • 好评度17点
  • 原创分0分
  • 专家分0分
18楼#
发布于:2008-04-10 10:32
试了你的代码:删除这个文件夹"C:\Documents and Settings\All Users\「开始」菜单\程序\启动".可文件夹下的文件没有被删除.而"启动"文件夹名字被改成了"程序",期望改进和各位指点
qianjunhua
驱动小牛
驱动小牛
  • 注册日期2003-12-08
  • 最后登录2013-02-27
  • 粉丝11
  • 关注0
  • 积分712分
  • 威望1052点
  • 贡献值1点
  • 好评度57点
  • 原创分0分
  • 专家分0分
19楼#
发布于:2008-04-10 15:11
还有一个方法 也比较简单,就是不要使用队列 或者链表什么的!就是把当前扫描的路径放到一个动态增加的字符串数组里面,它的子文件夹,就添加到这个字符串后面,这样就形成一个当前扫描的文件夹或者文件的全路径,从后面往前删除。 tooflat的实现是从根目录往子目录删除,这个方法是从子目录忘根目录删除。少用了内存,但是多用了cpu执行的时间
游客

返回顶部