вернуть исходный DACL после работы кода
Подскажите пожалуйста, почему не срабатывает код.
В глобальных переменных модуля
PACL pCS1OldDACL, pCS2OldDACL, pCCSOldDACL;
содранный из справки кусок дает полный доступ определенному пользователю, оставляя при этом имеющиеся разрешения
DWORD AddAceToAcl (LPTSTR lpObjectName, SE_OBJECT_TYPE ObjectType)
{
DWORD dwRes;
PSECURITY_DESCRIPTOR pSD;
EXPLICIT_ACCESS ea;
PACL pNewDACL;
DWORD size;
AnsiString CH;
CH=lpObjectName;
size=sizeof(UserName);
GetUserName(UserName,&size);
if (NULL == lpObjectName)
return ERROR_INVALID_PARAMETER;
if (CH.Pos("ControlSet001")!=0)
dwRes = GetNamedSecurityInfo(lpObjectName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL, &pCS1OldDACL, NULL, &pSD);
if (CH.Pos("ControlSet002")!=0)
dwRes = GetNamedSecurityInfo(lpObjectName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL, &pCS2OldDACL, NULL, &pSD);
if (CH.Pos("CurrentControlSet")!=0)
dwRes = GetNamedSecurityInfo(lpObjectName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL, &pCCSOldDACL, NULL, &pSD);
if (ERROR_SUCCESS != dwRes)
return dwRes;
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
BuildExplicitAccessWithName(&ea, UserName,GENERIC_ALL,
SET_ACCESS, SUB_CONTAINERS_AND_OBJECTS_INHERIT);
// create an new ACL by merging the EXPLICIT_ACCESS structure
// with the existing DACL
if (CH.Pos("ControlSet001")!=0)
dwRes = SetEntriesInAcl(1, &ea, pCS1OldDACL, &pNewDACL);
if (CH.Pos("ControlSet002")!=0)
dwRes = SetEntriesInAcl(1, &ea, pCS2OldDACL, &pNewDACL);
if (CH.Pos("CurrentControlSet")!=0)
dwRes = SetEntriesInAcl(1, &ea, pCCSOldDACL, &pNewDACL);
if (ERROR_SUCCESS != dwRes)
goto Cleanup;
// attach the new ACL as the object's DACL
dwRes = SetNamedSecurityInfo(lpObjectName, ObjectType,
DACL_SECURITY_INFORMATION,
NULL, NULL, pNewDACL, NULL);
// free the buffers returned by SetEntriesInAcl
// and GetNamedSecurityInfo
Cleanup:
if(pSD != NULL)
LocalFree((HLOCAL) pSD);
if(pNewDACL != NULL)
LocalFree((HLOCAL) pNewDACL);
return dwRes;
}
при нажатии кнопки GetAccess даются права
void __fastcall TForm2::GetAccessClick(TObject *Sender)
{
int success=0;
if(pCS1OldDACL != NULL)
LocalFree((HLOCAL) pCS1OldDACL);
if (AddAceToAcl(TEXT("MACHINE\\SYSTEM\\ControlSet001\\Enum"),SE_REGISTRY_KEY)==ERROR_SUCCESS)
success++;
if(pCS2OldDACL != NULL)
LocalFree((HLOCAL) pCS2OldDACL);
if (AddAceToAcl(TEXT("MACHINE\\SYSTEM\\ControlSet002\\Enum"),SE_REGISTRY_KEY)==ERROR_SUCCESS)
success++;
if(pCCSOldDACL != NULL)
LocalFree((HLOCAL) pCCSOldDACL);
if (AddAceToAcl(TEXT("MACHINE\\SYSTEM\\CurrentControlSet\\Enum"),SE_REGISTRY_KEY)==ERROR_SUCCESS)
success++;
if (success==3){
ShowMessage ("успешно");
CancelAccess->Enabled=true;}
else
ShowMessage ("не вышло");
}
Нажатие CancelAccess должно вернуть прежний DACL
void __fastcall TForm2::CancelAccessClick(TObject *Sender)
{
if (SetNamedSecurityInfo(TEXT("MACHINE\\SYSTEM\\ControlSet001\\Enum"), SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION,NULL, NULL, pCS1OldDACL, NULL)==ERROR_SUCCESS
&& SetNamedSecurityInfo(TEXT("MACHINE\\SYSTEM\\ControlSet002\\Enum"), SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION,NULL, NULL, pCS2OldDACL, NULL)==ERROR_SUCCESS
&& SetNamedSecurityInfo(TEXT("MACHINE\\SYSTEM\\CurrentControlSet\\Enum"), SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION,NULL, NULL, pCCSOldDACL, NULL)==ERROR_SUCCESS){
ShowMessage ("успешно");
CancelAccess->Enabled=false;}
else
ShowMessage ("не вышло");
}
функция SetNamedSecurityInfo возвращает ошибку 87 INVALID_PARAMETER, или вызывает системное исключение access violation
В моем случае дело было в первом параметре функции SetNamedSecurityInfo.
Посмотрите в режиме отладки на реальное значение строкового параметра.
У меня были проблемы с обратными слэшами (пршлось удваивать) и с окончанием строки.
Должно кончаться 0x0 , а не 0A 0D.
Рад, если оказался полезен.