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
32 #include "credui_resources.h"
34 #include "wine/debug.h"
35 #include "wine/list.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(credui
);
39 #define TOOLID_INCORRECTPASSWORD 1
40 #define TOOLID_CAPSLOCKON 2
42 #define ID_CAPSLOCKPOP 1
44 struct pending_credentials
53 static HINSTANCE hinstCredUI
;
55 static struct list pending_credentials_list
= LIST_INIT(pending_credentials_list
);
57 static CRITICAL_SECTION csPendingCredentials
;
58 static CRITICAL_SECTION_DEBUG critsect_debug
=
60 0, 0, &csPendingCredentials
,
61 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
62 0, 0, { (DWORD_PTR
)(__FILE__
": csPendingCredentials") }
64 static CRITICAL_SECTION csPendingCredentials
= { &critsect_debug
, -1, 0, 0, 0, 0 };
67 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
69 struct pending_credentials
*entry
, *cursor2
;
70 TRACE("(0x%p, %d, %p)\n",hinstDLL
,fdwReason
,lpvReserved
);
74 case DLL_WINE_PREATTACH
:
75 return FALSE
; /* prefer native version */
77 case DLL_PROCESS_ATTACH
:
78 DisableThreadLibraryCalls(hinstDLL
);
79 hinstCredUI
= hinstDLL
;
83 case DLL_PROCESS_DETACH
:
84 if (lpvReserved
) break;
85 LIST_FOR_EACH_ENTRY_SAFE(entry
, cursor2
, &pending_credentials_list
, struct pending_credentials
, entry
)
87 list_remove(&entry
->entry
);
89 HeapFree(GetProcessHeap(), 0, entry
->pszTargetName
);
90 HeapFree(GetProcessHeap(), 0, entry
->pszUsername
);
91 SecureZeroMemory(entry
->pszPassword
, lstrlenW(entry
->pszPassword
) * sizeof(WCHAR
));
92 HeapFree(GetProcessHeap(), 0, entry
->pszPassword
);
93 HeapFree(GetProcessHeap(), 0, entry
);
95 DeleteCriticalSection(&csPendingCredentials
);
102 static DWORD
save_credentials(PCWSTR pszTargetName
, PCWSTR pszUsername
,
103 PCWSTR pszPassword
, BOOL generic
)
107 TRACE("saving servername %s with username %s\n", debugstr_w(pszTargetName
), debugstr_w(pszUsername
));
110 cred
.Type
= generic
? CRED_TYPE_GENERIC
: CRED_TYPE_DOMAIN_PASSWORD
;
111 cred
.TargetName
= (LPWSTR
)pszTargetName
;
113 cred
.CredentialBlobSize
= lstrlenW(pszPassword
) * sizeof(WCHAR
);
114 cred
.CredentialBlob
= (LPBYTE
)pszPassword
;
115 cred
.Persist
= CRED_PERSIST_ENTERPRISE
;
116 cred
.AttributeCount
= 0;
117 cred
.Attributes
= NULL
;
118 cred
.TargetAlias
= NULL
;
119 cred
.UserName
= (LPWSTR
)pszUsername
;
121 if (CredWriteW(&cred
, 0))
122 return ERROR_SUCCESS
;
125 DWORD ret
= GetLastError();
126 ERR("CredWriteW failed with error %d\n", ret
);
131 struct cred_dialog_params
133 PCWSTR pszTargetName
;
134 PCWSTR pszMessageText
;
135 PCWSTR pszCaptionText
;
138 ULONG ulUsernameMaxChars
;
140 ULONG ulPasswordMaxChars
;
144 BOOL fBalloonTipActive
;
147 static void CredDialogFillUsernameCombo(HWND hwndUsername
, const struct cred_dialog_params
*params
)
151 PCREDENTIALW
*credentials
;
153 if (!CredEnumerateW(NULL
, 0, &count
, &credentials
))
156 for (i
= 0; i
< count
; i
++)
158 COMBOBOXEXITEMW comboitem
;
160 BOOL duplicate
= FALSE
;
162 if (!credentials
[i
]->UserName
)
165 if (params
->dwFlags
& CREDUI_FLAGS_GENERIC_CREDENTIALS
)
167 if (credentials
[i
]->Type
!= CRED_TYPE_GENERIC
)
169 credentials
[i
]->UserName
= NULL
;
173 else if (credentials
[i
]->Type
== CRED_TYPE_GENERIC
)
175 credentials
[i
]->UserName
= NULL
;
179 /* don't add another item with the same name if we've already added it */
180 for (j
= 0; j
< i
; j
++)
181 if (credentials
[j
]->UserName
182 && !lstrcmpW(credentials
[i
]->UserName
, credentials
[j
]->UserName
))
191 comboitem
.mask
= CBEIF_TEXT
;
192 comboitem
.iItem
= -1;
193 comboitem
.pszText
= credentials
[i
]->UserName
;
194 SendMessageW(hwndUsername
, CBEM_INSERTITEMW
, 0, (LPARAM
)&comboitem
);
197 CredFree(credentials
);
200 static void CredDialogCreateBalloonTip(HWND hwndDlg
, struct cred_dialog_params
*params
)
202 TTTOOLINFOW toolinfo
;
205 if (params
->hwndBalloonTip
)
208 params
->hwndBalloonTip
= CreateWindowExW(WS_EX_TOOLWINDOW
, TOOLTIPS_CLASSW
,
209 NULL
, WS_POPUP
| TTS_NOPREFIX
| TTS_BALLOON
, CW_USEDEFAULT
,
210 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, hwndDlg
, NULL
,
212 SetWindowPos(params
->hwndBalloonTip
, HWND_TOPMOST
, 0, 0, 0, 0,
213 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
215 if (!LoadStringW(hinstCredUI
, IDS_INCORRECTPASSWORD
, wszText
, ARRAY_SIZE(wszText
)))
217 ERR("failed to load IDS_INCORRECTPASSWORD\n");
221 toolinfo
.cbSize
= sizeof(toolinfo
);
222 toolinfo
.uFlags
= TTF_TRACK
;
223 toolinfo
.hwnd
= hwndDlg
;
224 toolinfo
.uId
= TOOLID_INCORRECTPASSWORD
;
225 SetRectEmpty(&toolinfo
.rect
);
226 toolinfo
.hinst
= NULL
;
227 toolinfo
.lpszText
= wszText
;
229 toolinfo
.lpReserved
= NULL
;
230 SendMessageW(params
->hwndBalloonTip
, TTM_ADDTOOLW
, 0, (LPARAM
)&toolinfo
);
232 if (!LoadStringW(hinstCredUI
, IDS_CAPSLOCKON
, wszText
, ARRAY_SIZE(wszText
)))
234 ERR("failed to load IDS_CAPSLOCKON\n");
238 toolinfo
.uId
= TOOLID_CAPSLOCKON
;
239 SendMessageW(params
->hwndBalloonTip
, TTM_ADDTOOLW
, 0, (LPARAM
)&toolinfo
);
242 static void CredDialogShowIncorrectPasswordBalloon(HWND hwndDlg
, struct cred_dialog_params
*params
)
244 TTTOOLINFOW toolinfo
;
250 /* user name likely wrong so balloon would be confusing. focus is also
251 * not set to the password edit box, so more notification would need to be
253 if (!params
->pszUsername
[0])
256 /* don't show two balloon tips at once */
257 if (params
->fBalloonTipActive
)
260 if (!LoadStringW(hinstCredUI
, IDS_INCORRECTPASSWORDTITLE
, wszTitle
, ARRAY_SIZE(wszTitle
)))
262 ERR("failed to load IDS_INCORRECTPASSWORDTITLE\n");
266 CredDialogCreateBalloonTip(hwndDlg
, params
);
268 memset(&toolinfo
, 0, sizeof(toolinfo
));
269 toolinfo
.cbSize
= sizeof(toolinfo
);
270 toolinfo
.hwnd
= hwndDlg
;
271 toolinfo
.uId
= TOOLID_INCORRECTPASSWORD
;
273 SendMessageW(params
->hwndBalloonTip
, TTM_SETTITLEW
, TTI_ERROR
, (LPARAM
)wszTitle
);
275 GetWindowRect(GetDlgItem(hwndDlg
, IDC_PASSWORD
), &rcPassword
);
276 /* centered vertically and in the right side of the password edit control */
277 x
= rcPassword
.right
- 12;
278 y
= (rcPassword
.top
+ rcPassword
.bottom
) / 2;
279 SendMessageW(params
->hwndBalloonTip
, TTM_TRACKPOSITION
, 0, MAKELONG(x
, y
));
281 SendMessageW(params
->hwndBalloonTip
, TTM_TRACKACTIVATE
, TRUE
, (LPARAM
)&toolinfo
);
283 params
->fBalloonTipActive
= TRUE
;
286 static void CredDialogShowCapsLockBalloon(HWND hwndDlg
, struct cred_dialog_params
*params
)
288 TTTOOLINFOW toolinfo
;
294 /* don't show two balloon tips at once */
295 if (params
->fBalloonTipActive
)
298 if (!LoadStringW(hinstCredUI
, IDS_CAPSLOCKONTITLE
, wszTitle
, ARRAY_SIZE(wszTitle
)))
300 ERR("failed to load IDS_IDSCAPSLOCKONTITLE\n");
304 CredDialogCreateBalloonTip(hwndDlg
, params
);
306 memset(&toolinfo
, 0, sizeof(toolinfo
));
307 toolinfo
.cbSize
= sizeof(toolinfo
);
308 toolinfo
.hwnd
= hwndDlg
;
309 toolinfo
.uId
= TOOLID_CAPSLOCKON
;
311 SendMessageW(params
->hwndBalloonTip
, TTM_SETTITLEW
, TTI_WARNING
, (LPARAM
)wszTitle
);
313 GetWindowRect(GetDlgItem(hwndDlg
, IDC_PASSWORD
), &rcPassword
);
314 /* just inside the left side of the password edit control */
315 x
= rcPassword
.left
+ 12;
316 y
= rcPassword
.bottom
- 3;
317 SendMessageW(params
->hwndBalloonTip
, TTM_TRACKPOSITION
, 0, MAKELONG(x
, y
));
319 SendMessageW(params
->hwndBalloonTip
, TTM_TRACKACTIVATE
, TRUE
, (LPARAM
)&toolinfo
);
321 SetTimer(hwndDlg
, ID_CAPSLOCKPOP
,
322 SendMessageW(params
->hwndBalloonTip
, TTM_GETDELAYTIME
, TTDT_AUTOPOP
, 0),
325 params
->fBalloonTipActive
= TRUE
;
328 static void CredDialogHideBalloonTip(HWND hwndDlg
, struct cred_dialog_params
*params
)
330 TTTOOLINFOW toolinfo
;
332 if (!params
->hwndBalloonTip
)
335 memset(&toolinfo
, 0, sizeof(toolinfo
));
337 toolinfo
.cbSize
= sizeof(toolinfo
);
338 toolinfo
.hwnd
= hwndDlg
;
340 SendMessageW(params
->hwndBalloonTip
, TTM_TRACKACTIVATE
, FALSE
, (LPARAM
)&toolinfo
);
342 SendMessageW(params
->hwndBalloonTip
, TTM_TRACKACTIVATE
, FALSE
, (LPARAM
)&toolinfo
);
344 params
->fBalloonTipActive
= FALSE
;
347 static inline BOOL
CredDialogCapsLockOn(void)
349 return (GetKeyState(VK_CAPITAL
) & 0x1) != 0;
352 static LRESULT CALLBACK
CredDialogPasswordSubclassProc(HWND hwnd
, UINT uMsg
,
353 WPARAM wParam
, LPARAM lParam
, UINT_PTR uIdSubclass
, DWORD_PTR dwRefData
)
355 struct cred_dialog_params
*params
= (struct cred_dialog_params
*)dwRefData
;
359 if (wParam
== VK_CAPITAL
)
361 HWND hwndDlg
= GetParent(hwnd
);
362 if (CredDialogCapsLockOn())
363 CredDialogShowCapsLockBalloon(hwndDlg
, params
);
365 CredDialogHideBalloonTip(hwndDlg
, params
);
369 RemoveWindowSubclass(hwnd
, CredDialogPasswordSubclassProc
, uIdSubclass
);
372 return DefSubclassProc(hwnd
, uMsg
, wParam
, lParam
);
375 static BOOL
CredDialogInit(HWND hwndDlg
, struct cred_dialog_params
*params
)
377 HWND hwndUsername
= GetDlgItem(hwndDlg
, IDC_USERNAME
);
378 HWND hwndPassword
= GetDlgItem(hwndDlg
, IDC_PASSWORD
);
380 SetWindowLongPtrW(hwndDlg
, DWLP_USER
, (LONG_PTR
)params
);
382 if (params
->hbmBanner
)
383 SendMessageW(GetDlgItem(hwndDlg
, IDB_BANNER
), STM_SETIMAGE
,
384 IMAGE_BITMAP
, (LPARAM
)params
->hbmBanner
);
386 if (params
->pszMessageText
)
387 SetDlgItemTextW(hwndDlg
, IDC_MESSAGE
, params
->pszMessageText
);
392 LoadStringW(hinstCredUI
, IDS_MESSAGEFORMAT
, format
, ARRAY_SIZE(format
));
393 swprintf(message
, ARRAY_SIZE(message
), format
, params
->pszTargetName
);
394 SetDlgItemTextW(hwndDlg
, IDC_MESSAGE
, message
);
396 SetWindowTextW(hwndUsername
, params
->pszUsername
);
397 SetWindowTextW(hwndPassword
, params
->pszPassword
);
399 CredDialogFillUsernameCombo(hwndUsername
, params
);
401 if (params
->pszUsername
[0])
403 /* prevent showing a balloon tip here */
404 params
->fBalloonTipActive
= TRUE
;
405 SetFocus(hwndPassword
);
406 params
->fBalloonTipActive
= FALSE
;
409 SetFocus(hwndUsername
);
411 if (params
->pszCaptionText
)
412 SetWindowTextW(hwndDlg
, params
->pszCaptionText
);
417 LoadStringW(hinstCredUI
, IDS_TITLEFORMAT
, format
, ARRAY_SIZE(format
));
418 swprintf(title
, ARRAY_SIZE(title
), format
, params
->pszTargetName
);
419 SetWindowTextW(hwndDlg
, title
);
422 if (params
->dwFlags
& CREDUI_FLAGS_PERSIST
||
423 (params
->dwFlags
& CREDUI_FLAGS_DO_NOT_PERSIST
&&
424 !(params
->dwFlags
& CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX
)))
425 ShowWindow(GetDlgItem(hwndDlg
, IDC_SAVE
), SW_HIDE
);
426 else if (params
->fSave
)
427 CheckDlgButton(hwndDlg
, IDC_SAVE
, BST_CHECKED
);
429 /* setup subclassing for Caps Lock detection */
430 SetWindowSubclass(hwndPassword
, CredDialogPasswordSubclassProc
, 1, (DWORD_PTR
)params
);
432 if (params
->dwFlags
& CREDUI_FLAGS_INCORRECT_PASSWORD
)
433 CredDialogShowIncorrectPasswordBalloon(hwndDlg
, params
);
434 else if ((GetFocus() == hwndPassword
) && CredDialogCapsLockOn())
435 CredDialogShowCapsLockBalloon(hwndDlg
, params
);
440 static void CredDialogCommandOk(HWND hwndDlg
, struct cred_dialog_params
*params
)
442 HWND hwndUsername
= GetDlgItem(hwndDlg
, IDC_USERNAME
);
447 len
= GetWindowTextLengthW(hwndUsername
);
448 user
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
449 GetWindowTextW(hwndUsername
, user
, len
+ 1);
453 HeapFree(GetProcessHeap(), 0, user
);
457 if (!wcschr(user
, '\\') && !wcschr(user
, '@'))
459 ULONG len_target
= lstrlenW(params
->pszTargetName
);
460 memcpy(params
->pszUsername
, params
->pszTargetName
,
461 min(len_target
, params
->ulUsernameMaxChars
) * sizeof(WCHAR
));
462 if (len_target
+ 1 < params
->ulUsernameMaxChars
)
463 params
->pszUsername
[len_target
] = '\\';
464 if (len_target
+ 2 < params
->ulUsernameMaxChars
)
465 params
->pszUsername
[len_target
+ 1] = '\0';
467 else if (params
->ulUsernameMaxChars
> 0)
468 params
->pszUsername
[0] = '\0';
470 len2
= lstrlenW(params
->pszUsername
);
471 memcpy(params
->pszUsername
+ len2
, user
, min(len
, params
->ulUsernameMaxChars
- len2
) * sizeof(WCHAR
));
472 if (params
->ulUsernameMaxChars
)
473 params
->pszUsername
[len2
+ min(len
, params
->ulUsernameMaxChars
- len2
- 1)] = '\0';
475 HeapFree(GetProcessHeap(), 0, user
);
477 GetDlgItemTextW(hwndDlg
, IDC_PASSWORD
, params
->pszPassword
,
478 params
->ulPasswordMaxChars
);
480 params
->fSave
= IsDlgButtonChecked(hwndDlg
, IDC_SAVE
) == BST_CHECKED
;
482 EndDialog(hwndDlg
, IDOK
);
485 static INT_PTR CALLBACK
CredDialogProc(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
,
492 struct cred_dialog_params
*params
= (struct cred_dialog_params
*)lParam
;
494 return CredDialogInit(hwndDlg
, params
);
499 case MAKELONG(IDOK
, BN_CLICKED
):
501 struct cred_dialog_params
*params
=
502 (struct cred_dialog_params
*)GetWindowLongPtrW(hwndDlg
, DWLP_USER
);
503 CredDialogCommandOk(hwndDlg
, params
);
506 case MAKELONG(IDCANCEL
, BN_CLICKED
):
507 EndDialog(hwndDlg
, IDCANCEL
);
509 case MAKELONG(IDC_PASSWORD
, EN_SETFOCUS
):
510 if (CredDialogCapsLockOn())
512 struct cred_dialog_params
*params
=
513 (struct cred_dialog_params
*)GetWindowLongPtrW(hwndDlg
, DWLP_USER
);
514 CredDialogShowCapsLockBalloon(hwndDlg
, params
);
516 /* don't allow another window to steal focus while the
517 * user is typing their password */
518 LockSetForegroundWindow(LSFW_LOCK
);
520 case MAKELONG(IDC_PASSWORD
, EN_KILLFOCUS
):
522 struct cred_dialog_params
*params
=
523 (struct cred_dialog_params
*)GetWindowLongPtrW(hwndDlg
, DWLP_USER
);
524 /* the user is no longer typing their password, so allow
525 * other windows to become foreground ones */
526 LockSetForegroundWindow(LSFW_UNLOCK
);
527 CredDialogHideBalloonTip(hwndDlg
, params
);
530 case MAKELONG(IDC_PASSWORD
, EN_CHANGE
):
532 struct cred_dialog_params
*params
=
533 (struct cred_dialog_params
*)GetWindowLongPtrW(hwndDlg
, DWLP_USER
);
534 CredDialogHideBalloonTip(hwndDlg
, params
);
540 if (wParam
== ID_CAPSLOCKPOP
)
542 struct cred_dialog_params
*params
=
543 (struct cred_dialog_params
*)GetWindowLongPtrW(hwndDlg
, DWLP_USER
);
544 CredDialogHideBalloonTip(hwndDlg
, params
);
550 struct cred_dialog_params
*params
=
551 (struct cred_dialog_params
*)GetWindowLongPtrW(hwndDlg
, DWLP_USER
);
552 if (params
->hwndBalloonTip
) DestroyWindow(params
->hwndBalloonTip
);
560 static BOOL
find_existing_credential(const WCHAR
*target
, WCHAR
*username
, ULONG len_username
,
561 WCHAR
*password
, ULONG len_password
)
564 CREDENTIALW
**credentials
;
566 if (!CredEnumerateW(target
, 0, &count
, &credentials
)) return FALSE
;
567 for (i
= 0; i
< count
; i
++)
569 if (credentials
[i
]->Type
!= CRED_TYPE_DOMAIN_PASSWORD
&&
570 credentials
[i
]->Type
!= CRED_TYPE_GENERIC
)
572 FIXME("no support for type %u credentials\n", credentials
[i
]->Type
);
575 if ((!*username
|| !lstrcmpW(username
, credentials
[i
]->UserName
)) &&
576 lstrlenW(credentials
[i
]->UserName
) < len_username
&&
577 credentials
[i
]->CredentialBlobSize
/ sizeof(WCHAR
) < len_password
)
579 TRACE("found existing credential for %s\n", debugstr_w(credentials
[i
]->UserName
));
581 lstrcpyW(username
, credentials
[i
]->UserName
);
582 memcpy(password
, credentials
[i
]->CredentialBlob
, credentials
[i
]->CredentialBlobSize
);
583 password
[credentials
[i
]->CredentialBlobSize
/ sizeof(WCHAR
)] = 0;
585 CredFree(credentials
);
589 CredFree(credentials
);
593 /******************************************************************************
594 * CredUIPromptForCredentialsW [CREDUI.@]
596 DWORD WINAPI
CredUIPromptForCredentialsW(PCREDUI_INFOW pUIInfo
,
597 PCWSTR pszTargetName
,
598 PCtxtHandle Reserved
,
601 ULONG ulUsernameMaxChars
,
603 ULONG ulPasswordMaxChars
, PBOOL pfSave
,
607 struct cred_dialog_params params
;
608 DWORD result
= ERROR_SUCCESS
;
610 TRACE("(%p, %s, %p, %d, %s, %d, %p, %d, %p, 0x%08x)\n", pUIInfo
,
611 debugstr_w(pszTargetName
), Reserved
, dwAuthError
, debugstr_w(pszUsername
),
612 ulUsernameMaxChars
, pszPassword
, ulPasswordMaxChars
, pfSave
, dwFlags
);
614 if ((dwFlags
& (CREDUI_FLAGS_ALWAYS_SHOW_UI
|CREDUI_FLAGS_GENERIC_CREDENTIALS
)) == CREDUI_FLAGS_ALWAYS_SHOW_UI
)
615 return ERROR_INVALID_FLAGS
;
618 return ERROR_INVALID_PARAMETER
;
620 if ((dwFlags
& CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX
) && !pfSave
)
621 return ERROR_INVALID_PARAMETER
;
623 if (!(dwFlags
& CREDUI_FLAGS_ALWAYS_SHOW_UI
) &&
624 !(dwFlags
& CREDUI_FLAGS_INCORRECT_PASSWORD
) &&
625 find_existing_credential(pszTargetName
, pszUsername
, ulUsernameMaxChars
, pszPassword
, ulPasswordMaxChars
))
626 return ERROR_SUCCESS
;
628 params
.pszTargetName
= pszTargetName
;
631 params
.pszMessageText
= pUIInfo
->pszMessageText
;
632 params
.pszCaptionText
= pUIInfo
->pszCaptionText
;
633 params
.hbmBanner
= pUIInfo
->hbmBanner
;
637 params
.pszMessageText
= NULL
;
638 params
.pszCaptionText
= NULL
;
639 params
.hbmBanner
= NULL
;
641 params
.pszUsername
= pszUsername
;
642 params
.ulUsernameMaxChars
= ulUsernameMaxChars
;
643 params
.pszPassword
= pszPassword
;
644 params
.ulPasswordMaxChars
= ulPasswordMaxChars
;
645 params
.fSave
= pfSave
? *pfSave
: FALSE
;
646 params
.dwFlags
= dwFlags
;
647 params
.hwndBalloonTip
= NULL
;
648 params
.fBalloonTipActive
= FALSE
;
650 ret
= DialogBoxParamW(hinstCredUI
, MAKEINTRESOURCEW(IDD_CREDDIALOG
),
651 pUIInfo
? pUIInfo
->hwndParent
: NULL
,
652 CredDialogProc
, (LPARAM
)¶ms
);
654 return GetLastError();
658 TRACE("dialog cancelled\n");
659 return ERROR_CANCELLED
;
663 *pfSave
= params
.fSave
;
667 if (dwFlags
& CREDUI_FLAGS_EXPECT_CONFIRMATION
)
670 struct pending_credentials
*entry
;
673 EnterCriticalSection(&csPendingCredentials
);
675 /* find existing pending credentials for the same target and overwrite */
676 /* FIXME: is this correct? */
677 LIST_FOR_EACH_ENTRY(entry
, &pending_credentials_list
, struct pending_credentials
, entry
)
678 if (!lstrcmpW(pszTargetName
, entry
->pszTargetName
))
681 HeapFree(GetProcessHeap(), 0, entry
->pszUsername
);
682 SecureZeroMemory(entry
->pszPassword
, lstrlenW(entry
->pszPassword
) * sizeof(WCHAR
));
683 HeapFree(GetProcessHeap(), 0, entry
->pszPassword
);
688 entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*entry
));
689 len
= lstrlenW(pszTargetName
);
690 entry
->pszTargetName
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1)*sizeof(WCHAR
));
691 memcpy(entry
->pszTargetName
, pszTargetName
, (len
+ 1)*sizeof(WCHAR
));
692 list_add_tail(&pending_credentials_list
, &entry
->entry
);
695 len
= lstrlenW(params
.pszUsername
);
696 entry
->pszUsername
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1)*sizeof(WCHAR
));
697 memcpy(entry
->pszUsername
, params
.pszUsername
, (len
+ 1)*sizeof(WCHAR
));
698 len
= lstrlenW(params
.pszPassword
);
699 entry
->pszPassword
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1)*sizeof(WCHAR
));
700 memcpy(entry
->pszPassword
, params
.pszPassword
, (len
+ 1)*sizeof(WCHAR
));
701 entry
->generic
= (dwFlags
& CREDUI_FLAGS_GENERIC_CREDENTIALS
) != 0;
703 LeaveCriticalSection(&csPendingCredentials
);
705 else if (!(dwFlags
& CREDUI_FLAGS_DO_NOT_PERSIST
))
706 result
= save_credentials(pszTargetName
, pszUsername
, pszPassword
,
707 (dwFlags
& CREDUI_FLAGS_GENERIC_CREDENTIALS
) != 0);
713 /******************************************************************************
714 * CredUIConfirmCredentialsW [CREDUI.@]
716 DWORD WINAPI
CredUIConfirmCredentialsW(PCWSTR pszTargetName
, BOOL bConfirm
)
718 struct pending_credentials
*entry
;
719 DWORD result
= ERROR_NOT_FOUND
;
721 TRACE("(%s, %s)\n", debugstr_w(pszTargetName
), bConfirm
? "TRUE" : "FALSE");
724 return ERROR_INVALID_PARAMETER
;
726 EnterCriticalSection(&csPendingCredentials
);
728 LIST_FOR_EACH_ENTRY(entry
, &pending_credentials_list
, struct pending_credentials
, entry
)
730 if (!lstrcmpW(pszTargetName
, entry
->pszTargetName
))
733 result
= save_credentials(entry
->pszTargetName
, entry
->pszUsername
,
734 entry
->pszPassword
, entry
->generic
);
736 result
= ERROR_SUCCESS
;
738 list_remove(&entry
->entry
);
740 HeapFree(GetProcessHeap(), 0, entry
->pszTargetName
);
741 HeapFree(GetProcessHeap(), 0, entry
->pszUsername
);
742 SecureZeroMemory(entry
->pszPassword
, lstrlenW(entry
->pszPassword
) * sizeof(WCHAR
));
743 HeapFree(GetProcessHeap(), 0, entry
->pszPassword
);
744 HeapFree(GetProcessHeap(), 0, entry
);
750 LeaveCriticalSection(&csPendingCredentials
);
755 /******************************************************************************
756 * CredUIParseUserNameW [CREDUI.@]
758 DWORD WINAPI
CredUIParseUserNameW(PCWSTR pszUserName
, PWSTR pszUser
,
759 ULONG ulMaxUserChars
, PWSTR pszDomain
,
760 ULONG ulMaxDomainChars
)
764 TRACE("(%s, %p, %d, %p, %d)\n", debugstr_w(pszUserName
), pszUser
,
765 ulMaxUserChars
, pszDomain
, ulMaxDomainChars
);
767 if (!pszUserName
|| !pszUser
|| !ulMaxUserChars
|| !pszDomain
||
769 return ERROR_INVALID_PARAMETER
;
771 /* FIXME: handle marshaled credentials */
773 p
= wcschr(pszUserName
, '\\');
776 if (p
- pszUserName
> ulMaxDomainChars
- 1)
777 return ERROR_INSUFFICIENT_BUFFER
;
778 if (lstrlenW(p
+ 1) > ulMaxUserChars
- 1)
779 return ERROR_INSUFFICIENT_BUFFER
;
780 lstrcpyW(pszUser
, p
+ 1);
781 memcpy(pszDomain
, pszUserName
, (p
- pszUserName
)*sizeof(WCHAR
));
782 pszDomain
[p
- pszUserName
] = '\0';
784 return ERROR_SUCCESS
;
787 p
= wcsrchr(pszUserName
, '@');
790 if (p
+ 1 - pszUserName
> ulMaxUserChars
- 1)
791 return ERROR_INSUFFICIENT_BUFFER
;
792 if (lstrlenW(p
+ 1) > ulMaxDomainChars
- 1)
793 return ERROR_INSUFFICIENT_BUFFER
;
794 lstrcpyW(pszDomain
, p
+ 1);
795 memcpy(pszUser
, pszUserName
, (p
- pszUserName
)*sizeof(WCHAR
));
796 pszUser
[p
- pszUserName
] = '\0';
798 return ERROR_SUCCESS
;
801 if (lstrlenW(pszUserName
) > ulMaxUserChars
- 1)
802 return ERROR_INSUFFICIENT_BUFFER
;
803 lstrcpyW(pszUser
, pszUserName
);
806 return ERROR_SUCCESS
;
809 /******************************************************************************
810 * CredUIStoreSSOCredA [CREDUI.@]
812 DWORD WINAPI
CredUIStoreSSOCredA(PCSTR pszRealm
, PCSTR pszUsername
,
813 PCSTR pszPassword
, BOOL bPersist
)
815 FIXME("(%s, %s, %p, %d)\n", debugstr_a(pszRealm
), debugstr_a(pszUsername
),
816 pszPassword
, bPersist
);
817 return ERROR_SUCCESS
;
820 /******************************************************************************
821 * CredUIStoreSSOCredW [CREDUI.@]
823 DWORD WINAPI
CredUIStoreSSOCredW(PCWSTR pszRealm
, PCWSTR pszUsername
,
824 PCWSTR pszPassword
, BOOL bPersist
)
826 FIXME("(%s, %s, %p, %d)\n", debugstr_w(pszRealm
), debugstr_w(pszUsername
),
827 pszPassword
, bPersist
);
828 return ERROR_SUCCESS
;
831 /******************************************************************************
832 * CredUIReadSSOCredA [CREDUI.@]
834 DWORD WINAPI
CredUIReadSSOCredA(PCSTR pszRealm
, PSTR
*ppszUsername
)
836 FIXME("(%s, %p)\n", debugstr_a(pszRealm
), ppszUsername
);
838 *ppszUsername
= NULL
;
839 return ERROR_NOT_FOUND
;
842 /******************************************************************************
843 * CredUIReadSSOCredW [CREDUI.@]
845 DWORD WINAPI
CredUIReadSSOCredW(PCWSTR pszRealm
, PWSTR
*ppszUsername
)
847 FIXME("(%s, %p)\n", debugstr_w(pszRealm
), ppszUsername
);
849 *ppszUsername
= NULL
;
850 return ERROR_NOT_FOUND
;
853 /******************************************************************************
854 * CredUIInitControls [CREDUI.@]
856 BOOL WINAPI
CredUIInitControls(void)
862 /******************************************************************************
863 * SspiPromptForCredentialsW [CREDUI.@]
865 ULONG SEC_ENTRY
SspiPromptForCredentialsW( PCWSTR target
, void *info
,
866 DWORD error
, PCWSTR package
,
867 PSEC_WINNT_AUTH_IDENTITY_OPAQUE input_id
,
868 PSEC_WINNT_AUTH_IDENTITY_OPAQUE
*output_id
,
869 BOOL
*save
, DWORD sspi_flags
)
871 static const WCHAR basicW
[] = {'B','a','s','i','c',0};
872 static const WCHAR ntlmW
[] = {'N','T','L','M',0};
873 static const WCHAR negotiateW
[] = {'N','e','g','o','t','i','a','t','e',0};
874 WCHAR username
[CREDUI_MAX_USERNAME_LENGTH
+ 1] = {0};
875 WCHAR password
[CREDUI_MAX_PASSWORD_LENGTH
+ 1] = {0};
876 DWORD len_username
= ARRAY_SIZE(username
);
877 DWORD len_password
= ARRAY_SIZE(password
);
879 CREDUI_INFOW
*cred_info
= info
;
880 SEC_WINNT_AUTH_IDENTITY_W
*id
= input_id
;
882 FIXME( "(%s, %p, %u, %s, %p, %p, %p, %x) stub\n", debugstr_w(target
), info
,
883 error
, debugstr_w(package
), input_id
, output_id
, save
, sspi_flags
);
885 if (!target
) return ERROR_INVALID_PARAMETER
;
886 if (!package
|| (wcsicmp( package
, basicW
) && wcsicmp( package
, ntlmW
) &&
887 wcsicmp( package
, negotiateW
)))
889 FIXME( "package %s not supported\n", debugstr_w(package
) );
890 return ERROR_NO_SUCH_PACKAGE
;
893 flags
= CREDUI_FLAGS_ALWAYS_SHOW_UI
| CREDUI_FLAGS_GENERIC_CREDENTIALS
;
895 if (sspi_flags
& SSPIPFC_CREDPROV_DO_NOT_SAVE
)
896 flags
|= CREDUI_FLAGS_DO_NOT_PERSIST
;
898 if (!(sspi_flags
& SSPIPFC_NO_CHECKBOX
))
899 flags
|= CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX
;
901 if (!id
) find_existing_credential( target
, username
, len_username
, password
, len_password
);
904 if (id
->User
&& id
->UserLength
> 0 && id
->UserLength
<= CREDUI_MAX_USERNAME_LENGTH
)
906 memcpy( username
, id
->User
, id
->UserLength
* sizeof(WCHAR
) );
907 username
[id
->UserLength
] = 0;
909 if (id
->Password
&& id
->PasswordLength
> 0 && id
->PasswordLength
<= CREDUI_MAX_PASSWORD_LENGTH
)
911 memcpy( password
, id
->Password
, id
->PasswordLength
* sizeof(WCHAR
) );
912 password
[id
->PasswordLength
] = 0;
916 if (!(ret
= CredUIPromptForCredentialsW( cred_info
, target
, NULL
, error
, username
,
917 len_username
, password
, len_password
, save
, flags
)))
919 DWORD size
= sizeof(*id
), len_domain
= 0;
920 WCHAR
*ptr
, *user
= username
, *domain
= NULL
;
922 if ((ptr
= wcschr( username
, '\\' )))
925 len_username
= lstrlenW( user
);
926 if (!wcsicmp( package
, ntlmW
) || !wcsicmp( package
, negotiateW
))
929 len_domain
= ptr
- username
;
933 else len_username
= lstrlenW( username
);
934 len_password
= lstrlenW( password
);
936 size
+= (len_username
+ 1) * sizeof(WCHAR
);
937 size
+= (len_domain
+ 1) * sizeof(WCHAR
);
938 size
+= (len_password
+ 1) * sizeof(WCHAR
);
939 if (!(id
= HeapAlloc( GetProcessHeap(), 0, size
))) return ERROR_OUTOFMEMORY
;
940 ptr
= (WCHAR
*)(id
+ 1);
942 memcpy( ptr
, user
, (len_username
+ 1) * sizeof(WCHAR
) );
944 id
->UserLength
= len_username
;
945 ptr
+= len_username
+ 1;
948 memcpy( ptr
, domain
, (len_domain
+ 1) * sizeof(WCHAR
) );
950 id
->DomainLength
= len_domain
;
951 ptr
+= len_domain
+ 1;
956 id
->DomainLength
= 0;
958 memcpy( ptr
, password
, (len_password
+ 1) * sizeof(WCHAR
) );
960 id
->PasswordLength
= len_password
;
969 /******************************************************************************
970 * CredUIPromptForWindowsCredentialsW [CREDUI.@]
972 DWORD WINAPI
CredUIPromptForWindowsCredentialsW( CREDUI_INFOW
*info
, DWORD error
, ULONG
*package
,
973 const void *in_buf
, ULONG in_buf_size
, void **out_buf
,
974 ULONG
*out_buf_size
, BOOL
*save
, DWORD flags
)
976 FIXME( "(%p, %u, %p, %p, %u, %p, %p, %p, %08x) stub\n", info
, error
, package
, in_buf
, in_buf_size
,
977 out_buf
, out_buf_size
, save
, flags
);
978 return ERROR_CALL_NOT_IMPLEMENTED
;
981 /******************************************************************************
982 * CredPackAuthenticationBufferW [CREDUI.@]
984 BOOL WINAPI
CredPackAuthenticationBufferW( DWORD flags
, WCHAR
*username
, WCHAR
*password
, BYTE
*buf
,
987 FIXME( "(%08x, %s, %p, %p, %p) stub\n", flags
, debugstr_w(username
), password
, buf
, size
);
988 return ERROR_CALL_NOT_IMPLEMENTED
;
991 /******************************************************************************
992 * CredUnPackAuthenticationBufferW [CREDUI.@]
994 BOOL WINAPI
CredUnPackAuthenticationBufferW( DWORD flags
, void *buf
, DWORD size
, WCHAR
*username
,
995 DWORD
*len_username
, WCHAR
*domain
, DWORD
*len_domain
,
996 WCHAR
*password
, DWORD
*len_password
)
998 FIXME( "(%08x, %p, %u, %p, %p, %p, %p, %p, %p) stub\n", flags
, buf
, size
, username
, len_username
,
999 domain
, len_domain
, password
, len_password
);
1000 return ERROR_CALL_NOT_IMPLEMENTED
;