sync advapi32 winetest to wine 1.1.31
authorChristoph von Wittich <christoph_vw@reactos.org>
Sun, 18 Oct 2009 14:57:22 +0000 (14:57 +0000)
committerChristoph von Wittich <christoph_vw@reactos.org>
Sun, 18 Oct 2009 14:57:22 +0000 (14:57 +0000)
svn path=/trunk/; revision=43556

rostests/winetests/advapi32/cred.c
rostests/winetests/advapi32/crypt_sha.c
rostests/winetests/advapi32/lsa.c
rostests/winetests/advapi32/registry.c
rostests/winetests/advapi32/security.c
rostests/winetests/advapi32/service.c

index ad06fd5..6b7fa26 100644 (file)
@@ -101,8 +101,8 @@ static void test_CredWriteA(void)
     ret = pCredWriteA(&new_cred, 0);
     if (ret)
     {
-        /* Vista */
-        ok(GetLastError() == ERROR_IO_PENDING,
+        ok(GetLastError() == ERROR_SUCCESS ||
+           GetLastError() == ERROR_IO_PENDING, /* Vista */
            "Expected ERROR_IO_PENDING, got %d\n", GetLastError());
     }
     else
@@ -154,12 +154,13 @@ static void test_CredReadDomainCredentialsA(void)
 
     /* these two tests would crash on both native and Wine. Implementations
      * does not check for NULL output pointers and try to zero them out early */
-#if 0
+if(0)
+{
     ok(!pCredReadDomainCredentialsA(&info, 0, NULL, &creds) &&
             GetLastError() == ERROR_INVALID_PARAMETER, "!\n");
     ok(!pCredReadDomainCredentialsA(&info, 0, &count, NULL) &&
             GetLastError() == ERROR_INVALID_PARAMETER, "!\n");
-#endif
+}
 
     SetLastError(0xdeadbeef);
     ret = pCredReadDomainCredentialsA(NULL, 0, &count, &creds);
index 025f2cd..2737ee7 100644 (file)
@@ -35,21 +35,22 @@ typedef struct {
 
 static void test_sha_ctx(void)
 {
-   FARPROC pA_SHAInit, pA_SHAUpdate, pA_SHAFinal;
-   static const char test_buffer[] = "In our Life there's If"
-                       "In our beliefs there's Lie"
-                       "In our business there is Sin"
-                       "In our bodies, there is Die";
-   ULONG test_buffer_size = strlen(test_buffer);
+    void (WINAPI *pA_SHAInit)(PSHA_CTX);
+    void (WINAPI *pA_SHAUpdate)(PSHA_CTX, const unsigned char *, UINT);
+    void (WINAPI *pA_SHAFinal)(PSHA_CTX, PULONG);
+    static const unsigned char test_buffer[] = "In our Life there's If"
+                                               "In our beliefs there's Lie"
+                                               "In our business there is Sin"
+                                               "In our bodies, there is Die";
    HMODULE hmod;
    SHA_CTX ctx;
    ULONG result[5];
    ULONG result_correct[5] = {0xe014f93, 0xe09791ec, 0x6dcf96c8, 0x8e9385fc, 0x1611c1bb};
 
    hmod = GetModuleHandleA("advapi32.dll");
-   pA_SHAInit = GetProcAddress(hmod, "A_SHAInit");
-   pA_SHAUpdate = GetProcAddress(hmod, "A_SHAUpdate");
-   pA_SHAFinal = GetProcAddress(hmod, "A_SHAFinal");
+   pA_SHAInit = (void *)GetProcAddress(hmod, "A_SHAInit");
+   pA_SHAUpdate = (void *)GetProcAddress(hmod, "A_SHAUpdate");
+   pA_SHAFinal = (void *)GetProcAddress(hmod, "A_SHAFinal");
 
    if (!pA_SHAInit || !pA_SHAUpdate || !pA_SHAFinal)
    {
@@ -59,8 +60,8 @@ static void test_sha_ctx(void)
 
    RtlZeroMemory(&ctx, sizeof(ctx));
    pA_SHAInit(&ctx);
-   pA_SHAUpdate(&ctx, test_buffer, test_buffer_size);
-   pA_SHAUpdate(&ctx, test_buffer, test_buffer_size);
+   pA_SHAUpdate(&ctx, test_buffer, sizeof(test_buffer)-1);
+   pA_SHAUpdate(&ctx, test_buffer, sizeof(test_buffer)-1);
    pA_SHAFinal(&ctx, result);
    ok(!memcmp(result, result_correct, sizeof(result)), "incorrect result\n");
 }
index e69e4e1..efb75bb 100644 (file)
@@ -41,7 +41,8 @@ static NTSTATUS (WINAPI *pLsaEnumerateAccountRights)(LSA_HANDLE,PSID,PLSA_UNICOD
 static NTSTATUS (WINAPI *pLsaFreeMemory)(PVOID);
 static NTSTATUS (WINAPI *pLsaOpenPolicy)(PLSA_UNICODE_STRING,PLSA_OBJECT_ATTRIBUTES,ACCESS_MASK,PLSA_HANDLE);
 static NTSTATUS (WINAPI *pLsaQueryInformationPolicy)(LSA_HANDLE,POLICY_INFORMATION_CLASS,PVOID*);
-static BOOL     (WINAPI *pConvertSidToStringSidA)(PSID pSid, LPSTR *str);
+static BOOL     (WINAPI *pConvertSidToStringSidA)(PSID,LPSTR*);
+static NTSTATUS (WINAPI *pLsaLookupNames2)(LSA_HANDLE,ULONG,ULONG,PLSA_UNICODE_STRING,PLSA_REFERENCED_DOMAIN_LIST*,PLSA_TRANSLATED_SID2*);
 
 static BOOL init(void)
 {
@@ -53,6 +54,7 @@ static BOOL init(void)
     pLsaOpenPolicy = (void*)GetProcAddress(hadvapi32, "LsaOpenPolicy");
     pLsaQueryInformationPolicy = (void*)GetProcAddress(hadvapi32, "LsaQueryInformationPolicy");
     pConvertSidToStringSidA = (void*)GetProcAddress(hadvapi32, "ConvertSidToStringSidA");
+    pLsaLookupNames2 = (void*)GetProcAddress(hadvapi32, "LsaLookupNames2");
 
     if (pLsaClose && pLsaEnumerateAccountRights && pLsaFreeMemory && pLsaOpenPolicy && pLsaQueryInformationPolicy && pConvertSidToStringSidA)
         return TRUE;
@@ -216,6 +218,139 @@ static void test_lsa(void)
     }
 }
 
+static void get_sid_info(PSID psid, LPSTR *user, LPSTR *dom)
+{
+    static char account[257], domain[257];
+    DWORD user_size, dom_size;
+    SID_NAME_USE use;
+    BOOL ret;
+
+    *user = account;
+    *dom = domain;
+
+    user_size = dom_size = 257;
+    account[0] = domain[0] = 0;
+    ret = LookupAccountSidA(NULL, psid, account, &user_size, domain, &dom_size, &use);
+    ok(ret, "LookupAccountSidA failed %u\n", GetLastError());
+}
+
+static void test_LsaLookupNames2(void)
+{
+    static const WCHAR n1[] = {'L','O','C','A','L',' ','S','E','R','V','I','C','E'};
+    static const WCHAR n2[] = {'N','T',' ','A','U','T','H','O','R','I','T','Y','\\','L','o','c','a','l','S','e','r','v','i','c','e'};
+
+    NTSTATUS status;
+    LSA_HANDLE handle;
+    LSA_OBJECT_ATTRIBUTES attrs;
+    PLSA_REFERENCED_DOMAIN_LIST domains;
+    PLSA_TRANSLATED_SID2 sids;
+    LSA_UNICODE_STRING name[3];
+    LPSTR account, sid_dom;
+
+    if (!pLsaLookupNames2)
+    {
+        win_skip("LsaLookupNames2 not avaliable\n");
+        return;
+    }
+
+    if (PRIMARYLANGID(LANGIDFROMLCID(GetThreadLocale())) != LANG_ENGLISH)
+    {
+        skip("Non-english locale (skipping LsaLookupNames2 tests)\n");
+        return;
+    }
+
+    memset(&attrs, 0, sizeof(attrs));
+    attrs.Length = sizeof(attrs);
+
+    status = pLsaOpenPolicy(NULL, &attrs, POLICY_ALL_ACCESS, &handle);
+    ok(status == STATUS_SUCCESS || status == STATUS_ACCESS_DENIED,
+       "LsaOpenPolicy(POLICY_ALL_ACCESS) returned 0x%08x\n", status);
+
+    /* try a more restricted access mask if necessary */
+    if (status == STATUS_ACCESS_DENIED)
+    {
+        trace("LsaOpenPolicy(POLICY_ALL_ACCESS) failed, trying POLICY_VIEW_LOCAL_INFORMATION\n");
+        status = pLsaOpenPolicy(NULL, &attrs, POLICY_LOOKUP_NAMES, &handle);
+        ok(status == STATUS_SUCCESS, "LsaOpenPolicy(POLICY_VIEW_LOCAL_INFORMATION) returned 0x%08x\n", status);
+    }
+    if (status != STATUS_SUCCESS)
+    {
+        skip("Cannot acquire policy handle\n");
+        return;
+    }
+
+    name[0].Buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(n1));
+    name[0].Length = name[0].MaximumLength = sizeof(n1);
+    memcpy(name[0].Buffer, n1, sizeof(n1));
+
+    name[1].Buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(n1));
+    name[1].Length = name[1].MaximumLength = sizeof(n1) - sizeof(WCHAR);
+    memcpy(name[1].Buffer, n1, sizeof(n1) - sizeof(WCHAR));
+
+    name[2].Buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(n2));
+    name[2].Length = name[2].MaximumLength = sizeof(n2);
+    memcpy(name[2].Buffer, n2, sizeof(n2));
+
+    /* account name only */
+    sids = NULL;
+    domains = NULL;
+    status = pLsaLookupNames2(handle, 0, 1, &name[0], &domains, &sids);
+    ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %x)\n", status);
+    ok(sids[0].Use == SidTypeWellKnownGroup, "expected SidTypeWellKnownGroup, got %u\n", sids[0].Use);
+    ok(sids[0].Flags == 0, "expected 0, got 0x%08x\n", sids[0].Flags);
+    ok(domains->Entries == 1, "expected 1, got %u\n", domains->Entries);
+    get_sid_info(sids[0].Sid, &account, &sid_dom);
+    ok(!strcmp(account, "LOCAL SERVICE"), "expected \"LOCAL SERVICE\", got \"%s\"\n", account);
+    ok(!strcmp(sid_dom, "NT AUTHORITY"), "expected \"NT AUTHORITY\", got \"%s\"\n", sid_dom);
+    pLsaFreeMemory(sids);
+    pLsaFreeMemory(domains);
+
+    /* unknown account name */
+    sids = NULL;
+    domains = NULL;
+    status = pLsaLookupNames2(handle, 0, 1, &name[1], &domains, &sids);
+    ok(status == STATUS_NONE_MAPPED, "expected STATUS_NONE_MAPPED, got %x)\n", status);
+    ok(sids[0].Use == SidTypeUnknown, "expected SidTypeUnknown, got %u\n", sids[0].Use);
+    ok(sids[0].Flags == 0, "expected 0, got 0x%08x\n", sids[0].Flags);
+    ok(domains->Entries == 0, "expected 0, got %u\n", domains->Entries);
+    pLsaFreeMemory(sids);
+    pLsaFreeMemory(domains);
+
+    /* account + domain */
+    sids = NULL;
+    domains = NULL;
+    status = pLsaLookupNames2(handle, 0, 1, &name[2], &domains, &sids);
+    ok(status == STATUS_SUCCESS, "expected STATUS_SUCCESS, got %x)\n", status);
+    ok(sids[0].Use == SidTypeWellKnownGroup, "expected SidTypeWellKnownGroup, got %u\n", sids[0].Use);
+    ok(sids[0].Flags == 0, "expected 0, got 0x%08x\n", sids[0].Flags);
+    ok(domains->Entries == 1, "expected 1, got %u\n", domains->Entries);
+    get_sid_info(sids[0].Sid, &account, &sid_dom);
+    ok(!strcmp(account, "LOCAL SERVICE"), "expected \"LOCAL SERVICE\", got \"%s\"\n", account);
+    ok(!strcmp(sid_dom, "NT AUTHORITY"), "expected \"NT AUTHORITY\", got \"%s\"\n", sid_dom);
+    pLsaFreeMemory(sids);
+    pLsaFreeMemory(domains);
+
+    /* all three */
+    sids = NULL;
+    domains = NULL;
+    status = pLsaLookupNames2(handle, 0, 3, name, &domains, &sids);
+    ok(status == STATUS_SOME_NOT_MAPPED, "expected STATUS_SOME_NOT_MAPPED, got %x)\n", status);
+    ok(sids[0].Use == SidTypeWellKnownGroup, "expected SidTypeWellKnownGroup, got %u\n", sids[0].Use);
+    ok(sids[1].Use == SidTypeUnknown, "expected SidTypeUnknown, got %u\n", sids[0].Use);
+    ok(sids[2].Use == SidTypeWellKnownGroup, "expected SidTypeWellKnownGroup, got %u\n", sids[0].Use);
+    ok(sids[0].DomainIndex == 0, "expected 0, got %u\n", sids[0].DomainIndex);
+    ok(domains->Entries == 1, "expected 1, got %u\n", domains->Entries);
+    pLsaFreeMemory(sids);
+    pLsaFreeMemory(domains);
+
+    HeapFree(GetProcessHeap(), 0, name[0].Buffer);
+    HeapFree(GetProcessHeap(), 0, name[1].Buffer);
+    HeapFree(GetProcessHeap(), 0, name[2].Buffer);
+
+    status = pLsaClose(handle);
+    ok(status == STATUS_SUCCESS, "LsaClose() failed, returned 0x%08x\n", status);
+}
+
 START_TEST(lsa)
 {
     if (!init()) {
@@ -224,4 +359,5 @@ START_TEST(lsa)
     }
 
     test_lsa();
+    test_LsaLookupNames2();
 }
