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