1 /* 2 * Subject Interface Package tests 3 * 4 * Copyright 2006 Paul Vriens 5 * Copyright 2008 Juan Lang 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include <stdio.h> 23 #include <stdarg.h> 24 #include <windef.h> 25 #include <winbase.h> 26 #include <winerror.h> 27 #include <winnls.h> 28 #include <wincrypt.h> 29 #include <mssip.h> 30 31 #include "wine/test.h" 32 33 static BOOL (WINAPI * funcCryptSIPGetSignedDataMsg)(SIP_SUBJECTINFO *,DWORD *,DWORD,DWORD *,BYTE *); 34 static BOOL (WINAPI * funcCryptSIPPutSignedDataMsg)(SIP_SUBJECTINFO *,DWORD,DWORD *,DWORD,BYTE *); 35 static BOOL (WINAPI * funcCryptSIPCreateIndirectData)(SIP_SUBJECTINFO *,DWORD *,SIP_INDIRECT_DATA *); 36 static BOOL (WINAPI * funcCryptSIPVerifyIndirectData)(SIP_SUBJECTINFO *,SIP_INDIRECT_DATA *); 37 static BOOL (WINAPI * funcCryptSIPRemoveSignedDataMsg)(SIP_SUBJECTINFO *,DWORD); 38 39 static void test_AddRemoveProvider(void) 40 { 41 BOOL ret; 42 SIP_ADD_NEWPROVIDER newprov; 43 GUID actionid = { 0xdeadbe, 0xefde, 0xadbe, { 0xef,0xde,0xad,0xbe,0xef,0xde,0xad,0xbe }}; 44 static WCHAR dummydll[] = {'d','e','a','d','b','e','e','f','.','d','l','l',0 }; 45 static WCHAR dummyfunction[] = {'d','u','m','m','y','f','u','n','c','t','i','o','n',0 }; 46 47 /* NULL check */ 48 SetLastError(0xdeadbeef); 49 ret = CryptSIPRemoveProvider(NULL); 50 ok (!ret, "Expected CryptSIPRemoveProvider to fail.\n"); 51 ok (GetLastError() == ERROR_INVALID_PARAMETER, 52 "Expected ERROR_INVALID_PARAMETER, got %d.\n", GetLastError()); 53 54 /* nonexistent provider should result in a registry error */ 55 SetLastError(0xdeadbeef); 56 ret = CryptSIPRemoveProvider(&actionid); 57 if (!ret && GetLastError() == ERROR_ACCESS_DENIED) 58 { 59 /* Apparently the needed rights are checked before the existence of the provider */ 60 skip("Need admin rights\n"); 61 } 62 else 63 { 64 /* On some Win98 systems, CryptSIPRemoveProvider always succeeds if 65 * the arguments are correct, whether or not the registry key is 66 * present, so don't test ret, just check the last error if it does 67 * return FALSE. 68 */ 69 if (!ret) 70 ok (GetLastError() == ERROR_FILE_NOT_FOUND, 71 "Expected ERROR_FILE_NOT_FOUND, got %d.\n", GetLastError()); 72 } 73 74 /* Everything OK, pwszIsFunctionName and pwszIsFunctionNameFmt2 are left NULL 75 * as allowed */ 76 77 memset(&newprov, 0, sizeof(SIP_ADD_NEWPROVIDER)); 78 newprov.cbStruct = sizeof(SIP_ADD_NEWPROVIDER); 79 newprov.pgSubject = &actionid; 80 newprov.pwszDLLFileName = dummydll; 81 newprov.pwszGetFuncName = dummyfunction; 82 newprov.pwszPutFuncName = dummyfunction; 83 newprov.pwszCreateFuncName = dummyfunction; 84 newprov.pwszVerifyFuncName = dummyfunction; 85 newprov.pwszRemoveFuncName = dummyfunction; 86 SetLastError(0xdeadbeef); 87 ret = CryptSIPAddProvider(&newprov); 88 if (!ret && GetLastError() == ERROR_ACCESS_DENIED) 89 { 90 skip("Need admin rights\n"); 91 return; 92 } 93 ok ( ret, "CryptSIPAddProvider should have succeeded, last error %d\n", GetLastError()); 94 95 /* Dummy provider will be deleted, but the function still fails because 96 * pwszIsFunctionName and pwszIsFunctionNameFmt2 are not present in the 97 * registry. 98 */ 99 SetLastError(0xdeadbeef); 100 ret = CryptSIPRemoveProvider(&actionid); 101 /* On some Win98 systems, CryptSIPRemoveProvider always succeeds if 102 * the arguments are correct, whether or not the registry key is 103 * present, so don't test ret, just check the last error if it does 104 * return FALSE. 105 */ 106 if (!ret) 107 ok (GetLastError() == ERROR_FILE_NOT_FOUND, 108 "Expected ERROR_FILE_NOT_FOUND, got %d.\n", GetLastError()); 109 110 /* Everything OK */ 111 memset(&newprov, 0, sizeof(SIP_ADD_NEWPROVIDER)); 112 newprov.cbStruct = sizeof(SIP_ADD_NEWPROVIDER); 113 newprov.pgSubject = &actionid; 114 newprov.pwszDLLFileName = dummydll; 115 newprov.pwszGetFuncName = dummyfunction; 116 newprov.pwszPutFuncName = dummyfunction; 117 newprov.pwszCreateFuncName = dummyfunction; 118 newprov.pwszVerifyFuncName = dummyfunction; 119 newprov.pwszRemoveFuncName = dummyfunction; 120 newprov.pwszIsFunctionNameFmt2 = dummyfunction; 121 newprov.pwszIsFunctionName = dummyfunction; 122 /* If GetCapFuncName set to NULL, then CryptSIPRemoveProvider fails on win 8 */ 123 newprov.pwszGetCapFuncName = dummyfunction; 124 125 SetLastError(0xdeadbeef); 126 ret = CryptSIPAddProvider(&newprov); 127 ok ( ret, "CryptSIPAddProvider should have succeeded, last error %d\n", GetLastError()); 128 129 /* Dummy provider should be deleted */ 130 SetLastError(0xdeadbeef); 131 ret = CryptSIPRemoveProvider(&actionid); 132 ok ( ret, "CryptSIPRemoveProvider should have succeeded, last error %d\n", GetLastError()); 133 } 134 135 static const BYTE cabFileData[] = { 136 0x4d,0x53,0x43,0x46,0x00,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 137 0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x01,0x00,0x01,0x00,0x00,0x00, 138 0xef,0xbe,0xff,0xff,0x42,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,0x00,0x00,0x00, 139 0x00,0x00,0x00,0x00,0x00,0x00,0xf7,0x38,0x4b,0xac,0x00,0x00,0x61,0x2e,0x74,0x78, 140 0x74,0x00,0x6d,0x5a,0x72,0x78,0x06,0x00,0x06,0x00,0x61,0x2e,0x74,0x78,0x74,0x0a, 141 }; 142 143 static void test_SIPRetrieveSubjectGUID(void) 144 { 145 BOOL ret; 146 GUID subject; 147 HANDLE file; 148 static const CHAR windir[] = "windir"; 149 static const CHAR regeditExe[] = "regedit.exe"; 150 static const GUID nullSubject = { 0x0, 0x0, 0x0, { 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 }}; 151 static const WCHAR deadbeef[] = { 'c',':','\\','d','e','a','d','b','e','e','f','.','d','b','f',0 }; 152 /* Couldn't find a name for this GUID, it's the one used for 95% of the files */ 153 static const GUID unknownGUID = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; 154 static const GUID cabGUID = { 0xc689aaba, 0x8e78, 0x11d0, {0x8c,0x47,0x00,0xc0,0x4f,0xc2,0x95,0xee }}; 155 static CHAR regeditPath[MAX_PATH]; 156 static WCHAR regeditPathW[MAX_PATH]; 157 static CHAR path[MAX_PATH]; 158 static CHAR tempfile[MAX_PATH]; 159 static WCHAR tempfileW[MAX_PATH]; 160 DWORD written; 161 162 /* NULL check */ 163 SetLastError(0xdeadbeef); 164 ret = CryptSIPRetrieveSubjectGuid(NULL, NULL, NULL); 165 ok ( !ret, "Expected CryptSIPRetrieveSubjectGuid to fail\n"); 166 ok (GetLastError() == ERROR_INVALID_PARAMETER, 167 "Expected ERROR_INVALID_PARAMETER, got %d.\n", GetLastError()); 168 169 /* Test with a nonexistent file (hopefully) */ 170 SetLastError(0xdeadbeef); 171 /* Set subject to something other than zeros */ 172 memset(&subject, 1, sizeof(GUID)); 173 ret = CryptSIPRetrieveSubjectGuid(deadbeef, NULL, &subject); 174 ok ( !ret, "Expected CryptSIPRetrieveSubjectGuid to fail\n"); 175 ok (GetLastError() == ERROR_FILE_NOT_FOUND || 176 GetLastError() == ERROR_PATH_NOT_FOUND, 177 "Expected ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND, got %d.\n", 178 GetLastError()); 179 ok(IsEqualGUID(&subject, &nullSubject), 180 "Expected a NULL GUID for c:\\deadbeef.dbf, not %s\n", wine_dbgstr_guid(&subject)); 181 182 /* Now with an executable that should exist 183 * 184 * Use A-functions where possible as that should be available on all platforms 185 */ 186 ret = GetEnvironmentVariableA(windir, regeditPath, MAX_PATH); 187 ok (ret > 0, "expected GEVA(windir) to succeed, last error %d\n", GetLastError()); 188 strcat(regeditPath, "\\"); 189 strcat(regeditPath, regeditExe); 190 MultiByteToWideChar(CP_ACP, 0, regeditPath, strlen(regeditPath)+1, regeditPathW, 191 ARRAY_SIZE(regeditPathW)); 192 193 SetLastError(0xdeadbeef); 194 memset(&subject, 1, sizeof(GUID)); 195 ret = CryptSIPRetrieveSubjectGuid(regeditPathW, NULL, &subject); 196 ok ( ret, "Expected CryptSIPRetrieveSubjectGuid to succeed\n"); 197 ok(IsEqualGUID(&subject, &unknownGUID), 198 "Expected (%s), got (%s).\n", wine_dbgstr_guid(&unknownGUID), wine_dbgstr_guid(&subject)); 199 200 /* The same thing but now with a handle instead of a filename */ 201 file = CreateFileA(regeditPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); 202 SetLastError(0xdeadbeef); 203 memset(&subject, 1, sizeof(GUID)); 204 ret = CryptSIPRetrieveSubjectGuid(NULL, file, &subject); 205 ok ( ret, "Expected CryptSIPRetrieveSubjectGuid to succeed\n"); 206 ok(IsEqualGUID(&subject, &unknownGUID), 207 "Expected (%s), got (%s).\n", wine_dbgstr_guid(&unknownGUID), wine_dbgstr_guid(&subject)); 208 CloseHandle(file); 209 210 /* And both */ 211 file = CreateFileA(regeditPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); 212 SetLastError(0xdeadbeef); 213 memset(&subject, 1, sizeof(GUID)); 214 ret = CryptSIPRetrieveSubjectGuid(regeditPathW, file, &subject); 215 ok ( ret, "Expected CryptSIPRetrieveSubjectGuid to succeed\n"); 216 ok(IsEqualGUID(&subject, &unknownGUID), 217 "Expected (%s), got (%s).\n", wine_dbgstr_guid(&unknownGUID), wine_dbgstr_guid(&subject)); 218 CloseHandle(file); 219 220 /* Now with an empty file */ 221 GetTempPathA(sizeof(path), path); 222 GetTempFileNameA(path, "sip", 0 , tempfile); 223 MultiByteToWideChar(CP_ACP, 0, tempfile, strlen(tempfile)+1, tempfileW, ARRAY_SIZE(tempfileW)); 224 225 SetLastError(0xdeadbeef); 226 memset(&subject, 1, sizeof(GUID)); 227 ret = CryptSIPRetrieveSubjectGuid(tempfileW, NULL, &subject); 228 ok ( !ret, "Expected CryptSIPRetrieveSubjectGuid to fail\n"); 229 ok ( GetLastError() == ERROR_FILE_INVALID || 230 GetLastError() == ERROR_INVALID_PARAMETER /* Vista */ || 231 GetLastError() == ERROR_SUCCESS /* most Win98 */ || 232 GetLastError() == TRUST_E_SUBJECT_FORM_UNKNOWN /* some Win98 */, 233 "Expected ERROR_FILE_INVALID, ERROR_INVALID_PARAMETER, ERROR_SUCCESS or TRUST_E_SUBJECT_FORM_UNKNOWN, got 0x%08x\n", GetLastError()); 234 ok(IsEqualGUID(&subject, &nullSubject), 235 "Expected a NULL GUID for empty file %s, not %s\n", tempfile, wine_dbgstr_guid(&subject)); 236 237 /* Use a file with a size of 3 (at least < 4) */ 238 file = CreateFileA(tempfile, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 239 WriteFile(file, "123", 3, &written, NULL); 240 CloseHandle(file); 241 242 SetLastError(0xdeadbeef); 243 memset(&subject, 1, sizeof(GUID)); 244 ret = CryptSIPRetrieveSubjectGuid(tempfileW, NULL, &subject); 245 ok ( !ret, "Expected CryptSIPRetrieveSubjectGuid to fail\n"); 246 ok ( GetLastError() == ERROR_INVALID_PARAMETER || 247 GetLastError() == ERROR_SUCCESS /* most Win98 */ || 248 GetLastError() == TRUST_E_SUBJECT_FORM_UNKNOWN /* some Win98 */, 249 "Expected ERROR_INVALID_PARAMETER, ERROR_SUCCESS or TRUST_E_SUBJECT_FORM_UNKNOWN, got 0x%08x\n", GetLastError()); 250 ok(IsEqualGUID(&subject, &nullSubject), 251 "Expected a NULL GUID for empty file %s, not %s\n", tempfile, wine_dbgstr_guid(&subject)); 252 253 /* And now >= 4 */ 254 file = CreateFileA(tempfile, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); 255 WriteFile(file, "1234", 4, &written, NULL); 256 CloseHandle(file); 257 258 SetLastError(0xdeadbeef); 259 memset(&subject, 1, sizeof(GUID)); 260 ret = CryptSIPRetrieveSubjectGuid(tempfileW, NULL, &subject); 261 ok ( !ret, "Expected CryptSIPRetrieveSubjectGuid to fail\n"); 262 ok ( GetLastError() == TRUST_E_SUBJECT_FORM_UNKNOWN || 263 GetLastError() == ERROR_SUCCESS /* Win98 */, 264 "Expected TRUST_E_SUBJECT_FORM_UNKNOWN or ERROR_SUCCESS, got 0x%08x\n", GetLastError()); 265 ok(IsEqualGUID(&subject, &nullSubject), 266 "Expected a NULL GUID for empty file %s, not %s\n", tempfile, wine_dbgstr_guid(&subject)); 267 268 /* Clean up */ 269 DeleteFileA(tempfile); 270 271 /* Create a file with just the .cab header 'MSCF' */ 272 SetLastError(0xdeadbeef); 273 file = CreateFileA(tempfile, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); 274 ok(file != INVALID_HANDLE_VALUE, "failed with %u\n", GetLastError()); 275 WriteFile(file, cabFileData, 4, &written, NULL); 276 CloseHandle(file); 277 278 SetLastError(0xdeadbeef); 279 memset(&subject, 1, sizeof(GUID)); 280 ret = CryptSIPRetrieveSubjectGuid(tempfileW, NULL, &subject); 281 ok( ret, "CryptSIPRetrieveSubjectGuid failed: %d (0x%08x)\n", 282 GetLastError(), GetLastError() ); 283 ok(IsEqualGUID(&subject, &cabGUID), 284 "Expected GUID %s for cabinet file, not %s\n", wine_dbgstr_guid(&cabGUID), wine_dbgstr_guid(&subject)); 285 286 /* Clean up */ 287 DeleteFileA(tempfile); 288 289 /* Create a .cab file */ 290 SetLastError(0xdeadbeef); 291 file = CreateFileA(tempfile, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL); 292 ok(file != INVALID_HANDLE_VALUE, "failed with %u\n", GetLastError()); 293 WriteFile(file, cabFileData, sizeof(cabFileData), &written, NULL); 294 CloseHandle(file); 295 296 SetLastError(0xdeadbeef); 297 memset(&subject, 1, sizeof(GUID)); 298 ret = CryptSIPRetrieveSubjectGuid(tempfileW, NULL, &subject); 299 ok( ret, "CryptSIPRetrieveSubjectGuid failed: %d (0x%08x)\n", 300 GetLastError(), GetLastError() ); 301 ok(IsEqualGUID(&subject, &cabGUID), 302 "Expected GUID %s for cabinet file, not %s\n", wine_dbgstr_guid(&cabGUID), wine_dbgstr_guid(&subject)); 303 304 /* Clean up */ 305 DeleteFileA(tempfile); 306 } 307 308 static void test_SIPLoad(void) 309 { 310 BOOL ret; 311 GUID subject; 312 static GUID dummySubject = { 0xdeadbeef, 0xdead, 0xbeef, { 0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef }}; 313 static GUID unknown = { 0xC689AABA, 0x8E78, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; /* WINTRUST.DLL */ 314 static GUID unknown2 = { 0xDE351A43, 0x8E59, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; /* WINTRUST.DLL */ 315 /* The next SIP is available on Windows and on Wine */ 316 static GUID unknown3 = { 0x000C10F1, 0x0000, 0x0000, { 0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 }}; /* MSISIP.DLL */ 317 SIP_DISPATCH_INFO sdi; 318 HMODULE hCrypt; 319 320 /* All NULL */ 321 SetLastError(0xdeadbeef); 322 ret = CryptSIPLoad(NULL, 0, NULL); 323 ok ( !ret, "Expected CryptSIPLoad to fail\n"); 324 ok ( GetLastError() == ERROR_INVALID_PARAMETER, 325 "Expected ERROR_INVALID_PARAMETER, got 0x%08x\n", GetLastError()); 326 327 /* Only pSipDispatch NULL */ 328 SetLastError(0xdeadbeef); 329 ret = CryptSIPLoad(&subject, 0, NULL); 330 ok ( !ret, "Expected CryptSIPLoad to fail\n"); 331 ok ( GetLastError() == ERROR_INVALID_PARAMETER, 332 "Expected ERROR_INVALID_PARAMETER, got 0x%08x\n", GetLastError()); 333 334 /* No NULLs, but nonexistent pgSubject */ 335 SetLastError(0xdeadbeef); 336 memset(&sdi, 0, sizeof(SIP_DISPATCH_INFO)); 337 sdi.cbSize = sizeof(SIP_DISPATCH_INFO); 338 sdi.pfGet = (pCryptSIPGetSignedDataMsg)0xdeadbeef; 339 ret = CryptSIPLoad(&dummySubject, 0, &sdi); 340 ok ( !ret, "Expected CryptSIPLoad to fail\n"); 341 ok ( GetLastError() == TRUST_E_SUBJECT_FORM_UNKNOWN, 342 "Expected TRUST_E_SUBJECT_FORM_UNKNOWN, got 0x%08x\n", GetLastError()); 343 ok( sdi.pfGet == (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected no change to the function pointer\n"); 344 345 hCrypt = GetModuleHandleA("crypt32.dll"); 346 funcCryptSIPGetSignedDataMsg = (void*)GetProcAddress(hCrypt, "CryptSIPGetSignedDataMsg"); 347 funcCryptSIPPutSignedDataMsg = (void*)GetProcAddress(hCrypt, "CryptSIPPutSignedDataMsg"); 348 funcCryptSIPCreateIndirectData = (void*)GetProcAddress(hCrypt, "CryptSIPCreateIndirectData"); 349 funcCryptSIPVerifyIndirectData = (void*)GetProcAddress(hCrypt, "CryptSIPVerifyIndirectData"); 350 funcCryptSIPRemoveSignedDataMsg = (void*)GetProcAddress(hCrypt, "CryptSIPRemoveSignedDataMsg"); 351 352 /* All OK */ 353 SetLastError(0xdeadbeef); 354 memset(&sdi, 0, sizeof(SIP_DISPATCH_INFO)); 355 sdi.cbSize = sizeof(SIP_DISPATCH_INFO); 356 sdi.pfGet = (pCryptSIPGetSignedDataMsg)0xdeadbeef; 357 ret = CryptSIPLoad(&unknown, 0, &sdi); 358 ok ( ret, "Expected CryptSIPLoad to succeed\n"); 359 /* On native the last error will always be ERROR_PROC_NOT_FOUND as native searches for the function DllCanUnloadNow 360 * in WINTRUST.DLL (in this case). This function is not available in WINTRUST.DLL. 361 * For now there's no need to implement this is Wine as I doubt any program will rely on 362 * this last error when the call succeeded. 363 */ 364 ok( sdi.pfGet != (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected a function pointer to be loaded.\n"); 365 366 /* The function addresses returned by CryptSIPLoad are actually the addresses of 367 * crypt32's own functions. A function calling these addresses will end up first 368 * calling crypt32 functions which in its turn call the equivalent in the SIP 369 * as dictated by the given GUID. 370 */ 371 if (funcCryptSIPGetSignedDataMsg && funcCryptSIPPutSignedDataMsg && funcCryptSIPCreateIndirectData && 372 funcCryptSIPVerifyIndirectData && funcCryptSIPRemoveSignedDataMsg) 373 ok (sdi.pfGet == funcCryptSIPGetSignedDataMsg && 374 sdi.pfPut == funcCryptSIPPutSignedDataMsg && 375 sdi.pfCreate == funcCryptSIPCreateIndirectData && 376 sdi.pfVerify == funcCryptSIPVerifyIndirectData && 377 sdi.pfRemove == funcCryptSIPRemoveSignedDataMsg, 378 "Expected function addresses to be from crypt32\n"); 379 else 380 trace("Couldn't load function pointers\n"); 381 382 /* All OK, but different GUID (same SIP though) */ 383 SetLastError(0xdeadbeef); 384 memset(&sdi, 0, sizeof(SIP_DISPATCH_INFO)); 385 sdi.cbSize = sizeof(SIP_DISPATCH_INFO); 386 sdi.pfGet = (pCryptSIPGetSignedDataMsg)0xdeadbeef; 387 ret = CryptSIPLoad(&unknown2, 0, &sdi); 388 ok ( ret, "Expected CryptSIPLoad to succeed\n"); 389 /* This call on its own would have resulted in an ERROR_PROC_NOT_FOUND, but the previous 390 * call to CryptSIPLoad already loaded wintrust.dll. As this information is cached, 391 * CryptSIPLoad will not try to search for the already mentioned DllCanUnloadNow. 392 */ 393 ok( sdi.pfGet != (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected a function pointer to be loaded.\n"); 394 395 /* All OK, but other SIP */ 396 SetLastError(0xdeadbeef); 397 memset(&sdi, 0, sizeof(SIP_DISPATCH_INFO)); 398 sdi.cbSize = sizeof(SIP_DISPATCH_INFO); 399 sdi.pfGet = (pCryptSIPGetSignedDataMsg)0xdeadbeef; 400 ret = CryptSIPLoad(&unknown3, 0, &sdi); 401 if (ret) 402 { 403 /* The SIP is known so we can safely assume that the next tests can be done */ 404 405 /* As msisip.dll is not checked yet by any of the previous calls, the 406 * function DllCanUnloadNow will be checked again in msisip.dll (it's not present) 407 */ 408 ok( sdi.pfGet != (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected a function pointer to be loaded.\n"); 409 410 /* This is another SIP but this test proves the function addresses are the same as 411 * in the previous test. 412 */ 413 if (funcCryptSIPGetSignedDataMsg && funcCryptSIPPutSignedDataMsg && funcCryptSIPCreateIndirectData && 414 funcCryptSIPVerifyIndirectData && funcCryptSIPRemoveSignedDataMsg) 415 ok (sdi.pfGet == funcCryptSIPGetSignedDataMsg && 416 sdi.pfPut == funcCryptSIPPutSignedDataMsg && 417 sdi.pfCreate == funcCryptSIPCreateIndirectData && 418 sdi.pfVerify == funcCryptSIPVerifyIndirectData && 419 sdi.pfRemove == funcCryptSIPRemoveSignedDataMsg, 420 "Expected function addresses to be from crypt32\n"); 421 else 422 trace("Couldn't load function pointers\n"); 423 } 424 425 /* Reserved parameter not 0 */ 426 SetLastError(0xdeadbeef); 427 memset(&sdi, 0, sizeof(SIP_DISPATCH_INFO)); 428 sdi.cbSize = sizeof(SIP_DISPATCH_INFO); 429 sdi.pfGet = (pCryptSIPGetSignedDataMsg)0xdeadbeef; 430 ret = CryptSIPLoad(&unknown, 1, &sdi); 431 ok ( !ret, "Expected CryptSIPLoad to fail\n"); 432 ok ( GetLastError() == ERROR_INVALID_PARAMETER, 433 "Expected ERROR_INVALID_PARAMETER, got 0x%08x\n", GetLastError()); 434 ok( sdi.pfGet == (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected no change to the function pointer\n"); 435 } 436 437 START_TEST(sip) 438 { 439 test_AddRemoveProvider(); 440 /* It seems that the caching for loaded dlls is shared between CryptSIPRetrieveSubjectGUID 441 * and CryptSIPLoad. The tests have to be in this order to succeed. This is because in the last 442 * test for CryptSIPRetrieveSubjectGUID, several SIPs will be loaded (on Windows). 443 */ 444 test_SIPLoad(); 445 test_SIPRetrieveSubjectGUID(); 446 } 447