1 /* Unit test suite for wintrust crypt functions
3 * Copyright 2007 Paul Vriens
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/test.h"
29 static char selfname[MAX_PATH];
31 static CHAR CURR_DIR[MAX_PATH];
33 static BOOL (WINAPI * pCryptCATAdminAcquireContext)(HCATADMIN*, const GUID*, DWORD);
34 static BOOL (WINAPI * pCryptCATAdminReleaseContext)(HCATADMIN, DWORD);
35 static BOOL (WINAPI * pCryptCATAdminCalcHashFromFileHandle)(HANDLE hFile, DWORD*, BYTE*, DWORD);
37 static void InitFunctionPtrs(void)
39 HMODULE hWintrust = GetModuleHandleA("wintrust.dll");
41 #define WINTRUST_GET_PROC(func) \
42 p ## func = (void*)GetProcAddress(hWintrust, #func); \
44 trace("GetProcAddress(%s) failed\n", #func); \
47 WINTRUST_GET_PROC(CryptCATAdminAcquireContext)
48 WINTRUST_GET_PROC(CryptCATAdminReleaseContext)
49 WINTRUST_GET_PROC(CryptCATAdminCalcHashFromFileHandle)
51 #undef WINTRUST_GET_PROC
54 static void test_context(void)
58 static GUID dummy = { 0xdeadbeef, 0xdead, 0xbeef, { 0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef }};
59 static GUID unknown = { 0xC689AABA, 0x8E78, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; /* WINTRUST.DLL */
60 CHAR windir[MAX_PATH], catroot[MAX_PATH], catroot2[MAX_PATH], dummydir[MAX_PATH];
63 if (!pCryptCATAdminAcquireContext || !pCryptCATAdminReleaseContext)
65 skip("CryptCATAdminAcquireContext and/or CryptCATAdminReleaseContext are not available\n");
69 /* When CryptCATAdminAcquireContext is successful it will create
70 * several directories if they don't exist:
72 * ...\system32\CatRoot\{GUID}, this directory holds the .cat files
73 * ...\system32\CatRoot2\{GUID} (WinXP and up), here we find the catalog database for that GUID
75 * Windows Vista uses lowercase catroot and catroot2.
77 * When passed a NULL GUID it will create the following directories although on
78 * WinXP and up these directories are already present when Windows is installed:
80 * ...\system32\CatRoot\{127D0A1D-4EF2-11D1-8608-00C04FC295EE}
81 * ...\system32\CatRoot2\{127D0A1D-4EF2-11D1-8608-00C04FC295EE} (WinXP up)
83 * TODO: Find out what this GUID is/does.
85 * On WinXP and up there is also a TimeStamp file in some of directories that
86 * seem to indicate the last change to the catalog database for that GUID.
88 * On Windows 2000 some files are created/updated:
90 * ...\system32\CatRoot\SYSMAST.cbk
91 * ...\system32\CatRoot\SYSMAST.cbd
92 * ...\system32\CatRoot\{GUID}\CATMAST.cbk
93 * ...\system32\CatRoot\{GUID}\CATMAST.cbd
98 SetLastError(0xdeadbeef);
99 ret = pCryptCATAdminAcquireContext(NULL, NULL, 0);
100 ok(!ret, "Expected failure\n");
101 ok(GetLastError() == ERROR_INVALID_PARAMETER,
102 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
105 SetLastError(0xdeadbeef);
106 ret = pCryptCATAdminAcquireContext(&hca, NULL, 0);
107 ok(ret, "Expected success\n");
108 ok(GetLastError() == ERROR_SUCCESS ||
109 GetLastError() == 0xdeadbeef /* Vista */,
110 "Expected ERROR_SUCCESS or 0xdeadbeef, got %d\n", GetLastError());
111 ok(hca != NULL, "Expected a context handle, got NULL\n");
114 SetLastError(0xdeadbeef);
115 ret = pCryptCATAdminReleaseContext(NULL, 0);
118 ok(!ret, "Expected failure\n");
119 ok(GetLastError() == ERROR_INVALID_PARAMETER,
120 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
124 SetLastError(0xdeadbeef);
125 ret = pCryptCATAdminReleaseContext(hca, 0);
126 ok(ret, "Expected success\n");
127 ok(GetLastError() == 0xdeadbeef,
128 "Expected no change in last error, got %d\n", GetLastError());
130 /* Try to release a second time */
131 SetLastError(0xdeadbeef);
132 ret = pCryptCATAdminReleaseContext(hca, 0);
135 ok(!ret, "Expected failure\n");
136 ok(GetLastError() == ERROR_INVALID_PARAMETER,
137 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
140 /* NULL context handle and dummy GUID */
141 SetLastError(0xdeadbeef);
142 ret = pCryptCATAdminAcquireContext(NULL, &dummy, 0);
143 ok(!ret, "Expected failure\n");
144 ok(GetLastError() == ERROR_INVALID_PARAMETER,
145 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
147 /* Correct context handle and dummy GUID
149 * The tests run in the past unfortunately made sure that some directories were created.
152 * We don't want to mess too much with these for now so we should delete only the ones
153 * that shouldn't be there like the deadbeef ones. We first have to figure out if it's
154 * save to remove files and directories from CatRoot/CatRoot2.
157 SetLastError(0xdeadbeef);
158 ret = pCryptCATAdminAcquireContext(&hca, &dummy, 0);
159 ok(ret, "Expected success\n");
160 ok(GetLastError() == ERROR_SUCCESS ||
161 GetLastError() == 0xdeadbeef /* Vista */,
162 "Expected ERROR_SUCCESS or 0xdeadbeef, got %d\n", GetLastError());
163 ok(hca != NULL, "Expected a context handle, got NULL\n");
165 GetWindowsDirectoryA(windir, MAX_PATH);
166 lstrcpyA(catroot, windir);
167 lstrcatA(catroot, "\\system32\\CatRoot");
168 lstrcpyA(catroot2, windir);
169 lstrcatA(catroot2, "\\system32\\CatRoot2");
171 attrs = GetFileAttributes(catroot);
172 /* On a clean Wine this will fail. When a native wintrust.dll was used in the past
173 * some tests will succeed.
176 ok(attrs != INVALID_FILE_ATTRIBUTES,
177 "Expected the CatRoot directory to exist\n");
179 /* Windows creates the GUID directory in capitals */
180 lstrcpyA(dummydir, catroot);
181 lstrcatA(dummydir, "\\{DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF}");
182 attrs = GetFileAttributes(dummydir);
184 ok(attrs != INVALID_FILE_ATTRIBUTES,
185 "Expected CatRoot\\{DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF} directory to exist\n");
187 /* Only present on XP or higher. */
188 attrs = GetFileAttributes(catroot2);
189 if (attrs != INVALID_FILE_ATTRIBUTES)
191 lstrcpyA(dummydir, catroot2);
192 lstrcatA(dummydir, "\\{DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF}");
193 attrs = GetFileAttributes(dummydir);
194 ok(attrs != INVALID_FILE_ATTRIBUTES,
195 "Expected CatRoot2\\{DEADBEEF-DEAD-BEEF-DEAD-BEEFDEADBEEF} directory to exist\n");
198 ret = pCryptCATAdminReleaseContext(hca, 0);
199 ok(ret, "Expected success\n");
201 /* Correct context handle and GUID */
202 SetLastError(0xdeadbeef);
203 ret = pCryptCATAdminAcquireContext(&hca, &unknown, 0);
204 ok(ret, "Expected success\n");
205 ok(GetLastError() == ERROR_SUCCESS ||
206 GetLastError() == 0xdeadbeef /* Vista */,
207 "Expected ERROR_SUCCESS or 0xdeadbeef, got %d\n", GetLastError());
208 ok(hca != NULL, "Expected a context handle, got NULL\n");
210 ret = pCryptCATAdminReleaseContext(hca, 0);
211 ok(ret, "Expected success\n");
213 /* Flags not equal to 0 */
214 SetLastError(0xdeadbeef);
215 ret = pCryptCATAdminAcquireContext(&hca, &unknown, 1);
216 ok(ret, "Expected success\n");
217 ok(GetLastError() == ERROR_SUCCESS ||
218 GetLastError() == 0xdeadbeef /* Vista */,
219 "Expected ERROR_SUCCESS or 0xdeadbeef, got %d\n", GetLastError());
220 ok(hca != NULL, "Expected a context handle, got NULL\n");
222 ret = pCryptCATAdminReleaseContext(hca, 0);
223 ok(ret, "Expected success\n");
226 /* TODO: Check whether SHA-1 is the algorithm that's always used */
227 static void test_calchash(void)
233 BYTE expectedhash[20] = {0x3a,0xa1,0x19,0x08,0xec,0xa6,0x0d,0x2e,0x7e,0xcc,0x7a,0xca,0xf5,0xb8,0x2e,0x62,0x6a,0xda,0xf0,0x19};
237 if (!pCryptCATAdminCalcHashFromFileHandle)
239 skip("CryptCATAdminCalcHashFromFileHandle is not available\n");
244 SetLastError(0xdeadbeef);
245 ret = pCryptCATAdminCalcHashFromFileHandle(NULL, NULL, NULL, 0);
248 ok(!ret, "Expected failure\n");
249 ok(GetLastError() == ERROR_INVALID_PARAMETER,
250 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
253 /* NULL filehandle, rest is legal */
254 SetLastError(0xdeadbeef);
255 ret = pCryptCATAdminCalcHashFromFileHandle(NULL, &hashsize, NULL, 0);
258 ok(!ret, "Expected failure\n");
259 ok(GetLastError() == ERROR_INVALID_PARAMETER,
260 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
263 /* Correct filehandle, rest is NULL */
264 file = CreateFileA(selfname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
265 SetLastError(0xdeadbeef);
266 ret = pCryptCATAdminCalcHashFromFileHandle(file, NULL, NULL, 0);
269 ok(!ret, "Expected failure\n");
270 ok(GetLastError() == ERROR_INVALID_PARAMETER,
271 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
275 /* All OK, but dwFlags set to 1 */
276 file = CreateFileA(selfname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
277 SetLastError(0xdeadbeef);
278 ret = pCryptCATAdminCalcHashFromFileHandle(file, &hashsize, NULL, 1);
281 ok(!ret, "Expected failure\n");
282 ok(GetLastError() == ERROR_INVALID_PARAMETER,
283 "Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
287 /* All OK, requesting the size of the hash */
288 file = CreateFileA(selfname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
289 SetLastError(0xdeadbeef);
290 ret = pCryptCATAdminCalcHashFromFileHandle(file, &hashsize, NULL, 0);
291 ok(ret, "Expected success\n");
294 ok(hashsize == 20," Expected a hash size of 20, got %d\n", hashsize);
295 ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
296 "Expected ERROR_INSUFFICIENT_BUFFER, got %d\n", GetLastError());
300 /* All OK, retrieve the hash
301 * Double the hash buffer to see what happens to the size parameter
303 file = CreateFileA(selfname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
305 hash = HeapAlloc(GetProcessHeap(), 0, hashsize);
306 SetLastError(0xdeadbeef);
307 ret = pCryptCATAdminCalcHashFromFileHandle(file, &hashsize, hash, 0);
308 ok(ret, "Expected success\n");
311 ok(hashsize == 20," Expected a hash size of 20, got %d\n", hashsize);
312 ok(GetLastError() == ERROR_SUCCESS,
313 "Expected ERROR_SUCCESS, got %d\n", GetLastError());
316 HeapFree(GetProcessHeap(), 0, hash);
318 /* Do the same test with a file created and filled by ourselves (and we thus
319 * have a known hash for).
321 GetTempFileNameA(CURR_DIR, "hsh", 0, temp);
322 file = CreateFileA(temp, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
323 WriteFile(file, "Text in this file is needed to create a know hash", 49, &written, NULL);
326 /* All OK, first request the size and then retrieve the hash */
327 file = CreateFileA(temp, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
329 pCryptCATAdminCalcHashFromFileHandle(file, &hashsize, NULL, 0);
330 hash = HeapAlloc(GetProcessHeap(), 0, hashsize);
331 SetLastError(0xdeadbeef);
332 ret = pCryptCATAdminCalcHashFromFileHandle(file, &hashsize, hash, 0);
333 ok(ret, "Expected success\n");
336 ok(GetLastError() == ERROR_SUCCESS,
337 "Expected ERROR_SUCCESS, got %d\n", GetLastError());
338 ok(hashsize == sizeof(expectedhash) &&
339 !memcmp(hash, expectedhash, sizeof(expectedhash)),
340 "Hashes didn't match\n");
344 HeapFree(GetProcessHeap(), 0, hash);
355 myARGC = winetest_get_mainargs(&myARGV);
356 strcpy(selfname, myARGV[0]);
358 GetCurrentDirectoryA(MAX_PATH, CURR_DIR);