secur32: Try to retrive credentials by using the credential manager to retrieve credentials saved for the target server in InitializeContextHandleW, if possible.
diff --git a/dlls/secur32/ntlm.c b/dlls/secur32/ntlm.c
index 423a167..5b95d92 100644
--- a/dlls/secur32/ntlm.c
+++ b/dlls/secur32/ntlm.c
@@ -24,11 +24,13 @@
 #include "windef.h"
 #include "winbase.h"
 #include "winnls.h"
+#include "wincred.h"
 #include "rpc.h"
 #include "sspi.h"
 #include "lm.h"
 #include "secur32_priv.h"
 #include "hmac_md5.h"
+#include "wine/unicode.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ntlm);
@@ -93,6 +95,42 @@
     return ret;
 }
 
+static char *ntlm_GetUsernameArg(LPCWSTR userW, INT userW_length)
+{
+    static const char username_arg[] = "--username=";
+    char *user;
+    int unixcp_size;
+
+    unixcp_size =  WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS,
+        userW, userW_length, NULL, 0, NULL, NULL) + sizeof(username_arg);
+    user = HeapAlloc(GetProcessHeap(), 0, unixcp_size);
+    if (!user) return NULL;
+    memcpy(user, username_arg, sizeof(username_arg) - 1);
+    WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, userW, userW_length,
+        user + sizeof(username_arg) - 1,
+        unixcp_size - sizeof(username_arg) + 1, NULL, NULL);
+    user[unixcp_size - 1] = '\0';
+    return user;
+}
+
+static char *ntlm_GetDomainArg(LPCWSTR domainW, INT domainW_length)
+{
+    static const char domain_arg[] = "--domain=";
+    char *domain;
+    int unixcp_size;
+
+    unixcp_size = WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS,
+        domainW, domainW_length, NULL, 0,  NULL, NULL) + sizeof(domain_arg);
+    domain = HeapAlloc(GetProcessHeap(), 0, unixcp_size);
+    if (!domain) return NULL;
+    memcpy(domain, domain_arg, sizeof(domain_arg) - 1);
+    WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, domainW,
+        domainW_length, domain + sizeof(domain_arg) - 1,
+        unixcp_size - sizeof(domain) + 1, NULL, NULL);
+    domain[unixcp_size - 1] = '\0';
+    return domain;
+}
+
 /***********************************************************************
  *              AcquireCredentialsHandleW
  */
@@ -129,10 +167,6 @@
             break;
         case SECPKG_CRED_OUTBOUND:
             {
-                static const char username_arg[] = "--username=";
-                static const char domain_arg[] = "--domain=";
-                int unixcp_size;
-
                 ntlm_cred = HeapAlloc(GetProcessHeap(), 0, sizeof(*ntlm_cred));
                 if (!ntlm_cred)
                 {
@@ -153,24 +187,8 @@
                     TRACE("Username is %s\n", debugstr_wn(auth_data->User, auth_data->UserLength));
                     TRACE("Domain name is %s\n", debugstr_wn(auth_data->Domain, auth_data->DomainLength));
 
-                    /* Get username and domain from pAuthData */
-                    unixcp_size =  WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS,
-                            auth_data->User, auth_data->UserLength, NULL, 0, NULL, NULL) + sizeof(username_arg);
-                    ntlm_cred->username_arg = HeapAlloc(GetProcessHeap(), 0, unixcp_size);
-                    memcpy(ntlm_cred->username_arg, username_arg, sizeof(username_arg) - 1);
-                    WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, auth_data->User, auth_data->UserLength,
-                            ntlm_cred->username_arg + sizeof(username_arg) - 1,
-                            unixcp_size - sizeof(username_arg) + 1, NULL, NULL);
-                    ntlm_cred->username_arg[unixcp_size - 1] = '\0';
-
-                    unixcp_size = WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS,
-                            auth_data->Domain, auth_data->DomainLength, NULL, 0,  NULL, NULL) + sizeof(domain_arg);
-                    ntlm_cred->domain_arg = HeapAlloc(GetProcessHeap(), 0, unixcp_size);
-                    memcpy(ntlm_cred->domain_arg, domain_arg, sizeof(domain_arg) - 1);
-                    WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, auth_data->Domain,
-                            auth_data->DomainLength, ntlm_cred->domain_arg + sizeof(domain_arg) - 1,
-                            unixcp_size - sizeof(domain) + 1, NULL, NULL);
-                    ntlm_cred->domain_arg[unixcp_size - 1] = '\0';
+                    ntlm_cred->username_arg = ntlm_GetUsernameArg(auth_data->User, auth_data->UserLength);
+                    ntlm_cred->domain_arg = ntlm_GetDomainArg(auth_data->Domain, auth_data->DomainLength);
 
                     if(auth_data->PasswordLength != 0)
                     {
@@ -362,6 +380,46 @@
     return -1;
 }
 
