2011年7月8日 星期五

Setting ACL by Well-Known SID Instead of Name to Avoid Multilingual Issue

以下這段 code 在大部份語系的 Windows 上試過都沒問題, 但卻在俄文語系失敗.

    EXPLICIT_ACCESS ea;
    BuildExplicitAccessWithName(&ea, _T("Everyone"), GENERIC_ALL,
        SET_ACCESS, SUB_CONTAINERS_AND_OBJECTS_INHERIT);
    SetEntriesInAcl(1, &ea, NULL, ...)

明眼人一看就知道, 這應該是跟 "Everyone" 這字串有關係. 沒錯, 在大部份語系上都有 "Everyone" 這個使用者的權限, 但在俄文語系上就轉譯為俄文了, 不叫 "Everyone" 了.

因此我們必須直接使用 security identifier(SID) 來避免多國語言的問題. Windows API 中 AllocateAndInitializeSid 或是 CreateWellKnownSid 都可用來取得 SID, 以下使用 AllocateAndInitializeSid 為例.

    // Get well-known SID.
    SID_IDENTIFIER_AUTHORITY authWorld = SECURITY_WORLD_SID_AUTHORITY;
    PSID everyoneSid = NULL;
    AllocateAndInitializeSid(&authWorld, 1,
        SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0,
        &everyoneSid))

    // Build EA.
    EXPLICIT_ACCESS ea;
    ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
    ea.grfAccessPermissions = GENERIC_ALL;
    ea.grfAccessMode = SET_ACCESS;
    ea.grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT;
    ea.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
    ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
    ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    ea.Trustee.ptstrName = (LPTSTR)everyoneSid;

    // Set ACL.
    SetEntriesInAcl(1, &ea, NULL, ...);

    FreeSid(everyoneSid);

沒有留言:

張貼留言