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 static void convert_PCREDENTIALW_to_PCREDENTIALA(const CREDENTIALW *CredentialW, PCREDENTIALA CredentialA, DWORD *len)
389 char *buffer = (char *)CredentialA + sizeof(CREDENTIALA);
392 *len += sizeof(CREDENTIALA);
395 if (CredentialW->TargetName) *len += WideCharToMultiByte(CP_ACP, 0, CredentialW->TargetName, -1, NULL, 0, NULL, NULL);
396 if (CredentialW->Comment) *len += WideCharToMultiByte(CP_ACP, 0, CredentialW->Comment, -1, NULL, 0, NULL, NULL);
397 *len += CredentialW->CredentialBlobSize;
398 if (CredentialW->TargetAlias) *len += WideCharToMultiByte(CP_ACP, 0, CredentialW->TargetAlias, -1, NULL, 0, NULL, NULL);
399 if (CredentialW->UserName) *len += WideCharToMultiByte(CP_ACP, 0, CredentialW->UserName, -1, NULL, 0, NULL, NULL);
404 CredentialA->Flags = CredentialW->Flags;
405 CredentialA->Type = CredentialW->Type;
406 if (CredentialW->TargetName)
408 CredentialA->TargetName = (LPSTR)buffer;
409 string_len = WideCharToMultiByte(CP_ACP, 0, CredentialW->TargetName, -1, CredentialA->TargetName, -1, NULL, NULL);
410 buffer += string_len;
414 CredentialA->TargetName = NULL;
415 if (CredentialW->Comment)
417 CredentialA->Comment = (LPSTR)buffer;
418 string_len = WideCharToMultiByte(CP_ACP, 0, CredentialW->Comment, -1, CredentialA->Comment, -1, NULL, NULL);
419 buffer += string_len;
423 CredentialA->Comment = NULL;
424 CredentialA->LastWritten = CredentialW->LastWritten;
425 CredentialA->CredentialBlobSize = CredentialW->CredentialBlobSize;
426 if (CredentialW->CredentialBlobSize)
428 CredentialA->CredentialBlob =(LPBYTE)buffer;
429 memcpy(CredentialA->CredentialBlob, CredentialW->CredentialBlob,
430 CredentialW->CredentialBlobSize);
431 buffer += CredentialW->CredentialBlobSize;
432 *len += CredentialW->CredentialBlobSize;
435 CredentialA->CredentialBlob = NULL;
436 CredentialA->Persist = CredentialW->Persist;
437 CredentialA->AttributeCount = 0;
438 CredentialA->Attributes = NULL; /* FIXME */
439 if (CredentialW->TargetAlias)
441 CredentialA->TargetAlias = (LPSTR)buffer;
442 string_len = WideCharToMultiByte(CP_ACP, 0, CredentialW->TargetAlias, -1, CredentialA->TargetAlias, -1, NULL, NULL);
443 buffer += string_len;
447 CredentialA->TargetAlias = NULL;
448 if (CredentialW->UserName)
450 CredentialA->UserName = (LPSTR)buffer;
451 string_len = WideCharToMultiByte(CP_ACP, 0, CredentialW->UserName, -1, CredentialA->UserName, -1, NULL, NULL);
452 buffer += string_len;
456 CredentialA->UserName = NULL;
459 static void convert_PCREDENTIALA_to_PCREDENTIALW(const CREDENTIALA *CredentialA, PCREDENTIALW CredentialW, DWORD *len)
461 char *buffer = (char *)CredentialW + sizeof(CREDENTIALW);
464 *len += sizeof(CREDENTIALW);
467 if (CredentialA->TargetName) *len += sizeof(WCHAR) * MultiByteToWideChar(CP_ACP, 0, CredentialA->TargetName, -1, NULL, 0);
468 if (CredentialA->Comment) *len += sizeof(WCHAR) * MultiByteToWideChar(CP_ACP, 0, CredentialA->Comment, -1, NULL, 0);
469 *len += CredentialA->CredentialBlobSize;
470 if (CredentialA->TargetAlias) *len += sizeof(WCHAR) * MultiByteToWideChar(CP_ACP, 0, CredentialA->TargetAlias, -1, NULL, 0);
471 if (CredentialA->UserName) *len += sizeof(WCHAR) * MultiByteToWideChar(CP_ACP, 0, CredentialA->UserName, -1, NULL, 0);
476 CredentialW->Flags = CredentialA->Flags;
477 CredentialW->Type = CredentialA->Type;
478 if (CredentialA->TargetName)
480 CredentialW->TargetName = (LPWSTR)buffer;
481 string_len = MultiByteToWideChar(CP_ACP, 0, CredentialA->TargetName, -1, CredentialW->TargetName, -1);
482 buffer += sizeof(WCHAR) * string_len;
483 *len += sizeof(WCHAR) * string_len;
486 CredentialW->TargetName = NULL;
487 if (CredentialA->Comment)
489 CredentialW->Comment = (LPWSTR)buffer;
490 string_len = MultiByteToWideChar(CP_ACP, 0, CredentialA->Comment, -1, CredentialW->Comment, -1);
491 buffer += sizeof(WCHAR) * string_len;
492 *len += sizeof(WCHAR) * string_len;
495 CredentialW->Comment = NULL;
496 CredentialW->LastWritten = CredentialA->LastWritten;
497 CredentialW->CredentialBlobSize = CredentialA->CredentialBlobSize;
498 if (CredentialA->CredentialBlobSize)
500 CredentialW->CredentialBlob =(LPBYTE)buffer;
501 memcpy(CredentialW->CredentialBlob, CredentialA->CredentialBlob,
502 CredentialA->CredentialBlobSize);
503 buffer += CredentialA->CredentialBlobSize;
504 *len += CredentialA->CredentialBlobSize;
507 CredentialW->CredentialBlob = NULL;
508 CredentialW->Persist = CredentialA->Persist;
509 CredentialW->AttributeCount = 0;
510 CredentialW->Attributes = NULL; /* FIXME */
511 if (CredentialA->TargetAlias)
513 CredentialW->TargetAlias = (LPWSTR)buffer;
514 string_len = MultiByteToWideChar(CP_ACP, 0, CredentialA->TargetAlias, -1, CredentialW->TargetAlias, -1);
515 buffer += sizeof(WCHAR) * string_len;
516 *len += sizeof(WCHAR) * string_len;
519 CredentialW->TargetAlias = NULL;
520 if (CredentialA->UserName)
522 CredentialW->UserName = (LPWSTR)buffer;
523 string_len = MultiByteToWideChar(CP_ACP, 0, CredentialA->UserName, -1, CredentialW->UserName, -1);
524 buffer += sizeof(WCHAR) * string_len;
525 *len += sizeof(WCHAR) * string_len;
528 CredentialW->UserName = NULL;
531 /******************************************************************************
532 * CredDeleteA [ADVAPI32.@]
534 BOOL WINAPI CredDeleteA(LPCSTR TargetName, DWORD Type, DWORD Flags)
540 TRACE("(%s, %d, 0x%x)\n", debugstr_a(TargetName), Type, Flags);
544 SetLastError(ERROR_INVALID_PARAMETER);
548 len = MultiByteToWideChar(CP_ACP, 0, TargetName, -1, NULL, 0);
549 TargetNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
552 SetLastError(ERROR_OUTOFMEMORY);
555 MultiByteToWideChar(CP_ACP, 0, TargetName, -1, TargetNameW, len);
557 ret = CredDeleteW(TargetNameW, Type, Flags);
559 HeapFree(GetProcessHeap(), 0, TargetNameW);
564 /******************************************************************************
565 * CredDeleteW [ADVAPI32.@]
567 BOOL WINAPI CredDeleteW(LPCWSTR TargetName, DWORD Type, DWORD Flags)
573 TRACE("(%s, %d, 0x%x)\n", debugstr_w(TargetName), Type, Flags);
577 SetLastError(ERROR_INVALID_PARAMETER);
581 if (Type != CRED_TYPE_GENERIC && Type != CRED_TYPE_DOMAIN_PASSWORD)
583 FIXME("unhandled type %d\n", Type);
584 SetLastError(ERROR_INVALID_PARAMETER);
590 FIXME("unhandled flags 0x%x\n", Flags);
591 SetLastError(ERROR_INVALID_FLAGS);
595 ret = open_cred_mgr_key(&hkeyMgr, TRUE);
596 if (ret != ERROR_SUCCESS)
598 WARN("couldn't open/create manager key, error %d\n", ret);
599 SetLastError(ERROR_NO_SUCH_LOGON_SESSION);
603 key_name = get_key_name_for_target(TargetName, Type);
604 ret = RegDeleteKeyW(hkeyMgr, key_name);
605 HeapFree(GetProcessHeap(), 0, key_name);
606 RegCloseKey(hkeyMgr);
607 if (ret != ERROR_SUCCESS)
609 SetLastError(ERROR_NOT_FOUND);
616 /******************************************************************************
617 * CredEnumerateA [ADVAPI32.@]
619 BOOL WINAPI CredEnumerateA(LPCSTR Filter, DWORD Flags, DWORD *Count,
620 PCREDENTIALA **Credentials)
623 PCREDENTIALW *CredentialsW;
628 TRACE("(%s, 0x%x, %p, %p)\n", debugstr_a(Filter), Flags, Count, Credentials);
632 len = MultiByteToWideChar(CP_ACP, 0, Filter, -1, NULL, 0);
633 FilterW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
636 SetLastError(ERROR_OUTOFMEMORY);
639 MultiByteToWideChar(CP_ACP, 0, Filter, -1, FilterW, len);
644 if (!CredEnumerateW(FilterW, Flags, Count, &CredentialsW))
646 HeapFree(GetProcessHeap(), 0, FilterW);
649 HeapFree(GetProcessHeap(), 0, FilterW);
651 len = *Count * sizeof(PCREDENTIALA);
652 for (i = 0; i < *Count; i++)
653 convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW[i], NULL, &len);
655 *Credentials = HeapAlloc(GetProcessHeap(), 0, len);
658 CredFree(CredentialsW);
659 SetLastError(ERROR_OUTOFMEMORY);
663 buffer = (char *)&(*Credentials)[*Count];
664 for (i = 0; i < *Count; i++)
667 (*Credentials)[i] = (PCREDENTIALA)buffer;
668 convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW[i], (*Credentials)[i], &len);
672 CredFree(CredentialsW);
677 static BOOL credential_matches_filter(HKEY hkeyCred, LPCWSTR filter)
685 if (!filter) return TRUE;
687 ret = RegQueryValueExW(hkeyCred, NULL, 0, &type, NULL, &count);
688 if (ret != ERROR_SUCCESS)
690 else if (type != REG_SZ)
693 target_name = HeapAlloc(GetProcessHeap(), 0, count);
696 ret = RegQueryValueExW(hkeyCred, NULL, 0, &type, (LPVOID)target_name, &count);
697 if (ret != ERROR_SUCCESS || type != REG_SZ)
699 HeapFree(GetProcessHeap(), 0, target_name);
703 TRACE("comparing filter %s to target name %s\n", debugstr_w(filter),
704 debugstr_w(target_name));
706 p = strchrW(filter, '*');
707 ret = CompareStringW(GetThreadLocale(), 0, filter,
708 (p && !p[1] ? p - filter : -1), target_name,
709 (p && !p[1] ? p - filter : -1)) == CSTR_EQUAL;
711 HeapFree(GetProcessHeap(), 0, target_name);
715 /******************************************************************************
716 * CredEnumerateW [ADVAPI32.@]
718 BOOL WINAPI CredEnumerateW(LPCWSTR Filter, DWORD Flags, DWORD *Count,
719 PCREDENTIALW **Credentials)
725 DWORD target_name_len;
729 BYTE key_data[KEY_SIZE];
731 TRACE("(%s, 0x%x, %p, %p)\n", debugstr_w(Filter), Flags, Count, Credentials);
735 SetLastError(ERROR_INVALID_FLAGS);
739 ret = open_cred_mgr_key(&hkeyMgr, FALSE);
740 if (ret != ERROR_SUCCESS)
742 WARN("couldn't open/create manager key, error %d\n", ret);
743 SetLastError(ERROR_NO_SUCH_LOGON_SESSION);
747 ret = get_cred_mgr_encryption_key(hkeyMgr, key_data);
748 if (ret != ERROR_SUCCESS)
750 RegCloseKey(hkeyMgr);
755 ret = RegQueryInfoKeyW(hkeyMgr, NULL, NULL, NULL, NULL, &target_name_len, NULL, NULL, NULL, NULL, NULL, NULL);
756 if (ret != ERROR_SUCCESS)
758 RegCloseKey(hkeyMgr);
763 target_name = HeapAlloc(GetProcessHeap(), 0, (target_name_len+1)*sizeof(WCHAR));
766 RegCloseKey(hkeyMgr);
767 SetLastError(ERROR_OUTOFMEMORY);
775 ret = RegEnumKeyW(hkeyMgr, i, target_name, target_name_len+1);
776 if (ret == ERROR_NO_MORE_ITEMS)
781 else if (ret != ERROR_SUCCESS)
786 ret = RegOpenKeyExW(hkeyMgr, target_name, 0, KEY_QUERY_VALUE, &hkeyCred);
787 if (ret != ERROR_SUCCESS)
792 if (!credential_matches_filter(hkeyCred, Filter))
794 RegCloseKey(hkeyCred);
797 len += sizeof(CREDENTIALW);
798 ret = read_credential(hkeyCred, NULL, key_data, NULL, &len);
799 RegCloseKey(hkeyCred);
800 if (ret != ERROR_SUCCESS) break;
803 if (ret == ERROR_SUCCESS && *Count == 0)
804 ret = ERROR_NOT_FOUND;
805 if (ret != ERROR_SUCCESS)
807 HeapFree(GetProcessHeap(), 0, target_name);
808 RegCloseKey(hkeyMgr);
812 len += *Count + sizeof(PCREDENTIALW);
814 if (ret == ERROR_SUCCESS)
816 buffer = HeapAlloc(GetProcessHeap(), 0, len);
817 *Credentials = (PCREDENTIALW *)buffer;
820 buffer += *Count * sizeof(PCREDENTIALW);
824 ret = RegEnumKeyW(hkeyMgr, i, target_name, target_name_len+1);
825 if (ret == ERROR_NO_MORE_ITEMS)
830 else if (ret != ERROR_SUCCESS)
835 TRACE("target_name = %s\n", debugstr_w(target_name));
836 ret = RegOpenKeyExW(hkeyMgr, target_name, 0, KEY_QUERY_VALUE, &hkeyCred);
837 if (ret != ERROR_SUCCESS)
842 if (!credential_matches_filter(hkeyCred, Filter))
844 RegCloseKey(hkeyCred);
847 len = sizeof(CREDENTIALW);
848 (*Credentials)[*Count] = (PCREDENTIALW)buffer;
849 ret = read_credential(hkeyCred, (*Credentials)[*Count],
851 buffer + sizeof(CREDENTIALW), &len);
852 RegCloseKey(hkeyCred);
853 if (ret != ERROR_SUCCESS) break;
859 ret = ERROR_OUTOFMEMORY;
862 HeapFree(GetProcessHeap(), 0, target_name);
863 RegCloseKey(hkeyMgr);
865 if (ret != ERROR_SUCCESS)
873 /******************************************************************************
874 * CredFree [ADVAPI32.@]
876 VOID WINAPI CredFree(PVOID Buffer)
878 HeapFree(GetProcessHeap(), 0, Buffer);
881 /******************************************************************************
882 * CredReadA [ADVAPI32.@]
884 BOOL WINAPI CredReadA(LPCSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALA *Credential)
887 PCREDENTIALW CredentialW;
890 TRACE("(%s, %d, 0x%x, %p)\n", debugstr_a(TargetName), Type, Flags, Credential);
894 SetLastError(ERROR_INVALID_PARAMETER);
898 len = MultiByteToWideChar(CP_ACP, 0, TargetName, -1, NULL, 0);
899 TargetNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
902 SetLastError(ERROR_OUTOFMEMORY);
905 MultiByteToWideChar(CP_ACP, 0, TargetName, -1, TargetNameW, len);
907 if (!CredReadW(TargetNameW, Type, Flags, &CredentialW))
909 HeapFree(GetProcessHeap(), 0, TargetNameW);
912 HeapFree(GetProcessHeap(), 0, TargetNameW);
915 convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW, NULL, &len);
916 *Credential = HeapAlloc(GetProcessHeap(), 0, len);
919 SetLastError(ERROR_OUTOFMEMORY);
923 convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW, *Credential, &len);
925 CredFree(CredentialW);
930 /******************************************************************************
931 * CredReadW [ADVAPI32.@]
933 BOOL WINAPI CredReadW(LPCWSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALW *Credential)
940 BYTE key_data[KEY_SIZE];
942 TRACE("(%s, %d, 0x%x, %p)\n", debugstr_w(TargetName), Type, Flags, Credential);
946 SetLastError(ERROR_INVALID_PARAMETER);
950 if (Type != CRED_TYPE_GENERIC && Type != CRED_TYPE_DOMAIN_PASSWORD)
952 FIXME("unhandled type %d\n", Type);
953 SetLastError(ERROR_INVALID_PARAMETER);
959 FIXME("unhandled flags 0x%x\n", Flags);
960 SetLastError(ERROR_INVALID_FLAGS);
964 ret = open_cred_mgr_key(&hkeyMgr, FALSE);
965 if (ret != ERROR_SUCCESS)
967 WARN("couldn't open/create manager key, error %d\n", ret);
968 SetLastError(ERROR_NO_SUCH_LOGON_SESSION);
972 ret = get_cred_mgr_encryption_key(hkeyMgr, key_data);
973 if (ret != ERROR_SUCCESS)
975 RegCloseKey(hkeyMgr);
980 key_name = get_key_name_for_target(TargetName, Type);
981 ret = RegOpenKeyExW(hkeyMgr, key_name, 0, KEY_QUERY_VALUE, &hkeyCred);
982 HeapFree(GetProcessHeap(), 0, key_name);
983 if (ret != ERROR_SUCCESS)
985 TRACE("credentials for target name %s not found\n", debugstr_w(TargetName));
986 SetLastError(ERROR_NOT_FOUND);
990 len = sizeof(**Credential);
991 ret = read_credential(hkeyCred, NULL, key_data, NULL, &len);
992 if (ret == ERROR_SUCCESS)
994 *Credential = HeapAlloc(GetProcessHeap(), 0, len);
997 len = sizeof(**Credential);
998 ret = read_credential(hkeyCred, *Credential, key_data,
999 (char *)(*Credential + 1), &len);
1002 ret = ERROR_OUTOFMEMORY;
1005 RegCloseKey(hkeyCred);
1006 RegCloseKey(hkeyMgr);
1008 if (ret != ERROR_SUCCESS)
1016 /******************************************************************************
1017 * CredWriteA [ADVAPI32.@]
1019 BOOL WINAPI CredWriteA(PCREDENTIALA Credential, DWORD Flags)
1023 PCREDENTIALW CredentialW;
1025 TRACE("(%p, 0x%x)\n", Credential, Flags);
1027 if (!Credential || !Credential->TargetName)
1029 SetLastError(ERROR_INVALID_PARAMETER);
1034 convert_PCREDENTIALA_to_PCREDENTIALW(Credential, NULL, &len);
1035 CredentialW = HeapAlloc(GetProcessHeap(), 0, len);
1038 SetLastError(ERROR_OUTOFMEMORY);
1042 convert_PCREDENTIALA_to_PCREDENTIALW(Credential, CredentialW, &len);
1044 ret = CredWriteW(CredentialW, Flags);
1046 HeapFree(GetProcessHeap(), 0, CredentialW);
1051 /******************************************************************************
1052 * CredWriteW [ADVAPI32.@]
1054 BOOL WINAPI CredWriteW(PCREDENTIALW Credential, DWORD Flags)
1060 BYTE key_data[KEY_SIZE];
1062 TRACE("(%p, 0x%x)\n", Credential, Flags);
1064 if (!Credential || !Credential->TargetName)
1066 SetLastError(ERROR_INVALID_PARAMETER);
1070 if (Flags & ~CRED_PRESERVE_CREDENTIAL_BLOB)
1072 FIXME("unhandled flags 0x%x\n", Flags);
1073 SetLastError(ERROR_INVALID_FLAGS);
1077 if (Credential->Type != CRED_TYPE_GENERIC && Credential->Type != CRED_TYPE_DOMAIN_PASSWORD)
1079 FIXME("unhandled type %d\n", Credential->Type);
1080 SetLastError(ERROR_INVALID_PARAMETER);
1084 TRACE("Credential->TargetName = %s\n", debugstr_w(Credential->TargetName));
1085 TRACE("Credential->UserName = %s\n", debugstr_w(Credential->UserName));
1087 if (Credential->Type == CRED_TYPE_DOMAIN_PASSWORD)
1089 if (!Credential->UserName ||
1090 (!strchrW(Credential->UserName, '\\') && !strchrW(Credential->UserName, '@')))
1092 ERR("bad username %s\n", debugstr_w(Credential->UserName));
1093 SetLastError(ERROR_BAD_USERNAME);
1098 ret = open_cred_mgr_key(&hkeyMgr, FALSE);
1099 if (ret != ERROR_SUCCESS)
1101 WARN("couldn't open/create manager key, error %d\n", ret);
1102 SetLastError(ERROR_NO_SUCH_LOGON_SESSION);
1106 ret = get_cred_mgr_encryption_key(hkeyMgr, key_data);
1107 if (ret != ERROR_SUCCESS)
1109 RegCloseKey(hkeyMgr);
1114 key_name = get_key_name_for_target(Credential->TargetName, Credential->Type);
1115 ret = RegCreateKeyExW(hkeyMgr, key_name, 0, NULL, REG_OPTION_VOLATILE,
1116 KEY_READ|KEY_WRITE, NULL, &hkeyCred, NULL);
1117 HeapFree(GetProcessHeap(), 0, key_name);
1118 if (ret != ERROR_SUCCESS)
1120 TRACE("credentials for target name %s not found\n",
1121 debugstr_w(Credential->TargetName));
1122 SetLastError(ERROR_NOT_FOUND);
1126 ret = write_credential(hkeyCred, Credential, key_data,
1127 Flags & CRED_PRESERVE_CREDENTIAL_BLOB);
1129 RegCloseKey(hkeyCred);
1130 RegCloseKey(hkeyMgr);
1132 if (ret != ERROR_SUCCESS)