[ADVAPI32_WINETEST] Sync with Wine Staging 2.16. CORE-13762
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 8 Oct 2017 10:06:20 +0000 (11:06 +0100)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 8 Oct 2017 12:41:17 +0000 (13:41 +0100)
modules/rostests/winetests/advapi32/CMakeLists.txt
modules/rostests/winetests/advapi32/eventlog.c
modules/rostests/winetests/advapi32/registry.c
modules/rostests/winetests/advapi32/security.c

index d6958f4..5005dd5 100644 (file)
@@ -22,5 +22,5 @@ if(NOT MSVC)
 endif()
 
 set_module_type(advapi32_winetest win32cui)
-add_importlibs(advapi32_winetest advapi32 ole32 msvcrt kernel32 ntdll)
+add_importlibs(advapi32_winetest advapi32 ole32 user32 msvcrt kernel32 ntdll)
 add_rostests_file(TARGET advapi32_winetest)
index be9b467..8c78dcf 100644 (file)
@@ -1209,11 +1209,7 @@ static void test_start_trace(void)
     ret = StartTraceA(&handle, sessionname, properties);
     todo_wine
     ok(ret == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", ret);
-#ifndef __REACTOS__
-    properties->Wnode.Guid = (GUID){0};
-#else
     memset(&properties->Wnode.Guid, 0, sizeof(properties->Wnode.Guid));
-#endif
 
     properties->LogFileNameOffset = 0;
     ret = StartTraceA(&handle, sessionname, properties);
index 8af1ebf..053113a 100644 (file)
@@ -3523,40 +3523,76 @@ static void test_RegNotifyChangeKeyValue(void)
     CloseHandle(event);
 }
 
+static const char *dbgstr_longlong(ULONGLONG ll)
+{
+    static char buf[16][64];
+    static int idx;
+
+    idx &= 0x0f;
+
+    if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
+        sprintf(buf[idx], "0x%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll);
+    else
+        sprintf(buf[idx], "0x%08lx", (unsigned long)ll);
+
+    return buf[idx++];
+}
+
+#define cmp_li(a, b, c) cmp_li_real(a, b, c, __LINE__)
+static void cmp_li_real(LARGE_INTEGER *l1, LARGE_INTEGER *l2, LONGLONG slack, int line)
+{
+    LONGLONG diff = l2->QuadPart - l1->QuadPart;
+    if (diff < 0) diff = -diff;
+    ok_(__FILE__, line)(diff <= slack, "values don't match: %s/%s\n",
+        dbgstr_longlong(l1->QuadPart), dbgstr_longlong(l2->QuadPart));
+}
+
 static void test_RegQueryValueExPerformanceData(void)
 {
-    DWORD cbData, len;
+    static const WCHAR globalW[] = { 'G','l','o','b','a','l',0 };
+    static const WCHAR dummyW[5] = { 'd','u','m','m','y' };
+    static const char * const names[] = { NULL, "", "Global", "2" "invalid counter name" };
+    DWORD cbData, len, i, type;
     BYTE *value;
     DWORD dwret;
     LONG limit = 6;
     PERF_DATA_BLOCK *pdb;
+    HKEY hkey;
+    BYTE buf[256 + sizeof(PERF_DATA_BLOCK)];
 
     /* Test with data == NULL */
     dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, NULL, &cbData );
-    todo_wine ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
+    ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
+
+    dwret = RegQueryValueExW( HKEY_PERFORMANCE_DATA, globalW, NULL, NULL, NULL, &cbData );
+    ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
 
     /* Test ERROR_MORE_DATA, start with small buffer */
     len = 10;
     value = HeapAlloc(GetProcessHeap(), 0, len);
     cbData = len;
-    dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, value, &cbData );
-    todo_wine ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
+    type = 0xdeadbeef;
+    dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, &type, value, &cbData );
+    ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret );
+    ok(type == REG_BINARY, "got %u\n", type);
     while( dwret == ERROR_MORE_DATA && limit)
     {
         len = len * 10;
         value = HeapReAlloc( GetProcessHeap(), 0, value, len );
         cbData = len;
-        dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, value, &cbData );
+        type = 0xdeadbeef;
+        dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, &type, value, &cbData );
         limit--;
     }
     ok(limit > 0, "too many times ERROR_MORE_DATA returned\n");
 
