ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

cred.c
Go to the documentation of this file.
00001 /*
00002  * Credential Management APIs
00003  *
00004  * Copyright 2007 Robert Shearman for CodeWeavers
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #include <advapi32.h>
00022 WINE_DEFAULT_DEBUG_CHANNEL(cred);
00023 
00024 /* the size of the ARC4 key used to encrypt the password data */
00025 #define KEY_SIZE 8
00026 
00027 static const WCHAR wszCredentialManagerKey[] = {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\',
00028     'C','r','e','d','e','n','t','i','a','l',' ','M','a','n','a','g','e','r',0};
00029 static const WCHAR wszEncryptionKeyValue[] = {'E','n','c','r','y','p','t','i','o','n','K','e','y',0};
00030 
00031 static const WCHAR wszFlagsValue[] = {'F','l','a','g','s',0};
00032 static const WCHAR wszTypeValue[] = {'T','y','p','e',0};
00033 static const WCHAR wszCommentValue[] = {'C','o','m','m','e','n','t',0};
00034 static const WCHAR wszLastWrittenValue[] = {'L','a','s','t','W','r','i','t','t','e','n',0};
00035 static const WCHAR wszPersistValue[] = {'P','e','r','s','i','s','t',0};
00036 static const WCHAR wszTargetAliasValue[] = {'T','a','r','g','e','t','A','l','i','a','s',0};
00037 static const WCHAR wszUserNameValue[] = {'U','s','e','r','N','a','m','e',0};
00038 static const WCHAR wszPasswordValue[] = {'P','a','s','s','w','o','r','d',0};
00039 
00040 static DWORD read_credential_blob(HKEY hkey, const BYTE key_data[KEY_SIZE],
00041                                   LPBYTE credential_blob,
00042                                   DWORD *credential_blob_size)
00043 {
00044     DWORD ret;
00045     DWORD type;
00046 
00047     *credential_blob_size = 0;
00048     ret = RegQueryValueExW(hkey, wszPasswordValue, 0, &type, NULL, credential_blob_size);
00049     if (ret != ERROR_SUCCESS)
00050         return ret;
00051     else if (type != REG_BINARY)
00052         return ERROR_REGISTRY_CORRUPT;
00053     if (credential_blob)
00054     {
00055         struct ustring data;
00056         struct ustring key;
00057 
00058         ret = RegQueryValueExW(hkey, wszPasswordValue, 0, &type, credential_blob,
00059                                credential_blob_size);
00060         if (ret != ERROR_SUCCESS)
00061             return ret;
00062         else if (type != REG_BINARY)
00063             return ERROR_REGISTRY_CORRUPT;
00064 
00065         key.Length = key.MaximumLength = KEY_SIZE;
00066         key.Buffer = (unsigned char *)key_data;
00067 
00068         data.Length = data.MaximumLength = *credential_blob_size;
00069         data.Buffer = credential_blob;
00070         SystemFunction032(&data, &key);
00071     }
00072     return ERROR_SUCCESS;
00073 }
00074 
00075 static DWORD registry_read_credential(HKEY hkey, PCREDENTIALW credential,
00076                                       const BYTE key_data[KEY_SIZE],
00077                                       char *buffer, DWORD *len)
00078 {
00079     DWORD type;
00080     DWORD ret;
00081     DWORD count;
00082 
00083     ret = RegQueryValueExW(hkey, NULL, 0, &type, NULL, &count);
00084     if (ret != ERROR_SUCCESS)
00085         return ret;
00086     else if (type != REG_SZ)
00087         return ERROR_REGISTRY_CORRUPT;
00088     *len += count;
00089     if (credential)
00090     {
00091         credential->TargetName = (LPWSTR)buffer;
00092         ret = RegQueryValueExW(hkey, NULL, 0, &type, (LPVOID)credential->TargetName,
00093                                &count);
00094         if (ret != ERROR_SUCCESS)
00095             return ret;
00096         else if (type != REG_SZ)
00097             return ERROR_REGISTRY_CORRUPT;
00098         buffer += count;
00099     }
00100 
00101     ret = RegQueryValueExW(hkey, wszCommentValue, 0, &type, NULL, &count);
00102     if (ret != ERROR_FILE_NOT_FOUND)
00103     {
00104         if (ret != ERROR_SUCCESS)
00105             return ret;
00106         else if (type != REG_SZ)
00107             return ERROR_REGISTRY_CORRUPT;
00108         *len += count;
00109     }
00110     if (credential)
00111     {
00112         credential->Comment = (LPWSTR)buffer;
00113         ret = RegQueryValueExW(hkey, wszCommentValue, 0, &type, (LPVOID)credential->Comment,
00114                                &count);
00115         if (ret == ERROR_FILE_NOT_FOUND)
00116             credential->Comment = NULL;
00117         else if (ret != ERROR_SUCCESS)
00118             return ret;
00119         else if (type != REG_SZ)
00120             return ERROR_REGISTRY_CORRUPT;
00121         else
00122             buffer += count;
00123     }
00124 
00125     ret = RegQueryValueExW(hkey, wszTargetAliasValue, 0, &type, NULL, &count);
00126     if (ret != ERROR_FILE_NOT_FOUND)
00127     {
00128         if (ret != ERROR_SUCCESS)
00129             return ret;
00130         else if (type != REG_SZ)
00131             return ERROR_REGISTRY_CORRUPT;
00132         *len += count;
00133     }
00134     if (credential)
00135     {
00136         credential->TargetAlias = (LPWSTR)buffer;
00137         ret = RegQueryValueExW(hkey, wszTargetAliasValue, 0, &type, (LPVOID)credential->TargetAlias,
00138                                &count);
00139         if (ret == ERROR_FILE_NOT_FOUND)
00140             credential->TargetAlias = NULL;
00141         else if (ret != ERROR_SUCCESS)
00142             return ret;
00143         else if (type != REG_SZ)
00144             return ERROR_REGISTRY_CORRUPT;
00145         else
00146             buffer += count;
00147     }
00148 
00149     ret = RegQueryValueExW(hkey, wszUserNameValue, 0, &type, NULL, &count);
00150     if (ret != ERROR_FILE_NOT_FOUND)
00151     {
00152         if (ret != ERROR_SUCCESS)
00153             return ret;
00154         else if (type != REG_SZ)
00155             return ERROR_REGISTRY_CORRUPT;
00156         *len += count;
00157     }
00158     if (credential)
00159     {
00160         credential->UserName = (LPWSTR)buffer;
00161         ret = RegQueryValueExW(hkey, wszUserNameValue, 0, &type, (LPVOID)credential->UserName,
00162                                &count);
00163         if (ret == ERROR_FILE_NOT_FOUND)
00164             credential->UserName = NULL;
00165         else if (ret != ERROR_SUCCESS)
00166             return ret;
00167         else if (type != REG_SZ)
00168             return ERROR_REGISTRY_CORRUPT;
00169         else
00170             buffer += count;
00171     }
00172 
00173     ret = read_credential_blob(hkey, key_data, NULL, &count);
00174     if (ret != ERROR_FILE_NOT_FOUND)
00175     {
00176         if (ret != ERROR_SUCCESS)
00177             return ret;
00178         *len += count;
00179     }
00180     if (credential)
00181     {
00182         credential->CredentialBlob = (LPBYTE)buffer;
00183         ret = read_credential_blob(hkey, key_data, credential->CredentialBlob, &count);
00184         if (ret == ERROR_FILE_NOT_FOUND)
00185             credential->CredentialBlob = NULL;
00186         else if (ret != ERROR_SUCCESS)
00187             return ret;
00188         credential->CredentialBlobSize = count;
00189         buffer += count;
00190     }
00191 
00192     /* FIXME: Attributes */
00193     if (credential)
00194     {
00195         credential->AttributeCount = 0;
00196         credential->Attributes = NULL;
00197     }
00198 
00199     if (!credential) return ERROR_SUCCESS;
00200 
00201     count = sizeof(credential->Flags);
00202     ret = RegQueryValueExW(hkey, wszFlagsValue, NULL, &type, (LPVOID)&credential->Flags,
00203                            &count);
00204     if (ret != ERROR_SUCCESS)
00205         return ret;
00206     else if (type != REG_DWORD)
00207         return ERROR_REGISTRY_CORRUPT;
00208     count = sizeof(credential->Type);
00209     ret = RegQueryValueExW(hkey, wszTypeValue, NULL, &type, (LPVOID)&credential->Type,
00210                            &count);
00211     if (ret != ERROR_SUCCESS)
00212         return ret;
00213     else if (type != REG_DWORD)
00214         return ERROR_REGISTRY_CORRUPT;
00215 
00216     count = sizeof(credential->LastWritten);
00217     ret = RegQueryValueExW(hkey, wszLastWrittenValue, NULL, &type, (LPVOID)&credential->LastWritten,
00218                            &count);
00219     if (ret != ERROR_SUCCESS)
00220         return ret;
00221     else if (type != REG_BINARY)
00222         return ERROR_REGISTRY_CORRUPT;
00223     count = sizeof(credential->Persist);
00224     ret = RegQueryValueExW(hkey, wszPersistValue, NULL, &type, (LPVOID)&credential->Persist,
00225                            &count);
00226     if (ret == ERROR_SUCCESS && type != REG_DWORD)
00227         return ERROR_REGISTRY_CORRUPT;
00228     return ret;
00229 }
00230 
00231 #ifdef __APPLE__
00232 static DWORD mac_read_credential_from_item(SecKeychainItemRef item, BOOL require_password,
00233                                            PCREDENTIALW credential, char *buffer,
00234                                            DWORD *len)
00235 {
00236     OSStatus status;
00237     UInt32 i;
00238     UInt32 cred_blob_len;
00239     void *cred_blob;
00240     LPWSTR domain = NULL;
00241     LPWSTR user = NULL;
00242     BOOL user_name_present = FALSE;
00243     SecKeychainAttributeInfo info;
00244     SecKeychainAttributeList *attr_list;
00245     UInt32 info_tags[] = { kSecServerItemAttr, kSecSecurityDomainItemAttr, kSecAccountItemAttr,
00246                            kSecCommentItemAttr, kSecCreationDateItemAttr };
00247     info.count = sizeof(info_tags)/sizeof(info_tags[0]);
00248     info.tag = info_tags;
00249     info.format = NULL;
00250     status = SecKeychainItemCopyAttributesAndData(item, &info, NULL, &attr_list, &cred_blob_len, &cred_blob);
00251     if (status == errSecAuthFailed && !require_password)
00252     {
00253         cred_blob_len = 0;
00254         cred_blob = NULL;
00255         status = SecKeychainItemCopyAttributesAndData(item, &info, NULL, &attr_list, &cred_blob_len, NULL);
00256     }
00257     if (status != noErr)
00258     {
00259         WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status);
00260         return ERROR_NOT_FOUND;
00261     }
00262 
00263     for (i = 0; i < attr_list->count; i++)
00264         if (attr_list->attr[i].tag == kSecAccountItemAttr && attr_list->attr[i].data)
00265         {
00266             user_name_present = TRUE;
00267             break;
00268         }
00269     if (!user_name_present)
00270     {
00271         WARN("no kSecAccountItemAttr for item\n");
00272         return ERROR_NOT_FOUND;
00273     }
00274 
00275     if (buffer)
00276     {
00277         credential->Flags = 0;
00278         credential->Type = CRED_TYPE_DOMAIN_PASSWORD;
00279         credential->TargetName = NULL;
00280         credential->Comment = NULL;
00281         memset(&credential->LastWritten, 0, sizeof(credential->LastWritten));
00282         credential->CredentialBlobSize = 0;
00283         credential->CredentialBlob = NULL;
00284         credential->Persist = CRED_PERSIST_LOCAL_MACHINE;
00285         credential->AttributeCount = 0;
00286         credential->Attributes = NULL;
00287         credential->TargetAlias = NULL;
00288         credential->UserName = NULL;
00289     }
00290     for (i = 0; i < attr_list->count; i++)
00291     {
00292         switch (attr_list->attr[i].tag)
00293         {
00294             case kSecServerItemAttr:
00295                 TRACE("kSecServerItemAttr: %.*s\n", (int)attr_list->attr[i].length,
00296                       (char *)attr_list->attr[i].data);
00297                 if (!attr_list->attr[i].data) continue;
00298                 if (buffer)
00299                 {
00300                     INT str_len;
00301                     credential->TargetName = (LPWSTR)buffer;
00302                     str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data,
00303                                                   attr_list->attr[i].length, (LPWSTR)buffer, 0xffff);
00304                     credential->TargetName[str_len] = '\0';
00305                     buffer += (str_len + 1) * sizeof(WCHAR);
00306                     *len += (str_len + 1) * sizeof(WCHAR);
00307                 }
00308                 else
00309                 {
00310                     INT str_len;
00311                     str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data,
00312                                                   attr_list->attr[i].length, NULL, 0);
00313                     *len += (str_len + 1) * sizeof(WCHAR);
00314                 }
00315                 break;
00316             case kSecAccountItemAttr:
00317             {
00318                 INT str_len;
00319                 TRACE("kSecAccountItemAttr: %.*s\n", (int)attr_list->attr[i].length,
00320                       (char *)attr_list->attr[i].data);
00321                 if (!attr_list->attr[i].data) continue;
00322                 str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data,
00323                                               attr_list->attr[i].length, NULL, 0);
00324                 user = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
00325                 MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data,
00326                                     attr_list->attr[i].length, user, str_len);
00327                 user[str_len] = '\0';
00328                 break;
00329             }
00330             case kSecCommentItemAttr:
00331                 TRACE("kSecCommentItemAttr: %.*s\n", (int)attr_list->attr[i].length,
00332                       (char *)attr_list->attr[i].data);
00333                 if (!attr_list->attr[i].data) continue;
00334                 if (buffer)
00335                 {
00336                     INT str_len;
00337                     credential->Comment = (LPWSTR)buffer;
00338                     str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data,
00339                                                   attr_list->attr[i].length, (LPWSTR)buffer, 0xffff);
00340                     credential->Comment[str_len] = '\0';
00341                     buffer += (str_len + 1) * sizeof(WCHAR);
00342                     *len += (str_len + 1) * sizeof(WCHAR);
00343                 }
00344                 else
00345                 {
00346                     INT str_len;
00347                     str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data,
00348                                                   attr_list->attr[i].length, NULL, 0);
00349                     *len += (str_len + 1) * sizeof(WCHAR);
00350                 }
00351                 break;
00352             case kSecSecurityDomainItemAttr:
00353             {
00354                 INT str_len;
00355                 TRACE("kSecSecurityDomainItemAttr: %.*s\n", (int)attr_list->attr[i].length,
00356                       (char *)attr_list->attr[i].data);
00357                 if (!attr_list->attr[i].data) continue;
00358                 str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data,
00359                                               attr_list->attr[i].length, NULL, 0);
00360                 domain = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
00361                 MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[i].data,
00362                                     attr_list->attr[i].length, domain, str_len);
00363                 domain[str_len] = '\0';
00364                 break;
00365             }
00366             case kSecCreationDateItemAttr:
00367                 TRACE("kSecCreationDateItemAttr: %.*s\n", (int)attr_list->attr[i].length,
00368                       (char *)attr_list->attr[i].data);
00369                 if (buffer)
00370                 {
00371                     LARGE_INTEGER win_time;
00372                     struct tm tm;
00373                     time_t time;
00374                     memset(&tm, 0, sizeof(tm));
00375                     strptime(attr_list->attr[i].data, "%Y%m%d%H%M%SZ", &tm);
00376                     time = mktime(&tm);
00377                     RtlSecondsSince1970ToTime(time, &win_time);
00378                     credential->LastWritten.dwLowDateTime = win_time.u.LowPart;
00379                     credential->LastWritten.dwHighDateTime = win_time.u.HighPart;
00380                 }
00381                 break;
00382         }
00383     }
00384 
00385     if (user)
00386     {
00387         INT str_len;
00388         if (buffer)
00389             credential->UserName = (LPWSTR)buffer;
00390         if (domain)
00391         {
00392             str_len = strlenW(domain);
00393             *len += (str_len + 1) * sizeof(WCHAR);
00394             if (buffer)
00395             {
00396                 memcpy(credential->UserName, domain, str_len * sizeof(WCHAR));
00397                 /* FIXME: figure out when to use an '@' */
00398                 credential->UserName[str_len] = '\\';
00399                 buffer += (str_len + 1) * sizeof(WCHAR);
00400             }
00401         }
00402         str_len = strlenW(user);
00403         *len += (str_len + 1) * sizeof(WCHAR);
00404         if (buffer)
00405         {
00406             memcpy(buffer, user, (str_len + 1) * sizeof(WCHAR));
00407             buffer += (str_len + 1) * sizeof(WCHAR);
00408             TRACE("UserName = %s\n", debugstr_w(credential->UserName));
00409         }
00410     }
00411     HeapFree(GetProcessHeap(), 0, user);
00412     HeapFree(GetProcessHeap(), 0, domain);
00413 
00414     if (cred_blob)
00415     {
00416         if (buffer)
00417         {
00418             INT str_len;
00419             credential->CredentialBlob = (BYTE *)buffer;
00420             str_len = MultiByteToWideChar(CP_UTF8, 0, cred_blob, cred_blob_len,
00421                                           (LPWSTR)buffer, 0xffff);
00422             credential->CredentialBlobSize = str_len * sizeof(WCHAR);
00423             buffer += str_len * sizeof(WCHAR);
00424             *len += str_len * sizeof(WCHAR);
00425         }
00426         else
00427         {
00428             INT str_len;
00429             str_len = MultiByteToWideChar(CP_UTF8, 0, cred_blob, cred_blob_len,
00430                                           NULL, 0);
00431             *len += str_len * sizeof(WCHAR);
00432         }
00433     }
00434     SecKeychainItemFreeAttributesAndData(attr_list, cred_blob);
00435     return ERROR_SUCCESS;
00436 }
00437 #endif
00438 
00439 static DWORD write_credential_blob(HKEY hkey, LPCWSTR target_name, DWORD type,
00440                                    const BYTE key_data[KEY_SIZE],
00441                                    const BYTE *credential_blob, DWORD credential_blob_size)
00442 {
00443     LPBYTE encrypted_credential_blob;
00444     struct ustring data;
00445     struct ustring key;
00446     DWORD ret;
00447 
00448     key.Length = key.MaximumLength = KEY_SIZE;
00449     key.Buffer = (unsigned char *)key_data;
00450 
00451     encrypted_credential_blob = HeapAlloc(GetProcessHeap(), 0, credential_blob_size);
00452     if (!encrypted_credential_blob) return ERROR_OUTOFMEMORY;
00453 
00454     memcpy(encrypted_credential_blob, credential_blob, credential_blob_size);
00455     data.Length = data.MaximumLength = credential_blob_size;
00456     data.Buffer = encrypted_credential_blob;
00457     SystemFunction032(&data, &key);
00458 
00459     ret = RegSetValueExW(hkey, wszPasswordValue, 0, REG_BINARY, encrypted_credential_blob, credential_blob_size);
00460     HeapFree(GetProcessHeap(), 0, encrypted_credential_blob);
00461 
00462     return ret;
00463 }
00464 
00465 static DWORD registry_write_credential(HKEY hkey, const CREDENTIALW *credential,
00466                                        const BYTE key_data[KEY_SIZE], BOOL preserve_blob)
00467 {
00468     DWORD ret;
00469     FILETIME LastWritten;
00470 
00471     GetSystemTimeAsFileTime(&LastWritten);
00472 
00473     ret = RegSetValueExW(hkey, wszFlagsValue, 0, REG_DWORD, (LPVOID)&credential->Flags,
00474                          sizeof(credential->Flags));
00475     if (ret != ERROR_SUCCESS) return ret;
00476     ret = RegSetValueExW(hkey, wszTypeValue, 0, REG_DWORD, (LPVOID)&credential->Type,
00477                          sizeof(credential->Type));
00478     if (ret != ERROR_SUCCESS) return ret;
00479     ret = RegSetValueExW(hkey, NULL, 0, REG_SZ, (LPVOID)credential->TargetName,
00480                          sizeof(WCHAR)*(strlenW(credential->TargetName)+1));
00481     if (ret != ERROR_SUCCESS) return ret;
00482     if (credential->Comment)
00483     {
00484         ret = RegSetValueExW(hkey, wszCommentValue, 0, REG_SZ, (LPVOID)credential->Comment,
00485                              sizeof(WCHAR)*(strlenW(credential->Comment)+1));
00486         if (ret != ERROR_SUCCESS) return ret;
00487     }
00488     ret = RegSetValueExW(hkey, wszLastWrittenValue, 0, REG_BINARY, (LPVOID)&LastWritten,
00489                          sizeof(LastWritten));
00490     if (ret != ERROR_SUCCESS) return ret;
00491     ret = RegSetValueExW(hkey, wszPersistValue, 0, REG_DWORD, (LPVOID)&credential->Persist,
00492                          sizeof(credential->Persist));
00493     if (ret != ERROR_SUCCESS) return ret;
00494     /* FIXME: Attributes */
00495     if (credential->TargetAlias)
00496     {
00497         ret = RegSetValueExW(hkey, wszTargetAliasValue, 0, REG_SZ, (LPVOID)credential->TargetAlias,
00498                              sizeof(WCHAR)*(strlenW(credential->TargetAlias)+1));
00499         if (ret != ERROR_SUCCESS) return ret;
00500     }
00501     if (credential->UserName)
00502     {
00503         ret = RegSetValueExW(hkey, wszUserNameValue, 0, REG_SZ, (LPVOID)credential->UserName,
00504                              sizeof(WCHAR)*(strlenW(credential->UserName)+1));
00505         if (ret != ERROR_SUCCESS) return ret;
00506     }
00507     if (!preserve_blob)
00508     {
00509         ret = write_credential_blob(hkey, credential->TargetName, credential->Type,
00510                                     key_data, credential->CredentialBlob,
00511                                     credential->CredentialBlobSize);
00512     }
00513     return ret;
00514 }
00515 
00516 #ifdef __APPLE__
00517 static DWORD mac_write_credential(const CREDENTIALW *credential, BOOL preserve_blob)
00518 {
00519     OSStatus status;
00520     SecKeychainItemRef keychain_item;
00521     char *username;
00522     char *domain = NULL;
00523     char *password;
00524     char *servername;
00525     UInt32 userlen;
00526     UInt32 domainlen = 0;
00527     UInt32 pwlen;
00528     UInt32 serverlen;
00529     LPCWSTR p;
00530     SecKeychainAttribute attrs[1];
00531     SecKeychainAttributeList attr_list;
00532 
00533     if (credential->Flags)
00534         FIXME("Flags 0x%x not written\n", credential->Flags);
00535     if (credential->Type != CRED_TYPE_DOMAIN_PASSWORD)
00536         FIXME("credential type of %d not supported\n", credential->Type);
00537     if (credential->Persist != CRED_PERSIST_LOCAL_MACHINE)
00538         FIXME("persist value of %d not supported\n", credential->Persist);
00539     if (credential->AttributeCount)
00540         FIXME("custom attributes not supported\n");
00541 
00542     p = strchrW(credential->UserName, '\\');
00543     if (p)
00544     {
00545         domainlen = WideCharToMultiByte(CP_UTF8, 0, credential->UserName,
00546                                         p - credential->UserName, NULL, 0, NULL, NULL);
00547         domain = HeapAlloc(GetProcessHeap(), 0, (domainlen + 1) * sizeof(*domain));
00548         WideCharToMultiByte(CP_UTF8, 0, credential->UserName, p - credential->UserName,
00549                             domain, domainlen, NULL, NULL);
00550         domain[domainlen] = '\0';
00551         p++;
00552     }
00553     else
00554         p = credential->UserName;
00555     userlen = WideCharToMultiByte(CP_UTF8, 0, p, -1, NULL, 0, NULL, NULL);
00556     username = HeapAlloc(GetProcessHeap(), 0, userlen * sizeof(*username));
00557     WideCharToMultiByte(CP_UTF8, 0, p, -1, username, userlen, NULL, NULL);
00558 
00559     serverlen = WideCharToMultiByte(CP_UTF8, 0, credential->TargetName, -1, NULL, 0, NULL, NULL);
00560     servername = HeapAlloc(GetProcessHeap(), 0, serverlen * sizeof(*servername));
00561     WideCharToMultiByte(CP_UTF8, 0, credential->TargetName, -1, servername, serverlen, NULL, NULL);
00562     pwlen = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)credential->CredentialBlob,
00563                                 credential->CredentialBlobSize / sizeof(WCHAR), NULL, 0, NULL, NULL);
00564     password = HeapAlloc(GetProcessHeap(), 0, pwlen * sizeof(*domain));
00565     WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)credential->CredentialBlob,
00566                         credential->CredentialBlobSize / sizeof(WCHAR), password, pwlen, NULL, NULL);
00567 
00568     TRACE("adding server %s, domain %s, username %s using Keychain\n", servername, domain, username);
00569     status = SecKeychainAddInternetPassword(NULL, strlen(servername), servername,
00570                                             strlen(domain), domain, strlen(username),
00571                                             username, 0, NULL, 0,
00572                                             0 /* no protocol */,
00573                                             kSecAuthenticationTypeDefault,
00574                                             strlen(password), password, &keychain_item);
00575     if (status != noErr)
00576         ERR("SecKeychainAddInternetPassword returned %ld\n", status);
00577     if (status == errSecDuplicateItem)
00578     {
00579         SecKeychainItemRef keychain_item;
00580 
00581         status = SecKeychainFindInternetPassword(NULL, strlen(servername), servername,
00582                                                  strlen(domain), domain,
00583                                                  strlen(username), username,
00584                                                  0, NULL /* any path */, 0,
00585                                                  0 /* any protocol */,
00586                                                  0 /* any authentication type */,
00587                                                  0, NULL, &keychain_item);
00588         if (status != noErr)
00589             ERR("SecKeychainFindInternetPassword returned %ld\n", status);
00590     }
00591     HeapFree(GetProcessHeap(), 0, domain);
00592     HeapFree(GetProcessHeap(), 0, username);
00593     HeapFree(GetProcessHeap(), 0, servername);
00594     if (status != noErr)
00595     {
00596         HeapFree(GetProcessHeap(), 0, password);
00597         return ERROR_GEN_FAILURE;
00598     }
00599     if (credential->Comment)
00600     {
00601         attr_list.count = 1;
00602         attr_list.attr = attrs;
00603         attrs[0].tag = kSecCommentItemAttr;
00604         attrs[0].length = WideCharToMultiByte(CP_UTF8, 0, credential->Comment, -1, NULL, 0, NULL, NULL);
00605         if (attrs[0].length) attrs[0].length--;
00606         attrs[0].data = HeapAlloc(GetProcessHeap(), 0, attrs[0].length);
00607         WideCharToMultiByte(CP_UTF8, 0, credential->Comment, -1, attrs[0].data, attrs[0].length, NULL, NULL);
00608     }
00609     else
00610     {
00611         attr_list.count = 0;
00612         attr_list.attr = NULL;
00613     }
00614     status = SecKeychainItemModifyAttributesAndData(keychain_item, &attr_list,
00615                                                     preserve_blob ? 0 : strlen(password),
00616                                                     preserve_blob ? NULL : password);
00617     if (credential->Comment)
00618         HeapFree(GetProcessHeap(), 0, attrs[0].data);
00619     HeapFree(GetProcessHeap(), 0, password);
00620     /* FIXME: set TargetAlias attribute */
00621     CFRelease(keychain_item);
00622     return ERROR_SUCCESS;
00623 }
00624 #endif
00625 
00626 static DWORD open_cred_mgr_key(HKEY *hkey, BOOL open_for_write)
00627 {
00628     return RegCreateKeyExW(HKEY_CURRENT_USER, wszCredentialManagerKey, 0,
00629                            NULL, REG_OPTION_NON_VOLATILE,
00630                            KEY_READ | (open_for_write ? KEY_WRITE : 0), NULL, hkey, NULL);
00631 }
00632 
00633 static DWORD get_cred_mgr_encryption_key(HKEY hkeyMgr, BYTE key_data[KEY_SIZE])
00634 {
00635     static const BYTE my_key_data[KEY_SIZE] = { 0 };
00636     DWORD type;
00637     DWORD count;
00638     FILETIME ft;
00639     ULONG seed;
00640     ULONG value;
00641     DWORD ret;
00642 
00643     memcpy(key_data, my_key_data, KEY_SIZE);
00644 
00645     count = KEY_SIZE;
00646     ret = RegQueryValueExW(hkeyMgr, wszEncryptionKeyValue, NULL, &type, key_data,
00647                            &count);
00648     if (ret == ERROR_SUCCESS)
00649     {
00650         if (type != REG_BINARY)
00651             return ERROR_REGISTRY_CORRUPT;
00652         else
00653             return ERROR_SUCCESS;
00654     }
00655     if (ret != ERROR_FILE_NOT_FOUND)
00656         return ret;
00657 
00658     GetSystemTimeAsFileTime(&ft);
00659     seed = ft.dwLowDateTime;
00660     value = RtlUniform(&seed);
00661     *(DWORD *)key_data = value;
00662     seed = ft.dwHighDateTime;
00663     value = RtlUniform(&seed);
00664     *(DWORD *)(key_data + 4) = value;
00665 
00666     ret = RegSetValueExW(hkeyMgr, wszEncryptionKeyValue, 0, REG_BINARY,
00667                          key_data, KEY_SIZE);
00668     if (ret == ERROR_ACCESS_DENIED)
00669     {
00670         ret = open_cred_mgr_key(&hkeyMgr, TRUE);
00671         if (ret == ERROR_SUCCESS)
00672         {
00673             ret = RegSetValueExW(hkeyMgr, wszEncryptionKeyValue, 0, REG_BINARY,
00674                                  key_data, KEY_SIZE);
00675             RegCloseKey(hkeyMgr);
00676         }
00677     }
00678     return ret;
00679 }
00680 
00681 static LPWSTR get_key_name_for_target(LPCWSTR target_name, DWORD type)
00682 {
00683     static const WCHAR wszGenericPrefix[] = {'G','e','n','e','r','i','c',':',' ',0};
00684     static const WCHAR wszDomPasswdPrefix[] = {'D','o','m','P','a','s','s','w','d',':',' ',0};
00685     INT len;
00686     LPCWSTR prefix = NULL;
00687     LPWSTR key_name, p;
00688 
00689     len = strlenW(target_name);
00690     if (type == CRED_TYPE_GENERIC)
00691     {
00692         prefix = wszGenericPrefix;
00693         len += sizeof(wszGenericPrefix)/sizeof(wszGenericPrefix[0]);
00694     }
00695     else
00696     {
00697         prefix = wszDomPasswdPrefix;
00698         len += sizeof(wszDomPasswdPrefix)/sizeof(wszDomPasswdPrefix[0]);
00699     }
00700 
00701     key_name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
00702     if (!key_name) return NULL;
00703 
00704     strcpyW(key_name, prefix);
00705     strcatW(key_name, target_name);
00706 
00707     for (p = key_name; *p; p++)
00708         if (*p == '\\') *p = '_';
00709 
00710     return key_name;
00711 }
00712 
00713 static BOOL credential_matches_filter(HKEY hkeyCred, LPCWSTR filter)
00714 {
00715     LPWSTR target_name;
00716     DWORD ret;
00717     DWORD type;
00718     DWORD count;
00719     LPCWSTR p;
00720 
00721     if (!filter) return TRUE;
00722 
00723     ret = RegQueryValueExW(hkeyCred, NULL, 0, &type, NULL, &count);
00724     if (ret != ERROR_SUCCESS)
00725         return FALSE;
00726     else if (type != REG_SZ)
00727         return FALSE;
00728 
00729     target_name = HeapAlloc(GetProcessHeap(), 0, count);
00730     if (!target_name)
00731         return FALSE;
00732     ret = RegQueryValueExW(hkeyCred, NULL, 0, &type, (LPVOID)target_name, &count);
00733     if (ret != ERROR_SUCCESS || type != REG_SZ)
00734     {
00735         HeapFree(GetProcessHeap(), 0, target_name);
00736         return FALSE;
00737     }
00738 
00739     TRACE("comparing filter %s to target name %s\n", debugstr_w(filter),
00740           debugstr_w(target_name));
00741 
00742     p = strchrW(filter, '*');
00743     ret = CompareStringW(GetThreadLocale(), 0, filter,
00744                          (p && !p[1] ? p - filter : -1), target_name,
00745                          (p && !p[1] ? p - filter : -1)) == CSTR_EQUAL;
00746 
00747     HeapFree(GetProcessHeap(), 0, target_name);
00748     return ret;
00749 }
00750 
00751 static DWORD registry_enumerate_credentials(HKEY hkeyMgr, LPCWSTR filter,
00752                                             LPWSTR target_name,
00753                                             DWORD target_name_len, BYTE key_data[KEY_SIZE],
00754                                             PCREDENTIALW *credentials, char **buffer,
00755                                             DWORD *len, DWORD *count)
00756 {
00757     DWORD i;
00758     DWORD ret;
00759     for (i = 0;; i++)
00760     {
00761         HKEY hkeyCred;
00762         ret = RegEnumKeyW(hkeyMgr, i, target_name, target_name_len+1);
00763         if (ret == ERROR_NO_MORE_ITEMS)
00764         {
00765             ret = ERROR_SUCCESS;
00766             break;
00767         }
00768         else if (ret != ERROR_SUCCESS)
00769         {
00770             ret = ERROR_SUCCESS;
00771             continue;
00772         }
00773         TRACE("target_name = %s\n", debugstr_w(target_name));
00774         ret = RegOpenKeyExW(hkeyMgr, target_name, 0, KEY_QUERY_VALUE, &hkeyCred);
00775         if (ret != ERROR_SUCCESS)
00776         {
00777             ret = ERROR_SUCCESS;
00778             continue;
00779         }
00780         if (!credential_matches_filter(hkeyCred, filter))
00781         {
00782             RegCloseKey(hkeyCred);
00783             continue;
00784         }
00785         if (buffer)
00786         {
00787             *len = sizeof(CREDENTIALW);
00788             credentials[*count] = (PCREDENTIALW)*buffer;
00789         }
00790         else
00791             *len += sizeof(CREDENTIALW);
00792         ret = registry_read_credential(hkeyCred, buffer ? credentials[*count] : NULL,
00793                                        key_data, buffer ? *buffer + sizeof(CREDENTIALW) : NULL,
00794                                        len);
00795         RegCloseKey(hkeyCred);
00796         if (ret != ERROR_SUCCESS) break;
00797         if (buffer) *buffer += *len;
00798         (*count)++;
00799     }
00800     return ret;
00801 }
00802 
00803 #ifdef __APPLE__
00804 static DWORD mac_enumerate_credentials(LPCWSTR filter, PCREDENTIALW *credentials,
00805                                        char *buffer, DWORD *len, DWORD *count)
00806 {
00807     SecKeychainSearchRef search;
00808     SecKeychainItemRef item;
00809     OSStatus status;
00810     Boolean saved_user_interaction_allowed;
00811     DWORD ret;
00812 
00813     SecKeychainGetUserInteractionAllowed(&saved_user_interaction_allowed);
00814     SecKeychainSetUserInteractionAllowed(false);
00815 
00816     status = SecKeychainSearchCreateFromAttributes(NULL, kSecInternetPasswordItemClass, NULL, &search);
00817     if (status == noErr)
00818     {
00819         while (SecKeychainSearchCopyNext(search, &item) == noErr)
00820         {
00821             SecKeychainAttributeInfo info;
00822             SecKeychainAttributeList *attr_list;
00823             UInt32 info_tags[] = { kSecServerItemAttr };
00824             info.count = sizeof(info_tags)/sizeof(info_tags[0]);
00825             info.tag = info_tags;
00826             info.format = NULL;
00827             status = SecKeychainItemCopyAttributesAndData(item, &info, NULL, &attr_list, NULL, NULL);
00828             if (status != noErr)
00829             {
00830                 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status);
00831                 continue;
00832             }
00833             if (buffer)
00834             {
00835                 *len = sizeof(CREDENTIALW);
00836                 credentials[*count] = (PCREDENTIALW)buffer;
00837             }
00838             else
00839                 *len += sizeof(CREDENTIALW);
00840             if (attr_list->count != 1 || attr_list->attr[0].tag != kSecServerItemAttr) continue;
00841             TRACE("server item: %.*s\n", (int)attr_list->attr[0].length, (char *)attr_list->attr[0].data);
00842             /* FIXME: filter based on attr_list->attr[0].data */
00843             SecKeychainItemFreeAttributesAndData(attr_list, NULL);
00844             ret = mac_read_credential_from_item(item, FALSE,
00845                                                 buffer ? credentials[*count] : NULL,
00846                                                 buffer ? buffer + sizeof(CREDENTIALW) : NULL,
00847                                                 len);
00848             CFRelease(item);
00849             if (ret == ERROR_SUCCESS)
00850             {
00851                 (*count)++;
00852                 if (buffer) buffer += *len;
00853             }
00854         }
00855         CFRelease(search);
00856     }
00857     else
00858         ERR("SecKeychainSearchCreateFromAttributes returned status %ld\n", status);
00859     SecKeychainSetUserInteractionAllowed(saved_user_interaction_allowed);
00860     return ERROR_SUCCESS;
00861 }
00862 
00863 static DWORD mac_delete_credential(LPCWSTR TargetName)
00864 {
00865     OSStatus status;
00866     SecKeychainSearchRef search;
00867     status = SecKeychainSearchCreateFromAttributes(NULL, kSecInternetPasswordItemClass, NULL, &search);
00868     if (status == noErr)
00869     {
00870         SecKeychainItemRef item;
00871         while (SecKeychainSearchCopyNext(search, &item) == noErr)
00872         {
00873             SecKeychainAttributeInfo info;
00874             SecKeychainAttributeList *attr_list;
00875             UInt32 info_tags[] = { kSecServerItemAttr };
00876             LPWSTR target_name;
00877             INT str_len;
00878             info.count = sizeof(info_tags)/sizeof(info_tags[0]);
00879             info.tag = info_tags;
00880             info.format = NULL;
00881             status = SecKeychainItemCopyAttributesAndData(item, &info, NULL, &attr_list, NULL, NULL);
00882             if (status != noErr)
00883             {
00884                 WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status);
00885                 continue;
00886             }
00887             if (attr_list->count != 1 || attr_list->attr[0].tag != kSecServerItemAttr)
00888             {
00889                 CFRelease(item);
00890                 continue;
00891             }
00892             str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[0].data, attr_list->attr[0].length, NULL, 0);
00893             target_name = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
00894             MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[0].data, attr_list->attr[0].length, target_name, str_len);
00895             /* nul terminate */
00896             target_name[str_len] = '\0';
00897             if (strcmpiW(TargetName, target_name))
00898             {
00899                 CFRelease(item);
00900                 HeapFree(GetProcessHeap(), 0, target_name);
00901                 continue;
00902             }
00903             HeapFree(GetProcessHeap(), 0, target_name);
00904             SecKeychainItemFreeAttributesAndData(attr_list, NULL);
00905             SecKeychainItemDelete(item);
00906             CFRelease(item);
00907             CFRelease(search);
00908 
00909             return ERROR_SUCCESS;
00910         }
00911         CFRelease(search);
00912     }
00913     return ERROR_NOT_FOUND;
00914 }
00915 #endif
00916 
00917 /******************************************************************************
00918  * convert_PCREDENTIALW_to_PCREDENTIALA [internal]
00919  *
00920  * convert a Credential struct from UNICODE to ANSI and return the needed size in Bytes
00921  *
00922  */
00923 
00924 static INT convert_PCREDENTIALW_to_PCREDENTIALA(const CREDENTIALW *CredentialW, PCREDENTIALA CredentialA, INT len)
00925 {
00926     char *buffer;
00927     INT string_len;
00928     INT needed = sizeof(CREDENTIALA);
00929 
00930     if (!CredentialA)
00931     {
00932         if (CredentialW->TargetName)
00933             needed += WideCharToMultiByte(CP_ACP, 0, CredentialW->TargetName, -1, NULL, 0, NULL, NULL);
00934         if (CredentialW->Comment)
00935             needed += WideCharToMultiByte(CP_ACP, 0, CredentialW->Comment, -1, NULL, 0, NULL, NULL);
00936         needed += CredentialW->CredentialBlobSize;
00937         if (CredentialW->TargetAlias)
00938             needed += WideCharToMultiByte(CP_ACP, 0, CredentialW->TargetAlias, -1, NULL, 0, NULL, NULL);
00939         if (CredentialW->UserName)
00940             needed += WideCharToMultiByte(CP_ACP, 0, CredentialW->UserName, -1, NULL, 0, NULL, NULL);
00941 
00942         return needed;
00943     }
00944 
00945 
00946     buffer = (char *)CredentialA + sizeof(CREDENTIALA);
00947     len -= sizeof(CREDENTIALA);
00948     CredentialA->Flags = CredentialW->Flags;
00949     CredentialA->Type = CredentialW->Type;
00950 
00951     if (CredentialW->TargetName)
00952     {
00953         CredentialA->TargetName = buffer;
00954         string_len = WideCharToMultiByte(CP_ACP, 0, CredentialW->TargetName, -1, buffer, len, NULL, NULL);
00955         buffer += string_len;
00956         needed += string_len;
00957         len -= string_len;
00958     }
00959     else
00960         CredentialA->TargetName = NULL;
00961     if (CredentialW->Comment)
00962     {
00963         CredentialA->Comment = buffer;
00964         string_len = WideCharToMultiByte(CP_ACP, 0, CredentialW->Comment, -1, buffer, len, NULL, NULL);
00965         buffer += string_len;
00966         needed += string_len;
00967         len -= string_len;
00968     }
00969     else
00970         CredentialA->Comment = NULL;
00971     CredentialA->LastWritten = CredentialW->LastWritten;
00972     CredentialA->CredentialBlobSize = CredentialW->CredentialBlobSize;
00973     if (CredentialW->CredentialBlobSize && (CredentialW->CredentialBlobSize <= len))
00974     {
00975         CredentialA->CredentialBlob =(LPBYTE)buffer;
00976         memcpy(CredentialA->CredentialBlob, CredentialW->CredentialBlob,
00977                CredentialW->CredentialBlobSize);
00978         buffer += CredentialW->CredentialBlobSize;
00979         needed += CredentialW->CredentialBlobSize;
00980         len -= CredentialW->CredentialBlobSize;
00981     }
00982     else
00983         CredentialA->CredentialBlob = NULL;
00984     CredentialA->Persist = CredentialW->Persist;
00985     CredentialA->AttributeCount = 0;
00986     CredentialA->Attributes = NULL; /* FIXME */
00987     if (CredentialW->TargetAlias)
00988     {
00989         CredentialA->TargetAlias = buffer;
00990         string_len = WideCharToMultiByte(CP_ACP, 0, CredentialW->TargetAlias, -1, buffer, len, NULL, NULL);
00991         buffer += string_len;
00992         needed += string_len;
00993         len -= string_len;
00994     }
00995     else
00996         CredentialA->TargetAlias = NULL;
00997     if (CredentialW->UserName)
00998     {
00999         CredentialA->UserName = buffer;
01000         string_len = WideCharToMultiByte(CP_ACP, 0, CredentialW->UserName, -1, buffer, len, NULL, NULL);
01001         needed += string_len;
01002     }
01003     else
01004         CredentialA->UserName = NULL;
01005 
01006     return needed;
01007 }
01008 
01009 /******************************************************************************
01010  * convert_PCREDENTIALA_to_PCREDENTIALW [internal]
01011  *
01012  * convert a Credential struct from ANSI to UNICODE and return the needed size in Bytes
01013  *
01014  */
01015 static INT convert_PCREDENTIALA_to_PCREDENTIALW(const CREDENTIALA *CredentialA, PCREDENTIALW CredentialW, INT len)
01016 {
01017     char *buffer;
01018     INT string_len;
01019     INT needed = sizeof(CREDENTIALW);
01020 
01021     if (!CredentialW)
01022     {
01023         if (CredentialA->TargetName)
01024             needed += sizeof(WCHAR) * MultiByteToWideChar(CP_ACP, 0, CredentialA->TargetName, -1, NULL, 0);
01025         if (CredentialA->Comment)
01026             needed += sizeof(WCHAR) * MultiByteToWideChar(CP_ACP, 0, CredentialA->Comment, -1, NULL, 0);
01027         needed += CredentialA->CredentialBlobSize;
01028         if (CredentialA->TargetAlias)
01029             needed += sizeof(WCHAR) * MultiByteToWideChar(CP_ACP, 0, CredentialA->TargetAlias, -1, NULL, 0);
01030         if (CredentialA->UserName)
01031             needed += sizeof(WCHAR) * MultiByteToWideChar(CP_ACP, 0, CredentialA->UserName, -1, NULL, 0);
01032 
01033         return needed;
01034     }
01035 
01036     buffer = (char *)CredentialW + sizeof(CREDENTIALW);
01037     len -= sizeof(CREDENTIALW);
01038     CredentialW->Flags = CredentialA->Flags;
01039     CredentialW->Type = CredentialA->Type;
01040     if (CredentialA->TargetName)
01041     {
01042         CredentialW->TargetName = (LPWSTR)buffer;
01043         string_len = MultiByteToWideChar(CP_ACP, 0, CredentialA->TargetName, -1, CredentialW->TargetName, len / sizeof(WCHAR));
01044         buffer += sizeof(WCHAR) * string_len;
01045         needed += sizeof(WCHAR) * string_len;
01046         len -= sizeof(WCHAR) * string_len;
01047     }
01048     else
01049         CredentialW->TargetName = NULL;
01050     if (CredentialA->Comment)
01051     {
01052         CredentialW->Comment = (LPWSTR)buffer;
01053         string_len = MultiByteToWideChar(CP_ACP, 0, CredentialA->Comment, -1, CredentialW->Comment, len / sizeof(WCHAR));
01054         buffer += sizeof(WCHAR) * string_len;
01055         needed += sizeof(WCHAR) * string_len;
01056         len -= sizeof(WCHAR) * string_len;
01057     }
01058     else
01059         CredentialW->Comment = NULL;
01060     CredentialW->LastWritten = CredentialA->LastWritten;
01061     CredentialW->CredentialBlobSize = CredentialA->CredentialBlobSize;
01062     if (CredentialA->CredentialBlobSize)
01063     {
01064         CredentialW->CredentialBlob =(LPBYTE)buffer;
01065         memcpy(CredentialW->CredentialBlob, CredentialA->CredentialBlob,
01066                CredentialA->CredentialBlobSize);
01067         buffer += CredentialA->CredentialBlobSize;
01068         needed += CredentialA->CredentialBlobSize;
01069         len -= CredentialA->CredentialBlobSize;
01070     }
01071     else
01072         CredentialW->CredentialBlob = NULL;
01073     CredentialW->Persist = CredentialA->Persist;
01074     CredentialW->AttributeCount = 0;
01075     CredentialW->Attributes = NULL; /* FIXME */
01076     if (CredentialA->TargetAlias)
01077     {
01078         CredentialW->TargetAlias = (LPWSTR)buffer;
01079         string_len = MultiByteToWideChar(CP_ACP, 0, CredentialA->TargetAlias, -1, CredentialW->TargetAlias, len / sizeof(WCHAR));
01080         buffer += sizeof(WCHAR) * string_len;
01081         needed += sizeof(WCHAR) * string_len;
01082         len -= sizeof(WCHAR) * string_len;
01083     }
01084     else
01085         CredentialW->TargetAlias = NULL;
01086     if (CredentialA->UserName)
01087     {
01088         CredentialW->UserName = (LPWSTR)buffer;
01089         string_len = MultiByteToWideChar(CP_ACP, 0, CredentialA->UserName, -1, CredentialW->UserName, len / sizeof(WCHAR));
01090         needed += sizeof(WCHAR) * string_len;
01091     }
01092     else
01093         CredentialW->UserName = NULL;
01094 
01095     return needed;
01096 }
01097 
01098 /******************************************************************************
01099  * CredDeleteA [ADVAPI32.@]
01100  */
01101 BOOL WINAPI CredDeleteA(LPCSTR TargetName, DWORD Type, DWORD Flags)
01102 {
01103     LPWSTR TargetNameW;
01104     DWORD len;
01105     BOOL ret;
01106 
01107     TRACE("(%s, %d, 0x%x)\n", debugstr_a(TargetName), Type, Flags);
01108 
01109     if (!TargetName)
01110     {
01111         SetLastError(ERROR_INVALID_PARAMETER);
01112         return FALSE;
01113     }
01114 
01115     len = MultiByteToWideChar(CP_ACP, 0, TargetName, -1, NULL, 0);
01116     TargetNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
01117     if (!TargetNameW)
01118     {
01119         SetLastError(ERROR_OUTOFMEMORY);
01120         return FALSE;
01121     }
01122     MultiByteToWideChar(CP_ACP, 0, TargetName, -1, TargetNameW, len);
01123 
01124     ret = CredDeleteW(TargetNameW, Type, Flags);
01125 
01126     HeapFree(GetProcessHeap(), 0, TargetNameW);
01127 
01128     return ret;
01129 }
01130 
01131 /******************************************************************************
01132  * CredDeleteW [ADVAPI32.@]
01133  */
01134 BOOL WINAPI CredDeleteW(LPCWSTR TargetName, DWORD Type, DWORD Flags)
01135 {
01136     HKEY hkeyMgr;
01137     DWORD ret;
01138     LPWSTR key_name;
01139 
01140     TRACE("(%s, %d, 0x%x)\n", debugstr_w(TargetName), Type, Flags);
01141 
01142     if (!TargetName)
01143     {
01144         SetLastError(ERROR_INVALID_PARAMETER);
01145         return FALSE;
01146     }
01147 
01148     if (Type != CRED_TYPE_GENERIC && Type != CRED_TYPE_DOMAIN_PASSWORD)
01149     {
01150         FIXME("unhandled type %d\n", Type);
01151         SetLastError(ERROR_INVALID_PARAMETER);
01152         return FALSE;
01153     }
01154 
01155     if (Flags)
01156     {
01157         FIXME("unhandled flags 0x%x\n", Flags);
01158         SetLastError(ERROR_INVALID_FLAGS);
01159         return FALSE;
01160     }
01161 
01162 #ifdef __APPLE__
01163     if (Type == CRED_TYPE_DOMAIN_PASSWORD)
01164     {
01165         ret = mac_delete_credential(TargetName);
01166         if (ret == ERROR_SUCCESS)
01167             return TRUE;
01168     }
01169 #endif
01170 
01171     ret = open_cred_mgr_key(&hkeyMgr, TRUE);
01172     if (ret != ERROR_SUCCESS)
01173     {
01174         WARN("couldn't open/create manager key, error %d\n", ret);
01175         SetLastError(ERROR_NO_SUCH_LOGON_SESSION);
01176         return FALSE;
01177     }
01178 
01179     key_name = get_key_name_for_target(TargetName, Type);
01180     ret = RegDeleteKeyW(hkeyMgr, key_name);
01181     HeapFree(GetProcessHeap(), 0, key_name);
01182     RegCloseKey(hkeyMgr);
01183     if (ret != ERROR_SUCCESS)
01184     {
01185         SetLastError(ERROR_NOT_FOUND);
01186         return FALSE;
01187     }
01188 
01189     return TRUE;
01190 }
01191 
01192 /******************************************************************************
01193  * CredEnumerateA [ADVAPI32.@]
01194  */
01195 BOOL WINAPI CredEnumerateA(LPCSTR Filter, DWORD Flags, DWORD *Count,
01196                            PCREDENTIALA **Credentials)
01197 {
01198     LPWSTR FilterW;
01199     PCREDENTIALW *CredentialsW;
01200     DWORD i;
01201     INT len;
01202     INT needed;
01203     char *buffer;
01204 
01205     TRACE("(%s, 0x%x, %p, %p)\n", debugstr_a(Filter), Flags, Count, Credentials);
01206 
01207     if (Filter)
01208     {
01209         len = MultiByteToWideChar(CP_ACP, 0, Filter, -1, NULL, 0);
01210         FilterW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
01211         if (!FilterW)
01212         {
01213             SetLastError(ERROR_OUTOFMEMORY);
01214             return FALSE;
01215         }
01216         MultiByteToWideChar(CP_ACP, 0, Filter, -1, FilterW, len);
01217     }
01218     else
01219         FilterW = NULL;
01220 
01221     if (!CredEnumerateW(FilterW, Flags, Count, &CredentialsW))
01222     {
01223         HeapFree(GetProcessHeap(), 0, FilterW);
01224         return FALSE;
01225     }
01226     HeapFree(GetProcessHeap(), 0, FilterW);
01227 
01228     len = *Count * sizeof(PCREDENTIALA);
01229     for (i = 0; i < *Count; i++)
01230         len += convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW[i], NULL, 0);
01231 
01232     *Credentials = HeapAlloc(GetProcessHeap(), 0, len);
01233     if (!*Credentials)
01234     {
01235         CredFree(CredentialsW);
01236         SetLastError(ERROR_OUTOFMEMORY);
01237         return FALSE;
01238     }
01239 
01240     buffer = (char *)&(*Credentials)[*Count];
01241     len -= *Count * sizeof(PCREDENTIALA);
01242     for (i = 0; i < *Count; i++)
01243     {
01244         (*Credentials)[i] = (PCREDENTIALA)buffer;
01245         needed = convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW[i], (*Credentials)[i], len);
01246         buffer += needed;
01247         len -= needed;
01248     }
01249 
01250     CredFree(CredentialsW);
01251 
01252     return TRUE;
01253 }
01254 
01255 /******************************************************************************
01256  * CredEnumerateW [ADVAPI32.@]
01257  */
01258 BOOL WINAPI CredEnumerateW(LPCWSTR Filter, DWORD Flags, DWORD *Count,
01259                            PCREDENTIALW **Credentials)
01260 {
01261     HKEY hkeyMgr;
01262     DWORD ret;
01263     LPWSTR target_name;
01264     DWORD target_name_len;
01265     DWORD len;
01266     char *buffer;
01267     BYTE key_data[KEY_SIZE];
01268 
01269     TRACE("(%s, 0x%x, %p, %p)\n", debugstr_w(Filter), Flags, Count, Credentials);
01270 
01271     if (Flags)
01272     {
01273         SetLastError(ERROR_INVALID_FLAGS);
01274         return FALSE;
01275     }
01276 
01277     ret = open_cred_mgr_key(&hkeyMgr, FALSE);
01278     if (ret != ERROR_SUCCESS)
01279     {
01280         WARN("couldn't open/create manager key, error %d\n", ret);
01281         SetLastError(ERROR_NO_SUCH_LOGON_SESSION);
01282         return FALSE;
01283     }
01284 
01285     ret = get_cred_mgr_encryption_key(hkeyMgr, key_data);
01286     if (ret != ERROR_SUCCESS)
01287     {
01288         RegCloseKey(hkeyMgr);
01289         SetLastError(ret);
01290         return FALSE;
01291     }
01292 
01293     ret = RegQueryInfoKeyW(hkeyMgr, NULL, NULL, NULL, NULL, &target_name_len, NULL, NULL, NULL, NULL, NULL, NULL);
01294     if (ret != ERROR_SUCCESS)
01295     {
01296         RegCloseKey(hkeyMgr);
01297         SetLastError(ret);
01298         return FALSE;
01299     }
01300 
01301     target_name = HeapAlloc(GetProcessHeap(), 0, (target_name_len+1)*sizeof(WCHAR));
01302     if (!target_name)
01303     {
01304         RegCloseKey(hkeyMgr);
01305         SetLastError(ERROR_OUTOFMEMORY);
01306         return FALSE;
01307     }
01308 
01309     *Count = 0;
01310     len = 0;
01311     ret = registry_enumerate_credentials(hkeyMgr, Filter, target_name, target_name_len,
01312                                          key_data, NULL, NULL, &len, Count);
01313 #ifdef __APPLE__
01314     if (ret == ERROR_SUCCESS)
01315         ret = mac_enumerate_credentials(Filter, NULL, NULL, &len, Count);
01316 #endif
01317     if (ret == ERROR_SUCCESS && *Count == 0)
01318         ret = ERROR_NOT_FOUND;
01319     if (ret != ERROR_SUCCESS)
01320     {
01321         HeapFree(GetProcessHeap(), 0, target_name);
01322         RegCloseKey(hkeyMgr);
01323         SetLastError(ret);
01324         return FALSE;
01325     }
01326     len += *Count * sizeof(PCREDENTIALW);
01327 
01328     if (ret == ERROR_SUCCESS)
01329     {
01330         buffer = HeapAlloc(GetProcessHeap(), 0, len);
01331         *Credentials = (PCREDENTIALW *)buffer;
01332         if (buffer)
01333         {
01334             buffer += *Count * sizeof(PCREDENTIALW);
01335             *Count = 0;
01336             ret = registry_enumerate_credentials(hkeyMgr, Filter, target_name,
01337                                                  target_name_len, key_data,
01338                                                  *Credentials, &buffer, &len,
01339                                                  Count);
01340 #ifdef __APPLE__
01341             if (ret == ERROR_SUCCESS)
01342                 ret = mac_enumerate_credentials(Filter, *Credentials,
01343                                                 buffer, &len, Count);
01344 #endif
01345         }
01346         else
01347             ret = ERROR_OUTOFMEMORY;
01348     }
01349 
01350     HeapFree(GetProcessHeap(), 0, target_name);
01351     RegCloseKey(hkeyMgr);
01352 
01353     if (ret != ERROR_SUCCESS)
01354     {
01355         SetLastError(ret);
01356         return FALSE;
01357     }
01358     return TRUE;
01359 }
01360 
01361 /******************************************************************************
01362  * CredFree [ADVAPI32.@]
01363  */
01364 VOID WINAPI CredFree(PVOID Buffer)
01365 {
01366     HeapFree(GetProcessHeap(), 0, Buffer);
01367 }
01368 
01369 /******************************************************************************
01370  * CredReadA [ADVAPI32.@]
01371  */
01372 BOOL WINAPI CredReadA(LPCSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALA *Credential)
01373 {
01374     LPWSTR TargetNameW;
01375     PCREDENTIALW CredentialW;
01376     INT len;
01377 
01378     TRACE("(%s, %d, 0x%x, %p)\n", debugstr_a(TargetName), Type, Flags, Credential);
01379 
01380     if (!TargetName)
01381     {
01382         SetLastError(ERROR_INVALID_PARAMETER);
01383         return FALSE;
01384     }
01385 
01386     len = MultiByteToWideChar(CP_ACP, 0, TargetName, -1, NULL, 0);
01387     TargetNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
01388     if (!TargetNameW)
01389     {
01390         SetLastError(ERROR_OUTOFMEMORY);
01391         return FALSE;
01392     }
01393     MultiByteToWideChar(CP_ACP, 0, TargetName, -1, TargetNameW, len);
01394 
01395     if (!CredReadW(TargetNameW, Type, Flags, &CredentialW))
01396     {
01397         HeapFree(GetProcessHeap(), 0, TargetNameW);
01398         return FALSE;
01399     }
01400     HeapFree(GetProcessHeap(), 0, TargetNameW);
01401 
01402     len = convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW, NULL, 0);
01403     *Credential = HeapAlloc(GetProcessHeap(), 0, len);
01404     if (!*Credential)
01405     {
01406         SetLastError(ERROR_OUTOFMEMORY);
01407         return FALSE;
01408     }
01409     convert_PCREDENTIALW_to_PCREDENTIALA(CredentialW, *Credential, len);
01410 
01411     CredFree(CredentialW);
01412 
01413     return TRUE;
01414 }
01415 
01416 /******************************************************************************
01417  * CredReadW [ADVAPI32.@]
01418  */
01419 BOOL WINAPI CredReadW(LPCWSTR TargetName, DWORD Type, DWORD Flags, PCREDENTIALW *Credential)
01420 {
01421     HKEY hkeyMgr;
01422     HKEY hkeyCred;
01423     DWORD ret;
01424     LPWSTR key_name;
01425     DWORD len;
01426     BYTE key_data[KEY_SIZE];
01427 
01428     TRACE("(%s, %d, 0x%x, %p)\n", debugstr_w(TargetName), Type, Flags, Credential);
01429 
01430     if (!TargetName)
01431     {
01432         SetLastError(ERROR_INVALID_PARAMETER);
01433         return FALSE;
01434     }
01435 
01436     if (Type != CRED_TYPE_GENERIC && Type != CRED_TYPE_DOMAIN_PASSWORD)
01437     {
01438         FIXME("unhandled type %d\n", Type);
01439         SetLastError(ERROR_INVALID_PARAMETER);
01440         return FALSE;
01441     }
01442 
01443     if (Flags)
01444     {
01445         FIXME("unhandled flags 0x%x\n", Flags);
01446         SetLastError(ERROR_INVALID_FLAGS);
01447         return FALSE;
01448     }
01449 
01450 #ifdef __APPLE__
01451     if (Type == CRED_TYPE_DOMAIN_PASSWORD)
01452     {
01453         OSStatus status;
01454         SecKeychainSearchRef search;
01455         status = SecKeychainSearchCreateFromAttributes(NULL, kSecInternetPasswordItemClass, NULL, &search);
01456         if (status == noErr)
01457         {
01458             SecKeychainItemRef item;
01459             while (SecKeychainSearchCopyNext(search, &item) == noErr)
01460             {
01461                 SecKeychainAttributeInfo info;
01462                 SecKeychainAttributeList *attr_list;
01463                 UInt32 info_tags[] = { kSecServerItemAttr };
01464                 LPWSTR target_name;
01465                 INT str_len;
01466                 info.count = sizeof(info_tags)/sizeof(info_tags[0]);
01467                 info.tag = info_tags;
01468                 info.format = NULL;
01469                 status = SecKeychainItemCopyAttributesAndData(item, &info, NULL, &attr_list, NULL, NULL);
01470                 len = sizeof(**Credential);
01471                 if (status != noErr)
01472                 {
01473                     WARN("SecKeychainItemCopyAttributesAndData returned status %ld\n", status);
01474                     continue;
01475                 }
01476                 if (attr_list->count != 1 || attr_list->attr[0].tag != kSecServerItemAttr)
01477                 {
01478                     CFRelease(item);
01479                     continue;
01480                 }
01481                 str_len = MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[0].data, attr_list->attr[0].length, NULL, 0);
01482                 target_name = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
01483                 MultiByteToWideChar(CP_UTF8, 0, attr_list->attr[0].data, attr_list->attr[0].length, target_name, str_len);
01484                 /* nul terminate */
01485                 target_name[str_len] = '\0';
01486                 if (strcmpiW(TargetName, target_name))
01487                 {
01488                     CFRelease(item);
01489                     HeapFree(GetProcessHeap(), 0, target_name);
01490                     continue;
01491                 }
01492                 HeapFree(GetProcessHeap(), 0, target_name);
01493                 SecKeychainItemFreeAttributesAndData(attr_list, NULL);
01494                 ret = mac_read_credential_from_item(item, TRUE, NULL, NULL, &len);
01495                 if (ret == ERROR_SUCCESS)
01496                 {
01497                     *Credential = HeapAlloc(GetProcessHeap(), 0, len);
01498                     if (*Credential)
01499                     {
01500                         len = sizeof(**Credential);
01501                         ret = mac_read_credential_from_item(item, TRUE, *Credential,
01502                                                             (char *)(*Credential + 1), &len);
01503                     }
01504                     else
01505                         ret = ERROR_OUTOFMEMORY;
01506                     CFRelease(item);
01507                     CFRelease(search);
01508                     if (ret != ERROR_SUCCESS)
01509                     {
01510                         SetLastError(ret);
01511                         return FALSE;
01512                     }
01513                     return TRUE;
01514                 }
01515                 CFRelease(item);
01516             }
01517             CFRelease(search);
01518         }
01519     }
01520 #endif
01521 
01522     ret = open_cred_mgr_key(&hkeyMgr, FALSE);
01523     if (ret != ERROR_SUCCESS)
01524     {
01525         WARN("couldn't open/create manager key, error %d\n", ret);
01526         SetLastError(ERROR_NO_SUCH_LOGON_SESSION);
01527         return FALSE;
01528     }
01529 
01530     ret = get_cred_mgr_encryption_key(hkeyMgr, key_data);
01531     if (ret != ERROR_SUCCESS)
01532     {
01533         RegCloseKey(hkeyMgr);
01534         SetLastError(ret);
01535         return FALSE;
01536     }
01537 
01538     key_name = get_key_name_for_target(TargetName, Type);
01539     ret = RegOpenKeyExW(hkeyMgr, key_name, 0, KEY_QUERY_VALUE, &hkeyCred);
01540     HeapFree(GetProcessHeap(), 0, key_name);
01541     if (ret != ERROR_SUCCESS)
01542     {
01543         TRACE("credentials for target name %s not found\n", debugstr_w(TargetName));
01544         SetLastError(ERROR_NOT_FOUND);
01545         return FALSE;
01546     }
01547 
01548     len = sizeof(**Credential);
01549     ret = registry_read_credential(hkeyCred, NULL, key_data, NULL, &len);
01550     if (ret == ERROR_SUCCESS)
01551     {
01552         *Credential = HeapAlloc(GetProcessHeap(), 0, len);
01553         if (*Credential)
01554         {
01555             len = sizeof(**Credential);
01556             ret = registry_read_credential(hkeyCred, *Credential, key_data,
01557                                            (char *)(*Credential + 1), &len);
01558         }
01559         else
01560             ret = ERROR_OUTOFMEMORY;
01561     }
01562 
01563     RegCloseKey(hkeyCred);
01564     RegCloseKey(hkeyMgr);
01565 
01566     if (ret != ERROR_SUCCESS)
01567     {
01568         SetLastError(ret);
01569         return FALSE;
01570     }
01571     return TRUE;
01572 }
01573 
01574 /******************************************************************************
01575  * CredReadDomainCredentialsA [ADVAPI32.@]
01576  */
01577 BOOL WINAPI CredReadDomainCredentialsA(PCREDENTIAL_TARGET_INFORMATIONA TargetInformation,
01578                                        DWORD Flags, DWORD *Size, PCREDENTIALA **Credentials)
01579 {
01580     PCREDENTIAL_TARGET_INFORMATIONW TargetInformationW;
01581     INT len, i;
01582     WCHAR *buffer, *end;
01583     BOOL ret;
01584     PCREDENTIALW* CredentialsW;
01585 
01586     TRACE("(%p, 0x%x, %p, %p)\n", TargetInformation, Flags, Size, Credentials);
01587 
01588     /* follow Windows behavior - do not test for NULL, initialize early */
01589     *Size = 0;
01590     *Credentials = NULL;
01591 
01592     if (!TargetInformation)
01593     {
01594         SetLastError(ERROR_INVALID_PARAMETER);
01595         return FALSE;
01596     }
01597 
01598     len = sizeof(*TargetInformationW);
01599     if (TargetInformation->TargetName)
01600         len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->TargetName, -1, NULL, 0) * sizeof(WCHAR);
01601     if (TargetInformation->NetbiosServerName)
01602         len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->NetbiosServerName, -1, NULL, 0) * sizeof(WCHAR);
01603     if (TargetInformation->DnsServerName)
01604         len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsServerName, -1, NULL, 0) * sizeof(WCHAR);
01605     if (TargetInformation->NetbiosDomainName)
01606         len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->NetbiosDomainName, -1, NULL, 0) * sizeof(WCHAR);
01607     if (TargetInformation->DnsDomainName)
01608         len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsDomainName, -1, NULL, 0) * sizeof(WCHAR);
01609     if (TargetInformation->DnsTreeName)
01610         len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsTreeName, -1, NULL, 0) * sizeof(WCHAR);
01611     if (TargetInformation->PackageName)
01612         len += MultiByteToWideChar(CP_ACP, 0, TargetInformation->PackageName, -1, NULL, 0) * sizeof(WCHAR);
01613 
01614     TargetInformationW = HeapAlloc(GetProcessHeap(), 0, len);
01615     if (!TargetInformationW)
01616     {
01617         SetLastError(ERROR_OUTOFMEMORY);
01618         return FALSE;
01619     }
01620     buffer = (WCHAR*)(TargetInformationW + 1);
01621     end = (WCHAR *)((char *)TargetInformationW + len);
01622 
01623     if (TargetInformation->TargetName)
01624     {
01625         TargetInformationW->TargetName = buffer;
01626         buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->TargetName, -1,
01627                                       TargetInformationW->TargetName, end - buffer);
01628     } else
01629         TargetInformationW->TargetName = NULL;
01630 
01631     if (TargetInformation->NetbiosServerName)
01632     {
01633         TargetInformationW->NetbiosServerName = buffer;
01634         buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->NetbiosServerName, -1,
01635                                       TargetInformationW->NetbiosServerName, end - buffer);
01636     } else
01637         TargetInformationW->NetbiosServerName = NULL;
01638 
01639     if (TargetInformation->DnsServerName)
01640     {
01641         TargetInformationW->DnsServerName = buffer;
01642         buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsServerName, -1,
01643                                       TargetInformationW->DnsServerName, end - buffer);
01644     } else
01645         TargetInformationW->DnsServerName = NULL;
01646 
01647     if (TargetInformation->NetbiosDomainName)
01648     {
01649         TargetInformationW->NetbiosDomainName = buffer;
01650         buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->NetbiosDomainName, -1,
01651                                       TargetInformationW->NetbiosDomainName, end - buffer);
01652     } else
01653         TargetInformationW->NetbiosDomainName = NULL;
01654 
01655     if (TargetInformation->DnsDomainName)
01656     {
01657         TargetInformationW->DnsDomainName = buffer;
01658         buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsDomainName, -1,
01659                                       TargetInformationW->DnsDomainName, end - buffer);
01660     } else
01661         TargetInformationW->DnsDomainName = NULL;
01662 
01663     if (TargetInformation->DnsTreeName)
01664     {
01665         TargetInformationW->DnsTreeName = buffer;
01666         buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->DnsTreeName, -1,
01667                                       TargetInformationW->DnsTreeName, end - buffer);
01668     } else
01669         TargetInformationW->DnsTreeName = NULL;
01670 
01671     if (TargetInformation->PackageName)
01672     {
01673         TargetInformationW->PackageName = buffer;
01674         buffer += MultiByteToWideChar(CP_ACP, 0, TargetInformation->PackageName, -1,
01675                                       TargetInformationW->PackageName, end - buffer);
01676     } else
01677         TargetInformationW->PackageName = NULL;
01678 
01679     TargetInformationW->Flags = TargetInformation->Flags;
01680     TargetInformationW->CredTypeCount = TargetInformation->CredTypeCount;
01681     TargetInformationW->CredTypes = TargetInformation->CredTypes;
01682 
01683     ret = CredReadDomainCredentialsW(TargetInformationW, Flags, Size, &CredentialsW);
01684 
01685     HeapFree(GetProcessHeap(), 0, TargetInformationW);
01686 
01687     if (ret)
01688     {
01689         char *buf;
01690         INT needed;
01691 
01692         len = *Size * sizeof(PCREDENTIALA);
01693         for (i = 0; i < *Size; i++)
01694             len += convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW[i], NULL, 0);
01695 
01696         *Credentials = HeapAlloc(GetProcessHeap(), 0, len);
01697         if (!*Credentials)
01698         {
01699             CredFree(CredentialsW);
01700             SetLastError(ERROR_OUTOFMEMORY);
01701             return FALSE;
01702         }
01703 
01704         buf = (char *)&(*Credentials)[*Size];
01705         len -= *Size * sizeof(PCREDENTIALA);
01706         for (i = 0; i < *Size; i++)
01707         {
01708             (*Credentials)[i] = (PCREDENTIALA)buf;
01709             needed = convert_PCREDENTIALW_to_PCREDENTIALA(CredentialsW[i], (*Credentials)[i], len);
01710             buf += needed;
01711             len -= needed;
01712         }
01713 
01714         CredFree(CredentialsW);
01715     }
01716     return ret;
01717 }
01718 
01719 /******************************************************************************
01720  * CredReadDomainCredentialsW [ADVAPI32.@]
01721  */
01722 BOOL WINAPI CredReadDomainCredentialsW(PCREDENTIAL_TARGET_INFORMATIONW TargetInformation, DWORD Flags,
01723                                        DWORD *Size, PCREDENTIALW **Credentials)
01724 {
01725     FIXME("(%p, 0x%x, %p, %p) stub\n", TargetInformation, Flags, Size, Credentials);
01726 
01727     /* follow Windows behavior - do not test for NULL, initialize early */
01728     *Size = 0;
01729     *Credentials = NULL;
01730     if (!TargetInformation)
01731     {
01732         SetLastError(ERROR_INVALID_PARAMETER);
01733         return FALSE;
01734     }
01735 
01736     SetLastError(ERROR_NOT_FOUND);
01737     return FALSE;
01738 }
01739 
01740 /******************************************************************************
01741  * CredWriteA [ADVAPI32.@]
01742  */
01743 BOOL WINAPI CredWriteA(PCREDENTIALA Credential, DWORD Flags)
01744 {
01745     BOOL ret;
01746     INT len;
01747     PCREDENTIALW CredentialW;
01748 
01749     TRACE("(%p, 0x%x)\n", Credential, Flags);
01750 
01751     if (!Credential || !Credential->TargetName)
01752     {
01753         SetLastError(ERROR_INVALID_PARAMETER);
01754         return FALSE;
01755     }
01756 
01757     len = convert_PCREDENTIALA_to_PCREDENTIALW(Credential, NULL, 0);
01758     CredentialW = HeapAlloc(GetProcessHeap(), 0, len);
01759     if (!CredentialW)
01760     {
01761         SetLastError(ERROR_OUTOFMEMORY);
01762         return FALSE;
01763     }
01764 
01765     convert_PCREDENTIALA_to_PCREDENTIALW(Credential, CredentialW, len);
01766 
01767     ret = CredWriteW(CredentialW, Flags);
01768 
01769     HeapFree(GetProcessHeap(), 0, CredentialW);
01770 
01771     return ret;
01772 }
01773 
01774 /******************************************************************************
01775  * CredWriteW [ADVAPI32.@]
01776  */
01777 BOOL WINAPI CredWriteW(PCREDENTIALW Credential, DWORD Flags)
01778 {
01779     HKEY hkeyMgr;
01780     HKEY hkeyCred;
01781     DWORD ret;
01782     LPWSTR key_name;
01783     BYTE key_data[KEY_SIZE];
01784 
01785     TRACE("(%p, 0x%x)\n", Credential, Flags);
01786 
01787     if (!Credential || !Credential->TargetName)
01788     {
01789         SetLastError(ERROR_INVALID_PARAMETER);
01790         return FALSE;
01791     }
01792 
01793     if (Flags & ~CRED_PRESERVE_CREDENTIAL_BLOB)
01794     {
01795         FIXME("unhandled flags 0x%x\n", Flags);
01796         SetLastError(ERROR_INVALID_FLAGS);
01797         return FALSE;
01798     }
01799 
01800     if (Credential->Type != CRED_TYPE_GENERIC && Credential->Type != CRED_TYPE_DOMAIN_PASSWORD)
01801     {
01802         FIXME("unhandled type %d\n", Credential->Type);
01803         SetLastError(ERROR_INVALID_PARAMETER);
01804         return FALSE;
01805     }
01806 
01807     TRACE("Credential->TargetName = %s\n", debugstr_w(Credential->TargetName));
01808     TRACE("Credential->UserName = %s\n", debugstr_w(Credential->UserName));
01809 
01810     if (Credential->Type == CRED_TYPE_DOMAIN_PASSWORD)
01811     {
01812         if (!Credential->UserName ||
01813             (!strchrW(Credential->UserName, '\\') && !strchrW(Credential->UserName, '@')))
01814         {
01815             ERR("bad username %s\n", debugstr_w(Credential->UserName));
01816             SetLastError(ERROR_BAD_USERNAME);
01817             return FALSE;
01818         }
01819     }
01820 
01821 #ifdef __APPLE__
01822     if (!Credential->AttributeCount &&
01823         Credential->Type == CRED_TYPE_DOMAIN_PASSWORD &&
01824         (Credential->Persist == CRED_PERSIST_LOCAL_MACHINE || Credential->Persist == CRED_PERSIST_ENTERPRISE))
01825     {
01826         ret = mac_write_credential(Credential, Flags & CRED_PRESERVE_CREDENTIAL_BLOB);
01827         if (ret != ERROR_SUCCESS)
01828         {
01829             SetLastError(ret);
01830             return FALSE;
01831         }
01832         return TRUE;
01833     }
01834 #endif
01835 
01836     ret = open_cred_mgr_key(&hkeyMgr, FALSE);
01837     if (ret != ERROR_SUCCESS)
01838     {
01839         WARN("couldn't open/create manager key, error %d\n", ret);
01840         SetLastError(ERROR_NO_SUCH_LOGON_SESSION);
01841         return FALSE;
01842     }
01843 
01844     ret = get_cred_mgr_encryption_key(hkeyMgr, key_data);
01845     if (ret != ERROR_SUCCESS)
01846     {
01847         RegCloseKey(hkeyMgr);
01848         SetLastError(ret);
01849         return FALSE;
01850     }
01851 
01852     key_name = get_key_name_for_target(Credential->TargetName, Credential->Type);
01853     ret = RegCreateKeyExW(hkeyMgr, key_name, 0, NULL,
01854                           Credential->Persist == CRED_PERSIST_SESSION ? REG_OPTION_VOLATILE : REG_OPTION_NON_VOLATILE,
01855                           KEY_READ|KEY_WRITE, NULL, &hkeyCred, NULL);
01856     HeapFree(GetProcessHeap(), 0, key_name);
01857     if (ret != ERROR_SUCCESS)
01858     {
01859         TRACE("credentials for target name %s not found\n",
01860               debugstr_w(Credential->TargetName));
01861         SetLastError(ERROR_NOT_FOUND);
01862         return FALSE;
01863     }
01864 
01865     ret = registry_write_credential(hkeyCred, Credential, key_data,
01866                                     Flags & CRED_PRESERVE_CREDENTIAL_BLOB);
01867 
01868     RegCloseKey(hkeyCred);
01869     RegCloseKey(hkeyMgr);
01870 
01871     if (ret != ERROR_SUCCESS)
01872     {
01873         SetLastError(ret);
01874         return FALSE;
01875     }
01876     return TRUE;
01877 }
01878 
01879 /******************************************************************************
01880  * CredGetSessionTypes [ADVAPI32.@]
01881  */
01882 BOOL WINAPI CredGetSessionTypes(DWORD persistCount, LPDWORD persists)
01883 {
01884     TRACE("(%u, %p)\n", persistCount, persists);
01885 
01886     memset(persists, CRED_PERSIST_NONE, persistCount*sizeof(*persists));
01887     if (CRED_TYPE_GENERIC < persistCount)
01888     {
01889         persists[CRED_TYPE_GENERIC] = CRED_PERSIST_ENTERPRISE;
01890 
01891         if (CRED_TYPE_DOMAIN_PASSWORD < persistCount)
01892         {
01893             persists[CRED_TYPE_DOMAIN_PASSWORD] = CRED_PERSIST_ENTERPRISE;
01894         }
01895     }
01896     return TRUE;
01897 }
01898 
01899 BOOL
01900 WINAPI
01901 CredWriteDomainCredentialsW(PCREDENTIAL_TARGET_INFORMATIONW TargetInfo,
01902                             PCREDENTIALW Credential,
01903                             DWORD Flags)
01904 {
01905     WARN("Not implemented\n");
01906     return FALSE;
01907 }
01908 
01909 BOOL
01910 WINAPI
01911 CredWriteDomainCredentialsA(PCREDENTIAL_TARGET_INFORMATIONA TargetInfo,
01912                             PCREDENTIALA Credential,
01913                             DWORD Flags)
01914 {
01915     WARN("Not implemented\n");
01916     return FALSE;
01917 }
01918 
01919 BOOL
01920 WINAPI
01921 CredUnmarshalCredentialW(LPCWSTR MarshaledCredential,
01922                          PCRED_MARSHAL_TYPE CredType,
01923                          PVOID *Credential)
01924 {
01925     WARN("Not implemented\n");
01926     return FALSE;
01927 }
01928 
01929 BOOL
01930 WINAPI
01931 CredUnmarshalCredentialA(LPCSTR MarshaledCredential,
01932                          PCRED_MARSHAL_TYPE CredType,
01933                          PVOID *Credential)
01934 {
01935     WARN("Not implemented\n");
01936     return FALSE;
01937 }

Generated on Sat May 26 2012 04:21:12 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.