Я пытаюсь написать инструмент для резервного копирования и восстановления. Я запускаю свой код на компакт-диске WinPE (http://en.wikipedia.org/wiki/Windows_Preinstallation_Environment). Я пытаюсь прочитать весь раздел C: и записать его в сеть. Так же, как команда tar, но для конкретных окон. У меня все работает, кроме настройки владельца файла. Кажется, что Windows действительно нетерпима к файлам, принадлежащим неизвестным идентификаторам безопасности. Поскольку я работаю в WinPE, большинство пользователей, определенных на C:, не находятся в локальной базе данных пользователей.
Вот некоторые из функций, которые я пробовал:
Я знаю, что это можно сделать. SetACL (http://helgeklein.com/setacl/) умеет это делать.
Итак, вопрос. Как мне установить владельца файла на несуществующего пользователя / SID? Любая помощь очень ценится!
Вот пример кода, который я пробовал:
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <sddl.h>
#include <aclapi.h>
#include <tchar.h>
INT _tmain(){
PSECURITY_DESCRIPTOR psdOwner = LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH);
if (InitializeSecurityDescriptor(psdOwner,SECURITY_DESCRIPTOR_REVISION)){
PSID psOwner = (PSID)0;
if (ConvertStringSidToSid(TEXT("S-1-5-21-3626571138-2175758104-1447827851-1013"),&psOwner)){
if (SetSecurityDescriptorOwner(psdOwner,psOwner,FALSE)){
DWORD dwError = SetNamedSecurityInfo(TEXT("test.txt"),SE_FILE_OBJECT,OWNER_SECURITY_INFORMATION,psdOwner,NULL,NULL,NULL);
if (dwError == ERROR_SUCCESS){
_tprintf(TEXT("Success!\n"));
}else{
_tprintf(TEXT("Failed to set owner: %u\n"),dwError);
}
}else{
_tprintf(TEXT("Failed to set owner into SD: %u\n"),GetLastError());
}
}else{
_tprintf(TEXT("Failed to covnert Sid string to Sid: %u\n"),GetLastError());
}
if (psOwner) LocalFree(psOwner);
}else{
_tprintf(TEXT("Failed to initialize SD: %u\n"),GetLastError());
}
if (psdOwner) LocalFree(psdOwner);
return 0;
}
Оказывается, вам нужна привилегия токена SE_RESTORE_NAME. Вы можете настроить свой токен процесса следующим образом:
BOOL TakeSecurityPriv(LPCTSTR szPriv){
BOOL bReturn = FALSE;
HANDLE hProcToken = (HANDLE)0;
if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hProcToken)){
TOKEN_PRIVILEGES tpTokPriv;
if (LookupPrivilegeValue(NULL,szPriv,&tpTokPriv.Privileges[0].Luid)){
tpTokPriv.PrivilegeCount = 1;
tpTokPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (AdjustTokenPrivileges(hProcToken,FALSE,&tpTokPriv,0,NULL,0)){
bReturn = TRUE;
}
}
}
return bReturn;
}
Затем вы можете добавить следующее в начало main в моем примере:
if (TakeSecurityPriv(SE_RESTORE_NAME)){
Это избавляет от ошибки 1307. К сожалению, в моем примере есть еще одна ошибка, потому что владелец не настроен на правильный SID. Однако когда я переключаюсь обратно на BackupRead / BackupWrite, мне не нужно создавать SID или SECURITY_DESCRIPTOR. Я размышлял над тем, что может быть проблемой некоторое время без удачи. Возможно, кто-то еще может ответить на эту часть.
Других решений пока нет …