-    todo_wine ok(dwret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", dwret);
+    ok(dwret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", dwret);
+    ok(type == REG_BINARY, "got %u\n", type);
 
     /* Check returned data */
     if (dwret == ERROR_SUCCESS)
     {
-        todo_wine ok(len >= sizeof(PERF_DATA_BLOCK), "got size %d\n", len);
+        ok(len >= sizeof(PERF_DATA_BLOCK), "got size %d\n", len);
         if (len >= sizeof(PERF_DATA_BLOCK)) {
             pdb = (PERF_DATA_BLOCK*) value;
             ok(pdb->Signature[0] == 'P', "expected Signature[0] = 'P', got 0x%x\n", pdb->Signature[0]);
@@ -3568,8 +3604,155 @@ static void test_RegQueryValueExPerformanceData(void)
     }
 
     HeapFree(GetProcessHeap(), 0, value);
-}
 
+    for (i = 0; i < sizeof(names)/sizeof(names[0]); i++)
+    {
+        cbData = 0xdeadbeef;
+        dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, names[i], NULL, NULL, NULL, &cbData);
+        ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
+        ok(cbData == 0, "got %u\n", cbData);
+
+        cbData = 0;
+        dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, names[i], NULL, NULL, NULL, &cbData);
+        ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
+        ok(cbData == 0, "got %u\n", cbData);
+
+        cbData = 0xdeadbeef;
+        dwret = RegQueryValueExA(HKEY_PERFORMANCE_TEXT, names[i], NULL, NULL, NULL, &cbData);
+todo_wine
+        ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
+        ok(cbData == 0, "got %u\n", cbData);
+
+        cbData = 0;
+        dwret = RegQueryValueExA(HKEY_PERFORMANCE_TEXT, names[i], NULL, NULL, NULL, &cbData);
+todo_wine
+        ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
+        ok(cbData == 0, "got %u\n", cbData);
+
+        cbData = 0xdeadbeef;
+        dwret = RegQueryValueExA(HKEY_PERFORMANCE_NLSTEXT, names[i], NULL, NULL, NULL, &cbData);
+todo_wine
+        ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
+        ok(cbData == 0, "got %u\n", cbData);
+
+        cbData = 0;
+        dwret = RegQueryValueExA(HKEY_PERFORMANCE_NLSTEXT, names[i], NULL, NULL, NULL, &cbData);
+todo_wine
+        ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret);
+        ok(cbData == 0, "got %u\n", cbData);
+    }
+
+    memset(buf, 0x77, sizeof(buf));
+    type = 0xdeadbeef;
+    cbData = sizeof(buf);
+    dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "invalid counter name", NULL, &type, buf, &cbData);
+    ok(dwret == ERROR_SUCCESS, "got %u\n", dwret);
+    ok(type == REG_BINARY, "got %u\n", type);
+    if (dwret == ERROR_SUCCESS)
+    {
+        SYSTEMTIME st;
+        WCHAR sysname[MAX_COMPUTERNAME_LENGTH + 1];
+        DWORD sysname_len;
+        LARGE_INTEGER counter, freq, ftime;
+
+        GetSystemTime(&st);
+        GetSystemTimeAsFileTime((FILETIME *)&ftime);
+        QueryPerformanceCounter(&counter);
+        QueryPerformanceFrequency(&freq);
+
+        sysname_len = MAX_COMPUTERNAME_LENGTH + 1;
+        GetComputerNameW(sysname, &sysname_len);
+
+        pdb = (PERF_DATA_BLOCK *)buf;
+        ok(pdb->Signature[0] == 'P', "got '%c'\n", pdb->Signature[0]);
+        ok(pdb->Signature[1] == 'E', "got '%c'\n", pdb->Signature[1]);
+        ok(pdb->Signature[2] == 'R', "got '%c'\n", pdb->Signature[2]);
+        ok(pdb->Signature[3] == 'F', "got '%c'\n", pdb->Signature[3]);
+
+        ok(pdb->LittleEndian == 1, "got %u\n", pdb->LittleEndian);
+        ok(pdb->Version == 1, "got %u\n", pdb->Version);
+        ok(pdb->Revision == 1, "got %u\n", pdb->Revision);
+        len = (sizeof(*pdb) + pdb->SystemNameLength + 7) & ~7;
+        ok(pdb->TotalByteLength == len, "got %u vs %u\n", pdb->TotalByteLength, len);
+        ok(pdb->HeaderLength == pdb->TotalByteLength, "got %u\n", pdb->HeaderLength);
+        ok(pdb->NumObjectTypes == 0, "got %u\n", pdb->NumObjectTypes);
+todo_wine
+        ok(pdb->DefaultObject != 0, "got %u\n", pdb->DefaultObject);
+        ok(pdb->SystemTime.wYear == st.wYear, "got %u\n", pdb->SystemTime.wYear);
+        ok(pdb->SystemTime.wMonth == st.wMonth, "got %u\n", pdb->SystemTime.wMonth);
+        ok(pdb->SystemTime.wDayOfWeek == st.wDayOfWeek, "got %u\n", pdb->SystemTime.wDayOfWeek);
+        ok(pdb->SystemTime.wDay == st.wDay, "got %u\n", pdb->SystemTime.wDay);
+        if (U(pdb->PerfTime).LowPart != 0x77777777) /* TestBot is broken */
+            cmp_li(&pdb->PerfTime, &counter, freq.QuadPart);
+        if (U(pdb->PerfFreq).LowPart != 0x77777777) /* TestBot is broken */
+            cmp_li(&pdb->PerfFreq, &freq, 0);
+        cmp_li(&pdb->PerfTime100nSec, &ftime, 200000); /* TestBot needs huge slack value */
+        ok(pdb->SystemNameLength == (sysname_len + 1) * sizeof(WCHAR), "expected %u, got %u\n",
+           (sysname_len + 1) * sizeof(WCHAR), pdb->SystemNameLength);
+        ok(pdb->SystemNameOffset == sizeof(*pdb), "got %u\n", pdb->SystemNameOffset);
+        ok(!lstrcmpW(sysname, (LPCWSTR)(pdb + 1)), "%s != %s\n",
+           wine_dbgstr_w(sysname), wine_dbgstr_w((LPCWSTR)(pdb + 1)));
+
+        len = pdb->TotalByteLength - (sizeof(*pdb) + pdb->SystemNameLength);
+        if (len)
+        {
+            BYTE remainder[8], *p;
+
+            memset(remainder, 0x77, sizeof(remainder));
+            p = buf + sizeof(*pdb) + pdb->SystemNameLength;
+            ok(!memcmp(p, remainder, len), "remainder: %02x,%02x...\n", p[0], p[1]);
+        }
+    }
+
+    dwret = RegOpenKeyA(HKEY_PERFORMANCE_DATA, NULL, &hkey);
+todo_wine
+    ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
+
+    dwret = RegOpenKeyA(HKEY_PERFORMANCE_DATA, "Global", &hkey);
+todo_wine
+    ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
+
+    dwret = RegOpenKeyExA(HKEY_PERFORMANCE_DATA, "Global", 0, KEY_READ, &hkey);
+todo_wine
+    ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
+
+    dwret = RegQueryValueA(HKEY_PERFORMANCE_DATA, "Global", NULL, (LONG *)&cbData);
+todo_wine
+    ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
+
+    dwret = RegSetValueA(HKEY_PERFORMANCE_DATA, "Global", REG_SZ, "dummy", 4);
+todo_wine
+    ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
+
+    dwret = RegSetValueExA(HKEY_PERFORMANCE_DATA, "Global", 0, REG_SZ, (const BYTE *)"dummy", 40);
+todo_wine
+    ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
+
+    cbData = sizeof(buf);
+    dwret = RegEnumKeyA(HKEY_PERFORMANCE_DATA, 0, (LPSTR)buf, cbData);
+todo_wine
+    ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
+
+    cbData = sizeof(buf);
+    dwret = RegEnumValueA(HKEY_PERFORMANCE_DATA, 0, (LPSTR)buf, &cbData, NULL, NULL, NULL, NULL);
+todo_wine
+    ok(dwret == ERROR_MORE_DATA, "got %u\n", dwret);
+todo_wine
+    ok(cbData == sizeof(buf), "got %u\n", cbData);
+
+    dwret = RegEnumValueA(HKEY_PERFORMANCE_DATA, 0, NULL, &cbData, NULL, NULL, NULL, NULL);
+    ok(dwret == ERROR_INVALID_PARAMETER, "got %u\n", dwret);
+
+    if (pRegSetKeyValueW)
+    {
+        dwret = pRegSetKeyValueW(HKEY_PERFORMANCE_DATA, NULL, globalW, REG_SZ, dummyW, sizeof(dummyW));
+todo_wine
+        ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret);
+    }
+
+    dwret = RegCloseKey(HKEY_PERFORMANCE_DATA);
+    ok(dwret == ERROR_SUCCESS, "got %u\n", dwret);
+}
 
 START_TEST(registry)
 {
index d037969..7ca17b7 100644 (file)
@@ -89,7 +89,6 @@ static VOID (WINAPI *pBuildTrusteeWithObjectsAndSidA)( PTRUSTEEA pTrustee,
                                                          PSID pSid );
 static LPSTR (WINAPI *pGetTrusteeNameA)( PTRUSTEEA pTrustee );
 static BOOL (WINAPI *pMakeSelfRelativeSD)( PSECURITY_DESCRIPTOR, PSECURITY_DESCRIPTOR, LPDWORD );
-static BOOL (WINAPI *pConvertSidToStringSidA)( PSID pSid, LPSTR *str );
 static BOOL (WINAPI *pConvertStringSidToSidA)( LPCSTR str, PSID pSid );
 static BOOL (WINAPI *pCheckTokenMembership)(HANDLE, PSID, PBOOL);
 static BOOL (WINAPI *pConvertStringSecurityDescriptorToSecurityDescriptorA)(LPCSTR, DWORD,
@@ -157,9 +156,8 @@ static const char* debugstr_sid(PSID sid)
     DWORD le = GetLastError();
     char* res = debugsid_str[debugsid_index];
     debugsid_index = (debugsid_index + 1) % SID_SLOTS;
-    if (!pConvertSidToStringSidA)
-        strcpy(res, "missing ConvertSidToStringSidA");
-    else if (!pConvertSidToStringSidA(sid, &sidstr))
+
+    if (!ConvertSidToStringSidA(sid, &sidstr))
         sprintf(res, "ConvertSidToStringSidA failed le=%u", GetLastError());
     else if (strlen(sidstr) > sizeof(*debugsid_str) - 1)
     {
@@ -218,14 +216,13 @@ static void init(void)
     pGetSecurityInfo = (void *)GetProcAddress(hmod, "GetSecurityInfo");
     pSetSecurityInfo = (void *)GetProcAddress(hmod, "SetSecurityInfo");
     pCreateRestrictedToken = (void *)GetProcAddress(hmod, "CreateRestrictedToken");
-    pConvertSidToStringSidA = (void *)GetProcAddress(hmod, "ConvertSidToStringSidA");
     pConvertStringSidToSidA = (void *)GetProcAddress(hmod, "ConvertStringSidToSidA");
     pGetAclInformation = (void *)GetProcAddress(hmod, "GetAclInformation");
     pGetAce = (void *)GetProcAddress(hmod, "GetAce");
     pGetWindowsAccountDomainSid = (void *)GetProcAddress(hmod, "GetWindowsAccountDomainSid");
     pGetSidIdentifierAuthority = (void *)GetProcAddress(hmod, "GetSidIdentifierAuthority");
-    pGetExplicitEntriesFromAclW = (void *)GetProcAddress(hmod, "GetExplicitEntriesFromAclW");
     pDuplicateTokenEx = (void *)GetProcAddress(hmod, "DuplicateTokenEx");
+    pGetExplicitEntriesFromAclW = (void *)GetProcAddress(hmod, "GetExplicitEntriesFromAclW");
 
     myARGC = winetest_get_mainargs( &myARGV );
 }
@@ -363,7 +360,7 @@ static void test_sid(void)
     BOOL r;
     LPSTR str;
 
-    if( !pConvertSidToStringSidA || !pConvertStringSidToSidA )
+    if( !pConvertStringSidToSidA )
     {
         win_skip("ConvertSidToStringSidA or ConvertStringSidToSidA not available\n");
         return;
@@ -407,7 +404,7 @@ static void test_sid(void)
         r = AllocateAndInitializeSid( &refs[i].auth, 1,1,0,0,0,0,0,0,0,
          &psid );
         ok( r, "failed to allocate sid\n" );
-        r = pConvertSidToStringSidA( psid, &str );
+        r = ConvertSidToStringSidA( psid, &str );
         ok( r, "failed to convert sid\n" );
         if (r)
         {
@@ -475,7 +472,7 @@ static void test_sid(void)
                     *GetSidSubAuthority(psid, n) = 0;
             }
 
-            r = pConvertSidToStringSidA(psid, &sid_string);
+            r = ConvertSidToStringSidA(psid, &sid_string);
             ok(r, "%s: ConvertSidToStringSid error %u\n", strsid_table[i].str, GetLastError());
             if (winetest_debug > 1)
                 trace("%s => %s\n", strsid_table[i].str, sid_string);
@@ -484,7 +481,7 @@ static void test_sid(void)
             r = pCreateWellKnownSid(strsid_table[i].sid_type, domain_sid, buf, &size);
             ok(r, "%u: CreateWellKnownSid(%u) error %u\n", i, strsid_table[i].sid_type, GetLastError());
 
-            r = pConvertSidToStringSidA(buf, &well_known_sid_string);
+            r = ConvertSidToStringSidA(buf, &well_known_sid_string);
             ok(r, "%u: ConvertSidToStringSi(%u) error %u\n", i, strsid_table[i].sid_type, GetLastError());
             if (winetest_debug > 1)
                 trace("%u => %s\n", strsid_table[i].sid_type, well_known_sid_string);
@@ -1821,12 +1818,6 @@ static void test_token_attr(void)
         CloseHandle(Token);
     }
 
-    if(!pConvertSidToStringSidA)
-    {
-        win_skip("ConvertSidToStringSidA is not available\n");
-        return;
-    }
-
     SetLastError(0xdeadbeef);
     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &Token);
     ok(ret, "OpenProcessToken failed with error %d\n", GetLastError());
@@ -1877,7 +1868,7 @@ static void test_token_attr(void)
         ret = LookupAccountSidA(NULL, Groups->Groups[i].Sid, Name, &NameLength, Domain, &DomainLength, &SidNameUse);
         if (ret)
         {
-            pConvertSidToStringSidA(Groups->Groups[i].Sid, &SidString);
+            ConvertSidToStringSidA(Groups->Groups[i].Sid, &SidString);
             trace("%s, %s\\%s use: %d attr: 0x%08x\n", SidString, Domain, Name, SidNameUse, Groups->Groups[i].Attributes);
             LocalFree(SidString);
         }
@@ -1894,7 +1885,7 @@ static void test_token_attr(void)
     ok(ret,
         "GetTokenInformation(TokenUser) failed with error %d\n", GetLastError());
 
-    pConvertSidToStringSidA(User->User.Sid, &SidString);
+    ConvertSidToStringSidA(User->User.Sid, &SidString);
     trace("TokenUser: %s attr: 0x%08x\n", SidString, User->User.Attributes);
     LocalFree(SidString);
     HeapFree(GetProcessHeap(), 0, User);
@@ -2009,7 +2000,7 @@ typedef union _MAX_SID
 static void test_sid_str(PSID * sid)
 {
     char *str_sid;
-    BOOL ret = pConvertSidToStringSidA(sid, &str_sid);
+    BOOL ret = ConvertSidToStringSidA(sid, &str_sid);
     ok(ret, "ConvertSidToStringSidA() failed: %d\n", GetLastError());
     if (ret)
     {
@@ -2126,7 +2117,7 @@ static void test_CreateWellKnownSid(void)
         ok(pCreateWellKnownSid(i, value->without_domain ? NULL : domainsid, sid_buffer, &cb), "Couldn't create well known sid %u\n", i);
         expect_eq(GetSidLengthRequired(*GetSidSubAuthorityCount(sid_buffer)), cb, DWORD, "%d");
         ok(IsValidSid(sid_buffer), "The sid is not valid\n");
-        ok(pConvertSidToStringSidA(sid_buffer, &str), "Couldn't convert SID to string\n");
+        ok(ConvertSidToStringSidA(sid_buffer, &str), "Couldn't convert SID to string\n");
         ok(strcmp(str, value->sid_string) == 0, "%d: SID mismatch - expected %s, got %s\n", i,
             value->sid_string, str);
         LocalFree(str);
@@ -2349,7 +2340,7 @@ static void test_LookupAccountSid(void)
     }
     HeapFree(GetProcessHeap(), 0, ptiUser);
 
-    if (pCreateWellKnownSid && pConvertSidToStringSidA)
+    if (pCreateWellKnownSid)
     {
         trace("Well Known SIDs:\n");
         for (i = 0; i <= 84; i++)
@@ -2357,7 +2348,7 @@ static void test_LookupAccountSid(void)
             size = SECURITY_MAX_SID_SIZE;
             if (pCreateWellKnownSid(i, NULL, &max_sid.sid, &size))
             {
-                if (pConvertSidToStringSidA(&max_sid.sid, &str_sidA))
+                if (ConvertSidToStringSidA(&max_sid.sid, &str_sidA))
                 {
                     acc_sizeA = MAX_PATH;
                     dom_sizeA = MAX_PATH;
@@ -3770,7 +3761,6 @@ static void test_CreateDirectoryA(void)
     ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
     bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
     ok(bret, "GetAclInformation failed\n");
-    todo_wine
     ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
                                acl_size.AceCount);
     LocalFree(pSD);
@@ -3905,6 +3895,7 @@ static void test_CreateDirectoryA(void)
     ok(error == ERROR_SUCCESS, "GetNamedSecurityInfo failed with error %d\n", error);
     bret = pGetAclInformation(pDacl, &acl_size, sizeof(acl_size), AclSizeInformation);
     ok(bret, "GetAclInformation failed\n");
+    todo_wine
     ok(acl_size.AceCount == 0, "GetAclInformation returned unexpected entry count (%d != 0).\n",
                                acl_size.AceCount);
     LocalFree(pSD);
@@ -4281,7 +4272,7 @@ static void test_GetNamedSecurityInfoA(void)
         if (bret) admins_ace_id = i;
     }
     ok(users_ace_id != -1 || broken(users_ace_id == -1) /* win2k */,
-       "Bultin Users ACE not found.\n");
+       "Builtin Users ACE not found.\n");
     if (users_ace_id != -1)
     {
         bret = pGetAce(pDacl, users_ace_id, (VOID **)&ace);
@@ -4298,7 +4289,7 @@ static void test_GetNamedSecurityInfoA(void)
            "Builtin Users ACE has unexpected mask (0x%x != 0x%x)\n",
                                       ace->Mask, GENERIC_READ);
     }
-    ok(admins_ace_id != -1, "Bultin Admins ACE not found.\n");
+    ok(admins_ace_id != -1, "Builtin Admins ACE not found.\n");
     if (admins_ace_id != -1)
     {
         bret = pGetAce(pDacl, admins_ace_id, (VOID **)&ace);
@@ -5309,10 +5300,13 @@ static void test_GetUserNameW(void)
 
 static void test_CreateRestrictedToken(void)
 {
+    TOKEN_PRIMARY_GROUP *primary_group, *primary_group2;
     HANDLE process_token, token, r_token;
     PTOKEN_GROUPS token_groups, groups2;
     SID_AND_ATTRIBUTES sattr;
     SECURITY_IMPERSONATION_LEVEL level;
+    TOKEN_PRIVILEGES *privs;
+    PRIVILEGE_SET privset;
     TOKEN_TYPE type;
     BOOL is_member;
     DWORD size;
@@ -5328,7 +5322,7 @@ static void test_CreateRestrictedToken(void)
     ret = OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_QUERY, &process_token);
     ok(ret, "got error %d\n", GetLastError());
 
-    ret = DuplicateTokenEx(process_token, TOKEN_DUPLICATE|TOKEN_ADJUST_GROUPS|TOKEN_QUERY,
+    ret = DuplicateTokenEx(process_token, TOKEN_DUPLICATE|TOKEN_ADJUST_GROUPS|TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
         NULL, SecurityImpersonation, TokenImpersonation, &token);
     ok(ret, "got error %d\n", GetLastError());
 
@@ -5359,11 +5353,21 @@ static void test_CreateRestrictedToken(void)
     ok(ret, "got error %d\n", GetLastError());
     ok(is_member, "not a member\n");
 
-    /* disable a SID in new token */
+    privset.PrivilegeCount = 1;
+    privset.Control = PRIVILEGE_SET_ALL_NECESSARY;
+    ret = LookupPrivilegeValueA(NULL, "SeChangeNotifyPrivilege", &privset.Privilege[0].Luid);
+    ok(ret, "got error %d\n", GetLastError());
+
+    is_member = FALSE;
+    ret = PrivilegeCheck(token, &privset, &is_member);
+    ok(ret, "got error %d\n", GetLastError());
+    ok(is_member, "Expected SeChangeNotifyPrivilege to be enabled\n");
+
+    /* disable a SID and a privilege in new token */
     sattr.Sid = token_groups->Groups[i].Sid;
     sattr.Attributes = 0;
     r_token = NULL;
-    ret = pCreateRestrictedToken(token, 0, 1, &sattr, 0, NULL, 0, NULL, &r_token);
+    ret = pCreateRestrictedToken(token, 0, 1, &sattr, 1, &privset.Privilege[0], 0, NULL, &r_token);
     ok(ret, "got error %d\n", GetLastError());
 
     if (ret)
@@ -5372,7 +5376,7 @@ static void test_CreateRestrictedToken(void)
         is_member = TRUE;
         ret = pCheckTokenMembership(r_token, token_groups->Groups[i].Sid, &is_member);
         ok(ret, "got error %d\n", GetLastError());
-        todo_wine ok(!is_member, "not a member\n");
+        ok(!is_member, "not a member\n");
 
         ret = GetTokenInformation(r_token, TokenGroups, NULL, 0, &size);
         ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n",
@@ -5387,9 +5391,9 @@ static void test_CreateRestrictedToken(void)
                 break;
         }
 
-        todo_wine ok(groups2->Groups[j].Attributes & SE_GROUP_USE_FOR_DENY_ONLY,
+        ok(groups2->Groups[j].Attributes & SE_GROUP_USE_FOR_DENY_ONLY,
             "got wrong attributes\n");
-        todo_wine ok((groups2->Groups[j].Attributes & SE_GROUP_ENABLED) == 0,
+        ok((groups2->Groups[j].Attributes & SE_GROUP_ENABLED) == 0,
             "got wrong attributes\n");
 
         HeapFree(GetProcessHeap(), 0, groups2);
@@ -5403,10 +5407,73 @@ static void test_CreateRestrictedToken(void)
         ret = GetTokenInformation(r_token, TokenImpersonationLevel, &level, size, &size);
         ok(ret, "got error %d\n", GetLastError());
         ok(level == SecurityImpersonation, "got level %u\n", type);
+
+        is_member = TRUE;
+        ret = PrivilegeCheck(r_token, &privset, &is_member);
+        ok(ret, "got error %d\n", GetLastError());
+        ok(!is_member, "Expected SeChangeNotifyPrivilege not to be enabled\n");
+
+        ret = GetTokenInformation(r_token, TokenPrivileges, NULL, 0, &size);
+        ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n",
+            ret, GetLastError());
+        privs = HeapAlloc(GetProcessHeap(), 0, size);
+        ret = GetTokenInformation(r_token, TokenPrivileges, privs, size, &size);
+        ok(ret, "got error %d\n", GetLastError());
+
+        is_member = FALSE;
+        for (j = 0; j < privs->PrivilegeCount; j++)
+        {
+            if (RtlEqualLuid(&privs->Privileges[j].Luid, &privset.Privilege[0].Luid))
+            {
+                is_member = TRUE;
+                break;
+            }
+        }
+
+        ok(!is_member, "Expected not to find privilege\n");
+        HeapFree(GetProcessHeap(), 0, privs);
     }
 
     HeapFree(GetProcessHeap(), 0, token_groups);
     CloseHandle(r_token);
+
+    ret = GetTokenInformation(token, TokenPrimaryGroup, NULL, 0, &size);
+    ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n",
+        ret, GetLastError());
+    primary_group = HeapAlloc(GetProcessHeap(), 0, size);
+    ret = GetTokenInformation(token, TokenPrimaryGroup, primary_group, size, &size);
+    ok(ret, "got error %d\n", GetLastError());
+
+    /* disable primary group */
+    sattr.Sid = primary_group->PrimaryGroup;
+    sattr.Attributes = 0;
+    r_token = NULL;
+    ret = pCreateRestrictedToken(token, 0, 1, &sattr, 0, NULL, 0, NULL, &r_token);
+    ok(ret, "got error %d\n", GetLastError());
+
+    if (ret)
+    {
+        is_member = TRUE;
+        ret = pCheckTokenMembership(r_token, primary_group->PrimaryGroup, &is_member);
+        ok(ret, "got error %d\n", GetLastError());
+        ok(!is_member, "not a member\n");
+
+        ret = GetTokenInformation(r_token, TokenPrimaryGroup, NULL, 0, &size);
+        ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "got %d with error %d\n",
+            ret, GetLastError());
+        primary_group2 = HeapAlloc(GetProcessHeap(), 0, size);
+        ret = GetTokenInformation(r_token, TokenPrimaryGroup, primary_group2, size, &size);
+        ok(ret, "got error %d\n", GetLastError());
+
+        ok(EqualSid(primary_group2->PrimaryGroup, primary_group->PrimaryGroup),
+           "Expected same primary group\n");
+
+        HeapFree(GetProcessHeap(), 0, primary_group2);
+    }
+
+    HeapFree(GetProcessHeap(), 0, primary_group);
+    CloseHandle(r_token);
+
     CloseHandle(token);
     CloseHandle(process_token);
 }
