|
|
以下是针对你需求的32位DLL实现代码。代码通过修改NTFS安全描述符,为指定文件夹及其所有子对象设置“拒绝Everyone完全访问”的ACL,从而禁止任何用户(包括管理员)对该文件夹及其内部文件/文件夹进行读取、写入、删除、重命名、复制、移动等操作。由于权限被彻底拒绝,拖拽、DOS命令和所有其他方式都无法进行复制或移动。
注意:此方案会导致文件夹完全不可访问(包括查看内容)。若需要保留只读查看权限,则无法阻止复制操作,因为复制依赖于读取权限。根据你的描述“禁止以各种手段重命名”“禁止DOS命令复制”,该实现满足要求。
DLL导出函数说明:
- 函数名:ProtectFolder
- 参数:文件夹路径(ANSI字符串,支持中文)
- 返回值:BOOL(成功返回TRUE,失败返回FALSE)
- 调用约定:_stdcall(易语言默认)
-
- // ProtectFolderDll.cpp
- // 编译为32位DLL(Release配置,平台x86)
- // 需要管理员权限运行调用进程(因为修改安全描述符需要特权)
- #include <windows.h>
- #include <aclapi.h>
- #include <sddl.h>
- #include <tchar.h>
- #pragma comment(lib, "advapi32.lib")
- #pragma comment(lib, "user32.lib")
- // 提升当前进程的权限(SeSecurityPrivilege, SeBackupPrivilege)
- BOOL EnablePrivilege(LPCTSTR lpszPrivilege)
- {
- HANDLE hToken;
- TOKEN_PRIVILEGES tp;
- LUID luid;
- if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
- return FALSE;
- if (!LookupPrivilegeValue(NULL, lpszPrivilege, &luid))
- {
- CloseHandle(hToken);
- return FALSE;
- }
- tp.PrivilegeCount = 1;
- tp.Privileges[0].Luid = luid;
- tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
- BOOL bRet = AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
- CloseHandle(hToken);
- return bRet && (GetLastError() == ERROR_SUCCESS);
- }
- // 递归设置目录及其子对象的拒绝访问ACE
- BOOL SetDenyACLRecursive(LPCTSTR pszPath, PSID pEveryoneSID)
- {
- // 为当前文件/文件夹构建新的DACL
- EXPLICIT_ACCESS ea;
- ZeroMemory(&ea, sizeof(ea));
- ea.grfAccessPermissions = GENERIC_ALL; // 拒绝所有权限
- ea.grfAccessMode = DENY_ACCESS;
- ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; // 继承给子容器和对象
- ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
- ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
- ea.Trustee.ptstrName = (LPTSTR)pEveryoneSID;
- PACL pNewDACL = NULL;
- DWORD dwErr = SetEntriesInAcl(1, &ea, NULL, &pNewDACL);
- if (dwErr != ERROR_SUCCESS)
- return FALSE;
- // 应用新的DACL到当前对象(保护DACL,防止继承父权限)
- dwErr = SetNamedSecurityInfo(
- (LPTSTR)pszPath,
- SE_FILE_OBJECT,
- DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
- NULL, NULL, pNewDACL, NULL);
- LocalFree(pNewDACL);
- if (dwErr != ERROR_SUCCESS)
- return FALSE;
- // 如果是目录,递归处理子项
- if (GetFileAttributes(pszPath) & FILE_ATTRIBUTE_DIRECTORY)
- {
- WIN32_FIND_DATA ffd;
- TCHAR szSearch[MAX_PATH];
- _tcscpy_s(szSearch, MAX_PATH, pszPath);
- _tcscat_s(szSearch, MAX_PATH, _T("\\*"));
- HANDLE hFind = FindFirstFile(szSearch, &ffd);
- if (hFind == INVALID_HANDLE_VALUE)
- return FALSE; // 可能空文件夹或权限不足
- do
- {
- if (_tcscmp(ffd.cFileName, _T(".")) == 0 || _tcscmp(ffd.cFileName, _T("..")) == 0)
- continue;
- TCHAR szSubPath[MAX_PATH];
- _tcscpy_s(szSubPath, MAX_PATH, pszPath);
- _tcscat_s(szSubPath, MAX_PATH, _T("\"));
- _tcscat_s(szSubPath, MAX_PATH, ffd.cFileName);
- // 递归设置子对象(忽略失败继续)
- SetDenyACLRecursive(szSubPath, pEveryoneSID);
- } while (FindNextFile(hFind, &ffd) != 0);
- FindClose(hFind);
- }
- return TRUE;
- }
- // 导出的保护函数(ANSI版本,易语言可直接调用)
- extern "C" __declspec(dllexport) BOOL __stdcall ProtectFolder(LPCSTR lpszFolderPath)
- {
- // 将ANSI路径转换为宽字符(支持中文)
- int nLen = MultiByteToWideChar(CP_ACP, 0, lpszFolderPath, -1, NULL, 0);
- if (nLen == 0)
- return FALSE;
- TCHAR* pszWidePath = new TCHAR[nLen];
- MultiByteToWideChar(CP_ACP, 0, lpszFolderPath, -1, pszWidePath, nLen);
- // 提升必要的权限
- if (!EnablePrivilege(SE_SECURITY_NAME)) { delete[] pszWidePath; return FALSE; }
- if (!EnablePrivilege(SE_BACKUP_NAME)) { delete[] pszWidePath; return FALSE; }
- // 创建Everyone SID
- PSID pEveryoneSID = NULL;
- SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
- if (!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID))
- {
- delete[] pszWidePath;
- return FALSE;
- }
- BOOL bResult = SetDenyACLRecursive(pszWidePath, pEveryoneSID);
- FreeSid(pEveryoneSID);
- delete[] pszWidePath;
- return bResult;
- }
- // 标准DLL入口
- BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
- {
- switch (ul_reason_for_call)
- {
- case DLL_PROCESS_ATTACH:
- case DLL_THREAD_ATTACH:
- case DLL_THREAD_DETACH:
- case DLL_PROCESS_DETACH:
- break;
- }
- return TRUE;
- }
复制代码
使用方法:
1. 在Visual Studio中新建Win32项目,选择DLL,编译得到32位DLL文件。
2. 在易语言中声明DLL函数(注意易语言文本型默认是ANSI):
.版本 2
.DLL命令 ProtectFolder, 整数型, "ProtectFolder.dll", "ProtectFolder"
.参数 文件夹路径, 文本型
3. 以管理员身份运行易语言程序(因为修改安全描述符需要SeSecurityPrivilege权限)。
4. 调用命令: ProtectFolder (“C:\目标文件夹\Categories”)
执行后该文件夹及其所有内容将永久拒绝所有访问(直到手动修改安全属性)。
警告:此操作不可逆!保护后的文件夹将无法以任何方式访问,包括管理员也无法打开、复制、删除、重命名。恢复方法:需要以管理员身份启动安全属性界面,取得所有权并手动修改权限。请谨慎使用。
如果需要解除保护,可以编写类似的UnprotectFolder函数,或手动修改ACL。若有此需求可进一步联系。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 |
|