+static BOOL ntlm_GetCachedCredential(const SEC_WCHAR *pszTargetName, PCREDENTIALW *cred)
+{
+    LPCWSTR p;
+    LPCWSTR pszHost;
+    LPWSTR pszHostOnly;
+    BOOL ret;
+
+    if (!pszTargetName)
+        return FALSE;
+
+    /* try to get the start of the hostname from service principal name (SPN) */
+    pszHost = strchrW(pszTargetName, '/');
+    if (pszHost)
+    {
+        /* skip slash character */
+        pszHost++;
+
+        /* find end of host by detecting start of instance port or start of referrer */
+        p = strchrW(pszHost, ':');
+        if (!p)
+            p = strchrW(pszHost, '/');
+        if (!p)
+            p = pszHost + strlenW(pszHost);
+    }
+    else /* otherwise not an SPN, just a host */
+        p = pszHost + strlenW(pszHost);
+
+    pszHostOnly = HeapAlloc(GetProcessHeap(), 0, (p - pszHost + 1) * sizeof(WCHAR));
+    if (!pszHostOnly)
+        return FALSE;
+
+    memcpy(pszHostOnly, pszHost, (p - pszHost) * sizeof(WCHAR));
+    pszHostOnly[p - pszHost] = '\0';
+
+    ret = CredReadW(pszHostOnly, CRED_TYPE_DOMAIN_PASSWORD, 0, cred);
+
+    HeapFree(GetProcessHeap(), 0, pszHostOnly);
+    return ret;
+}
+
 /***********************************************************************
  *              InitializeSecurityContextW
  */
@@ -380,6 +438,8 @@
     int buffer_len, bin_len, max_len = NTLM_MAX_BUF;
     int token_idx;
     SEC_CHAR *username = NULL;
+    SEC_CHAR *domain = NULL;
+    SEC_CHAR *password = NULL;
 
     TRACE("%p %p %s %d %d %d %p %d %p %p %p %p\n", phCredential, phContext,
      debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
@@ -399,11 +459,6 @@
      */
     /* The squid cache size is 2010 chars, and that's what ntlm_auth uses */
 
-    if (pszTargetName)
-    {
-        TRACE("According to a MS whitepaper pszTargetName is ignored.\n");
-    }
-
     if(TargetDataRep == SECURITY_NETWORK_DREP){
         TRACE("Setting SECURITY_NETWORK_DREP\n");
     }
@@ -416,6 +471,7 @@
         static char helper_protocol[] = "--helper-protocol=ntlmssp-client-1";
         static CHAR credentials_argv[] = "--use-cached-creds";
         SEC_CHAR *client_argv[5];
+        int pwlen = 0;
 
         TRACE("First time in ISC()\n");
 
@@ -442,30 +498,62 @@
         {
             LPWKSTA_USER_INFO_1 ui = NULL;
             NET_API_STATUS status;
-            int unixcp_size;
-            static const char username_arg[] = "--username=";
+            PCREDENTIALW cred;
 
-            status = NetWkstaUserGetInfo(NULL, 1, (LPBYTE *)&ui);
-            if (status != NERR_Success || ui == NULL)
+            if (ntlm_GetCachedCredential(pszTargetName, &cred))
             {
-                ret = SEC_E_NO_CREDENTIALS;
-                goto isc_end;
+                LPWSTR p;
+                p = strchrW(cred->UserName, '\\');
+                if (p)
+                {
+                    domain = ntlm_GetDomainArg(cred->UserName, p - cred->UserName);
+                    p++;
+                }
+                else
+                {
+                    domain = ntlm_GetDomainArg(NULL, 0);
+                    p = cred->UserName;
+                }
+
+                username = ntlm_GetUsernameArg(p, -1);
+
+                if(cred->CredentialBlobSize != 0)
+                {
+                    pwlen = WideCharToMultiByte(CP_UNIXCP,
+                        WC_NO_BEST_FIT_CHARS, (LPWSTR)cred->CredentialBlob,
+                        cred->CredentialBlobSize / sizeof(WCHAR), NULL, 0,
+                        NULL, NULL);
+
+                    password = HeapAlloc(GetProcessHeap(), 0, pwlen);
+
+                    WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS,
+                                        (LPWSTR)cred->CredentialBlob,
+                                        cred->CredentialBlobSize / sizeof(WCHAR),
+                                        password, pwlen, NULL, NULL);
+                }
+
+                CredFree(cred);
+
+                client_argv[2] = username;
+                client_argv[3] = domain;
+                client_argv[4] = NULL;
             }
+            else
+            {
+                status = NetWkstaUserGetInfo(NULL, 1, (LPBYTE *)&ui);
+                if (status != NERR_Success || ui == NULL)
+                {
+                    ret = SEC_E_NO_CREDENTIALS;
+                    goto isc_end;
+                }
+                username = ntlm_GetUsernameArg(ui->wkui1_username, -1);
 
-            unixcp_size =  WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS,
-                    ui->wkui1_username, -1, NULL, 0, NULL, NULL) + sizeof(username_arg);
-            username = HeapAlloc(GetProcessHeap(), 0, unixcp_size);
-            memcpy(username, username_arg, sizeof(username_arg) - 1);
-            WideCharToMultiByte(CP_UNIXCP, WC_NO_BEST_FIT_CHARS, ui->wkui1_username, -1,
-                    username + sizeof(username_arg) - 1,
-                    unixcp_size - sizeof(username_arg) + 1, NULL, NULL);
-            username[unixcp_size - 1] = '\0';
+                TRACE("using cached credentials\n");
 
-            TRACE("using cached credentials\n");
-
-            client_argv[2] = username;
-            client_argv[3] = credentials_argv;
-            client_argv[4] = NULL;
+                client_argv[2] = username;
+                client_argv[3] = credentials_argv;
+                client_argv[4] = NULL;
+            }
         }
         else
         {
@@ -487,19 +575,20 @@
         }
 
         /* Generate the dummy session key = MD4(MD4(password))*/