@@ -6189,7 +6256,8 @@ static void test_process_access(void)
         case GENERIC_WRITE:
             ok(access == map[i].mapped ||
                access == (map[i].mapped | PROCESS_TERMINATE) /* before Vista */ ||
-               access == (map[i].mapped | PROCESS_SET_LIMITED_INFORMATION) /* win8 */,
+               access == (map[i].mapped | PROCESS_SET_LIMITED_INFORMATION) /* win8 */ ||
+               access == (map[i].mapped | PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_SET_LIMITED_INFORMATION) /* Win10 Anniversary Update */,
                "%d: expected %#x, got %#x\n", i, map[i].mapped, access);
             break;
         case GENERIC_EXECUTE:
@@ -6411,7 +6479,7 @@ static void test_default_dacl_owner_sid(void)
 
 static void test_AdjustTokenPrivileges(void)
 {
-    TOKEN_PRIVILEGES tp, prev;
+    TOKEN_PRIVILEGES tp;
     HANDLE token;
     DWORD len;
     LUID luid;
@@ -6439,7 +6507,8 @@ static void test_AdjustTokenPrivileges(void)
     tp.PrivilegeCount = 1;
     tp.Privileges[0].Luid = luid;
     tp.Privileges[0].Attributes = 0;
-    AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), &prev, NULL);
+    ret = AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
+    ok(ret, "got %d\n", ret);
 
     CloseHandle(token);
 }
@@ -6495,18 +6564,19 @@ static void test_AddMandatoryAce(void)
                             {SECURITY_MANDATORY_LOW_RID}};
     static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
                                {SECURITY_MANDATORY_MEDIUM_RID}};
-    static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
-                             {SECURITY_MANDATORY_HIGH_RID}};
-    SYSTEM_MANDATORY_LABEL_ACE *ace;
+    static SID_IDENTIFIER_AUTHORITY sia_world = {SECURITY_WORLD_SID_AUTHORITY};
     char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
     SECURITY_DESCRIPTOR *sd2, *sd = (SECURITY_DESCRIPTOR *)&buffer_sd;
-    SECURITY_ATTRIBUTES sa;
-    char buffer_acl[256];
-    ACL *pAcl = (ACL *)&buffer_acl;
-    ACL *sAcl;
     BOOL defaulted, present, ret, found, found2;
-    HANDLE handle;
+    ACL_SIZE_INFORMATION acl_size_info;
+    SYSTEM_MANDATORY_LABEL_ACE *ace;
+    char buffer_acl[256];
+    ACL *acl = (ACL *)&buffer_acl;
+    SECURITY_ATTRIBUTES sa;
     DWORD index, size;
+    HANDLE handle;
+    SID *everyone;
+    ACL *sacl;
 
     if (!pAddMandatoryAce)
     {
@@ -6515,50 +6585,48 @@ static void test_AddMandatoryAce(void)
     }
 
     ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
-    ok(ret, "InitializeSecurityDescriptor failed with %u\n", GetLastError());
+    ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
 
-    sa.nLength              = sizeof(SECURITY_ATTRIBUTES);
+    sa.nLength = sizeof(sa);
     sa.lpSecurityDescriptor = sd;
-    sa.bInheritHandle       = FALSE;
+    sa.bInheritHandle = FALSE;
 
     handle = CreateEventA(&sa, TRUE, TRUE, "test_event");
     ok(handle != NULL, "CreateEventA failed with error %u\n", GetLastError());
 
     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
-       "GetKernelObjectSecurity failed with %u\n", GetLastError());
+       "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
 
     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
-    ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError());
+    ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
 
-    sAcl = (void *)0xdeadbeef;
+    sacl = (void *)0xdeadbeef;
     present = TRUE;
-    defaulted = TRUE;
-    ret = GetSecurityDescriptorSacl(sd2, &present, &sAcl, &defaulted);
-    ok(ret, "GetSecurityDescriptorSacl failed with %u\n", GetLastError());
-    ok(!present, "sAcl is present\n");
-    ok(sAcl == (void *)0xdeadbeef, "sAcl is set\n");
-    todo_wine ok(!defaulted, "sAcl defaulted\n");
+    ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
+    ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+    ok(!present, "SACL is present\n");
+    ok(sacl == (void *)0xdeadbeef, "SACL is set\n");
 
     HeapFree(GetProcessHeap(), 0, sd2);
     CloseHandle(handle);
 
-    ret = InitializeAcl(pAcl, 256, ACL_REVISION);
+    ret = InitializeAcl(acl, 256, ACL_REVISION);
     ok(ret, "InitializeAcl failed with %u\n", GetLastError());
 
     SetLastError(0xdeadbeef);
-    ret = pAddMandatoryAce(pAcl, ACL_REVISION, 0, 0x1234, &low_level);
+    ret = pAddMandatoryAce(acl, ACL_REVISION, 0, 0x1234, &low_level);
     ok(!ret, "AddMandatoryAce succeeded\n");
     ok(GetLastError() == ERROR_INVALID_PARAMETER,
        "Expected ERROR_INVALID_PARAMETER got %u\n", GetLastError());
 
-    ret = pAddMandatoryAce(pAcl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level);
+    ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level);
     ok(ret, "AddMandatoryAce failed with %u\n", GetLastError());
 
     index = 0;
     found = FALSE;
