本文介绍在 Windows 系统上实现使某个文件无法被用户或其他程序删除。
实现的原理大致如下:
通过DuplicateHandle拷贝文件句柄给另外一个进程(一般是系统进程),因为系统进程不会被关闭,所以达到了占用某个文件,不让其他进程删除、读取、写入等。
DuplicateHandle的用法参考:- Windows内核对象
因为需要拷贝文件句柄给系统进程,所以涉及到打开系统进程,可能需要提权操作,一般授权给进程SE_DEBUG_NAME权限即可。
实现一个用于锁住文件的函数LockFile,将文件句柄复制给系统csrss.exe进程,函数实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
   | bool LockFile(LPCTSTR lpFilePath) {   if (lpFilePath == NULL)     return false;
          DWORD dwCsrssProcessID = 0;   PROCESSENTRY32 pe;   pe.dwSize = sizeof(PROCESSENTRY32);   HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    while (Process32Next(hSnapShot, &pe)) {     if (lstrcmpi(pe.szExeFile, TEXT("csrss.exe")) == 0) {       dwCsrssProcessID = pe.th32ProcessID;       break;     }   }
    CloseHandle(hSnapShot);
       if (dwCsrssProcessID == 0) {     return false;   }
    HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwCsrssProcessID);
       if (hProcess == NULL) {     return false;   }
    HANDLE hFile = CreateFile(lpFilePath,     GENERIC_READ | GENERIC_EXECUTE | GENERIC_WRITE,     0,     NULL,     OPEN_ALWAYS,     FILE_ATTRIBUTE_NORMAL,     NULL);
    if (hFile == INVALID_HANDLE_VALUE) {     CloseHandle(hProcess);     return false;   }
    HANDLE hTargetHandle = INVALID_HANDLE_VALUE;   BOOL bRet = DuplicateHandle(GetCurrentProcess(),     hFile,     hProcess,     &hTargetHandle,     0,     FALSE,     DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE   );   CloseHandle(hProcess);
    return (bRet == TRUE); }
  |