MSDN样本中SetEntriesAcl错误87的原因

MSDN样本中SetEntriesAcl错误87的原因,c,windows,winapi,acl,C,Windows,Winapi,Acl,我对windows的安全描述符了解不多。为了了解这一点,我密切关注他们发布的示例。调用setEntriesIncl时,我的代码一直存在相同的错误(87-无效参数)。我无法理解它,所以我复制并粘贴了样本中的精确代码并运行了它。我最后也犯了同样的错误;有这方面经验的人知道发生了什么吗?下面是与示例中相同的代码: #pragma comment(lib, "advapi32.lib") #include <windows.h> #include <stdio.h> #

我对windows的安全描述符了解不多。为了了解这一点,我密切关注他们发布的示例。调用setEntriesIncl时,我的代码一直存在相同的错误(87-无效参数)。我无法理解它,所以我复制并粘贴了样本中的精确代码并运行了它。我最后也犯了同样的错误;有这方面经验的人知道发生了什么吗?下面是与示例中相同的代码:

    #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(&SIDAuthWorld, 1,
        SECURITY_WORLD_RID,
        0, 0, 0, 0, 0, 0, 0,
        &pEveryoneSID))
    {
        _tprintf(_T("AllocateAndInitializeSid Error %u\n"), GetLastError());
        goto Cleanup;
    }

    // Initialize an EXPLICIT_ACCESS structure for an ACE.
    // The ACE will allow Everyone read access to the key.
    ZeroMemory(&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 BUILTIN\Administrators group.
    if (!AllocateAndInitializeSid(&SIDAuthNT, 2,
        SECURITY_BUILTIN_DOMAIN_RID,
        DOMAIN_ALIAS_RID_ADMINS,
        0, 0, 0, 0, 0, 0,
        &pAdminSID))
    {
        _tprintf(_T("AllocateAndInitializeSid Error %u\n"), 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, &pACL);
    if (ERROR_SUCCESS != dwRes)
    {
        _tprintf(_T("SetEntriesInAcl Error %u\n"), GetLastError());
        goto Cleanup;
    }

    // Initialize a security descriptor.  
    pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR,
        SECURITY_DESCRIPTOR_MIN_LENGTH);
    if (NULL == pSD)
    {
        _tprintf(_T("LocalAlloc Error %u\n"), GetLastError());
        goto Cleanup;
    }

    if (!InitializeSecurityDescriptor(pSD,
        SECURITY_DESCRIPTOR_REVISION))
    {
        _tprintf(_T("InitializeSecurityDescriptor Error %u\n"),
            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 %u\n"),
            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, &sa, &hkSub, &dwDisposition);
    _tprintf(_T("RegCreateKeyEx result %u\n"), lRes);

Cleanup:

    if (pEveryoneSID)
        FreeSid(pEveryoneSID);
    if (pAdminSID)
        FreeSid(pAdminSID);
    if (pACL)
        LocalFree(pACL);
    if (pSD)
        LocalFree(pSD);
    if (hkSub)
        RegCloseKey(hkSub);

    return;

}
#pragma注释(lib,“advapi32.lib”)
#包括
#包括
#包括
#包括
void main()
{
德沃德·德布雷斯,德沃德·德布雷斯;
PSID pEveryoneSID=NULL,pAdminSID=NULL;
PACL PACL=NULL;
PSECURITY_描述符pSD=NULL;
显式访问ea[2];
SID\u标识符\u权限SIDAuthWorld=
世界安全局;
SID\u IDENTIFIER\u AUTHORITY SIDAuthNT=安全\u NT\u AUTHORITY;
安全(a);
长LRE;
HKEY hkSub=NULL;
//为Everyone组创建一个已知的SID。
如果(!AllocateAndInitializeSid(&SIDAuthWorld,1,
安全,世界,,
0, 0, 0, 0, 0, 0, 0,
&pEveryoneSID)
{
_tprintf(_T(“AllocateAndInitializeSid错误%u\n”),GetLastError();
去清理;
}
//初始化ACE的显式访问结构。
//ACE将允许每个人对密钥进行读取访问。
零内存(&ea,2*sizeof(显式访问));
ea[0]。grfAccessPermissions=KEY\u READ;
ea[0].grfAccessMode=SET\u ACCESS;
ea[0]。grfInheritance=NO_继承;
ea[0].Trustee.TrusteeForm=Trustee\u是\u SID;
ea[0].Trustee.TrusteeType=Trustee\u是\u众所周知的\u组;
ea[0].Trustee.ptstrName=(LPTSTR)pEveryoneSID;
//为BUILTIN\Administrators组创建SID。
如果(!AllocateAndInitializeSid(&SIDAuthNT,2,
安全性\u内置\u域\u RID,
域\u别名\u RID\u管理员,
0, 0, 0, 0, 0, 0,
&pAdminSID)
{
_tprintf(_T(“AllocateAndInitializeSid错误%u\n”),GetLastError();
去清理;
}
//初始化ACE的显式访问结构。
//ACE将允许管理员组完全访问
//钥匙。
ea[1]。grfAccessPermissions=KEY\u ALL\u ACCESS;
ea[1].grfAccessMode=SET\u ACCESS;
ea[1]。grfInheritance=NO_继承;
ea[1].Trustee.TrusteeForm=Trustee\u是\u SID;
ea[1].Trustee.TrusteeType=Trustee\u是\u组;
ea[1].Trustee.ptstrName=(LPTSTR)pAdminSID;
//创建包含新ACE的新ACL。
dwRes=setEntriesAcl(2,ea,NULL和pACL);
如果(错误\u成功!=dwRes)
{
_tprintf(_T(“SetEntriesInAcl错误%u\n”),GetLastError();
去清理;
}
//初始化安全描述符。
pSD=(PSECURITY_描述符)LocalAlloc(LPTR,
安全描述符(最小长度);
如果(NULL==pSD)
{
_tprintf(_T(“LocalAlloc错误%u\n”),GetLastError();
去清理;
}
如果(!InitializeSecurityDescriptor(pSD,
安全(描述符(修订版))
{
_tprintf(_T(“InitializeSecurityDescriptor错误%u\n”),
GetLastError());
去清理;
}
//将ACL添加到安全描述符。
如果(!SetSecurityDescriptorDacl(pSD,
TRUE,//bDaclPresent标志
pACL,
FALSE))//不是默认的DACL
{
_tprintf(_T(“SetSecurityDescriptorDacl错误%u\n”),
GetLastError());
去清理;
}
//初始化安全属性结构。
sa.nLength=sizeof(安全属性);
sa.lpSecurityDescriptor=pSD;
sa.bInheritHandle=FALSE;
//使用安全属性设置安全描述符
//创建密钥时。
lRes=RegCreateKeyEx(HKEY\U当前用户,\u T(“mykey”),0,\u T(“”),0,
按键读取、按键写入、sa、hkSub和DWD);
_tprintf(_T(“RegCreateKeyEx结果%u\n”),lRes);
清理:
if(pEveryoneSID)
自由体;
if(pAdminSID)
FreeSid(pAdminSID);
国际单项体育联合会(pACL)
本地免费(pACL);
中频(pSD)
本地自由(pSD);
国际单项体育联合会(香港分会)
RegCloseKey(hkSub);;
返回;
}

函数setEntriesAcl一直失败,错误代码87-无效参数的原因是设置了编译器选项(/Zp1)。Zp1将默认结构成员对齐方式设置为一个字节。当编译器选项设置回默认值时,函数正常工作。Zp1正在将显式访问结构的大小从48更改为40,导致出现无效参数错误


在这段经历之后,我建议不要设置全局结构打包(/Zp),而是对需要打包的结构使用#pragma pack(n);然后在定义后使用#pragma pack()重置回默认值。我很确定Zp选项会影响其他结构,比如安全描述符及其一些成员。在对内存映射文件使用安全属性时,我注意到了一个类似的问题,这在删除Zp#时得到了解决。

您发布的代码对我来说运行得非常好。你在用什么编译器?什么版本的Windows?@HarryJohnston我正在使用MSVC编译器运行Windows 10 Pro 10.0.14393。我不确定MSVC的编译器版本,但我的目标是Windows10。我还没有尝试将不同的操作系统版本作为目标,看看它是否有效。@HarryJohnston将windows 8.1作为目标也不适用于我。您使用的是什么版本的Windows和什么编译器?Visual Studio 2010。我刚刚试着在Windows10(Build1607)上运行这个可执行文件,它在那里也可以运行。你应该把它作为一个答案发布。它对未来的读者很有帮助。