-    while (pGetAce( pAcl, index++, (void **)&ace ))
+    while (pGetAce(acl, index++, (void **)&ace))
     {
         if (ace->Header.AceType != SYSTEM_MANDATORY_LABEL_ACE_TYPE) continue;
         ok(ace->Header.AceFlags == 0, "Expected flags 0, got %x\n", ace->Header.AceFlags);
@@ -6569,192 +6637,184 @@ static void test_AddMandatoryAce(void)
     }
     ok(found, "Could not find mandatory label ace\n");
 
-    ret = SetSecurityDescriptorSacl(sd, TRUE, pAcl, FALSE);
-    ok(ret, "SetSecurityDescriptorSacl failed with %u\n", GetLastError());
+    ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
+    ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
 
     handle = CreateEventA(&sa, TRUE, TRUE, "test_event");
     ok(handle != NULL, "CreateEventA failed with error %u\n", GetLastError());
 
     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
-       "GetKernelObjectSecurity failed with %u\n", GetLastError());
+       "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
 
     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
-    ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError());
+    ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
 
-    sAcl = (void *)0xdeadbeef;
+    sacl = (void *)0xdeadbeef;
     present = FALSE;
     defaulted = TRUE;
-    ret = GetSecurityDescriptorSacl(sd2, &present, &sAcl, &defaulted);
-    ok(ret, "GetSecurityDescriptorSacl failed with %u\n", GetLastError());
-    ok(present, "sAcl not present\n");
-    ok(sAcl != (void *)0xdeadbeef, "sAcl not set\n");
-    ok(!defaulted, "sAcl defaulted\n");
-
-    index = 0;
-    found = FALSE;
-    while (pGetAce( sAcl, index++, (void **)&ace ))
-    {
-        if (ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE)
-        {
-            found = TRUE;
-            ok(ace->Header.AceFlags == 0, "Expected 0 as flags, got %x\n", ace->Header.AceFlags);
-            ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP,
-               "Expected SYSTEM_MANDATORY_LABEL_NO_WRITE_UP as flag, got %x\n", ace->Mask);
-            ok(EqualSid(&ace->SidStart, &low_level), "Expected low integrity level\n");
-        }
-    }
-    ok(found, "Could not find mandatory label\n");
+    ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
+    ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+    ok(present, "SACL not present\n");
+    ok(sacl != (void *)0xdeadbeef, "SACL not set\n");
+    ok(!defaulted, "SACL defaulted\n");
+    ret = pGetAclInformation(sacl, &acl_size_info, sizeof(acl_size_info), AclSizeInformation);
+    ok(ret, "GetAclInformation failed with error %u\n", GetLastError());
+    ok(acl_size_info.AceCount == 1, "SACL contains an unexpected ACE count %u\n", acl_size_info.AceCount);
+
+    ret = pGetAce(sacl, 0, (void **)&ace);
+    ok(ret, "GetAce failed with error %u\n", GetLastError());
+    ok (ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType);
+    ok(!ace->Header.AceFlags, "Unexpected ACE flags %#x\n", ace->Header.AceFlags);
+    ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "Unexpected ACE mask %#x\n", ace->Mask);
+    ok(EqualSid(&ace->SidStart, &low_level), "Expected low integrity level\n");
 
     HeapFree(GetProcessHeap(), 0, sd2);
 
-    ret = pAddMandatoryAce(pAcl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level);
-    ok(ret, "AddMandatoryAce failed with %u\n", GetLastError());
+    ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level);
+    ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError());
 
     ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
-    ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError());
+    ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
 
     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
-       "GetKernelObjectSecurity failed with %u\n", GetLastError());
+       "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
 
     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
-    ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError());
+    ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
 
-    sAcl = (void *)0xdeadbeef;
+    sacl = (void *)0xdeadbeef;
     present = FALSE;
     defaulted = TRUE;
-    ret = GetSecurityDescriptorSacl(sd2, &present, &sAcl, &defaulted);
-    ok(ret, "GetSecurityDescriptorSacl failed with %u\n", GetLastError());
-    ok(present, "sAcl not present\n");
-    ok(sAcl != (void *)0xdeadbeef, "sAcl not set\n");
-    ok(sAcl->AceCount == 2, "Expected 2 ACEs, got %d\n", sAcl->AceCount);
-    ok(!defaulted, "sAcl defaulted\n");
+    ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
+    ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+    ok(present, "SACL not present\n");
+    ok(sacl != (void *)0xdeadbeef, "SACL not set\n");
+    ok(sacl->AceCount == 2, "Expected 2 ACEs, got %d\n", sacl->AceCount);
+    ok(!defaulted, "SACL defaulted\n");
 
     index = 0;
     found = found2 = FALSE;
-    while (pGetAce( sAcl, index++, (void **)&ace ))
+    while (pGetAce(sacl, index++, (void **)&ace))
     {
         if (ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE)
         {
             if (EqualSid(&ace->SidStart, &low_level))
             {
                 found = TRUE;
-                ok(ace->Header.AceFlags == 0, "Expected 0 as flags, got %x\n", ace->Header.AceFlags);
+                ok(!ace->Header.AceFlags, "Expected 0 as flags, got %#x\n", ace->Header.AceFlags);
                 ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP,
-                   "Expected SYSTEM_MANDATORY_LABEL_NO_WRITE_UP as flag, got %x\n", ace->Mask);
+                   "Expected SYSTEM_MANDATORY_LABEL_NO_WRITE_UP as mask, got %#x\n", ace->Mask);
             }
             if (EqualSid(&ace->SidStart, &medium_level))
             {
                 found2 = TRUE;
-                ok(ace->Header.AceFlags == 0, "Expected 0 as flags, got %x\n", ace->Header.AceFlags);
+                ok(!ace->Header.AceFlags, "Expected 0 as flags, got %#x\n", ace->Header.AceFlags);
                 ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP,
-                   "Expected SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP as flag, got %x\n", ace->Mask);
+                   "Expected SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP as mask, got %#x\n", ace->Mask);
             }
         }
     }
     ok(found, "Could not find low mandatory label\n");
     ok(found2, "Could not find medium mandatory label\n");
 
-    HeapFree( GetProcessHeap(), 0, sd2);
+    HeapFree(GetProcessHeap(), 0, sd2);
 
     ret = SetSecurityDescriptorSacl(sd, FALSE, NULL, FALSE);
-    ok(ret, "SetSecurityDescriptorSacl failed with %u\n", GetLastError());
+    ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
 
     ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
-    ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError());
+    ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
 
     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
-       "GetKernelObjectSecurity failed with %u\n", GetLastError());
+       "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
 
     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
-    ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError());
+    ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
 
-    sAcl = (void *)0xdeadbeef;
+    sacl = (void *)0xdeadbeef;
     present = FALSE;
     defaulted = TRUE;
-    ret = GetSecurityDescriptorSacl(sd2, &present, &sAcl, &defaulted);
-    ok(ret, "GetSecurityDescriptorSacl failed with %u\n", GetLastError());
-    ok(present, "sAcl not present\n");
-    ok(sAcl != (void *)0xdeadbeef, "sAcl not set\n");
-    ok(sAcl->AceCount == 0, "Expected 0 ACEs, got %d\n", sAcl->AceCount);
-    ok(!defaulted, "sAcl defaulted\n");
+    ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
+    ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+    ok(present, "SACL not present\n");
+    ok(sacl && sacl != (void *)0xdeadbeef, "SACL not set\n");
+    ok(!defaulted, "SACL defaulted\n");
+    ok(!sacl->AceCount, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
 
     HeapFree(GetProcessHeap(), 0, sd2);
 
-    ret = InitializeAcl(pAcl, 256, ACL_REVISION);
-    ok(ret, "InitializeAcl failed with %u\n", GetLastError());
+    ret = InitializeAcl(acl, 256, ACL_REVISION);
+    ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
 
-    ret = pAddMandatoryAce(pAcl, ACL_REVISION3, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level);
-    ok(ret, "AddMandatoryAce failed with %u\n", GetLastError());
+    ret = pAddMandatoryAce(acl, ACL_REVISION3, 0, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, &medium_level);
+    ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError());
 
-    ret = SetSecurityDescriptorSacl(sd, TRUE, pAcl, FALSE);
-    ok(ret, "SetSecurityDescriptorSacl failed with %u\n", GetLastError());
+    ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
+    ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
 
     ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
-    ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError());
+    ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
 
     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
-       "GetKernelObjectSecurity failed with %u\n", GetLastError());
+       "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
 
     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
-    ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError());
+    ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
 
-    sAcl = (void *)0xdeadbeef;
+    sacl = (void *)0xdeadbeef;
     present = FALSE;
     defaulted = TRUE;
-    ret = GetSecurityDescriptorSacl(sd2, &present, &sAcl, &defaulted);
-    ok(ret, "GetSecurityDescriptorSacl failed with %u\n", GetLastError());
-    ok(present, "sAcl not present\n");
-    ok(sAcl != (void *)0xdeadbeef, "sAcl not set\n");
-    ok(sAcl->AclRevision == ACL_REVISION3, "Expected revision 3, got %d\n", sAcl->AclRevision);
-    ok(!defaulted, "sAcl defaulted\n");
+    ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
+    ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+    ok(present, "SACL not present\n");
+    ok(sacl != (void *)0xdeadbeef, "SACL not set\n");
+    ok(sacl->AclRevision == ACL_REVISION3, "Expected revision 3, got %d\n", sacl->AclRevision);
+    ok(!defaulted, "SACL defaulted\n");
 
     HeapFree(GetProcessHeap(), 0, sd2);
-    CloseHandle(handle);
 
-    ret = OpenProcessToken(GetCurrentProcess(), READ_CONTROL, &handle);
-    ok(ret, "got %d with %d (expected TRUE)\n", ret, GetLastError());
+    ret = InitializeAcl(acl, 256, ACL_REVISION);
+    ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
+
+    ret = AllocateAndInitializeSid(&sia_world, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, (void **)&everyone);
+    ok(ret, "AllocateAndInitializeSid failed with error %u\n", GetLastError());
+
+    ret = AddAccessAllowedAce(acl, ACL_REVISION, KEY_READ, everyone);
+    ok(ret, "AddAccessAllowedAce failed with error %u\n", GetLastError());
+
+    ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
+    ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+
+    ret = SetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd);
+    ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
 
     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
-       "GetKernelObjectSecurity failed with %u\n", GetLastError());
+       "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
 
     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
     ret = GetKernelObjectSecurity(handle, LABEL_SECURITY_INFORMATION, sd2, size, &size);
-    ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError());
+    ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
 
-    sAcl = (void *)0xdeadbeef;
+    sacl = (void *)0xdeadbeef;
     present = FALSE;
     defaulted = TRUE;
-    ret = GetSecurityDescriptorSacl(sd2, &present, &sAcl, &defaulted);
-    ok(ret, "GetSecurityDescriptorSacl failed with %u\n", GetLastError());
-    ok(present, "sAcl not present\n");
-    ok(sAcl != (void *)0xdeadbeef, "sAcl not set\n");
-    ok(sAcl->AceCount == 1, "Expected 1 ACEs, got %d\n", sAcl->AceCount);
-    ok(!defaulted, "sAcl defaulted\n");
-
-    index = 0;
-    found = FALSE;
-    while (pGetAce( sAcl, index++, (void **)&ace ))
-    {
-        if (ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE &&
-            (EqualSid(&ace->SidStart, &medium_level) || EqualSid(&ace->SidStart, &high_level)))
-        {
-            found = TRUE;
-            ok(ace->Header.AceFlags == 0, "Expected 0 as flags, got %x\n", ace->Header.AceFlags);
-            ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP,
-               "Expected SYSTEM_MANDATORY_LABEL_NO_WRITE_UP as flag, got %x\n", ace->Mask);
-        }
-    }
-    ok(found, "Could not find medium/high mandatory label\n");
-
+    ret = GetSecurityDescriptorSacl(sd2, &present, &sacl, &defaulted);
+    ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+    ok(present, "SACL not present\n");
+    ok(sacl && sacl != (void *)0xdeadbeef, "SACL not set\n");
+    ok(!defaulted, "SACL defaulted\n");
+    ok(!sacl->AceCount, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
+
+    FreeSid(everyone);
     HeapFree(GetProcessHeap(), 0, sd2);
     CloseHandle(handle);
 }
