一直想做一个类似 Windows 命令行中 del 命令删除文件的功能,它支持 环境变量通配符可以递归,后来发现自己写这么一个小功能还真的不是一件容易的事情,没办法为了着急使用先临时做了一个小版本。代码有些缺憾。

  • 不支持环境变量
  • 不支持固定后缀文件递归删除
// example.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <windows.h>
#include <iostream>


BOOL DeleteFiles(const std::wstring file_full_path)
{
    BOOL no_error = TRUE;
    WIN32_FIND_DATA win32_find_data = { 0 };

    std::wstring dir = file_full_path.substr(0, file_full_path.rfind(_T("\\"))).c_str();
    std::wstring file = file_full_path.substr(file_full_path.rfind(_T("\\")) + 1, file_full_path.length());

    if (dir.size() == 0 || file.size() == 0)
    {
        return FALSE;
    }

    HANDLE handle = FindFirstFile(file_full_path.c_str(), &win32_find_data);
    if (INVALID_HANDLE_VALUE == handle)
    {
        return no_error;
    }

    do
    {
        // 如果是目录递归操作
        if (win32_find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
            // 排除 . 和 .. 两个文件夹
            if (_tcsicmp(_T("."), win32_find_data.cFileName) != 0 &&
                _tcsicmp(_T(".."), win32_find_data.cFileName) != 0)
            {
                // 根目录加上搜索出来的目录
                std::wstring new_full_path = dir;
                new_full_path += _T("\\");
                new_full_path += win32_find_data.cFileName;

                // 备份搜索出来的目录完整路径用以删除
                std::wstring new_dir = new_full_path;

                // 再加上要删除的文件名
                new_full_path += _T("\\");
                new_full_path += file;

                // 开始删除
                if (DeleteFiles(new_full_path))
                {
                    // 删除子文件后删除整个目录
                    RemoveDirectory(new_dir.c_str());
                }
            }
        }
        else
        {
            std::wstring full_file_name = dir;
            full_file_name += _T("\\");
            full_file_name += win32_find_data.cFileName;

            // 去除只读文件的只读属性
            DWORD file_attr = GetFileAttributes(full_file_name.c_str());
            if ((file_attr & FILE_ATTRIBUTE_READONLY) != 0)
            {
                SetFileAttributes(full_file_name.c_str(), file_attr & (~FILE_ATTRIBUTE_READONLY));
            }

            BOOL del_res = DeleteFiles(full_file_name.c_str());
            if (del_res)
            {
                std::wcout << full_file_name.c_str() << std::endl;
            }

            // 如果有一个文件删除失败则返回上层,上层若发现有删除失败的文件则不删除其斧文件夹
            if (del_res == FALSE && no_error == TRUE)
            {
                no_error = FALSE;
            }
        }
    } while (FindNextFile(handle, &win32_find_data) != 0);

    FindClose(handle);
    return no_error;
}

int _tmain(int argc, _TCHAR* argv[])
{
    _wsetlocale(LC_ALL, L"chs");

    DeleteFiles(_T(R"(C:\Users\ADMINI~1\AppData\Local\Temp\*)"));

    return 0;
}

处理文件路径信息是经常要用到的字符串处理的手段,应用场景非常的多,不论是 Linux 还是 Windows,在我没接触这一系列函数之前,都是使用一系列字符串处理函数来自己写。而在 Windows 环境下,系统给我们提供了一系列处理路径相关的 API,我们在需要使用的时候直接调用即可,不但可以避免自己使用字符串处理函数处理时可能造成的各种问题,还可以加快我们编程的速度。当然如果你还没有使用字符串处理函数自己处理过路径等信息,我强烈建议你先自己尝试学习一下。轮子可不重复制造,但你必须要清楚轮子的制作工艺,否则在出现故障时就不知道如何处理了。

继续阅读

最近在重构一个项目的时候需要用到遍历系统账户信息和每个账户的 SID 信息用来对比数据,所以就涉及到如何获取 Windows 的账户信息,以及每个账户所关联的 SID。学习了一些前辈的代码后自己总结了一下记录在博客里,方便以后使用。

继续阅读

在日常开发过程中,我们常常用如下这种形式的结构体来传递数据。

typedef struct  _PATH_INFO {
    HANDLE  hPPid;              // 父进程 PID
    HANDLE  hPid;               // 子进程 PID
    ULONG   PathLength;         // 子进程路径长度
    TCHAR   Path[1];            // 用于存储子进程路径
} PATH_INFO, *PPATH_INFO;

其中前三个成员用来描述一个进程的父进程PID和自身进程的PID以及路径长度信息,而最后一个成员来描述该路径的实际内容,由于路径长度是不定的,我们为了节省内存,加了一个 PathLength 的成员来描述路径长度,不会将实际储存路径的成员设置成固定的 512 大小或者 1024 大小,这样会非常浪费内存,在使用过程中,我们会想如下这种方式来给结构体分配内存和填充数据。

继续阅读

Windows 内核开发市面上流传的教程基本上都在写 CmRegisterCallback 函数的功能,而 CmRegisterCallbackEx 几乎没有(本人没有见到有描述比较清晰的)。看任何人写的教程都不如看一眼 MSDNExample,跟着微软的例子我详细记录一下这个函数的每个参数,希望可以帮到后面要使用该函数的人,如果大家看到有什么不对的地方请指证,以免我误导他人。

继续阅读

前段时间一直在学习内核监控进程创建的知识,虽然成功监视,但一直在内核输出到 DebugView 中,不能通知我们的应用程序来显示指定内容,无论如何也不方便,所以赶在周末参考了 Windows 内核安全与驱动开发 中第五章 “应用与内核通讯” 制作了以下程序。程序主要使用了内核事件 KEVENT 实现同步,更多请参考 Windows 内核安全与驱动开发,程序运行后的效果如下:

继续阅读

前段时间借助开源项目 EasyHook 制作了一个在应用层下的监控进程创建的工具。但应用层实现有一些限制,比如 Hook 时风险较高、能取到的信息有限、XP 和 Win7 需要 Hook 不同的函数等。这些问题最终让我向内核研究,希望可以通过一份代码,编译出适应不同系统的驱动程序实现我们的需求,所以就有了本文的内容,我们先来看一下效果图。

继续阅读