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)
9 #define WIN32_NO_STATUS
22 #include "wine/test.h"
23 #include "apitest_iathook.h"
24 #include "apphelp_apitest.h"
27 #define GPLK_MACHINE 2
28 #define MAX_LAYER_LENGTH 256
29 #define LAYER_APPLY_TO_SYSTEM_EXES 1
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
);
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)
43 if (g_QueryFlag
== 0xffffffff)
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;
52 /* Helper function to prepare the registry key with a value. */
53 static BOOL
setLayerValue(BOOL bMachine
, const char* valueName
, const char* value
)
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
)
61 lstatus
= RegSetValueExA(key
, valueName
, 0, REG_SZ
, (const BYTE
*)value
, (DWORD
)strlen(value
)+1);
64 lstatus
= RegDeleteValueA(key
, valueName
);
65 lstatus
= (lstatus
== ERROR_FILE_NOT_FOUND
? ERROR_SUCCESS
: lstatus
);
69 return lstatus
== ERROR_SUCCESS
;
73 static void expect_LayerValue_imp(BOOL bMachine
, const char* valueName
, const char* value
)
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
)
81 char data
[512] = { 0 };
83 DWORD dwDataLen
= sizeof(data
);
84 lstatus
= RegQueryValueExA(key
, valueName
, NULL
, &dwType
, (LPBYTE
)data
, &dwDataLen
);
87 winetest_ok(lstatus
== ERROR_SUCCESS
, "Expected to get a valid value, err: %u\n", lstatus
);
88 if (lstatus
== ERROR_SUCCESS
)
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
);
96 winetest_ok(lstatus
== ERROR_FILE_NOT_FOUND
, "Expected not to find the value %s\n", valueName
);
102 static void expect_LayerValue_imp2(BOOL bMachine
, const char* valueName
, const char* value
, int use_alt
, const char* alt_value
)
104 expect_LayerValue_imp(bMachine
, valueName
, use_alt
? alt_value
: value
);
108 void expect_Sdb_imp(PCSTR path
, DWORD type
, BOOL result
, DWORD lenResult
, PCSTR stringResult
)
110 WCHAR pathW
[MAX_PATH
], buffer
[MAX_LAYER_LENGTH
] = { 0 };
111 char resultBuffer
[MAX_LAYER_LENGTH
] = { 0 };
112 DWORD dwBufSize
= sizeof(buffer
);
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. */
117 MultiByteToWideChar(CP_ACP
, 0, path
, -1, pathW
, MAX_PATH
);
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
);
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
);
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
));
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
);
137 UNICODE_STRING pathNT
;
139 if (RtlDosPathNameToNtPathName_U(pathW
, &pathNT
, NULL
, NULL
))
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");
145 RtlFreeUnicodeString(&pathNT
);
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
158 BOOL
wrapAllowPermLayer(const char* str
)
161 MultiByteToWideChar(CP_ACP
, 0, str
, -1, buf
, 100);
162 return pAllowPermLayer(buf
);
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...)
170 static void test_AllowPermLayer(void)
175 ok(pAllowPermLayer(NULL
) == FALSE
, "Expected AllowPermLayer to fail for NULL\n");
176 if (g_WinVersion
< WINVER_WIN8
)
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");
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
)
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
);
193 static BOOL
wrapSdbSetPermLayerKeys(PCWSTR wszPath
, PCSTR szLayers
, BOOL bMachine
)
195 WCHAR wszLayers
[MAX_LAYER_LENGTH
];
196 MultiByteToWideChar(CP_ACP
, 0, szLayers
, -1, wszLayers
, MAX_LAYER_LENGTH
);
197 return pSdbSetPermLayerKeys(wszPath
, wszLayers
, bMachine
);
200 static void test_SdbSetPermLayerKeysLevel(BOOL bMachine
, const char* file
)
202 WCHAR fileW
[MAX_PATH
+20];
203 WCHAR emptyString
[1] = { 0 };
205 MultiByteToWideChar(CP_ACP
, 0, file
, -1, fileW
, MAX_PATH
+20);
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");
215 ok(wrapSdbSetPermLayerKeys(fileW
, "TEST1", bMachine
), "Expected SdbSetPermLayerKeys to succeed\n");
216 expect_LayerValue(bMachine
, file
, "TEST1");
218 ok(wrapSdbSetPermLayerKeys(fileW
, "TEST1 TEST2", bMachine
), "Expected SdbSetPermLayerKeys to succeed\n");
219 expect_LayerValue(bMachine
, file
, "TEST1 TEST2");
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");
225 ok(wrapSdbSetPermLayerKeys(fileW
, "!#$% TEST1 TEST2", bMachine
), "Expected SdbSetPermLayerKeys to succeed\n");
226 expect_LayerValue(bMachine
, file
, "!#$% TEST1 TEST2");
228 ok(pSdbSetPermLayerKeys(fileW
, NULL
, bMachine
) == TRUE
, "Expected SdbSetPermLayerKeys to succeed\n");
229 expect_LayerValue(bMachine
, file
, NULL
);
231 ok(wrapSdbSetPermLayerKeys(fileW
, " ", bMachine
), "Expected SdbSetPermLayerKeys to succeed\n");
232 expect_LayerValue(bMachine
, file
, " ");
234 ok(pSdbSetPermLayerKeys(fileW
, NULL
, bMachine
) == TRUE
, "Expected SdbSetPermLayerKeys to fail\n");
235 expect_LayerValue(bMachine
, file
, NULL
);
238 static void test_SdbGetPermLayerKeys(void)
240 WCHAR pathW
[MAX_PATH
], buffer
[MAX_LAYER_LENGTH
] = { 0 };
241 char file
[MAX_PATH
+ 20], tmp
[MAX_PATH
+ 20];
242 BOOL bUser
, bMachine
;
244 DWORD dwBufSize
= sizeof(buffer
);
246 GetTempPathA(MAX_PATH
, tmp
);
247 GetLongPathNameA(tmp
, file
, sizeof(file
));
248 PathCombineA(tmp
, file
, "notexist.exe");
249 PathAppendA(file
, "test_file.exe");
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");
257 skip("Cannot do any tests if I cannot set some values\n");
260 bMachine
= setLayerValue(TRUE
, file
, "WINXPSP3 WINXPSP2");
263 expect_LayerValue(TRUE
, file
, "WINXPSP3 WINXPSP2");
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
)
271 skip("Running these tests is useless without a file present\n");
276 MultiByteToWideChar(CP_ACP
, 0, file
, -1, pathW
, MAX_PATH
);
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
);
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");
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");
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");
311 skip("Skipping tests for HKLM, cannot alter the registry\n");
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, "");
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 ");
325 ok(DeleteFileA(file
), "DeleteFile failed....\n");
326 setLayerValue(FALSE
, file
, NULL
);
327 setLayerValue(TRUE
, file
, NULL
);
331 static BOOL
wrapSetPermLayerState(PCWSTR wszPath
, PCSTR szLayer
, DWORD dwFlags
, BOOL bMachine
, BOOL bEnable
)
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
);
338 static void test_SetPermLayerStateLevel(BOOL bMachine
, const char* file
)
340 WCHAR fileW
[MAX_PATH
+20];
341 WCHAR emptyString
[1] = { 0 };
344 MultiByteToWideChar(CP_ACP
, 0, file
, -1, fileW
, MAX_PATH
+20);
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
);
350 ok(pSetPermLayerState(fileW
, NULL
, 0, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
351 expect_LayerValue(bMachine
, file
, NULL
);
353 ok(wrapSetPermLayerState(fileW
, "", 0, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
354 expect_LayerValue(bMachine
, file
, NULL
);
356 ok(wrapSetPermLayerState(fileW
, "", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
357 expect_LayerValue(bMachine
, file
, NULL
);
359 ok(wrapSetPermLayerState(NULL
, NULL
, 0, bMachine
, 0) == FALSE
, "Expected SetPermLayerState to fail\n");
360 expect_LayerValue(bMachine
, NULL
, NULL
);
362 ok(wrapSetPermLayerState(NULL
, NULL
, 0, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
363 expect_LayerValue(bMachine
, NULL
, NULL
);
365 ok(wrapSetPermLayerState(emptyString
, "", 0, bMachine
, 0) == FALSE
, "Expected SetPermLayerState to fail\n");
366 expect_LayerValue(bMachine
, NULL
, NULL
);
368 ok(wrapSetPermLayerState(emptyString
, "", 0, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
369 expect_LayerValue(bMachine
, NULL
, NULL
);
371 ok(wrapSetPermLayerState(emptyString
, "TEST", 0, bMachine
, 0) == FALSE
, "Expected SetPermLayerState to fail\n");
372 expect_LayerValue(bMachine
, NULL
, NULL
);
374 if (g_WinVersion
<= WINVER_WIN8
)
376 ok(wrapSetPermLayerState(emptyString
, "TEST", 0, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
377 expect_LayerValue(bMachine
, NULL
, NULL
);
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
);
386 ok(wrapSetPermLayerState(fileW
, "TEST", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
387 expect_LayerValue(bMachine
, file
, "TEST");
389 ok(wrapSetPermLayerState(fileW
, "", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
390 expect_LayerValue(bMachine
, file
, "TEST");
392 ok(wrapSetPermLayerState(fileW
, "test", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
393 expect_LayerValue(bMachine
, file
, "test");
395 ok(wrapSetPermLayerState(fileW
, "TEST", 0, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
396 expect_LayerValue(bMachine
, file
, NULL
);
398 ok(wrapSetPermLayerState(fileW
, "TEST", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
399 expect_LayerValue(bMachine
, file
, "TEST");
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");
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");
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");
410 ok(wrapSetPermLayerState(fileW
, "TEST", 0, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
411 expect_LayerValue(bMachine
, file
, "TEST2");
413 ok(wrapSetPermLayerState(fileW
, "TEST2", 0, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
414 expect_LayerValue(bMachine
, file
, NULL
);
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
)
420 ok(wrapSetPermLayerState(fileW
, "TEST", (1<<dwFlag
), bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail on 0x%x\n", (1<<dwFlag
));
422 expect_LayerValue(bMachine
, file
, NULL
);
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");
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");
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");
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");
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");
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");
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");
447 ok(wrapSetPermLayerState(fileW
, "TEST3", LAYER_APPLY_TO_SYSTEM_EXES
, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
448 expect_LayerValue(bMachine
, file
, "! TEST");
450 ok(wrapSetPermLayerState(fileW
, "TEST", 2, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
451 expect_LayerValue(bMachine
, file
, NULL
);
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
);
457 ok(wrapSetPermLayerState(fileW
, "TEST2", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
458 expect_LayerValue(bMachine
, file
, "TEST2");
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");
464 ok(wrapSetPermLayerState(fileW
, "!", 0, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
465 expect_LayerValue(bMachine
, file
, "TEST2");
467 /* Now we prepare the registry with some crap to see how data is validated. */
468 setLayerValue(bMachine
, file
, "!#!# TEST2 TEST2 !# TEST ");
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");
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");
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");
481 if(g_WinVersion
< WINVER_WIN8
)
483 ok(wrapSetPermLayerState(fileW
, "$%$%^^", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
484 expect_LayerValue(bMachine
, file
, "!# TEST TEST1 $%$%^^");
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");
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");
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");
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");
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");
510 ok(wrapSetPermLayerState(fileW
, "", LAYER_APPLY_TO_SYSTEM_EXES
, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
511 expect_LayerValue(bMachine
, file
, "! TEST2 !# TEST");
513 ok(wrapSetPermLayerState(fileW
, "", 2, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
514 expect_LayerValue(bMachine
, file
, "TEST2 !# TEST");
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");
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");
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
);
529 static void test_SetPermLayer(void)
531 char file
[MAX_PATH
+ 20], tmp
[MAX_PATH
+ 20];
534 GetTempPathA(MAX_PATH
, tmp
);
535 GetLongPathNameA(tmp
, file
, sizeof(file
));
536 PathAppendA(file
, "test_file.exe");
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
)
542 skip("Running these tests is useless without a file present\n");
547 if (setLayerValue(FALSE
, file
, NULL
))
549 test_SdbSetPermLayerKeysLevel(FALSE
, file
);
550 test_SetPermLayerStateLevel(FALSE
, file
);
554 skip("Skipping SetPermLayerStateLevel tests for User, because I cannot prepare the environment\n");
556 if (setLayerValue(TRUE
, file
, NULL
))
558 test_SdbSetPermLayerKeysLevel(TRUE
, file
);
559 test_SetPermLayerStateLevel(TRUE
, file
);
563 skip("Skipping SetPermLayerStateLevel tests for Machine (HKLM), because I cannot prepare the environment\n");
565 ok(DeleteFileA(file
), "DeleteFile failed....\n");
568 static BOOL
create_file(LPCSTR dir
, LPCSTR name
, int filler
, DWORD size
)
570 char target
[MAX_PATH
], *tmp
;
572 PathCombineA(target
, dir
, name
);
575 memset(tmp
, filler
, size
);
577 file
= CreateFileA(target
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
578 if(file
== INVALID_HANDLE_VALUE
)
581 WriteFile(file
, tmp
, size
, &size
, NULL
);
587 static BOOL
delete_file(LPCSTR dir
, LPCSTR name
)
589 char target
[MAX_PATH
];
590 PathCombineA(target
, dir
, name
);
591 return DeleteFileA(target
);
594 static char g_FakeDrive
= 0;
596 UINT (WINAPI
*pGetDriveTypeW
)(LPCWSTR target
) = NULL
;
597 UINT WINAPI
mGetDriveTypeW(LPCWSTR target
)
599 UINT uRet
= pGetDriveTypeW(target
);
600 if(g_FakeDrive
&& target
&& (char)*target
== g_FakeDrive
)
605 static BOOL
wrapSdbSetPermLayerKeys2(LPCSTR dir
, LPCSTR name
, PCSTR szLayers
, BOOL bMachine
)
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
);
616 BOOL
expect_files(const char* dir
, int num
, ...)
618 char finddir
[MAX_PATH
+ 20];
620 WIN32_FIND_DATAA find
= { 0 };
626 PathCombineA(finddir
, dir
, "*");
627 hFind
= FindFirstFileA(finddir
, &find
);
628 if (hFind
!= INVALID_HANDLE_VALUE
)
633 if (!(find
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
637 file
= va_arg(args
, const char*);
638 cmp
= strcmp(file
, find
.cFileName
);
640 } while (cmp
== 0 && FindNextFileA(hFind
, &find
));
644 return cmp
== 0 && num
== 0;
648 static void test_Sign_Media(void)
650 char workdir
[MAX_PATH
], subdir
[MAX_PATH
], drive
[5] = "Z:";
653 DWORD logical_drives
= GetLogicalDrives();
655 for (drive
[0] = 'D'; drive
[0] <= 'Z'; drive
[0]++)
657 DWORD idx
= 1 << (drive
[0] - 'D' + 3);
658 if (!(logical_drives
& idx
))
660 g_FakeDrive
= drive
[0];
666 skip("Unable to find a free drive\n");
670 ret
= GetTempPathA(MAX_PATH
, workdir
);
671 ok(ret
, "GetTempPathA error: %d\n", GetLastError());
672 PathAppendA(workdir
, "apphelp_test");
674 ret
= CreateDirectoryA(workdir
, NULL
);
675 ok(ret
, "CreateDirectoryA error: %d\n", GetLastError());
677 PathCombineA(subdir
, workdir
, "sub");
678 ret
= CreateDirectoryA(subdir
, NULL
);
679 ok(ret
, "CreateDirectoryA error: %d\n", GetLastError());
681 ret
= DefineDosDeviceA(DDD_NO_BROADCAST_SYSTEM
, drive
, workdir
);
682 ok(ret
, "DefineDosDeviceA error: %d\n", GetLastError());
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");
691 ok(create_file(workdir
, "test.exe", 'a', 4), "create_file error: %d\n", GetLastError());
693 ok(wrapSdbSetPermLayerKeys2(drive
, "test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
696 expect_LayerValue(0, "SIGN.MEDIA=4 test.exe", "TEST");
697 ok(wrapSdbSetPermLayerKeys2(drive
, "test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
699 ok(create_file(workdir
, "test.txt", 'a', 1), "create_file error: %d\n", GetLastError());
701 if (!expect_files(workdir
, 2, "test.exe", "test.txt"))
703 skip("Skipping test, files are not returned in the expected order by the FS\n");
707 ok(wrapSdbSetPermLayerKeys2(drive
, "test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
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");
714 ok(create_file(workdir
, "test.zz", 'a', 0x1000), "create_file error: %d\n", GetLastError());
716 if (!expect_files(workdir
, 3, "test.exe", "test.txt", "test.zz"))
718 skip("Skipping test, files are not returned in the expected order by the FS\n");
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");
729 ok(create_file(subdir
, "test.exe", 'a', 0x10203), "create_file error: %d\n", GetLastError());
731 if (!expect_files(subdir
, 1, "test.exe"))
733 skip("Skipping test, files are not returned in the expected order by the FS\n");
737 ok(wrapSdbSetPermLayerKeys2(drive
, "sub\\test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
740 expect_LayerValue(0, "SIGN.MEDIA=10203 sub\\test.exe", "TEST");
741 ok(wrapSdbSetPermLayerKeys2(drive
, "sub\\test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
744 ok(create_file(subdir
, "test.bbb", 'a', 0), "create_file error: %d\n", GetLastError());
746 if (!expect_files(subdir
, 2, "test.bbb", "test.exe"))
748 skip("Skipping test, files are not returned in the expected order by the FS\n");
752 ok(wrapSdbSetPermLayerKeys2(drive
, "sub\\test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
755 expect_LayerValue(0, "SIGN.MEDIA=10203 sub\\test.exe", "TEST");
756 ok(wrapSdbSetPermLayerKeys2(drive
, "sub\\test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
759 ok(create_file(subdir
, "TEST.txt", 'a', 0x30201), "create_file error: %d\n", GetLastError());
761 if (!expect_files(subdir
, 3, "test.bbb", "test.exe", "TEST.txt"))
763 skip("Skipping test, files are not returned in the expected order by the FS\n");
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");
774 ok(create_file(subdir
, "TEST.aaa", 'a', 0x3a2a1), "create_file error: %d\n", GetLastError());
776 if (!expect_files(subdir
, 4, "TEST.aaa", "test.bbb", "test.exe", "TEST.txt"))
778 skip("Skipping test, files are not returned in the expected order by the FS\n");
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");
789 ret
= RestoreIat(GetModuleHandleA("apphelp.dll"), "kernel32.dll", "GetDriveTypeW", (ULONG_PTR
)pGetDriveTypeW
);
790 ok(ret
, "Expected restore_iat to succeed\n");
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());
800 ret
= DefineDosDeviceA(DDD_REMOVE_DEFINITION
| DDD_NO_BROADCAST_SYSTEM
, drive
, NULL
);
801 ok(ret
, "DefineDosDeviceA error: %d\n", GetLastError());
803 ret
= RemoveDirectoryA(subdir
);
804 ok(ret
, "RemoveDirectoryA error: %d\n", GetLastError());
805 ret
= RemoveDirectoryA(workdir
);
806 ok(ret
, "RemoveDirectoryA error: %d\n", GetLastError());
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();
821 if (!pAllowPermLayer
)
823 skip("Skipping tests with AllowPermLayer, function not found\n");
827 test_AllowPermLayer();
830 if (!pSdbSetPermLayerKeys
)
832 skip("Skipping tests with SdbSetPermLayerKeys, function not found\n");
836 if (!pSdbGetPermLayerKeys
)
838 skip("Skipping tests with SdbGetPermLayerKeys, function not found\n");
842 test_SdbGetPermLayerKeys();
845 if (!pSetPermLayerState
)
847 skip("Skipping tests with SetPermLayerState, function not found\n");