-        if(ntlm_cred->password)
+        if(password || ntlm_cred->password)
         {
             SEC_WCHAR *unicode_password;
             int passwd_lenW;
 
             TRACE("Converting password to unicode.\n");
             passwd_lenW = MultiByteToWideChar(CP_ACP, 0,
-                                              (LPCSTR)ntlm_cred->password, ntlm_cred->pwlen,
+                                              password ? (LPCSTR)password : (LPCSTR)ntlm_cred->password,
+                                              password ? pwlen : ntlm_cred->pwlen,
                                               NULL, 0);
             unicode_password = HeapAlloc(GetProcessHeap(), 0,
                                          passwd_lenW * sizeof(SEC_WCHAR));
-            MultiByteToWideChar(CP_ACP, 0, (LPCSTR)ntlm_cred->password,
-                                ntlm_cred->pwlen, unicode_password, passwd_lenW);
+            MultiByteToWideChar(CP_ACP, 0, password ? (LPCSTR)password : (LPCSTR)ntlm_cred->password,
+                                password ? pwlen : ntlm_cred->pwlen, unicode_password, passwd_lenW);
 
             SECUR32_CreateNTLMv1SessionKey((PBYTE)unicode_password,
                                            passwd_lenW * sizeof(SEC_WCHAR), helper->session_key);
@@ -560,7 +649,7 @@
 
         /* If no password is given, try to use cached credentials. Fall back to an empty
          * password if this failed. */
-        if(ntlm_cred->password == NULL)
+        if(!password && !ntlm_cred->password)
         {
             lstrcpynA(buffer, "OK", max_len-1);
             if((ret = run_helper(helper, buffer, max_len, &buffer_len)) != SEC_E_OK)
@@ -581,8 +670,8 @@
         else
         {
             lstrcpynA(buffer, "PW ", max_len-1);
-            if((ret = encodeBase64((unsigned char*)ntlm_cred->password,
-                        ntlm_cred->pwlen, buffer+3,
+            if((ret = encodeBase64(password ? (unsigned char *)password : (unsigned char *)ntlm_cred->password,
+                        password ? pwlen : ntlm_cred->pwlen, buffer+3,
                         max_len-3, &buffer_len)) != SEC_E_OK)
             {
                 cleanup_helper(helper);
@@ -836,6 +925,8 @@
 
 isc_end:
     HeapFree(GetProcessHeap(), 0, username);
+    HeapFree(GetProcessHeap(), 0, domain);
+    HeapFree(GetProcessHeap(), 0, password);
     HeapFree(GetProcessHeap(), 0, want_flags);
     HeapFree(GetProcessHeap(), 0, buffer);
     HeapFree(GetProcessHeap(), 0, bin);