@@ -7054,164 +7114,113 @@ static void test_maximum_allowed(void)
     CloseHandle(handle);
 }
 
-static void test_GetExplicitEntriesFromAclW(void)
+static void test_token_label(void)
 {
-    static const WCHAR wszCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
-    SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
-    SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
-    PSID everyone_sid = NULL, users_sid = NULL;
-    EXPLICIT_ACCESSW access;
-    EXPLICIT_ACCESSW *access2;
-    PACL new_acl, old_acl = NULL;
-    ULONG count;
-    DWORD res;
-
-    if (!pGetExplicitEntriesFromAclW)
-    {
-        win_skip("GetExplicitEntriesFromAclW is not available\n");
-        return;
-    }
-
-    if (!pSetEntriesInAclW)
-    {
-        win_skip("SetEntriesInAclW is not available\n");
-        return;
-    }
-
-    old_acl = HeapAlloc(GetProcessHeap(), 0, 256);
-    res = InitializeAcl(old_acl, 256, ACL_REVISION);
-    if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
-    {
-        win_skip("ACLs not implemented - skipping tests\n");
-        HeapFree(GetProcessHeap(), 0, old_acl);
-        return;
-    }
-    ok(res, "InitializeAcl failed with error %d\n", GetLastError());
-
-    res = AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyone_sid);
-    ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
+    static SID medium_sid = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
+                             {SECURITY_MANDATORY_MEDIUM_RID}};
+    static SID high_sid = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
+                           {SECURITY_MANDATORY_HIGH_RID}};
+    SECURITY_DESCRIPTOR_CONTROL control;
+    SYSTEM_MANDATORY_LABEL_ACE *ace;
+    BOOL ret, present, defaulted;
+    SECURITY_DESCRIPTOR *sd;
+    ACL *sacl = NULL, *dacl;
+    DWORD size, revision;
+    HANDLE token;
+    char *str;
+    SID *sid;
 
-    res = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
-                                   DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &users_sid);
-    ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
+    ret = OpenProcessToken(GetCurrentProcess(), READ_CONTROL | WRITE_OWNER, &token);
+    ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
 
-    res = AddAccessAllowedAce(old_acl, ACL_REVISION, KEY_READ, users_sid);
-    ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
+    ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
+    ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+       "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
 
-    access2 = NULL;
-    res = pGetExplicitEntriesFromAclW(old_acl, &count, &access2);
-    ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
-    ok(count == 1, "Expected count == 1, got %d\n", count);
-    ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
-    ok(access2[0].grfAccessPermissions == KEY_READ, "Expected KEY_READ, got %d\n", access2[0].grfAccessPermissions);
-    ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
-    ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
-    ok(EqualSid(access2[0].Trustee.ptstrName, users_sid), "Expected equal SIDs\n");
-    LocalFree(access2);
+    sd = HeapAlloc(GetProcessHeap(), 0, size);
+    ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size);
+    ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
 
-    access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
-    access.Trustee.pMultipleTrustee = NULL;
+    ret = GetSecurityDescriptorControl(sd, &control, &revision);
+    ok(ret, "GetSecurityDescriptorControl failed with error %u\n", GetLastError());
+    todo_wine ok(control == (SE_SELF_RELATIVE | SE_SACL_AUTO_INHERITED | SE_SACL_PRESENT) ||
+                 broken(control == SE_SELF_RELATIVE) /* WinXP, Win2003 */,
+                 "Unexpected security descriptor control %#x\n", control);
+    ok(revision == 1, "Unexpected security descriptor revision %u\n", revision);
 
-    access.grfAccessPermissions = KEY_WRITE;
-    access.grfAccessMode = GRANT_ACCESS;
-    access.grfInheritance = NO_INHERITANCE;
-    access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
-    access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
-    access.Trustee.ptstrName = everyone_sid;
-    res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
-    ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
-    ok(new_acl != NULL, "returned acl was NULL\n");
+    sid = (void *)0xdeadbeef;
+    defaulted = TRUE;
+    ret = GetSecurityDescriptorOwner(sd, (void **)&sid, &defaulted);
+    ok(ret, "GetSecurityDescriptorOwner failed with error %u\n", GetLastError());
+    ok(!sid, "Owner present\n");
+    ok(!defaulted, "Owner defaulted\n");
 
-    access2 = NULL;
-    res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
-    ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
-    ok(count == 2, "Expected count == 2, got %d\n", count);
-    ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
-    ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions);
-    ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
-       "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
-    ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
-    ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
-    ok(EqualSid(access2[0].Trustee.ptstrName, everyone_sid), "Expected equal SIDs\n");
-    LocalFree(access2);
-    LocalFree(new_acl);
+    sid = (void *)0xdeadbeef;
+    defaulted = TRUE;
+    ret = GetSecurityDescriptorGroup(sd, (void **)&sid, &defaulted);
+    ok(ret, "GetSecurityDescriptorGroup failed with error %u\n", GetLastError());
+    ok(!sid, "Group present\n");
+    ok(!defaulted, "Group defaulted\n");
 
-    access.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
-    res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
-    ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
-    ok(new_acl != NULL, "returned acl was NULL\n");
+    ret = GetSecurityDescriptorSacl(sd, &present, &sacl, &defaulted);
+    ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+    ok(present || broken(!present) /* WinXP, Win2003 */, "No SACL in the security descriptor\n");
+    ok(sacl || broken(!sacl) /* WinXP, Win2003 */, "NULL SACL in the security descriptor\n");
 
-    access2 = NULL;
-    res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
-    ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
-    ok(count == 2, "Expected count == 2, got %d\n", count);
-    ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
-    ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions);
-    ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
-       "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
-    ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
-    ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
-    ok(EqualSid(access2[0].Trustee.ptstrName, everyone_sid), "Expected equal SIDs\n");
-    LocalFree(access2);
-    LocalFree(new_acl);
+    if (present)
+    {
+        ok(!defaulted, "SACL defaulted\n");
+        ok(sacl->AceCount == 1, "SACL contains an unexpected ACE count %u\n", sacl->AceCount);
 
-    access.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
-    access.Trustee.ptstrName = (LPWSTR)wszCurrentUser;
-    res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
-    ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
-    ok(new_acl != NULL, "returned acl was NULL\n");
+        ret = pGetAce(sacl, 0, (void **)&ace);
+        ok(ret, "GetAce failed with error %u\n", GetLastError());
 
-    access2 = NULL;
-    res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
-    ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
-    ok(count == 2, "Expected count == 2, got %d\n", count);
-    ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
-    ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions);
-    ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
-       "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
-    ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
-    ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
-    LocalFree(access2);
-    LocalFree(new_acl);
+        ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
+           "Unexpected ACE type %#x\n", ace->Header.AceType);
+        ok(!ace->Header.AceFlags, "Unexpected ACE flags %#x\n", ace->Header.AceFlags);
+        ok(ace->Header.AceSize, "Unexpected ACE size %u\n", ace->Header.AceSize);
+        ok(ace->Mask == SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, "Unexpected ACE mask %#x\n", ace->Mask);
 
-    access.grfAccessMode = REVOKE_ACCESS;
-    access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
-    access.Trustee.ptstrName = users_sid;
-    res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
-    ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
-    ok(new_acl != NULL, "returned acl was NULL\n");
+        sid = (SID *)&ace->SidStart;
+        ConvertSidToStringSidA(sid, &str);
+        ok(EqualSid(sid, &medium_sid) || EqualSid(sid, &high_sid), "Got unexpected SID %s\n", str);
+        LocalFree(str);
+    }
 
-    access2 = (void *)0xdeadbeef;
-    res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
-    ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
-    ok(count == 0, "Expected count == 0, got %d\n", count);
-    ok(access2 == NULL, "access2 was not NULL\n");
-    LocalFree(new_acl);
+    ret = GetSecurityDescriptorDacl(sd, &present, &dacl, &defaulted);
+    ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
+    todo_wine ok(!present, "DACL present\n");
 
-    FreeSid(users_sid);
-    FreeSid(everyone_sid);
-    HeapFree(GetProcessHeap(), 0, old_acl);
+    HeapFree(GetProcessHeap(), 0, sd);
+    CloseHandle(token);
 }
 
 static void test_token_security_descriptor(void)
 {
     static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
-                                             {SECURITY_MANDATORY_LOW_RID}};
-    ACCESS_ALLOWED_ACE *ace;
+                            {SECURITY_MANDATORY_LOW_RID}};
+    static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
+                               {SECURITY_MANDATORY_MEDIUM_RID}};
+    static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
+                             {SECURITY_MANDATORY_HIGH_RID}};
     char buffer_sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
-    SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)&buffer_sd, *sd2;
+    SECURITY_DESCRIPTOR *sd = (SECURITY_DESCRIPTOR *)&buffer_sd, *sd2, *sd3;
     char buffer_acl[256], buffer[MAX_PATH];
-    ACL *pAcl = (ACL *)&buffer_acl, *pAcl2, *pAclChild;
+    ACL *acl = (ACL *)&buffer_acl, *acl2, *acl_child, *sacl;
     BOOL defaulted, present, ret, found;
-    HANDLE token, token2, token3;
+    HANDLE token, token2, token3, token4, token5, token6;
     EXPLICIT_ACCESSW exp_access;
+    TOKEN_MANDATORY_LABEL *tml;
+    BYTE buffer_integrity[64];
     PROCESS_INFORMATION info;
-    SECURITY_ATTRIBUTES sa;
     DWORD size, index, retd;
+    ACCESS_ALLOWED_ACE *ace;
+    SECURITY_ATTRIBUTES sa;
     STARTUPINFOA startup;
     PSID psid;
 
-    if (!pDuplicateTokenEx || !pConvertStringSidToSidA || !pAddAccessAllowedAceEx || !pGetAce || !pSetEntriesInAclW)
+    if (!pDuplicateTokenEx || !pConvertStringSidToSidA || !pAddAccessAllowedAceEx || !pGetAce
+        || !pSetEntriesInAclW)
     {
         win_skip("Some functions not available\n");
         return;
@@ -7222,131 +7231,109 @@ static void test_token_security_descriptor(void)
     ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
 
     ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
-    ok(ret, "InitializeSecurityDescriptor failed with %u\n", GetLastError());
+    ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
 
-    ret = InitializeAcl(pAcl, 256, ACL_REVISION);
-    ok(ret, "InitializeAcl failed with %u\n", GetLastError());
+    ret = InitializeAcl(acl, 256, ACL_REVISION);
+    ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
 
     ret = pConvertStringSidToSidA("S-1-5-6", &psid);
-    ok(ret, "ConvertStringSidToSidA failed with %u\n", GetLastError());
+    ok(ret, "ConvertStringSidToSidA failed with error %u\n", GetLastError());
 
-    ret = pAddAccessAllowedAceEx(pAcl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, GENERIC_ALL, psid);
-    ok(ret, "AddAccessAllowedAceEx failed with %u\n", GetLastError());
+    ret = pAddAccessAllowedAceEx(acl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, GENERIC_ALL, psid);
+    ok(ret, "AddAccessAllowedAceEx failed with error %u\n", GetLastError());
 
-    ret = SetSecurityDescriptorDacl(sd, TRUE, pAcl, FALSE);
-    ok(ret, "SetSecurityDescriptorDacl failed with %u\n", GetLastError());
+    ret = SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE);
+    ok(ret, "SetSecurityDescriptorDacl failed with error %u\n", GetLastError());
 
-    sa.nLength              = sizeof(SECURITY_ATTRIBUTES);
+    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
     sa.lpSecurityDescriptor = sd;
-    sa.bInheritHandle       = FALSE;
+    sa.bInheritHandle = FALSE;
 
     ret = pDuplicateTokenEx(token, MAXIMUM_ALLOWED, &sa, SecurityImpersonation, TokenImpersonation, &token2);
