1 /* 2 * Credential Function Tests 3 * 4 * Copyright 2007 Robert Shearman 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "precomp.h" 22 23 #include <wincred.h> 24 25 static BOOL (WINAPI *pCredDeleteA)(LPCSTR,DWORD,DWORD); 26 static BOOL (WINAPI *pCredEnumerateA)(LPCSTR,DWORD,DWORD *,PCREDENTIALA **); 27 static VOID (WINAPI *pCredFree)(PVOID); 28 static BOOL (WINAPI *pCredGetSessionTypes)(DWORD,LPDWORD); 29 static BOOL (WINAPI *pCredReadA)(LPCSTR,DWORD,DWORD,PCREDENTIALA *); 30 static BOOL (WINAPI *pCredRenameA)(LPCSTR,LPCSTR,DWORD,DWORD); 31 static BOOL (WINAPI *pCredWriteA)(PCREDENTIALA,DWORD); 32 static BOOL (WINAPI *pCredReadDomainCredentialsA)(PCREDENTIAL_TARGET_INFORMATIONA,DWORD,DWORD*,PCREDENTIALA**); 33 static BOOL (WINAPI *pCredMarshalCredentialA)(CRED_MARSHAL_TYPE,PVOID,LPSTR *); 34 static BOOL (WINAPI *pCredUnmarshalCredentialA)(LPCSTR,PCRED_MARSHAL_TYPE,PVOID); 35 static BOOL (WINAPI *pCredIsMarshaledCredentialA)(LPCSTR); 36 37 #define TEST_TARGET_NAME "credtest.winehq.org" 38 #define TEST_TARGET_NAME2 "credtest2.winehq.org" 39 static const WCHAR TEST_PASSWORD[] = {'p','4','$','$','w','0','r','d','!',0}; 40 41 static void test_CredReadA(void) 42 { 43 BOOL ret; 44 PCREDENTIALA cred; 45 46 SetLastError(0xdeadbeef); 47 ret = pCredReadA(TEST_TARGET_NAME, -1, 0, &cred); 48 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 49 "CredReadA should have failed with ERROR_INVALID_PARAMETER instead of %d\n", 50 GetLastError()); 51 52 SetLastError(0xdeadbeef); 53 ret = pCredReadA(TEST_TARGET_NAME, CRED_TYPE_GENERIC, 0xdeadbeef, &cred); 54 ok(!ret && ( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER ), 55 "CredReadA should have failed with ERROR_INVALID_FLAGS or ERROR_INVALID_PARAMETER instead of %d\n", 56 GetLastError()); 57 58 SetLastError(0xdeadbeef); 59 ret = pCredReadA(NULL, CRED_TYPE_GENERIC, 0, &cred); 60 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 61 "CredReadA should have failed with ERROR_INVALID_PARAMETER instead of %d\n", 62 GetLastError()); 63 } 64 65 static void test_CredWriteA(void) 66 { 67 CREDENTIALA new_cred; 68 BOOL ret; 69 70 SetLastError(0xdeadbeef); 71 ret = pCredWriteA(NULL, 0); 72 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 73 "CredWriteA should have failed with ERROR_INVALID_PARAMETER instead of %d\n", 74 GetLastError()); 75 76 new_cred.Flags = 0; 77 new_cred.Type = CRED_TYPE_GENERIC; 78 new_cred.TargetName = NULL; 79 new_cred.Comment = (char *)"Comment"; 80 new_cred.CredentialBlobSize = 0; 81 new_cred.CredentialBlob = NULL; 82 new_cred.Persist = CRED_PERSIST_ENTERPRISE; 83 new_cred.AttributeCount = 0; 84 new_cred.Attributes = NULL; 85 new_cred.TargetAlias = NULL; 86 new_cred.UserName = (char *)"winetest"; 87 88 SetLastError(0xdeadbeef); 89 ret = pCredWriteA(&new_cred, 0); 90 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 91 "CredWriteA should have failed with ERROR_INVALID_PARAMETER instead of %d\n", 92 GetLastError()); 93 94 new_cred.TargetName = (char *)TEST_TARGET_NAME; 95 new_cred.Type = CRED_TYPE_DOMAIN_PASSWORD; 96 97 SetLastError(0xdeadbeef); 98 ret = pCredWriteA(&new_cred, 0); 99 if (ret) 100 { 101 ok(GetLastError() == ERROR_SUCCESS || 102 GetLastError() == ERROR_IO_PENDING, /* Vista */ 103 "Expected ERROR_IO_PENDING, got %d\n", GetLastError()); 104 } 105 else 106 { 107 ok(GetLastError() == ERROR_BAD_USERNAME || 108 GetLastError() == ERROR_NO_SUCH_LOGON_SESSION, /* Vista */ 109 "CredWrite with username without domain should return ERROR_BAD_USERNAME" 110 "or ERROR_NO_SUCH_LOGON_SESSION not %d\n", GetLastError()); 111 } 112 113 new_cred.UserName = NULL; 114 SetLastError(0xdeadbeef); 115 ret = pCredWriteA(&new_cred, 0); 116 ok(!ret && GetLastError() == ERROR_BAD_USERNAME, 117 "CredWriteA with NULL username should have failed with ERROR_BAD_USERNAME instead of %d\n", 118 GetLastError()); 119 120 new_cred.UserName = (char *)"winetest"; 121 new_cred.Persist = CRED_PERSIST_LOCAL_MACHINE; 122 SetLastError(0xdeadbeef); 123 ret = pCredWriteA(&new_cred, 0); 124 ok(ret || broken(!ret), "CredWriteA failed with error %u\n", GetLastError()); 125 if (ret) 126 { 127 ret = pCredDeleteA(TEST_TARGET_NAME, CRED_TYPE_DOMAIN_PASSWORD, 0); 128 ok(ret, "CredDeleteA failed with error %u\n", GetLastError()); 129 } 130 new_cred.Type = CRED_TYPE_GENERIC; 131 SetLastError(0xdeadbeef); 132 ret = pCredWriteA(&new_cred, 0); 133 ok(ret || broken(!ret), "CredWriteA failed with error %u\n", GetLastError()); 134 if (ret) 135 { 136 ret = pCredDeleteA(TEST_TARGET_NAME, CRED_TYPE_GENERIC, 0); 137 ok(ret, "CredDeleteA failed with error %u\n", GetLastError()); 138 } 139 new_cred.Persist = CRED_PERSIST_SESSION; 140 ret = pCredWriteA(&new_cred, 0); 141 ok(ret, "CredWriteA failed with error %u\n", GetLastError()); 142 143 ret = pCredDeleteA(TEST_TARGET_NAME, CRED_TYPE_GENERIC, 0); 144 ok(ret, "CredDeleteA failed with error %u\n", GetLastError()); 145 146 new_cred.Type = CRED_TYPE_DOMAIN_PASSWORD; 147 SetLastError(0xdeadbeef); 148 ret = pCredWriteA(&new_cred, 0); 149 ok(ret || broken(!ret), "CredWriteA failed with error %u\n", GetLastError()); 150 if (ret) 151 { 152 ret = pCredDeleteA(TEST_TARGET_NAME, CRED_TYPE_DOMAIN_PASSWORD, 0); 153 ok(ret, "CredDeleteA failed with error %u\n", GetLastError()); 154 } 155 new_cred.UserName = NULL; 156 SetLastError(0xdeadbeef); 157 ret = pCredWriteA(&new_cred, 0); 158 ok(!ret, "CredWriteA succeeded\n"); 159 ok(GetLastError() == ERROR_BAD_USERNAME, "got %u\n", GetLastError()); 160 } 161 162 static void test_CredDeleteA(void) 163 { 164 BOOL ret; 165 166 SetLastError(0xdeadbeef); 167 ret = pCredDeleteA(TEST_TARGET_NAME, -1, 0); 168 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 169 "CredDeleteA should have failed with ERROR_INVALID_PARAMETER instead of %d\n", 170 GetLastError()); 171 172 SetLastError(0xdeadbeef); 173 ret = pCredDeleteA(TEST_TARGET_NAME, CRED_TYPE_GENERIC, 0xdeadbeef); 174 ok(!ret && ( GetLastError() == ERROR_INVALID_FLAGS || GetLastError() == ERROR_INVALID_PARAMETER /* Vista */ ), 175 "CredDeleteA should have failed with ERROR_INVALID_FLAGS or ERROR_INVALID_PARAMETER instead of %d\n", 176 GetLastError()); 177 } 178 179 static void test_CredReadDomainCredentialsA(void) 180 { 181 BOOL ret; 182 char target_name[] = "no_such_target"; 183 CREDENTIAL_TARGET_INFORMATIONA info = {target_name, NULL, target_name, NULL, NULL, NULL, NULL, 0, 0, NULL}; 184 DWORD count; 185 PCREDENTIALA* creds; 186 187 if (!pCredReadDomainCredentialsA) 188 { 189 win_skip("CredReadDomainCredentialsA() is not implemented\n"); 190 return; 191 } 192 193 /* these two tests would crash on both native and Wine. Implementations 194 * does not check for NULL output pointers and try to zero them out early */ 195 if(0) 196 { 197 ret = pCredReadDomainCredentialsA(&info, 0, NULL, &creds); 198 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "!\n"); 199 ret = pCredReadDomainCredentialsA(&info, 0, &count, NULL); 200 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, "!\n"); 201 } 202 203 SetLastError(0xdeadbeef); 204 ret = pCredReadDomainCredentialsA(NULL, 0, &count, &creds); 205 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 206 "CredReadDomainCredentialsA should have failed with ERROR_INVALID_PARAMETER instead of %d\n", 207 GetLastError()); 208 209 SetLastError(0xdeadbeef); 210 creds = (void*)0x12345; 211 count = 2; 212 ret = pCredReadDomainCredentialsA(&info, 0, &count, &creds); 213 ok(!ret && GetLastError() == ERROR_NOT_FOUND, 214 "CredReadDomainCredentialsA should have failed with ERROR_NOT_FOUND instead of %d\n", 215 GetLastError()); 216 ok(count ==0 && creds == NULL, "CredReadDomainCredentialsA must not return any result\n"); 217 218 info.TargetName = NULL; 219 220 SetLastError(0xdeadbeef); 221 ret = pCredReadDomainCredentialsA(&info, 0, &count, &creds); 222 ok(!ret, "CredReadDomainCredentialsA should have failed\n"); 223 ok(GetLastError() == ERROR_NOT_FOUND || 224 GetLastError() == ERROR_INVALID_PARAMETER, /* Vista, W2K8 */ 225 "Expected ERROR_NOT_FOUND or ERROR_INVALID_PARAMETER instead of %d\n", 226 GetLastError()); 227 228 info.DnsServerName = NULL; 229 230 SetLastError(0xdeadbeef); 231 ret = pCredReadDomainCredentialsA(&info, 0, &count, &creds); 232 ok(!ret, "CredReadDomainCredentialsA should have failed\n"); 233 ok(GetLastError() == ERROR_NOT_FOUND || 234 GetLastError() == ERROR_INVALID_PARAMETER, /* Vista, W2K8 */ 235 "Expected ERROR_NOT_FOUND or ERROR_INVALID_PARAMETER instead of %d\n", 236 GetLastError()); 237 } 238 239 static void check_blob(int line, DWORD cred_type, PCREDENTIALA cred) 240 { 241 if (cred_type == CRED_TYPE_DOMAIN_PASSWORD) 242 { 243 todo_ros 244 ok_(__FILE__, line)(cred->CredentialBlobSize == 0, "expected CredentialBlobSize of 0 but got %d\n", cred->CredentialBlobSize); 245 todo_ros 246 ok_(__FILE__, line)(!cred->CredentialBlob, "expected NULL credentials but got %p\n", cred->CredentialBlob); 247 } 248 else 249 { 250 DWORD size=sizeof(TEST_PASSWORD); 251 ok_(__FILE__, line)(cred->CredentialBlobSize == size, "expected CredentialBlobSize of %u but got %u\n", size, cred->CredentialBlobSize); 252 ok_(__FILE__, line)(cred->CredentialBlob != NULL, "CredentialBlob should be present\n"); 253 if (cred->CredentialBlob) 254 ok_(__FILE__, line)(!memcmp(cred->CredentialBlob, TEST_PASSWORD, size), "wrong CredentialBlob\n"); 255 } 256 } 257 258 static void test_generic(void) 259 { 260 BOOL ret; 261 DWORD count, i; 262 PCREDENTIALA *creds; 263 CREDENTIALA new_cred; 264 PCREDENTIALA cred; 265 BOOL found = FALSE; 266 267 new_cred.Flags = 0; 268 new_cred.Type = CRED_TYPE_GENERIC; 269 new_cred.TargetName = (char *)TEST_TARGET_NAME; 270 new_cred.Comment = (char *)"Comment"; 271 new_cred.CredentialBlobSize = sizeof(TEST_PASSWORD); 272 new_cred.CredentialBlob = (LPBYTE)TEST_PASSWORD; 273 new_cred.Persist = CRED_PERSIST_ENTERPRISE; 274 new_cred.AttributeCount = 0; 275 new_cred.Attributes = NULL; 276 new_cred.TargetAlias = NULL; 277 new_cred.UserName = (char *)"winetest"; 278 279 ret = pCredWriteA(&new_cred, 0); 280 ok(ret || broken(GetLastError() == ERROR_NO_SUCH_LOGON_SESSION), 281 "CredWriteA failed with error %d\n", GetLastError()); 282 if (!ret) 283 { 284 skip("couldn't write generic credentials, skipping tests\n"); 285 return; 286 } 287 288 ret = pCredEnumerateA(NULL, 0, &count, &creds); 289 ok(ret, "CredEnumerateA failed with error %d\n", GetLastError()); 290 291 for (i = 0; i < count; i++) 292 { 293 if (creds[i]->TargetName && !strcmp(creds[i]->TargetName, TEST_TARGET_NAME)) 294 { 295 ok(creds[i]->Type == CRED_TYPE_GENERIC || 296 creds[i]->Type == CRED_TYPE_DOMAIN_PASSWORD, /* Vista */ 297 "expected creds[%d]->Type CRED_TYPE_GENERIC or CRED_TYPE_DOMAIN_PASSWORD but got %d\n", i, creds[i]->Type); 298 ok(!creds[i]->Flags, "expected creds[%d]->Flags 0 but got 0x%x\n", i, creds[i]->Flags); 299 ok(!strcmp(creds[i]->Comment, "Comment"), "expected creds[%d]->Comment \"Comment\" but got \"%s\"\n", i, creds[i]->Comment); 300 check_blob(__LINE__, creds[i]->Type, creds[i]); 301 ok(creds[i]->Persist, "expected creds[%d]->Persist CRED_PERSIST_ENTERPRISE but got %d\n", i, creds[i]->Persist); 302 ok(!strcmp(creds[i]->UserName, "winetest"), "expected creds[%d]->UserName \"winetest\" but got \"%s\"\n", i, creds[i]->UserName); 303 found = TRUE; 304 } 305 } 306 pCredFree(creds); 307 ok(found, "credentials not found\n"); 308 309 ret = pCredReadA(TEST_TARGET_NAME, CRED_TYPE_GENERIC, 0, &cred); 310 ok(ret, "CredReadA failed with error %d\n", GetLastError()); 311 pCredFree(cred); 312 313 ret = pCredDeleteA(TEST_TARGET_NAME, CRED_TYPE_GENERIC, 0); 314 ok(ret, "CredDeleteA failed with error %d\n", GetLastError()); 315 } 316 317 static void test_domain_password(DWORD cred_type) 318 { 319 BOOL ret; 320 DWORD count, i; 321 PCREDENTIALA *creds; 322 CREDENTIALA new_cred; 323 PCREDENTIALA cred; 324 BOOL found = FALSE; 325 326 new_cred.Flags = 0; 327 new_cred.Type = cred_type; 328 new_cred.TargetName = (char *)TEST_TARGET_NAME; 329 new_cred.Comment = (char *)"Comment"; 330 new_cred.CredentialBlobSize = sizeof(TEST_PASSWORD); 331 new_cred.CredentialBlob = (LPBYTE)TEST_PASSWORD; 332 new_cred.Persist = CRED_PERSIST_ENTERPRISE; 333 new_cred.AttributeCount = 0; 334 new_cred.Attributes = NULL; 335 new_cred.TargetAlias = NULL; 336 new_cred.UserName = (char *)"test\\winetest"; 337 ret = pCredWriteA(&new_cred, 0); 338 if (!ret && GetLastError() == ERROR_NO_SUCH_LOGON_SESSION) 339 { 340 skip("CRED_TYPE_DOMAIN_PASSWORD credentials are not supported " 341 "or are disabled. Skipping\n"); 342 return; 343 } 344 ok(ret, "CredWriteA failed with error %d\n", GetLastError()); 345 346 ret = pCredEnumerateA(NULL, 0, &count, &creds); 347 ok(ret, "CredEnumerateA failed with error %d\n", GetLastError()); 348 349 for (i = 0; i < count; i++) 350 { 351 if (creds[i]->TargetName && !strcmp(creds[i]->TargetName, TEST_TARGET_NAME)) 352 { 353 ok(creds[i]->Type == cred_type, "expected creds[%d]->Type CRED_TYPE_DOMAIN_PASSWORD but got %d\n", i, creds[i]->Type); 354 ok(!creds[i]->Flags, "expected creds[%d]->Flags 0 but got 0x%x\n", i, creds[i]->Flags); 355 ok(!strcmp(creds[i]->Comment, "Comment"), "expected creds[%d]->Comment \"Comment\" but got \"%s\"\n", i, creds[i]->Comment); 356 check_blob(__LINE__, cred_type, creds[i]); 357 ok(creds[i]->Persist, "expected creds[%d]->Persist CRED_PERSIST_ENTERPRISE but got %d\n", i, creds[i]->Persist); 358 ok(!strcmp(creds[i]->UserName, "test\\winetest"), "expected creds[%d]->UserName \"winetest\" but got \"%s\"\n", i, creds[i]->UserName); 359 found = TRUE; 360 } 361 } 362 pCredFree(creds); 363 ok(found, "credentials not found\n"); 364 365 ret = pCredReadA(TEST_TARGET_NAME, cred_type, 0, &cred); 366 ok(ret, "CredReadA failed with error %d\n", GetLastError()); 367 if (ret) /* don't check the values of cred, if CredReadA failed. */ 368 { 369 check_blob(__LINE__, cred_type, cred); 370 pCredFree(cred); 371 } 372 373 ret = pCredDeleteA(TEST_TARGET_NAME, cred_type, 0); 374 ok(ret, "CredDeleteA failed with error %d\n", GetLastError()); 375 } 376 377 static void test_CredMarshalCredentialA(void) 378 { 379 static WCHAR emptyW[] = {0}; 380 static WCHAR tW[] = {'t',0}; 381 static WCHAR teW[] = {'t','e',0}; 382 static WCHAR tesW[] = {'t','e','s',0}; 383 static WCHAR testW[] = {'t','e','s','t',0}; 384 static WCHAR test1W[] = {'t','e','s','t','1',0}; 385 CERT_CREDENTIAL_INFO cert; 386 USERNAME_TARGET_CREDENTIAL_INFO username; 387 DWORD error; 388 char *str; 389 BOOL ret; 390 391 SetLastError( 0xdeadbeef ); 392 ret = pCredMarshalCredentialA( 0, NULL, NULL ); 393 error = GetLastError(); 394 ok( !ret, "unexpected success\n" ); 395 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error ); 396 397 memset( cert.rgbHashOfCert, 0, sizeof(cert.rgbHashOfCert) ); 398 cert.cbSize = sizeof(cert); 399 SetLastError( 0xdeadbeef ); 400 ret = pCredMarshalCredentialA( 0, &cert, NULL ); 401 error = GetLastError(); 402 ok( !ret, "unexpected success\n" ); 403 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error ); 404 405 str = (char *)0xdeadbeef; 406 SetLastError( 0xdeadbeef ); 407 ret = pCredMarshalCredentialA( 0, &cert, &str ); 408 error = GetLastError(); 409 ok( !ret, "unexpected success\n" ); 410 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error ); 411 ok( str == (char *)0xdeadbeef, "got %p\n", str ); 412 413 SetLastError( 0xdeadbeef ); 414 ret = pCredMarshalCredentialA( CertCredential, NULL, NULL ); 415 error = GetLastError(); 416 ok( !ret, "unexpected success\n" ); 417 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error ); 418 419 if (0) { /* crash */ 420 SetLastError( 0xdeadbeef ); 421 ret = pCredMarshalCredentialA( CertCredential, &cert, NULL ); 422 error = GetLastError(); 423 ok( !ret, "unexpected success\n" ); 424 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error ); 425 } 426 427 cert.cbSize = 0; 428 str = (char *)0xdeadbeef; 429 SetLastError( 0xdeadbeef ); 430 ret = pCredMarshalCredentialA( CertCredential, &cert, &str ); 431 error = GetLastError(); 432 ok( !ret, "unexpected success\n" ); 433 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error ); 434 ok( str == (char *)0xdeadbeef, "got %p\n", str ); 435 436 cert.cbSize = sizeof(cert) + 4; 437 str = NULL; 438 ret = pCredMarshalCredentialA( CertCredential, &cert, &str ); 439 ok( ret, "unexpected failure %u\n", GetLastError() ); 440 ok( str != NULL, "str not set\n" ); 441 ok( !lstrcmpA( str, "@@BAAAAAAAAAAAAAAAAAAAAAAAAAAA" ), "got %s\n", str ); 442 pCredFree( str ); 443 444 cert.cbSize = sizeof(cert); 445 cert.rgbHashOfCert[0] = 2; 446 str = NULL; 447 ret = pCredMarshalCredentialA( CertCredential, &cert, &str ); 448 ok( ret, "unexpected failure %u\n", GetLastError() ); 449 ok( str != NULL, "str not set\n" ); 450 ok( !lstrcmpA( str, "@@BCAAAAAAAAAAAAAAAAAAAAAAAAAA" ), "got %s\n", str ); 451 pCredFree( str ); 452 453 cert.rgbHashOfCert[0] = 255; 454 str = NULL; 455 ret = pCredMarshalCredentialA( CertCredential, &cert, &str ); 456 ok( ret, "unexpected failure %u\n", GetLastError() ); 457 ok( str != NULL, "str not set\n" ); 458 ok( !lstrcmpA( str, "@@B-DAAAAAAAAAAAAAAAAAAAAAAAAA" ), "got %s\n", str ); 459 pCredFree( str ); 460 461 cert.rgbHashOfCert[0] = 1; 462 cert.rgbHashOfCert[1] = 1; 463 str = NULL; 464 ret = pCredMarshalCredentialA( CertCredential, &cert, &str ); 465 ok( ret, "unexpected failure %u\n", GetLastError() ); 466 ok( str != NULL, "str not set\n" ); 467 ok( !lstrcmpA( str, "@@BBEAAAAAAAAAAAAAAAAAAAAAAAAA" ), "got %s\n", str ); 468 pCredFree( str ); 469 470 cert.rgbHashOfCert[0] = 1; 471 cert.rgbHashOfCert[1] = 1; 472 cert.rgbHashOfCert[2] = 1; 473 str = NULL; 474 ret = pCredMarshalCredentialA( CertCredential, &cert, &str ); 475 ok( ret, "unexpected failure %u\n", GetLastError() ); 476 ok( str != NULL, "str not set\n" ); 477 ok( !lstrcmpA( str, "@@BBEQAAAAAAAAAAAAAAAAAAAAAAAA" ), "got %s\n", str ); 478 pCredFree( str ); 479 480 memset( cert.rgbHashOfCert, 0, sizeof(cert.rgbHashOfCert) ); 481 cert.rgbHashOfCert[0] = 'W'; 482 cert.rgbHashOfCert[1] = 'i'; 483 cert.rgbHashOfCert[2] = 'n'; 484 cert.rgbHashOfCert[3] = 'e'; 485 str = NULL; 486 ret = pCredMarshalCredentialA( CertCredential, &cert, &str ); 487 ok( ret, "unexpected failure %u\n", GetLastError() ); 488 ok( str != NULL, "str not set\n" ); 489 ok( !lstrcmpA( str, "@@BXlmblBAAAAAAAAAAAAAAAAAAAAA" ), "got %s\n", str ); 490 pCredFree( str ); 491 492 memset( cert.rgbHashOfCert, 0xff, sizeof(cert.rgbHashOfCert) ); 493 str = NULL; 494 ret = pCredMarshalCredentialA( CertCredential, &cert, &str ); 495 ok( ret, "unexpected failure %u\n", GetLastError() ); 496 ok( str != NULL, "str not set\n" ); 497 ok( !lstrcmpA( str, "@@B--------------------------P" ), "got %s\n", str ); 498 pCredFree( str ); 499 500 username.UserName = NULL; 501 str = (char *)0xdeadbeef; 502 SetLastError( 0xdeadbeef ); 503 ret = pCredMarshalCredentialA( UsernameTargetCredential, &username, &str ); 504 error = GetLastError(); 505 ok( !ret, "unexpected success\n" ); 506 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error ); 507 ok( str == (char *)0xdeadbeef, "got %p\n", str ); 508 509 username.UserName = emptyW; 510 str = (char *)0xdeadbeef; 511 SetLastError( 0xdeadbeef ); 512 ret = pCredMarshalCredentialA( UsernameTargetCredential, &username, &str ); 513 error = GetLastError(); 514 ok( !ret, "unexpected success\n" ); 515 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error ); 516 ok( str == (char *)0xdeadbeef, "got %p\n", str ); 517 518 username.UserName = tW; 519 str = NULL; 520 ret = pCredMarshalCredentialA( UsernameTargetCredential, &username, &str ); 521 ok( ret, "unexpected failure %u\n", GetLastError() ); 522 ok( str != NULL, "str not set\n" ); 523 ok( !lstrcmpA( str, "@@CCAAAAA0BA" ), "got %s\n", str ); 524 pCredFree( str ); 525 526 username.UserName = teW; 527 str = NULL; 528 ret = pCredMarshalCredentialA( UsernameTargetCredential, &username, &str ); 529 ok( ret, "unexpected failure %u\n", GetLastError() ); 530 ok( str != NULL, "str not set\n" ); 531 ok( !lstrcmpA( str, "@@CEAAAAA0BQZAA" ), "got %s\n", str ); 532 pCredFree( str ); 533 534 username.UserName = tesW; 535 str = NULL; 536 ret = pCredMarshalCredentialA( UsernameTargetCredential, &username, &str ); 537 ok( ret, "unexpected failure %u\n", GetLastError() ); 538 ok( str != NULL, "str not set\n" ); 539 ok( !lstrcmpA( str, "@@CGAAAAA0BQZAMHA" ), "got %s\n", str ); 540 pCredFree( str ); 541 542 username.UserName = testW; 543 str = NULL; 544 ret = pCredMarshalCredentialA( UsernameTargetCredential, &username, &str ); 545 ok( ret, "unexpected failure %u\n", GetLastError() ); 546 ok( str != NULL, "str not set\n" ); 547 ok( !lstrcmpA( str, "@@CIAAAAA0BQZAMHA0BA" ), "got %s\n", str ); 548 pCredFree( str ); 549 550 username.UserName = test1W; 551 str = NULL; 552 ret = pCredMarshalCredentialA( UsernameTargetCredential, &username, &str ); 553 ok( ret, "unexpected failure %u\n", GetLastError() ); 554 ok( str != NULL, "str not set\n" ); 555 ok( !lstrcmpA( str, "@@CKAAAAA0BQZAMHA0BQMAA" ), "got %s\n", str ); 556 pCredFree( str ); 557 } 558 559 static void test_CredUnmarshalCredentialA(void) 560 { 561 static const UCHAR cert_empty[CERT_HASH_LENGTH] = {0}; 562 static const UCHAR cert_wine[CERT_HASH_LENGTH] = {'W','i','n','e',0}; 563 static const WCHAR tW[] = {'t',0}; 564 static const WCHAR teW[] = {'t','e',0}; 565 static const WCHAR tesW[] = {'t','e','s',0}; 566 static const WCHAR testW[] = {'t','e','s','t',0}; 567 void *p; 568 CERT_CREDENTIAL_INFO *cert; 569 const UCHAR *hash; 570 USERNAME_TARGET_CREDENTIAL_INFO *username; 571 CRED_MARSHAL_TYPE type; 572 unsigned int i, j; 573 DWORD error; 574 BOOL ret; 575 const struct { 576 const char *cred; 577 CRED_MARSHAL_TYPE type; 578 const void *unmarshaled; 579 } tests[] = { 580 { "", 0, NULL }, 581 { "@", 0, NULL }, 582 { "@@", 0, NULL }, 583 { "@@@", 0, NULL }, 584 { "@@A", 0, NULL }, 585 { "@@E", 4, NULL }, 586 { "@@Z", 25, NULL }, 587 { "@@a", 26, NULL }, 588 { "@@0", 52, NULL }, 589 { "@@#", 62, NULL }, 590 { "@@-", 63, NULL }, 591 { "@@B", CertCredential, NULL }, 592 { "@@BA", CertCredential, NULL }, 593 { "@@BAAAAAAAAAAAAAAAAAAAAAAAAAA", CertCredential, NULL }, 594 { "@@BAAAAAAAAAAAAAAAAAAAAAAAAAAAA", CertCredential, NULL }, 595 { "@@BAAAAAAAAAAAAAAAAAAAAAAAAAAA", CertCredential, cert_empty }, 596 { "@@BXlmblBAAAAAAAAAAAAAAAAAAAAA", CertCredential, cert_wine }, 597 { "@@C", UsernameTargetCredential, NULL }, 598 { "@@CA", UsernameTargetCredential, NULL }, 599 { "@@CAAAAAA", UsernameTargetCredential, NULL }, 600 { "@@CAAAAAA0B", UsernameTargetCredential, NULL }, 601 { "@@CAAAAAA0BA", UsernameTargetCredential, NULL }, 602 { "@@CCAAAAA0BA", UsernameTargetCredential, tW }, 603 { "@@CEAAAAA0BA", UsernameTargetCredential, NULL }, 604 { "@@CEAAAAA0BAd", UsernameTargetCredential, NULL }, 605 { "@@CEAAAAA0BAdA", UsernameTargetCredential, NULL }, 606 { "@@CEAAAAA0BQZAA", UsernameTargetCredential, teW }, 607 { "@@CEAAAAA0BQZAQ", UsernameTargetCredential, teW }, 608 { "@@CEAAAAA0BQZAg", UsernameTargetCredential, teW }, 609 { "@@CEAAAAA0BQZAw", UsernameTargetCredential, teW }, 610 { "@@CEAAAAA0BQZAAA", UsernameTargetCredential, NULL }, 611 { "@@CGAAAAA0BQZAMH", UsernameTargetCredential, NULL }, 612 { "@@CGAAAAA0BQZAMHA", UsernameTargetCredential, tesW }, 613 { "@@CGAAAAA0BQZAMHAA", UsernameTargetCredential, NULL }, 614 { "@@CCAAAAA0BAA", UsernameTargetCredential, NULL }, 615 { "@@CBAAAAA0BAA", UsernameTargetCredential, NULL }, 616 { "@@CAgAAAA0BAA", UsernameTargetCredential, NULL }, 617 { "@@CIAAAAA0BQZAMHA0BA", UsernameTargetCredential, testW }, 618 { "@@CA-----0BQZAMHA0BA", UsernameTargetCredential, NULL }, 619 }; 620 621 SetLastError( 0xdeadbeef ); 622 ret = pCredUnmarshalCredentialA( NULL, NULL, NULL ); 623 error = GetLastError(); 624 ok( !ret, "unexpected success\n" ); 625 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error ); 626 627 cert = NULL; 628 SetLastError( 0xdeadbeef ); 629 ret = pCredUnmarshalCredentialA( NULL, NULL, (void **)&cert ); 630 error = GetLastError(); 631 ok( !ret, "unexpected success\n" ); 632 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error ); 633 634 type = 0; 635 cert = NULL; 636 SetLastError( 0xdeadbeef ); 637 ret = pCredUnmarshalCredentialA( NULL, &type, (void **)&cert ); 638 error = GetLastError(); 639 ok( !ret, "unexpected success\n" ); 640 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error ); 641 642 if (0) { /* crash */ 643 SetLastError( 0xdeadbeef ); 644 ret = pCredUnmarshalCredentialA( "@@BAAAAAAAAAAAAAAAAAAAAAAAAAAA", &type, NULL ); 645 error = GetLastError(); 646 ok( !ret, "unexpected success\n" ); 647 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error ); 648 649 SetLastError( 0xdeadbeef ); 650 ret = pCredUnmarshalCredentialA( "@@BAAAAAAAAAAAAAAAAAAAAAAAAAAA", NULL, (void **)&cert ); 651 error = GetLastError(); 652 ok( !ret, "unexpected success\n" ); 653 ok( error == ERROR_INVALID_PARAMETER, "got %u\n", error ); 654 } 655 656 for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) 657 { 658 SetLastError(0xdeadbeef); 659 type = 0; 660 p = NULL; 661 ret = pCredUnmarshalCredentialA(tests[i].cred, &type, &p); 662 error = GetLastError(); 663 if (tests[i].unmarshaled) 664 { 665 ok(ret, "[%u] unexpected failure %u\n", i, error); 666 ok(type == tests[i].type, "[%u] got %u\n", i, type); 667 ok(p != NULL, "[%u] returned pointer is NULL\n", i); 668 if (tests[i].type == CertCredential) 669 { 670 cert = p; 671 hash = tests[i].unmarshaled; 672 ok(cert->cbSize == sizeof(*cert), 673 "[%u] wrong size %u\n", i, cert->cbSize); 674 for (j = 0; j < sizeof(cert->rgbHashOfCert); j++) 675 ok(cert->rgbHashOfCert[j] == hash[j], "[%u] wrong data\n", i); 676 } 677 else if (tests[i].type == UsernameTargetCredential) 678 { 679 username = p; 680 ok(username->UserName != NULL, "[%u] UserName is NULL\n", i); 681 ok(!lstrcmpW(username->UserName, tests[i].unmarshaled), 682 "[%u] got %s\n", i, wine_dbgstr_w(username->UserName)); 683 } 684 } 685 else 686 { 687 ok(!ret, "[%u] unexpected success\n", i); 688 ok(error == ERROR_INVALID_PARAMETER, "[%u] got %u\n", i, error); 689 ok(type == tests[i].type, "[%u] got %u\n", i, type); 690 ok(p == NULL, "[%u] returned pointer is not NULL\n", i); 691 } 692 693 if (ret) 694 pCredFree(p); 695 } 696 } 697 698 static void test_CredIsMarshaledCredentialA(void) 699 { 700 int i; 701 BOOL res; 702 BOOL expected = TRUE; 703 704 const char * ptr[] = { 705 /* CertCredential */ 706 "@@BXlmblBAAAAAAAAAAAAAAAAAAAAA", /* hash for 'W','i','n','e' */ 707 "@@BAAAAAAAAAAAAAAAAAAAAAAAAAAA", /* hash for all 0 */ 708 709 /* UsernameTargetCredential */ 710 "@@CCAAAAA0BA", /* "t" */ 711 "@@CIAAAAA0BQZAMHA0BA", /* "test" */ 712 713 /* todo: BinaryBlobCredential */ 714 715 /* not marshaled names return always FALSE */ 716 "winetest", 717 "", 718 "@@", 719 "@@A", 720 "@@AA", 721 "@@AAA", 722 "@@B", 723 "@@BB", 724 "@@BBB", 725 726 /* CertCredential */ 727 "@@BAAAAAAAAAAAAAAAAAAAAAAAAAAAA", /* to long */ 728 "@@BAAAAAAAAAAAAAAAAAAAAAAAAAA", /* to short */ 729 "@@BAAAAAAAAAAAAAAAAAAAAAAAAAA+", /* bad char */ 730 "@@BAAAAAAAAAAAAAAAAAAAAAAAAAA:", 731 "@@BAAAAAAAAAAAAAAAAAAAAAAAAAA>", 732 "@@BAAAAAAAAAAAAAAAAAAAAAAAAAA<", 733 734 "@@C", 735 "@@CC", 736 "@@CCC", 737 "@@D", 738 "@@DD", 739 "@@DDD", 740 NULL}; 741 742 for (i = 0; ptr[i]; i++) 743 { 744 if (*ptr[i] != '@') 745 expected = FALSE; 746 747 SetLastError(0xdeadbeef); 748 res = pCredIsMarshaledCredentialA(ptr[i]); 749 if (expected) 750 ok(res != FALSE, "%d: got %d and %u for %s (expected TRUE)\n", i, res, GetLastError(), ptr[i]); 751 else 752 { 753 /* Windows returns ERROR_INVALID_PARAMETER here, but that's not documented */ 754 ok(!res, "%d: got %d and %u for %s (expected FALSE)\n", i, res, GetLastError(), ptr[i]); 755 } 756 } 757 } 758 759 START_TEST(cred) 760 { 761 DWORD persists[CRED_TYPE_MAXIMUM]; 762 HMODULE mod = GetModuleHandleA("advapi32.dll"); 763 764 pCredEnumerateA = (void *)GetProcAddress(mod, "CredEnumerateA"); 765 pCredFree = (void *)GetProcAddress(mod, "CredFree"); 766 pCredGetSessionTypes = (void *)GetProcAddress(mod, "CredGetSessionTypes"); 767 pCredWriteA = (void *)GetProcAddress(mod, "CredWriteA"); 768 pCredDeleteA = (void *)GetProcAddress(mod, "CredDeleteA"); 769 pCredReadA = (void *)GetProcAddress(mod, "CredReadA"); 770 pCredRenameA = (void *)GetProcAddress(mod, "CredRenameA"); 771 pCredReadDomainCredentialsA = (void *)GetProcAddress(mod, "CredReadDomainCredentialsA"); 772 pCredMarshalCredentialA = (void *)GetProcAddress(mod, "CredMarshalCredentialA"); 773 pCredUnmarshalCredentialA = (void *)GetProcAddress(mod, "CredUnmarshalCredentialA"); 774 pCredIsMarshaledCredentialA = (void *)GetProcAddress(mod, "CredIsMarshaledCredentialA"); 775 776 if (!pCredEnumerateA || !pCredFree || !pCredWriteA || !pCredDeleteA || !pCredReadA) 777 { 778 win_skip("credentials functions not present in advapi32.dll\n"); 779 return; 780 } 781 782 if (pCredGetSessionTypes) 783 { 784 BOOL ret; 785 DWORD i; 786 ret = pCredGetSessionTypes(CRED_TYPE_MAXIMUM, persists); 787 ok(ret, "CredGetSessionTypes failed with error %d\n", GetLastError()); 788 ok(persists[0] == CRED_PERSIST_NONE, "persists[0] = %u instead of CRED_PERSIST_NONE\n", persists[0]); 789 for (i=0; i < CRED_TYPE_MAXIMUM; i++) 790 ok(persists[i] <= CRED_PERSIST_ENTERPRISE, "bad value for persists[%u]: %u\n", i, persists[i]); 791 } 792 else 793 memset(persists, CRED_PERSIST_ENTERPRISE, sizeof(persists)); 794 795 test_CredReadA(); 796 test_CredWriteA(); 797 test_CredDeleteA(); 798 799 test_CredReadDomainCredentialsA(); 800 801 trace("generic:\n"); 802 if (persists[CRED_TYPE_GENERIC] == CRED_PERSIST_NONE) 803 skip("CRED_TYPE_GENERIC credentials are not supported or are disabled. Skipping\n"); 804 else 805 test_generic(); 806 807 trace("domain password:\n"); 808 if (persists[CRED_TYPE_DOMAIN_PASSWORD] == CRED_PERSIST_NONE) 809 skip("CRED_TYPE_DOMAIN_PASSWORD credentials are not supported or are disabled. Skipping\n"); 810 else 811 test_domain_password(CRED_TYPE_DOMAIN_PASSWORD); 812 813 trace("domain visible password:\n"); 814 if (persists[CRED_TYPE_DOMAIN_VISIBLE_PASSWORD] == CRED_PERSIST_NONE) 815 skip("CRED_TYPE_DOMAIN_VISIBLE_PASSWORD credentials are not supported or are disabled. Skipping\n"); 816 else 817 test_domain_password(CRED_TYPE_DOMAIN_VISIBLE_PASSWORD); 818 819 test_CredMarshalCredentialA(); 820 test_CredUnmarshalCredentialA(); 821 test_CredIsMarshaledCredentialA(); 822 } 823