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
21 #include "wine/test.h"
22 #include "apitest_iathook.h"
23 #include "apphelp_apitest.h"
26 #define GPLK_MACHINE 2
27 #define MAX_LAYER_LENGTH 256
28 #define LAYER_APPLY_TO_SYSTEM_EXES 1
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
);
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)
42 if (g_QueryFlag
== 0xffffffff)
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;
51 /* Helper function to prepare the registry key with a value. */
52 static BOOL
setLayerValue(BOOL bMachine
, const char* valueName
, const char* value
)
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
)
60 lstatus
= RegSetValueExA(key
, valueName
, 0, REG_SZ
, (const BYTE
*)value
, (DWORD
)strlen(value
)+1);
63 lstatus
= RegDeleteValueA(key
, valueName
);
64 lstatus
= (lstatus
== ERROR_FILE_NOT_FOUND
? ERROR_SUCCESS
: lstatus
);
68 return lstatus
== ERROR_SUCCESS
;
72 static void expect_LayerValue_imp(BOOL bMachine
, const char* valueName
, const char* value
)
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
)
80 char data
[512] = { 0 };
82 DWORD dwDataLen
= sizeof(data
);
83 lstatus
= RegQueryValueExA(key
, valueName
, NULL
, &dwType
, (LPBYTE
)data
, &dwDataLen
);
86 winetest_ok(lstatus
== ERROR_SUCCESS
, "Expected to get a valid value, err: %u\n", lstatus
);
87 if (lstatus
== ERROR_SUCCESS
)
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
);
95 winetest_ok(lstatus
== ERROR_FILE_NOT_FOUND
, "Expected not to find the value %s\n", valueName
);
101 static void expect_LayerValue_imp2(BOOL bMachine
, const char* valueName
, const char* value
, int use_alt
, const char* alt_value
)
103 expect_LayerValue_imp(bMachine
, valueName
, use_alt
? alt_value
: value
);
107 void expect_Sdb_imp(PCSTR path
, DWORD type
, BOOL result
, DWORD lenResult
, PCSTR stringResult
)
109 WCHAR pathW
[MAX_PATH
], buffer
[MAX_LAYER_LENGTH
] = { 0 };
110 char resultBuffer
[MAX_LAYER_LENGTH
] = { 0 };
111 DWORD dwBufSize
= sizeof(buffer
);
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. */
116 MultiByteToWideChar(CP_ACP
, 0, path
, -1, pathW
, MAX_PATH
);
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
);
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
);
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
));
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
);
136 UNICODE_STRING pathNT
;
138 if (RtlDosPathNameToNtPathName_U(pathW
, &pathNT
, NULL
, NULL
))
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");
144 RtlFreeUnicodeString(&pathNT
);
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
157 BOOL
wrapAllowPermLayer(const char* str
)
160 MultiByteToWideChar(CP_ACP
, 0, str
, -1, buf
, 100);
161 return pAllowPermLayer(buf
);
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...)
169 static void test_AllowPermLayer(void)
174 ok(pAllowPermLayer(NULL
) == FALSE
, "Expected AllowPermLayer to fail for NULL\n");
175 if (g_WinVersion
< WINVER_WIN8
)
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");
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
)
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
);
192 static BOOL
wrapSdbSetPermLayerKeys(PCWSTR wszPath
, PCSTR szLayers
, BOOL bMachine
)
194 WCHAR wszLayers
[MAX_LAYER_LENGTH
];
195 MultiByteToWideChar(CP_ACP
, 0, szLayers
, -1, wszLayers
, MAX_LAYER_LENGTH
);
196 return pSdbSetPermLayerKeys(wszPath
, wszLayers
, bMachine
);
199 static void test_SdbSetPermLayerKeysLevel(BOOL bMachine
, const char* file
)
201 WCHAR fileW
[MAX_PATH
+20];
202 WCHAR emptyString
[1] = { 0 };
204 MultiByteToWideChar(CP_ACP
, 0, file
, -1, fileW
, MAX_PATH
+20);
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");
214 ok(wrapSdbSetPermLayerKeys(fileW
, "TEST1", bMachine
), "Expected SdbSetPermLayerKeys to succeed\n");
215 expect_LayerValue(bMachine
, file
, "TEST1");
217 ok(wrapSdbSetPermLayerKeys(fileW
, "TEST1 TEST2", bMachine
), "Expected SdbSetPermLayerKeys to succeed\n");
218 expect_LayerValue(bMachine
, file
, "TEST1 TEST2");
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");
224 ok(wrapSdbSetPermLayerKeys(fileW
, "!#$% TEST1 TEST2", bMachine
), "Expected SdbSetPermLayerKeys to succeed\n");
225 expect_LayerValue(bMachine
, file
, "!#$% TEST1 TEST2");
227 ok(pSdbSetPermLayerKeys(fileW
, NULL
, bMachine
) == TRUE
, "Expected SdbSetPermLayerKeys to succeed\n");
228 expect_LayerValue(bMachine
, file
, NULL
);
230 ok(wrapSdbSetPermLayerKeys(fileW
, " ", bMachine
), "Expected SdbSetPermLayerKeys to succeed\n");
231 expect_LayerValue(bMachine
, file
, " ");
233 ok(pSdbSetPermLayerKeys(fileW
, NULL
, bMachine
) == TRUE
, "Expected SdbSetPermLayerKeys to fail\n");
234 expect_LayerValue(bMachine
, file
, NULL
);
237 static void test_SdbGetPermLayerKeys(void)
239 WCHAR pathW
[MAX_PATH
], buffer
[MAX_LAYER_LENGTH
] = { 0 };
240 char file
[MAX_PATH
+ 20], tmp
[MAX_PATH
+ 20];
241 BOOL bUser
, bMachine
;
243 DWORD dwBufSize
= sizeof(buffer
);
245 GetTempPathA(MAX_PATH
, tmp
);
246 GetLongPathNameA(tmp
, file
, sizeof(file
));
247 PathCombineA(tmp
, file
, "notexist.exe");
248 PathAppendA(file
, "test_file.exe");
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");
256 skip("Cannot do any tests if I cannot set some values\n");
259 bMachine
= setLayerValue(TRUE
, file
, "WINXPSP3 WINXPSP2");
262 expect_LayerValue(TRUE
, file
, "WINXPSP3 WINXPSP2");
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
)
270 skip("Running these tests is useless without a file present\n");
275 MultiByteToWideChar(CP_ACP
, 0, file
, -1, pathW
, MAX_PATH
);
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
);
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");
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");
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");
310 skip("Skipping tests for HKLM, cannot alter the registry\n");
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, "");
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 ");
324 ok(DeleteFileA(file
), "DeleteFile failed....\n");
325 setLayerValue(FALSE
, file
, NULL
);
326 setLayerValue(TRUE
, file
, NULL
);
330 static BOOL
wrapSetPermLayerState(PCWSTR wszPath
, PCSTR szLayer
, DWORD dwFlags
, BOOL bMachine
, BOOL bEnable
)
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
);
337 static void test_SetPermLayerStateLevel(BOOL bMachine
, const char* file
)
339 WCHAR fileW
[MAX_PATH
+20];
340 WCHAR emptyString
[1] = { 0 };
343 MultiByteToWideChar(CP_ACP
, 0, file
, -1, fileW
, MAX_PATH
+20);
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
);
349 ok(pSetPermLayerState(fileW
, NULL
, 0, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
350 expect_LayerValue(bMachine
, file
, NULL
);
352 ok(wrapSetPermLayerState(fileW
, "", 0, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
353 expect_LayerValue(bMachine
, file
, NULL
);
355 ok(wrapSetPermLayerState(fileW
, "", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
356 expect_LayerValue(bMachine
, file
, NULL
);
358 ok(wrapSetPermLayerState(NULL
, NULL
, 0, bMachine
, 0) == FALSE
, "Expected SetPermLayerState to fail\n");
359 expect_LayerValue(bMachine
, NULL
, NULL
);
361 ok(wrapSetPermLayerState(NULL
, NULL
, 0, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
362 expect_LayerValue(bMachine
, NULL
, NULL
);
364 ok(wrapSetPermLayerState(emptyString
, "", 0, bMachine
, 0) == FALSE
, "Expected SetPermLayerState to fail\n");
365 expect_LayerValue(bMachine
, NULL
, NULL
);
367 ok(wrapSetPermLayerState(emptyString
, "", 0, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
368 expect_LayerValue(bMachine
, NULL
, NULL
);
370 ok(wrapSetPermLayerState(emptyString
, "TEST", 0, bMachine
, 0) == FALSE
, "Expected SetPermLayerState to fail\n");
371 expect_LayerValue(bMachine
, NULL
, NULL
);
373 if (g_WinVersion
<= WINVER_WIN8
)
375 ok(wrapSetPermLayerState(emptyString
, "TEST", 0, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
376 expect_LayerValue(bMachine
, NULL
, NULL
);
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
);
385 ok(wrapSetPermLayerState(fileW
, "TEST", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
386 expect_LayerValue(bMachine
, file
, "TEST");
388 ok(wrapSetPermLayerState(fileW
, "", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
389 expect_LayerValue(bMachine
, file
, "TEST");
391 ok(wrapSetPermLayerState(fileW
, "test", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
392 expect_LayerValue(bMachine
, file
, "test");
394 ok(wrapSetPermLayerState(fileW
, "TEST", 0, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
395 expect_LayerValue(bMachine
, file
, NULL
);
397 ok(wrapSetPermLayerState(fileW
, "TEST", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
398 expect_LayerValue(bMachine
, file
, "TEST");
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");
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");
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");
409 ok(wrapSetPermLayerState(fileW
, "TEST", 0, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
410 expect_LayerValue(bMachine
, file
, "TEST2");
412 ok(wrapSetPermLayerState(fileW
, "TEST2", 0, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
413 expect_LayerValue(bMachine
, file
, NULL
);
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
)
419 ok(wrapSetPermLayerState(fileW
, "TEST", (1<<dwFlag
), bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail on 0x%x\n", (1<<dwFlag
));
421 expect_LayerValue(bMachine
, file
, NULL
);
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");
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");
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");
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");
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");
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");
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");
446 ok(wrapSetPermLayerState(fileW
, "TEST3", LAYER_APPLY_TO_SYSTEM_EXES
, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
447 expect_LayerValue(bMachine
, file
, "! TEST");
449 ok(wrapSetPermLayerState(fileW
, "TEST", 2, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
450 expect_LayerValue(bMachine
, file
, NULL
);
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
);
456 ok(wrapSetPermLayerState(fileW
, "TEST2", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
457 expect_LayerValue(bMachine
, file
, "TEST2");
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");
463 ok(wrapSetPermLayerState(fileW
, "!", 0, bMachine
, 1) == FALSE
, "Expected SetPermLayerState to fail\n");
464 expect_LayerValue(bMachine
, file
, "TEST2");
466 /* Now we prepare the registry with some crap to see how data is validated. */
467 setLayerValue(bMachine
, file
, "!#!# TEST2 TEST2 !# TEST ");
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");
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");
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");
480 if(g_WinVersion
< WINVER_WIN8
)
482 ok(wrapSetPermLayerState(fileW
, "$%$%^^", 0, bMachine
, 1) == TRUE
, "Expected SetPermLayerState to succeed\n");
483 expect_LayerValue(bMachine
, file
, "!# TEST TEST1 $%$%^^");
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");
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");
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");
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");
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");
509 ok(wrapSetPermLayerState(fileW
, "", LAYER_APPLY_TO_SYSTEM_EXES
, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
510 expect_LayerValue(bMachine
, file
, "! TEST2 !# TEST");
512 ok(wrapSetPermLayerState(fileW
, "", 2, bMachine
, 0) == TRUE
, "Expected SetPermLayerState to succeed\n");
513 expect_LayerValue(bMachine
, file
, "TEST2 !# TEST");
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");
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");
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
);
528 static void test_SetPermLayer(void)
530 char file
[MAX_PATH
+ 20], tmp
[MAX_PATH
+ 20];
533 GetTempPathA(MAX_PATH
, tmp
);
534 GetLongPathNameA(tmp
, file
, sizeof(file
));
535 PathAppendA(file
, "test_file.exe");
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
)
541 skip("Running these tests is useless without a file present\n");
546 if (setLayerValue(FALSE
, file
, NULL
))
548 test_SdbSetPermLayerKeysLevel(FALSE
, file
);
549 test_SetPermLayerStateLevel(FALSE
, file
);
553 skip("Skipping SetPermLayerStateLevel tests for User, because I cannot prepare the environment\n");
555 if (setLayerValue(TRUE
, file
, NULL
))
557 test_SdbSetPermLayerKeysLevel(TRUE
, file
);
558 test_SetPermLayerStateLevel(TRUE
, file
);
562 skip("Skipping SetPermLayerStateLevel tests for Machine (HKLM), because I cannot prepare the environment\n");
564 ok(DeleteFileA(file
), "DeleteFile failed....\n");
567 static BOOL
create_file(LPCSTR dir
, LPCSTR name
, int filler
, DWORD size
)
569 char target
[MAX_PATH
], *tmp
;
571 PathCombineA(target
, dir
, name
);
574 memset(tmp
, filler
, size
);
576 file
= CreateFileA(target
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
577 if(file
== INVALID_HANDLE_VALUE
)
580 WriteFile(file
, tmp
, size
, &size
, NULL
);
586 static BOOL
delete_file(LPCSTR dir
, LPCSTR name
)
588 char target
[MAX_PATH
];
589 PathCombineA(target
, dir
, name
);
590 return DeleteFileA(target
);
593 static char g_FakeDrive
= 0;
595 UINT (WINAPI
*pGetDriveTypeW
)(LPCWSTR target
) = NULL
;
596 UINT WINAPI
mGetDriveTypeW(LPCWSTR target
)
598 UINT uRet
= pGetDriveTypeW(target
);
599 if(g_FakeDrive
&& target
&& (char)*target
== g_FakeDrive
)
604 static BOOL
wrapSdbSetPermLayerKeys2(LPCSTR dir
, LPCSTR name
, PCSTR szLayers
, BOOL bMachine
)
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
);
615 BOOL
expect_files(const char* dir
, int num
, ...)
617 char finddir
[MAX_PATH
+ 20];
619 WIN32_FIND_DATAA find
= { 0 };
625 PathCombineA(finddir
, dir
, "*");
626 hFind
= FindFirstFileA(finddir
, &find
);
627 if (hFind
!= INVALID_HANDLE_VALUE
)
632 if (!(find
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
))
636 file
= va_arg(args
, const char*);
637 cmp
= strcmp(file
, find
.cFileName
);
639 } while (cmp
== 0 && FindNextFileA(hFind
, &find
));
643 return cmp
== 0 && num
== 0;
647 static void test_Sign_Media(void)
649 char workdir
[MAX_PATH
], subdir
[MAX_PATH
], drive
[5] = "Z:";
652 DWORD logical_drives
= GetLogicalDrives();
654 for (drive
[0] = 'D'; drive
[0] <= 'Z'; drive
[0]++)
656 DWORD idx
= 1 << (drive
[0] - 'D' + 3);
657 if (!(logical_drives
& idx
))
659 g_FakeDrive
= drive
[0];
665 skip("Unable to find a free drive\n");
669 ret
= GetTempPathA(MAX_PATH
, workdir
);
670 ok(ret
, "GetTempPathA error: %d\n", GetLastError());
671 PathAppendA(workdir
, "apphelp_test");
673 ret
= CreateDirectoryA(workdir
, NULL
);
674 ok(ret
, "CreateDirectoryA error: %d\n", GetLastError());
676 PathCombineA(subdir
, workdir
, "sub");
677 ret
= CreateDirectoryA(subdir
, NULL
);
678 ok(ret
, "CreateDirectoryA error: %d\n", GetLastError());
680 ret
= DefineDosDeviceA(DDD_NO_BROADCAST_SYSTEM
, drive
, workdir
);
681 ok(ret
, "DefineDosDeviceA error: %d\n", GetLastError());
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");
690 ok(create_file(workdir
, "test.exe", 'a', 4), "create_file error: %d\n", GetLastError());
692 ok(wrapSdbSetPermLayerKeys2(drive
, "test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
695 expect_LayerValue(0, "SIGN.MEDIA=4 test.exe", "TEST");
696 ok(wrapSdbSetPermLayerKeys2(drive
, "test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
698 ok(create_file(workdir
, "test.txt", 'a', 1), "create_file error: %d\n", GetLastError());
700 if (!expect_files(workdir
, 2, "test.exe", "test.txt"))
702 skip("Skipping test, files are not returned in the expected order by the FS\n");
706 ok(wrapSdbSetPermLayerKeys2(drive
, "test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
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");
713 ok(create_file(workdir
, "test.zz", 'a', 0x1000), "create_file error: %d\n", GetLastError());
715 if (!expect_files(workdir
, 3, "test.exe", "test.txt", "test.zz"))
717 skip("Skipping test, files are not returned in the expected order by the FS\n");
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");
728 ok(create_file(subdir
, "test.exe", 'a', 0x10203), "create_file error: %d\n", GetLastError());
730 if (!expect_files(subdir
, 1, "test.exe"))
732 skip("Skipping test, files are not returned in the expected order by the FS\n");
736 ok(wrapSdbSetPermLayerKeys2(drive
, "sub\\test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
739 expect_LayerValue(0, "SIGN.MEDIA=10203 sub\\test.exe", "TEST");
740 ok(wrapSdbSetPermLayerKeys2(drive
, "sub\\test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
743 ok(create_file(subdir
, "test.bbb", 'a', 0), "create_file error: %d\n", GetLastError());
745 if (!expect_files(subdir
, 2, "test.bbb", "test.exe"))
747 skip("Skipping test, files are not returned in the expected order by the FS\n");
751 ok(wrapSdbSetPermLayerKeys2(drive
, "sub\\test.exe", "TEST", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
754 expect_LayerValue(0, "SIGN.MEDIA=10203 sub\\test.exe", "TEST");
755 ok(wrapSdbSetPermLayerKeys2(drive
, "sub\\test.exe", "", 0), "Expected wrapSdbSetPermLayerKeys2 to succeed\n");
758 ok(create_file(subdir
, "TEST.txt", 'a', 0x30201), "create_file error: %d\n", GetLastError());
760 if (!expect_files(subdir
, 3, "test.bbb", "test.exe", "TEST.txt"))
762 skip("Skipping test, files are not returned in the expected order by the FS\n");
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");
773 ok(create_file(subdir
, "TEST.aaa", 'a', 0x3a2a1), "create_file error: %d\n", GetLastError());
775 if (!expect_files(subdir
, 4, "TEST.aaa", "test.bbb", "test.exe", "TEST.txt"))
777 skip("Skipping test, files are not returned in the expected order by the FS\n");
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");
788 ret
= RestoreIat(GetModuleHandleA("apphelp.dll"), "kernel32.dll", "GetDriveTypeW", (ULONG_PTR
)pGetDriveTypeW
);
789 ok(ret
, "Expected restore_iat to succeed\n");
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());
799 ret
= DefineDosDeviceA(DDD_REMOVE_DEFINITION
| DDD_NO_BROADCAST_SYSTEM
, drive
, NULL
);
800 ok(ret
, "DefineDosDeviceA error: %d\n", GetLastError());
802 ret
= RemoveDirectoryA(subdir
);
803 ok(ret
, "RemoveDirectoryA error: %d\n", GetLastError());
804 ret
= RemoveDirectoryA(workdir
);
805 ok(ret
, "RemoveDirectoryA error: %d\n", GetLastError());
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();
820 if (!pAllowPermLayer
)
822 skip("Skipping tests with AllowPermLayer, function not found\n");
826 test_AllowPermLayer();
829 if (!pSdbSetPermLayerKeys
)
831 skip("Skipping tests with SdbSetPermLayerKeys, function not found\n");
835 if (!pSdbGetPermLayerKeys
)
837 skip("Skipping tests with SdbGetPermLayerKeys, function not found\n");
841 test_SdbGetPermLayerKeys();
844 if (!pSetPermLayerState
)
846 skip("Skipping tests with SetPermLayerState, function not found\n");