2 * Credential Management APIs
4 * Copyright 2007 Robert Shearman for CodeWeavers
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.
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.
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
31 #include "wine/unicode.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(cred
);
36 /* the size of the ARC4 key used to encrypt the password data */
39 static const WCHAR wszCredentialManagerKey
[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
40 'C','r','e','d','e','n','t','i','a','l',' ','M','a','n','a','g','e','r',0};
41 static const WCHAR wszEncryptionKeyValue
[] = {'E','n','c','r','y','p','t','i','o','n','K','e','y',0};
43 static const WCHAR wszFlagsValue
[] = {'F','l','a','g','s',0};
44 static const WCHAR wszTypeValue
[] = {'T','y','p','e',0};
45 static const WCHAR wszTargetNameValue
[] = {'T','a','r','g','e','t','N','a','m','e',0};
46 static const WCHAR wszCommentValue
[] = {'C','o','m','m','e','n','t',0};
47 static const WCHAR wszLastWrittenValue
[] = {'L','a','s','t','W','r','i','t','t','e','n',0};
48 static const WCHAR wszPersistValue
[] = {'P','e','r','s','i','s','t',0};
49 static const WCHAR wszTargetAliasValue
[] = {'T','a','r','g','e','t','A','l','i','a','s',0};
50 static const WCHAR wszUserNameValue
[] = {'U','s','e','r','N','a','m','e',0};
51 static const WCHAR wszPasswordValue
[] = {'P','a','s','s','w','o','r','d',0};
53 static DWORD
read_credential_blob(HKEY hkey
, const BYTE key_data
[KEY_SIZE
],
54 LPBYTE credential_blob
,
55 DWORD
*credential_blob_size
)
60 *credential_blob_size
= 0;
61 ret
= RegQueryValueExW(hkey
, wszPasswordValue
, 0, &type
, NULL
, credential_blob_size
);
62 if (ret
!= ERROR_SUCCESS
)
64 else if (type
!= REG_BINARY
)
65 return ERROR_REGISTRY_CORRUPT
;
71 ret
= RegQueryValueExW(hkey
, wszPasswordValue
, 0, &type
, (LPVOID
)credential_blob
,
72 credential_blob_size
);
73 if (ret
!= ERROR_SUCCESS
)
75 else if (type
!= REG_BINARY
)
76 return ERROR_REGISTRY_CORRUPT
;
78 key
.Length
= key
.MaximumLength
= sizeof(key_data
);
79 key
.Buffer
= (unsigned char *)key_data
;
81 data
.Length
= data
.MaximumLength
= *credential_blob_size
;
82 data
.Buffer
= credential_blob
;
83 SystemFunction032(&data
, &key
);
88 static DWORD
read_credential(HKEY hkey
, PCREDENTIALW credential
,
89 const BYTE key_data
[KEY_SIZE
], char *buffer
, DWORD
*len
)
95 ret
= RegQueryValueExW(hkey
, NULL
, 0, &type
, NULL
, &count
);
96 if (ret
!= ERROR_SUCCESS
)
98 else if (type
!= REG_SZ
)
99 return ERROR_REGISTRY_CORRUPT
;
103 credential
->TargetName
= (LPWSTR
)buffer
;
104 ret
= RegQueryValueExW(hkey
, NULL
, 0, &type
, (LPVOID
)credential
->TargetName
,
106 if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
) return ret
;
110 ret
= RegQueryValueExW(hkey
, wszCommentValue
, 0, &type
, NULL
, &count
);
111 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
113 else if (type
!= REG_SZ
)
114 return ERROR_REGISTRY_CORRUPT
;
118 credential
->Comment
= (LPWSTR
)buffer
;
119 ret
= RegQueryValueExW(hkey
, wszCommentValue
, 0, &type
, (LPVOID
)credential
->Comment
,
121 if (ret
== ERROR_FILE_NOT_FOUND
)
122 credential
->Comment
= NULL
;
123 else if (ret
!= ERROR_SUCCESS
)
125 else if (type
!= REG_SZ
)
126 return ERROR_REGISTRY_CORRUPT
;
131 ret
= RegQueryValueExW(hkey
, wszTargetAliasValue
, 0, &type
, NULL
, &count
);
132 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
134 else if (type
!= REG_SZ
)
135 return ERROR_REGISTRY_CORRUPT
;
139 credential
->TargetAlias
= (LPWSTR
)buffer
;
140 ret
= RegQueryValueExW(hkey
, wszTargetAliasValue
, 0, &type
, (LPVOID
)credential
->TargetAlias
,
142 if (ret
== ERROR_FILE_NOT_FOUND
)
143 credential
->TargetAlias
= NULL
;
144 else if (ret
!= ERROR_SUCCESS
)
146 else if (type
!= REG_SZ
)
147 return ERROR_REGISTRY_CORRUPT
;
152 ret
= RegQueryValueExW(hkey
, wszUserNameValue
, 0, &type
, NULL
, &count
);
153 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
155 else if (type
!= REG_SZ
)
156 return ERROR_REGISTRY_CORRUPT
;
160 credential
->UserName
= (LPWSTR
)buffer
;
161 ret
= RegQueryValueExW(hkey
, wszUserNameValue
, 0, &type
, (LPVOID
)credential
->UserName
,
163 if (ret
== ERROR_FILE_NOT_FOUND
)
165 credential
->UserName
= NULL
;
168 else if (ret
!= ERROR_SUCCESS
)
170 else if (type
!= REG_SZ
)
171 return ERROR_REGISTRY_CORRUPT
;
176 ret
= read_credential_blob(hkey
, key_data
, NULL
, &count
);
177 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
182 credential
->CredentialBlob
= (LPBYTE
)buffer
;
183 ret
= read_credential_blob(hkey
, key_data
, credential
->CredentialBlob
, &count
);
184 if (ret
== ERROR_FILE_NOT_FOUND
)
186 credential
->CredentialBlob
= NULL
;
189 else if (ret
!= ERROR_SUCCESS
)
191 credential
->CredentialBlobSize
= count
;
195 /* FIXME: Attributes */
198 credential
->AttributeCount
= 0;
199 credential
->Attributes
= NULL
;
202 if (!credential
) return ERROR_SUCCESS
;
204 count
= sizeof(credential
->Flags
);
205 ret
= RegQueryValueExW(hkey
, wszFlagsValue
, NULL
, &type
, (LPVOID
)&credential
->Flags
,
207 if (ret
!= ERROR_SUCCESS
)
209 else if (type
!= REG_DWORD
)
210 return ERROR_REGISTRY_CORRUPT
;
211 count
= sizeof(credential
->Type
);
212 ret
= RegQueryValueExW(hkey
, wszTypeValue
, NULL
, &type
, (LPVOID
)&credential
->Type
,
214 if (ret
!= ERROR_SUCCESS
)
216 else if (type
!= REG_DWORD
)
217 return ERROR_REGISTRY_CORRUPT
;
219 count
= sizeof(credential
->LastWritten
);
220 ret
= RegQueryValueExW(hkey
, wszLastWrittenValue
, NULL
, &type
, (LPVOID
)&credential
->LastWritten
,
222 if (ret
!= ERROR_SUCCESS
)
224 else if (type
!= REG_BINARY
)
225 return ERROR_REGISTRY_CORRUPT
;
226 count
= sizeof(credential
->Persist
);
227 ret
= RegQueryValueExW(hkey
, wszPersistValue
, NULL
, &type
, (LPVOID
)&credential
->Persist
,
229 if (ret
== ERROR_SUCCESS
&& type
!= REG_DWORD
)
230 return ERROR_REGISTRY_CORRUPT
;
234 static DWORD
write_credential_blob(HKEY hkey
, LPCWSTR target_name
, DWORD type
,
235 const BYTE key_data
[KEY_SIZE
],
236 const BYTE
*credential_blob
, DWORD credential_blob_size
)
238 LPBYTE encrypted_credential_blob
;
243 key
.Length
= key
.MaximumLength
= sizeof(key_data
);
244 key
.Buffer
= (unsigned char *)key_data
;
246 encrypted_credential_blob
= HeapAlloc(GetProcessHeap(), 0, credential_blob_size
);
247 if (!encrypted_credential_blob
) return ERROR_OUTOFMEMORY
;
249 memcpy(encrypted_credential_blob
, credential_blob
, credential_blob_size
);
250 data
.Length
= data
.MaximumLength
= credential_blob_size
;
251 data
.Buffer
= encrypted_credential_blob
;
252 SystemFunction032(&data
, &key
);
254 ret
= RegSetValueExW(hkey
, wszPasswordValue
, 0, REG_BINARY
, (LPVOID
)encrypted_credential_blob
, credential_blob_size
);
255 HeapFree(GetProcessHeap(), 0, encrypted_credential_blob
);
260 static DWORD
write_credential(HKEY hkey
, const CREDENTIALW
*credential
,
261 const BYTE key_data
[KEY_SIZE
], BOOL preserve_blob
)
264 FILETIME LastWritten
;
266 GetSystemTimeAsFileTime(&LastWritten
);
268 ret
= RegSetValueExW(hkey
, wszFlagsValue
, 0, REG_DWORD
, (LPVOID
)&credential
->Flags
,
269 sizeof(credential
->Flags
));
270 if (ret
!= ERROR_SUCCESS
) return ret
;
271 ret
= RegSetValueExW(hkey
, wszTypeValue
, 0, REG_DWORD
, (LPVOID
)&credential
->Type
,
272 sizeof(credential
->Type
));
273 if (ret
!= ERROR_SUCCESS
) return ret
;
274 ret
= RegSetValueExW(hkey
, NULL
, 0, REG_SZ
, (LPVOID
)credential
->TargetName
,
275 sizeof(WCHAR
)*(strlenW(credential
->TargetName
)+1));
276 if (ret
!= ERROR_SUCCESS
) return ret
;
277 if (credential
->Comment
)
279 ret
= RegSetValueExW(hkey
, wszCommentValue
, 0, REG_SZ
, (LPVOID
)credential
->Comment
,
280 sizeof(WCHAR
)*(strlenW(credential
->Comment
)+1));
281 if (ret
!= ERROR_SUCCESS
) return ret
;
283 ret
= RegSetValueExW(hkey
, wszLastWrittenValue
, 0, REG_BINARY
, (LPVOID
)&LastWritten
,
284 sizeof(LastWritten
));
285 if (ret
!= ERROR_SUCCESS
) return ret
;
286 ret
= RegSetValueExW(hkey
, wszPersistValue
, 0, REG_DWORD
, (LPVOID
)&credential
->Persist
,
287 sizeof(credential
->Persist
));
288 if (ret
!= ERROR_SUCCESS
) return ret
;
289 /* FIXME: Attributes */
290 if (credential
->TargetAlias
)
292 ret
= RegSetValueExW(hkey
, wszTargetAliasValue
, 0, REG_SZ
, (LPVOID
)credential
->TargetAlias
,
293 sizeof(WCHAR
)*(strlenW(credential
->TargetAlias
)+1));
294 if (ret
!= ERROR_SUCCESS
) return ret
;
296 if (credential
->UserName
)
298 ret
= RegSetValueExW(hkey
, wszUserNameValue
, 0, REG_SZ
, (LPVOID
)credential
->UserName
,
299 sizeof(WCHAR
)*(strlenW(credential
->UserName
)+1));
300 if (ret
!= ERROR_SUCCESS
) return ret
;
304 ret
= write_credential_blob(hkey
, credential
->TargetName
, credential
->Type
,
305 key_data
, credential
->CredentialBlob
,
306 credential
->CredentialBlobSize
);
311 static DWORD
open_cred_mgr_key(HKEY
*hkey
, BOOL open_for_write
)
313 return RegCreateKeyExW(HKEY_CURRENT_USER
, wszCredentialManagerKey
, 0,
314 NULL
, REG_OPTION_NON_VOLATILE
,
315 KEY_READ
| KEY_WRITE
, NULL
, hkey
, NULL
);
318 static DWORD
get_cred_mgr_encryption_key(HKEY hkeyMgr
, BYTE key_data
[KEY_SIZE
])
320 static const BYTE my_key_data
[KEY_SIZE
] = { 0 };
328 memcpy(key_data
, my_key_data
, KEY_SIZE
);
331 ret
= RegQueryValueExW(hkeyMgr
, wszEncryptionKeyValue
, NULL
, &type
, (LPVOID
)key_data
,
333 if (ret
== ERROR_SUCCESS
)
335 if (type
!= REG_BINARY
)
336 return ERROR_REGISTRY_CORRUPT
;
338 return ERROR_SUCCESS
;
340 if (ret
!= ERROR_FILE_NOT_FOUND
)
343 GetSystemTimeAsFileTime(&ft
);
344 seed
= ft
.dwLowDateTime
;
345 value
= RtlUniform(&seed
);
346 *(DWORD
*)key_data
= value
;
347 seed
= ft
.dwHighDateTime
;
348 value
= RtlUniform(&seed
);
349 *(DWORD
*)(key_data
+ 4) = value
;
351 return RegSetValueExW(hkeyMgr
, wszEncryptionKeyValue
, 0, REG_BINARY
,
352 (LPVOID
)key_data
, KEY_SIZE
);
355 static LPWSTR
get_key_name_for_target(LPCWSTR target_name
, DWORD type
)
357 static const WCHAR wszGenericPrefix
[] = {'G','e','n','e','r','i','c',':',' ',0};
358 static const WCHAR wszDomPasswdPrefix
[] = {'D','o','m','P','a','s','s','w','d',':',' ',0};
360 LPCWSTR prefix
= NULL
;
363 len
= strlenW(target_name
);
364 if (type
== CRED_TYPE_GENERIC
)
366 prefix
= wszGenericPrefix
;
367 len
+= sizeof(wszGenericPrefix
)/sizeof(wszGenericPrefix
[0]);
371 prefix
= wszDomPasswdPrefix
;
372 len
+= sizeof(wszDomPasswdPrefix
)/sizeof(wszDomPasswdPrefix
[0]);
375 key_name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
376 if (!key_name
) return NULL
;
378 strcpyW(key_name
, prefix
);
379 strcatW(key_name
, target_name
);
381 for (p
= key_name
; *p
; p
++)
382 if (*p
== '\\') *p
= '_';
387 /******************************************************************************
388 * CredDeleteW [ADVAPI32.@]
390 BOOL WINAPI
CredDeleteW(LPCWSTR TargetName
, DWORD Type
, DWORD Flags
)
396 TRACE("(%s, %d, 0x%x)\n", debugstr_w(TargetName
), Type
, Flags
);
400 SetLastError(ERROR_INVALID_PARAMETER
);
404 if (Type
!= CRED_TYPE_GENERIC
&& Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
406 FIXME("unhandled type %d\n", Type
);
407 SetLastError(ERROR_INVALID_PARAMETER
);
413 FIXME("unhandled flags 0x%x\n", Flags
);
414 SetLastError(ERROR_INVALID_FLAGS
);
418 ret
= open_cred_mgr_key(&hkeyMgr
, TRUE
);
419 if (ret
!= ERROR_SUCCESS
)
421 WARN("couldn't open/create manager key, error %d\n", ret
);
422 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
426 key_name
= get_key_name_for_target(TargetName
, Type
);
427 ret
= RegDeleteKeyW(hkeyMgr
, key_name
);
428 HeapFree(GetProcessHeap(), 0, key_name
);
429 RegCloseKey(hkeyMgr
);
430 if (ret
!= ERROR_SUCCESS
)
432 SetLastError(ERROR_NOT_FOUND
);
439 static BOOL
credential_matches_filter(HKEY hkeyCred
, LPCWSTR filter
)
441 if (!filter
) return TRUE
;
443 FIXME("%s\n", debugstr_w(filter
));
447 /******************************************************************************
448 * CredEnumerateW [ADVAPI32.@]
450 BOOL WINAPI
CredEnumerateW(LPCWSTR Filter
, DWORD Flags
, DWORD
*Count
,
451 PCREDENTIALW
**Credentials
)
457 DWORD target_name_len
;
461 BYTE key_data
[KEY_SIZE
];
463 TRACE("(%s, 0x%x, %p, %p)\n", debugstr_w(Filter
), Flags
, Count
, Credentials
);
467 SetLastError(ERROR_INVALID_FLAGS
);
471 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
472 if (ret
!= ERROR_SUCCESS
)
474 WARN("couldn't open/create manager key, error %d\n", ret
);
475 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
479 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
480 if (ret
!= ERROR_SUCCESS
)
482 RegCloseKey(hkeyMgr
);
487 ret
= RegQueryInfoKeyW(hkeyMgr
, NULL
, NULL
, NULL
, NULL
, &target_name_len
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
488 if (ret
!= ERROR_SUCCESS
)
490 RegCloseKey(hkeyMgr
);
495 target_name
= HeapAlloc(GetProcessHeap(), 0, (target_name_len
+1)*sizeof(WCHAR
));
498 RegCloseKey(hkeyMgr
);
499 SetLastError(ERROR_OUTOFMEMORY
);
507 ret
= RegEnumKeyW(hkeyMgr
, i
, target_name
, target_name_len
+1);
508 if (ret
== ERROR_NO_MORE_ITEMS
)
513 else if (ret
!= ERROR_SUCCESS
)
518 ret
= RegOpenKeyExW(hkeyMgr
, target_name
, 0, KEY_QUERY_VALUE
, &hkeyCred
);
519 if (ret
!= ERROR_SUCCESS
)
524 if (!credential_matches_filter(hkeyCred
, Filter
))
526 RegCloseKey(hkeyCred
);
529 len
+= sizeof(CREDENTIALW
);
530 ret
= read_credential(hkeyCred
, NULL
, key_data
, NULL
, &len
);
531 RegCloseKey(hkeyCred
);
532 if (ret
!= ERROR_SUCCESS
) break;
535 if (ret
== ERROR_SUCCESS
&& *Count
== 0)
536 ret
= ERROR_NOT_FOUND
;
537 if (ret
!= ERROR_SUCCESS
)
539 HeapFree(GetProcessHeap(), 0, target_name
);
540 RegCloseKey(hkeyMgr
);
544 len
+= *Count
+ sizeof(PCREDENTIALW
);
546 if (ret
== ERROR_SUCCESS
)
548 buffer
= HeapAlloc(GetProcessHeap(), 0, len
);
549 *Credentials
= (PCREDENTIALW
*)buffer
;
552 buffer
+= *Count
* sizeof(PCREDENTIALW
);
556 ret
= RegEnumKeyW(hkeyMgr
, i
, target_name
, target_name_len
+1);
557 if (ret
== ERROR_NO_MORE_ITEMS
)
562 else if (ret
!= ERROR_SUCCESS
)
567 TRACE("target_name = %s\n", debugstr_w(target_name
));
568 ret
= RegOpenKeyExW(hkeyMgr
, target_name
, 0, KEY_QUERY_VALUE
, &hkeyCred
);
569 if (ret
!= ERROR_SUCCESS
)
574 if (!credential_matches_filter(hkeyCred
, Filter
))
576 RegCloseKey(hkeyCred
);
579 len
= sizeof(CREDENTIALW
);
580 (*Credentials
)[*Count
] = (PCREDENTIALW
)buffer
;
581 ret
= read_credential(hkeyCred
, (*Credentials
)[*Count
],
583 buffer
+ sizeof(CREDENTIALW
), &len
);
584 RegCloseKey(hkeyCred
);
585 if (ret
!= ERROR_SUCCESS
) break;
591 ret
= ERROR_OUTOFMEMORY
;
594 HeapFree(GetProcessHeap(), 0, target_name
);
595 RegCloseKey(hkeyMgr
);
597 if (ret
!= ERROR_SUCCESS
)
605 /******************************************************************************
606 * CredFree [ADVAPI32.@]
608 VOID WINAPI
CredFree(PVOID Buffer
)
610 HeapFree(GetProcessHeap(), 0, Buffer
);
613 /******************************************************************************
614 * CredReadW [ADVAPI32.@]
616 BOOL WINAPI
CredReadW(LPCWSTR TargetName
, DWORD Type
, DWORD Flags
, PCREDENTIALW
*Credential
)
623 BYTE key_data
[KEY_SIZE
];
625 TRACE("(%s, %d, 0x%x, %p)\n", debugstr_w(TargetName
), Type
, Flags
, Credential
);
629 SetLastError(ERROR_INVALID_PARAMETER
);
633 if (Type
!= CRED_TYPE_GENERIC
&& Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
635 FIXME("unhandled type %d\n", Type
);
636 SetLastError(ERROR_INVALID_PARAMETER
);
642 FIXME("unhandled flags 0x%x\n", Flags
);
643 SetLastError(ERROR_INVALID_FLAGS
);
647 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
648 if (ret
!= ERROR_SUCCESS
)
650 WARN("couldn't open/create manager key, error %d\n", ret
);
651 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
655 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
656 if (ret
!= ERROR_SUCCESS
)
658 RegCloseKey(hkeyMgr
);
663 key_name
= get_key_name_for_target(TargetName
, Type
);
664 ret
= RegOpenKeyExW(hkeyMgr
, key_name
, 0, KEY_QUERY_VALUE
, &hkeyCred
);
665 HeapFree(GetProcessHeap(), 0, key_name
);
666 if (ret
!= ERROR_SUCCESS
)
668 TRACE("credentials for target name %s not found\n", debugstr_w(TargetName
));
669 SetLastError(ERROR_NOT_FOUND
);
673 len
= sizeof(**Credential
);
674 ret
= read_credential(hkeyCred
, NULL
, key_data
, NULL
, &len
);
675 if (ret
== ERROR_SUCCESS
)
677 *Credential
= HeapAlloc(GetProcessHeap(), 0, len
);
680 len
= sizeof(**Credential
);
681 ret
= read_credential(hkeyCred
, *Credential
, key_data
,
682 (char *)(*Credential
+ 1), &len
);
685 ret
= ERROR_OUTOFMEMORY
;
688 RegCloseKey(hkeyCred
);
689 RegCloseKey(hkeyMgr
);
691 if (ret
!= ERROR_SUCCESS
)
699 /******************************************************************************
700 * CredWriteW [ADVAPI32.@]
702 BOOL WINAPI
CredWriteW(PCREDENTIALW Credential
, DWORD Flags
)
708 BYTE key_data
[KEY_SIZE
];
710 TRACE("(%p, 0x%x)\n", Credential
, Flags
);
712 if (!Credential
|| !Credential
->TargetName
)
714 SetLastError(ERROR_INVALID_PARAMETER
);
718 if (Flags
& ~CRED_PRESERVE_CREDENTIAL_BLOB
)
720 FIXME("unhandled flags 0x%x\n", Flags
);
721 SetLastError(ERROR_INVALID_FLAGS
);
725 if (Credential
->Type
!= CRED_TYPE_GENERIC
&& Credential
->Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
727 FIXME("unhandled type %d\n", Credential
->Type
);
728 SetLastError(ERROR_INVALID_PARAMETER
);
732 TRACE("Credential->TargetName = %s\n", debugstr_w(Credential
->TargetName
));
733 TRACE("Credential->UserName = %s\n", debugstr_w(Credential
->UserName
));
735 if (Credential
->Type
== CRED_TYPE_DOMAIN_PASSWORD
)
737 if (!Credential
->UserName
||
738 (!strchrW(Credential
->UserName
, '\\') && !strchrW(Credential
->UserName
, '@')))
740 ERR("bad username %s\n", debugstr_w(Credential
->UserName
));
741 SetLastError(ERROR_BAD_USERNAME
);
746 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
747 if (ret
!= ERROR_SUCCESS
)
749 WARN("couldn't open/create manager key, error %d\n", ret
);
750 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
754 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
755 if (ret
!= ERROR_SUCCESS
)
757 RegCloseKey(hkeyMgr
);
762 key_name
= get_key_name_for_target(Credential
->TargetName
, Credential
->Type
);
763 ret
= RegCreateKeyExW(hkeyMgr
, key_name
, 0, NULL
, REG_OPTION_VOLATILE
,
764 KEY_READ
|KEY_WRITE
, NULL
, &hkeyCred
, NULL
);
765 HeapFree(GetProcessHeap(), 0, key_name
);
766 if (ret
!= ERROR_SUCCESS
)
768 TRACE("credentials for target name %s not found\n",
769 debugstr_w(Credential
->TargetName
));
770 SetLastError(ERROR_NOT_FOUND
);
774 ret
= write_credential(hkeyCred
, Credential
, key_data
,
775 Flags
& CRED_PRESERVE_CREDENTIAL_BLOB
);
777 RegCloseKey(hkeyCred
);
778 RegCloseKey(hkeyMgr
);
780 if (ret
!= ERROR_SUCCESS
)