advapi32: Implement CredEnumerateW.
[wine.git] / dlls / advapi32 / cred.c
blob39d369db11dead7f0162551f9533576db48195b5
1 /*
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
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winreg.h"
26 #include "wincred.h"
27 #include "winternl.h"
29 #include "crypt.h"
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 */
37 #define KEY_SIZE 8
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)
57 DWORD ret;
58 DWORD type;
60 *credential_blob_size = 0;
61 ret = RegQueryValueExW(hkey, wszPasswordValue, 0, &type, NULL, credential_blob_size);
62 if (ret != ERROR_SUCCESS)
63 return ret;
64 else if (type != REG_BINARY)
65 return ERROR_REGISTRY_CORRUPT;
66 if (credential_blob)
68 struct ustring data;
69 struct ustring key;
71 ret = RegQueryValueExW(hkey, wszPasswordValue, 0, &type, (LPVOID)credential_blob,
72 credential_blob_size);
73 if (ret != ERROR_SUCCESS)
74 return ret;
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);
85 return ERROR_SUCCESS;
88 static DWORD read_credential(HKEY hkey, PCREDENTIALW credential,
89 const BYTE key_data[KEY_SIZE], char *buffer, DWORD *len)
91 DWORD type;
92 DWORD ret;
93 DWORD count;
95 ret = RegQueryValueExW(hkey, NULL, 0, &type, NULL, &count);
96 if (ret != ERROR_SUCCESS)
97 return ret;
98 else if (type != REG_SZ)
99 return ERROR_REGISTRY_CORRUPT;
100 *len += count;
101 if (credential)
103 credential->TargetName = (LPWSTR)buffer;
104 ret = RegQueryValueExW(hkey, NULL, 0, &type, (LPVOID)credential->TargetName,
105 &count);
106 if (ret != ERROR_SUCCESS || type != REG_SZ) return ret;
107 buffer += count;
110 ret = RegQueryValueExW(hkey, wszCommentValue, 0, &type, NULL, &count);
111 if (ret != ERROR_FILE_NOT_FOUND && ret != ERROR_SUCCESS)
112 return ret;
113 else if (type != REG_SZ)
114 return ERROR_REGISTRY_CORRUPT;
115 *len += count;
116 if (credential)
118 credential->Comment = (LPWSTR)buffer;
119 ret = RegQueryValueExW(hkey, wszCommentValue, 0, &type, (LPVOID)credential->Comment,
120 &count);
121 if (ret == ERROR_FILE_NOT_FOUND)
122 credential->Comment = NULL;
123 else if (ret != ERROR_SUCCESS)
124 return ret;
125 else if (type != REG_SZ)
126 return ERROR_REGISTRY_CORRUPT;
127 else
128 buffer += count;
131 ret = RegQueryValueExW(hkey, wszTargetAliasValue, 0, &type, NULL, &count);
132 if (ret != ERROR_FILE_NOT_FOUND && ret != ERROR_SUCCESS)
133 return ret;
134 else if (type != REG_SZ)
135 return ERROR_REGISTRY_CORRUPT;
136 *len += count;
137 if (credential)
139 credential->TargetAlias = (LPWSTR)buffer;
140 ret = RegQueryValueExW(hkey, wszTargetAliasValue, 0, &type, (LPVOID)credential->TargetAlias,
141 &count);
142 if (ret == ERROR_FILE_NOT_FOUND)
143 credential->TargetAlias = NULL;
144 else if (ret != ERROR_SUCCESS)
145 return ret;
146 else if (type != REG_SZ)
147 return ERROR_REGISTRY_CORRUPT;
148 else
149 buffer += count;
152 ret = RegQueryValueExW(hkey, wszUserNameValue, 0, &type, NULL, &count);
153 if (ret != ERROR_FILE_NOT_FOUND && ret != ERROR_SUCCESS)
154 return ret;
155 else if (type != REG_SZ)
156 return ERROR_REGISTRY_CORRUPT;
157 *len += count;
158 if (credential)
160 credential->UserName = (LPWSTR)buffer;
161 ret = RegQueryValueExW(hkey, wszUserNameValue, 0, &type, (LPVOID)credential->UserName,
162 &count);
163 if (ret == ERROR_FILE_NOT_FOUND)
165 credential->UserName = NULL;
166 ret = ERROR_SUCCESS;
168 else if (ret != ERROR_SUCCESS)
169 return ret;
170 else if (type != REG_SZ)
171 return ERROR_REGISTRY_CORRUPT;
172 else
173 buffer += count;
176 ret = read_credential_blob(hkey, key_data, NULL, &count);
177 if (ret != ERROR_FILE_NOT_FOUND && ret != ERROR_SUCCESS)
178 return ret;
179 *len += count;
180 if (credential)
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;
187 ret = ERROR_SUCCESS;
189 else if (ret != ERROR_SUCCESS)
190 return ret;
191 credential->CredentialBlobSize = count;
192 buffer += count;
195 /* FIXME: Attributes */
196 if (credential)
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,
206 &count);
207 if (ret != ERROR_SUCCESS)
208 return ret;
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,
213 &count);
214 if (ret != ERROR_SUCCESS)
215 return ret;
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,
221 &count);
222 if (ret != ERROR_SUCCESS)
223 return ret;
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,
228 &count);
229 if (ret == ERROR_SUCCESS && type != REG_DWORD)
230 return ERROR_REGISTRY_CORRUPT;
231 return ret;
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;
239 struct ustring data;
240 struct ustring key;
241 DWORD ret;
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);
257 return ret;
260 static DWORD write_credential(HKEY hkey, const CREDENTIALW *credential,
261 const BYTE key_data[KEY_SIZE], BOOL preserve_blob)
263 DWORD ret;
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;
302 if (!preserve_blob)
304 ret = write_credential_blob(hkey, credential->TargetName, credential->Type,
305 key_data, credential->CredentialBlob,
306 credential->CredentialBlobSize);
308 return ret;
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 };
321 DWORD type;
322 DWORD count;
323 FILETIME ft;
324 ULONG seed;
325 ULONG value;
326 DWORD ret;
328 memcpy(key_data, my_key_data, KEY_SIZE);
330 count = KEY_SIZE;
331 ret = RegQueryValueExW(hkeyMgr, wszEncryptionKeyValue, NULL, &type, (LPVOID)key_data,
332 &count);
333 if (ret == ERROR_SUCCESS)
335 if (type != REG_BINARY)
336 return ERROR_REGISTRY_CORRUPT;
337 else
338 return ERROR_SUCCESS;
340 if (ret != ERROR_FILE_NOT_FOUND)
341 return ret;
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};
359 INT len;
360 LPCWSTR prefix = NULL;
361 LPWSTR key_name, p;
363 len = strlenW(target_name);
364 if (type == CRED_TYPE_GENERIC)
366 prefix = wszGenericPrefix;
367 len += sizeof(wszGenericPrefix)/sizeof(wszGenericPrefix[0]);
369 else
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 = '_';
384 return key_name;
387 /******************************************************************************
388 * CredDeleteW [ADVAPI32.@]
390 BOOL WINAPI CredDeleteW(LPCWSTR TargetName, DWORD Type, DWORD Flags)
392 HKEY hkeyMgr;
393 DWORD ret;
394 LPWSTR key_name;
396 TRACE("(%s, %d, 0x%x)\n", debugstr_w(TargetName), Type, Flags);
398 if (!TargetName)
400 SetLastError(ERROR_INVALID_PARAMETER);
401 return FALSE;
404 if (Type != CRED_TYPE_GENERIC && Type != CRED_TYPE_DOMAIN_PASSWORD)
406 FIXME("unhandled type %d\n", Type);
407 SetLastError(ERROR_INVALID_PARAMETER);
408 return FALSE;
411 if (Flags)
413 FIXME("unhandled flags 0x%x\n", Flags);
414 SetLastError(ERROR_INVALID_FLAGS);
415 return FALSE;
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);
423 return FALSE;
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);
433 return FALSE;
436 return TRUE;
439 static BOOL credential_matches_filter(HKEY hkeyCred, LPCWSTR filter)
441 if (!filter) return TRUE;
443 FIXME("%s\n", debugstr_w(filter));
444 return TRUE;
447 /******************************************************************************
448 * CredEnumerateW [ADVAPI32.@]
450 BOOL WINAPI CredEnumerateW(LPCWSTR Filter, DWORD Flags, DWORD *Count,
451 PCREDENTIALW **Credentials)
453 HKEY hkeyMgr;
454 HKEY hkeyCred;
455 DWORD ret;
456 LPWSTR target_name;
457 DWORD target_name_len;
458 DWORD len;
459 char *buffer;
460 DWORD i;
461 BYTE key_data[KEY_SIZE];
463 TRACE("(%s, 0x%x, %p, %p)\n", debugstr_w(Filter), Flags, Count, Credentials);
465 if (Flags)
467 SetLastError(ERROR_INVALID_FLAGS);
468 return FALSE;
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);
476 return FALSE;
479 ret = get_cred_mgr_encryption_key(hkeyMgr, key_data);
480 if (ret != ERROR_SUCCESS)
482 RegCloseKey(hkeyMgr);
483 SetLastError(ret);
484 return FALSE;
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);
491 SetLastError(ret);
492 return FALSE;
495 target_name = HeapAlloc(GetProcessHeap(), 0, (target_name_len+1)*sizeof(WCHAR));
496 if (!target_name)
498 RegCloseKey(hkeyMgr);
499 SetLastError(ERROR_OUTOFMEMORY);
500 return FALSE;
503 *Count = 0;
504 len = 0;
505 for (i = 0;; i++)
507 ret = RegEnumKeyW(hkeyMgr, i, target_name, target_name_len+1);
508 if (ret == ERROR_NO_MORE_ITEMS)
510 ret = ERROR_SUCCESS;
511 break;
513 else if (ret != ERROR_SUCCESS)
515 ret = ERROR_SUCCESS;
516 continue;
518 ret = RegOpenKeyExW(hkeyMgr, target_name, 0, KEY_QUERY_VALUE, &hkeyCred);
519 if (ret != ERROR_SUCCESS)
521 ret = ERROR_SUCCESS;
522 continue;
524 if (!credential_matches_filter(hkeyCred, Filter))
526 RegCloseKey(hkeyCred);
527 continue;
529 len += sizeof(CREDENTIALW);
530 ret = read_credential(hkeyCred, NULL, key_data, NULL, &len);
531 RegCloseKey(hkeyCred);
532 if (ret != ERROR_SUCCESS) break;
533 (*Count)++;
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);
541 SetLastError(ret);
542 return FALSE;
544 len += *Count + sizeof(PCREDENTIALW);
546 if (ret == ERROR_SUCCESS)
548 buffer = HeapAlloc(GetProcessHeap(), 0, len);
549 *Credentials = (PCREDENTIALW *)buffer;
550 if (buffer)
552 buffer += *Count * sizeof(PCREDENTIALW);
553 *Count = 0;
554 for (i = 0;; i++)
556 ret = RegEnumKeyW(hkeyMgr, i, target_name, target_name_len+1);
557 if (ret == ERROR_NO_MORE_ITEMS)
559 ret = ERROR_SUCCESS;
560 break;
562 else if (ret != ERROR_SUCCESS)
564 ret = ERROR_SUCCESS;
565 continue;
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)
571 ret = ERROR_SUCCESS;
572 continue;
574 if (!credential_matches_filter(hkeyCred, Filter))
576 RegCloseKey(hkeyCred);
577 continue;
579 len = sizeof(CREDENTIALW);
580 (*Credentials)[*Count] = (PCREDENTIALW)buffer;
581 ret = read_credential(hkeyCred, (*Credentials)[*Count],
582 key_data,
583 buffer + sizeof(CREDENTIALW), &len);
584 RegCloseKey(hkeyCred);
585 if (ret != ERROR_SUCCESS) break;
586 buffer += len;
587 (*Count)++;
590 else
591 ret = ERROR_OUTOFMEMORY;
594 HeapFree(GetProcessHeap(), 0, target_name);
595 RegCloseKey(hkeyMgr);
597 if (ret != ERROR_SUCCESS)
599 SetLastError(ret);
600 return FALSE;
602 return TRUE;
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)
618 HKEY hkeyMgr;
619 HKEY hkeyCred;
620 DWORD ret;
621 LPWSTR key_name;
622 DWORD len;
623 BYTE key_data[KEY_SIZE];
625 TRACE("(%s, %d, 0x%x, %p)\n", debugstr_w(TargetName), Type, Flags, Credential);
627 if (!TargetName)
629 SetLastError(ERROR_INVALID_PARAMETER);
630 return FALSE;
633 if (Type != CRED_TYPE_GENERIC && Type != CRED_TYPE_DOMAIN_PASSWORD)
635 FIXME("unhandled type %d\n", Type);
636 SetLastError(ERROR_INVALID_PARAMETER);
637 return FALSE;
640 if (Flags)
642 FIXME("unhandled flags 0x%x\n", Flags);
643 SetLastError(ERROR_INVALID_FLAGS);
644 return FALSE;
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);
652 return FALSE;
655 ret = get_cred_mgr_encryption_key(hkeyMgr, key_data);
656 if (ret != ERROR_SUCCESS)
658 RegCloseKey(hkeyMgr);
659 SetLastError(ret);
660 return FALSE;
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);
670 return FALSE;
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);
678 if (*Credential)
680 len = sizeof(**Credential);
681 ret = read_credential(hkeyCred, *Credential, key_data,
682 (char *)(*Credential + 1), &len);
684 else
685 ret = ERROR_OUTOFMEMORY;
688 RegCloseKey(hkeyCred);
689 RegCloseKey(hkeyMgr);
691 if (ret != ERROR_SUCCESS)
693 SetLastError(ret);
694 return FALSE;
696 return TRUE;
699 /******************************************************************************
700 * CredWriteW [ADVAPI32.@]
702 BOOL WINAPI CredWriteW(PCREDENTIALW Credential, DWORD Flags)
704 HKEY hkeyMgr;
705 HKEY hkeyCred;
706 DWORD ret;
707 LPWSTR key_name;
708 BYTE key_data[KEY_SIZE];
710 TRACE("(%p, 0x%x)\n", Credential, Flags);
712 if (!Credential || !Credential->TargetName)
714 SetLastError(ERROR_INVALID_PARAMETER);
715 return FALSE;
718 if (Flags & ~CRED_PRESERVE_CREDENTIAL_BLOB)
720 FIXME("unhandled flags 0x%x\n", Flags);
721 SetLastError(ERROR_INVALID_FLAGS);
722 return FALSE;
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);
729 return FALSE;
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);
742 return FALSE;
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);
751 return FALSE;
754 ret = get_cred_mgr_encryption_key(hkeyMgr, key_data);
755 if (ret != ERROR_SUCCESS)
757 RegCloseKey(hkeyMgr);
758 SetLastError(ret);
759 return FALSE;
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);
771 return FALSE;
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)
782 SetLastError(ret);
783 return FALSE;
785 return TRUE;