1 /* 2 * PROJECT: apphelp_apitest 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 * PURPOSE: Tests for (registry)layer manipulation api's 5 * COPYRIGHT: Copyright 2015-2017 Mark Jansen (mark.jansen@reactos.org) 6 */ 7 8 #include <ntstatus.h> 9 #define WIN32_NO_STATUS 10 #include <windows.h> 11 #include <shlwapi.h> 12 #include <winnt.h> 13 #ifdef __REACTOS__ 14 #include <ntndk.h> 15 #else 16 #include <winternl.h> 17 #endif 18 #include <winerror.h> 19 #include <stdio.h> 20 21 #include "wine/test.h" 22 #include "apitest_iathook.h" 23 #include "apphelp_apitest.h" 24 25 #define GPLK_USER 1 26 #define GPLK_MACHINE 2 27 #define MAX_LAYER_LENGTH 256 28 #define LAYER_APPLY_TO_SYSTEM_EXES 1 29 30 31 static HMODULE hdll; 32 static BOOL(WINAPI *pAllowPermLayer)(PCWSTR path); 33 static BOOL(WINAPI *pSdbSetPermLayerKeys)(PCWSTR wszPath, PCWSTR wszLayers, BOOL bMachine); 34 static BOOL(WINAPI *pSdbGetPermLayerKeys)(PCWSTR wszPath, PWSTR pwszLayers, PDWORD pdwBytes, DWORD dwFlags); 35 static BOOL(WINAPI *pSetPermLayerState)(PCWSTR wszPath, PCWSTR wszLayer, DWORD dwFlags, BOOL bMachine, BOOL bEnable); 36 37 38 /* Helper function to disable Wow64 redirection on an os that reports it being enabled. */ 39 static DWORD g_QueryFlag = 0xffffffff; 40 static DWORD QueryFlag(void) 41 { 42 if (g_QueryFlag == 0xffffffff) 43 { 44 ULONG_PTR wow64_ptr = 0; 45 NTSTATUS status = NtQueryInformationProcess(NtCurrentProcess(), ProcessWow64Information, &wow64_ptr, sizeof(wow64_ptr), NULL); 46 g_QueryFlag = (NT_SUCCESS(status) && wow64_ptr != 0) ? KEY_WOW64_64KEY : 0; 47 } 48 return g_QueryFlag; 49 } 50 51 /* Helper function to prepare the registry key with a value. */ 52 static BOOL setLayerValue(BOOL bMachine, const char* valueName, const char* value) 53 { 54 HKEY key = NULL; 55 LSTATUS lstatus = RegCreateKeyExA(bMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, 56 "Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers", 0, NULL, 0, QueryFlag() | KEY_SET_VALUE, NULL, &key, NULL); 57 if (lstatus == ERROR_SUCCESS) 58 { 59 if (value) 60 lstatus = RegSetValueExA(key, valueName, 0, REG_SZ, (const BYTE*)value, strlen(value)+1); 61 else 62 { 63 lstatus = RegDeleteValueA(key, valueName); 64 lstatus = (lstatus == ERROR_FILE_NOT_FOUND ? ERROR_SUCCESS : lstatus); 65 } 66 RegCloseKey(key); 67 } 68 return lstatus == ERROR_SUCCESS; 69 } 70 71 72 static void expect_LayerValue_imp(BOOL bMachine, const char* valueName, const char* value) 73 { 74 HKEY key = NULL; 75 LSTATUS lstatus = RegCreateKeyExA(bMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, 76 "Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers", 0, NULL, 0, QueryFlag() | KEY_QUERY_VALUE, NULL, &key, NULL); 77 winetest_ok(lstatus == ERROR_SUCCESS, "Expected to be able to open a registry key\n"); 78 if (lstatus == ERROR_SUCCESS) 79 { 80 char data[512] = { 0 }; 81 DWORD dwType = 0; 82 DWORD dwDataLen = sizeof(data); 83 lstatus = RegQueryValueExA(key, valueName, NULL, &dwType, (LPBYTE)data, &dwDataLen); 84 if (value) 85 { 86 winetest_ok(lstatus == ERROR_SUCCESS, "Expected to get a valid value, err: %u\n", lstatus); 87 if (lstatus == ERROR_SUCCESS) 88 { 89 winetest_ok(dwType == REG_SZ, "Expected the type to be REG_SZ, was: %u\n", dwType); 90 winetest_ok(!strcmp(data, value), "Expected the data to be: '%s', was: '%s'\n", value, data); 91 } 92 } 93 else 94 { 95 winetest_ok(lstatus == ERROR_FILE_NOT_FOUND, "Expected not to find the value %s\n", valueName); 96 } 97 RegCloseKey(key); 98 } 99 } 100 101 static void expect_LayerValue_imp2(BOOL bMachine, const char* valueName, const char* value, int use_alt, const char* alt_value) 102 { 103 expect_LayerValue_imp(bMachine, valueName, use_alt ? alt_value : value); 104 } 105 106 107 void expect_Sdb_imp(PCSTR path, DWORD type, BOOL result, DWORD lenResult, PCSTR stringResult) 108 { 109 WCHAR pathW[MAX_PATH], buffer[MAX_LAYER_LENGTH] = { 0 }; 110 char resultBuffer[MAX_LAYER_LENGTH] = { 0 }; 111 DWORD dwBufSize = sizeof(buffer); 112 113 /* In case of a failure, the buffer size is sometimes set to 0, and sometimes not touched, 114 depending on the version. Either case is fine, since the function returns FALSE anyway. */ 115 116 MultiByteToWideChar(CP_ACP, 0, path, -1, pathW, MAX_PATH); 117 118 winetest_ok(pSdbGetPermLayerKeys(pathW, buffer, &dwBufSize, type) == result, "Expected pSdbGetPermLayerKeys to %s\n", (result ? "succeed" : "fail")); 119 if (!result && lenResult == 0xffffffff) 120 winetest_ok(dwBufSize == 0 || dwBufSize == sizeof(buffer), "Expected dwBufSize to be 0 or %u, was %u\n", sizeof(buffer), dwBufSize); 121 else 122 winetest_ok(dwBufSize == lenResult || 123 /* W2k3 is off by 2 when concatenating user / machine */ 124 broken(g_WinVersion < WINVER_VISTA && type == (GPLK_MACHINE|GPLK_USER) && (lenResult + 2) == dwBufSize), 125 "Expected dwBufSize to be %u, was %u\n", lenResult, dwBufSize); 126 if (result) 127 { 128 winetest_ok(lstrlenW(buffer) * sizeof(WCHAR) + sizeof(WCHAR) == lenResult, "Expected lstrlenW(buffer)*2+2 to be %u, was %u\n", 129 lenResult, lstrlenW(buffer) * sizeof(WCHAR) + sizeof(WCHAR)); 130 } 131 WideCharToMultiByte(CP_ACP, 0, buffer, -1, resultBuffer, sizeof(resultBuffer), NULL, NULL); 132 winetest_ok(!strcmp(stringResult, resultBuffer), "Expected the result to be '%s', was '%s'\n", stringResult, resultBuffer); 133 134 if (result) 135 { 136 UNICODE_STRING pathNT; 137 138 if (RtlDosPathNameToNtPathName_U(pathW, &pathNT, NULL, NULL)) 139 { 140 memset(buffer, 0, sizeof(buffer)); 141 dwBufSize = sizeof(buffer); 142 winetest_ok(pSdbGetPermLayerKeys(pathNT.Buffer, buffer, &dwBufSize, type) == FALSE, "Expected pSdbGetPermLayerKeys to fail for NT path\n"); 143 144 RtlFreeUnicodeString(&pathNT); 145 } 146 } 147 148 } 149 150 151 /* In case of a failure, let the location be from where the function was invoked, not inside the function itself. */ 152 #define expect_Sdb (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_Sdb_imp 153 #define expect_LayerValue (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_LayerValue_imp 154 #define expect_LayerValue2 (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_LayerValue_imp2 155 156 157 BOOL wrapAllowPermLayer(const char* str) 158 { 159 WCHAR buf[100]; 160 MultiByteToWideChar(CP_ACP, 0, str, -1, buf, 100); 161 return pAllowPermLayer(buf); 162 } 163 164 /* Brute forcing all ascii chars in the first 2 places seems to indicate that all it cares for is: 165 - Second char has to be a ':' 166 if it's not a ':', display a diagnostic message (and a different one for '\\'). 167 - First char does not really matter, as long as it's not on a DRIVE_REMOTE (but, according to the logging this is meant to check for a CDROM drive...) 168 */ 169 static void test_AllowPermLayer(void) 170 { 171 char buf[20]; 172 char drive_letter; 173 UINT drivetype = 0; 174 ok(pAllowPermLayer(NULL) == FALSE, "Expected AllowPermLayer to fail for NULL\n"); 175 if (g_WinVersion < WINVER_WIN8) 176 { 177 ok(wrapAllowPermLayer("-:"), "Expected AllowPermLayer to succeed\n"); 178 ok(wrapAllowPermLayer("@:"), "Expected AllowPermLayer to succeed\n"); 179 ok(wrapAllowPermLayer("4:"), "Expected AllowPermLayer to succeed\n"); 180 ok(wrapAllowPermLayer("*:"), "Expected AllowPermLayer to succeed\n"); 181 } 182 ok(wrapAllowPermLayer("*a") == FALSE, "Expected AllowPermLayer to fail\n"); 183 ok(wrapAllowPermLayer("*\\") == FALSE, "Expected AllowPermLayer to fail\n"); 184 for (drive_letter = 'a'; drive_letter <= 'z'; ++drive_letter) 185 { 186 sprintf(buf, "%c:\\", drive_letter); 187 drivetype = GetDriveTypeA(buf); 188 ok(wrapAllowPermLayer(buf) == (drivetype != DRIVE_REMOTE), "Expected AllowPermLayer to be %d for %c:\\\n", (drivetype != DRIVE_REMOTE), drive_letter); 189 } 190 } 191 192 static BOOL wrapSdbSetPermLayerKeys(PCWSTR wszPath, PCSTR szLayers, BOOL bMachine) 193 { 194 WCHAR wszLayers[MAX_LAYER_LENGTH]; 195 MultiByteToWideChar(CP_ACP, 0, szLayers, -1, wszLayers, MAX_LAYER_LENGTH); 196 return pSdbSetPermLayerKeys(wszPath, wszLayers, bMachine); 197 } 198 199 static void test_SdbSetPermLayerKeysLevel(BOOL bMachine, const char* file) 200 { 201 WCHAR fileW[MAX_PATH+20]; 202 WCHAR emptyString[1] = { 0 }; 203 204 MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, MAX_PATH+20); 205 206 /* Test some parameter validation. */ 207 ok(pSdbSetPermLayerKeys(NULL, NULL, bMachine) == FALSE, "Expected SdbSetPermLayerKeys to fail\n"); 208 ok(pSdbSetPermLayerKeys(NULL, emptyString, bMachine) == FALSE, "Expected SdbSetPermLayerKeys to fail\n"); 209 ok(pSdbSetPermLayerKeys(emptyString, emptyString, bMachine) == FALSE, "Expected SdbSetPermLayerKeys to fail\n"); 210 ok(pSdbSetPermLayerKeys(fileW, NULL, bMachine) == TRUE, "Expected SdbSetPermLayerKeys to succeed\n"); 211 ok(pSdbSetPermLayerKeys(fileW, emptyString, bMachine) == TRUE, "Expected SdbSetPermLayerKeys to fail\n"); 212 213 /* Basic tests */ 214 ok(wrapSdbSetPermLayerKeys(fileW, "TEST1", bMachine), "Expected SdbSetPermLayerKeys to succeed\n"); 215 expect_LayerValue(bMachine, file, "TEST1"); 216 217 ok(wrapSdbSetPermLayerKeys(fileW, "TEST1 TEST2", bMachine), "Expected SdbSetPermLayerKeys to succeed\n"); 218 expect_LayerValue(bMachine, file, "TEST1 TEST2"); 219 220 /* SdbSetPermLayerKeys does not do any validation of the value passed in. */ 221 ok(wrapSdbSetPermLayerKeys(fileW, "!#$% TEST1 TEST2", bMachine), "Expected SdbSetPermLayerKeys to succeed\n"); 222 expect_LayerValue(bMachine, file, "!#$% TEST1 TEST2"); 223 224 ok(wrapSdbSetPermLayerKeys(fileW, "!#$% TEST1 TEST2", bMachine), "Expected SdbSetPermLayerKeys to succeed\n"); 225 expect_LayerValue(bMachine, file, "!#$% TEST1 TEST2"); 226 227 ok(pSdbSetPermLayerKeys(fileW, NULL, bMachine) == TRUE, "Expected SdbSetPermLayerKeys to succeed\n"); 228 expect_LayerValue(bMachine, file, NULL); 229 230 ok(wrapSdbSetPermLayerKeys(fileW, " ", bMachine), "Expected SdbSetPermLayerKeys to succeed\n"); 231 expect_LayerValue(bMachine, file, " "); 232 233 ok(pSdbSetPermLayerKeys(fileW, NULL, bMachine) == TRUE, "Expected SdbSetPermLayerKeys to fail\n"); 234 expect_LayerValue(bMachine, file, NULL); 235 } 236 237 static void test_SdbGetPermLayerKeys(void) 238 { 239 WCHAR pathW[MAX_PATH], buffer[MAX_LAYER_LENGTH] = { 0 }; 240 char file[MAX_PATH + 20], tmp[MAX_PATH + 20]; 241 BOOL bUser, bMachine; 242 HANDLE hfile; 243 DWORD dwBufSize = sizeof(buffer); 244 245 GetTempPathA(MAX_PATH, tmp); 246 GetLongPathNameA(tmp, file, sizeof(file)); 247 PathCombineA(tmp, file, "notexist.exe"); 248 PathAppendA(file, "test_file.exe"); 249 250 /* Check that we can access the keys */ 251 bUser = setLayerValue(FALSE, file, "RUNASADMIN WINXPSP3"); 252 expect_LayerValue(FALSE, file, "RUNASADMIN WINXPSP3"); 253 ok(bUser, "Expected to be able to set atleast the flags for the user\n"); 254 if (!bUser) 255 { 256 skip("Cannot do any tests if I cannot set some values\n"); 257 return; 258 } 259 bMachine = setLayerValue(TRUE, file, "WINXPSP3 WINXPSP2"); 260 if (bMachine) 261 { 262 expect_LayerValue(TRUE, file, "WINXPSP3 WINXPSP2"); 263 } 264 265 266 hfile = CreateFileA(file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 267 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed on '%s'..\n", file); 268 if (hfile == INVALID_HANDLE_VALUE) 269 { 270 skip("Running these tests is useless without a file present\n"); 271 return; 272 } 273 CloseHandle(hfile); 274 275 MultiByteToWideChar(CP_ACP, 0, file, -1, pathW, MAX_PATH); 276 277 /* Parameter validation */ 278 ok(pSdbGetPermLayerKeys(NULL, NULL, NULL, 0) == FALSE, "Expected pSdbGetPermLayerKeys to fail\n"); 279 ok(pSdbGetPermLayerKeys(pathW, NULL, NULL, 0) == FALSE, "Expected pSdbGetPermLayerKeys to fail\n"); 280 ok(pSdbGetPermLayerKeys(pathW, buffer, NULL, 0) == FALSE, "Expected pSdbGetPermLayerKeys to fail\n"); 281 ok(pSdbGetPermLayerKeys(pathW, buffer, &dwBufSize, 0) == FALSE, "Expected pSdbGetPermLayerKeys to fail\n"); 282 ok(dwBufSize == 0, "Expected dwBufSize to be %u, was %u\n", 0, dwBufSize); 283 284 /* It fails on a nonexisting file */ 285 expect_Sdb(tmp, GPLK_USER | GPLK_MACHINE, FALSE, 0xffffffff, ""); 286 expect_Sdb(file, GPLK_USER, TRUE, 40, "RUNASADMIN WINXPSP3"); 287 GetShortPathNameA(file, tmp, sizeof(tmp)); 288 expect_Sdb(tmp, GPLK_USER, TRUE, 40, "RUNASADMIN WINXPSP3"); 289 290 if (bMachine) 291 { 292 /* Query from HKLM */ 293 expect_Sdb(file, GPLK_MACHINE, TRUE, 36, "WINXPSP3 WINXPSP2"); 294 /* Query from both, showing that duplicates are not removed */ 295 expect_Sdb(file, GPLK_USER | GPLK_MACHINE, TRUE, 76, "WINXPSP3 WINXPSP2 RUNASADMIN WINXPSP3"); 296 297 /* Showing that no validation is done on the value read. */ 298 ok(setLayerValue(TRUE, file, "!#!# WINXPSP3 WINXPSP3 !# WINXPSP2 "), "Expected setLayerValue not to fail\n"); 299 expect_Sdb(file, GPLK_MACHINE, TRUE, 82, "!#!# WINXPSP3 WINXPSP3 !# WINXPSP2 "); 300 /* Showing that a space is inserted, even if the last char was already a space. */ 301 expect_Sdb(file, GPLK_USER | GPLK_MACHINE, TRUE, 122, "!#!# WINXPSP3 WINXPSP3 !# WINXPSP2 RUNASADMIN WINXPSP3"); 302 /* Now clear the user key */ 303 setLayerValue(FALSE, file, NULL); 304 /* Request both, to show that the last space (from the key) is not cut off. */ 305 expect_Sdb(file, GPLK_USER | GPLK_MACHINE, TRUE, 82, "!#!# WINXPSP3 WINXPSP3 !# WINXPSP2 "); 306 setLayerValue(FALSE, file, "RUNASADMIN WINXPSP3"); 307 } 308 else 309 { 310 skip("Skipping tests for HKLM, cannot alter the registry\n"); 311 } 312 /* Fail from these paths */ 313 sprintf(tmp, "\\?\\%s", file); 314 expect_Sdb(tmp, GPLK_USER, FALSE, 0xffffffff, ""); 315 sprintf(tmp, "\\??\\%s", file); 316 expect_Sdb(tmp, GPLK_USER, FALSE, 0xffffffff, ""); 317 318 ok(setLayerValue(FALSE, file, "!#!# RUNASADMIN RUNASADMIN !# WINXPSP3 "), "Expected setLayerValue not to fail\n"); 319 /* There is no validation on information read back. */ 320 expect_Sdb(file, GPLK_USER, TRUE, 90, "!#!# RUNASADMIN RUNASADMIN !# WINXPSP3 "); 321 322 323 /* Cleanup */ 324 ok(DeleteFileA(file), "DeleteFile failed....\n"); 325 setLayerValue(FALSE, file, NULL); 326 setLayerValue(TRUE, file, NULL); 327 } 328 329 330 static BOOL wrapSetPermLayerState(PCWSTR wszPath, PCSTR szLayer, DWORD dwFlags, BOOL bMachine, BOOL bEnable) 331 { 332 WCHAR wszLayer[MAX_LAYER_LENGTH]; 333 MultiByteToWideChar(CP_ACP, 0, szLayer, -1, wszLayer, MAX_LAYER_LENGTH); 334 return pSetPermLayerState(wszPath, wszLayer, dwFlags, bMachine, bEnable); 335 } 336 337 static void test_SetPermLayerStateLevel(BOOL bMachine, const char* file) 338 { 339 WCHAR fileW[MAX_PATH+20]; 340 WCHAR emptyString[1] = { 0 }; 341 DWORD dwFlag; 342 343 MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, MAX_PATH+20); 344 345 /* Test some parameter validation. */ 346 ok(pSetPermLayerState(fileW, NULL, 0, bMachine, 0) == FALSE, "Expected SetPermLayerState to fail\n"); 347 expect_LayerValue(bMachine, file, NULL); 348 349 ok(pSetPermLayerState(fileW, NULL, 0, bMachine, 1) == FALSE, "Expected SetPermLayerState to fail\n"); 350 expect_LayerValue(bMachine, file, NULL); 351 352 ok(wrapSetPermLayerState(fileW, "", 0, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 353 expect_LayerValue(bMachine, file, NULL); 354 355 ok(wrapSetPermLayerState(fileW, "", 0, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 356 expect_LayerValue(bMachine, file, NULL); 357 358 ok(wrapSetPermLayerState(NULL, NULL, 0, bMachine, 0) == FALSE, "Expected SetPermLayerState to fail\n"); 359 expect_LayerValue(bMachine, NULL, NULL); 360 361 ok(wrapSetPermLayerState(NULL, NULL, 0, bMachine, 1) == FALSE, "Expected SetPermLayerState to fail\n"); 362 expect_LayerValue(bMachine, NULL, NULL); 363 364 ok(wrapSetPermLayerState(emptyString, "", 0, bMachine, 0) == FALSE, "Expected SetPermLayerState to fail\n"); 365 expect_LayerValue(bMachine, NULL, NULL); 366 367 ok(wrapSetPermLayerState(emptyString, "", 0, bMachine, 1) == FALSE, "Expected SetPermLayerState to fail\n"); 368 expect_LayerValue(bMachine, NULL, NULL); 369 370 ok(wrapSetPermLayerState(emptyString, "TEST", 0, bMachine, 0) == FALSE, "Expected SetPermLayerState to fail\n"); 371 expect_LayerValue(bMachine, NULL, NULL); 372 373 if (g_WinVersion <= WINVER_WIN8) 374 { 375 ok(wrapSetPermLayerState(emptyString, "TEST", 0, bMachine, 1) == FALSE, "Expected SetPermLayerState to fail\n"); 376 expect_LayerValue(bMachine, NULL, NULL); 377 } 378 379 380 /* Now, on to the actual tests. */ 381 expect_LayerValue(bMachine, file, NULL); 382 ok(wrapSetPermLayerState(fileW, "TEST", 0, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 383 expect_LayerValue(bMachine, file, NULL); 384 385 ok(wrapSetPermLayerState(fileW, "TEST", 0, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 386 expect_LayerValue(bMachine, file, "TEST"); 387 388 ok(wrapSetPermLayerState(fileW, "", 0, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 389 expect_LayerValue(bMachine, file, "TEST"); 390 391 ok(wrapSetPermLayerState(fileW, "test", 0, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 392 expect_LayerValue(bMachine, file, "test"); 393 394 ok(wrapSetPermLayerState(fileW, "TEST", 0, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 395 expect_LayerValue(bMachine, file, NULL); 396 397 ok(wrapSetPermLayerState(fileW, "TEST", 0, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 398 expect_LayerValue(bMachine, file, "TEST"); 399 400 ok(wrapSetPermLayerState(fileW, "TEST1", 0, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 401 expect_LayerValue2(bMachine, file, "TEST TEST1", g_WinVersion >= WINVER_WIN8, "TEST1 TEST"); 402 403 ok(wrapSetPermLayerState(fileW, "TEST2", 0, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 404 expect_LayerValue2(bMachine, file, "TEST TEST1 TEST2", g_WinVersion >= WINVER_WIN8, "TEST2 TEST1 TEST"); 405 406 ok(wrapSetPermLayerState(fileW, "TEST1", 0, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 407 expect_LayerValue2(bMachine, file, "TEST TEST2", g_WinVersion >= WINVER_WIN8, "TEST2 TEST"); 408 409 ok(wrapSetPermLayerState(fileW, "TEST", 0, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 410 expect_LayerValue(bMachine, file, "TEST2"); 411 412 ok(wrapSetPermLayerState(fileW, "TEST2", 0, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 413 expect_LayerValue(bMachine, file, NULL); 414 415 /* Valid flags until win8: !# */ 416 /* Key is empty, now play around with the flags. */ 417 for (dwFlag = ((g_WinVersion >= WINVER_WIN8) ? 6 : 2); dwFlag < 32; ++dwFlag) 418 { 419 ok(wrapSetPermLayerState(fileW, "TEST", (1<<dwFlag), bMachine, 1) == FALSE, "Expected SetPermLayerState to fail on 0x%x\n", (1<<dwFlag)); 420 } 421 expect_LayerValue(bMachine, file, NULL); 422 423 /* Add layer flags */ 424 ok(wrapSetPermLayerState(fileW, "TEST", LAYER_APPLY_TO_SYSTEM_EXES, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 425 expect_LayerValue(bMachine, file, "# TEST"); 426 427 ok(wrapSetPermLayerState(fileW, "TEST2", 2, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 428 expect_LayerValue2(bMachine, file, "!# TEST TEST2", g_WinVersion >= WINVER_WIN8, "!# TEST2 TEST"); 429 430 ok(wrapSetPermLayerState(fileW, "TEST", 0, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 431 expect_LayerValue2(bMachine, file, "!# TEST2 TEST", g_WinVersion >= WINVER_WIN8, "!# TEST TEST2"); 432 433 ok(wrapSetPermLayerState(fileW, "TEST3", 0, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 434 expect_LayerValue2(bMachine, file, "!# TEST2 TEST TEST3", g_WinVersion >= WINVER_WIN8, "!# TEST3 TEST TEST2"); 435 436 /* Remove on a flag removes that flag from the start. */ 437 ok(wrapSetPermLayerState(fileW, "TEST2", 2, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 438 expect_LayerValue2(bMachine, file, "# TEST TEST3", g_WinVersion >= WINVER_WIN8, "# TEST3 TEST"); 439 440 ok(wrapSetPermLayerState(fileW, "", LAYER_APPLY_TO_SYSTEM_EXES, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 441 expect_LayerValue2(bMachine, file, "TEST TEST3", g_WinVersion >= WINVER_WIN8, "TEST3 TEST"); 442 443 ok(wrapSetPermLayerState(fileW, "", LAYER_APPLY_TO_SYSTEM_EXES | 2, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 444 expect_LayerValue2(bMachine, file, "!# TEST TEST3", g_WinVersion >= WINVER_WIN8, "!# TEST3 TEST"); 445 446 ok(wrapSetPermLayerState(fileW, "TEST3", LAYER_APPLY_TO_SYSTEM_EXES, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 447 expect_LayerValue(bMachine, file, "! TEST"); 448 449 ok(wrapSetPermLayerState(fileW, "TEST", 2, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 450 expect_LayerValue(bMachine, file, NULL); 451 452 /* Try adding multiple layers: */ 453 ok(wrapSetPermLayerState(fileW, "TEST TEST2", LAYER_APPLY_TO_SYSTEM_EXES | 2, bMachine, 1) == FALSE, "Expected SetPermLayerState to fail\n"); 454 expect_LayerValue(bMachine, file, NULL); 455 456 ok(wrapSetPermLayerState(fileW, "TEST2", 0, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 457 expect_LayerValue(bMachine, file, "TEST2"); 458 459 /* Try adding flags in via layer string */ 460 ok(wrapSetPermLayerState(fileW, "#", 0, bMachine, 1) == FALSE, "Expected SetPermLayerState to fail\n"); 461 expect_LayerValue(bMachine, file, "TEST2"); 462 463 ok(wrapSetPermLayerState(fileW, "!", 0, bMachine, 1) == FALSE, "Expected SetPermLayerState to fail\n"); 464 expect_LayerValue(bMachine, file, "TEST2"); 465 466 /* Now we prepare the registry with some crap to see how data is validated. */ 467 setLayerValue(bMachine, file, "!#!# TEST2 TEST2 !# TEST "); 468 469 ok(wrapSetPermLayerState(fileW, "TEST1", 0, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 470 expect_LayerValue2(bMachine, file, "!# TEST2 TEST2 !# TEST TEST1", g_WinVersion >= WINVER_WIN8, "!# TEST1 TEST2 TEST2 !# TEST"); 471 472 /* Removing a duplicate entry will remove all instances of it */ 473 ok(wrapSetPermLayerState(fileW, "TEST2", 0, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 474 expect_LayerValue2(bMachine, file, "!# !# TEST TEST1", g_WinVersion >= WINVER_WIN8, "!# TEST1 !# TEST"); 475 476 /* Adding a flag cleans other flags (from the start) */ 477 ok(wrapSetPermLayerState(fileW, "", LAYER_APPLY_TO_SYSTEM_EXES, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 478 expect_LayerValue2(bMachine, file, "!# TEST TEST1", g_WinVersion >= WINVER_WIN8, "!# TEST1 !# TEST"); 479 480 if(g_WinVersion < WINVER_WIN8) 481 { 482 ok(wrapSetPermLayerState(fileW, "$%$%^^", 0, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 483 expect_LayerValue(bMachine, file, "!# TEST TEST1 $%$%^^"); 484 } 485 486 setLayerValue(bMachine, file, "!#!# TEST2 !# TEST "); 487 ok(wrapSetPermLayerState(fileW, "", LAYER_APPLY_TO_SYSTEM_EXES, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 488 expect_LayerValue(bMachine, file, "! TEST2 !# TEST"); 489 490 /* Tabs are treated as spaces */ 491 setLayerValue(bMachine, file, "!#!# TEST2 \t TEST2 !# \t TEST "); 492 ok(wrapSetPermLayerState(fileW, "TEST2", 0, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 493 expect_LayerValue2(bMachine, file, "!# !# TEST TEST2", g_WinVersion >= WINVER_WIN8, "!# TEST2 !# TEST"); 494 495 /* Newlines are left as-is */ 496 setLayerValue(bMachine, file, "!#!# TEST2 \n TEST2 !# \r\n TEST "); 497 ok(wrapSetPermLayerState(fileW, "TEST2", 0, bMachine, 1) == TRUE, "Expected SetPermLayerState to succeed\n"); 498 expect_LayerValue2(bMachine, file, "!# \n !# \r\n TEST TEST2", g_WinVersion >= WINVER_WIN8, "!# TEST2 \n !# \r\n TEST"); 499 500 /* Whitespace and duplicate flags are eaten from the start */ 501 setLayerValue(bMachine, file, " !#!# TEST2 \t TEST2 !# \t TEST "); 502 ok(wrapSetPermLayerState(fileW, "", LAYER_APPLY_TO_SYSTEM_EXES, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 503 expect_LayerValue(bMachine, file, "! TEST2 TEST2 !# TEST"); 504 505 setLayerValue(bMachine, file, "!# !# TEST2 !# TEST "); 506 ok(wrapSetPermLayerState(fileW, "", LAYER_APPLY_TO_SYSTEM_EXES, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 507 expect_LayerValue(bMachine, file, "! TEST2 !# TEST"); 508 509 ok(wrapSetPermLayerState(fileW, "", LAYER_APPLY_TO_SYSTEM_EXES, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 510 expect_LayerValue(bMachine, file, "! TEST2 !# TEST"); 511 512 ok(wrapSetPermLayerState(fileW, "", 2, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 513 expect_LayerValue(bMachine, file, "TEST2 !# TEST"); 514 515 /* First flags are cleaned, then a layer is removed. */ 516 ok(wrapSetPermLayerState(fileW, "TEST2", 2, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 517 expect_LayerValue(bMachine, file, "!# TEST"); 518 519 /* Nothing is changed, still it succeeds. */ 520 ok(wrapSetPermLayerState(fileW, "TEST2", 2, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 521 expect_LayerValue(bMachine, file, "# TEST"); 522 523 /* And remove the last bits. */ 524 ok(wrapSetPermLayerState(fileW, "TEST", LAYER_APPLY_TO_SYSTEM_EXES, bMachine, 0) == TRUE, "Expected SetPermLayerState to succeed\n"); 525 expect_LayerValue(bMachine, file, NULL); 526 } 527 528 static void test_SetPermLayer(void) 529 { 530 char file[MAX_PATH + 20], tmp[MAX_PATH + 20]; 531 HANDLE hfile; 532 533 GetTempPathA(MAX_PATH, tmp); 534 GetLongPathNameA(tmp, file, sizeof(file)); 535 PathAppendA(file, "test_file.exe"); 536 537 hfile = CreateFileA(file, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 538 ok(hfile != INVALID_HANDLE_VALUE, "CreateFile failed for '%s'\n", file); 539 if (hfile == INVALID_HANDLE_VALUE) 540 { 541 skip("Running these tests is useless without a file present\n"); 542 return; 543 } 544 CloseHandle(hfile); 545 546 if (setLayerValue(FALSE, file, NULL)) 547 { 548 test_SdbSetPermLayerKeysLevel(FALSE, file); 549 test_SetPermLayerStateLevel(FALSE, file); 550 } 551 else 552 { 553 skip("Skipping SetPermLayerStateLevel tests for User, because I cannot prepare the environment\n"); 554 } 555 if (setLayerValue(TRUE, file, NULL)) 556 { 557 test_SdbSetPermLayerKeysLevel(TRUE, file); 558 test_SetPermLayerStateLevel(TRUE, file); 559 } 560 else 561 { 562 skip("Skipping SetPermLayerStateLevel tests for Machine (HKLM), because I cannot prepare the environment\n"); 563 } 564 ok(DeleteFileA(file), "DeleteFile failed....\n"); 565 } 566 567 static BOOL create_file(LPCSTR dir, LPCSTR name, int filler, size_t size) 568 { 569 char target[MAX_PATH], *tmp; 570 HANDLE file; 571 PathCombineA(target, dir, name); 572 573 tmp = malloc(size); 574 memset(tmp, filler, size); 575 576 file = CreateFileA(target, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 577 if(file == INVALID_HANDLE_VALUE) 578 return FALSE; 579 580 WriteFile(file, tmp, size, &size, NULL); 581 CloseHandle(file); 582 free(tmp); 583 return TRUE; 584 } 585 586 static BOOL delete_file(LPCSTR dir, LPCSTR name) 587 { 588 char target[MAX_PATH]; 589 PathCombineA(target, dir, name); 590 return DeleteFileA(target); 591 } 592 593 static char g_FakeDrive = 0; 594 595 UINT (WINAPI *pGetDriveTypeW)(LPCWSTR target) = NULL; 596 UINT WINAPI mGetDriveTypeW(LPCWSTR target) 597 { 598 UINT uRet = pGetDriveTypeW(target); 599 if(g_FakeDrive && target && (char)*target == g_FakeDrive) 600 return DRIVE_CDROM; 601 return uRet; 602 } 603 604 static BOOL wrapSdbSetPermLayerKeys2(LPCSTR dir, LPCSTR name, PCSTR szLayers, BOOL bMachine) 605 { 606 char szPath[MAX_PATH]; 607 WCHAR wszPath[MAX_PATH], wszLayers[MAX_LAYER_LENGTH]; 608 PathCombineA(szPath, dir, name); 609 MultiByteToWideChar(CP_ACP, 0, szLayers, -1, wszLayers, MAX_LAYER_LENGTH); 610 MultiByteToWideChar(CP_ACP, 0, szPath, -1, wszPath, MAX_PATH); 611 return pSdbSetPermLayerKeys(wszPath, wszLayers, bMachine); 612 } 613 614 615 BOOL expect_files(const char* dir, int num, ...) 616 { 617 char finddir[MAX_PATH + 20]; 618 va_list args; 619 WIN32_FIND_DATAA find = { 0 }; 620 HANDLE hFind; 621 int cmp = 0; 622 623 va_start(args, num); 624 625 PathCombineA(finddir, dir, "*"); 626 hFind = FindFirstFileA(finddir, &find); 627 if (hFind != INVALID_HANDLE_VALUE) 628 { 629 const char* file; 630 do 631 { 632 if (!(find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) 633 { 634 if (--num < 0) 635 break; 636 file = va_arg(args, const char*); 637 cmp = strcmp(file, find.cFileName); 638 } 639 } while (cmp == 0 && FindNextFileA(hFind, &find)); 640 FindClose(hFind); 641 } 642 va_end(args); 643 return cmp == 0 && num == 0; 644 } 645 646 647 static void test_Sign_Media(void) 648 { 649 char workdir[MAX_PATH], subdir[MAX_PATH], drive[5] = "Z:"; 650 BOOL ret; 651 652 DWORD logical_drives = GetLogicalDrives(); 653 g_FakeDrive = 0; 654 for (drive[0] = 'D'; drive[0] <= 'Z'; drive[0]++) 655 { 656 DWORD idx = 1 << (drive[0] - 'D' + 3); 657 if (!(logical_drives & idx)) 658 { 659 g_FakeDrive = drive[0]; 660 break; 661 } 662 } 663 if (!g_FakeDrive) 664 { 665 skip("Unable to find a free drive\n"); 666 return; 667 } 668 669 ret = GetTempPathA(MAX_PATH, workdir); 670 ok(ret, "GetTempPathA error: %d\n", GetLastError()); 671 PathAppendA(workdir, "apphelp_test"); 672 673 ret = CreateDirectoryA(workdir, NULL); 674 ok(ret, "CreateDirectoryA error: %d\n", GetLastError()); 675 676 PathCombineA(subdir, workdir, "sub"); 677 ret = CreateDirectoryA(subdir, NULL); 678 ok(ret, "CreateDirectoryA error: %d\n", GetLastError()); 679 680 ret = DefineDosDeviceA(DDD_NO_BROADCAST_SYSTEM, drive, workdir); 681 ok(ret, "DefineDosDeviceA error: %d\n", GetLastError()); 682 if(ret) 683 { 684 ret = RedirectIat(GetModuleHandleA("apphelp.dll"), "kernel32.dll", "GetDriveTypeW", 685 (ULONG_PTR)mGetDriveTypeW, (ULONG_PTR*)&pGetDriveTypeW); 686 if (g_WinVersion < WINVER_WIN8) 687 ok(ret, "Expected redirect_iat to succeed\n"); 688 if(ret) 689 { 690 ok(create_file(workdir, "test.exe", 'a', 4), "create_file error: %d\n", GetLastError()); 691 692 ok(wrapSdbSetPermLayerKeys2(drive, "test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n"); 693 /* 4 */ 694 /* test.exe */ 695 expect_LayerValue(0, "SIGN.MEDIA=4 test.exe", "TEST"); 696 ok(wrapSdbSetPermLayerKeys2(drive, "test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n"); 697 698 ok(create_file(workdir, "test.txt", 'a', 1), "create_file error: %d\n", GetLastError()); 699 700 if (!expect_files(workdir, 2, "test.exe", "test.txt")) 701 { 702 skip("Skipping test, files are not returned in the expected order by the FS\n"); 703 } 704 else 705 { 706 ok(wrapSdbSetPermLayerKeys2(drive, "test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n"); 707 /* (4 << 1) ^ 1 */ 708 /* test.exe test.txt */ 709 expect_LayerValue(0, "SIGN.MEDIA=9 test.exe", "TEST"); 710 ok(wrapSdbSetPermLayerKeys2(drive, "test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n"); 711 } 712 713 ok(create_file(workdir, "test.zz", 'a', 0x1000), "create_file error: %d\n", GetLastError()); 714 715 if (!expect_files(workdir, 3, "test.exe", "test.txt", "test.zz")) 716 { 717 skip("Skipping test, files are not returned in the expected order by the FS\n"); 718 } 719 else 720 { 721 ok(wrapSdbSetPermLayerKeys2(drive, "test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n"); 722 /* (((4 << 1) ^ 1) << 1) ^ 0x1000 */ 723 /* test.exe test.txt test.zz */ 724 expect_LayerValue(0, "SIGN.MEDIA=1012 test.exe", "TEST"); 725 ok(wrapSdbSetPermLayerKeys2(drive, "test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n"); 726 } 727 728 ok(create_file(subdir, "test.exe", 'a', 0x10203), "create_file error: %d\n", GetLastError()); 729 730 if (!expect_files(subdir, 1, "test.exe")) 731 { 732 skip("Skipping test, files are not returned in the expected order by the FS\n"); 733 } 734 else 735 { 736 ok(wrapSdbSetPermLayerKeys2(drive, "sub\\test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n"); 737 /* 0x10203 */ 738 /* test.exe */ 739 expect_LayerValue(0, "SIGN.MEDIA=10203 sub\\test.exe", "TEST"); 740 ok(wrapSdbSetPermLayerKeys2(drive, "sub\\test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n"); 741 } 742 743 ok(create_file(subdir, "test.bbb", 'a', 0), "create_file error: %d\n", GetLastError()); 744 745 if (!expect_files(subdir, 2, "test.bbb", "test.exe")) 746 { 747 skip("Skipping test, files are not returned in the expected order by the FS\n"); 748 } 749 else 750 { 751 ok(wrapSdbSetPermLayerKeys2(drive, "sub\\test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n"); 752 /* 0x10203 */ 753 /* test.exe */ 754 expect_LayerValue(0, "SIGN.MEDIA=10203 sub\\test.exe", "TEST"); 755 ok(wrapSdbSetPermLayerKeys2(drive, "sub\\test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n"); 756 } 757 758 ok(create_file(subdir, "TEST.txt", 'a', 0x30201), "create_file error: %d\n", GetLastError()); 759 760 if (!expect_files(subdir, 3, "test.bbb", "test.exe", "TEST.txt")) 761 { 762 skip("Skipping test, files are not returned in the expected order by the FS\n"); 763 } 764 else 765 { 766 ok(wrapSdbSetPermLayerKeys2(drive, "sub\\test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n"); 767 /* (0x10203 << 1) ^ 0x30201 */ 768 /* test.exe TEST.txt */ 769 expect_LayerValue(0, "SIGN.MEDIA=10607 sub\\test.exe", "TEST"); 770 ok(wrapSdbSetPermLayerKeys2(drive, "sub\\test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n"); 771 } 772 773 ok(create_file(subdir, "TEST.aaa", 'a', 0x3a2a1), "create_file error: %d\n", GetLastError()); 774 775 if (!expect_files(subdir, 4, "TEST.aaa", "test.bbb", "test.exe", "TEST.txt")) 776 { 777 skip("Skipping test, files are not returned in the expected order by the FS\n"); 778 } 779 else 780 { 781 ok(wrapSdbSetPermLayerKeys2(drive, "sub\\test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n"); 782 /* (((0x3a2a1 << 1) ^ 0x10203) << 1) ^ 0x30201 */ 783 /* TEST.aaa test.exe TEST.txt */ 784 expect_LayerValue(0, "SIGN.MEDIA=F8C83 sub\\test.exe", "TEST"); 785 ok(wrapSdbSetPermLayerKeys2(drive, "sub\\test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n"); 786 } 787 788 ret = RestoreIat(GetModuleHandleA("apphelp.dll"), "kernel32.dll", "GetDriveTypeW", (ULONG_PTR)pGetDriveTypeW); 789 ok(ret, "Expected restore_iat to succeed\n"); 790 791 ok(delete_file(subdir, "test.bbb"), "delete_file error: %d\n", GetLastError()); 792 ok(delete_file(subdir, "TEST.aaa"), "delete_file error: %d\n", GetLastError()); 793 ok(delete_file(subdir, "TEST.txt"), "delete_file error: %d\n", GetLastError()); 794 ok(delete_file(subdir, "test.exe"), "delete_file error: %d\n", GetLastError()); 795 ok(delete_file(workdir, "test.zz"), "delete_file error: %d\n", GetLastError()); 796 ok(delete_file(workdir, "test.txt"), "delete_file error: %d\n", GetLastError()); 797 ok(delete_file(workdir, "test.exe"), "delete_file error: %d\n", GetLastError()); 798 } 799 ret = DefineDosDeviceA(DDD_REMOVE_DEFINITION | DDD_NO_BROADCAST_SYSTEM, drive, NULL); 800 ok(ret, "DefineDosDeviceA error: %d\n", GetLastError()); 801 } 802 ret = RemoveDirectoryA(subdir); 803 ok(ret, "RemoveDirectoryA error: %d\n", GetLastError()); 804 ret = RemoveDirectoryA(workdir); 805 ok(ret, "RemoveDirectoryA error: %d\n", GetLastError()); 806 } 807 808 809 START_TEST(layerapi) 810 { 811 silence_debug_output(); 812 /*SetEnvironmentVariable("SHIM_DEBUG_LEVEL", "4");*/ 813 hdll = LoadLibraryA("apphelp.dll"); 814 pAllowPermLayer = (void *)GetProcAddress(hdll, "AllowPermLayer"); 815 pSdbSetPermLayerKeys = (void *)GetProcAddress(hdll, "SdbSetPermLayerKeys"); 816 pSdbGetPermLayerKeys = (void *)GetProcAddress(hdll, "SdbGetPermLayerKeys"); 817 pSetPermLayerState = (void *)GetProcAddress(hdll, "SetPermLayerState"); 818 g_WinVersion = get_host_winver(); 819 820 if (!pAllowPermLayer) 821 { 822 skip("Skipping tests with AllowPermLayer, function not found\n"); 823 } 824 else 825 { 826 test_AllowPermLayer(); 827 } 828 829 if (!pSdbSetPermLayerKeys) 830 { 831 skip("Skipping tests with SdbSetPermLayerKeys, function not found\n"); 832 } 833 else 834 { 835 if (!pSdbGetPermLayerKeys) 836 { 837 skip("Skipping tests with SdbGetPermLayerKeys, function not found\n"); 838 } 839 else 840 { 841 test_SdbGetPermLayerKeys(); 842 } 843 844 if (!pSetPermLayerState) 845 { 846 skip("Skipping tests with SetPermLayerState, function not found\n"); 847 } 848 else 849 { 850 test_SetPermLayer(); 851 test_Sign_Media(); 852 } 853 } 854 } 855