无法在具有不同语言设置的 PC 上设置组策略设置
Can't set group policy settings on PC's with different language settings
在我的程序中,我必须将某些文件的组策略设置设置为ALL APPLICATION PACKAGES
。为了实现这一点,我使用了以下函数,它将 FilePath
带到一个文件并在该文件上设置 ALL APPLICATION PACKAGES
组策略:
DWORD AdjustGroupPolicy(std::wstring wstrFilePath)
{
PACL pOldDACL = NULL, pNewDACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
EXPLICIT_ACCESS eaAccess;
SECURITY_INFORMATION siInfo = DACL_SECURITY_INFORMATION;
DWORD dwResult = ERROR_SUCCESS;
dwResult = GetNamedSecurityInfo(wstrFilePath.c_str(), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldDACL, NULL, &pSD);
if (dwResult != ERROR_SUCCESS)
{
if (pSD != NULL)
LocalFree((HLOCAL)pSD);
}
ZeroMemory(&eaAccess, sizeof(EXPLICIT_ACCESS));
eaAccess.grfAccessPermissions = GENERIC_READ | GENERIC_EXECUTE;
eaAccess.grfAccessMode = SET_ACCESS;
eaAccess.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
eaAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
eaAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
eaAccess.Trustee.ptstrName = L"ALL APPLICATION PACKAGES";
dwResult = SetEntriesInAcl(1, &eaAccess, pOldDACL, &pNewDACL);
if (ERROR_SUCCESS != dwResult)
{
if (pSD != NULL)
LocalFree((HLOCAL)pSD);
if (pNewDACL != NULL)
LocalFree((HLOCAL)pNewDACL);
}
dwResult = SetNamedSecurityInfo((LPWSTR)wstrFilePath.c_str(), SE_FILE_OBJECT, siInfo, NULL, NULL, pNewDACL, NULL);
if (ERROR_SUCCESS != dwResult)
{
if (pSD != NULL)
LocalFree((HLOCAL)pSD);
if (pNewDACL != NULL)
LocalFree((HLOCAL)pNewDACL);
}
return dwResult;
}
问题是,一些用户报告此功能因某种原因失败。在深入研究这个问题后,我发现在 PC 上的语言设置不是英语,该功能在 SetEntiresInAcl
处失败,错误代码为 1332 (0x534)。在MSDN documentation中,错误代码对应错误ERROR_NONE_MAPPED
,描述为:
No mapping between account names and security IDs was done.
我猜是因为 ALL APPLICATION PACKAGES
根据语言设置的不同而被命名,因此 Windows 找不到它的安全 ID;但是,我不确定如何修复此错误。我该如何解决这个错误,以便无论用户语言设置如何,该功能都能可靠地工作?
我对 Windows 中的访问控制策略还比较陌生,在我当前的项目之前从未处理过它。我吸取了一个教训,我不应该按名称设置受托人,因为你不能依赖跨系统的名称相同,即使它是一个众所周知的组。
我最终通过将以下代码添加到函数中来修复它:
PSID pSID;
ConvertStringSidToSid(L"S-1-15-2-1", &pSID); // S-1-15-2 is the SID for ALL_APP_PACKAGES
后来当我设置受托人信息时,我将代码更改为:
eaAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
eaAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
eaAccess.Trustee.ptstrName = (LPTSTR)pSID;
ConvertStringSidToSid
采用字符串格式的 SID 和 returns 指向相应 SID 结构的指针。然后我可以使用该 SID 而不是使用它的名称,这避免了我之前遇到的翻译问题。
在我的程序中,我必须将某些文件的组策略设置设置为ALL APPLICATION PACKAGES
。为了实现这一点,我使用了以下函数,它将 FilePath
带到一个文件并在该文件上设置 ALL APPLICATION PACKAGES
组策略:
DWORD AdjustGroupPolicy(std::wstring wstrFilePath)
{
PACL pOldDACL = NULL, pNewDACL = NULL;
PSECURITY_DESCRIPTOR pSD = NULL;
EXPLICIT_ACCESS eaAccess;
SECURITY_INFORMATION siInfo = DACL_SECURITY_INFORMATION;
DWORD dwResult = ERROR_SUCCESS;
dwResult = GetNamedSecurityInfo(wstrFilePath.c_str(), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldDACL, NULL, &pSD);
if (dwResult != ERROR_SUCCESS)
{
if (pSD != NULL)
LocalFree((HLOCAL)pSD);
}
ZeroMemory(&eaAccess, sizeof(EXPLICIT_ACCESS));
eaAccess.grfAccessPermissions = GENERIC_READ | GENERIC_EXECUTE;
eaAccess.grfAccessMode = SET_ACCESS;
eaAccess.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
eaAccess.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
eaAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
eaAccess.Trustee.ptstrName = L"ALL APPLICATION PACKAGES";
dwResult = SetEntriesInAcl(1, &eaAccess, pOldDACL, &pNewDACL);
if (ERROR_SUCCESS != dwResult)
{
if (pSD != NULL)
LocalFree((HLOCAL)pSD);
if (pNewDACL != NULL)
LocalFree((HLOCAL)pNewDACL);
}
dwResult = SetNamedSecurityInfo((LPWSTR)wstrFilePath.c_str(), SE_FILE_OBJECT, siInfo, NULL, NULL, pNewDACL, NULL);
if (ERROR_SUCCESS != dwResult)
{
if (pSD != NULL)
LocalFree((HLOCAL)pSD);
if (pNewDACL != NULL)
LocalFree((HLOCAL)pNewDACL);
}
return dwResult;
}
问题是,一些用户报告此功能因某种原因失败。在深入研究这个问题后,我发现在 PC 上的语言设置不是英语,该功能在 SetEntiresInAcl
处失败,错误代码为 1332 (0x534)。在MSDN documentation中,错误代码对应错误ERROR_NONE_MAPPED
,描述为:
No mapping between account names and security IDs was done.
我猜是因为 ALL APPLICATION PACKAGES
根据语言设置的不同而被命名,因此 Windows 找不到它的安全 ID;但是,我不确定如何修复此错误。我该如何解决这个错误,以便无论用户语言设置如何,该功能都能可靠地工作?
我对 Windows 中的访问控制策略还比较陌生,在我当前的项目之前从未处理过它。我吸取了一个教训,我不应该按名称设置受托人,因为你不能依赖跨系统的名称相同,即使它是一个众所周知的组。
我最终通过将以下代码添加到函数中来修复它:
PSID pSID;
ConvertStringSidToSid(L"S-1-15-2-1", &pSID); // S-1-15-2 is the SID for ALL_APP_PACKAGES
后来当我设置受托人信息时,我将代码更改为:
eaAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
eaAccess.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
eaAccess.Trustee.ptstrName = (LPTSTR)pSID;
ConvertStringSidToSid
采用字符串格式的 SID 和 returns 指向相应 SID 结构的指针。然后我可以使用该 SID 而不是使用它的名称,这避免了我之前遇到的翻译问题。