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