-    ok(ret, "DuplicateTokenEx failed with %u\n", GetLastError());
+    ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
 
     ret = GetKernelObjectSecurity(token2, DACL_SECURITY_INFORMATION, NULL, 0, &size);
     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
-       "GetKernelObjectSecurity failed with %u\n", GetLastError());
+       "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
 
     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
     ret = GetKernelObjectSecurity(token2, DACL_SECURITY_INFORMATION, sd2, size, &size);
-    ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError());
+    ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
 
-    pAcl2 = (void *)0xdeadbeef;
+    acl2 = (void *)0xdeadbeef;
     present = FALSE;
     defaulted = TRUE;
-    ret = GetSecurityDescriptorDacl(sd2, &present, &pAcl2, &defaulted);
-    ok(ret, "GetSecurityDescriptorDacl failed with %u\n", GetLastError());
-    ok(present, "pAcl2 not present\n");
-    ok(pAcl2 != (void *)0xdeadbeef, "pAcl2 not set\n");
-    ok(pAcl2->AceCount == 1, "Expected 1 ACEs, got %d\n", pAcl2->AceCount);
-    ok(!defaulted, "pAcl2 defaulted\n");
+    ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted);
+    ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
+    ok(present, "acl2 not present\n");
+    ok(acl2 != (void *)0xdeadbeef, "acl2 not set\n");
+    ok(acl2->AceCount == 1, "Expected 1 ACE, got %d\n", acl2->AceCount);
+    ok(!defaulted, "acl2 defaulted\n");
+
+    ret = pGetAce(acl2, 0, (void **)&ace);
+    ok(ret, "GetAce failed with error %u\n", GetLastError());
+    ok(ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE, "Unexpected ACE type %#x\n", ace->Header.AceType);
+    ok(EqualSid(&ace->SidStart, psid), "Expected access allowed ACE\n");
+    ok(ace->Header.AceFlags == NO_PROPAGATE_INHERIT_ACE,
+       "Expected NO_PROPAGATE_INHERIT_ACE as flags, got %x\n", ace->Header.AceFlags);
 
-    index = 0;
-    found = FALSE;
-    while (pGetAce( pAcl2, index++, (void **)&ace ))
-    {
-        if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE && EqualSid(&ace->SidStart, psid))
-        {
-            found = TRUE;
-            ok(ace->Header.AceFlags == NO_PROPAGATE_INHERIT_ACE,
-               "Expected NO_PROPAGATE_INHERIT_ACE as flags, got %x\n", ace->Header.AceFlags);
-        }
-    }
-    ok(found, "Could not find access allowed ace\n");
-
-    HeapFree( GetProcessHeap(), 0, sd2);
+    HeapFree(GetProcessHeap(), 0, sd2);
 
     /* Duplicate token without security attributes.
-     * Tokens do not inherit the security descriptor when calling DuplicateToken,
-     * see https://blogs.msdn.microsoft.com/oldnewthing/20160512-00/?p=93447
-     */
+     * Tokens do not inherit the security descriptor in DuplicateToken. */
     ret = pDuplicateTokenEx(token2, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenImpersonation, &token3);
-    ok(ret, "DuplicateTokenEx failed with %u\n", GetLastError());
+    ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
 
     ret = GetKernelObjectSecurity(token3, DACL_SECURITY_INFORMATION, NULL, 0, &size);
     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
-       "GetKernelObjectSecurity failed with %u\n", GetLastError());
+       "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
 
     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
     ret = GetKernelObjectSecurity(token3, DACL_SECURITY_INFORMATION, sd2, size, &size);
-    ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError());
+    ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
 
-    pAcl2 = (void *)0xdeadbeef;
+    acl2 = (void *)0xdeadbeef;
     present = FALSE;
     defaulted = TRUE;
-    ret = GetSecurityDescriptorDacl(sd2, &present, &pAcl2, &defaulted);
-    ok(ret, "GetSecurityDescriptorDacl failed with %u\n", GetLastError());
-    todo_wine
-    ok(present, "pAcl2 not present\n");
-    ok(pAcl2 != (void *)0xdeadbeef, "pAcl2 not set\n");
-    ok(!defaulted, "pAcl2 defaulted\n");
+    ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted);
+    ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
+    ok(present, "DACL not present\n");
 
-    if (pAcl2)
+    if (present)
     {
+        ok(acl2 != (void *)0xdeadbeef, "DACL not set\n");
+        ok(!defaulted, "DACL defaulted\n");
+
         index = 0;
         found = FALSE;
-        while (pGetAce( pAcl2, index++, (void **)&ace ))
+        while (pGetAce(acl2, index++, (void **)&ace))
         {
             if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE && EqualSid(&ace->SidStart, psid))
                 found = TRUE;
         }
-        ok(!found, "Access allowed ace got inherited!\n");
+        ok(!found, "Access allowed ACE was inherited\n");
     }
 
     HeapFree(GetProcessHeap(), 0, sd2);
 
-    /* When creating a child process, the process does only inherit the
-     * Token of the parent, but not the DACL of the token.
-     */
+    /* When creating a child process, the process does inherit the token of
+     * the parent but not the DACL of the token */
     ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, NULL, 0, &size);
     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
-       "GetKernelObjectSecurity failed with %u\n", GetLastError());
+       "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
 
     sd2 = HeapAlloc(GetProcessHeap(), 0, size);
     ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd2, size, &size);
-    ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError());
+    ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
 
-    pAcl2 = (void *)0xdeadbeef;
+    acl2 = (void *)0xdeadbeef;
     present = FALSE;
     defaulted = TRUE;
-    ret = GetSecurityDescriptorDacl(sd2, &present, &pAcl2, &defaulted);
-    ok(ret, "GetSecurityDescriptorDacl failed with %u\n", GetLastError());
-    ok(present, "pAcl2 not present\n");
-    ok(pAcl2 != (void *)0xdeadbeef, "pAcl2 not set\n");
-    ok(!defaulted, "pAcl2 defaulted\n");
-
-    /* check that the ace we add for testing does not already exist! */
-    if (pAcl2)
-    {
-        index = 0;
-        found = FALSE;
-        while (pGetAce( pAcl2, index++, (void **)&ace ))
-        {
-            if (ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE && EqualSid(&ace->SidStart, psid))
-                found = TRUE;
-        }
-        ok(!found, "Test ace does already exist!\n");
-    }
+    ret = GetSecurityDescriptorDacl(sd2, &present, &acl2, &defaulted);
+    ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
+    ok(present, "DACL not present\n");
+    ok(acl2 != (void *)0xdeadbeef, "DACL not set\n");
+    ok(!defaulted, "DACL defaulted\n");
 
     exp_access.grfAccessPermissions = GENERIC_ALL;
     exp_access.grfAccessMode = GRANT_ACCESS;
@@ -7357,42 +7344,305 @@ static void test_token_security_descriptor(void)
     exp_access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
     exp_access.Trustee.ptstrName = (void*)psid;
 
-    retd = pSetEntriesInAclW(1, &exp_access, pAcl2, &pAclChild);
+    retd = pSetEntriesInAclW(1, &exp_access, acl2, &acl_child);
     ok(retd == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", retd);
 
     memset(sd, 0, sizeof(buffer_sd));
     ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
-    ok(ret, "InitializeSecurityDescriptor failed with %u\n", GetLastError());
+    ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
 
-    ret = SetSecurityDescriptorDacl(sd, TRUE, pAclChild, FALSE);
-    ok(ret, "SetSecurityDescriptorDacl failed with %u\n", GetLastError());
+    ret = SetSecurityDescriptorDacl(sd, TRUE, acl_child, FALSE);
+    ok(ret, "SetSecurityDescriptorDacl failed with error %u\n", GetLastError());
 
     ret = SetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd);
-    ok(ret, "SetKernelObjectSecurity failed with %u\n", GetLastError());
+    ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
 
     /* The security label is also not inherited */
     if (pAddMandatoryAce)
     {
-        ret = InitializeAcl(pAcl, 256, ACL_REVISION);
-        ok(ret, "InitializeAcl failed with %u\n", GetLastError());
+        memset(buffer_integrity, 0, sizeof(buffer_integrity));
+        ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
+        ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
+        tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
+        ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level),
+           "Expected medium or high integrity level\n");
+
+        if (EqualSid(tml->Label.Sid, &high_level))
+        {
+            DWORD process_id;
+            HANDLE process;
+            HWND shell;
+
+            /* This test tries to get a medium token and then impersonates this token. The
+             * idea is to check whether the sd label of a newly created token depends on the
+             * current active token or the integrity level of the newly created token. */
+
+             /* Steal process token of the explorer.exe process */
+            shell = GetShellWindow();
+            todo_wine ok(shell != NULL, "Failed to get shell window\n");
+            if (!shell) shell = GetDesktopWindow();  /* FIXME: Workaround for Wine */
+            ok(GetWindowThreadProcessId(shell, &process_id),
+               "Failed to get process id of shell window: %u\n", GetLastError());
+            process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, process_id);
+            ok(process != NULL, "Failed to open process: %u\n", GetLastError());
+            ok(OpenProcessToken(process, TOKEN_ALL_ACCESS, &token4),
+               "Failed to open process token: %u\n", GetLastError());
+            CloseHandle(process);
+
+            /* Check TokenIntegrityLevel and LABEL_SECURITY_INFORMATION of explorer.exe token */
+            memset(buffer_integrity, 0, sizeof(buffer_integrity));
+            ret = GetTokenInformation(token4, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
+            ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
+            tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
+            ok(EqualSid(tml->Label.Sid, &medium_level), "Expected medium integrity level\n");
+
+            size = 0;
+            ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
+            ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+               "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
+
+            sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
+            ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, sd3, size, &size);
+            ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
+
+            sacl = NULL;
+            ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
+            ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+            ok(present, "No SACL in the security descriptor\n");
+            ok(sacl != NULL, "NULL SACL in the security descriptor\n");
+
+            if (sacl)
+            {
+                ret = pGetAce(sacl, 0, (void **)&ace);
+                ok(ret, "GetAce failed with error %u\n", GetLastError());
+                ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
+                   "Unexpected ACE type %#x\n", ace->Header.AceType);
+                ok(EqualSid(&ace->SidStart, &medium_level),
+                   "Expected medium integrity level\n");
+            }
+
+            HeapFree(GetProcessHeap(), 0, sd3);
+
+            /* Start child process with the explorer.exe token */
+            memset(&startup, 0, sizeof(startup));
+            startup.cb = sizeof(startup);
+            startup.dwFlags = STARTF_USESHOWWINDOW;
+            startup.wShowWindow = SW_SHOWNORMAL;
+
+            sprintf(buffer, "%s tests/security.c test_token_sd_medium", myARGV[0]);
+            ret = CreateProcessAsUserA(token4, NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info);
+            ok(ret || GetLastError() == ERROR_PRIVILEGE_NOT_HELD,
+                "CreateProcess failed with error %u\n", GetLastError());
+            if (ret)
+            {
+                winetest_wait_child_process(info.hProcess);
+                CloseHandle(info.hProcess);
+                CloseHandle(info.hThread);
+            }
+            else
+                win_skip("Skipping test for creating process with medium level token\n");
+
+            ret = DuplicateTokenEx(token4, 0, NULL, SecurityImpersonation, TokenImpersonation, &token5);
+            ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
+            ret = SetThreadToken(NULL, token5);
+            ok(ret, "SetThreadToken failed with error %u\n", GetLastError());
+            CloseHandle(token4);
+
+            /* Restrict current process token while impersonating a medium integrity token */
+            ret = CreateRestrictedToken(token, 0, 0, NULL, 0, NULL, 0, NULL, &token6);
+            ok(ret, "CreateRestrictedToken failed with error %u\n", GetLastError());
+
+            memset(buffer_integrity, 0, sizeof(buffer_integrity));
+            ret = GetTokenInformation(token6, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
+            ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
+            tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
+            ok(EqualSid(tml->Label.Sid, &high_level), "Expected high integrity level\n");
+
+            size = 0;
+            ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
+            ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+               "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
+
+            sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
+            ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, sd3, size, &size);
+            ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
+
+            sacl = NULL;
+            ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
+            ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+            ok(present, "No SACL in the security descriptor\n");
+            ok(sacl != NULL, "NULL SACL in the security descriptor\n");
+
+            if (sacl)
+            {
+                ret = pGetAce(sacl, 0, (void **)&ace);
+                ok(ret, "GetAce failed with error %u\n", GetLastError());
+                ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
+                   "Unexpected ACE type %#x\n", ace->Header.AceType);
+                ok(EqualSid(&ace->SidStart, &medium_level),
+                   "Expected medium integrity level\n");
+            }
+
+            HeapFree(GetProcessHeap(), 0, sd3);
+            RevertToSelf();
+            CloseHandle(token5);
+
+            /* Start child process with the restricted token */
+            sprintf(buffer, "%s tests/security.c test_token_sd_restricted", myARGV[0]);
+            ret = CreateProcessAsUserA(token6, NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info);
+            ok(ret, "CreateProcess failed with error %u\n", GetLastError());
+            winetest_wait_child_process(info.hProcess);
+            CloseHandle(info.hProcess);
+            CloseHandle(info.hThread);
+            CloseHandle(token6);
+
+            /* DuplicateTokenEx should assign security label even when SA points to empty SD */
+            memset(sd, 0, sizeof(buffer_sd));
+            ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
+            ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
+
+            sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+            sa.lpSecurityDescriptor = sd;
+            sa.bInheritHandle = FALSE;
+
+            ret = DuplicateTokenEx(token, 0, &sa, 0, TokenPrimary, &token6);
+            ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
+
+            size = 0;
+            ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
+            ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+               "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
+
+            sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
+            ret = GetKernelObjectSecurity(token6, LABEL_SECURITY_INFORMATION, sd3, size, &size);
+            ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
+
+            sacl = NULL;
+            ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
+            ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+            ok(present, "No SACL in the security descriptor\n");
+            ok(sacl != NULL, "NULL SACL in the security descriptor\n");
+
+            if (sacl)
+            {
+                ret = pGetAce(sacl, 0, (void **)&ace);
+                ok(ret, "GetAce failed with error %u\n", GetLastError());
+                ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
+                   "Unexpected ACE type %#x\n", ace->Header.AceType);
+                ok(EqualSid(&ace->SidStart, &high_level),
+                   "Expected high integrity level\n");
+            }
+
+            HeapFree(GetProcessHeap(), 0, sd3);
+            CloseHandle(token6);
+        }
+        else
+            skip("Skipping test, running without admin rights\n");
+
+        ret = InitializeAcl(acl, 256, ACL_REVISION);
+        ok(ret, "InitializeAcl failed with error %u\n", GetLastError());
 
