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