index 47e76b2..abc2eb4 100644 (file)
@@ -111,57 +111,6 @@ static const char *wine_debugstr_an( const char *str, int n )
     return res;
 }
 
-static const char *wine_debugstr_wn( const WCHAR *str, int n )
-{
-    char *dst, *res;
-    size_t size;
-
-    if (!HIWORD(str))
-    {
-        if (!str) return "(null)";
-        res = get_temp_buffer( 6 );
-        sprintf( res, "#%04x", LOWORD(str) );
-        return res;
-    }
-    if (n == -1) n = lstrlenW(str);
-    if (n < 0) n = 0;
-    size = 12 + min( 300, n * 5);
-    dst = res = get_temp_buffer( n * 5 + 7 );
-    *dst++ = 'L';
-    *dst++ = '"';
-    while (n-- > 0 && dst <= res + size - 10)
-    {
-        WCHAR c = *str++;
-        switch (c)
-        {
-        case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
-        case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
-        case '\t': *dst++ = '\\'; *dst++ = 't'; break;
-        case '"':  *dst++ = '\\'; *dst++ = '"'; break;
-        case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
-        default:
-            if (c >= ' ' && c <= 126)
-                *dst++ = (char)c;
-            else
-            {
-                *dst++ = '\\';
-                sprintf(dst,"%04x",c);
-                dst+=4;
-            }
-        }
-    }
-    *dst++ = '"';
-    if (n > 0)
-    {
-        *dst++ = '.';
-        *dst++ = '.';
-        *dst++ = '.';
-    }
-    *dst = 0;
-    return res;
-}
-
-
 #define ADVAPI32_GET_PROC(func) \
     p ## func = (void*)GetProcAddress(hadvapi32, #func);
 