-        ret = pAddMandatoryAce(pAcl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level);
-        ok(ret, "AddMandatoryAce failed with %u\n", GetLastError());
+        ret = pAddMandatoryAce(acl, ACL_REVISION, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP, &low_level);
+        ok(ret, "AddMandatoryAce failed with error %u\n", GetLastError());
 
         memset(sd, 0, sizeof(buffer_sd));
         ret = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION);
-        ok(ret, "InitializeSecurityDescriptor failed with %u\n", GetLastError());
+        ok(ret, "InitializeSecurityDescriptor failed with error %u\n", GetLastError());
 
-        ret = SetSecurityDescriptorSacl(sd, TRUE, pAcl, FALSE);
-        ok(ret, "SetSecurityDescriptorSacl failed with %u\n", GetLastError());
+        ret = SetSecurityDescriptorSacl(sd, TRUE, acl, FALSE);
+        ok(ret, "SetSecurityDescriptorSacl failed with error %u\n", GetLastError());
 
         ret = SetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd);
-        ok(ret, "SetKernelObjectSecurity failed with %u\n", GetLastError());
+        ok(ret, "SetKernelObjectSecurity failed with error %u\n", GetLastError());
+
+        /* changing the label of the security descriptor does not change the integrity level of the token itself */
+        memset(buffer_integrity, 0, sizeof(buffer_integrity));
+        ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
+        ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
+        tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
+        ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level),
+            "Expected medium or high integrity level\n");
+
+        /* restricting / duplicating a token resets the mandatory sd label */
+        ret = CreateRestrictedToken(token, 0, 0, NULL, 0, NULL, 0, NULL, &token4);
+        ok(ret, "CreateRestrictedToken failed with error %u\n", GetLastError());
+
+        memset(buffer_integrity, 0, sizeof(buffer_integrity));
+        ret = GetTokenInformation(token4, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
+        ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
+        tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
+        ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level),
+            "Expected medium or high integrity level\n");
+
+        size = 0;
+        ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
+        ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+           "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
+
+        sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
+        ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, sd3, size, &size);
+        ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
+
+        ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
+        ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+        ok(present, "No SACL in the security descriptor\n");
+        ok(sacl != NULL, "NULL SACL in the security descriptor\n");
+
+        if (sacl)
+        {
+            ret = pGetAce(sacl, 0, (void **)&ace);
+            ok(ret, "GetAce failed with error %u\n", GetLastError());
+            ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
+               "Unexpected ACE type %#x\n", ace->Header.AceType);
+            ok(EqualSid(&ace->SidStart, &medium_level) || EqualSid(&ace->SidStart, &high_level),
+               "Low integrity level should not have been inherited\n");
+        }
+
+        HeapFree(GetProcessHeap(), 0, sd3);
+        CloseHandle(token4);
+
+        ret = DuplicateTokenEx(token, 0, NULL, 0, TokenPrimary, &token4);
+        ok(ret, "DuplicateTokenEx failed with error %u\n", GetLastError());
+
+        memset(buffer_integrity, 0, sizeof(buffer_integrity));
+        ret = GetTokenInformation(token4, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
+        ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
+        tml = (TOKEN_MANDATORY_LABEL*) buffer_integrity;
+        ok(EqualSid(tml->Label.Sid, &medium_level) || EqualSid(tml->Label.Sid, &high_level),
+            "Expected medium or high integrity level\n");
+
+        size = 0;
+        ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
+        ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+           "Unexpected GetKernelObjectSecurity return value %u, error %u\n", ret, GetLastError());
+
+        sd3 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
+        ret = GetKernelObjectSecurity(token4, LABEL_SECURITY_INFORMATION, sd3, size, &size);
+        ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
+
+        sacl = NULL;
+        ret = GetSecurityDescriptorSacl(sd3, &present, &sacl, &defaulted);
+        ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+        ok(present, "No SACL in the security descriptor\n");
+        ok(sacl != NULL, "NULL SACL in the security descriptor\n");
+
+        if (sacl)
+        {
+            ret = pGetAce(sacl, 0, (void **)&ace);
+            ok(ret, "GetAce failed with error %u\n", GetLastError());
+            ok(ace->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
+               "Unexpected ACE type %#x\n", ace->Header.AceType);
+            ok(EqualSid(&ace->SidStart, &medium_level) || EqualSid(&ace->SidStart, &high_level),
+               "Low integrity level should not have been inherited\n");
+        }
+
+        HeapFree(GetProcessHeap(), 0, sd3);
+        CloseHandle(token4);
     }
     else
         win_skip("SYSTEM_MANDATORY_LABEL not supported\n");
 
-    /* start child process with our modified token */
+    /* Start child process with our modified token */
     memset(&startup, 0, sizeof(startup));
     startup.cb = sizeof(startup);
     startup.dwFlags = STARTF_USESHOWWINDOW;
@@ -7405,7 +7655,7 @@ static void test_token_security_descriptor(void)
     CloseHandle(info.hProcess);
     CloseHandle(info.hThread);
 
-    LocalFree(pAclChild);
+    LocalFree(acl_child);
     LocalFree(psid);
 
     CloseHandle(token3);
@@ -7416,48 +7666,46 @@ static void test_token_security_descriptor(void)
 static void test_child_token_sd(void)
 {
     static SID low_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
-                                             {SECURITY_MANDATORY_LOW_RID}};
+                            {SECURITY_MANDATORY_LOW_RID}};
     SYSTEM_MANDATORY_LABEL_ACE *ace_label;
-    BOOL ret, present, defaulted, found;
-    ACCESS_ALLOWED_ACE *ace_acc;
+    BOOL ret, present, defaulted;
+    ACCESS_ALLOWED_ACE *acc_ace;
     SECURITY_DESCRIPTOR *sd;
-    DWORD size, index;
+    DWORD size, i;
     HANDLE token;
-    ACL *pAcl;
     PSID psid;
+    ACL *acl;
 
     ret = pConvertStringSidToSidA("S-1-5-6", &psid);
-    ok(ret, "ConvertStringSidToSidA failed with %u\n", GetLastError());
+    ok(ret, "ConvertStringSidToSidA failed with error %u\n", GetLastError());
 
     ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
     ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
 
     ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, NULL, 0, &size);
     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
-       "GetKernelObjectSecurity failed with %u\n", GetLastError());
+       "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
 
     sd = HeapAlloc(GetProcessHeap(), 0, size);
     ret = GetKernelObjectSecurity(token, DACL_SECURITY_INFORMATION, sd, size, &size);
-    ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError());
+    ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
 
-    pAcl = NULL;
+    acl = NULL;
     present = FALSE;
     defaulted = TRUE;
-    ret = GetSecurityDescriptorDacl(sd, &present, &pAcl, &defaulted);
-    ok(ret, "GetSecurityDescriptorSacl failed with %u\n", GetLastError());
+    ret = GetSecurityDescriptorDacl(sd, &present, &acl, &defaulted);
+    ok(ret, "GetSecurityDescriptorDacl failed with error %u\n", GetLastError());
+    ok(present, "DACL not present\n");
+    ok(acl && acl != (void *)0xdeadbeef, "Got invalid DACL\n");
+    ok(!defaulted, "DACL defaulted\n");
 
-    index = 0;
-    found = FALSE;
-    if (present && pAcl)
+    ok(acl->AceCount, "Expected at least one ACE\n");
+    for (i = 0; i < acl->AceCount; i++)
     {
-        ok(pAcl->AceCount > 0, "Expected at least one ACE\n");
-        while (pGetAce( pAcl, index++, (void **)&ace_acc ))
-        {
-            if (ace_acc->Header.AceType == ACCESS_ALLOWED_ACE_TYPE && EqualSid(&ace_acc->SidStart, psid))
-                found = TRUE;
-        }
+        ok(pGetAce(acl, i, (void **)&acc_ace), "GetAce failed with error %u\n", GetLastError());
+        ok(acc_ace->Header.AceType != ACCESS_ALLOWED_ACE_TYPE || !EqualSid(&acc_ace->SidStart, psid),
+           "ACE inherited from the parent\n");
     }
-    ok(!found, "The ACE should not haven been inherited from the parent\n");
 
     LocalFree(psid);
     HeapFree(GetProcessHeap(), 0, sd);
@@ -7470,33 +7718,280 @@ static void test_child_token_sd(void)
 
     ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
     ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
-       "GetKernelObjectSecurity failed with %u\n", GetLastError());
+       "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
 
     sd = HeapAlloc(GetProcessHeap(), 0, size);
     ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size);
-    ok(ret, "GetKernelObjectSecurity failed %u\n", GetLastError());
+    ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
 
-    pAcl = NULL;
+    acl = NULL;
     present = FALSE;
     defaulted = TRUE;
-    ret = GetSecurityDescriptorSacl(sd, &present, &pAcl, &defaulted);
-    ok(ret, "GetSecurityDescriptorSacl failed with %u\n", GetLastError());
+    ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted);
+    ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+    ok(present, "SACL not present\n");
+    ok(acl && acl != (void *)0xdeadbeef, "Got invalid SACL\n");
+    ok(!defaulted, "SACL defaulted\n");
+    ok(acl->AceCount == 1, "Expected exactly one ACE\n");
+    ret = pGetAce(acl, 0, (void **)&ace_label);
+    ok(ret, "GetAce failed with error %u\n", GetLastError());
+    ok(ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
+       "Unexpected ACE type %#x\n", ace_label->Header.AceType);
+    ok(!EqualSid(&ace_label->SidStart, &low_level),
+       "Low integrity level should not have been inherited\n");
 
