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