xref: /reactos/dll/win32/credui/credui_main.c (revision 98ef8700)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * Credentials User Interface
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * Copyright 2006 Robert Shearman (for CodeWeavers)
5c2c66affSColin Finck  *
6c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
7c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
8c2c66affSColin Finck  * License as published by the Free Software Foundation; either
9c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
10c2c66affSColin Finck  *
11c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
12c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14c2c66affSColin Finck  * Lesser General Public License for more details.
15c2c66affSColin Finck  *
16c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
17c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
18c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19c2c66affSColin Finck  */
20c2c66affSColin Finck 
21c2c66affSColin Finck #include <stdarg.h>
22*98ef8700SAmine Khaldi #ifdef __REACTOS__
23*98ef8700SAmine Khaldi #include <wchar.h>
24*98ef8700SAmine Khaldi #endif
25c2c66affSColin Finck 
2698e90aa9SAmine Khaldi #include "windef.h"
2798e90aa9SAmine Khaldi #include "winbase.h"
2898e90aa9SAmine Khaldi #include "winnt.h"
2998e90aa9SAmine Khaldi #include "winuser.h"
3098e90aa9SAmine Khaldi #include "wincred.h"
3198e90aa9SAmine Khaldi #include "rpc.h"
3298e90aa9SAmine Khaldi #include "sspi.h"
3398e90aa9SAmine Khaldi #include "commctrl.h"
34c2c66affSColin Finck 
35c2c66affSColin Finck #include "credui_resources.h"
36c2c66affSColin Finck 
3798e90aa9SAmine Khaldi #include "wine/debug.h"
3898e90aa9SAmine Khaldi #include "wine/list.h"
39c2c66affSColin Finck 
40c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(credui);
41c2c66affSColin Finck 
42c2c66affSColin Finck #define TOOLID_INCORRECTPASSWORD    1
43c2c66affSColin Finck #define TOOLID_CAPSLOCKON           2
44c2c66affSColin Finck 
45c2c66affSColin Finck #define ID_CAPSLOCKPOP              1
46c2c66affSColin Finck 
47c2c66affSColin Finck struct pending_credentials
48c2c66affSColin Finck {
49c2c66affSColin Finck     struct list entry;
50c2c66affSColin Finck     PWSTR pszTargetName;
51c2c66affSColin Finck     PWSTR pszUsername;
52c2c66affSColin Finck     PWSTR pszPassword;
53c2c66affSColin Finck     BOOL generic;
54c2c66affSColin Finck };
55c2c66affSColin Finck 
56c2c66affSColin Finck static HINSTANCE hinstCredUI;
57c2c66affSColin Finck 
58c2c66affSColin Finck static struct list pending_credentials_list = LIST_INIT(pending_credentials_list);
59c2c66affSColin Finck 
60c2c66affSColin Finck static CRITICAL_SECTION csPendingCredentials;
61c2c66affSColin Finck static CRITICAL_SECTION_DEBUG critsect_debug =
62c2c66affSColin Finck {
63c2c66affSColin Finck     0, 0, &csPendingCredentials,
64c2c66affSColin Finck     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
65c2c66affSColin Finck     0, 0, { (DWORD_PTR)(__FILE__ ": csPendingCredentials") }
66c2c66affSColin Finck };
67c2c66affSColin Finck static CRITICAL_SECTION csPendingCredentials = { &critsect_debug, -1, 0, 0, 0, 0 };
68c2c66affSColin Finck 
69c2c66affSColin Finck 
DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)70c2c66affSColin Finck BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
71c2c66affSColin Finck {
72c2c66affSColin Finck     struct pending_credentials *entry, *cursor2;
73c2c66affSColin Finck     TRACE("(0x%p, %d, %p)\n",hinstDLL,fdwReason,lpvReserved);
74c2c66affSColin Finck 
75c2c66affSColin Finck     switch (fdwReason)
76c2c66affSColin Finck     {
77c2c66affSColin Finck     case DLL_WINE_PREATTACH:
78c2c66affSColin Finck         return FALSE;	/* prefer native version */
79c2c66affSColin Finck 
80c2c66affSColin Finck     case DLL_PROCESS_ATTACH:
81c2c66affSColin Finck         DisableThreadLibraryCalls(hinstDLL);
82c2c66affSColin Finck         hinstCredUI = hinstDLL;
83c2c66affSColin Finck         InitCommonControls();
84c2c66affSColin Finck         break;
85c2c66affSColin Finck 
86c2c66affSColin Finck     case DLL_PROCESS_DETACH:
87c2c66affSColin Finck         if (lpvReserved) break;
88c2c66affSColin Finck         LIST_FOR_EACH_ENTRY_SAFE(entry, cursor2, &pending_credentials_list, struct pending_credentials, entry)
89c2c66affSColin Finck         {
90c2c66affSColin Finck             list_remove(&entry->entry);
91c2c66affSColin Finck 
92c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, entry->pszTargetName);
93c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, entry->pszUsername);
94*98ef8700SAmine Khaldi             SecureZeroMemory(entry->pszPassword, lstrlenW(entry->pszPassword) * sizeof(WCHAR));
95c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, entry->pszPassword);
96c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, entry);
97c2c66affSColin Finck         }
98c2c66affSColin Finck         DeleteCriticalSection(&csPendingCredentials);
99c2c66affSColin Finck         break;
100c2c66affSColin Finck     }
101c2c66affSColin Finck 
102c2c66affSColin Finck     return TRUE;
103c2c66affSColin Finck }
104c2c66affSColin Finck 
save_credentials(PCWSTR pszTargetName,PCWSTR pszUsername,PCWSTR pszPassword,BOOL generic)105c2c66affSColin Finck static DWORD save_credentials(PCWSTR pszTargetName, PCWSTR pszUsername,
106c2c66affSColin Finck                               PCWSTR pszPassword, BOOL generic)
107c2c66affSColin Finck {
108c2c66affSColin Finck     CREDENTIALW cred;
109c2c66affSColin Finck 
110c2c66affSColin Finck     TRACE("saving servername %s with username %s\n", debugstr_w(pszTargetName), debugstr_w(pszUsername));
111c2c66affSColin Finck 
112c2c66affSColin Finck     cred.Flags = 0;
113c2c66affSColin Finck     cred.Type = generic ? CRED_TYPE_GENERIC : CRED_TYPE_DOMAIN_PASSWORD;
114c2c66affSColin Finck     cred.TargetName = (LPWSTR)pszTargetName;
115c2c66affSColin Finck     cred.Comment = NULL;
116*98ef8700SAmine Khaldi     cred.CredentialBlobSize = lstrlenW(pszPassword) * sizeof(WCHAR);
117c2c66affSColin Finck     cred.CredentialBlob = (LPBYTE)pszPassword;
118c2c66affSColin Finck     cred.Persist = CRED_PERSIST_ENTERPRISE;
119c2c66affSColin Finck     cred.AttributeCount = 0;
120c2c66affSColin Finck     cred.Attributes = NULL;
121c2c66affSColin Finck     cred.TargetAlias = NULL;
122c2c66affSColin Finck     cred.UserName = (LPWSTR)pszUsername;
123c2c66affSColin Finck 
124c2c66affSColin Finck     if (CredWriteW(&cred, 0))
125c2c66affSColin Finck         return ERROR_SUCCESS;
126c2c66affSColin Finck     else
127c2c66affSColin Finck     {
128c2c66affSColin Finck         DWORD ret = GetLastError();
129c2c66affSColin Finck         ERR("CredWriteW failed with error %d\n", ret);
130c2c66affSColin Finck         return ret;
131c2c66affSColin Finck     }
132c2c66affSColin Finck }
133c2c66affSColin Finck 
134c2c66affSColin Finck struct cred_dialog_params
135c2c66affSColin Finck {
136c2c66affSColin Finck     PCWSTR pszTargetName;
137c2c66affSColin Finck     PCWSTR pszMessageText;
138c2c66affSColin Finck     PCWSTR pszCaptionText;
139c2c66affSColin Finck     HBITMAP hbmBanner;
140c2c66affSColin Finck     PWSTR pszUsername;
141c2c66affSColin Finck     ULONG ulUsernameMaxChars;
142c2c66affSColin Finck     PWSTR pszPassword;
143c2c66affSColin Finck     ULONG ulPasswordMaxChars;
144c2c66affSColin Finck     BOOL fSave;
145c2c66affSColin Finck     DWORD dwFlags;
146c2c66affSColin Finck     HWND hwndBalloonTip;
147c2c66affSColin Finck     BOOL fBalloonTipActive;
148c2c66affSColin Finck };
149c2c66affSColin Finck 
CredDialogFillUsernameCombo(HWND hwndUsername,const struct cred_dialog_params * params)150c2c66affSColin Finck static void CredDialogFillUsernameCombo(HWND hwndUsername, const struct cred_dialog_params *params)
151c2c66affSColin Finck {
152c2c66affSColin Finck     DWORD count;
153c2c66affSColin Finck     DWORD i;
154c2c66affSColin Finck     PCREDENTIALW *credentials;
155c2c66affSColin Finck 
156c2c66affSColin Finck     if (!CredEnumerateW(NULL, 0, &count, &credentials))
157c2c66affSColin Finck         return;
158c2c66affSColin Finck 
159c2c66affSColin Finck     for (i = 0; i < count; i++)
160c2c66affSColin Finck     {
161c2c66affSColin Finck         COMBOBOXEXITEMW comboitem;
162c2c66affSColin Finck         DWORD j;
163c2c66affSColin Finck         BOOL duplicate = FALSE;
164c2c66affSColin Finck 
16587671158SAmine Khaldi         if (!credentials[i]->UserName)
16687671158SAmine Khaldi             continue;
16787671158SAmine Khaldi 
168c2c66affSColin Finck         if (params->dwFlags & CREDUI_FLAGS_GENERIC_CREDENTIALS)
169c2c66affSColin Finck         {
17087671158SAmine Khaldi             if (credentials[i]->Type != CRED_TYPE_GENERIC)
17187671158SAmine Khaldi             {
17287671158SAmine Khaldi                 credentials[i]->UserName = NULL;
173c2c66affSColin Finck                 continue;
174c2c66affSColin Finck             }
17587671158SAmine Khaldi         }
17687671158SAmine Khaldi         else if (credentials[i]->Type == CRED_TYPE_GENERIC)
177c2c66affSColin Finck         {
17887671158SAmine Khaldi             credentials[i]->UserName = NULL;
179c2c66affSColin Finck             continue;
180c2c66affSColin Finck         }
181c2c66affSColin Finck 
182c2c66affSColin Finck         /* don't add another item with the same name if we've already added it */
183c2c66affSColin Finck         for (j = 0; j < i; j++)
18487671158SAmine Khaldi             if (credentials[j]->UserName
185*98ef8700SAmine Khaldi                 && !lstrcmpW(credentials[i]->UserName, credentials[j]->UserName))
186c2c66affSColin Finck             {
187c2c66affSColin Finck                 duplicate = TRUE;
188c2c66affSColin Finck                 break;
189c2c66affSColin Finck             }
190c2c66affSColin Finck 
191c2c66affSColin Finck         if (duplicate)
192c2c66affSColin Finck             continue;
193c2c66affSColin Finck 
194c2c66affSColin Finck         comboitem.mask = CBEIF_TEXT;
195c2c66affSColin Finck         comboitem.iItem = -1;
196c2c66affSColin Finck         comboitem.pszText = credentials[i]->UserName;
197c2c66affSColin Finck         SendMessageW(hwndUsername, CBEM_INSERTITEMW, 0, (LPARAM)&comboitem);
198c2c66affSColin Finck     }
199c2c66affSColin Finck 
200c2c66affSColin Finck     CredFree(credentials);
201c2c66affSColin Finck }
202c2c66affSColin Finck 
CredDialogCreateBalloonTip(HWND hwndDlg,struct cred_dialog_params * params)203c2c66affSColin Finck static void CredDialogCreateBalloonTip(HWND hwndDlg, struct cred_dialog_params *params)
204c2c66affSColin Finck {
205c2c66affSColin Finck     TTTOOLINFOW toolinfo;
206c2c66affSColin Finck     WCHAR wszText[256];
207c2c66affSColin Finck 
208c2c66affSColin Finck     if (params->hwndBalloonTip)
209c2c66affSColin Finck         return;
210c2c66affSColin Finck 
211c2c66affSColin Finck     params->hwndBalloonTip = CreateWindowExW(WS_EX_TOOLWINDOW, TOOLTIPS_CLASSW,
212c2c66affSColin Finck         NULL, WS_POPUP | TTS_NOPREFIX | TTS_BALLOON, CW_USEDEFAULT,
213c2c66affSColin Finck         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL,
214c2c66affSColin Finck         hinstCredUI, NULL);
215c2c66affSColin Finck     SetWindowPos(params->hwndBalloonTip, HWND_TOPMOST, 0, 0, 0, 0,
216c2c66affSColin Finck                  SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
217c2c66affSColin Finck 
21840934404SAmine Khaldi     if (!LoadStringW(hinstCredUI, IDS_INCORRECTPASSWORD, wszText, ARRAY_SIZE(wszText)))
219c2c66affSColin Finck     {
220c2c66affSColin Finck         ERR("failed to load IDS_INCORRECTPASSWORD\n");
221c2c66affSColin Finck         return;
222c2c66affSColin Finck     }
223c2c66affSColin Finck 
224c2c66affSColin Finck     toolinfo.cbSize = sizeof(toolinfo);
225c2c66affSColin Finck     toolinfo.uFlags = TTF_TRACK;
226c2c66affSColin Finck     toolinfo.hwnd = hwndDlg;
227c2c66affSColin Finck     toolinfo.uId = TOOLID_INCORRECTPASSWORD;
228c2c66affSColin Finck     SetRectEmpty(&toolinfo.rect);
229c2c66affSColin Finck     toolinfo.hinst = NULL;
230c2c66affSColin Finck     toolinfo.lpszText = wszText;
231c2c66affSColin Finck     toolinfo.lParam = 0;
232c2c66affSColin Finck     toolinfo.lpReserved = NULL;
233c2c66affSColin Finck     SendMessageW(params->hwndBalloonTip, TTM_ADDTOOLW, 0, (LPARAM)&toolinfo);
234c2c66affSColin Finck 
23540934404SAmine Khaldi     if (!LoadStringW(hinstCredUI, IDS_CAPSLOCKON, wszText, ARRAY_SIZE(wszText)))
236c2c66affSColin Finck     {
237c2c66affSColin Finck         ERR("failed to load IDS_CAPSLOCKON\n");
238c2c66affSColin Finck         return;
239c2c66affSColin Finck     }
240c2c66affSColin Finck 
241c2c66affSColin Finck     toolinfo.uId = TOOLID_CAPSLOCKON;
242c2c66affSColin Finck     SendMessageW(params->hwndBalloonTip, TTM_ADDTOOLW, 0, (LPARAM)&toolinfo);
243c2c66affSColin Finck }
244c2c66affSColin Finck 
CredDialogShowIncorrectPasswordBalloon(HWND hwndDlg,struct cred_dialog_params * params)245c2c66affSColin Finck static void CredDialogShowIncorrectPasswordBalloon(HWND hwndDlg, struct cred_dialog_params *params)
246c2c66affSColin Finck {
247c2c66affSColin Finck     TTTOOLINFOW toolinfo;
248c2c66affSColin Finck     RECT rcPassword;
249c2c66affSColin Finck     INT x;
250c2c66affSColin Finck     INT y;
251c2c66affSColin Finck     WCHAR wszTitle[256];
252c2c66affSColin Finck 
253c2c66affSColin Finck     /* user name likely wrong so balloon would be confusing. focus is also
254c2c66affSColin Finck      * not set to the password edit box, so more notification would need to be
255c2c66affSColin Finck      * handled */
256c2c66affSColin Finck     if (!params->pszUsername[0])
257c2c66affSColin Finck         return;
258c2c66affSColin Finck 
259c2c66affSColin Finck     /* don't show two balloon tips at once */
260c2c66affSColin Finck     if (params->fBalloonTipActive)
261c2c66affSColin Finck         return;
262c2c66affSColin Finck 
26340934404SAmine Khaldi     if (!LoadStringW(hinstCredUI, IDS_INCORRECTPASSWORDTITLE, wszTitle, ARRAY_SIZE(wszTitle)))
264c2c66affSColin Finck     {
265c2c66affSColin Finck         ERR("failed to load IDS_INCORRECTPASSWORDTITLE\n");
266c2c66affSColin Finck         return;
267c2c66affSColin Finck     }
268c2c66affSColin Finck 
269c2c66affSColin Finck     CredDialogCreateBalloonTip(hwndDlg, params);
270c2c66affSColin Finck 
271c2c66affSColin Finck     memset(&toolinfo, 0, sizeof(toolinfo));
272c2c66affSColin Finck     toolinfo.cbSize = sizeof(toolinfo);
273c2c66affSColin Finck     toolinfo.hwnd = hwndDlg;
274c2c66affSColin Finck     toolinfo.uId = TOOLID_INCORRECTPASSWORD;
275c2c66affSColin Finck 
276c2c66affSColin Finck     SendMessageW(params->hwndBalloonTip, TTM_SETTITLEW, TTI_ERROR, (LPARAM)wszTitle);
277c2c66affSColin Finck 
278c2c66affSColin Finck     GetWindowRect(GetDlgItem(hwndDlg, IDC_PASSWORD), &rcPassword);
279c2c66affSColin Finck     /* centered vertically and in the right side of the password edit control */
280c2c66affSColin Finck     x = rcPassword.right - 12;
281c2c66affSColin Finck     y = (rcPassword.top + rcPassword.bottom) / 2;
282c2c66affSColin Finck     SendMessageW(params->hwndBalloonTip, TTM_TRACKPOSITION, 0, MAKELONG(x, y));
283c2c66affSColin Finck 
284c2c66affSColin Finck     SendMessageW(params->hwndBalloonTip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&toolinfo);
285c2c66affSColin Finck 
286c2c66affSColin Finck     params->fBalloonTipActive = TRUE;
287c2c66affSColin Finck }
288c2c66affSColin Finck 
CredDialogShowCapsLockBalloon(HWND hwndDlg,struct cred_dialog_params * params)289c2c66affSColin Finck static void CredDialogShowCapsLockBalloon(HWND hwndDlg, struct cred_dialog_params *params)
290c2c66affSColin Finck {
291c2c66affSColin Finck     TTTOOLINFOW toolinfo;
292c2c66affSColin Finck     RECT rcPassword;
293c2c66affSColin Finck     INT x;
294c2c66affSColin Finck     INT y;
295c2c66affSColin Finck     WCHAR wszTitle[256];
296c2c66affSColin Finck 
297c2c66affSColin Finck     /* don't show two balloon tips at once */
298c2c66affSColin Finck     if (params->fBalloonTipActive)
299c2c66affSColin Finck         return;
300c2c66affSColin Finck 
30140934404SAmine Khaldi     if (!LoadStringW(hinstCredUI, IDS_CAPSLOCKONTITLE, wszTitle, ARRAY_SIZE(wszTitle)))
302c2c66affSColin Finck     {
303c2c66affSColin Finck         ERR("failed to load IDS_IDSCAPSLOCKONTITLE\n");
304c2c66affSColin Finck         return;
305c2c66affSColin Finck     }
306c2c66affSColin Finck 
307c2c66affSColin Finck     CredDialogCreateBalloonTip(hwndDlg, params);
308c2c66affSColin Finck 
309c2c66affSColin Finck     memset(&toolinfo, 0, sizeof(toolinfo));
310c2c66affSColin Finck     toolinfo.cbSize = sizeof(toolinfo);
311c2c66affSColin Finck     toolinfo.hwnd = hwndDlg;
312c2c66affSColin Finck     toolinfo.uId = TOOLID_CAPSLOCKON;
313c2c66affSColin Finck 
314c2c66affSColin Finck     SendMessageW(params->hwndBalloonTip, TTM_SETTITLEW, TTI_WARNING, (LPARAM)wszTitle);
315c2c66affSColin Finck 
316c2c66affSColin Finck     GetWindowRect(GetDlgItem(hwndDlg, IDC_PASSWORD), &rcPassword);
317c2c66affSColin Finck     /* just inside the left side of the password edit control */
318c2c66affSColin Finck     x = rcPassword.left + 12;
319c2c66affSColin Finck     y = rcPassword.bottom - 3;
320c2c66affSColin Finck     SendMessageW(params->hwndBalloonTip, TTM_TRACKPOSITION, 0, MAKELONG(x, y));
321c2c66affSColin Finck 
322c2c66affSColin Finck     SendMessageW(params->hwndBalloonTip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&toolinfo);
323c2c66affSColin Finck 
324c2c66affSColin Finck     SetTimer(hwndDlg, ID_CAPSLOCKPOP,
325c2c66affSColin Finck              SendMessageW(params->hwndBalloonTip, TTM_GETDELAYTIME, TTDT_AUTOPOP, 0),
326c2c66affSColin Finck              NULL);
327c2c66affSColin Finck 
328c2c66affSColin Finck     params->fBalloonTipActive = TRUE;
329c2c66affSColin Finck }
330c2c66affSColin Finck 
CredDialogHideBalloonTip(HWND hwndDlg,struct cred_dialog_params * params)331c2c66affSColin Finck static void CredDialogHideBalloonTip(HWND hwndDlg, struct cred_dialog_params *params)
332c2c66affSColin Finck {
333c2c66affSColin Finck     TTTOOLINFOW toolinfo;
334c2c66affSColin Finck 
335c2c66affSColin Finck     if (!params->hwndBalloonTip)
336c2c66affSColin Finck         return;
337c2c66affSColin Finck 
338c2c66affSColin Finck     memset(&toolinfo, 0, sizeof(toolinfo));
339c2c66affSColin Finck 
340c2c66affSColin Finck     toolinfo.cbSize = sizeof(toolinfo);
341c2c66affSColin Finck     toolinfo.hwnd = hwndDlg;
342c2c66affSColin Finck     toolinfo.uId = 0;
343c2c66affSColin Finck     SendMessageW(params->hwndBalloonTip, TTM_TRACKACTIVATE, FALSE, (LPARAM)&toolinfo);
344c2c66affSColin Finck     toolinfo.uId = 1;
345c2c66affSColin Finck     SendMessageW(params->hwndBalloonTip, TTM_TRACKACTIVATE, FALSE, (LPARAM)&toolinfo);
346c2c66affSColin Finck 
347c2c66affSColin Finck     params->fBalloonTipActive = FALSE;
348c2c66affSColin Finck }
349c2c66affSColin Finck 
CredDialogCapsLockOn(void)350c2c66affSColin Finck static inline BOOL CredDialogCapsLockOn(void)
351c2c66affSColin Finck {
352c2c66affSColin Finck     return (GetKeyState(VK_CAPITAL) & 0x1) != 0;
353c2c66affSColin Finck }
354c2c66affSColin Finck 
CredDialogPasswordSubclassProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam,UINT_PTR uIdSubclass,DWORD_PTR dwRefData)355c2c66affSColin Finck static LRESULT CALLBACK CredDialogPasswordSubclassProc(HWND hwnd, UINT uMsg,
356c2c66affSColin Finck     WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
357c2c66affSColin Finck {
358c2c66affSColin Finck     struct cred_dialog_params *params = (struct cred_dialog_params *)dwRefData;
359c2c66affSColin Finck     switch (uMsg)
360c2c66affSColin Finck     {
361c2c66affSColin Finck     case WM_KEYDOWN:
362c2c66affSColin Finck         if (wParam == VK_CAPITAL)
363c2c66affSColin Finck         {
364c2c66affSColin Finck             HWND hwndDlg = GetParent(hwnd);
365c2c66affSColin Finck             if (CredDialogCapsLockOn())
366c2c66affSColin Finck                 CredDialogShowCapsLockBalloon(hwndDlg, params);
367c2c66affSColin Finck             else
368c2c66affSColin Finck                 CredDialogHideBalloonTip(hwndDlg, params);
369c2c66affSColin Finck         }
370c2c66affSColin Finck         break;
371c2c66affSColin Finck     case WM_DESTROY:
372c2c66affSColin Finck         RemoveWindowSubclass(hwnd, CredDialogPasswordSubclassProc, uIdSubclass);
373c2c66affSColin Finck         break;
374c2c66affSColin Finck     }
375c2c66affSColin Finck     return DefSubclassProc(hwnd, uMsg, wParam, lParam);
376c2c66affSColin Finck }
377c2c66affSColin Finck 
CredDialogInit(HWND hwndDlg,struct cred_dialog_params * params)378c2c66affSColin Finck static BOOL CredDialogInit(HWND hwndDlg, struct cred_dialog_params *params)
379c2c66affSColin Finck {
380c2c66affSColin Finck     HWND hwndUsername = GetDlgItem(hwndDlg, IDC_USERNAME);
381c2c66affSColin Finck     HWND hwndPassword = GetDlgItem(hwndDlg, IDC_PASSWORD);
382c2c66affSColin Finck 
383c2c66affSColin Finck     SetWindowLongPtrW(hwndDlg, DWLP_USER, (LONG_PTR)params);
384c2c66affSColin Finck 
385c2c66affSColin Finck     if (params->hbmBanner)
386c2c66affSColin Finck         SendMessageW(GetDlgItem(hwndDlg, IDB_BANNER), STM_SETIMAGE,
387c2c66affSColin Finck                      IMAGE_BITMAP, (LPARAM)params->hbmBanner);
388c2c66affSColin Finck 
389c2c66affSColin Finck     if (params->pszMessageText)
390c2c66affSColin Finck         SetDlgItemTextW(hwndDlg, IDC_MESSAGE, params->pszMessageText);
391c2c66affSColin Finck     else
392c2c66affSColin Finck     {
393c2c66affSColin Finck         WCHAR format[256];
394c2c66affSColin Finck         WCHAR message[256];
39540934404SAmine Khaldi         LoadStringW(hinstCredUI, IDS_MESSAGEFORMAT, format, ARRAY_SIZE(format));
396*98ef8700SAmine Khaldi         swprintf(message, format, params->pszTargetName);
397c2c66affSColin Finck         SetDlgItemTextW(hwndDlg, IDC_MESSAGE, message);
398c2c66affSColin Finck     }
399c2c66affSColin Finck     SetWindowTextW(hwndUsername, params->pszUsername);
400c2c66affSColin Finck     SetWindowTextW(hwndPassword, params->pszPassword);
401c2c66affSColin Finck 
402c2c66affSColin Finck     CredDialogFillUsernameCombo(hwndUsername, params);
403c2c66affSColin Finck 
404c2c66affSColin Finck     if (params->pszUsername[0])
405c2c66affSColin Finck     {
406c2c66affSColin Finck         /* prevent showing a balloon tip here */
407c2c66affSColin Finck         params->fBalloonTipActive = TRUE;
408c2c66affSColin Finck         SetFocus(hwndPassword);
409c2c66affSColin Finck         params->fBalloonTipActive = FALSE;
410c2c66affSColin Finck     }
411c2c66affSColin Finck     else
412c2c66affSColin Finck         SetFocus(hwndUsername);
413c2c66affSColin Finck 
414c2c66affSColin Finck     if (params->pszCaptionText)
415c2c66affSColin Finck         SetWindowTextW(hwndDlg, params->pszCaptionText);
416c2c66affSColin Finck     else
417c2c66affSColin Finck     {
418c2c66affSColin Finck         WCHAR format[256];
419c2c66affSColin Finck         WCHAR title[256];
42040934404SAmine Khaldi         LoadStringW(hinstCredUI, IDS_TITLEFORMAT, format, ARRAY_SIZE(format));
421*98ef8700SAmine Khaldi         swprintf(title, format, params->pszTargetName);
422c2c66affSColin Finck         SetWindowTextW(hwndDlg, title);
423c2c66affSColin Finck     }
424c2c66affSColin Finck 
425c2c66affSColin Finck     if (params->dwFlags & CREDUI_FLAGS_PERSIST ||
426c2c66affSColin Finck         (params->dwFlags & CREDUI_FLAGS_DO_NOT_PERSIST &&
427c2c66affSColin Finck          !(params->dwFlags & CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX)))
428c2c66affSColin Finck         ShowWindow(GetDlgItem(hwndDlg, IDC_SAVE), SW_HIDE);
429c2c66affSColin Finck     else if (params->fSave)
430c2c66affSColin Finck         CheckDlgButton(hwndDlg, IDC_SAVE, BST_CHECKED);
431c2c66affSColin Finck 
432c2c66affSColin Finck     /* setup subclassing for Caps Lock detection */
433c2c66affSColin Finck     SetWindowSubclass(hwndPassword, CredDialogPasswordSubclassProc, 1, (DWORD_PTR)params);
434c2c66affSColin Finck 
435c2c66affSColin Finck     if (params->dwFlags & CREDUI_FLAGS_INCORRECT_PASSWORD)
436c2c66affSColin Finck         CredDialogShowIncorrectPasswordBalloon(hwndDlg, params);
437c2c66affSColin Finck     else if ((GetFocus() == hwndPassword) && CredDialogCapsLockOn())
438c2c66affSColin Finck         CredDialogShowCapsLockBalloon(hwndDlg, params);
439c2c66affSColin Finck 
440c2c66affSColin Finck     return FALSE;
441c2c66affSColin Finck }
442c2c66affSColin Finck 
CredDialogCommandOk(HWND hwndDlg,struct cred_dialog_params * params)443c2c66affSColin Finck static void CredDialogCommandOk(HWND hwndDlg, struct cred_dialog_params *params)
444c2c66affSColin Finck {
445c2c66affSColin Finck     HWND hwndUsername = GetDlgItem(hwndDlg, IDC_USERNAME);
446c2c66affSColin Finck     LPWSTR user;
447c2c66affSColin Finck     INT len;
448c2c66affSColin Finck     INT len2;
449c2c66affSColin Finck 
450c2c66affSColin Finck     len = GetWindowTextLengthW(hwndUsername);
451c2c66affSColin Finck     user = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
452c2c66affSColin Finck     GetWindowTextW(hwndUsername, user, len + 1);
453c2c66affSColin Finck 
454c2c66affSColin Finck     if (!user[0])
455c2c66affSColin Finck     {
456c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, user);
457c2c66affSColin Finck         return;
458c2c66affSColin Finck     }
459c2c66affSColin Finck 
460*98ef8700SAmine Khaldi     if (!wcschr(user, '\\') && !wcschr(user, '@'))
461c2c66affSColin Finck     {
462*98ef8700SAmine Khaldi         ULONG len_target = lstrlenW(params->pszTargetName);
463c2c66affSColin Finck         memcpy(params->pszUsername, params->pszTargetName,
464c2c66affSColin Finck                min(len_target, params->ulUsernameMaxChars) * sizeof(WCHAR));
465c2c66affSColin Finck         if (len_target + 1 < params->ulUsernameMaxChars)
466c2c66affSColin Finck             params->pszUsername[len_target] = '\\';
467c2c66affSColin Finck         if (len_target + 2 < params->ulUsernameMaxChars)
468c2c66affSColin Finck             params->pszUsername[len_target + 1] = '\0';
469c2c66affSColin Finck     }
470c2c66affSColin Finck     else if (params->ulUsernameMaxChars > 0)
471c2c66affSColin Finck         params->pszUsername[0] = '\0';
472c2c66affSColin Finck 
473*98ef8700SAmine Khaldi     len2 = lstrlenW(params->pszUsername);
474c2c66affSColin Finck     memcpy(params->pszUsername + len2, user, min(len, params->ulUsernameMaxChars - len2) * sizeof(WCHAR));
475c2c66affSColin Finck     if (params->ulUsernameMaxChars)
476c2c66affSColin Finck         params->pszUsername[len2 + min(len, params->ulUsernameMaxChars - len2 - 1)] = '\0';
477c2c66affSColin Finck 
478c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, user);
479c2c66affSColin Finck 
480c2c66affSColin Finck     GetDlgItemTextW(hwndDlg, IDC_PASSWORD, params->pszPassword,
481c2c66affSColin Finck                     params->ulPasswordMaxChars);
482c2c66affSColin Finck 
483c2c66affSColin Finck     params->fSave = IsDlgButtonChecked(hwndDlg, IDC_SAVE) == BST_CHECKED;
484c2c66affSColin Finck 
485c2c66affSColin Finck     EndDialog(hwndDlg, IDOK);
486c2c66affSColin Finck }
487c2c66affSColin Finck 
CredDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)488c2c66affSColin Finck static INT_PTR CALLBACK CredDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
489c2c66affSColin Finck                                        LPARAM lParam)
490c2c66affSColin Finck {
491c2c66affSColin Finck     switch (uMsg)
492c2c66affSColin Finck     {
493c2c66affSColin Finck         case WM_INITDIALOG:
494c2c66affSColin Finck         {
495c2c66affSColin Finck             struct cred_dialog_params *params = (struct cred_dialog_params *)lParam;
496c2c66affSColin Finck 
497c2c66affSColin Finck             return CredDialogInit(hwndDlg, params);
498c2c66affSColin Finck         }
499c2c66affSColin Finck         case WM_COMMAND:
500c2c66affSColin Finck             switch (wParam)
501c2c66affSColin Finck             {
502c2c66affSColin Finck                 case MAKELONG(IDOK, BN_CLICKED):
503c2c66affSColin Finck                 {
504c2c66affSColin Finck                     struct cred_dialog_params *params =
505c2c66affSColin Finck                         (struct cred_dialog_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
506c2c66affSColin Finck                     CredDialogCommandOk(hwndDlg, params);
507c2c66affSColin Finck                     return TRUE;
508c2c66affSColin Finck                 }
509c2c66affSColin Finck                 case MAKELONG(IDCANCEL, BN_CLICKED):
510c2c66affSColin Finck                     EndDialog(hwndDlg, IDCANCEL);
511c2c66affSColin Finck                     return TRUE;
512c2c66affSColin Finck                 case MAKELONG(IDC_PASSWORD, EN_SETFOCUS):
513c2c66affSColin Finck                     if (CredDialogCapsLockOn())
514c2c66affSColin Finck                     {
515c2c66affSColin Finck                         struct cred_dialog_params *params =
516c2c66affSColin Finck                             (struct cred_dialog_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
517c2c66affSColin Finck                         CredDialogShowCapsLockBalloon(hwndDlg, params);
518c2c66affSColin Finck                     }
519c2c66affSColin Finck                     /* don't allow another window to steal focus while the
520c2c66affSColin Finck                      * user is typing their password */
521c2c66affSColin Finck                     LockSetForegroundWindow(LSFW_LOCK);
522c2c66affSColin Finck                     return TRUE;
523c2c66affSColin Finck                 case MAKELONG(IDC_PASSWORD, EN_KILLFOCUS):
524c2c66affSColin Finck                 {
525c2c66affSColin Finck                     struct cred_dialog_params *params =
526c2c66affSColin Finck                         (struct cred_dialog_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
527c2c66affSColin Finck                     /* the user is no longer typing their password, so allow
528c2c66affSColin Finck                      * other windows to become foreground ones */
529c2c66affSColin Finck                     LockSetForegroundWindow(LSFW_UNLOCK);
530c2c66affSColin Finck                     CredDialogHideBalloonTip(hwndDlg, params);
531c2c66affSColin Finck                     return TRUE;
532c2c66affSColin Finck                 }
533c2c66affSColin Finck                 case MAKELONG(IDC_PASSWORD, EN_CHANGE):
534c2c66affSColin Finck                 {
535c2c66affSColin Finck                     struct cred_dialog_params *params =
536c2c66affSColin Finck                         (struct cred_dialog_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
537c2c66affSColin Finck                     CredDialogHideBalloonTip(hwndDlg, params);
538c2c66affSColin Finck                     return TRUE;
539c2c66affSColin Finck                 }
540c2c66affSColin Finck             }
541c2c66affSColin Finck             return FALSE;
542c2c66affSColin Finck         case WM_TIMER:
543c2c66affSColin Finck             if (wParam == ID_CAPSLOCKPOP)
544c2c66affSColin Finck             {
545c2c66affSColin Finck                 struct cred_dialog_params *params =
546c2c66affSColin Finck                     (struct cred_dialog_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
547c2c66affSColin Finck                 CredDialogHideBalloonTip(hwndDlg, params);
548c2c66affSColin Finck                 return TRUE;
549c2c66affSColin Finck             }
550c2c66affSColin Finck             return FALSE;
551c2c66affSColin Finck         case WM_DESTROY:
552c2c66affSColin Finck         {
553c2c66affSColin Finck             struct cred_dialog_params *params =
554c2c66affSColin Finck                 (struct cred_dialog_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
555c2c66affSColin Finck             if (params->hwndBalloonTip) DestroyWindow(params->hwndBalloonTip);
556c2c66affSColin Finck             return TRUE;
557c2c66affSColin Finck         }
558c2c66affSColin Finck         default:
559c2c66affSColin Finck             return FALSE;
560c2c66affSColin Finck     }
561c2c66affSColin Finck }
562c2c66affSColin Finck 
find_existing_credential(const WCHAR * target,WCHAR * username,ULONG len_username,WCHAR * password,ULONG len_password)563c2c66affSColin Finck static BOOL find_existing_credential(const WCHAR *target, WCHAR *username, ULONG len_username,
564c2c66affSColin Finck                                      WCHAR *password, ULONG len_password)
565c2c66affSColin Finck {
566c2c66affSColin Finck     DWORD count, i;
567c2c66affSColin Finck     CREDENTIALW **credentials;
568c2c66affSColin Finck 
569c2c66affSColin Finck     if (!CredEnumerateW(target, 0, &count, &credentials)) return FALSE;
570c2c66affSColin Finck     for (i = 0; i < count; i++)
571c2c66affSColin Finck     {
572c2c66affSColin Finck         if (credentials[i]->Type != CRED_TYPE_DOMAIN_PASSWORD &&
573c2c66affSColin Finck             credentials[i]->Type != CRED_TYPE_GENERIC)
574c2c66affSColin Finck         {
575c2c66affSColin Finck             FIXME("no support for type %u credentials\n", credentials[i]->Type);
576c2c66affSColin Finck             continue;
577c2c66affSColin Finck         }
578*98ef8700SAmine Khaldi         if ((!*username || !lstrcmpW(username, credentials[i]->UserName)) &&
579*98ef8700SAmine Khaldi             lstrlenW(credentials[i]->UserName) < len_username &&
580c2c66affSColin Finck             credentials[i]->CredentialBlobSize / sizeof(WCHAR) < len_password)
581c2c66affSColin Finck         {
582c2c66affSColin Finck             TRACE("found existing credential for %s\n", debugstr_w(credentials[i]->UserName));
583c2c66affSColin Finck 
584*98ef8700SAmine Khaldi             lstrcpyW(username, credentials[i]->UserName);
585c2c66affSColin Finck             memcpy(password, credentials[i]->CredentialBlob, credentials[i]->CredentialBlobSize);
586c2c66affSColin Finck             password[credentials[i]->CredentialBlobSize / sizeof(WCHAR)] = 0;
587c2c66affSColin Finck 
588c2c66affSColin Finck             CredFree(credentials);
589c2c66affSColin Finck             return TRUE;
590c2c66affSColin Finck         }
591c2c66affSColin Finck     }
592c2c66affSColin Finck     CredFree(credentials);
593c2c66affSColin Finck     return FALSE;
594c2c66affSColin Finck }
595c2c66affSColin Finck 
596c2c66affSColin Finck /******************************************************************************
597c2c66affSColin Finck  *           CredUIPromptForCredentialsW [CREDUI.@]
598c2c66affSColin Finck  */
CredUIPromptForCredentialsW(PCREDUI_INFOW pUIInfo,PCWSTR pszTargetName,PCtxtHandle Reserved,DWORD dwAuthError,PWSTR pszUsername,ULONG ulUsernameMaxChars,PWSTR pszPassword,ULONG ulPasswordMaxChars,PBOOL pfSave,DWORD dwFlags)599c2c66affSColin Finck DWORD WINAPI CredUIPromptForCredentialsW(PCREDUI_INFOW pUIInfo,
600c2c66affSColin Finck                                          PCWSTR pszTargetName,
601c2c66affSColin Finck                                          PCtxtHandle Reserved,
602c2c66affSColin Finck                                          DWORD dwAuthError,
603c2c66affSColin Finck                                          PWSTR pszUsername,
604c2c66affSColin Finck                                          ULONG ulUsernameMaxChars,
605c2c66affSColin Finck                                          PWSTR pszPassword,
606c2c66affSColin Finck                                          ULONG ulPasswordMaxChars, PBOOL pfSave,
607c2c66affSColin Finck                                          DWORD dwFlags)
608c2c66affSColin Finck {
609c2c66affSColin Finck     INT_PTR ret;
610c2c66affSColin Finck     struct cred_dialog_params params;
611c2c66affSColin Finck     DWORD result = ERROR_SUCCESS;
612c2c66affSColin Finck 
613c2c66affSColin Finck     TRACE("(%p, %s, %p, %d, %s, %d, %p, %d, %p, 0x%08x)\n", pUIInfo,
614c2c66affSColin Finck           debugstr_w(pszTargetName), Reserved, dwAuthError, debugstr_w(pszUsername),
615c2c66affSColin Finck           ulUsernameMaxChars, pszPassword, ulPasswordMaxChars, pfSave, dwFlags);
616c2c66affSColin Finck 
617c2c66affSColin Finck     if ((dwFlags & (CREDUI_FLAGS_ALWAYS_SHOW_UI|CREDUI_FLAGS_GENERIC_CREDENTIALS)) == CREDUI_FLAGS_ALWAYS_SHOW_UI)
618c2c66affSColin Finck         return ERROR_INVALID_FLAGS;
619c2c66affSColin Finck 
620c2c66affSColin Finck     if (!pszTargetName)
621c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
622c2c66affSColin Finck 
623c2c66affSColin Finck     if ((dwFlags & CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX) && !pfSave)
624c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
625c2c66affSColin Finck 
626c2c66affSColin Finck     if (!(dwFlags & CREDUI_FLAGS_ALWAYS_SHOW_UI) &&
627c2c66affSColin Finck         !(dwFlags & CREDUI_FLAGS_INCORRECT_PASSWORD) &&
628c2c66affSColin Finck         find_existing_credential(pszTargetName, pszUsername, ulUsernameMaxChars, pszPassword, ulPasswordMaxChars))
629c2c66affSColin Finck         return ERROR_SUCCESS;
630c2c66affSColin Finck 
631c2c66affSColin Finck     params.pszTargetName = pszTargetName;
632c2c66affSColin Finck     if (pUIInfo)
633c2c66affSColin Finck     {
634c2c66affSColin Finck         params.pszMessageText = pUIInfo->pszMessageText;
635c2c66affSColin Finck         params.pszCaptionText = pUIInfo->pszCaptionText;
636c2c66affSColin Finck         params.hbmBanner  = pUIInfo->hbmBanner;
637c2c66affSColin Finck     }
638c2c66affSColin Finck     else
639c2c66affSColin Finck     {
640c2c66affSColin Finck         params.pszMessageText = NULL;
641c2c66affSColin Finck         params.pszCaptionText = NULL;
642c2c66affSColin Finck         params.hbmBanner = NULL;
643c2c66affSColin Finck     }
644c2c66affSColin Finck     params.pszUsername = pszUsername;
645c2c66affSColin Finck     params.ulUsernameMaxChars = ulUsernameMaxChars;
646c2c66affSColin Finck     params.pszPassword = pszPassword;
647c2c66affSColin Finck     params.ulPasswordMaxChars = ulPasswordMaxChars;
648c2c66affSColin Finck     params.fSave = pfSave ? *pfSave : FALSE;
649c2c66affSColin Finck     params.dwFlags = dwFlags;
650c2c66affSColin Finck     params.hwndBalloonTip = NULL;
651c2c66affSColin Finck     params.fBalloonTipActive = FALSE;
652c2c66affSColin Finck 
653c2c66affSColin Finck     ret = DialogBoxParamW(hinstCredUI, MAKEINTRESOURCEW(IDD_CREDDIALOG),
654c2c66affSColin Finck                           pUIInfo ? pUIInfo->hwndParent : NULL,
655c2c66affSColin Finck                           CredDialogProc, (LPARAM)&params);
656c2c66affSColin Finck     if (ret <= 0)
657c2c66affSColin Finck         return GetLastError();
658c2c66affSColin Finck 
659c2c66affSColin Finck     if (ret == IDCANCEL)
660c2c66affSColin Finck     {
661c2c66affSColin Finck         TRACE("dialog cancelled\n");
662c2c66affSColin Finck         return ERROR_CANCELLED;
663c2c66affSColin Finck     }
664c2c66affSColin Finck 
665c2c66affSColin Finck     if (pfSave)
666c2c66affSColin Finck         *pfSave = params.fSave;
667c2c66affSColin Finck 
668c2c66affSColin Finck     if (params.fSave)
669c2c66affSColin Finck     {
670c2c66affSColin Finck         if (dwFlags & CREDUI_FLAGS_EXPECT_CONFIRMATION)
671c2c66affSColin Finck         {
672c2c66affSColin Finck             BOOL found = FALSE;
673c2c66affSColin Finck             struct pending_credentials *entry;
674c2c66affSColin Finck             int len;
675c2c66affSColin Finck 
676c2c66affSColin Finck             EnterCriticalSection(&csPendingCredentials);
677c2c66affSColin Finck 
678c2c66affSColin Finck             /* find existing pending credentials for the same target and overwrite */
679c2c66affSColin Finck             /* FIXME: is this correct? */
680c2c66affSColin Finck             LIST_FOR_EACH_ENTRY(entry, &pending_credentials_list, struct pending_credentials, entry)
681*98ef8700SAmine Khaldi                 if (!lstrcmpW(pszTargetName, entry->pszTargetName))
682c2c66affSColin Finck                 {
683c2c66affSColin Finck                     found = TRUE;
684c2c66affSColin Finck                     HeapFree(GetProcessHeap(), 0, entry->pszUsername);
685*98ef8700SAmine Khaldi                     SecureZeroMemory(entry->pszPassword, lstrlenW(entry->pszPassword) * sizeof(WCHAR));
686c2c66affSColin Finck                     HeapFree(GetProcessHeap(), 0, entry->pszPassword);
687c2c66affSColin Finck                 }
688c2c66affSColin Finck 
689c2c66affSColin Finck             if (!found)
690c2c66affSColin Finck             {
691c2c66affSColin Finck                 entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
692*98ef8700SAmine Khaldi                 len = lstrlenW(pszTargetName);
693c2c66affSColin Finck                 entry->pszTargetName = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
694c2c66affSColin Finck                 memcpy(entry->pszTargetName, pszTargetName, (len + 1)*sizeof(WCHAR));
695c2c66affSColin Finck                 list_add_tail(&pending_credentials_list, &entry->entry);
696c2c66affSColin Finck             }
697c2c66affSColin Finck 
698*98ef8700SAmine Khaldi             len = lstrlenW(params.pszUsername);
699c2c66affSColin Finck             entry->pszUsername = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
700c2c66affSColin Finck             memcpy(entry->pszUsername, params.pszUsername, (len + 1)*sizeof(WCHAR));
701*98ef8700SAmine Khaldi             len = lstrlenW(params.pszPassword);
702c2c66affSColin Finck             entry->pszPassword = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
703c2c66affSColin Finck             memcpy(entry->pszPassword, params.pszPassword, (len + 1)*sizeof(WCHAR));
704c2c66affSColin Finck             entry->generic = (dwFlags & CREDUI_FLAGS_GENERIC_CREDENTIALS) != 0;
705c2c66affSColin Finck 
706c2c66affSColin Finck             LeaveCriticalSection(&csPendingCredentials);
707c2c66affSColin Finck         }
708c2c66affSColin Finck         else if (!(dwFlags & CREDUI_FLAGS_DO_NOT_PERSIST))
709c2c66affSColin Finck             result = save_credentials(pszTargetName, pszUsername, pszPassword,
710c2c66affSColin Finck                                       (dwFlags & CREDUI_FLAGS_GENERIC_CREDENTIALS) != 0);
711c2c66affSColin Finck     }
712c2c66affSColin Finck 
713c2c66affSColin Finck     return result;
714c2c66affSColin Finck }
715c2c66affSColin Finck 
716c2c66affSColin Finck /******************************************************************************
717c2c66affSColin Finck  *           CredUIConfirmCredentialsW [CREDUI.@]
718c2c66affSColin Finck  */
CredUIConfirmCredentialsW(PCWSTR pszTargetName,BOOL bConfirm)719c2c66affSColin Finck DWORD WINAPI CredUIConfirmCredentialsW(PCWSTR pszTargetName, BOOL bConfirm)
720c2c66affSColin Finck {
721c2c66affSColin Finck     struct pending_credentials *entry;
722c2c66affSColin Finck     DWORD result = ERROR_NOT_FOUND;
723c2c66affSColin Finck 
724c2c66affSColin Finck     TRACE("(%s, %s)\n", debugstr_w(pszTargetName), bConfirm ? "TRUE" : "FALSE");
725c2c66affSColin Finck 
726c2c66affSColin Finck     if (!pszTargetName)
727c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
728c2c66affSColin Finck 
729c2c66affSColin Finck     EnterCriticalSection(&csPendingCredentials);
730c2c66affSColin Finck 
731c2c66affSColin Finck     LIST_FOR_EACH_ENTRY(entry, &pending_credentials_list, struct pending_credentials, entry)
732c2c66affSColin Finck     {
733*98ef8700SAmine Khaldi         if (!lstrcmpW(pszTargetName, entry->pszTargetName))
734c2c66affSColin Finck         {
735c2c66affSColin Finck             if (bConfirm)
736c2c66affSColin Finck                 result = save_credentials(entry->pszTargetName, entry->pszUsername,
737c2c66affSColin Finck                                           entry->pszPassword, entry->generic);
738c2c66affSColin Finck             else
739c2c66affSColin Finck                 result = ERROR_SUCCESS;
740c2c66affSColin Finck 
741c2c66affSColin Finck             list_remove(&entry->entry);
742c2c66affSColin Finck 
743c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, entry->pszTargetName);
744c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, entry->pszUsername);
745*98ef8700SAmine Khaldi             SecureZeroMemory(entry->pszPassword, lstrlenW(entry->pszPassword) * sizeof(WCHAR));
746c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, entry->pszPassword);
747c2c66affSColin Finck             HeapFree(GetProcessHeap(), 0, entry);
748c2c66affSColin Finck 
749c2c66affSColin Finck             break;
750c2c66affSColin Finck         }
751c2c66affSColin Finck     }
752c2c66affSColin Finck 
753c2c66affSColin Finck     LeaveCriticalSection(&csPendingCredentials);
754c2c66affSColin Finck 
755c2c66affSColin Finck     return result;
756c2c66affSColin Finck }
757c2c66affSColin Finck 
758c2c66affSColin Finck /******************************************************************************
759c2c66affSColin Finck  *           CredUIParseUserNameW [CREDUI.@]
760c2c66affSColin Finck  */
CredUIParseUserNameW(PCWSTR pszUserName,PWSTR pszUser,ULONG ulMaxUserChars,PWSTR pszDomain,ULONG ulMaxDomainChars)761c2c66affSColin Finck DWORD WINAPI CredUIParseUserNameW(PCWSTR pszUserName, PWSTR pszUser,
762c2c66affSColin Finck                                   ULONG ulMaxUserChars, PWSTR pszDomain,
763c2c66affSColin Finck                                   ULONG ulMaxDomainChars)
764c2c66affSColin Finck {
765c2c66affSColin Finck     PWSTR p;
766c2c66affSColin Finck 
767c2c66affSColin Finck     TRACE("(%s, %p, %d, %p, %d)\n", debugstr_w(pszUserName), pszUser,
768c2c66affSColin Finck           ulMaxUserChars, pszDomain, ulMaxDomainChars);
769c2c66affSColin Finck 
770c2c66affSColin Finck     if (!pszUserName || !pszUser || !ulMaxUserChars || !pszDomain ||
771c2c66affSColin Finck         !ulMaxDomainChars)
772c2c66affSColin Finck         return ERROR_INVALID_PARAMETER;
773c2c66affSColin Finck 
774c2c66affSColin Finck     /* FIXME: handle marshaled credentials */
775c2c66affSColin Finck 
776*98ef8700SAmine Khaldi     p = wcschr(pszUserName, '\\');
777c2c66affSColin Finck     if (p)
778c2c66affSColin Finck     {
779c2c66affSColin Finck         if (p - pszUserName > ulMaxDomainChars - 1)
780c2c66affSColin Finck             return ERROR_INSUFFICIENT_BUFFER;
781*98ef8700SAmine Khaldi         if (lstrlenW(p + 1) > ulMaxUserChars - 1)
782c2c66affSColin Finck             return ERROR_INSUFFICIENT_BUFFER;
783*98ef8700SAmine Khaldi         lstrcpyW(pszUser, p + 1);
784c2c66affSColin Finck         memcpy(pszDomain, pszUserName, (p - pszUserName)*sizeof(WCHAR));
785c2c66affSColin Finck         pszDomain[p - pszUserName] = '\0';
786c2c66affSColin Finck 
787c2c66affSColin Finck         return ERROR_SUCCESS;
788c2c66affSColin Finck     }
789c2c66affSColin Finck 
790*98ef8700SAmine Khaldi     p = wcsrchr(pszUserName, '@');
791c2c66affSColin Finck     if (p)
792c2c66affSColin Finck     {
793c2c66affSColin Finck         if (p + 1 - pszUserName > ulMaxUserChars - 1)
794c2c66affSColin Finck             return ERROR_INSUFFICIENT_BUFFER;
795*98ef8700SAmine Khaldi         if (lstrlenW(p + 1) > ulMaxDomainChars - 1)
796c2c66affSColin Finck             return ERROR_INSUFFICIENT_BUFFER;
797*98ef8700SAmine Khaldi         lstrcpyW(pszDomain, p + 1);
798c2c66affSColin Finck         memcpy(pszUser, pszUserName, (p - pszUserName)*sizeof(WCHAR));
799c2c66affSColin Finck         pszUser[p - pszUserName] = '\0';
800c2c66affSColin Finck 
801c2c66affSColin Finck         return ERROR_SUCCESS;
802c2c66affSColin Finck     }
803c2c66affSColin Finck 
804*98ef8700SAmine Khaldi     if (lstrlenW(pszUserName) > ulMaxUserChars - 1)
805c2c66affSColin Finck         return ERROR_INSUFFICIENT_BUFFER;
806*98ef8700SAmine Khaldi     lstrcpyW(pszUser, pszUserName);
807c2c66affSColin Finck     pszDomain[0] = '\0';
808c2c66affSColin Finck 
809c2c66affSColin Finck     return ERROR_SUCCESS;
810c2c66affSColin Finck }
811c2c66affSColin Finck 
812c2c66affSColin Finck /******************************************************************************
813c2c66affSColin Finck  *           CredUIStoreSSOCredA [CREDUI.@]
814c2c66affSColin Finck  */
CredUIStoreSSOCredA(PCSTR pszRealm,PCSTR pszUsername,PCSTR pszPassword,BOOL bPersist)815c2c66affSColin Finck DWORD WINAPI CredUIStoreSSOCredA(PCSTR pszRealm, PCSTR pszUsername,
816c2c66affSColin Finck                                  PCSTR pszPassword, BOOL bPersist)
817c2c66affSColin Finck {
818c2c66affSColin Finck     FIXME("(%s, %s, %p, %d)\n", debugstr_a(pszRealm), debugstr_a(pszUsername),
819c2c66affSColin Finck           pszPassword, bPersist);
820c2c66affSColin Finck     return ERROR_SUCCESS;
821c2c66affSColin Finck }
822c2c66affSColin Finck 
823c2c66affSColin Finck /******************************************************************************
824c2c66affSColin Finck  *           CredUIStoreSSOCredW [CREDUI.@]
825c2c66affSColin Finck  */
CredUIStoreSSOCredW(PCWSTR pszRealm,PCWSTR pszUsername,PCWSTR pszPassword,BOOL bPersist)826c2c66affSColin Finck DWORD WINAPI CredUIStoreSSOCredW(PCWSTR pszRealm, PCWSTR pszUsername,
827c2c66affSColin Finck                                  PCWSTR pszPassword, BOOL bPersist)
828c2c66affSColin Finck {
829c2c66affSColin Finck     FIXME("(%s, %s, %p, %d)\n", debugstr_w(pszRealm), debugstr_w(pszUsername),
830c2c66affSColin Finck           pszPassword, bPersist);
831c2c66affSColin Finck     return ERROR_SUCCESS;
832c2c66affSColin Finck }
833c2c66affSColin Finck 
834c2c66affSColin Finck /******************************************************************************
835c2c66affSColin Finck  *           CredUIReadSSOCredA [CREDUI.@]
836c2c66affSColin Finck  */
CredUIReadSSOCredA(PCSTR pszRealm,PSTR * ppszUsername)837c2c66affSColin Finck DWORD WINAPI CredUIReadSSOCredA(PCSTR pszRealm, PSTR *ppszUsername)
838c2c66affSColin Finck {
839c2c66affSColin Finck     FIXME("(%s, %p)\n", debugstr_a(pszRealm), ppszUsername);
840c2c66affSColin Finck     if (ppszUsername)
841c2c66affSColin Finck         *ppszUsername = NULL;
842c2c66affSColin Finck     return ERROR_NOT_FOUND;
843c2c66affSColin Finck }
844c2c66affSColin Finck 
845c2c66affSColin Finck /******************************************************************************
846c2c66affSColin Finck  *           CredUIReadSSOCredW [CREDUI.@]
847c2c66affSColin Finck  */
CredUIReadSSOCredW(PCWSTR pszRealm,PWSTR * ppszUsername)848c2c66affSColin Finck DWORD WINAPI CredUIReadSSOCredW(PCWSTR pszRealm, PWSTR *ppszUsername)
849c2c66affSColin Finck {
850c2c66affSColin Finck     FIXME("(%s, %p)\n", debugstr_w(pszRealm), ppszUsername);
851c2c66affSColin Finck     if (ppszUsername)
852c2c66affSColin Finck         *ppszUsername = NULL;
853c2c66affSColin Finck     return ERROR_NOT_FOUND;
854c2c66affSColin Finck }
855c2c66affSColin Finck 
856c2c66affSColin Finck /******************************************************************************
857c2c66affSColin Finck  * CredUIInitControls [CREDUI.@]
858c2c66affSColin Finck  */
CredUIInitControls(void)859c2c66affSColin Finck BOOL WINAPI CredUIInitControls(void)
860c2c66affSColin Finck {
861c2c66affSColin Finck     FIXME("() stub\n");
862c2c66affSColin Finck     return TRUE;
863c2c66affSColin Finck }
864c2c66affSColin Finck 
865c2c66affSColin Finck /******************************************************************************
866c2c66affSColin Finck  * SspiPromptForCredentialsW [CREDUI.@]
867c2c66affSColin Finck  */
SspiPromptForCredentialsW(PCWSTR target,void * info,DWORD error,PCWSTR package,PSEC_WINNT_AUTH_IDENTITY_OPAQUE input_id,PSEC_WINNT_AUTH_IDENTITY_OPAQUE * output_id,BOOL * save,DWORD sspi_flags)868c2c66affSColin Finck ULONG SEC_ENTRY SspiPromptForCredentialsW( PCWSTR target, void *info,
869c2c66affSColin Finck                                            DWORD error, PCWSTR package,
870c2c66affSColin Finck                                            PSEC_WINNT_AUTH_IDENTITY_OPAQUE input_id,
871c2c66affSColin Finck                                            PSEC_WINNT_AUTH_IDENTITY_OPAQUE *output_id,
872c2c66affSColin Finck                                            BOOL *save, DWORD sspi_flags )
873c2c66affSColin Finck {
874c2c66affSColin Finck     static const WCHAR basicW[] = {'B','a','s','i','c',0};
875c2c66affSColin Finck     static const WCHAR ntlmW[] = {'N','T','L','M',0};
876c2c66affSColin Finck     static const WCHAR negotiateW[] = {'N','e','g','o','t','i','a','t','e',0};
877c2c66affSColin Finck     WCHAR username[CREDUI_MAX_USERNAME_LENGTH + 1] = {0};
878c2c66affSColin Finck     WCHAR password[CREDUI_MAX_PASSWORD_LENGTH + 1] = {0};
87940934404SAmine Khaldi     DWORD len_username = ARRAY_SIZE(username);
88040934404SAmine Khaldi     DWORD len_password = ARRAY_SIZE(password);
881c2c66affSColin Finck     DWORD ret, flags;
882c2c66affSColin Finck     CREDUI_INFOW *cred_info = info;
883c2c66affSColin Finck     SEC_WINNT_AUTH_IDENTITY_W *id = input_id;
884c2c66affSColin Finck 
885c2c66affSColin Finck     FIXME( "(%s, %p, %u, %s, %p, %p, %p, %x) stub\n", debugstr_w(target), info,
886c2c66affSColin Finck            error, debugstr_w(package), input_id, output_id, save, sspi_flags );
887c2c66affSColin Finck 
888c2c66affSColin Finck     if (!target) return ERROR_INVALID_PARAMETER;
889*98ef8700SAmine Khaldi     if (!package || (wcsicmp( package, basicW ) && wcsicmp( package, ntlmW ) &&
890*98ef8700SAmine Khaldi                      wcsicmp( package, negotiateW )))
891c2c66affSColin Finck     {
892c2c66affSColin Finck         FIXME( "package %s not supported\n", debugstr_w(package) );
893c2c66affSColin Finck         return ERROR_NO_SUCH_PACKAGE;
894c2c66affSColin Finck     }
895c2c66affSColin Finck 
896c2c66affSColin Finck     flags = CREDUI_FLAGS_ALWAYS_SHOW_UI | CREDUI_FLAGS_GENERIC_CREDENTIALS;
897c2c66affSColin Finck 
898c2c66affSColin Finck     if (sspi_flags & SSPIPFC_CREDPROV_DO_NOT_SAVE)
899c2c66affSColin Finck         flags |= CREDUI_FLAGS_DO_NOT_PERSIST;
900c2c66affSColin Finck 
901c2c66affSColin Finck     if (!(sspi_flags & SSPIPFC_NO_CHECKBOX))
902c2c66affSColin Finck         flags |= CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX;
903c2c66affSColin Finck 
904c2c66affSColin Finck     if (!id) find_existing_credential( target, username, len_username, password, len_password );
905c2c66affSColin Finck     else
906c2c66affSColin Finck     {
907c2c66affSColin Finck         if (id->User && id->UserLength > 0 && id->UserLength <= CREDUI_MAX_USERNAME_LENGTH)
908c2c66affSColin Finck         {
909c2c66affSColin Finck             memcpy( username, id->User, id->UserLength * sizeof(WCHAR) );
910c2c66affSColin Finck             username[id->UserLength] = 0;
911c2c66affSColin Finck         }
912c2c66affSColin Finck         if (id->Password && id->PasswordLength > 0 && id->PasswordLength <= CREDUI_MAX_PASSWORD_LENGTH)
913c2c66affSColin Finck         {
914c2c66affSColin Finck             memcpy( password, id->Password, id->PasswordLength * sizeof(WCHAR) );
915c2c66affSColin Finck             password[id->PasswordLength] = 0;
916c2c66affSColin Finck         }
917c2c66affSColin Finck     }
918c2c66affSColin Finck 
919c2c66affSColin Finck     if (!(ret = CredUIPromptForCredentialsW( cred_info, target, NULL, error, username,
920c2c66affSColin Finck                                              len_username, password, len_password, save, flags )))
921c2c66affSColin Finck     {
922c2c66affSColin Finck         DWORD size = sizeof(*id), len_domain = 0;
923c2c66affSColin Finck         WCHAR *ptr, *user = username, *domain = NULL;
924c2c66affSColin Finck 
925*98ef8700SAmine Khaldi         if ((ptr = wcschr( username, '\\' )))
926c2c66affSColin Finck         {
927c2c66affSColin Finck             user = ptr + 1;
928*98ef8700SAmine Khaldi             len_username = lstrlenW( user );
929*98ef8700SAmine Khaldi             if (!wcsicmp( package, ntlmW ) || !wcsicmp( package, negotiateW ))
930c2c66affSColin Finck             {
931c2c66affSColin Finck                 domain = username;
932c2c66affSColin Finck                 len_domain = ptr - username;
933c2c66affSColin Finck             }
934c2c66affSColin Finck             *ptr = 0;
935c2c66affSColin Finck         }
936*98ef8700SAmine Khaldi         else len_username = lstrlenW( username );
937*98ef8700SAmine Khaldi         len_password = lstrlenW( password );
938c2c66affSColin Finck 
939c2c66affSColin Finck         size += (len_username + 1) * sizeof(WCHAR);
940c2c66affSColin Finck         size += (len_domain + 1) * sizeof(WCHAR);
941c2c66affSColin Finck         size += (len_password + 1) * sizeof(WCHAR);
942c2c66affSColin Finck         if (!(id = HeapAlloc( GetProcessHeap(), 0, size ))) return ERROR_OUTOFMEMORY;
943c2c66affSColin Finck         ptr = (WCHAR *)(id + 1);
944c2c66affSColin Finck 
945c2c66affSColin Finck         memcpy( ptr, user, (len_username + 1) * sizeof(WCHAR) );
946c2c66affSColin Finck         id->User           = ptr;
947c2c66affSColin Finck         id->UserLength     = len_username;
948c2c66affSColin Finck         ptr += len_username + 1;
949c2c66affSColin Finck         if (len_domain)
950c2c66affSColin Finck         {
951c2c66affSColin Finck             memcpy( ptr, domain, (len_domain + 1) * sizeof(WCHAR) );
952c2c66affSColin Finck             id->Domain         = ptr;
953c2c66affSColin Finck             id->DomainLength   = len_domain;
954c2c66affSColin Finck             ptr += len_domain + 1;
955c2c66affSColin Finck         }
956c2c66affSColin Finck         else
957c2c66affSColin Finck         {
958c2c66affSColin Finck             id->Domain         = NULL;
959c2c66affSColin Finck             id->DomainLength   = 0;
960c2c66affSColin Finck         }
961c2c66affSColin Finck         memcpy( ptr, password, (len_password + 1) * sizeof(WCHAR) );
962c2c66affSColin Finck         id->Password       = ptr;
963c2c66affSColin Finck         id->PasswordLength = len_password;
964c2c66affSColin Finck         id->Flags          = 0;
965c2c66affSColin Finck 
966c2c66affSColin Finck         *output_id = id;
967c2c66affSColin Finck     }
968c2c66affSColin Finck 
969c2c66affSColin Finck     return ret;
970c2c66affSColin Finck }
971c2c66affSColin Finck 
972c2c66affSColin Finck /******************************************************************************
973c2c66affSColin Finck  * CredUIPromptForWindowsCredentialsW [CREDUI.@]
974c2c66affSColin Finck  */
CredUIPromptForWindowsCredentialsW(CREDUI_INFOW * info,DWORD error,ULONG * package,const void * in_buf,ULONG in_buf_size,void ** out_buf,ULONG * out_buf_size,BOOL * save,DWORD flags)975c2c66affSColin Finck DWORD WINAPI CredUIPromptForWindowsCredentialsW( CREDUI_INFOW *info, DWORD error, ULONG *package,
976c2c66affSColin Finck                                                  const void *in_buf, ULONG in_buf_size, void **out_buf,
977c2c66affSColin Finck                                                  ULONG *out_buf_size, BOOL *save, DWORD flags )
978c2c66affSColin Finck {
979c2c66affSColin Finck     FIXME( "(%p, %u, %p, %p, %u, %p, %p, %p, %08x) stub\n", info, error, package, in_buf, in_buf_size,
980c2c66affSColin Finck            out_buf, out_buf_size, save, flags );
981c2c66affSColin Finck     return ERROR_CALL_NOT_IMPLEMENTED;
982c2c66affSColin Finck }
983c2c66affSColin Finck 
984c2c66affSColin Finck /******************************************************************************
985c2c66affSColin Finck  * CredPackAuthenticationBufferW [CREDUI.@]
986c2c66affSColin Finck  */
CredPackAuthenticationBufferW(DWORD flags,WCHAR * username,WCHAR * password,BYTE * buf,DWORD * size)987c2c66affSColin Finck BOOL  WINAPI CredPackAuthenticationBufferW( DWORD flags, WCHAR *username, WCHAR *password, BYTE *buf,
988c2c66affSColin Finck                                             DWORD *size )
989c2c66affSColin Finck {
990c2c66affSColin Finck     FIXME( "(%08x, %s, %p, %p, %p) stub\n", flags, debugstr_w(username), password, buf, size );
991c2c66affSColin Finck     return ERROR_CALL_NOT_IMPLEMENTED;
992c2c66affSColin Finck }
993c2c66affSColin Finck 
994c2c66affSColin Finck /******************************************************************************
995c2c66affSColin Finck  * CredUnPackAuthenticationBufferW [CREDUI.@]
996c2c66affSColin Finck  */
CredUnPackAuthenticationBufferW(DWORD flags,void * buf,DWORD size,WCHAR * username,DWORD * len_username,WCHAR * domain,DWORD * len_domain,WCHAR * password,DWORD * len_password)997c2c66affSColin Finck BOOL  WINAPI CredUnPackAuthenticationBufferW( DWORD flags, void *buf, DWORD size, WCHAR *username,
998c2c66affSColin Finck                                               DWORD *len_username, WCHAR *domain, DWORD *len_domain,
999c2c66affSColin Finck                                               WCHAR *password, DWORD *len_password )
1000c2c66affSColin Finck {
1001c2c66affSColin Finck     FIXME( "(%08x, %p, %u, %p, %p, %p, %p, %p, %p) stub\n", flags, buf, size, username, len_username,
1002c2c66affSColin Finck            domain, len_domain, password, len_password );
1003c2c66affSColin Finck     return ERROR_CALL_NOT_IMPLEMENTED;
1004c2c66affSColin Finck }
1005