Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/wintrust/tests/crypt.c | 76 ++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 22 deletions(-)
diff --git a/dlls/wintrust/tests/crypt.c b/dlls/wintrust/tests/crypt.c index 5a4344bc931..dfa411548f9 100644 --- a/dlls/wintrust/tests/crypt.c +++ b/dlls/wintrust/tests/crypt.c @@ -401,33 +401,65 @@ static void test_calchash(void)
static void test_CryptCATOpen(void) { - HANDLE hcat; - char empty[MAX_PATH]; - WCHAR emptyW[MAX_PATH]; - HANDLE file; + WCHAR filename[MAX_PATH], temp_path[MAX_PATH]; + HANDLE cat; + DWORD flags; BOOL ret; + FILE *file; + char buffer[10];
- SetLastError(0xdeadbeef); - hcat = pCryptCATOpen(NULL, 0, 0, 0, 0); - ok(hcat == INVALID_HANDLE_VALUE, "CryptCATOpen succeeded\n"); - ok(GetLastError() == ERROR_INVALID_PARAMETER, - "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); - - if (!GetTempFileNameA(CURR_DIR, "cat", 0, empty)) return; + GetTempPathW(ARRAY_SIZE(temp_path), temp_path); + GetTempFileNameW(temp_path, L"cat", 0, filename);
- file = CreateFileA(empty, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); - ok(file != INVALID_HANDLE_VALUE, "CreateFileA failed %u\n", GetLastError()); - CloseHandle(file); - MultiByteToWideChar(CP_ACP, 0, empty, -1, emptyW, MAX_PATH); + SetLastError(0xdeadbeef); + cat = pCryptCATOpen(NULL, 0, 0, 0, 0); + ok(cat == INVALID_HANDLE_VALUE, "expected failure\n"); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError());
- hcat = pCryptCATOpen(emptyW, 0, 0, 0, 0); - todo_wine - ok(hcat != INVALID_HANDLE_VALUE, "Expected a correct handle\n"); + for (flags = 0; flags < 8; ++flags) + { + SetLastError(0xdeadbeef); + cat = pCryptCATOpen(filename, flags, 0, 0, 0); + if (flags == CRYPTCAT_OPEN_EXISTING) + { + ok(cat == INVALID_HANDLE_VALUE, "flags %#x: expected failure\n", flags); + ok(GetLastError() == ERROR_FILE_NOT_FOUND, "flags %#x: got error %u\n", flags, GetLastError()); + ret = DeleteFileW(filename); + ok(!ret, "flags %#x: expected failure\n", flags); + } + else + { + todo_wine ok(cat != INVALID_HANDLE_VALUE, "flags %#x: expected success\n", flags); + todo_wine ok(!GetLastError(), "flags %#x: got error %u\n", flags, GetLastError()); + ret = pCryptCATClose(cat); + todo_wine ok(ret, "flags %#x: failed to close file\n", flags); + ret = DeleteFileW(filename); + todo_wine_if (flags & (CRYPTCAT_OPEN_ALWAYS | CRYPTCAT_OPEN_CREATENEW)) + ok(ret, "flags %#x: failed to delete file, error %u\n", flags, GetLastError()); + } + + file = _wfopen(filename, L"w"); + fputs("test text", file); + fclose(file);
- ret = pCryptCATClose(hcat); - todo_wine - ok(ret, "CryptCATClose failed\n"); - DeleteFileA(empty); + SetLastError(0xdeadbeef); + cat = pCryptCATOpen(filename, flags, 0, 0, 0); + todo_wine ok(cat != INVALID_HANDLE_VALUE, "flags %#x: expected success\n", flags); + todo_wine ok(!GetLastError(), "flags %#x: got error %u\n", flags, GetLastError()); + ret = pCryptCATClose(cat); + todo_wine ok(ret, "flags %#x: failed to close file\n", flags); + + file = _wfopen(filename, L"r"); + ret = fread(buffer, 1, sizeof(buffer), file); + if (flags & CRYPTCAT_OPEN_CREATENEW) + todo_wine ok(!ret, "flags %#x: got %s\n", flags, debugstr_an(buffer, ret)); + else + ok(ret == 9 && !strncmp(buffer, "test text", ret), "flags %#x: got %s\n", flags, debugstr_an(buffer, ret)); + fclose(file); + + ret = DeleteFileW(filename); + ok(ret, "flags %#x: failed to delete file, error %u\n", flags, GetLastError()); + } }
static DWORD error_area;
Found when debugging the "inf2cat" tool from the Windows 10 DDK.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- This is a set of four patches I wrote in the process of trying to make it possible for our tests to install and run PnP drivers. Some context on that follows:
Normally 64-bit Windows prevents unsigned drivers from being installed. This requirement can be overridden temporarily in boot options, but supposedly not for PnP drivers (though I haven't tested this).
It requires a lot of code, but it is actually possible to generate a catalog file, sign it with a self-signed certificate, add that certificate to the trusted publisher and root stores, and thereby install a test driver without prompting any dialog boxes. The basic process is described in more detail by Microsoft here:
https://docs.microsoft.com/en-us/windows-hardware/drivers/install/introducti...
It's harder for us, of course, because we don't really have access to those tools; instead we have to reverse-engineer them and replicate them in C code. Fortunately I already have a working test that is able to at least call SetupCopyOEMInf() successfully; hopefully actual driver code won't present any additional difficulty...
dlls/wintrust/crypt.c | 20 +++++++++++--------- dlls/wintrust/tests/crypt.c | 3 +-- 2 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/dlls/wintrust/crypt.c b/dlls/wintrust/crypt.c index b454c8b8853..4eef9d1bcbf 100644 --- a/dlls/wintrust/crypt.c +++ b/dlls/wintrust/crypt.c @@ -851,18 +851,18 @@ BOOL WINAPI CryptCATCatalogInfoFromContext(HCATINFO hcatinfo, CATALOG_INFO *info /*********************************************************************** * CryptCATOpen (WINTRUST.@) */ -HANDLE WINAPI CryptCATOpen(LPWSTR pwszFileName, DWORD fdwOpenFlags, HCRYPTPROV hProv, +HANDLE WINAPI CryptCATOpen(WCHAR *filename, DWORD flags, HCRYPTPROV hProv, DWORD dwPublicVersion, DWORD dwEncodingType) { HANDLE file, hmsg; BYTE *buffer = NULL; - DWORD size, flags = OPEN_EXISTING; + DWORD size, open_mode = OPEN_EXISTING; struct cryptcat *cc;
- TRACE("%s, %x, %lx, %x, %x\n", debugstr_w(pwszFileName), fdwOpenFlags, - hProv, dwPublicVersion, dwEncodingType); + TRACE("filename %s, flags %#x, provider %#lx, version %#x, type %#x\n", + debugstr_w(filename), flags, hProv, dwPublicVersion, dwEncodingType);
- if (!pwszFileName) + if (!filename) { SetLastError(ERROR_INVALID_PARAMETER); return INVALID_HANDLE_VALUE; @@ -870,10 +870,12 @@ HANDLE WINAPI CryptCATOpen(LPWSTR pwszFileName, DWORD fdwOpenFlags, HCRYPTPROV h
if (!dwEncodingType) dwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
- if (fdwOpenFlags & CRYPTCAT_OPEN_ALWAYS) flags |= OPEN_ALWAYS; - if (fdwOpenFlags & CRYPTCAT_OPEN_CREATENEW) flags |= CREATE_NEW; + if (flags & CRYPTCAT_OPEN_ALWAYS) + open_mode = OPEN_ALWAYS; + if (flags & CRYPTCAT_OPEN_CREATENEW) + open_mode = CREATE_NEW;
- file = CreateFileW(pwszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, flags, 0, NULL); + file = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, open_mode, 0, NULL); if (file == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE;
size = GetFileSize(file, NULL); @@ -951,7 +953,7 @@ HANDLE WINAPI CryptCATOpen(LPWSTR pwszFileName, DWORD fdwOpenFlags, HCRYPTPROV h p += size; } cc->inner = decode_inner_content(hmsg, dwEncodingType, &cc->inner_len); - if (!cc->inner || !CryptSIPRetrieveSubjectGuid(pwszFileName, NULL, &cc->subject)) + if (!cc->inner || !CryptSIPRetrieveSubjectGuid(filename, NULL, &cc->subject)) { CryptMsgClose(hmsg); HeapFree(GetProcessHeap(), 0, cc->attr); diff --git a/dlls/wintrust/tests/crypt.c b/dlls/wintrust/tests/crypt.c index dfa411548f9..e9928470332 100644 --- a/dlls/wintrust/tests/crypt.c +++ b/dlls/wintrust/tests/crypt.c @@ -434,8 +434,7 @@ static void test_CryptCATOpen(void) ret = pCryptCATClose(cat); todo_wine ok(ret, "flags %#x: failed to close file\n", flags); ret = DeleteFileW(filename); - todo_wine_if (flags & (CRYPTCAT_OPEN_ALWAYS | CRYPTCAT_OPEN_CREATENEW)) - ok(ret, "flags %#x: failed to delete file, error %u\n", flags, GetLastError()); + ok(ret, "flags %#x: failed to delete file, error %u\n", flags, GetLastError()); }
file = _wfopen(filename, L"w");
On 9/7/20 11:13 PM, Zebediah Figura wrote:
This is a set of four patches I wrote in the process of trying to make it possible for our tests to install and run PnP drivers. Some context on that follows:
Normally 64-bit Windows prevents unsigned drivers from being installed. This requirement can be overridden temporarily in boot options, but supposedly not for PnP drivers (though I haven't tested this).
It requires a lot of code, but it is actually possible to generate a catalog file, sign it with a self-signed certificate, add that certificate to the trusted publisher and root stores, and thereby install a test driver without prompting any dialog boxes. The basic process is described in more detail by Microsoft here:
https://docs.microsoft.com/en-us/windows-hardware/drivers/install/introducti...
It's harder for us, of course, because we don't really have access to those tools; instead we have to reverse-engineer them and replicate them in C code. Fortunately I already have a working test that is able to at least call SetupCopyOEMInf() successfully; hopefully actual driver code won't present any additional difficulty...
One of the caveats I forgot to mention is that the target machine still (apparently?) has to be configured to allow test-signing. Fortunately, that configuration is relatively easy to do, can be done from the command line, and persists across reboots. Specifically, one must run "bcdedit -set testsigning on".
On 9/7/20 11:28 PM, Zebediah Figura wrote:
On 9/7/20 11:13 PM, Zebediah Figura wrote:
This is a set of four patches I wrote in the process of trying to make it possible for our tests to install and run PnP drivers. Some context on that follows:
Normally 64-bit Windows prevents unsigned drivers from being installed. This requirement can be overridden temporarily in boot options, but supposedly not for PnP drivers (though I haven't tested this).
It requires a lot of code, but it is actually possible to generate a catalog file, sign it with a self-signed certificate, add that certificate to the trusted publisher and root stores, and thereby install a test driver without prompting any dialog boxes. The basic process is described in more detail by Microsoft here:
https://docs.microsoft.com/en-us/windows-hardware/drivers/install/introducti...
It's harder for us, of course, because we don't really have access to those tools; instead we have to reverse-engineer them and replicate them in C code. Fortunately I already have a working test that is able to at least call SetupCopyOEMInf() successfully; hopefully actual driver code won't present any additional difficulty...
One of the caveats I forgot to mention is that the target machine still (apparently?) has to be configured to allow test-signing. Fortunately, that configuration is relatively easy to do, can be done from the command line, and persists across reboots. Specifically, one must run "bcdedit -set testsigning on".
Predictably, I spoke too soon, but eventually I have managed to successfully programmatically test-sign drivers and run them on 64-bit Windows 7. I've attached basic patches, some of which still need some work before being ready for upstreaming, but which should be sufficient to demonstrate and test the process.
So right now, all we need in order to run these tests on the testbot is for (all) of the machines to be configured to turn on test-signing. This can be done in a terminal by running `bcdedit /set testsigning on`. François, does this seem like something that can be reasonably done?
Just to clarify, some of the motivations for this:
* It's actually possible to disable signature checking all together. (I believe this does also apply to PnP drivers, despite the documentation). The option doesn't persist across boots, however. That's not necessarily a problem for the testbot, as long as we just use snapshots from a boot with signature checking disabled, but it's a bit of an annoyance when testing locally, especially when crashing the kernel is easy. Still, maybe this option is preferable.
* This allows us to actually test ntoskrnl functions on current Windows, including functions only recently introduced. This is especially desirable as, having removed the XP test VM, we now only have one or two machines actually running the ntoskrnl tests. It also allows us to add tests for the PnP infrastructure, which is more than a little complex and I think deserves the tests. Included in this is wdfldr, which is both a newer feature and one that interacts heavily with PnP. I have an incomplete implementation in my local tree, but the API is quite large, and although we have access to a permissively-licensed source, it would be rather nice to have proper tests for it.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/wintrust/crypt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/wintrust/crypt.c b/dlls/wintrust/crypt.c index 4eef9d1bcbf..307eda32480 100644 --- a/dlls/wintrust/crypt.c +++ b/dlls/wintrust/crypt.c @@ -856,7 +856,7 @@ HANDLE WINAPI CryptCATOpen(WCHAR *filename, DWORD flags, HCRYPTPROV hProv, { HANDLE file, hmsg; BYTE *buffer = NULL; - DWORD size, open_mode = OPEN_EXISTING; + DWORD size, open_mode = OPEN_ALWAYS; struct cryptcat *cc;
TRACE("filename %s, flags %#x, provider %#lx, version %#x, type %#x\n", @@ -870,8 +870,8 @@ HANDLE WINAPI CryptCATOpen(WCHAR *filename, DWORD flags, HCRYPTPROV hProv,
if (!dwEncodingType) dwEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
- if (flags & CRYPTCAT_OPEN_ALWAYS) - open_mode = OPEN_ALWAYS; + if (flags == CRYPTCAT_OPEN_EXISTING) + open_mode = OPEN_EXISTING; if (flags & CRYPTCAT_OPEN_CREATENEW) open_mode = CREATE_NEW;
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/wintrust/crypt.c | 2 +- dlls/wintrust/tests/crypt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/wintrust/crypt.c b/dlls/wintrust/crypt.c index 307eda32480..975d51f14fd 100644 --- a/dlls/wintrust/crypt.c +++ b/dlls/wintrust/crypt.c @@ -873,7 +873,7 @@ HANDLE WINAPI CryptCATOpen(WCHAR *filename, DWORD flags, HCRYPTPROV hProv, if (flags == CRYPTCAT_OPEN_EXISTING) open_mode = OPEN_EXISTING; if (flags & CRYPTCAT_OPEN_CREATENEW) - open_mode = CREATE_NEW; + open_mode = CREATE_ALWAYS;
file = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, NULL, open_mode, 0, NULL); if (file == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE; diff --git a/dlls/wintrust/tests/crypt.c b/dlls/wintrust/tests/crypt.c index e9928470332..1b436e9f4ab 100644 --- a/dlls/wintrust/tests/crypt.c +++ b/dlls/wintrust/tests/crypt.c @@ -451,7 +451,7 @@ static void test_CryptCATOpen(void) file = _wfopen(filename, L"r"); ret = fread(buffer, 1, sizeof(buffer), file); if (flags & CRYPTCAT_OPEN_CREATENEW) - todo_wine ok(!ret, "flags %#x: got %s\n", flags, debugstr_an(buffer, ret)); + ok(!ret, "flags %#x: got %s\n", flags, debugstr_an(buffer, ret)); else ok(ret == 9 && !strncmp(buffer, "test text", ret), "flags %#x: got %s\n", flags, debugstr_an(buffer, ret)); fclose(file);