#c #windows #winapi #acl
#c #Windows #winapi #acl
Вопрос:
Я мало что знаю о дескрипторах безопасности для Windows. Чтобы узнать, я внимательно следил за их примером, размещенным здесь. Мой код продолжал выдавать ту же ошибку (87- недопустимый параметр) при вызове SetEntriesInAcl. Я не мог понять это, поэтому я скопировал и вставил точный код из примера и запустил его. В итоге у меня возникла та же ошибка; Кто-нибудь с опытом работы в этой области имеет представление о том, что происходит? Вот тот же код из примера:
#pragma comment(lib, "advapi32.lib")
#include <windows.h>
#include <stdio.h>
#include <aclapi.h>
#include <tchar.h>
void main()
{
DWORD dwRes, dwDisposition;
PSID pEveryoneSID = NULL, pAdminSID = NULL;
PACL pACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
EXPLICIT_ACCESS ea[2];
SID_IDENTIFIER_AUTHORITY SIDAuthWorld =
SECURITY_WORLD_SID_AUTHORITY;
SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY;
SECURITY_ATTRIBUTES sa;
LONG lRes;
HKEY hkSub = NULL;
// Create a well-known SID for the Everyone group.
if (!AllocateAndInitializeSid(amp;SIDAuthWorld, 1,
SECURITY_WORLD_RID,
0, 0, 0, 0, 0, 0, 0,
amp;pEveryoneSID))
{
_tprintf(_T("AllocateAndInitializeSid Error %un"), GetLastError());
goto Cleanup;
}
// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE will allow Everyone read access to the key.
ZeroMemory(amp;ea, 2 * sizeof(EXPLICIT_ACCESS));
ea[0].grfAccessPermissions = KEY_READ;
ea[0].grfAccessMode = SET_ACCESS;
ea[0].grfInheritance = NO_INHERITANCE;
ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea[0].Trustee.ptstrName = (LPTSTR)pEveryoneSID;
// Create a SID for the BUILTINAdministrators group.
if (!AllocateAndInitializeSid(amp;SIDAuthNT, 2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0, 0, 0, 0, 0, 0,
amp;pAdminSID))
{
_tprintf(_T("AllocateAndInitializeSid Error %un"), GetLastError());
goto Cleanup;
}
// Initialize an EXPLICIT_ACCESS structure for an ACE.
// The ACE will allow the Administrators group full access to
// the key.
ea[1].grfAccessPermissions = KEY_ALL_ACCESS;
ea[1].grfAccessMode = SET_ACCESS;
ea[1].grfInheritance = NO_INHERITANCE;
ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
ea[1].Trustee.ptstrName = (LPTSTR)pAdminSID;
// Create a new ACL that contains the new ACEs.
dwRes = SetEntriesInAcl(2, ea, NULL, amp;pACL);
if (ERROR_SUCCESS != dwRes)
{
_tprintf(_T("SetEntriesInAcl Error %un"), GetLastError());
goto Cleanup;
}
// Initialize a security descriptor.
pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,
SECURITY_DESCRIPTOR_MIN_LENGTH);
if (NULL == pSD)
{
_tprintf(_T("LocalAlloc Error %un"), GetLastError());
goto Cleanup;
}
if (!InitializeSecurityDescriptor(pSD,
SECURITY_DESCRIPTOR_REVISION))
{
_tprintf(_T("InitializeSecurityDescriptor Error %un"),
GetLastError());
goto Cleanup;
}
// Add the ACL to the security descriptor.
if (!SetSecurityDescriptorDacl(pSD,
TRUE, // bDaclPresent flag
pACL,
FALSE)) // not a default DACL
{
_tprintf(_T("SetSecurityDescriptorDacl Error %un"),
GetLastError());
goto Cleanup;
}
// Initialize a security attributes structure.
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = pSD;
sa.bInheritHandle = FALSE;
// Use the security attributes to set the security descriptor
// when you create a key.
lRes = RegCreateKeyEx(HKEY_CURRENT_USER, _T("mykey"), 0, _T(""), 0,
KEY_READ | KEY_WRITE, amp;sa, amp;hkSub, amp;dwDisposition);
_tprintf(_T("RegCreateKeyEx result %un"), lRes);
Cleanup:
if (pEveryoneSID)
FreeSid(pEveryoneSID);
if (pAdminSID)
FreeSid(pAdminSID);
if (pACL)
LocalFree(pACL);
if (pSD)
LocalFree(pSD);
if (hkSub)
RegCloseKey(hkSub);
return;
}
Комментарии:
1. Опубликованный вами код работает для меня идеально. Какой компилятор вы используете? Какая версия Windows?
2. @HarryJohnston Я использую Windows 10 Pro 10.0.14393 с компилятором MSVC. Я не уверен в версии компилятора для MSVC, хотя я ориентируюсь на Windows 10. Я не пытался настроить таргетинг на другую версию ОС, чтобы проверить, работает ли это.
3. @HarryJohnston, нацеленный на Windows 8.1, тоже не работает для меня. Какую версию Windows и какой компилятор вы используете?
4. Visual Studio 2010. Я только что попробовал запустить исполняемый файл в Windows 10 (сборка 1607), и там он тоже работает.
5. Вы должны опубликовать это в качестве ответа. Это может быть полезно будущим читателям.
Ответ №1:
Причина, по которой функция SetEntriesInAcl продолжала сбоить с кодом ошибки 87 — недопустимый параметр, заключается в том, что была установлена опция компилятора (/Zp1). Zp1 устанавливает выравнивание элементов структуры по умолчанию на один байт. Когда для параметра компилятора было возвращено значение по умолчанию, функция работала нормально. Zp1 изменял размер структуры EXPLICIT_ACCESS_W с 48 на 40, что приводило к возникновению ошибки недопустимого параметра.
После этого опыта я бы рекомендовал не устанавливать глобальную упаковку структуры (/ Zp), а вместо этого использовать #pragma pack(n) для упакованных структур, которые вам нужны; затем сбросьте значение по умолчанию с помощью #pragma pack() после определения (определений). Я почти уверен, что параметр Zp повлияет и на другие структуры, такие как SECURITY_DESCRIPTOR и некоторые из его членов. Я заметил аналогичную проблему при использовании атрибутов безопасности с файлом, отображенным в память, которая была устранена при удалении Zp #.