2 * Copyright 2015,2016 Mark Jansen
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define WIN32_NO_STATUS
32 #include "wine/test.h"
34 #include "apphelp_apitest.h"
37 #define GPLK_MACHINE 2
38 #define MAX_LAYER_LENGTH 256
39 #define LAYER_APPLY_TO_SYSTEM_EXES 1
43 static BOOL(WINAPI
*pAllowPermLayer
)(PCWSTR path
);
44 static BOOL(WINAPI
*pSdbSetPermLayerKeys
)(PCWSTR wszPath
, PCWSTR wszLayers
, BOOL bMachine
);
45 static BOOL(WINAPI
*pSdbGetPermLayerKeys
)(PCWSTR wszPath
, PWSTR pwszLayers
, PDWORD pdwBytes
, DWORD dwFlags
);
46 static BOOL(WINAPI
*pSetPermLayerState
)(PCWSTR wszPath
, PCWSTR wszLayer
, DWORD dwFlags
, BOOL bMachine
, BOOL bEnable
);
49 /* Helper function to disable Wow64 redirection on an os that reports it being enabled. */
50 static DWORD g_QueryFlag
= 0xffffffff;
51 static DWORD
QueryFlag(void)
53 if (g_QueryFlag
== 0xffffffff)
55 ULONG_PTR wow64_ptr
= 0;
56 NTSTATUS status
= NtQueryInformationProcess(NtCurrentProcess(), ProcessWow64Information
, &wow64_ptr
, sizeof(wow64_ptr
), NULL
);
57 g_QueryFlag
= (NT_SUCCESS(status
) && wow64_ptr
!= 0) ? KEY_WOW64_64KEY
: 0;
62 /* Helper function to prepare the registry key with a value. */
63 static BOOL
setLayerValue(BOOL bMachine
, const char* valueName
, const char* value
)
66 LSTATUS lstatus
= RegCreateKeyExA(bMachine
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
67 "Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers", 0, NULL
, 0, QueryFlag() | KEY_SET_VALUE
, NULL
, &key
, NULL
);
68 if (lstatus
== ERROR_SUCCESS
)
71 lstatus
= RegSetValueExA(key
, valueName
, 0, REG_SZ
, (const BYTE
*)value
, strlen(value
)+1);
74 lstatus
= RegDeleteValueA(key
, valueName
);
75 lstatus
= (lstatus
== ERROR_FILE_NOT_FOUND
? ERROR_SUCCESS
: lstatus
);
79 return lstatus
== ERROR_SUCCESS
;
83 static void expect_LayerValue_imp(BOOL bMachine
, const char* valueName
, const char* value
)
86 LSTATUS lstatus
= RegCreateKeyExA(bMachine
? HKEY_LOCAL_MACHINE
: HKEY_CURRENT_USER
,
87 "Software\\Microsoft\\Windows NT\\CurrentVersion\\AppCompatFlags\\Layers", 0, NULL
, 0, QueryFlag() | KEY_QUERY_VALUE
, NULL
, &key
, NULL
);
88 winetest_ok(lstatus
== ERROR_SUCCESS
, "Expected to be able to open a registry key\n");
89 if (lstatus
== ERROR_SUCCESS
)
91 char data
[512] = { 0 };
93 DWORD dwDataLen
= sizeof(data
);
94 lstatus
= RegQueryValueExA(key
, valueName
, NULL
, &dwType
, (LPBYTE
)data
, &dwDataLen
);
97 winetest_ok(lstatus
== ERROR_SUCCESS
, "Expected to get a valid value, err: %u\n", lstatus
);
98 if (lstatus
== ERROR_SUCCESS
)
100 winetest_ok(dwType
== REG_SZ
, "Expected the type to be REG_SZ, was: %u\n", dwType
);
101 winetest_ok(!strcmp(data
, value
), "Expected the data to be: '%s', was: '%s'\n", value
, data
);
106 winetest_ok(lstatus
== ERROR_FILE_NOT_FOUND
, "Expected not to find the value %s\n", valueName
);
112 static void expect_LayerValue_imp2(BOOL bMachine
, const char* valueName
, const char* value
, int use_alt
, const char* alt_value
)
114 expect_LayerValue_imp(bMachine
, valueName
, use_alt
? alt_value
: value
);
118 void expect_Sdb_imp(PCSTR path
, DWORD type
, BOOL result
, DWORD lenResult
, PCSTR stringResult
)
120 WCHAR pathW
[MAX_PATH
], buffer
[MAX_LAYER_LENGTH
] = { 0 };
121 char resultBuffer
[MAX_LAYER_LENGTH
] = { 0 };
122 DWORD dwBufSize
= sizeof(buffer
);
124 /* In case of a failure, the buffer size is sometimes set to 0, and sometimes not touched,
125 depending on the version. Either case is fine, since the function returns FALSE anyway. */
127 MultiByteToWideChar(CP_ACP
, 0, path
, -1, pathW
, MAX_PATH
);
129 winetest_ok(pSdbGetPermLayerKeys(pathW
, buffer
, &dwBufSize
, type
) == result
, "Expected pSdbGetPermLayerKeys to %s\n", (result
? "succeed" : "fail"));
130 if (!result
&& lenResult
== 0xffffffff)
131 winetest_ok(dwBufSize
== 0 || dwBufSize
== sizeof(buffer
), "Expected dwBufSize to be 0 or %u, was %u\n", sizeof(buffer
), dwBufSize
);
133 winetest_ok(dwBufSize
== lenResult
||
134 /* W2k3 is off by 2 when concatenating user / machine */
135 broken(g_WinVersion
< WINVER_VISTA
&& type
== (GPLK_MACHINE
|GPLK_USER
) && (lenResult
+ 2) == dwBufSize
),
136 "Expected dwBufSize to be %u, was %u\n", lenResult
, dwBufSize
);
139 winetest_ok(lstrlenW(buffer
) * sizeof(WCHAR
) + sizeof(WCHAR
) == lenResult
, "Expected lstrlenW(buffer)*2+2 to be %u, was %u\n",
140 lenResult
, lstrlenW(buffer
) * sizeof(WCHAR
) + sizeof(WCHAR
));
142 WideCharToMultiByte(CP_ACP
, 0, buffer
, -1, resultBuffer
, sizeof(resultBuffer
), NULL
, NULL
);
143 winetest_ok(!strcmp(stringResult
, resultBuffer
), "Expected the result to be '%s', was '%s'\n", stringResult
, resultBuffer
);
147 /* In case of a failure, let the location be from where the function was invoked, not inside the function itself. */
148 #define expect_Sdb (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_Sdb_imp
149 #define expect_LayerValue (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_LayerValue_imp
150 #define expect_LayerValue2 (winetest_set_location(__FILE__, __LINE__), 0) ? (void)0 : expect_LayerValue_imp2
153 BOOL
wrapAllowPermLayer(const char* str
)
156 MultiByteToWideChar(CP_ACP
, 0, str
, -1, buf
, 100);
157 return pAllowPermLayer(buf
);
160 /* Brute forcing all ascii chars in the first 2 places seems to indicate that all it cares for is:
161 - Second char has to be a ':'
162 if it's not a ':', display a diagnostic message (and a different one for '\\').
163 - 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...)
165 static void test_AllowPermLayer(void)
170 ok(pAllowPermLayer(NULL
) == FALSE
, "Expected AllowPermLayer to fail for NULL\n");
171 if (g_WinVersion
< WINVER_WIN8
)
173 ok(wrapAllowPermLayer("-:"), "Expected AllowPermLayer to succeed\n");
174 ok(wrapAllowPermLayer("@:"), "Expected AllowPermLayer to succeed\n");
175 ok(wrapAllowPermLayer("4:"), "Expected AllowPermLayer to succeed\n");
176 ok(wrapAllowPermLayer("*:"), "Expected AllowPermLayer to succeed\n");
178 ok(wrapAllowPermLayer("*a") == FALSE
, "Expected AllowPermLayer to fail\n");
179 ok(wrapAllowPermLayer("*\\") == FALSE
, "Expected AllowPermLayer to fail\n");
180 for (drive_letter
= 'a'; drive_letter
<= 'z'; ++drive_letter
)
182 sprintf(buf
, "%c:\\", drive_letter
);
183 drivetype
= GetDriveTypeA(buf
);
184 ok(wrapAllowPermLayer(buf
) == (drivetype
!= DRIVE_REMOTE
), "Expected AllowPermLayer to be %d for %c:\\\n", (drivetype
!= DRIVE_REMOTE
), drive_letter
);
188 static BOOL
wrapSdbSetPermLayerKeys(PCWSTR wszPath
, PCSTR szLayers
, BOOL bMachine
)
190 WCHAR wszLayers
[MAX_LAYER_LENGTH
];
191 MultiByteToWideChar(CP_ACP
, 0, szLayers
, -1, wszLayers
, MAX_LAYER_LENGTH
);
192 return pSdbSetPermLayerKeys(wszPath
, wszLayers
, bMachine
);
195 static void test_SdbSetPermLayerKeysLevel(BOOL bMachine
, const char* file
)
197 WCHAR fileW
[MAX_PATH
+20];
198 WCHAR emptyString
[1] = { 0 };
200 MultiByteToWideChar(CP_ACP
, 0, file
, -1, fileW
, MAX_PATH
+20);
202 /* Test some parameter validation. */
203 ok(pSdbSetPermLayerKeys(NULL
, NULL
, bMachine
) == FALSE
, "Expected SdbSetPermLayerKeys to fail\n");
204 ok(pSdbSetPermLayerKeys(NULL
, emptyString
, bMachine
) == FALSE
, "Expected SdbSetPermLayerKeys to fail\n");
205 ok(pSdbSetPermLayerKeys(emptyString
, emptyString
, bMachine
) == FALSE
, "Expected SdbSetPermLayerKeys to fail\n");
206 ok(pSdbSetPermLayerKeys(fileW
, NULL
, bMachine
) == TRUE
, "Expected SdbSetPermLayerKeys to succeed\n");
207 ok(pSdbSetPermLayerKeys(fileW
, emptyString
, bMachine
) == TRUE
, "Expected SdbSetPermLayerKeys to fail\n");
210 ok(wrapSdbSetPermLayerKeys(fileW
, "TEST1", bMachine
), "Expected SdbSetPermLayerKeys to succeed\n");
211 expect_LayerValue(bMachine
, file
, "TEST1");
213 ok(wrapSdbSetPermLayerKeys(fileW
, "TEST1 TEST2", bMachine
), "Expected SdbSetPermLayerKeys to succeed\n");
214 expect_LayerValue(bMachine
, file
, "TEST1 TEST2");
216 /* SdbSetPermLayerKeys does not do any validation of the value passed in. */
217 ok(wrapSdbSetPermLayerKeys(fileW
, "!#$% TEST1 TEST2", bMachine
), "Expected SdbSetPermLayerKeys to succeed\n");
218 expect_LayerValue(bMachine
, file
, "!#$% TEST1 TEST2");
220 ok(wrapSdbSetPermLayerKeys(fileW
, "!#$% TEST1 TEST2", bMachine
), "Expected SdbSetPermLayerKeys to succeed\n");
221 expect_LayerValue(bMachine
, file
, "!#$% TEST1 TEST2");
223 ok(pSdbSetPermLayerKeys(fileW
, NULL
, bMachine
) == TRUE
, "Expected SdbSetPermLayerKeys to succeed\n");
224 expect_LayerValue(bMachine
, file
, NULL
);
226 ok(wrapSdbSetPermLayerKeys(fileW
, " ", bMachine
), "Expected SdbSetPermLayerKeys to succeed\n");
227 expect_LayerValue(bMachine
, file
, " ");
229 ok(pSdbSetPermLayerKeys(fileW
, NULL
, bMachine
) == TRUE
, "Expected SdbSetPermLayerKeys to fail\n");
230 expect_LayerValue(bMachine
, file
, NULL
);
233 static void test_SdbGetPermLayerKeys(void)
235 WCHAR pathW
[MAX_PATH
], buffer
[MAX_LAYER_LENGTH
] = { 0 };
236 char file
[MAX_PATH
+ 20], tmp
[MAX_PATH
+ 20];
237 BOOL bUser
, bMachine
;
239 DWORD dwBufSize
= sizeof(buffer
);
241 GetTempPathA(MAX_PATH
, tmp
);
242 GetLongPathNameA(tmp
, file
, sizeof(file
));
243 PathCombineA(tmp
, file
, "notexist.exe");
244 PathAppendA(file
, "test_file.exe");
246 /* Check that we can access the keys */
247 bUser
= setLayerValue(FALSE
, file
, "RUNASADMIN WINXPSP3");
248 expect_LayerValue(FALSE
, file
, "RUNASADMIN WINXPSP3");
249 ok(bUser
, "Expected to be able to set atleast the flags for the user\n");
252 skip("Cannot do any tests if I cannot set some values\n");
255 bMachine
= setLayerValue(TRUE
, file
, "WINXPSP3 WINXPSP2");
258 expect_LayerValue(TRUE
, file
, "WINXPSP3 WINXPSP2");
262 hfile
= CreateFileA(file
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
263 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile failed on '%s'..\n", file
);
264 if (hfile
== INVALID_HANDLE_VALUE
)
266 skip("Running these tests is useless without a file present\n");
271 MultiByteToWideChar(CP_ACP
, 0, file
, -1, pathW
, MAX_PATH
);
273 /* Parameter validation */
274 ok(pSdbGetPermLayerKeys(NULL
, NULL
, NULL
, 0) == FALSE
, "Expected pSdbGetPermLayerKeys to fail\n");
275 ok(pSdbGetPermLayerKeys(pathW
, NULL
, NULL
, 0) == FALSE
, "Expected pSdbGetPermLayerKeys to fail\n");
276 ok(pSdbGetPermLayerKeys(pathW
, buffer
, NULL
, 0) == FALSE
, "Expected pSdbGetPermLayerKeys to fail\n");
277 ok(pSdbGetPermLayerKeys(pathW
, buffer
, &dwBufSize
, 0) == FALSE
, "Expected pSdbGetPermLayerKeys to fail\n");
278 ok(dwBufSize
== 0, "Expected dwBufSize to be %u, was %u\n", 0, dwBufSize
);
280 /* It fails on a nonexisting file */
281 expect_Sdb(tmp
, GPLK_USER
| GPLK_MACHINE
, FALSE
, 0xffffffff, "");
282 expect_Sdb(file
, GPLK_USER
, TRUE
, 40, "RUNASADMIN WINXPSP3");
283 GetShortPathNameA(file
, tmp
, sizeof(tmp
));
284 expect_Sdb(tmp
, GPLK_USER
, TRUE
, 40, "RUNASADMIN WINXPSP3");
288 /* Query from HKLM */
289 expect_Sdb(file
, GPLK_MACHINE
, TRUE
, 36, "WINXPSP3 WINXPSP2");
290 /* Query from both, showing that duplicates are not removed */
291 expect_Sdb(file
, GPLK_USER
| GPLK_MACHINE
, TRUE
, 76, "WINXPSP3 WINXPSP2 RUNASADMIN WINXPSP3");
293 /* Showing that no validation is done on the value read. */
294 ok(setLayerValue(TRUE
, file
, "!#!# WINXPSP3 WINXPSP3 !# WINXPSP2 "), "Expected setLayerValue not to fail\n");
295 expect_Sdb(file
, GPLK_MACHINE
, TRUE
, 82, "!#!# WINXPSP3 WINXPSP3 !# WINXPSP2 ");
296 /* Showing that a space is inserted, even if the last char was already a space. */
297 expect_Sdb(file
, GPLK_USER
| GPLK_MACHINE
, TRUE
, 122, "!#!# WINXPSP3 WINXPSP3 !# WINXPSP2 RUNASADMIN WINXPSP3");
298 /* Now clear the user key */
299 setLayerValue(FALSE
, file
, NULL
);
300 /* Request both, to show that the last space (from the key) is not cut off. */
301 expect_Sdb(file
, GPLK_USER
| GPLK_MACHINE
, TRUE
, 82, "!#!# WINXPSP3 WINXPSP3 !# WINXPSP2 ");
302 setLayerValue(FALSE
, file
, "RUNASADMIN WINXPSP3");
306 skip("Skipping tests for HKLM, cannot alter the registry\n");
308 /* Fail from these paths */
309 sprintf(tmp
, "\\?\\%s", file
);
310 expect_Sdb(tmp
, GPLK_USER
, FALSE
, 0xffffffff, "");
311 sprintf(tmp
, "\\??\\%s", file
);
312 expect_Sdb(tmp
, GPLK_USER
, FALSE
, 0xffffffff, "");
314 ok(setLayerValue(FALSE
, file
, "!#!# RUNASADMIN RUNASADMIN !# WINXPSP3 "), "Expected setLayerValue not to fail\n");
315 /* There is no validation on information read back. */
316 expect_Sdb(file
, GPLK_USER
, TRUE
, 90, "!#!# RUNASADMIN RUNASADMIN !# WINXPSP3 ");
320 ok(DeleteFileA(file
), "DeleteFile failed....\n");
321 setLayerValue(FALSE
, file
, NULL
);
322 setLayerValue(TRUE
, file
, NULL
);
326 static BOOL
wrapSetPermLayerState(PCWSTR wszPath
, PCSTR szLayer
, DWORD dwFlags
, BOOL bMachine
, BOOL bEnable
)
328 WCHAR wszLayer
[MAX_LAYER_LENGTH
];
329 MultiByteToWideChar(CP_ACP
, 0, szLayer
, -1, wszLayer
, MAX_LAYER_LENGTH
);
330 return pSetPermLayerState(wszPath
, wszLayer
, dwFlags
, bMachine
, bEnable
);
333 static void test_SetPermLayerStateLevel(BOOL bMachine
, const char* file
)
335 WCHAR fileW
[MAX_PATH
+20];
336 WCHAR emptyString
[1] = { 0 };
339 MultiByteToWideChar(CP_ACP
, 0, file
, -1, fileW
, MAX_PATH
+20);
341 /* Test some parameter validation. */
342 ok(pSetPermLayerState(fileW
, NULL
, 0, bMachine
, 0) == FALSE
, "Expected SetPermLayerState to fail\n");
343 expect_LayerValue(bMachine
, file
, NULL
);
345 ok(pSetPermLayerState(fileW
, NULL
, 0, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
346 expect_LayerValue(bMachine
, file
, NULL
);
348 ok(wrapSetPermLayerState(fileW
, "", 0, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
349 expect_LayerValue(bMachine
, file
, NULL
);
351 ok(wrapSetPermLayerState(fileW
, "", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
352 expect_LayerValue(bMachine
, file
, NULL
);
354 ok(wrapSetPermLayerState(NULL
, NULL
, 0, bMachine
, 0) == FALSE
, "Expected SetPermLayerState to fail\n");
355 expect_LayerValue(bMachine
, NULL
, NULL
);
357 ok(wrapSetPermLayerState(NULL
, NULL
, 0, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
358 expect_LayerValue(bMachine
, NULL
, NULL
);
360 ok(wrapSetPermLayerState(emptyString
, "", 0, bMachine
, 0) == FALSE
, "Expected SetPermLayerState to fail\n");
361 expect_LayerValue(bMachine
, NULL
, NULL
);
363 ok(wrapSetPermLayerState(emptyString
, "", 0, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
364 expect_LayerValue(bMachine
, NULL
, NULL
);
366 ok(wrapSetPermLayerState(emptyString
, "TEST", 0, bMachine
, 0) == FALSE
, "Expected SetPermLayerState to fail\n");
367 expect_LayerValue(bMachine
, NULL
, NULL
);
369 if (g_WinVersion
<= WINVER_WIN8
)
371 ok(wrapSetPermLayerState(emptyString
, "TEST", 0, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
372 expect_LayerValue(bMachine
, NULL
, NULL
);
376 /* Now, on to the actual tests. */
377 expect_LayerValue(bMachine
, file
, NULL
);
378 ok(wrapSetPermLayerState(fileW
, "TEST", 0, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
379 expect_LayerValue(bMachine
, file
, NULL
);
381 ok(wrapSetPermLayerState(fileW
, "TEST", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
382 expect_LayerValue(bMachine
, file
, "TEST");
384 ok(wrapSetPermLayerState(fileW
, "", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
385 expect_LayerValue(bMachine
, file
, "TEST");
387 ok(wrapSetPermLayerState(fileW
, "test", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
388 expect_LayerValue(bMachine
, file
, "test");
390 ok(wrapSetPermLayerState(fileW
, "TEST", 0, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
391 expect_LayerValue(bMachine
, file
, NULL
);
393 ok(wrapSetPermLayerState(fileW
, "TEST", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
394 expect_LayerValue(bMachine
, file
, "TEST");
396 ok(wrapSetPermLayerState(fileW
, "TEST1", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
397 expect_LayerValue2(bMachine
, file
, "TEST TEST1", g_WinVersion
>= WINVER_WIN8
, "TEST1 TEST");
399 ok(wrapSetPermLayerState(fileW
, "TEST2", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
400 expect_LayerValue2(bMachine
, file
, "TEST TEST1 TEST2", g_WinVersion
>= WINVER_WIN8
, "TEST2 TEST1 TEST");
402 ok(wrapSetPermLayerState(fileW
, "TEST1", 0, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
403 expect_LayerValue2(bMachine
, file
, "TEST TEST2", g_WinVersion
>= WINVER_WIN8
, "TEST2 TEST");
405 ok(wrapSetPermLayerState(fileW
, "TEST", 0, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
406 expect_LayerValue(bMachine
, file
, "TEST2");
408 ok(wrapSetPermLayerState(fileW
, "TEST2", 0, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
409 expect_LayerValue(bMachine
, file
, NULL
);
411 /* Valid flags until win8: !# */
412 /* Key is empty, now play around with the flags. */
413 for (dwFlag
= ((g_WinVersion
>= WINVER_WIN8
) ? 6 : 2); dwFlag
< 32; ++dwFlag
)
415 ok(wrapSetPermLayerState(fileW
, "TEST", (1<<dwFlag
), bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail on 0x%x\n", (1<<dwFlag
));
417 expect_LayerValue(bMachine
, file
, NULL
);
419 /* Add layer flags */
420 ok(wrapSetPermLayerState(fileW
, "TEST", LAYER_APPLY_TO_SYSTEM_EXES
, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
421 expect_LayerValue(bMachine
, file
, "# TEST");
423 ok(wrapSetPermLayerState(fileW
, "TEST2", 2, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
424 expect_LayerValue2(bMachine
, file
, "!# TEST TEST2", g_WinVersion
>= WINVER_WIN8
, "!# TEST2 TEST");
426 ok(wrapSetPermLayerState(fileW
, "TEST", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
427 expect_LayerValue2(bMachine
, file
, "!# TEST2 TEST", g_WinVersion
>= WINVER_WIN8
, "!# TEST TEST2");
429 ok(wrapSetPermLayerState(fileW
, "TEST3", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
430 expect_LayerValue2(bMachine
, file
, "!# TEST2 TEST TEST3", g_WinVersion
>= WINVER_WIN8
, "!# TEST3 TEST TEST2");
432 /* Remove on a flag removes that flag from the start. */
433 ok(wrapSetPermLayerState(fileW
, "TEST2", 2, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
434 expect_LayerValue2(bMachine
, file
, "# TEST TEST3", g_WinVersion
>= WINVER_WIN8
, "# TEST3 TEST");
436 ok(wrapSetPermLayerState(fileW
, "", LAYER_APPLY_TO_SYSTEM_EXES
, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
437 expect_LayerValue2(bMachine
, file
, "TEST TEST3", g_WinVersion
>= WINVER_WIN8
, "TEST3 TEST");
439 ok(wrapSetPermLayerState(fileW
, "", LAYER_APPLY_TO_SYSTEM_EXES
| 2, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
440 expect_LayerValue2(bMachine
, file
, "!# TEST TEST3", g_WinVersion
>= WINVER_WIN8
, "!# TEST3 TEST");
442 ok(wrapSetPermLayerState(fileW
, "TEST3", LAYER_APPLY_TO_SYSTEM_EXES
, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
443 expect_LayerValue(bMachine
, file
, "! TEST");
445 ok(wrapSetPermLayerState(fileW
, "TEST", 2, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
446 expect_LayerValue(bMachine
, file
, NULL
);
448 /* Try adding multiple layers: */
449 ok(wrapSetPermLayerState(fileW
, "TEST TEST2", LAYER_APPLY_TO_SYSTEM_EXES
| 2, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
450 expect_LayerValue(bMachine
, file
, NULL
);
452 ok(wrapSetPermLayerState(fileW
, "TEST2", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
453 expect_LayerValue(bMachine
, file
, "TEST2");
455 /* Try adding flags in via layer string */
456 ok(wrapSetPermLayerState(fileW
, "#", 0, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
457 expect_LayerValue(bMachine
, file
, "TEST2");
459 ok(wrapSetPermLayerState(fileW
, "!", 0, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
460 expect_LayerValue(bMachine
, file
, "TEST2");
462 /* Now we prepare the registry with some crap to see how data is validated. */
463 setLayerValue(bMachine
, file
, "!#!# TEST2 TEST2 !# TEST ");
465 ok(wrapSetPermLayerState(fileW
, "TEST1", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
466 expect_LayerValue2(bMachine
, file
, "!# TEST2 TEST2 !# TEST TEST1", g_WinVersion
>= WINVER_WIN8
, "!# TEST1 TEST2 TEST2 !# TEST");
468 /* Removing a duplicate entry will remove all instances of it */
469 ok(wrapSetPermLayerState(fileW
, "TEST2", 0, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
470 expect_LayerValue2(bMachine
, file
, "!# !# TEST TEST1", g_WinVersion
>= WINVER_WIN8
, "!# TEST1 !# TEST");
472 /* Adding a flag cleans other flags (from the start) */
473 ok(wrapSetPermLayerState(fileW
, "", LAYER_APPLY_TO_SYSTEM_EXES
, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
474 expect_LayerValue2(bMachine
, file
, "!# TEST TEST1", g_WinVersion
>= WINVER_WIN8
, "!# TEST1 !# TEST");
476 if(g_WinVersion
< WINVER_WIN8
)
478 ok(wrapSetPermLayerState(fileW
, "$%$%^^", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
479 expect_LayerValue(bMachine
, file
, "!# TEST TEST1 $%$%^^");
482 setLayerValue(bMachine
, file
, "!#!# TEST2 !# TEST ");
483 ok(wrapSetPermLayerState(fileW
, "", LAYER_APPLY_TO_SYSTEM_EXES
, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
484 expect_LayerValue(bMachine
, file
, "! TEST2 !# TEST");
486 /* Tabs are treated as spaces */
487 setLayerValue(bMachine
, file
, "!#!# TEST2 \t TEST2 !# \t TEST ");
488 ok(wrapSetPermLayerState(fileW
, "TEST2", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
489 expect_LayerValue2(bMachine
, file
, "!# !# TEST TEST2", g_WinVersion
>= WINVER_WIN8
, "!# TEST2 !# TEST");
491 /* Newlines are left as-is */
492 setLayerValue(bMachine
, file
, "!#!# TEST2 \n TEST2 !# \r\n TEST ");
493 ok(wrapSetPermLayerState(fileW
, "TEST2", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
494 expect_LayerValue2(bMachine
, file
, "!# \n !# \r\n TEST TEST2", g_WinVersion
>= WINVER_WIN8
, "!# TEST2 \n !# \r\n TEST");
496 /* Whitespace and duplicate flags are eaten from the start */
497 setLayerValue(bMachine
, file
, " !#!# TEST2 \t TEST2 !# \t TEST ");
498 ok(wrapSetPermLayerState(fileW
, "", LAYER_APPLY_TO_SYSTEM_EXES
, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
499 expect_LayerValue(bMachine
, file
, "! TEST2 TEST2 !# TEST");
501 setLayerValue(bMachine
, file
, "!# !# TEST2 !# TEST ");
502 ok(wrapSetPermLayerState(fileW
, "", LAYER_APPLY_TO_SYSTEM_EXES
, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
503 expect_LayerValue(bMachine
, file
, "! TEST2 !# TEST");
505 ok(wrapSetPermLayerState(fileW
, "", LAYER_APPLY_TO_SYSTEM_EXES
, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
506 expect_LayerValue(bMachine
, file
, "! TEST2 !# TEST");
508 ok(wrapSetPermLayerState(fileW
, "", 2, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
509 expect_LayerValue(bMachine
, file
, "TEST2 !# TEST");
511 /* First flags are cleaned, then a layer is removed. */
512 ok(wrapSetPermLayerState(fileW
, "TEST2", 2, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
513 expect_LayerValue(bMachine
, file
, "!# TEST");
515 /* Nothing is changed, still it succeeds. */
516 ok(wrapSetPermLayerState(fileW
, "TEST2", 2, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
517 expect_LayerValue(bMachine
, file
, "# TEST");
519 /* And remove the last bits. */
520 ok(wrapSetPermLayerState(fileW
, "TEST", LAYER_APPLY_TO_SYSTEM_EXES
, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
521 expect_LayerValue(bMachine
, file
, NULL
);
524 static void test_SetPermLayer(void)
526 char file
[MAX_PATH
+ 20], tmp
[MAX_PATH
+ 20];
529 GetTempPathA(MAX_PATH
, tmp
);
530 GetLongPathNameA(tmp
, file
, sizeof(file
));
531 PathAppendA(file
, "test_file.exe");
533 hfile
= CreateFileA(file
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
534 ok(hfile
!= INVALID_HANDLE_VALUE
, "CreateFile failed for '%s'\n", file
);
535 if (hfile
== INVALID_HANDLE_VALUE
)
537 skip("Running these tests is useless without a file present\n");
542 if (setLayerValue(FALSE
, file
, NULL
))
544 test_SdbSetPermLayerKeysLevel(FALSE
, file
);
545 test_SetPermLayerStateLevel(FALSE
, file
);
549 skip("Skipping SetPermLayerStateLevel tests for User, because I cannot prepare the environment\n");
551 if (setLayerValue(TRUE
, file
, NULL
))
553 test_SdbSetPermLayerKeysLevel(TRUE
, file
);
554 test_SetPermLayerStateLevel(TRUE
, file
);
558 skip("Skipping SetPermLayerStateLevel tests for Machine (HKLM), because I cannot prepare the environment\n");
560 ok(DeleteFileA(file
), "DeleteFile failed....\n");
563 static BOOL
create_file(LPCSTR dir
, LPCSTR name
, int filler
, size_t size
)
565 char target
[MAX_PATH
], *tmp
;
567 PathCombineA(target
, dir
, name
);
570 memset(tmp
, filler
, size
);
572 file
= CreateFileA(target
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
573 if(file
== INVALID_HANDLE_VALUE
)
576 WriteFile(file
, tmp
, size
, &size
, NULL
);
582 static BOOL
delete_file(LPCSTR dir
, LPCSTR name
)
584 char target
[MAX_PATH
];
585 PathCombineA(target
, dir
, name
);
586 return DeleteFileA(target
);
589 static char g_FakeDrive
= 0;
591 UINT (WINAPI
*pGetDriveTypeW
)(LPCWSTR target
) = NULL
;
592 UINT WINAPI
mGetDriveTypeW(LPCWSTR target
)
594 UINT uRet
= pGetDriveTypeW(target
);
595 if(g_FakeDrive
&& target
&& (char)*target
== g_FakeDrive
)
601 static PIMAGE_IMPORT_DESCRIPTOR
FindImportDescriptor(PBYTE DllBase
, PCSTR DllName
)
604 PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor
= RtlImageDirectoryEntryToData((HMODULE
)DllBase
, TRUE
, IMAGE_DIRECTORY_ENTRY_IMPORT
, &Size
);
605 while (ImportDescriptor
->Name
&& ImportDescriptor
->OriginalFirstThunk
)
607 PCHAR Name
= (PCHAR
)(DllBase
+ ImportDescriptor
->Name
);
608 if (!lstrcmpiA(Name
, DllName
))
610 return ImportDescriptor
;
617 static BOOL
RedirectIat(PCSTR TargetDllName
, PCSTR DllName
, PCSTR FunctionName
, ULONG_PTR NewFunction
, ULONG_PTR
* OriginalFunction
)
619 PBYTE DllBase
= (PBYTE
)GetModuleHandleA(TargetDllName
);
622 PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor
= FindImportDescriptor(DllBase
, DllName
);
623 if (ImportDescriptor
)
625 // On loaded images, OriginalFirstThunk points to the name / ordinal of the function
626 PIMAGE_THUNK_DATA OriginalThunk
= (PIMAGE_THUNK_DATA
)(DllBase
+ ImportDescriptor
->OriginalFirstThunk
);
627 // FirstThunk points to the resolved address.
628 PIMAGE_THUNK_DATA FirstThunk
= (PIMAGE_THUNK_DATA
)(DllBase
+ ImportDescriptor
->FirstThunk
);
629 while (OriginalThunk
->u1
.AddressOfData
&& FirstThunk
->u1
.Function
)
631 if (!IMAGE_SNAP_BY_ORDINAL32(OriginalThunk
->u1
.AddressOfData
))
633 PIMAGE_IMPORT_BY_NAME ImportName
= (PIMAGE_IMPORT_BY_NAME
)(DllBase
+ OriginalThunk
->u1
.AddressOfData
);
634 if (!lstrcmpiA((PCSTR
)ImportName
->Name
, FunctionName
))
637 VirtualProtect(&FirstThunk
->u1
.Function
, sizeof(ULONG_PTR
), PAGE_EXECUTE_READWRITE
, &dwOld
);
638 *OriginalFunction
= FirstThunk
->u1
.Function
;
639 FirstThunk
->u1
.Function
= NewFunction
;
640 VirtualProtect(&FirstThunk
->u1
.Function
, sizeof(ULONG_PTR
), dwOld
, &dwOld
);
647 skip("Unable to find the Import '%s' from '%s' in %s'\n", FunctionName
, DllName
, TargetDllName
);
651 skip("Unable to find the ImportDescriptor for '%s' in '%s'\n", DllName
, TargetDllName
);
656 skip("Unable to find the loaded module '%s'\n", TargetDllName
);
661 static BOOL
RestoreIat(PCSTR target
, PCSTR DllName
, PCSTR FunctionName
, ULONG_PTR OriginalFunction
)
664 return RedirectIat(target
, DllName
, FunctionName
, OriginalFunction
, &old
);
667 static BOOL
wrapSdbSetPermLayerKeys2(LPCSTR dir
, LPCSTR name
, PCSTR szLayers
, BOOL bMachine
)
669 char szPath
[MAX_PATH
];
670 WCHAR wszPath
[MAX_PATH
], wszLayers
[MAX_LAYER_LENGTH
];
671 PathCombineA(szPath
, dir
, name
);
672 MultiByteToWideChar(CP_ACP
, 0, szLayers
, -1, wszLayers
, MAX_LAYER_LENGTH
);
673 MultiByteToWideChar(CP_ACP
, 0, szPath
, -1, wszPath
, MAX_PATH
);
674 return pSdbSetPermLayerKeys(wszPath
, wszLayers
, bMachine
);
678 BOOL
expect_files(const char* dir
, int num
, ...)
680 char finddir
[MAX_PATH
+ 20];
682 WIN32_FIND_DATAA find
= { 0 };
688 PathCombineA(finddir
, dir
, "*");
689 hFind
= FindFirstFileA(finddir
, &find
);
690 if (hFind
!= INVALID_HANDLE_VALUE
)
695 if (!(find
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
699 file
= va_arg(args
, const char*);
700 cmp
= strcmp(file
, find
.cFileName
);
702 } while (cmp
== 0 && FindNextFileA(hFind
, &find
));
706 return cmp
== 0 && num
== 0;
710 static void test_Sign_Media(void)
712 char workdir
[MAX_PATH
], subdir
[MAX_PATH
], drive
[5] = "Z:";
715 DWORD logical_drives
= GetLogicalDrives();
717 for (drive
[0] = 'D'; drive
[0] <= 'Z'; drive
[0]++)
719 DWORD idx
= 1 << (drive
[0] - 'D' + 3);
720 if (!(logical_drives
& idx
))
722 g_FakeDrive
= drive
[0];
728 skip("Unable to find a free drive\n");
732 ret
= GetTempPathA(MAX_PATH
, workdir
);
733 ok(ret
, "GetTempPathA error: %d\n", GetLastError());
734 PathAppendA(workdir
, "apphelp_test");
736 ret
= CreateDirectoryA(workdir
, NULL
);
737 ok(ret
, "CreateDirectoryA error: %d\n", GetLastError());
739 PathCombineA(subdir
, workdir
, "sub");
740 ret
= CreateDirectoryA(subdir
, NULL
);
741 ok(ret
, "CreateDirectoryA error: %d\n", GetLastError());
743 ret
= DefineDosDeviceA(DDD_NO_BROADCAST_SYSTEM
, drive
, workdir
);
744 ok(ret
, "DefineDosDeviceA error: %d\n", GetLastError());
747 ret
= RedirectIat("apphelp.dll", "kernel32.dll", "GetDriveTypeW", (ULONG_PTR
)mGetDriveTypeW
, (ULONG_PTR
*)&pGetDriveTypeW
);
748 if (g_WinVersion
< WINVER_WIN8
)
749 ok(ret
, "Expected redirect_iat to succeed\n");
752 ok(create_file(workdir
, "test.exe", 'a', 4), "create_file error: %d\n", GetLastError());
754 ok(wrapSdbSetPermLayerKeys2(drive
, "test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
757 expect_LayerValue(0, "SIGN.MEDIA=4 test.exe", "TEST");
758 ok(wrapSdbSetPermLayerKeys2(drive
, "test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
760 ok(create_file(workdir
, "test.txt", 'a', 1), "create_file error: %d\n", GetLastError());
762 if (!expect_files(workdir
, 2, "test.exe", "test.txt"))
764 skip("Skipping test, files are not returned in the expected order by the FS\n");
768 ok(wrapSdbSetPermLayerKeys2(drive
, "test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
770 /* test.exe test.txt */
771 expect_LayerValue(0, "SIGN.MEDIA=9 test.exe", "TEST");
772 ok(wrapSdbSetPermLayerKeys2(drive
, "test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
775 ok(create_file(workdir
, "test.zz", 'a', 0x1000), "create_file error: %d\n", GetLastError());
777 if (!expect_files(workdir
, 3, "test.exe", "test.txt", "test.zz"))
779 skip("Skipping test, files are not returned in the expected order by the FS\n");
783 ok(wrapSdbSetPermLayerKeys2(drive
, "test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
784 /* (((4 << 1) ^ 1) << 1) ^ 0x1000 */
785 /* test.exe test.txt test.zz */
786 expect_LayerValue(0, "SIGN.MEDIA=1012 test.exe", "TEST");
787 ok(wrapSdbSetPermLayerKeys2(drive
, "test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
790 ok(create_file(subdir
, "test.exe", 'a', 0x10203), "create_file error: %d\n", GetLastError());
792 if (!expect_files(subdir
, 1, "test.exe"))
794 skip("Skipping test, files are not returned in the expected order by the FS\n");
798 ok(wrapSdbSetPermLayerKeys2(drive
, "sub\\test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
801 expect_LayerValue(0, "SIGN.MEDIA=10203 sub\\test.exe", "TEST");
802 ok(wrapSdbSetPermLayerKeys2(drive
, "sub\\test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
805 ok(create_file(subdir
, "test.bbb", 'a', 0), "create_file error: %d\n", GetLastError());
807 if (!expect_files(subdir
, 2, "test.bbb", "test.exe"))
809 skip("Skipping test, files are not returned in the expected order by the FS\n");
813 ok(wrapSdbSetPermLayerKeys2(drive
, "sub\\test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
816 expect_LayerValue(0, "SIGN.MEDIA=10203 sub\\test.exe", "TEST");
817 ok(wrapSdbSetPermLayerKeys2(drive
, "sub\\test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
820 ok(create_file(subdir
, "TEST.txt", 'a', 0x30201), "create_file error: %d\n", GetLastError());
822 if (!expect_files(subdir
, 3, "test.bbb", "test.exe", "TEST.txt"))
824 skip("Skipping test, files are not returned in the expected order by the FS\n");
828 ok(wrapSdbSetPermLayerKeys2(drive
, "sub\\test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
829 /* (0x10203 << 1) ^ 0x30201 */
830 /* test.exe TEST.txt */
831 expect_LayerValue(0, "SIGN.MEDIA=10607 sub\\test.exe", "TEST");
832 ok(wrapSdbSetPermLayerKeys2(drive
, "sub\\test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
835 ok(create_file(subdir
, "TEST.aaa", 'a', 0x3a2a1), "create_file error: %d\n", GetLastError());
837 if (!expect_files(subdir
, 4, "TEST.aaa", "test.bbb", "test.exe", "TEST.txt"))
839 skip("Skipping test, files are not returned in the expected order by the FS\n");
843 ok(wrapSdbSetPermLayerKeys2(drive
, "sub\\test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
844 /* (((0x3a2a1 << 1) ^ 0x10203) << 1) ^ 0x30201 */
845 /* TEST.aaa test.exe TEST.txt */
846 expect_LayerValue(0, "SIGN.MEDIA=F8C83 sub\\test.exe", "TEST");
847 ok(wrapSdbSetPermLayerKeys2(drive
, "sub\\test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
850 ret
= RestoreIat("apphelp.dll", "kernel32.dll", "GetDriveTypeW", (ULONG_PTR
)pGetDriveTypeW
);
851 ok(ret
, "Expected restore_iat to succeed\n");
853 ok(delete_file(subdir
, "test.bbb"), "delete_file error: %d\n", GetLastError());
854 ok(delete_file(subdir
, "TEST.aaa"), "delete_file error: %d\n", GetLastError());
855 ok(delete_file(subdir
, "TEST.txt"), "delete_file error: %d\n", GetLastError());
856 ok(delete_file(subdir
, "test.exe"), "delete_file error: %d\n", GetLastError());
857 ok(delete_file(workdir
, "test.zz"), "delete_file error: %d\n", GetLastError());
858 ok(delete_file(workdir
, "test.txt"), "delete_file error: %d\n", GetLastError());
859 ok(delete_file(workdir
, "test.exe"), "delete_file error: %d\n", GetLastError());
861 ret
= DefineDosDeviceA(DDD_REMOVE_DEFINITION
| DDD_NO_BROADCAST_SYSTEM
, drive
, NULL
);
862 ok(ret
, "DefineDosDeviceA error: %d\n", GetLastError());
864 ret
= RemoveDirectoryA(subdir
);
865 ok(ret
, "RemoveDirectoryA error: %d\n", GetLastError());
866 ret
= RemoveDirectoryA(workdir
);
867 ok(ret
, "RemoveDirectoryA error: %d\n", GetLastError());
873 silence_debug_output();
874 /*SetEnvironmentVariable("SHIM_DEBUG_LEVEL", "4");*/
875 hdll
= LoadLibraryA("apphelp.dll");
876 pAllowPermLayer
= (void *)GetProcAddress(hdll
, "AllowPermLayer");
877 pSdbSetPermLayerKeys
= (void *)GetProcAddress(hdll
, "SdbSetPermLayerKeys");
878 pSdbGetPermLayerKeys
= (void *)GetProcAddress(hdll
, "SdbGetPermLayerKeys");
879 pSetPermLayerState
= (void *)GetProcAddress(hdll
, "SetPermLayerState");
880 g_WinVersion
= get_host_winver();
882 if (!pAllowPermLayer
)
884 skip("Skipping tests with AllowPermLayer, function not found\n");
888 test_AllowPermLayer();
891 if (!pSdbSetPermLayerKeys
)
893 skip("Skipping tests with SdbSetPermLayerKeys, function not found\n");
897 if (!pSdbGetPermLayerKeys
)
899 skip("Skipping tests with SdbGetPermLayerKeys, function not found\n");
903 test_SdbGetPermLayerKeys();
906 if (!pSetPermLayerState
)
908 skip("Skipping tests with SetPermLayerState, function not found\n");