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 #define WINE_MOUNTMGR_EXTENSIONS
32 #include "ddk/mountmgr.h"
36 #include "wine/debug.h"
38 #include "advapi32_misc.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(cred
);
42 /* the size of the ARC4 key used to encrypt the password data */
45 static DWORD
read_credential_blob(HKEY hkey
, const BYTE key_data
[KEY_SIZE
],
46 LPBYTE credential_blob
,
47 DWORD
*credential_blob_size
)
52 *credential_blob_size
= 0;
53 ret
= RegQueryValueExW(hkey
, L
"Password", 0, &type
, NULL
, credential_blob_size
);
54 if (ret
!= ERROR_SUCCESS
)
56 else if (type
!= REG_BINARY
)
57 return ERROR_REGISTRY_CORRUPT
;
63 ret
= RegQueryValueExW(hkey
, L
"Password", 0, &type
, credential_blob
,
64 credential_blob_size
);
65 if (ret
!= ERROR_SUCCESS
)
67 else if (type
!= REG_BINARY
)
68 return ERROR_REGISTRY_CORRUPT
;
70 key
.Length
= key
.MaximumLength
= KEY_SIZE
;
71 key
.Buffer
= (unsigned char *)key_data
;
73 data
.Length
= data
.MaximumLength
= *credential_blob_size
;
74 data
.Buffer
= credential_blob
;
75 SystemFunction032(&data
, &key
);
80 static DWORD
registry_read_credential(HKEY hkey
, PCREDENTIALW credential
,
81 const BYTE key_data
[KEY_SIZE
],
82 char *buffer
, DWORD
*len
)
88 ret
= RegQueryValueExW(hkey
, NULL
, 0, &type
, NULL
, &count
);
89 if (ret
!= ERROR_SUCCESS
)
91 else if (type
!= REG_SZ
)
92 return ERROR_REGISTRY_CORRUPT
;
96 credential
->TargetName
= (LPWSTR
)buffer
;
97 ret
= RegQueryValueExW(hkey
, NULL
, 0, &type
, (LPVOID
)credential
->TargetName
,
99 if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
) return ret
;
103 ret
= RegQueryValueExW(hkey
, L
"Comment", 0, &type
, NULL
, &count
);
104 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
106 else if (type
!= REG_SZ
)
107 return ERROR_REGISTRY_CORRUPT
;
111 credential
->Comment
= (LPWSTR
)buffer
;
112 ret
= RegQueryValueExW(hkey
, L
"Comment", 0, &type
, (LPVOID
)credential
->Comment
,
114 if (ret
== ERROR_FILE_NOT_FOUND
)
115 credential
->Comment
= NULL
;
116 else if (ret
!= ERROR_SUCCESS
)
118 else if (type
!= REG_SZ
)
119 return ERROR_REGISTRY_CORRUPT
;
124 ret
= RegQueryValueExW(hkey
, L
"TargetAlias", 0, &type
, NULL
, &count
);
125 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
127 else if (type
!= REG_SZ
)
128 return ERROR_REGISTRY_CORRUPT
;
132 credential
->TargetAlias
= (LPWSTR
)buffer
;
133 ret
= RegQueryValueExW(hkey
, L
"TargetAlias", 0, &type
, (LPVOID
)credential
->TargetAlias
,
135 if (ret
== ERROR_FILE_NOT_FOUND
)
136 credential
->TargetAlias
= NULL
;
137 else if (ret
!= ERROR_SUCCESS
)
139 else if (type
!= REG_SZ
)
140 return ERROR_REGISTRY_CORRUPT
;
145 ret
= RegQueryValueExW(hkey
, L
"UserName", 0, &type
, NULL
, &count
);
146 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
148 else if (type
!= REG_SZ
)
149 return ERROR_REGISTRY_CORRUPT
;
153 credential
->UserName
= (LPWSTR
)buffer
;
154 ret
= RegQueryValueExW(hkey
, L
"UserName", 0, &type
, (LPVOID
)credential
->UserName
,
156 if (ret
== ERROR_FILE_NOT_FOUND
)
157 credential
->UserName
= NULL
;
158 else if (ret
!= ERROR_SUCCESS
)
160 else if (type
!= REG_SZ
)
161 return ERROR_REGISTRY_CORRUPT
;
166 ret
= read_credential_blob(hkey
, key_data
, NULL
, &count
);
167 if (ret
!= ERROR_FILE_NOT_FOUND
&& ret
!= ERROR_SUCCESS
)
172 credential
->CredentialBlob
= (LPBYTE
)buffer
;
173 ret
= read_credential_blob(hkey
, key_data
, credential
->CredentialBlob
, &count
);
174 if (ret
== ERROR_FILE_NOT_FOUND
)
175 credential
->CredentialBlob
= NULL
;
176 else if (ret
!= ERROR_SUCCESS
)
178 credential
->CredentialBlobSize
= count
;
181 /* FIXME: Attributes */
184 credential
->AttributeCount
= 0;
185 credential
->Attributes
= NULL
;
188 if (!credential
) return ERROR_SUCCESS
;
190 count
= sizeof(credential
->Flags
);
191 ret
= RegQueryValueExW(hkey
, L
"Flags", NULL
, &type
, (LPVOID
)&credential
->Flags
,
193 if (ret
!= ERROR_SUCCESS
)
195 else if (type
!= REG_DWORD
)
196 return ERROR_REGISTRY_CORRUPT
;
197 count
= sizeof(credential
->Type
);
198 ret
= RegQueryValueExW(hkey
, L
"Type", NULL
, &type
, (LPVOID
)&credential
->Type
,
200 if (ret
!= ERROR_SUCCESS
)
202 else if (type
!= REG_DWORD
)
203 return ERROR_REGISTRY_CORRUPT
;
205 count
= sizeof(credential
->LastWritten
);
206 ret
= RegQueryValueExW(hkey
, L
"LastWritten", NULL
, &type
, (LPVOID
)&credential
->LastWritten
,
208 if (ret
!= ERROR_SUCCESS
)
210 else if (type
!= REG_BINARY
)
211 return ERROR_REGISTRY_CORRUPT
;
212 count
= sizeof(credential
->Persist
);
213 ret
= RegQueryValueExW(hkey
, L
"Persist", NULL
, &type
, (LPVOID
)&credential
->Persist
,
215 if (ret
== ERROR_SUCCESS
&& type
!= REG_DWORD
)
216 return ERROR_REGISTRY_CORRUPT
;
220 static DWORD
write_credential_blob(HKEY hkey
, LPCWSTR target_name
, DWORD type
,
221 const BYTE key_data
[KEY_SIZE
],
222 const BYTE
*credential_blob
, DWORD credential_blob_size
)
224 LPBYTE encrypted_credential_blob
;
229 key
.Length
= key
.MaximumLength
= KEY_SIZE
;
230 key
.Buffer
= (unsigned char *)key_data
;
232 encrypted_credential_blob
= heap_alloc(credential_blob_size
);
233 if (!encrypted_credential_blob
) return ERROR_OUTOFMEMORY
;
235 memcpy(encrypted_credential_blob
, credential_blob
, credential_blob_size
);
236 data
.Length
= data
.MaximumLength
= credential_blob_size
;
237 data
.Buffer
= encrypted_credential_blob
;
238 SystemFunction032(&data
, &key
);
240 ret
= RegSetValueExW(hkey
, L
"Password", 0, REG_BINARY
, encrypted_credential_blob
, credential_blob_size
);
241 heap_free(encrypted_credential_blob
);
246 static DWORD
registry_write_credential(HKEY hkey
, const CREDENTIALW
*credential
,
247 const BYTE key_data
[KEY_SIZE
], BOOL preserve_blob
)
250 FILETIME LastWritten
;
252 GetSystemTimeAsFileTime(&LastWritten
);
254 ret
= RegSetValueExW(hkey
, L
"Flags", 0, REG_DWORD
, (const BYTE
*)&credential
->Flags
,
255 sizeof(credential
->Flags
));
256 if (ret
!= ERROR_SUCCESS
) return ret
;
257 ret
= RegSetValueExW(hkey
, L
"Type", 0, REG_DWORD
, (const BYTE
*)&credential
->Type
,
258 sizeof(credential
->Type
));
259 if (ret
!= ERROR_SUCCESS
) return ret
;
260 ret
= RegSetValueExW(hkey
, NULL
, 0, REG_SZ
, (LPVOID
)credential
->TargetName
,
261 sizeof(WCHAR
)*(lstrlenW(credential
->TargetName
)+1));
262 if (ret
!= ERROR_SUCCESS
) return ret
;
263 if (credential
->Comment
)
265 ret
= RegSetValueExW(hkey
, L
"Comment", 0, REG_SZ
, (LPVOID
)credential
->Comment
,
266 sizeof(WCHAR
)*(lstrlenW(credential
->Comment
)+1));
267 if (ret
!= ERROR_SUCCESS
) return ret
;
269 ret
= RegSetValueExW(hkey
, L
"LastWritten", 0, REG_BINARY
, (LPVOID
)&LastWritten
,
270 sizeof(LastWritten
));
271 if (ret
!= ERROR_SUCCESS
) return ret
;
272 ret
= RegSetValueExW(hkey
, L
"Persist", 0, REG_DWORD
, (const BYTE
*)&credential
->Persist
,
273 sizeof(credential
->Persist
));
274 if (ret
!= ERROR_SUCCESS
) return ret
;
275 /* FIXME: Attributes */
276 if (credential
->TargetAlias
)
278 ret
= RegSetValueExW(hkey
, L
"TargetAlias", 0, REG_SZ
, (LPVOID
)credential
->TargetAlias
,
279 sizeof(WCHAR
)*(lstrlenW(credential
->TargetAlias
)+1));
280 if (ret
!= ERROR_SUCCESS
) return ret
;
282 if (credential
->UserName
)
284 ret
= RegSetValueExW(hkey
, L
"UserName", 0, REG_SZ
, (LPVOID
)credential
->UserName
,
285 sizeof(WCHAR
)*(lstrlenW(credential
->UserName
)+1));
286 if (ret
!= ERROR_SUCCESS
) return ret
;
290 ret
= write_credential_blob(hkey
, credential
->TargetName
, credential
->Type
,
291 key_data
, credential
->CredentialBlob
,
292 credential
->CredentialBlobSize
);
297 static DWORD
host_write_credential( const CREDENTIALW
*credential
, BOOL preserve_blob
)
299 struct mountmgr_credential
*cred
;
305 if (credential
->Flags
)
306 FIXME( "flags 0x%x not written\n", credential
->Flags
);
307 if (credential
->Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
308 FIXME( "credential type of %d not supported\n", credential
->Type
);
309 if (credential
->Persist
!= CRED_PERSIST_LOCAL_MACHINE
)
310 FIXME( "persist value of %d not supported\n", credential
->Persist
);
311 if (credential
->AttributeCount
)
312 FIXME( "custom attributes not supported\n" );
314 if (credential
->CredentialBlobSize
% sizeof(WCHAR
)) return ERROR_NOT_SUPPORTED
;
316 mgr
= CreateFileW( MOUNTMGR_DOS_DEVICE_NAME
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
,
317 OPEN_EXISTING
, 0, 0 );
318 if (mgr
== INVALID_HANDLE_VALUE
) return GetLastError();
320 size
= sizeof(*cred
) + (lstrlenW( credential
->TargetName
) + lstrlenW( credential
->UserName
) + 2) * sizeof(WCHAR
);
321 size
+= credential
->CredentialBlobSize
;
322 if (credential
->Comment
) size
+= (lstrlenW( credential
->Comment
) + 1) * sizeof(WCHAR
);
323 if (!(cred
= heap_alloc( size
)))
326 return ERROR_OUTOFMEMORY
;
328 ptr
= (WCHAR
*)(cred
+ 1);
330 cred
->targetname_offset
= sizeof(*cred
);
331 cred
->targetname_size
= (lstrlenW( credential
->TargetName
) + 1) * sizeof(WCHAR
);
332 lstrcpyW( ptr
, credential
->TargetName
);
333 ptr
+= cred
->targetname_size
/ sizeof(WCHAR
);
335 cred
->username_offset
= cred
->targetname_offset
+ cred
->targetname_size
;
336 cred
->username_size
= (lstrlenW( credential
->UserName
) + 1) * sizeof(WCHAR
);
337 lstrcpyW( ptr
, credential
->UserName
);
338 ptr
+= cred
->username_size
/ sizeof(WCHAR
);
340 cred
->blob_offset
= cred
->username_offset
+ cred
->username_size
;
341 if (credential
->CredentialBlob
)
343 cred
->blob_size
= credential
->CredentialBlobSize
;
344 memcpy( ptr
, credential
->CredentialBlob
, credential
->CredentialBlobSize
);
345 ptr
+= cred
->blob_size
/ sizeof(WCHAR
);
347 else cred
->blob_size
= 0;
348 cred
->blob_preserve
= preserve_blob
;
350 cred
->comment_offset
= cred
->blob_offset
+ cred
->blob_size
;
351 if (credential
->Comment
)
353 cred
->comment_size
= (lstrlenW( credential
->Comment
) + 1) * sizeof(WCHAR
);
354 lstrcpyW( ptr
, credential
->Comment
);
356 else cred
->comment_size
= 0;
358 ret
= DeviceIoControl( mgr
, IOCTL_MOUNTMGR_WRITE_CREDENTIAL
, cred
, size
, NULL
, 0, NULL
, NULL
);
362 return ret
? ERROR_SUCCESS
: GetLastError();
365 static DWORD
open_cred_mgr_key(HKEY
*hkey
, BOOL open_for_write
)
367 return RegCreateKeyExW(HKEY_CURRENT_USER
, L
"Software\\Wine\\Credential Manager", 0,
368 NULL
, REG_OPTION_NON_VOLATILE
,
369 KEY_READ
| (open_for_write
? KEY_WRITE
: 0), NULL
, hkey
, NULL
);
372 static DWORD
get_cred_mgr_encryption_key(HKEY hkeyMgr
, BYTE key_data
[KEY_SIZE
])
374 static const BYTE my_key_data
[KEY_SIZE
] = { 0 };
382 memcpy(key_data
, my_key_data
, KEY_SIZE
);
385 ret
= RegQueryValueExW(hkeyMgr
, L
"EncryptionKey", NULL
, &type
, key_data
,
387 if (ret
== ERROR_SUCCESS
)
389 if (type
!= REG_BINARY
)
390 return ERROR_REGISTRY_CORRUPT
;
392 return ERROR_SUCCESS
;
394 if (ret
!= ERROR_FILE_NOT_FOUND
)
397 GetSystemTimeAsFileTime(&ft
);
398 seed
= ft
.dwLowDateTime
;
399 value
= RtlUniform(&seed
);
400 *(DWORD
*)key_data
= value
;
401 seed
= ft
.dwHighDateTime
;
402 value
= RtlUniform(&seed
);
403 *(DWORD
*)(key_data
+ 4) = value
;
405 ret
= RegSetValueExW(hkeyMgr
, L
"EncryptionKey", 0, REG_BINARY
,
407 if (ret
== ERROR_ACCESS_DENIED
)
409 ret
= open_cred_mgr_key(&hkeyMgr
, TRUE
);
410 if (ret
== ERROR_SUCCESS
)
412 ret
= RegSetValueExW(hkeyMgr
, L
"EncryptionKey", 0, REG_BINARY
,
414 RegCloseKey(hkeyMgr
);
420 static LPWSTR
get_key_name_for_target(LPCWSTR target_name
, DWORD type
)
423 LPCWSTR prefix
= NULL
;
426 len
= lstrlenW(target_name
);
427 if (type
== CRED_TYPE_GENERIC
)
429 prefix
= L
"Generic: ";
430 len
+= ARRAY_SIZE(L
"Generic: ");
434 prefix
= L
"DomPasswd: ";
435 len
+= ARRAY_SIZE(L
"DomPasswd: ");
438 key_name
= heap_alloc(len
* sizeof(WCHAR
));
439 if (!key_name
) return NULL
;
441 lstrcpyW(key_name
, prefix
);
442 lstrcatW(key_name
, target_name
);
444 for (p
= key_name
; *p
; p
++)
445 if (*p
== '\\') *p
= '_';
450 static BOOL
registry_credential_matches_filter(HKEY hkeyCred
, LPCWSTR filter
)
458 if (!filter
) return TRUE
;
460 ret
= RegQueryValueExW(hkeyCred
, NULL
, 0, &type
, NULL
, &count
);
461 if (ret
!= ERROR_SUCCESS
)
463 else if (type
!= REG_SZ
)
466 target_name
= heap_alloc(count
);
469 ret
= RegQueryValueExW(hkeyCred
, NULL
, 0, &type
, (LPVOID
)target_name
, &count
);
470 if (ret
!= ERROR_SUCCESS
|| type
!= REG_SZ
)
472 heap_free(target_name
);
476 TRACE("comparing filter %s to target name %s\n", debugstr_w(filter
),
477 debugstr_w(target_name
));
479 p
= wcschr(filter
, '*');
480 ret
= CompareStringW(GetThreadLocale(), NORM_IGNORECASE
, filter
,
481 (p
&& !p
[1] ? p
- filter
: -1), target_name
,
482 (p
&& !p
[1] ? p
- filter
: -1)) == CSTR_EQUAL
;
484 heap_free(target_name
);
488 static DWORD
registry_enumerate_credentials(HKEY hkeyMgr
, LPCWSTR filter
,
490 DWORD target_name_len
, const BYTE key_data
[KEY_SIZE
],
491 PCREDENTIALW
*credentials
, char **buffer
,
492 DWORD
*len
, DWORD
*count
)
499 ret
= RegEnumKeyW(hkeyMgr
, i
, target_name
, target_name_len
+1);
500 if (ret
== ERROR_NO_MORE_ITEMS
)
505 else if (ret
!= ERROR_SUCCESS
)
507 TRACE("target_name = %s\n", debugstr_w(target_name
));
508 ret
= RegOpenKeyExW(hkeyMgr
, target_name
, 0, KEY_QUERY_VALUE
, &hkeyCred
);
509 if (ret
!= ERROR_SUCCESS
)
511 if (!registry_credential_matches_filter(hkeyCred
, filter
))
513 RegCloseKey(hkeyCred
);
518 *len
= sizeof(CREDENTIALW
);
519 credentials
[*count
] = (PCREDENTIALW
)*buffer
;
522 *len
+= sizeof(CREDENTIALW
);
523 ret
= registry_read_credential(hkeyCred
, buffer
? credentials
[*count
] : NULL
,
524 key_data
, buffer
? *buffer
+ sizeof(CREDENTIALW
) : NULL
,
526 RegCloseKey(hkeyCred
);
527 if (ret
!= ERROR_SUCCESS
) break;
528 if (buffer
) *buffer
+= *len
;
534 /******************************************************************************
535 * convert_PCREDENTIALW_to_PCREDENTIALA [internal]
537 * convert a Credential struct from UNICODE to ANSI and return the needed size in Bytes
541 static INT
convert_PCREDENTIALW_to_PCREDENTIALA(const CREDENTIALW
*CredentialW
, PCREDENTIALA CredentialA
, DWORD len
)
545 INT needed
= sizeof(CREDENTIALA
);
549 if (CredentialW
->TargetName
)
550 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetName
, -1, NULL
, 0, NULL
, NULL
);
551 if (CredentialW
->Comment
)
552 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->Comment
, -1, NULL
, 0, NULL
, NULL
);
553 needed
+= CredentialW
->CredentialBlobSize
;
554 if (CredentialW
->TargetAlias
)
555 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetAlias
, -1, NULL
, 0, NULL
, NULL
);
556 if (CredentialW
->UserName
)
557 needed
+= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->UserName
, -1, NULL
, 0, NULL
, NULL
);
563 buffer
= (char *)CredentialA
+ sizeof(CREDENTIALA
);
564 len
-= sizeof(CREDENTIALA
);
565 CredentialA
->Flags
= CredentialW
->Flags
;
566 CredentialA
->Type
= CredentialW
->Type
;
568 if (CredentialW
->TargetName
)
570 CredentialA
->TargetName
= buffer
;
571 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetName
, -1, buffer
, len
, NULL
, NULL
);
572 buffer
+= string_len
;
573 needed
+= string_len
;
577 CredentialA
->TargetName
= NULL
;
578 if (CredentialW
->Comment
)
580 CredentialA
->Comment
= buffer
;
581 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->Comment
, -1, buffer
, len
, NULL
, NULL
);
582 buffer
+= string_len
;
583 needed
+= string_len
;
587 CredentialA
->Comment
= NULL
;
588 CredentialA
->LastWritten
= CredentialW
->LastWritten
;
589 CredentialA
->CredentialBlobSize
= CredentialW
->CredentialBlobSize
;
590 if (CredentialW
->CredentialBlobSize
&& (CredentialW
->CredentialBlobSize
<= len
))
592 CredentialA
->CredentialBlob
=(LPBYTE
)buffer
;
593 memcpy(CredentialA
->CredentialBlob
, CredentialW
->CredentialBlob
,
594 CredentialW
->CredentialBlobSize
);
595 buffer
+= CredentialW
->CredentialBlobSize
;
596 needed
+= CredentialW
->CredentialBlobSize
;
597 len
-= CredentialW
->CredentialBlobSize
;
600 CredentialA
->CredentialBlob
= NULL
;
601 CredentialA
->Persist
= CredentialW
->Persist
;
602 CredentialA
->AttributeCount
= 0;
603 CredentialA
->Attributes
= NULL
; /* FIXME */
604 if (CredentialW
->TargetAlias
)
606 CredentialA
->TargetAlias
= buffer
;
607 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->TargetAlias
, -1, buffer
, len
, NULL
, NULL
);
608 buffer
+= string_len
;
609 needed
+= string_len
;
613 CredentialA
->TargetAlias
= NULL
;
614 if (CredentialW
->UserName
)
616 CredentialA
->UserName
= buffer
;
617 string_len
= WideCharToMultiByte(CP_ACP
, 0, CredentialW
->UserName
, -1, buffer
, len
, NULL
, NULL
);
618 needed
+= string_len
;
621 CredentialA
->UserName
= NULL
;
626 /******************************************************************************
627 * convert_PCREDENTIALA_to_PCREDENTIALW [internal]
629 * convert a Credential struct from ANSI to UNICODE and return the needed size in Bytes
632 static INT
convert_PCREDENTIALA_to_PCREDENTIALW(const CREDENTIALA
*CredentialA
, PCREDENTIALW CredentialW
, INT len
)
636 INT needed
= sizeof(CREDENTIALW
);
640 if (CredentialA
->TargetName
)
641 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetName
, -1, NULL
, 0);
642 if (CredentialA
->Comment
)
643 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->Comment
, -1, NULL
, 0);
644 needed
+= CredentialA
->CredentialBlobSize
;
645 if (CredentialA
->TargetAlias
)
646 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetAlias
, -1, NULL
, 0);
647 if (CredentialA
->UserName
)
648 needed
+= sizeof(WCHAR
) * MultiByteToWideChar(CP_ACP
, 0, CredentialA
->UserName
, -1, NULL
, 0);
653 buffer
= (char *)CredentialW
+ sizeof(CREDENTIALW
);
654 len
-= sizeof(CREDENTIALW
);
655 CredentialW
->Flags
= CredentialA
->Flags
;
656 CredentialW
->Type
= CredentialA
->Type
;
657 if (CredentialA
->TargetName
)
659 CredentialW
->TargetName
= (LPWSTR
)buffer
;
660 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetName
, -1, CredentialW
->TargetName
, len
/ sizeof(WCHAR
));
661 buffer
+= sizeof(WCHAR
) * string_len
;
662 needed
+= sizeof(WCHAR
) * string_len
;
663 len
-= sizeof(WCHAR
) * string_len
;
666 CredentialW
->TargetName
= NULL
;
667 if (CredentialA
->Comment
)
669 CredentialW
->Comment
= (LPWSTR
)buffer
;
670 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->Comment
, -1, CredentialW
->Comment
, len
/ sizeof(WCHAR
));
671 buffer
+= sizeof(WCHAR
) * string_len
;
672 needed
+= sizeof(WCHAR
) * string_len
;
673 len
-= sizeof(WCHAR
) * string_len
;
676 CredentialW
->Comment
= NULL
;
677 CredentialW
->LastWritten
= CredentialA
->LastWritten
;
678 CredentialW
->CredentialBlobSize
= CredentialA
->CredentialBlobSize
;
679 if (CredentialA
->CredentialBlobSize
)
681 CredentialW
->CredentialBlob
=(LPBYTE
)buffer
;
682 memcpy(CredentialW
->CredentialBlob
, CredentialA
->CredentialBlob
,
683 CredentialA
->CredentialBlobSize
);
684 buffer
+= CredentialA
->CredentialBlobSize
;
685 needed
+= CredentialA
->CredentialBlobSize
;
686 len
-= CredentialA
->CredentialBlobSize
;
689 CredentialW
->CredentialBlob
= NULL
;
690 CredentialW
->Persist
= CredentialA
->Persist
;
691 CredentialW
->AttributeCount
= 0;
692 CredentialW
->Attributes
= NULL
; /* FIXME */
693 if (CredentialA
->TargetAlias
)
695 CredentialW
->TargetAlias
= (LPWSTR
)buffer
;
696 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->TargetAlias
, -1, CredentialW
->TargetAlias
, len
/ sizeof(WCHAR
));
697 buffer
+= sizeof(WCHAR
) * string_len
;
698 needed
+= sizeof(WCHAR
) * string_len
;
699 len
-= sizeof(WCHAR
) * string_len
;
702 CredentialW
->TargetAlias
= NULL
;
703 if (CredentialA
->UserName
)
705 CredentialW
->UserName
= (LPWSTR
)buffer
;
706 string_len
= MultiByteToWideChar(CP_ACP
, 0, CredentialA
->UserName
, -1, CredentialW
->UserName
, len
/ sizeof(WCHAR
));
707 needed
+= sizeof(WCHAR
) * string_len
;
710 CredentialW
->UserName
= NULL
;
715 /******************************************************************************
716 * CredDeleteA [ADVAPI32.@]
718 BOOL WINAPI
CredDeleteA(LPCSTR TargetName
, DWORD Type
, DWORD Flags
)
724 TRACE("(%s, %d, 0x%x)\n", debugstr_a(TargetName
), Type
, Flags
);
728 SetLastError(ERROR_INVALID_PARAMETER
);
732 len
= MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, NULL
, 0);
733 TargetNameW
= heap_alloc(len
* sizeof(WCHAR
));
736 SetLastError(ERROR_OUTOFMEMORY
);
739 MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, TargetNameW
, len
);
741 ret
= CredDeleteW(TargetNameW
, Type
, Flags
);
743 heap_free(TargetNameW
);
748 static DWORD
host_delete_credential( const WCHAR
*targetname
)
750 struct mountmgr_credential
*cred
;
751 DWORD size
, name_size
= (lstrlenW( targetname
) + 1) * sizeof(WCHAR
);
756 mgr
= CreateFileW( MOUNTMGR_DOS_DEVICE_NAME
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
,
757 OPEN_EXISTING
, 0, 0 );
758 if (mgr
== INVALID_HANDLE_VALUE
) return GetLastError();
760 size
= sizeof(*cred
) + name_size
;
761 if (!(cred
= heap_alloc( size
)))
764 return ERROR_OUTOFMEMORY
;
766 cred
->targetname_offset
= sizeof(*cred
);
767 cred
->targetname_size
= name_size
;
768 ptr
= (WCHAR
*)(cred
+ 1);
769 lstrcpyW( ptr
, targetname
);
771 ret
= DeviceIoControl( mgr
, IOCTL_MOUNTMGR_DELETE_CREDENTIAL
, cred
, size
, NULL
, 0, NULL
, NULL
);
775 return ret
? ERROR_SUCCESS
: GetLastError();
778 /******************************************************************************
779 * CredDeleteW [ADVAPI32.@]
781 BOOL WINAPI
CredDeleteW(LPCWSTR TargetName
, DWORD Type
, DWORD Flags
)
787 TRACE("(%s, %d, 0x%x)\n", debugstr_w(TargetName
), Type
, Flags
);
791 SetLastError(ERROR_INVALID_PARAMETER
);
795 if (Type
!= CRED_TYPE_GENERIC
&& Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
797 FIXME("unhandled type %d\n", Type
);
798 SetLastError(ERROR_INVALID_PARAMETER
);
804 FIXME("unhandled flags 0x%x\n", Flags
);
805 SetLastError(ERROR_INVALID_FLAGS
);
809 if (Type
== CRED_TYPE_DOMAIN_PASSWORD
)
811 ret
= host_delete_credential(TargetName
);
812 if (ret
== ERROR_SUCCESS
)
816 ret
= open_cred_mgr_key(&hkeyMgr
, TRUE
);
817 if (ret
!= ERROR_SUCCESS
)
819 WARN("couldn't open/create manager key, error %d\n", ret
);
820 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
824 key_name
= get_key_name_for_target(TargetName
, Type
);
825 ret
= RegDeleteKeyW(hkeyMgr
, key_name
);
827 RegCloseKey(hkeyMgr
);
828 if (ret
!= ERROR_SUCCESS
)
830 SetLastError(ERROR_NOT_FOUND
);
837 /******************************************************************************
838 * CredEnumerateA [ADVAPI32.@]
840 BOOL WINAPI
CredEnumerateA(LPCSTR Filter
, DWORD Flags
, DWORD
*Count
,
841 PCREDENTIALA
**Credentials
)
844 PCREDENTIALW
*CredentialsW
;
850 TRACE("(%s, 0x%x, %p, %p)\n", debugstr_a(Filter
), Flags
, Count
, Credentials
);
854 len
= MultiByteToWideChar(CP_ACP
, 0, Filter
, -1, NULL
, 0);
855 FilterW
= heap_alloc(len
* sizeof(WCHAR
));
858 SetLastError(ERROR_OUTOFMEMORY
);
861 MultiByteToWideChar(CP_ACP
, 0, Filter
, -1, FilterW
, len
);
866 if (!CredEnumerateW(FilterW
, Flags
, Count
, &CredentialsW
))
873 len
= *Count
* sizeof(PCREDENTIALA
);
874 for (i
= 0; i
< *Count
; i
++)
875 len
+= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], NULL
, 0);
877 *Credentials
= heap_alloc(len
);
880 CredFree(CredentialsW
);
881 SetLastError(ERROR_OUTOFMEMORY
);
885 buffer
= (char *)&(*Credentials
)[*Count
];
886 len
-= *Count
* sizeof(PCREDENTIALA
);
887 for (i
= 0; i
< *Count
; i
++)
889 (*Credentials
)[i
] = (PCREDENTIALA
)buffer
;
890 needed
= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], (*Credentials
)[i
], len
);
895 CredFree(CredentialsW
);
900 #define CRED_LIST_COUNT 16
901 #define CRED_DATA_SIZE 2048
902 static DWORD
host_enumerate_credentials( const WCHAR
*filter
, CREDENTIALW
**credentials
, char *buf
, DWORD
*len
, DWORD
*count
)
904 struct mountmgr_credential_list
*list
, *tmp
;
905 DWORD i
, j
, ret
, size
, filter_size
, offset
= 0;
909 if (filter
) filter_size
= (lstrlenW( filter
) + 1) * sizeof(WCHAR
);
913 filter_size
= sizeof(L
"");
916 mgr
= CreateFileW( MOUNTMGR_DOS_DEVICE_NAME
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
, OPEN_EXISTING
, 0, 0 );
917 if (mgr
== INVALID_HANDLE_VALUE
) return GetLastError();
919 size
= FIELD_OFFSET( struct mountmgr_credential_list
, creds
[CRED_LIST_COUNT
] ) + filter_size
+ CRED_DATA_SIZE
;
920 if (!(list
= heap_alloc( size
)))
923 return ERROR_OUTOFMEMORY
;
928 list
->filter_offset
= sizeof(*list
);
929 list
->filter_size
= filter_size
;
930 ptr
= (WCHAR
*)((char *)list
+ list
->filter_offset
);
931 lstrcpyW( ptr
, filter
);
933 if (DeviceIoControl( mgr
, IOCTL_MOUNTMGR_ENUMERATE_CREDENTIALS
, list
, size
, list
, size
, NULL
, NULL
)) break;
934 if ((ret
= GetLastError()) != ERROR_MORE_DATA
) goto done
;
936 size
= list
->size
+ filter_size
;
937 if (!(tmp
= heap_realloc( list
, size
)))
939 ret
= ERROR_OUTOFMEMORY
;
945 for (i
= 0, j
= *count
; i
< list
->count
; i
++)
947 CREDENTIALW
*cred
= (CREDENTIALW
*)(buf
+ offset
);
949 offset
+= sizeof(*cred
) + list
->creds
[i
].targetname_size
+ list
->creds
[i
].comment_size
+ list
->creds
[i
].blob_size
+
950 list
->creds
[i
].username_size
;
953 ptr
= (WCHAR
*)(cred
+ 1);
955 cred
->Type
= CRED_TYPE_DOMAIN_PASSWORD
;
956 cred
->TargetName
= ptr
;
957 memcpy( cred
->TargetName
, (char *)&list
->creds
[i
] + list
->creds
[i
].targetname_offset
, list
->creds
[i
].targetname_size
);
958 ptr
+= list
->creds
[i
].targetname_size
/ sizeof(WCHAR
);
959 if (list
->creds
[i
].comment_size
)
962 memcpy( cred
->Comment
, (char *)&list
->creds
[i
] + list
->creds
[i
].comment_offset
, list
->creds
[i
].comment_size
);
963 ptr
+= list
->creds
[i
].comment_size
/ sizeof(WCHAR
);
965 else cred
->Comment
= NULL
;
966 cred
->LastWritten
= list
->creds
[i
].last_written
;
967 if (list
->creds
[i
].blob_size
)
969 cred
->CredentialBlobSize
= list
->creds
[i
].blob_size
;
970 cred
->CredentialBlob
= (BYTE
*)ptr
;
971 memcpy( cred
->CredentialBlob
, (char *)&list
->creds
[i
] + list
->creds
[i
].blob_offset
, list
->creds
[i
].blob_size
);
972 ptr
+= list
->creds
[i
].blob_size
/ sizeof(WCHAR
);
976 cred
->CredentialBlobSize
= 0;
977 cred
->CredentialBlob
= NULL
;
979 cred
->Persist
= CRED_PERSIST_LOCAL_MACHINE
;
980 cred
->AttributeCount
= 0;
981 cred
->Attributes
= NULL
;
982 cred
->TargetAlias
= NULL
;
983 if (list
->creds
[i
].username_size
)
985 cred
->UserName
= ptr
;
986 memcpy( cred
->UserName
, (char *)&list
->creds
[i
] + list
->creds
[i
].username_offset
, list
->creds
[i
].username_size
);
988 else cred
->UserName
= NULL
;
989 if (credentials
) credentials
[j
++] = cred
;
993 *count
+= list
->count
;
1002 /******************************************************************************
1003 * CredEnumerateW [ADVAPI32.@]
1005 BOOL WINAPI
CredEnumerateW(LPCWSTR Filter
, DWORD Flags
, DWORD
*Count
, PCREDENTIALW
**Credentials
)
1010 DWORD target_name_len
;
1013 BYTE key_data
[KEY_SIZE
];
1015 TRACE("(%s, 0x%x, %p, %p)\n", debugstr_w(Filter
), Flags
, Count
, Credentials
);
1019 SetLastError(ERROR_INVALID_FLAGS
);
1023 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
1024 if (ret
!= ERROR_SUCCESS
)
1026 WARN("couldn't open/create manager key, error %d\n", ret
);
1027 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1031 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
1032 if (ret
!= ERROR_SUCCESS
)
1034 RegCloseKey(hkeyMgr
);
1039 ret
= RegQueryInfoKeyW(hkeyMgr
, NULL
, NULL
, NULL
, NULL
, &target_name_len
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
1040 if (ret
!= ERROR_SUCCESS
)
1042 RegCloseKey(hkeyMgr
);
1047 target_name
= heap_alloc((target_name_len
+1)*sizeof(WCHAR
));
1050 RegCloseKey(hkeyMgr
);
1051 SetLastError(ERROR_OUTOFMEMORY
);
1057 ret
= registry_enumerate_credentials(hkeyMgr
, Filter
, target_name
, target_name_len
,
1058 key_data
, NULL
, NULL
, &len
, Count
);
1059 if (ret
== ERROR_SUCCESS
)
1061 ret
= host_enumerate_credentials(Filter
, NULL
, NULL
, &len
, Count
);
1062 if (ret
== ERROR_NOT_SUPPORTED
) ret
= ERROR_SUCCESS
;
1064 if (ret
== ERROR_SUCCESS
&& *Count
== 0)
1065 ret
= ERROR_NOT_FOUND
;
1066 if (ret
!= ERROR_SUCCESS
)
1068 heap_free(target_name
);
1069 RegCloseKey(hkeyMgr
);
1073 len
+= *Count
* sizeof(PCREDENTIALW
);
1075 if (ret
== ERROR_SUCCESS
)
1077 buffer
= heap_alloc(len
);
1078 *Credentials
= (PCREDENTIALW
*)buffer
;
1081 buffer
+= *Count
* sizeof(PCREDENTIALW
);
1083 ret
= registry_enumerate_credentials(hkeyMgr
, Filter
, target_name
, target_name_len
, key_data
,
1084 *Credentials
, &buffer
, &len
, Count
);
1085 if (ret
== ERROR_SUCCESS
)
1087 ret
= host_enumerate_credentials(Filter
, *Credentials
, buffer
, &len
, Count
);
1088 if (ret
== ERROR_NOT_SUPPORTED
) ret
= ERROR_SUCCESS
;
1091 else ret
= ERROR_OUTOFMEMORY
;
1094 heap_free(target_name
);
1095 RegCloseKey(hkeyMgr
);
1097 if (ret
!= ERROR_SUCCESS
)
1105 /******************************************************************************
1106 * CredFree [ADVAPI32.@]
1108 VOID WINAPI
CredFree(PVOID Buffer
)
1113 /******************************************************************************
1114 * CredReadA [ADVAPI32.@]
1116 BOOL WINAPI
CredReadA(LPCSTR TargetName
, DWORD Type
, DWORD Flags
, PCREDENTIALA
*Credential
)
1119 PCREDENTIALW CredentialW
;
1122 TRACE("(%s, %d, 0x%x, %p)\n", debugstr_a(TargetName
), Type
, Flags
, Credential
);
1126 SetLastError(ERROR_INVALID_PARAMETER
);
1130 len
= MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, NULL
, 0);
1131 TargetNameW
= heap_alloc(len
* sizeof(WCHAR
));
1134 SetLastError(ERROR_OUTOFMEMORY
);
1137 MultiByteToWideChar(CP_ACP
, 0, TargetName
, -1, TargetNameW
, len
);
1139 if (!CredReadW(TargetNameW
, Type
, Flags
, &CredentialW
))
1141 heap_free(TargetNameW
);
1144 heap_free(TargetNameW
);
1146 len
= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW
, NULL
, 0);
1147 *Credential
= heap_alloc(len
);
1150 SetLastError(ERROR_OUTOFMEMORY
);
1153 convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW
, *Credential
, len
);
1155 CredFree(CredentialW
);
1160 static DWORD
host_read_credential( const WCHAR
*targetname
, CREDENTIALW
**ret_credential
)
1162 struct mountmgr_credential
*cred_in
, *cred_out
= NULL
, *tmp
;
1163 DWORD err
= ERROR_OUTOFMEMORY
, size_in
, size_out
, size_name
= (lstrlenW( targetname
) + 1) * sizeof(WCHAR
);
1168 mgr
= CreateFileW( MOUNTMGR_DOS_DEVICE_NAME
, GENERIC_READ
|GENERIC_WRITE
, FILE_SHARE_READ
|FILE_SHARE_WRITE
, NULL
,
1169 OPEN_EXISTING
, 0, 0 );
1170 if (mgr
== INVALID_HANDLE_VALUE
) return GetLastError();
1172 size_in
= sizeof(*cred_in
) + size_name
;
1173 if (!(cred_in
= heap_alloc( size_in
)))
1176 return ERROR_OUTOFMEMORY
;
1178 cred_in
->targetname_offset
= sizeof(*cred_in
);
1179 cred_in
->targetname_size
= size_name
;
1180 ptr
= (WCHAR
*)(cred_in
+ 1);
1181 lstrcpyW( ptr
, targetname
);
1184 if (!(cred_out
= heap_alloc( size_out
))) goto done
;
1188 ret
= DeviceIoControl( mgr
, IOCTL_MOUNTMGR_READ_CREDENTIAL
, cred_in
, size_in
, cred_out
, size_out
, NULL
, NULL
);
1189 if (ret
|| (err
= GetLastError()) != ERROR_MORE_DATA
) break;
1191 if (!(tmp
= heap_realloc( cred_out
, size_out
))) goto done
;
1197 CREDENTIALW
*credential
;
1198 DWORD size
= sizeof(*credential
) + cred_out
->targetname_size
+ cred_out
->username_size
+ cred_out
->comment_size
+
1199 cred_out
->blob_size
;
1201 if (!(credential
= heap_alloc_zero( size
)))
1203 err
= ERROR_OUTOFMEMORY
;
1206 ptr
= (WCHAR
*)(credential
+ 1);
1208 credential
->Type
= CRED_TYPE_DOMAIN_PASSWORD
;
1209 memcpy( ptr
, (char *)cred_out
+ cred_out
->targetname_offset
, cred_out
->targetname_size
);
1210 credential
->TargetName
= ptr
;
1211 ptr
+= lstrlenW( ptr
) + 1;
1212 if (cred_out
->comment_size
)
1214 memcpy( ptr
, (char *)cred_out
+ cred_out
->comment_offset
, cred_out
->comment_size
);
1215 credential
->Comment
= ptr
;
1216 ptr
+= lstrlenW( ptr
) + 1;
1218 credential
->LastWritten
= cred_out
->last_written
;
1219 if ((credential
->CredentialBlobSize
= cred_out
->blob_size
))
1221 memcpy( ptr
, (char *)cred_out
+ cred_out
->blob_offset
, cred_out
->blob_size
);
1222 credential
->CredentialBlob
= (BYTE
*)ptr
;
1223 ptr
+= cred_out
->blob_size
/ sizeof(WCHAR
);
1225 credential
->Persist
= CRED_PERSIST_LOCAL_MACHINE
;
1226 memcpy( ptr
, (char *)cred_out
+ cred_out
->username_offset
, cred_out
->username_size
);
1227 credential
->UserName
= ptr
;
1229 *ret_credential
= credential
;
1230 err
= ERROR_SUCCESS
;
1234 heap_free( cred_in
);
1235 heap_free( cred_out
);
1240 /******************************************************************************
1241 * CredReadW [ADVAPI32.@]
1243 BOOL WINAPI
CredReadW(LPCWSTR TargetName
, DWORD Type
, DWORD Flags
, PCREDENTIALW
*Credential
)
1250 BYTE key_data
[KEY_SIZE
];
1252 TRACE("(%s, %d, 0x%x, %p)\n", debugstr_w(TargetName
), Type
, Flags
, Credential
);
1256 SetLastError(ERROR_INVALID_PARAMETER
);
1260 if (Type
!= CRED_TYPE_GENERIC
&& Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
1262 FIXME("unhandled type %d\n", Type
);
1263 SetLastError(ERROR_INVALID_PARAMETER
);
1269 FIXME("unhandled flags 0x%x\n", Flags
);
1270 SetLastError(ERROR_INVALID_FLAGS
);
1274 if (Type
== CRED_TYPE_DOMAIN_PASSWORD
)
1276 ret
= host_read_credential( TargetName
, Credential
);
1277 if (ret
!= ERROR_SUCCESS
&& ret
!= ERROR_NOT_SUPPORTED
)
1282 if (ret
== ERROR_SUCCESS
) return TRUE
;
1285 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
1286 if (ret
!= ERROR_SUCCESS
)
1288 WARN("couldn't open/create manager key, error %d\n", ret
);
1289 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1293 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
1294 if (ret
!= ERROR_SUCCESS
)
1296 RegCloseKey(hkeyMgr
);
1301 key_name
= get_key_name_for_target(TargetName
, Type
);
1302 ret
= RegOpenKeyExW(hkeyMgr
, key_name
, 0, KEY_QUERY_VALUE
, &hkeyCred
);
1303 heap_free(key_name
);
1304 if (ret
!= ERROR_SUCCESS
)
1306 TRACE("credentials for target name %s not found\n", debugstr_w(TargetName
));
1307 SetLastError(ERROR_NOT_FOUND
);
1311 len
= sizeof(**Credential
);
1312 ret
= registry_read_credential(hkeyCred
, NULL
, key_data
, NULL
, &len
);
1313 if (ret
== ERROR_SUCCESS
)
1315 *Credential
= heap_alloc(len
);
1318 len
= sizeof(**Credential
);
1319 ret
= registry_read_credential(hkeyCred
, *Credential
, key_data
,
1320 (char *)(*Credential
+ 1), &len
);
1323 ret
= ERROR_OUTOFMEMORY
;
1326 RegCloseKey(hkeyCred
);
1327 RegCloseKey(hkeyMgr
);
1329 if (ret
!= ERROR_SUCCESS
)
1337 /******************************************************************************
1338 * CredReadDomainCredentialsA [ADVAPI32.@]
1340 BOOL WINAPI
CredReadDomainCredentialsA(PCREDENTIAL_TARGET_INFORMATIONA TargetInformation
,
1341 DWORD Flags
, DWORD
*Size
, PCREDENTIALA
**Credentials
)
1343 PCREDENTIAL_TARGET_INFORMATIONW TargetInformationW
;
1346 WCHAR
*buffer
, *end
;
1348 PCREDENTIALW
* CredentialsW
;
1350 TRACE("(%p, 0x%x, %p, %p)\n", TargetInformation
, Flags
, Size
, Credentials
);
1352 /* follow Windows behavior - do not test for NULL, initialize early */
1354 *Credentials
= NULL
;
1356 if (!TargetInformation
)
1358 SetLastError(ERROR_INVALID_PARAMETER
);
1362 len
= sizeof(*TargetInformationW
);
1363 if (TargetInformation
->TargetName
)
1364 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->TargetName
, -1, NULL
, 0) * sizeof(WCHAR
);
1365 if (TargetInformation
->NetbiosServerName
)
1366 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosServerName
, -1, NULL
, 0) * sizeof(WCHAR
);
1367 if (TargetInformation
->DnsServerName
)
1368 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsServerName
, -1, NULL
, 0) * sizeof(WCHAR
);
1369 if (TargetInformation
->NetbiosDomainName
)
1370 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosDomainName
, -1, NULL
, 0) * sizeof(WCHAR
);
1371 if (TargetInformation
->DnsDomainName
)
1372 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsDomainName
, -1, NULL
, 0) * sizeof(WCHAR
);
1373 if (TargetInformation
->DnsTreeName
)
1374 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsTreeName
, -1, NULL
, 0) * sizeof(WCHAR
);
1375 if (TargetInformation
->PackageName
)
1376 len
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->PackageName
, -1, NULL
, 0) * sizeof(WCHAR
);
1378 TargetInformationW
= heap_alloc(len
);
1379 if (!TargetInformationW
)
1381 SetLastError(ERROR_OUTOFMEMORY
);
1384 buffer
= (WCHAR
*)(TargetInformationW
+ 1);
1385 end
= (WCHAR
*)((char *)TargetInformationW
+ len
);
1387 if (TargetInformation
->TargetName
)
1389 TargetInformationW
->TargetName
= buffer
;
1390 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->TargetName
, -1,
1391 TargetInformationW
->TargetName
, end
- buffer
);
1393 TargetInformationW
->TargetName
= NULL
;
1395 if (TargetInformation
->NetbiosServerName
)
1397 TargetInformationW
->NetbiosServerName
= buffer
;
1398 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosServerName
, -1,
1399 TargetInformationW
->NetbiosServerName
, end
- buffer
);
1401 TargetInformationW
->NetbiosServerName
= NULL
;
1403 if (TargetInformation
->DnsServerName
)
1405 TargetInformationW
->DnsServerName
= buffer
;
1406 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsServerName
, -1,
1407 TargetInformationW
->DnsServerName
, end
- buffer
);
1409 TargetInformationW
->DnsServerName
= NULL
;
1411 if (TargetInformation
->NetbiosDomainName
)
1413 TargetInformationW
->NetbiosDomainName
= buffer
;
1414 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->NetbiosDomainName
, -1,
1415 TargetInformationW
->NetbiosDomainName
, end
- buffer
);
1417 TargetInformationW
->NetbiosDomainName
= NULL
;
1419 if (TargetInformation
->DnsDomainName
)
1421 TargetInformationW
->DnsDomainName
= buffer
;
1422 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsDomainName
, -1,
1423 TargetInformationW
->DnsDomainName
, end
- buffer
);
1425 TargetInformationW
->DnsDomainName
= NULL
;
1427 if (TargetInformation
->DnsTreeName
)
1429 TargetInformationW
->DnsTreeName
= buffer
;
1430 buffer
+= MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->DnsTreeName
, -1,
1431 TargetInformationW
->DnsTreeName
, end
- buffer
);
1433 TargetInformationW
->DnsTreeName
= NULL
;
1435 if (TargetInformation
->PackageName
)
1437 TargetInformationW
->PackageName
= buffer
;
1438 MultiByteToWideChar(CP_ACP
, 0, TargetInformation
->PackageName
, -1,
1439 TargetInformationW
->PackageName
, end
- buffer
);
1441 TargetInformationW
->PackageName
= NULL
;
1443 TargetInformationW
->Flags
= TargetInformation
->Flags
;
1444 TargetInformationW
->CredTypeCount
= TargetInformation
->CredTypeCount
;
1445 TargetInformationW
->CredTypes
= TargetInformation
->CredTypes
;
1447 ret
= CredReadDomainCredentialsW(TargetInformationW
, Flags
, Size
, &CredentialsW
);
1449 heap_free(TargetInformationW
);
1456 len
= *Size
* sizeof(PCREDENTIALA
);
1457 for (i
= 0; i
< *Size
; i
++)
1458 len
+= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], NULL
, 0);
1460 *Credentials
= heap_alloc(len
);
1463 CredFree(CredentialsW
);
1464 SetLastError(ERROR_OUTOFMEMORY
);
1468 buf
= (char *)&(*Credentials
)[*Size
];
1469 len
-= *Size
* sizeof(PCREDENTIALA
);
1470 for (i
= 0; i
< *Size
; i
++)
1472 (*Credentials
)[i
] = (PCREDENTIALA
)buf
;
1473 needed
= convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW
[i
], (*Credentials
)[i
], len
);
1478 CredFree(CredentialsW
);
1483 /******************************************************************************
1484 * CredReadDomainCredentialsW [ADVAPI32.@]
1486 BOOL WINAPI
CredReadDomainCredentialsW(PCREDENTIAL_TARGET_INFORMATIONW TargetInformation
, DWORD Flags
,
1487 DWORD
*Size
, PCREDENTIALW
**Credentials
)
1489 FIXME("(%p, 0x%x, %p, %p) stub\n", TargetInformation
, Flags
, Size
, Credentials
);
1491 /* follow Windows behavior - do not test for NULL, initialize early */
1493 *Credentials
= NULL
;
1494 if (!TargetInformation
)
1496 SetLastError(ERROR_INVALID_PARAMETER
);
1500 SetLastError(ERROR_NOT_FOUND
);
1504 /******************************************************************************
1505 * CredWriteA [ADVAPI32.@]
1507 BOOL WINAPI
CredWriteA(PCREDENTIALA Credential
, DWORD Flags
)
1511 PCREDENTIALW CredentialW
;
1513 TRACE("(%p, 0x%x)\n", Credential
, Flags
);
1515 if (!Credential
|| !Credential
->TargetName
)
1517 SetLastError(ERROR_INVALID_PARAMETER
);
1521 len
= convert_PCREDENTIALA_to_PCREDENTIALW(Credential
, NULL
, 0);
1522 CredentialW
= heap_alloc(len
);
1525 SetLastError(ERROR_OUTOFMEMORY
);
1529 convert_PCREDENTIALA_to_PCREDENTIALW(Credential
, CredentialW
, len
);
1531 ret
= CredWriteW(CredentialW
, Flags
);
1533 heap_free(CredentialW
);
1538 /******************************************************************************
1539 * CredWriteW [ADVAPI32.@]
1541 BOOL WINAPI
CredWriteW(PCREDENTIALW Credential
, DWORD Flags
)
1547 BYTE key_data
[KEY_SIZE
];
1549 TRACE("(%p, 0x%x)\n", Credential
, Flags
);
1551 if (!Credential
|| !Credential
->TargetName
)
1553 SetLastError(ERROR_INVALID_PARAMETER
);
1557 if (Flags
& ~CRED_PRESERVE_CREDENTIAL_BLOB
)
1559 FIXME("unhandled flags 0x%x\n", Flags
);
1560 SetLastError(ERROR_INVALID_FLAGS
);
1564 if (Credential
->Type
!= CRED_TYPE_GENERIC
&& Credential
->Type
!= CRED_TYPE_DOMAIN_PASSWORD
)
1566 FIXME("unhandled type %d\n", Credential
->Type
);
1567 SetLastError(ERROR_INVALID_PARAMETER
);
1571 TRACE("Credential->Flags = 0x%08x\n", Credential
->Flags
);
1572 TRACE("Credential->Type = %u\n", Credential
->Type
);
1573 TRACE("Credential->TargetName = %s\n", debugstr_w(Credential
->TargetName
));
1574 TRACE("Credential->Comment = %s\n", debugstr_w(Credential
->Comment
));
1575 TRACE("Credential->Persist = %u\n", Credential
->Persist
);
1576 TRACE("Credential->TargetAlias = %s\n", debugstr_w(Credential
->TargetAlias
));
1577 TRACE("Credential->UserName = %s\n", debugstr_w(Credential
->UserName
));
1579 if (Credential
->Type
== CRED_TYPE_DOMAIN_PASSWORD
)
1581 if (!Credential
->UserName
||
1582 (Credential
->Persist
== CRED_PERSIST_ENTERPRISE
&&
1583 (!wcschr(Credential
->UserName
, '\\') && !wcschr(Credential
->UserName
, '@'))))
1585 ERR("bad username %s\n", debugstr_w(Credential
->UserName
));
1586 SetLastError(ERROR_BAD_USERNAME
);
1591 if (!Credential
->AttributeCount
&&
1592 Credential
->Type
== CRED_TYPE_DOMAIN_PASSWORD
&&
1593 (Credential
->Persist
== CRED_PERSIST_LOCAL_MACHINE
|| Credential
->Persist
== CRED_PERSIST_ENTERPRISE
))
1595 ret
= host_write_credential(Credential
, Flags
& CRED_PRESERVE_CREDENTIAL_BLOB
);
1596 if (ret
!= ERROR_SUCCESS
&& ret
!= ERROR_NOT_SUPPORTED
)
1601 if (ret
== ERROR_SUCCESS
) return TRUE
;
1604 ret
= open_cred_mgr_key(&hkeyMgr
, FALSE
);
1605 if (ret
!= ERROR_SUCCESS
)
1607 WARN("couldn't open/create manager key, error %d\n", ret
);
1608 SetLastError(ERROR_NO_SUCH_LOGON_SESSION
);
1612 ret
= get_cred_mgr_encryption_key(hkeyMgr
, key_data
);
1613 if (ret
!= ERROR_SUCCESS
)
1615 RegCloseKey(hkeyMgr
);
1620 key_name
= get_key_name_for_target(Credential
->TargetName
, Credential
->Type
);
1621 ret
= RegCreateKeyExW(hkeyMgr
, key_name
, 0, NULL
,
1622 Credential
->Persist
== CRED_PERSIST_SESSION
? REG_OPTION_VOLATILE
: REG_OPTION_NON_VOLATILE
,
1623 KEY_READ
|KEY_WRITE
, NULL
, &hkeyCred
, NULL
);
1624 heap_free(key_name
);
1625 if (ret
!= ERROR_SUCCESS
)
1627 TRACE("credentials for target name %s not found\n",
1628 debugstr_w(Credential
->TargetName
));
1629 SetLastError(ERROR_NOT_FOUND
);
1633 ret
= registry_write_credential(hkeyCred
, Credential
, key_data
,
1634 Flags
& CRED_PRESERVE_CREDENTIAL_BLOB
);
1636 RegCloseKey(hkeyCred
);
1637 RegCloseKey(hkeyMgr
);
1639 if (ret
!= ERROR_SUCCESS
)
1647 /******************************************************************************
1648 * CredGetSessionTypes [ADVAPI32.@]
1650 WINADVAPI BOOL WINAPI
CredGetSessionTypes(DWORD persistCount
, LPDWORD persists
)
1652 TRACE("(%u, %p)\n", persistCount
, persists
);
1654 memset(persists
, CRED_PERSIST_NONE
, persistCount
*sizeof(*persists
));
1655 if (CRED_TYPE_GENERIC
< persistCount
)
1657 persists
[CRED_TYPE_GENERIC
] = CRED_PERSIST_ENTERPRISE
;
1659 if (CRED_TYPE_DOMAIN_PASSWORD
< persistCount
)
1661 persists
[CRED_TYPE_DOMAIN_PASSWORD
] = CRED_PERSIST_ENTERPRISE
;
1667 /******************************************************************************
1668 * CredMarshalCredentialA [ADVAPI32.@]
1670 BOOL WINAPI
CredMarshalCredentialA( CRED_MARSHAL_TYPE type
, PVOID cred
, LPSTR
*out
)
1675 TRACE("%u, %p, %p\n", type
, cred
, out
);
1677 if ((ret
= CredMarshalCredentialW( type
, cred
, &outW
)))
1679 int len
= WideCharToMultiByte( CP_ACP
, 0, outW
, -1, NULL
, 0, NULL
, NULL
);
1680 if (!(*out
= heap_alloc( len
)))
1685 WideCharToMultiByte( CP_ACP
, 0, outW
, -1, *out
, len
, NULL
, NULL
);
1691 static UINT
cred_encode( const char *bin
, unsigned int len
, WCHAR
*cred
)
1693 static const char enc
[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#-";
1698 cred
[n
++] = enc
[bin
[0] & 0x3f];
1699 x
= (bin
[0] & 0xc0) >> 6;
1705 cred
[n
++] = enc
[((bin
[1] & 0xf) << 2) | x
];
1706 x
= (bin
[1] & 0xf0) >> 4;
1712 cred
[n
++] = enc
[((bin
[2] & 0x3) << 4) | x
];
1713 cred
[n
++] = enc
[(bin
[2] & 0xfc) >> 2];
1720 /******************************************************************************
1721 * CredMarshalCredentialW [ADVAPI32.@]
1723 BOOL WINAPI
CredMarshalCredentialW( CRED_MARSHAL_TYPE type
, PVOID cred
, LPWSTR
*out
)
1725 CERT_CREDENTIAL_INFO
*cert
= cred
;
1726 USERNAME_TARGET_CREDENTIAL_INFO
*target
= cred
;
1730 TRACE("%u, %p, %p\n", type
, cred
, out
);
1732 if (!cred
|| (type
== CertCredential
&& cert
->cbSize
< sizeof(*cert
)) ||
1733 (type
!= CertCredential
&& type
!= UsernameTargetCredential
&& type
!= BinaryBlobCredential
) ||
1734 (type
== UsernameTargetCredential
&& (!target
->UserName
|| !target
->UserName
[0])))
1736 SetLastError( ERROR_INVALID_PARAMETER
);
1741 case CertCredential
:
1743 size
= (sizeof(cert
->rgbHashOfCert
) + 2) * 4 / 3;
1744 if (!(p
= heap_alloc( (size
+ 4) * sizeof(WCHAR
) ))) return FALSE
;
1748 len
= cred_encode( (const char *)cert
->rgbHashOfCert
, sizeof(cert
->rgbHashOfCert
), p
+ 3 );
1752 case UsernameTargetCredential
:
1754 len
= lstrlenW( target
->UserName
);
1755 size
= (sizeof(DWORD
) + len
* sizeof(WCHAR
) + 2) * 4 / 3;
1756 if (!(p
= heap_alloc( (size
+ 4) * sizeof(WCHAR
) ))) return FALSE
;
1760 size
= len
* sizeof(WCHAR
);
1761 len
= cred_encode( (const char *)&size
, sizeof(DWORD
), p
+ 3 );
1762 len
+= cred_encode( (const char *)target
->UserName
, size
, p
+ 3 + len
);
1766 case BinaryBlobCredential
:
1767 FIXME("BinaryBlobCredential not implemented\n");
1776 /******************************************************************************
1777 * CredUnmarshalCredentialA [ADVAPI32.@]
1779 BOOL WINAPI
CredUnmarshalCredentialA( LPCSTR cred
, PCRED_MARSHAL_TYPE type
, PVOID
*out
)
1782 WCHAR
*credW
= NULL
;
1784 TRACE("%s, %p, %p\n", debugstr_a(cred
), type
, out
);
1788 int len
= MultiByteToWideChar( CP_ACP
, 0, cred
, -1, NULL
, 0 );
1789 if (!(credW
= heap_alloc( len
* sizeof(WCHAR
) ))) return FALSE
;
1790 MultiByteToWideChar( CP_ACP
, 0, cred
, -1, credW
, len
);
1792 ret
= CredUnmarshalCredentialW( credW
, type
, out
);
1797 static inline char char_decode( WCHAR c
)
1799 if (c
>= 'A' && c
<= 'Z') return c
- 'A';
1800 if (c
>= 'a' && c
<= 'z') return c
- 'a' + 26;
1801 if (c
>= '0' && c
<= '9') return c
- '0' + 52;
1802 if (c
== '#') return 62;
1803 if (c
== '-') return 63;
1807 static BOOL
cred_decode( const WCHAR
*cred
, unsigned int len
, char *buf
)
1810 char c0
, c1
, c2
, c3
;
1811 const WCHAR
*p
= cred
;
1815 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
1816 if ((c1
= char_decode( p
[1] )) > 63) return FALSE
;
1817 if ((c2
= char_decode( p
[2] )) > 63) return FALSE
;
1818 if ((c3
= char_decode( p
[3] )) > 63) return FALSE
;
1820 buf
[i
+ 0] = (c1
<< 6) | c0
;
1821 buf
[i
+ 1] = (c2
<< 4) | (c1
>> 2);
1822 buf
[i
+ 2] = (c3
<< 2) | (c2
>> 4);
1829 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
1830 if ((c1
= char_decode( p
[1] )) > 63) return FALSE
;
1831 if ((c2
= char_decode( p
[2] )) > 63) return FALSE
;
1833 buf
[i
+ 0] = (c1
<< 6) | c0
;
1834 buf
[i
+ 1] = (c2
<< 4) | (c1
>> 2);
1838 if ((c0
= char_decode( p
[0] )) > 63) return FALSE
;
1839 if ((c1
= char_decode( p
[1] )) > 63) return FALSE
;
1841 buf
[i
+ 0] = (c1
<< 6) | c0
;
1850 /******************************************************************************
1851 * CredUnmarshalCredentialW [ADVAPI32.@]
1853 BOOL WINAPI
CredUnmarshalCredentialW( LPCWSTR cred
, PCRED_MARSHAL_TYPE type
, PVOID
*out
)
1855 unsigned int len
, buflen
;
1857 TRACE("%s, %p, %p\n", debugstr_w(cred
), type
, out
);
1859 if (!cred
|| cred
[0] != '@' || cred
[1] != '@' ||
1860 char_decode( cred
[2] ) > 63)
1862 SetLastError( ERROR_INVALID_PARAMETER
);
1865 len
= lstrlenW( cred
+ 3 );
1866 *type
= char_decode( cred
[2] );
1869 case CertCredential
:
1871 char hash
[CERT_HASH_LENGTH
];
1872 CERT_CREDENTIAL_INFO
*cert
;
1874 if (len
!= 27 || !cred_decode( cred
+ 3, len
, hash
))
1876 SetLastError( ERROR_INVALID_PARAMETER
);
1879 if (!(cert
= heap_alloc( sizeof(*cert
) ))) return FALSE
;
1880 memcpy( cert
->rgbHashOfCert
, hash
, sizeof(cert
->rgbHashOfCert
) );
1881 cert
->cbSize
= sizeof(*cert
);
1885 case UsernameTargetCredential
:
1887 USERNAME_TARGET_CREDENTIAL_INFO
*target
;
1890 if (len
< 9 || !cred_decode( cred
+ 3, 6, (char *)&size
) ||
1891 size
% sizeof(WCHAR
) || len
- 6 != (size
* 4 + 2) / 3)
1893 SetLastError( ERROR_INVALID_PARAMETER
);
1896 buflen
= sizeof(*target
) + size
+ sizeof(WCHAR
);
1897 if (!(target
= heap_alloc( buflen
))) return FALSE
;
1898 if (!cred_decode( cred
+ 9, len
- 6, (char *)(target
+ 1) ))
1900 heap_free( target
);
1903 target
->UserName
= (WCHAR
*)(target
+ 1);
1904 target
->UserName
[size
/ sizeof(WCHAR
)] = 0;
1908 case BinaryBlobCredential
:
1909 FIXME("BinaryBlobCredential not implemented\n");
1912 WARN("unhandled type %u\n", *type
);
1913 SetLastError( ERROR_INVALID_PARAMETER
);
1919 /******************************************************************************
1920 * CredIsMarshaledCredentialW [ADVAPI32.@]
1922 * Check, if the name parameter is a marshaled credential, hash or binary blob
1925 * name the name to check
1928 * TRUE: the name parameter is a marshaled credential, hash or binary blob
1929 * FALSE: the name is a plain username
1931 BOOL WINAPI
CredIsMarshaledCredentialW(LPCWSTR name
)
1933 TRACE("(%s)\n", debugstr_w(name
));
1935 if (name
&& name
[0] == '@' && name
[1] == '@' && name
[2] > 'A' && name
[3])
1937 char hash
[CERT_HASH_LENGTH
];
1938 int len
= lstrlenW(name
+ 3 );
1941 if ((name
[2] - 'A') == CertCredential
&& (len
== 27) && cred_decode(name
+ 3, len
, hash
))
1944 if (((name
[2] - 'A') == UsernameTargetCredential
) &&
1945 (len
>= 9) && cred_decode(name
+ 3, 6, (char *)&size
) && size
)
1948 if ((name
[2] - 'A') == BinaryBlobCredential
)
1949 FIXME("BinaryBlobCredential not checked\n");
1951 if ((name
[2] - 'A') > BinaryBlobCredential
)
1952 TRACE("unknown type: %d\n", (name
[2] - 'A'));
1955 SetLastError(ERROR_INVALID_PARAMETER
);
1959 /******************************************************************************
1960 * CredIsMarshaledCredentialA [ADVAPI32.@]
1962 * See CredIsMarshaledCredentialW
1965 BOOL WINAPI
CredIsMarshaledCredentialA(LPCSTR name
)
1967 LPWSTR nameW
= NULL
;
1971 TRACE("(%s)\n", debugstr_a(name
));
1975 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0);
1976 nameW
= heap_alloc(len
* sizeof(WCHAR
));
1977 MultiByteToWideChar(CP_ACP
, 0, name
, -1, nameW
, len
);
1980 res
= CredIsMarshaledCredentialW(nameW
);