-    index = 0;
-    found = FALSE;
-    if (present && pAcl)
+    HeapFree(GetProcessHeap(), 0, sd);
+}
+
+static void test_child_token_sd_restricted(void)
+{
+    static SID high_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
+                             {SECURITY_MANDATORY_HIGH_RID}};
+    SYSTEM_MANDATORY_LABEL_ACE *ace_label;
+    BOOL ret, present, defaulted;
+    TOKEN_MANDATORY_LABEL *tml;
+    BYTE buffer_integrity[64];
+    SECURITY_DESCRIPTOR *sd;
+    HANDLE token;
+    DWORD size;
+    ACL *acl;
+
+    if (!pAddMandatoryAce)
     {
-        while (pGetAce( pAcl, index++, (void **)&ace_label ))
-        {
-            if (ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE && EqualSid(&ace_label->SidStart, &low_level))
-                found = TRUE;
-        }
+        win_skip("SYSTEM_MANDATORY_LABEL not supported\n");
+        return;
     }
-    ok(!found, "Low integrity level should not have been inherited\n");
+
+    ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
+    ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
+
+    ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
+    ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+       "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
+
+    sd = HeapAlloc(GetProcessHeap(), 0, size);
+    ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size);
+    ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
+
+    acl = NULL;
+    present = FALSE;
+    defaulted = TRUE;
+    ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted);
+    ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+    ok(present, "SACL not present\n");
+    ok(acl && acl != (void *)0xdeadbeef, "Got invalid SACL\n");
+    ok(!defaulted, "SACL defaulted\n");
+    ok(acl->AceCount == 1, "Expected exactly one ACE\n");
+    ret = pGetAce(acl, 0, (void **)&ace_label);
+    ok(ret, "GetAce failed with error %u\n", GetLastError());
+    ok(ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
+       "Unexpected ACE type %#x\n", ace_label->Header.AceType);
+    ok(EqualSid(&ace_label->SidStart, &high_level),
+       "Expected high integrity level\n");
+
+    memset(buffer_integrity, 0, sizeof(buffer_integrity));
+    ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
+    ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
+    tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
+    ok(EqualSid(tml->Label.Sid, &high_level), "Expected high integrity level\n");
 
     HeapFree(GetProcessHeap(), 0, sd);
 }
 
+static void test_child_token_sd_medium(void)
+{
+    static SID medium_level = {SID_REVISION, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY},
+                               {SECURITY_MANDATORY_MEDIUM_RID}};
+    SYSTEM_MANDATORY_LABEL_ACE *ace_label;
+    BOOL ret, present, defaulted;
+    TOKEN_MANDATORY_LABEL *tml;
+    BYTE buffer_integrity[64];
+    SECURITY_DESCRIPTOR *sd;
+    HANDLE token;
+    DWORD size;
+    ACL *acl;
+
+    if (!pAddMandatoryAce)
+    {
+        win_skip("SYSTEM_MANDATORY_LABEL not supported\n");
+        return;
+    }
+
+    ret = OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &token);
+    ok(ret, "OpenProcessToken failed with error %u\n", GetLastError());
+
+    ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, NULL, 0, &size);
+    ok(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER,
+       "Unexpected GetKernelObjectSecurity return value %d, error %u\n", ret, GetLastError());
+
+    sd = HeapAlloc(GetProcessHeap(), 0, size);
+    ret = GetKernelObjectSecurity(token, LABEL_SECURITY_INFORMATION, sd, size, &size);
+    ok(ret, "GetKernelObjectSecurity failed with error %u\n", GetLastError());
+
+    acl = NULL;
+    present = FALSE;
+    defaulted = TRUE;
+    ret = GetSecurityDescriptorSacl(sd, &present, &acl, &defaulted);
+    ok(ret, "GetSecurityDescriptorSacl failed with error %u\n", GetLastError());
+    ok(present, "SACL not present\n");
+    ok(acl && acl != (void *)0xdeadbeef, "Got invalid SACL\n");
+    ok(!defaulted, "SACL defaulted\n");
+    ok(acl->AceCount == 1, "Expected exactly one ACE\n");
+    ret = pGetAce(acl, 0, (void **)&ace_label);
+    ok(ret, "GetAce failed with error %u\n", GetLastError());
+    ok(ace_label->Header.AceType == SYSTEM_MANDATORY_LABEL_ACE_TYPE,
+       "Unexpected ACE type %#x\n", ace_label->Header.AceType);
+    ok(EqualSid(&ace_label->SidStart, &medium_level),
+       "Expected medium integrity level\n");
+
+    memset(buffer_integrity, 0, sizeof(buffer_integrity));
+    ret = GetTokenInformation(token, TokenIntegrityLevel, buffer_integrity, sizeof(buffer_integrity), &size);
+    ok(ret, "GetTokenInformation failed with error %u\n", GetLastError());
+    tml = (TOKEN_MANDATORY_LABEL *)buffer_integrity;
+    ok(EqualSid(tml->Label.Sid, &medium_level), "Expected medium integrity level\n");
+
+    HeapFree(GetProcessHeap(), 0, sd);
+}
+
+static void test_GetExplicitEntriesFromAclW(void)
+{
+    static const WCHAR wszCurrentUser[] = { 'C','U','R','R','E','N','T','_','U','S','E','R','\0'};
+    SID_IDENTIFIER_AUTHORITY SIDAuthWorld = { SECURITY_WORLD_SID_AUTHORITY };
+    SID_IDENTIFIER_AUTHORITY SIDAuthNT = { SECURITY_NT_AUTHORITY };
+    PSID everyone_sid = NULL, users_sid = NULL;
+    EXPLICIT_ACCESSW access;
+    EXPLICIT_ACCESSW *access2;
+    PACL new_acl, old_acl = NULL;
+    ULONG count;
+    DWORD res;
+
+    if (!pGetExplicitEntriesFromAclW)
+    {
+        win_skip("GetExplicitEntriesFromAclW is not available\n");
+        return;
+    }
+
+    if (!pSetEntriesInAclW)
+    {
+        win_skip("SetEntriesInAclW is not available\n");
+        return;
+    }
+
+    old_acl = HeapAlloc(GetProcessHeap(), 0, 256);
+    res = InitializeAcl(old_acl, 256, ACL_REVISION);
+    if(!res && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+    {
+        win_skip("ACLs not implemented - skipping tests\n");
+        HeapFree(GetProcessHeap(), 0, old_acl);
+        return;
+    }
+    ok(res, "InitializeAcl failed with error %d\n", GetLastError());
+
+    res = AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everyone_sid);
+    ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
+
+    res = AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
+                                   DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &users_sid);
+    ok(res, "AllocateAndInitializeSid failed with error %d\n", GetLastError());
+
+    res = AddAccessAllowedAce(old_acl, ACL_REVISION, KEY_READ, users_sid);
+    ok(res, "AddAccessAllowedAce failed with error %d\n", GetLastError());
+
+    access2 = NULL;
+    res = pGetExplicitEntriesFromAclW(old_acl, &count, &access2);
+    ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
+    ok(count == 1, "Expected count == 1, got %d\n", count);
+    ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
+    ok(access2[0].grfAccessPermissions == KEY_READ, "Expected KEY_READ, got %d\n", access2[0].grfAccessPermissions);
+    ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
+    ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
+    ok(EqualSid(access2[0].Trustee.ptstrName, users_sid), "Expected equal SIDs\n");
+    LocalFree(access2);
+
+    access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
+    access.Trustee.pMultipleTrustee = NULL;
+
+    access.grfAccessPermissions = KEY_WRITE;
+    access.grfAccessMode = GRANT_ACCESS;
+    access.grfInheritance = NO_INHERITANCE;
+    access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
+    access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
+    access.Trustee.ptstrName = everyone_sid;
+    res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
+    ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
+    ok(new_acl != NULL, "returned acl was NULL\n");
+
+    access2 = NULL;
+    res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
+    ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
+    ok(count == 2, "Expected count == 2, got %d\n", count);
+    ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
+    ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions);
+    ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
+       "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
+    ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
+    ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
+    ok(EqualSid(access2[0].Trustee.ptstrName, everyone_sid), "Expected equal SIDs\n");
+    LocalFree(access2);
+    LocalFree(new_acl);
+
+    access.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
+    res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
+    ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
+    ok(new_acl != NULL, "returned acl was NULL\n");
+
+    access2 = NULL;
+    res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
+    ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
+    ok(count == 2, "Expected count == 2, got %d\n", count);
+    ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
+    ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions);
+    ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
+       "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
+    ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
+    ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
+    ok(EqualSid(access2[0].Trustee.ptstrName, everyone_sid), "Expected equal SIDs\n");
+    LocalFree(access2);
+    LocalFree(new_acl);
+
+    access.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
+    access.Trustee.ptstrName = (LPWSTR)wszCurrentUser;
+    res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
+    ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
+    ok(new_acl != NULL, "returned acl was NULL\n");
+
+    access2 = NULL;
+    res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
+    ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
+    ok(count == 2, "Expected count == 2, got %d\n", count);
+    ok(access2[0].grfAccessMode == GRANT_ACCESS, "Expected GRANT_ACCESS, got %d\n", access2[0].grfAccessMode);
+    ok(access2[0].grfAccessPermissions == KEY_WRITE, "Expected KEY_WRITE, got %d\n", access2[0].grfAccessPermissions);
+    ok(access2[0].Trustee.TrusteeType == TRUSTEE_IS_UNKNOWN,
+       "Expected TRUSTEE_IS_UNKNOWN trustee type, got %d\n", access2[0].Trustee.TrusteeType);
+    ok(access2[0].Trustee.TrusteeForm == TRUSTEE_IS_SID, "Expected SID trustee, got %d\n", access2[0].Trustee.TrusteeForm);
+    ok(access2[0].grfInheritance == NO_INHERITANCE, "Expected NO_INHERITANCE, got %x\n", access2[0].grfInheritance);
+    LocalFree(access2);
+    LocalFree(new_acl);
+
+    access.grfAccessMode = REVOKE_ACCESS;
+    access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
+    access.Trustee.ptstrName = users_sid;
+    res = pSetEntriesInAclW(1, &access, old_acl, &new_acl);
+    ok(res == ERROR_SUCCESS, "SetEntriesInAclW failed: %u\n", res);
+    ok(new_acl != NULL, "returned acl was NULL\n");
+
+    access2 = (void *)0xdeadbeef;
+    res = pGetExplicitEntriesFromAclW(new_acl, &count, &access2);
+    ok(res == ERROR_SUCCESS, "GetExplicitEntriesFromAclW failed with error %d\n", GetLastError());
+    ok(count == 0, "Expected count == 0, got %d\n", count);
+    ok(access2 == NULL, "access2 was not NULL\n");
+    LocalFree(new_acl);
+
+    FreeSid(users_sid);
+    FreeSid(everyone_sid);
+    HeapFree(GetProcessHeap(), 0, old_acl);
+}
+
 static void test_BuildSecurityDescriptorW(void)
 {
     SECURITY_DESCRIPTOR old_sd, *new_sd, *rel_sd;
@@ -7544,6 +8039,10 @@ START_TEST(security)
     {
         if (!strcmp(myARGV[2], "test_token_sd"))
             test_child_token_sd();
+        else if (!strcmp(myARGV[2], "test_token_sd_restricted"))
+            test_child_token_sd_restricted();
+        else if (!strcmp(myARGV[2], "test_token_sd_medium"))
+            test_child_token_sd_medium();
         else
             test_process_security_child();
         return;
@@ -7587,9 +8086,10 @@ START_TEST(security)
     test_GetSidIdentifierAuthority();
     test_pseudo_tokens();
     test_maximum_allowed();
+    test_token_label();
     test_GetExplicitEntriesFromAclW();
     test_BuildSecurityDescriptorW();
 
-    /* must be the last test, modifies process token */
+    /* Must be the last test, modifies process token */
     test_token_security_descriptor();
 }