cmd: Improve the message when the volume has no label.
[wine.git] / dlls / credui / credui_main.c
blob9d09b03cf5c0f42d4bfd021654588244ea8f5bee
1 /*
2 * Credentials User Interface
4 * Copyright 2006 Robert Shearman (for CodeWeavers)
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winnt.h"
26 #include "winuser.h"
27 #include "wincred.h"
28 #include "commctrl.h"
30 #include "credui_resources.h"
32 #include "wine/debug.h"
33 #include "wine/unicode.h"
34 #include "wine/list.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(credui);
38 #define TOOLID_INCORRECTPASSWORD 1
39 #define TOOLID_CAPSLOCKON 2
41 #define ID_CAPSLOCKPOP 1
43 struct pending_credentials
45 struct list entry;
46 PWSTR pszTargetName;
47 PWSTR pszUsername;
48 PWSTR pszPassword;
49 BOOL generic;
52 static HINSTANCE hinstCredUI;
54 static struct list pending_credentials_list = LIST_INIT(pending_credentials_list);
56 static CRITICAL_SECTION csPendingCredentials;
57 static CRITICAL_SECTION_DEBUG critsect_debug =
59 0, 0, &csPendingCredentials,
60 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
61 0, 0, { (DWORD_PTR)(__FILE__ ": csPendingCredentials") }
63 static CRITICAL_SECTION csPendingCredentials = { &critsect_debug, -1, 0, 0, 0, 0 };
66 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
68 struct pending_credentials *entry, *cursor2;
69 TRACE("(0x%p, %d, %p)\n",hinstDLL,fdwReason,lpvReserved);
71 switch (fdwReason)
73 case DLL_WINE_PREATTACH:
74 return FALSE; /* prefer native version */
76 case DLL_PROCESS_ATTACH:
77 DisableThreadLibraryCalls(hinstDLL);
78 hinstCredUI = hinstDLL;
79 InitCommonControls();
80 break;
82 case DLL_PROCESS_DETACH:
83 LIST_FOR_EACH_ENTRY_SAFE(entry, cursor2, &pending_credentials_list, struct pending_credentials, entry)
85 list_remove(&entry->entry);
87 HeapFree(GetProcessHeap(), 0, entry->pszTargetName);
88 HeapFree(GetProcessHeap(), 0, entry->pszUsername);
89 ZeroMemory(entry->pszPassword, (strlenW(entry->pszPassword) + 1) * sizeof(WCHAR));
90 HeapFree(GetProcessHeap(), 0, entry->pszPassword);
91 HeapFree(GetProcessHeap(), 0, entry);
93 DeleteCriticalSection(&csPendingCredentials);
94 break;
97 return TRUE;
100 static DWORD save_credentials(PCWSTR pszTargetName, PCWSTR pszUsername,
101 PCWSTR pszPassword, BOOL generic)
103 CREDENTIALW cred;
105 TRACE("saving servername %s with username %s\n", debugstr_w(pszTargetName), debugstr_w(pszUsername));
107 cred.Flags = 0;
108 cred.Type = generic ? CRED_TYPE_GENERIC : CRED_TYPE_DOMAIN_PASSWORD;
109 cred.TargetName = (LPWSTR)pszTargetName;
110 cred.Comment = NULL;
111 cred.CredentialBlobSize = strlenW(pszPassword) * sizeof(WCHAR);
112 cred.CredentialBlob = (LPBYTE)pszPassword;
113 cred.Persist = CRED_PERSIST_ENTERPRISE;
114 cred.AttributeCount = 0;
115 cred.Attributes = NULL;
116 cred.TargetAlias = NULL;
117 cred.UserName = (LPWSTR)pszUsername;
119 if (CredWriteW(&cred, 0))
120 return ERROR_SUCCESS;
121 else
123 DWORD ret = GetLastError();
124 ERR("CredWriteW failed with error %d\n", ret);
125 return ret;
129 struct cred_dialog_params
131 PCWSTR pszTargetName;
132 PCWSTR pszMessageText;
133 PCWSTR pszCaptionText;
134 HBITMAP hbmBanner;
135 PWSTR pszUsername;
136 ULONG ulUsernameMaxChars;
137 PWSTR pszPassword;
138 ULONG ulPasswordMaxChars;
139 BOOL fSave;
140 DWORD dwFlags;
141 HWND hwndBalloonTip;
142 BOOL fBalloonTipActive;
145 static void CredDialogFillUsernameCombo(HWND hwndUsername, const struct cred_dialog_params *params)
147 DWORD count;
148 DWORD i;
149 PCREDENTIALW *credentials;
151 if (!CredEnumerateW(NULL, 0, &count, &credentials))
152 return;
154 for (i = 0; i < count; i++)
156 COMBOBOXEXITEMW comboitem;
157 DWORD j;
158 BOOL duplicate = FALSE;
160 if (params->dwFlags & CREDUI_FLAGS_GENERIC_CREDENTIALS)
162 if ((credentials[i]->Type != CRED_TYPE_GENERIC) || !credentials[i]->UserName)
163 continue;
165 else
167 if (credentials[i]->Type == CRED_TYPE_GENERIC)
168 continue;
171 /* don't add another item with the same name if we've already added it */
172 for (j = 0; j < i; j++)
173 if (!strcmpW(credentials[i]->UserName, credentials[j]->UserName))
175 duplicate = TRUE;
176 break;
179 if (duplicate)
180 continue;
182 comboitem.mask = CBEIF_TEXT;
183 comboitem.iItem = -1;
184 comboitem.pszText = credentials[i]->UserName;
185 SendMessageW(hwndUsername, CBEM_INSERTITEMW, 0, (LPARAM)&comboitem);
188 CredFree(credentials);
191 static void CredDialogCreateBalloonTip(HWND hwndDlg, struct cred_dialog_params *params)
193 TTTOOLINFOW toolinfo;
194 WCHAR wszText[256];
196 if (params->hwndBalloonTip)
197 return;
199 params->hwndBalloonTip = CreateWindowExW(WS_EX_TOOLWINDOW, TOOLTIPS_CLASSW,
200 NULL, WS_POPUP | TTS_NOPREFIX | TTS_BALLOON, CW_USEDEFAULT,
201 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hwndDlg, NULL,
202 hinstCredUI, NULL);
203 SetWindowPos(params->hwndBalloonTip, HWND_TOPMOST, 0, 0, 0, 0,
204 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
206 if (!LoadStringW(hinstCredUI, IDS_INCORRECTPASSWORD, wszText, sizeof(wszText)/sizeof(wszText[0])))
208 ERR("failed to load IDS_INCORRECTPASSWORD\n");
209 return;
212 toolinfo.cbSize = sizeof(toolinfo);
213 toolinfo.uFlags = TTF_TRACK;
214 toolinfo.hwnd = hwndDlg;
215 toolinfo.uId = TOOLID_INCORRECTPASSWORD;
216 memset(&toolinfo.rect, 0, sizeof(toolinfo.rect));
217 toolinfo.hinst = NULL;
218 toolinfo.lpszText = wszText;
219 toolinfo.lParam = 0;
220 toolinfo.lpReserved = NULL;
221 SendMessageW(params->hwndBalloonTip, TTM_ADDTOOLW, 0, (LPARAM)&toolinfo);
223 if (!LoadStringW(hinstCredUI, IDS_CAPSLOCKON, wszText, sizeof(wszText)/sizeof(wszText[0])))
225 ERR("failed to load IDS_CAPSLOCKON\n");
226 return;
229 toolinfo.uId = TOOLID_CAPSLOCKON;
230 SendMessageW(params->hwndBalloonTip, TTM_ADDTOOLW, 0, (LPARAM)&toolinfo);
233 static void CredDialogShowIncorrectPasswordBalloon(HWND hwndDlg, struct cred_dialog_params *params)
235 TTTOOLINFOW toolinfo;
236 RECT rcPassword;
237 INT x;
238 INT y;
239 WCHAR wszTitle[256];
241 /* user name likely wrong so balloon would be confusing. focus is also
242 * not set to the password edit box, so more notification would need to be
243 * handled */
244 if (!params->pszUsername[0])
245 return;
247 /* don't show two balloon tips at once */
248 if (params->fBalloonTipActive)
249 return;
251 if (!LoadStringW(hinstCredUI, IDS_INCORRECTPASSWORDTITLE, wszTitle, sizeof(wszTitle)/sizeof(wszTitle[0])))
253 ERR("failed to load IDS_INCORRECTPASSWORDTITLE\n");
254 return;
257 CredDialogCreateBalloonTip(hwndDlg, params);
259 memset(&toolinfo, 0, sizeof(toolinfo));
260 toolinfo.cbSize = sizeof(toolinfo);
261 toolinfo.hwnd = hwndDlg;
262 toolinfo.uId = TOOLID_INCORRECTPASSWORD;
264 SendMessageW(params->hwndBalloonTip, TTM_SETTITLEW, TTI_ERROR, (LPARAM)wszTitle);
266 GetWindowRect(GetDlgItem(hwndDlg, IDC_PASSWORD), &rcPassword);
267 /* centered vertically and in the right side of the password edit control */
268 x = rcPassword.right - 12;
269 y = (rcPassword.top + rcPassword.bottom) / 2;
270 SendMessageW(params->hwndBalloonTip, TTM_TRACKPOSITION, 0, MAKELONG(x, y));
272 SendMessageW(params->hwndBalloonTip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&toolinfo);
274 params->fBalloonTipActive = TRUE;
277 static void CredDialogShowCapsLockBalloon(HWND hwndDlg, struct cred_dialog_params *params)
279 TTTOOLINFOW toolinfo;
280 RECT rcPassword;
281 INT x;
282 INT y;
283 WCHAR wszTitle[256];
285 /* don't show two balloon tips at once */
286 if (params->fBalloonTipActive)
287 return;
289 if (!LoadStringW(hinstCredUI, IDS_CAPSLOCKONTITLE, wszTitle, sizeof(wszTitle)/sizeof(wszTitle[0])))
291 ERR("failed to load IDS_IDSCAPSLOCKONTITLE\n");
292 return;
295 CredDialogCreateBalloonTip(hwndDlg, params);
297 memset(&toolinfo, 0, sizeof(toolinfo));
298 toolinfo.cbSize = sizeof(toolinfo);
299 toolinfo.hwnd = hwndDlg;
300 toolinfo.uId = TOOLID_CAPSLOCKON;
302 SendMessageW(params->hwndBalloonTip, TTM_SETTITLEW, TTI_WARNING, (LPARAM)wszTitle);
304 GetWindowRect(GetDlgItem(hwndDlg, IDC_PASSWORD), &rcPassword);
305 /* just inside the left side of the password edit control */
306 x = rcPassword.left + 12;
307 y = rcPassword.bottom - 3;
308 SendMessageW(params->hwndBalloonTip, TTM_TRACKPOSITION, 0, MAKELONG(x, y));
310 SendMessageW(params->hwndBalloonTip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&toolinfo);
312 SetTimer(hwndDlg, ID_CAPSLOCKPOP,
313 SendMessageW(params->hwndBalloonTip, TTM_GETDELAYTIME, TTDT_AUTOPOP, 0),
314 NULL);
316 params->fBalloonTipActive = TRUE;
319 static void CredDialogHideBalloonTip(HWND hwndDlg, struct cred_dialog_params *params)
321 TTTOOLINFOW toolinfo;
323 if (!params->hwndBalloonTip)
324 return;
326 memset(&toolinfo, 0, sizeof(toolinfo));
328 toolinfo.cbSize = sizeof(toolinfo);
329 toolinfo.hwnd = hwndDlg;
330 toolinfo.uId = 0;
331 SendMessageW(params->hwndBalloonTip, TTM_TRACKACTIVATE, FALSE, (LPARAM)&toolinfo);
332 toolinfo.uId = 1;
333 SendMessageW(params->hwndBalloonTip, TTM_TRACKACTIVATE, FALSE, (LPARAM)&toolinfo);
335 params->fBalloonTipActive = FALSE;
338 static inline BOOL CredDialogCapsLockOn(void)
340 return GetKeyState(VK_CAPITAL) & 0x1 ? TRUE : FALSE;
343 static LRESULT CALLBACK CredDialogPasswordSubclassProc(HWND hwnd, UINT uMsg,
344 WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
346 struct cred_dialog_params *params = (struct cred_dialog_params *)dwRefData;
347 switch (uMsg)
349 case WM_KEYDOWN:
350 if (wParam == VK_CAPITAL)
352 HWND hwndDlg = GetParent(hwnd);
353 if (CredDialogCapsLockOn())
354 CredDialogShowCapsLockBalloon(hwndDlg, params);
355 else
356 CredDialogHideBalloonTip(hwndDlg, params);
358 break;
359 case WM_DESTROY:
360 RemoveWindowSubclass(hwnd, CredDialogPasswordSubclassProc, uIdSubclass);
361 break;
363 return DefSubclassProc(hwnd, uMsg, wParam, lParam);
366 static BOOL CredDialogInit(HWND hwndDlg, struct cred_dialog_params *params)
368 HWND hwndUsername = GetDlgItem(hwndDlg, IDC_USERNAME);
369 HWND hwndPassword = GetDlgItem(hwndDlg, IDC_PASSWORD);
371 SetWindowLongPtrW(hwndDlg, DWLP_USER, (LONG_PTR)params);
373 if (params->hbmBanner)
374 SendMessageW(GetDlgItem(hwndDlg, IDB_BANNER), STM_SETIMAGE,
375 IMAGE_BITMAP, (LPARAM)params->hbmBanner);
377 if (params->pszMessageText)
378 SetDlgItemTextW(hwndDlg, IDC_MESSAGE, params->pszMessageText);
379 else
381 WCHAR format[256];
382 WCHAR message[256];
383 LoadStringW(hinstCredUI, IDS_MESSAGEFORMAT, format, sizeof(format)/sizeof(format[0]));
384 snprintfW(message, sizeof(message)/sizeof(message[0]), format, params->pszTargetName);
385 SetDlgItemTextW(hwndDlg, IDC_MESSAGE, message);
387 SetWindowTextW(hwndUsername, params->pszUsername);
388 SetWindowTextW(hwndPassword, params->pszPassword);
390 CredDialogFillUsernameCombo(hwndUsername, params);
392 if (params->pszUsername[0])
394 /* prevent showing a balloon tip here */
395 params->fBalloonTipActive = TRUE;
396 SetFocus(hwndPassword);
397 params->fBalloonTipActive = FALSE;
399 else
400 SetFocus(hwndUsername);
402 if (params->pszCaptionText)
403 SetWindowTextW(hwndDlg, params->pszCaptionText);
404 else
406 WCHAR format[256];
407 WCHAR title[256];
408 LoadStringW(hinstCredUI, IDS_TITLEFORMAT, format, sizeof(format)/sizeof(format[0]));
409 snprintfW(title, sizeof(title)/sizeof(title[0]), format, params->pszTargetName);
410 SetWindowTextW(hwndDlg, title);
413 if (params->dwFlags & (CREDUI_FLAGS_DO_NOT_PERSIST|CREDUI_FLAGS_PERSIST))
414 ShowWindow(GetDlgItem(hwndDlg, IDC_SAVE), SW_HIDE);
415 else if (params->fSave)
416 CheckDlgButton(hwndDlg, IDC_SAVE, BST_CHECKED);
418 /* setup subclassing for Caps Lock detection */
419 SetWindowSubclass(hwndPassword, CredDialogPasswordSubclassProc, 1, (DWORD_PTR)params);
421 if (params->dwFlags & CREDUI_FLAGS_INCORRECT_PASSWORD)
422 CredDialogShowIncorrectPasswordBalloon(hwndDlg, params);
423 else if ((GetFocus() == hwndPassword) && CredDialogCapsLockOn())
424 CredDialogShowCapsLockBalloon(hwndDlg, params);
426 return FALSE;
429 static void CredDialogCommandOk(HWND hwndDlg, struct cred_dialog_params *params)
431 HWND hwndUsername = GetDlgItem(hwndDlg, IDC_USERNAME);
432 LPWSTR user;
433 INT len;
434 INT len2;
436 len = GetWindowTextLengthW(hwndUsername);
437 user = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
438 GetWindowTextW(hwndUsername, user, len + 1);
440 if (!user[0])
442 HeapFree(GetProcessHeap(), 0, user);
443 return;
446 if (!strchrW(user, '\\') && !strchrW(user, '@'))
448 ULONG len_target = strlenW(params->pszTargetName);
449 memcpy(params->pszUsername, params->pszTargetName,
450 min(len_target, params->ulUsernameMaxChars) * sizeof(WCHAR));
451 if (len_target + 1 < params->ulUsernameMaxChars)
452 params->pszUsername[len_target] = '\\';
453 if (len_target + 2 < params->ulUsernameMaxChars)
454 params->pszUsername[len_target + 1] = '\0';
456 else if (params->ulUsernameMaxChars > 0)
457 params->pszUsername[0] = '\0';
459 len2 = strlenW(params->pszUsername);
460 memcpy(params->pszUsername + len2, user, min(len, params->ulUsernameMaxChars - len2) * sizeof(WCHAR));
461 if (params->ulUsernameMaxChars)
462 params->pszUsername[len2 + min(len, params->ulUsernameMaxChars - len2 - 1)] = '\0';
464 HeapFree(GetProcessHeap(), 0, user);
466 GetDlgItemTextW(hwndDlg, IDC_PASSWORD, params->pszPassword,
467 params->ulPasswordMaxChars);
469 params->fSave = IsDlgButtonChecked(hwndDlg, IDC_SAVE) == BST_CHECKED;
471 EndDialog(hwndDlg, IDOK);
474 static INT_PTR CALLBACK CredDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
475 LPARAM lParam)
477 switch (uMsg)
479 case WM_INITDIALOG:
481 struct cred_dialog_params *params = (struct cred_dialog_params *)lParam;
483 return CredDialogInit(hwndDlg, params);
485 case WM_COMMAND:
486 switch (wParam)
488 case MAKELONG(IDOK, BN_CLICKED):
490 struct cred_dialog_params *params =
491 (struct cred_dialog_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
492 CredDialogCommandOk(hwndDlg, params);
493 return TRUE;
495 case MAKELONG(IDCANCEL, BN_CLICKED):
496 EndDialog(hwndDlg, IDCANCEL);
497 return TRUE;
498 case MAKELONG(IDC_PASSWORD, EN_SETFOCUS):
499 if (CredDialogCapsLockOn())
501 struct cred_dialog_params *params =
502 (struct cred_dialog_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
503 CredDialogShowCapsLockBalloon(hwndDlg, params);
505 /* don't allow another window to steal focus while the
506 * user is typing their password */
507 LockSetForegroundWindow(LSFW_LOCK);
508 return TRUE;
509 case MAKELONG(IDC_PASSWORD, EN_KILLFOCUS):
511 struct cred_dialog_params *params =
512 (struct cred_dialog_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
513 /* the user is no longer typing their password, so allow
514 * other windows to become foreground ones */
515 LockSetForegroundWindow(LSFW_UNLOCK);
516 CredDialogHideBalloonTip(hwndDlg, params);
517 return TRUE;
519 case MAKELONG(IDC_PASSWORD, EN_CHANGE):
521 struct cred_dialog_params *params =
522 (struct cred_dialog_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
523 CredDialogHideBalloonTip(hwndDlg, params);
524 return TRUE;
527 return FALSE;
528 case WM_TIMER:
529 if (wParam == ID_CAPSLOCKPOP)
531 struct cred_dialog_params *params =
532 (struct cred_dialog_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
533 CredDialogHideBalloonTip(hwndDlg, params);
534 return TRUE;
536 return FALSE;
537 case WM_DESTROY:
539 struct cred_dialog_params *params =
540 (struct cred_dialog_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
541 if (params->hwndBalloonTip) DestroyWindow(params->hwndBalloonTip);
542 return TRUE;
544 default:
545 return FALSE;
549 /******************************************************************************
550 * CredUIPromptForCredentialsW [CREDUI.@]
552 DWORD WINAPI CredUIPromptForCredentialsW(PCREDUI_INFOW pUIInfo,
553 PCWSTR pszTargetName,
554 PCtxtHandle Reserved,
555 DWORD dwAuthError,
556 PWSTR pszUsername,
557 ULONG ulUsernameMaxChars,
558 PWSTR pszPassword,
559 ULONG ulPasswordMaxChars, PBOOL pfSave,
560 DWORD dwFlags)
562 INT_PTR ret;
563 struct cred_dialog_params params;
564 DWORD result = ERROR_SUCCESS;
566 TRACE("(%p, %s, %p, %d, %s, %d, %p, %d, %p, 0x%08x)\n", pUIInfo,
567 debugstr_w(pszTargetName), Reserved, dwAuthError, debugstr_w(pszUsername),
568 ulUsernameMaxChars, pszPassword, ulPasswordMaxChars, pfSave, dwFlags);
570 if ((dwFlags & (CREDUI_FLAGS_ALWAYS_SHOW_UI|CREDUI_FLAGS_GENERIC_CREDENTIALS)) == CREDUI_FLAGS_ALWAYS_SHOW_UI)
571 return ERROR_INVALID_FLAGS;
573 if (!pszTargetName)
574 return ERROR_INVALID_PARAMETER;
576 if ((dwFlags & CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX) && !pfSave)
577 return ERROR_INVALID_PARAMETER;
579 params.pszTargetName = pszTargetName;
580 if (pUIInfo)
582 params.pszMessageText = pUIInfo->pszMessageText;
583 params.pszCaptionText = pUIInfo->pszCaptionText;
584 params.hbmBanner = pUIInfo->hbmBanner;
586 else
588 params.pszMessageText = NULL;
589 params.pszCaptionText = NULL;
590 params.hbmBanner = NULL;
592 params.pszUsername = pszUsername;
593 params.ulUsernameMaxChars = ulUsernameMaxChars;
594 params.pszPassword = pszPassword;
595 params.ulPasswordMaxChars = ulPasswordMaxChars;
596 params.fSave = pfSave ? *pfSave : FALSE;
597 params.dwFlags = dwFlags;
598 params.hwndBalloonTip = NULL;
599 params.fBalloonTipActive = FALSE;
601 ret = DialogBoxParamW(hinstCredUI, MAKEINTRESOURCEW(IDD_CREDDIALOG),
602 pUIInfo ? pUIInfo->hwndParent : NULL,
603 CredDialogProc, (LPARAM)&params);
604 if (ret <= 0)
605 return GetLastError();
607 if (ret == IDCANCEL)
609 TRACE("dialog cancelled\n");
610 return ERROR_CANCELLED;
613 if (pfSave)
614 *pfSave = params.fSave;
616 if (params.fSave)
618 if (dwFlags & CREDUI_FLAGS_EXPECT_CONFIRMATION)
620 BOOL found = FALSE;
621 struct pending_credentials *entry;
622 int len;
624 EnterCriticalSection(&csPendingCredentials);
626 /* find existing pending credentials for the same target and overwrite */
627 /* FIXME: is this correct? */
628 LIST_FOR_EACH_ENTRY(entry, &pending_credentials_list, struct pending_credentials, entry)
629 if (!strcmpW(pszTargetName, entry->pszTargetName))
631 found = TRUE;
632 HeapFree(GetProcessHeap(), 0, entry->pszUsername);
633 ZeroMemory(entry->pszPassword, (strlenW(entry->pszPassword) + 1) * sizeof(WCHAR));
634 HeapFree(GetProcessHeap(), 0, entry->pszPassword);
637 if (!found)
639 entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
640 len = strlenW(pszTargetName);
641 entry->pszTargetName = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
642 memcpy(entry->pszTargetName, pszTargetName, (len + 1)*sizeof(WCHAR));
643 list_add_tail(&pending_credentials_list, &entry->entry);
646 len = strlenW(params.pszUsername);
647 entry->pszUsername = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
648 memcpy(entry->pszUsername, params.pszUsername, (len + 1)*sizeof(WCHAR));
649 len = strlenW(params.pszPassword);
650 entry->pszPassword = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
651 memcpy(entry->pszPassword, params.pszPassword, (len + 1)*sizeof(WCHAR));
652 entry->generic = dwFlags & CREDUI_FLAGS_GENERIC_CREDENTIALS ? TRUE : FALSE;
654 LeaveCriticalSection(&csPendingCredentials);
656 else
657 result = save_credentials(pszTargetName, pszUsername, pszPassword,
658 dwFlags & CREDUI_FLAGS_GENERIC_CREDENTIALS ? TRUE : FALSE);
661 return result;
664 /******************************************************************************
665 * CredUIConfirmCredentialsW [CREDUI.@]
667 DWORD WINAPI CredUIConfirmCredentialsW(PCWSTR pszTargetName, BOOL bConfirm)
669 struct pending_credentials *entry;
670 DWORD result = ERROR_NOT_FOUND;
672 TRACE("(%s, %s)\n", debugstr_w(pszTargetName), bConfirm ? "TRUE" : "FALSE");
674 if (!pszTargetName)
675 return ERROR_INVALID_PARAMETER;
677 EnterCriticalSection(&csPendingCredentials);
679 LIST_FOR_EACH_ENTRY(entry, &pending_credentials_list, struct pending_credentials, entry)
681 if (!strcmpW(pszTargetName, entry->pszTargetName))
683 if (bConfirm)
684 result = save_credentials(entry->pszTargetName, entry->pszUsername,
685 entry->pszPassword, entry->generic);
686 else
687 result = ERROR_SUCCESS;
689 list_remove(&entry->entry);
691 HeapFree(GetProcessHeap(), 0, entry->pszTargetName);
692 HeapFree(GetProcessHeap(), 0, entry->pszUsername);
693 ZeroMemory(entry->pszPassword, (strlenW(entry->pszPassword) + 1) * sizeof(WCHAR));
694 HeapFree(GetProcessHeap(), 0, entry->pszPassword);
695 HeapFree(GetProcessHeap(), 0, entry);
697 break;
701 LeaveCriticalSection(&csPendingCredentials);
703 return result;
706 /******************************************************************************
707 * CredUIParseUserNameW [CREDUI.@]
709 DWORD WINAPI CredUIParseUserNameW(PCWSTR pszUserName, PWSTR pszUser,
710 ULONG ulMaxUserChars, PWSTR pszDomain,
711 ULONG ulMaxDomainChars)
713 PWSTR p;
715 TRACE("(%s, %p, %d, %p, %d)\n", debugstr_w(pszUserName), pszUser,
716 ulMaxUserChars, pszDomain, ulMaxDomainChars);
718 if (!pszUserName || !pszUser || !ulMaxUserChars || !pszDomain ||
719 !ulMaxDomainChars)
720 return ERROR_INVALID_PARAMETER;
722 /* FIXME: handle marshaled credentials */
724 p = strchrW(pszUserName, '\\');
725 if (p)
727 if (p - pszUserName > ulMaxDomainChars - 1)
728 return ERROR_INSUFFICIENT_BUFFER;
729 if (strlenW(p + 1) > ulMaxUserChars - 1)
730 return ERROR_INSUFFICIENT_BUFFER;
731 strcpyW(pszUser, p + 1);
732 memcpy(pszDomain, pszUserName, (p - pszUserName)*sizeof(WCHAR));
733 pszDomain[p - pszUserName] = '\0';
735 return ERROR_SUCCESS;
738 p = strrchrW(pszUserName, '@');
739 if (p)
741 if (p + 1 - pszUserName > ulMaxUserChars - 1)
742 return ERROR_INSUFFICIENT_BUFFER;
743 if (strlenW(p + 1) > ulMaxDomainChars - 1)
744 return ERROR_INSUFFICIENT_BUFFER;
745 strcpyW(pszDomain, p + 1);
746 memcpy(pszUser, pszUserName, (p - pszUserName)*sizeof(WCHAR));
747 pszUser[p - pszUserName] = '\0';
749 return ERROR_SUCCESS;
752 if (strlenW(pszUserName) > ulMaxUserChars - 1)
753 return ERROR_INSUFFICIENT_BUFFER;
754 strcpyW(pszUser, pszUserName);
755 pszDomain[0] = '\0';
757 return ERROR_SUCCESS;
760 /******************************************************************************
761 * CredUIStoreSSOCredA [CREDUI.@]
763 DWORD WINAPI CredUIStoreSSOCredA(PCSTR pszRealm, PCSTR pszUsername,
764 PCSTR pszPassword, BOOL bPersist)
766 FIXME("(%s, %s, %p, %d)\n", debugstr_a(pszRealm), debugstr_a(pszUsername),
767 pszPassword, bPersist);
768 return ERROR_SUCCESS;
771 /******************************************************************************
772 * CredUIStoreSSOCredW [CREDUI.@]
774 DWORD WINAPI CredUIStoreSSOCredW(PCWSTR pszRealm, PCWSTR pszUsername,
775 PCWSTR pszPassword, BOOL bPersist)
777 FIXME("(%s, %s, %p, %d)\n", debugstr_w(pszRealm), debugstr_w(pszUsername),
778 pszPassword, bPersist);
779 return ERROR_SUCCESS;
782 /******************************************************************************
783 * CredUIReadSSOCredA [CREDUI.@]
785 DWORD WINAPI CredUIReadSSOCredA(PCSTR pszRealm, PSTR *ppszUsername)
787 FIXME("(%s, %p)\n", debugstr_a(pszRealm), ppszUsername);
788 if (ppszUsername)
789 *ppszUsername = NULL;
790 return ERROR_NOT_FOUND;
793 /******************************************************************************
794 * CredUIReadSSOCredW [CREDUI.@]
796 DWORD WINAPI CredUIReadSSOCredW(PCWSTR pszRealm, PWSTR *ppszUsername)
798 FIXME("(%s, %p)\n", debugstr_w(pszRealm), ppszUsername);
799 if (ppszUsername)
800 *ppszUsername = NULL;
801 return ERROR_NOT_FOUND;