@@ -288,8 +237,8 @@ static void _test_hkey_main_Value_W(int line, LPCWSTR name, LPCWSTR string,
     if (string)
     {
         lok(memcmp(value, string, cbData) == 0, "RegQueryValueExW failed: %s/%d != %s/%d\n",
-           wine_debugstr_wn((WCHAR*)value, cbData / sizeof(WCHAR)), cbData,
-           wine_debugstr_wn(string, full_byte_len / sizeof(WCHAR)), full_byte_len);
+           wine_dbgstr_wn((WCHAR*)value, cbData / sizeof(WCHAR)), cbData,
+           wine_dbgstr_wn(string, full_byte_len / sizeof(WCHAR)), full_byte_len);
     }
     /* This implies that when cbData == 0, RegQueryValueExW() should not modify the buffer */
     lok(*(value+cbData) == 0xbd, "RegQueryValueExW/2 overflowed at %u: %02x != bd\n", cbData, *(value+cbData));
@@ -959,6 +908,12 @@ static void test_reg_open_key(void)
     ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", NULL);
     ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret);
 
+    ret = RegOpenKeyA(HKEY_CURRENT_USER, NULL, NULL);
+    ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret);
+
+    ret = RegOpenKeyA(NULL, NULL, NULL);
+    ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret);
+
     /*  beginning backslash character */
     ret = RegOpenKeyA(HKEY_CURRENT_USER, "\\Software\\Wine\\Test", &hkResult);
        ok(ret == ERROR_BAD_PATHNAME || /* NT/2k/XP */
index af52a3a..dfcd45b 100644 (file)
@@ -92,6 +92,9 @@ typedef BOOL (WINAPI *fnSetFileSecurityA)(LPCSTR, SECURITY_INFORMATION,
 static DWORD (WINAPI *pGetNamedSecurityInfoA)(LPSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION,
                                               PSID*, PSID*, PACL*, PACL*,
                                               PSECURITY_DESCRIPTOR*);
+static PDWORD (WINAPI *pGetSidSubAuthority)(PSID, DWORD);
+static PUCHAR (WINAPI *pGetSidSubAuthorityCount)(PSID);
+static BOOL (WINAPI *pIsValidSid)(PSID);
 typedef DWORD (WINAPI *fnRtlAdjustPrivilege)(ULONG,BOOLEAN,BOOLEAN,PBOOLEAN);
 typedef BOOL (WINAPI *fnCreateWellKnownSid)(WELL_KNOWN_SID_TYPE,PSID,PSID,DWORD*);
 typedef BOOL (WINAPI *fnDuplicateTokenEx)(HANDLE,DWORD,LPSECURITY_ATTRIBUTES,
@@ -160,6 +163,9 @@ static void init(void)
     pSetFileSecurityA = (fnSetFileSecurityA)GetProcAddress(hmod, "SetFileSecurityA" );
     pCreateWellKnownSid = (fnCreateWellKnownSid)GetProcAddress( hmod, "CreateWellKnownSid" );
     pGetNamedSecurityInfoA = (void *)GetProcAddress(hmod, "GetNamedSecurityInfoA");
+    pGetSidSubAuthority = (void *)GetProcAddress(hmod, "GetSidSubAuthority");
+    pGetSidSubAuthorityCount = (void *)GetProcAddress(hmod, "GetSidSubAuthorityCount");
+    pIsValidSid = (void *)GetProcAddress(hmod, "IsValidSid");
     pMakeSelfRelativeSD = (void *)GetProcAddress(hmod, "MakeSelfRelativeSD");
     pSetEntriesInAclW = (void *)GetProcAddress(hmod, "SetEntriesInAclW");
     pSetSecurityDescriptorControl = (void *)GetProcAddress(hmod, "SetSecurityDescriptorControl");
@@ -2390,7 +2396,8 @@ static void test_impersonation_level(void)
     /* can't perform access check when opening object against an anonymous impersonation token */
     todo_wine {
     error = RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
-    ok(error == ERROR_INVALID_HANDLE, "RegOpenKeyEx should have failed with ERROR_INVALID_HANDLE instead of %d\n", error);
+    ok(error == ERROR_INVALID_HANDLE || error == ERROR_CANT_OPEN_ANONYMOUS,
+       "RegOpenKeyEx should have failed with ERROR_INVALID_HANDLE or ERROR_CANT_OPEN_ANONYMOUS instead of %d\n", error);
     }
     RevertToSelf();
 
@@ -2443,7 +2450,8 @@ static void test_impersonation_level(void)
     /* can't perform access check when opening object against an identification impersonation token */
     error = RegOpenKeyEx(HKEY_CURRENT_USER, "Software", 0, KEY_READ, &hkey);
     todo_wine {
-    ok(error == ERROR_INVALID_HANDLE, "RegOpenKeyEx should have failed with ERROR_INVALID_HANDLE instead of %d\n", error);
+    ok(error == ERROR_INVALID_HANDLE || error == ERROR_BAD_IMPERSONATION_LEVEL,
+       "RegOpenKeyEx should have failed with ERROR_INVALID_HANDLE or ERROR_BAD_IMPERSONATION_LEVEL instead of %d\n", error);
     }
     ret = PrivilegeCheck(Token, PrivilegeSet, &AccessGranted);
     ok(ret, "PrivilegeCheck for SecurityIdentification failed with error %d\n", GetLastError());
@@ -2476,6 +2484,7 @@ static void test_SetEntriesInAcl(void)
     SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
     EXPLICIT_ACCESSW ExplicitAccess;
     static const WCHAR wszEveryone[] = {'E','v','e','r','y','o','n','e',0};
+    static const WCHAR wszCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
 
     if (!pSetEntriesInAclW)
     {
@@ -2569,6 +2578,13 @@ static void test_SetEntriesInAcl(void)
         LocalFree(NewAcl);
     }
 
+    ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_USER;
+    ExplicitAccess.Trustee.ptstrName = (LPWSTR)wszCurrentUser;
+    res = pSetEntriesInAclW(1, &ExplicitAccess, OldAcl, &NewAcl);
+    ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
+    ok(NewAcl != NULL, "returned acl was NULL\n");
+    LocalFree(NewAcl);
+
     ExplicitAccess.grfAccessMode = REVOKE_ACCESS;
     ExplicitAccess.Trustee.TrusteeForm = TRUSTEE_IS_SID;
     ExplicitAccess.Trustee.ptstrName = UsersSid;
@@ -3036,20 +3052,25 @@ static void test_PrivateObjectSecurity(void)
         "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError());
     ok(retSize <= dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize);
     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed err=%u\n", GetLastError());
-    CHECK_RESULT_AND_FREE("G:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)");
+    CHECK_ONE_OF_AND_FREE("G:S-1-5-21-93476-23408-4576D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)",
+        "G:S-1-5-21-93476-23408-4576D:P(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"); /* Win7 */
     GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
-    expect_eq(ctrl, 0x8004, int, "%x");
+    expect_eq(ctrl & (~ SE_DACL_PROTECTED), 0x8004, int, "%x");
 
     ok(GetPrivateObjectSecurity(sec, sec_info, buf, dwDescSize, &retSize),
         "GetPrivateObjectSecurity failed (err=%u)\n", GetLastError());
     ok(retSize == dwDescSize, "Buffer too small (%d vs %d)\n", retSize, dwDescSize);
     ok(pConvertSecurityDescriptorToStringSecurityDescriptorA(buf, SDDL_REVISION_1, sec_info, &string, &len), "Conversion failed\n");
-    CHECK_RESULT_AND_FREE("O:SY"
+    CHECK_ONE_OF_AND_FREE("O:SY"
         "G:S-1-5-21-93476-23408-4576"
         "D:(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
-        "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)");
+        "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)",
+      "O:SY"
+        "G:S-1-5-21-93476-23408-4576"
+        "D:P(A;NP;GAGXGWGR;;;SU)(A;IOID;CCDC;;;SU)(D;OICI;0xffffffff;;;S-1-5-21-93476-23408-4576)"
+        "S:(AU;OICINPIOIDSAFA;CCDCLCSWRPRC;;;SU)(AU;NPSA;0x12019f;;;SU)"); /* Win7 */
     GetSecurityDescriptorControl(buf, &ctrl, &dwRevision);
-    expect_eq(ctrl, 0x8014, int, "%x");
+    expect_eq(ctrl & (~ SE_DACL_PROTECTED), 0x8014, int, "%x");
 
     SetLastError(0xdeadbeef);
     ok(GetPrivateObjectSecurity(sec, sec_info, buf, 5, &retSize) == FALSE, "GetPrivateObjectSecurity should have failed\n");
@@ -3176,6 +3197,34 @@ static void test_GetSecurityInfo(void)
     CloseHandle(obj);
 }
 
+static void test_GetSidSubAuthority(void)
+{
+    PSID psid = NULL;
+
+    if (!pGetSidSubAuthority || !pConvertStringSidToSidA || !pIsValidSid || !pGetSidSubAuthorityCount)
+    {
+        win_skip("Some functions not available\n");
+        return;
+    }
+    /* Note: on windows passing in an invalid index like -1, lets GetSidSubAuthority return 0x05000000 but
+             still GetLastError returns ERROR_SUCCESS then. We don't test these unlikely cornercases here for now */
+    ok(pConvertStringSidToSidA("S-1-5-21-93476-23408-4576",&psid),"ConvertStringSidToSidA failed\n");
+    ok(pIsValidSid(psid),"Sid is not valid\n");
+    SetLastError(0xbebecaca);
+    ok(*pGetSidSubAuthorityCount(psid) == 4,"GetSidSubAuthorityCount gave %d expected 4\n",*pGetSidSubAuthorityCount(psid));
+    ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
+    SetLastError(0xbebecaca);
+    ok(*pGetSidSubAuthority(psid,0) == 21,"GetSidSubAuthority gave %d expected 21\n",*pGetSidSubAuthority(psid,0));
+    ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
+    SetLastError(0xbebecaca);
+    ok(*pGetSidSubAuthority(psid,1) == 93476,"GetSidSubAuthority gave %d expected 93476\n",*pGetSidSubAuthority(psid,1));
+    ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
+    SetLastError(0xbebecaca);
+    todo_wine ok(*pGetSidSubAuthority(psid,4) == 0,"GetSidSubAuthority gave %d,expected 0\n",*pGetSidSubAuthority(psid,4));
+    ok(GetLastError() == 0,"GetLastError returned %d instead of 0\n",GetLastError());
+    LocalFree(psid);
+}
+
 START_TEST(security)
 {
     init();
@@ -3205,4 +3254,5 @@ START_TEST(security)
     test_PrivateObjectSecurity();
     test_acls();
     test_GetSecurityInfo();
+    test_GetSidSubAuthority();
 }
index b924c69..0851384 100644 (file)
@@ -28,6 +28,7 @@
 #include "winsvc.h"
 #include "winnls.h"
 #include "lmcons.h"
+#include "aclapi.h"
 
 #include "wine/test.h"
 
@@ -37,6 +38,8 @@ static BOOL (WINAPI *pChangeServiceConfig2A)(SC_HANDLE,DWORD,LPVOID);
 static BOOL (WINAPI *pEnumServicesStatusExA)(SC_HANDLE, SC_ENUM_TYPE, DWORD,
                                              DWORD, LPBYTE, DWORD, LPDWORD,
                                              LPDWORD, LPDWORD, LPCSTR);
+static DWORD (WINAPI *pGetSecurityInfo)(HANDLE, SE_OBJECT_TYPE, SECURITY_INFORMATION,
+                                        PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*);
 static BOOL (WINAPI *pQueryServiceConfig2A)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
 static BOOL (WINAPI *pQueryServiceConfig2W)(SC_HANDLE,DWORD,LPBYTE,DWORD,LPDWORD);
 static BOOL (WINAPI *pQueryServiceStatusEx)(SC_HANDLE, SC_STATUS_TYPE, LPBYTE,
@@ -48,6 +51,7 @@ static void init_function_pointers(void)
 
     pChangeServiceConfig2A = (void*)GetProcAddress(hadvapi32, "ChangeServiceConfig2A");
     pEnumServicesStatusExA= (void*)GetProcAddress(hadvapi32, "EnumServicesStatusExA");
+    pGetSecurityInfo = (void *)GetProcAddress(hadvapi32, "GetSecurityInfo");
     pQueryServiceConfig2A= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2A");
     pQueryServiceConfig2W= (void*)GetProcAddress(hadvapi32, "QueryServiceConfig2W");
     pQueryServiceStatusEx= (void*)GetProcAddress(hadvapi32, "QueryServiceStatusEx");
@@ -1743,7 +1747,17 @@ static void test_sequence(void)
         return;
     }
     else
+    {
         ok(svc_handle != NULL, "Could not create the service : %d\n", GetLastError());
+        if ((svc_handle != NULL) && (pGetSecurityInfo != NULL))
+        {
+            PSID sidOwner, sidGroup;
+            PACL dacl, sacl;
+            PSECURITY_DESCRIPTOR pSD;
+            HRESULT retval = pGetSecurityInfo(svc_handle,SE_SERVICE,DACL_SECURITY_INFORMATION,&sidOwner,&sidGroup,&dacl,&sacl,&pSD);
+            todo_wine ok(ERROR_SUCCESS == retval, "Expected GetSecurityInfo to succeed: result %d\n",retval);
+        }
+    }
 
     if (!svc_handle) return;