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/unicode.h"
36 #include "wine/list.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(credui
);
40 #define TOOLID_INCORRECTPASSWORD 1
41 #define TOOLID_CAPSLOCKON 2
43 #define ID_CAPSLOCKPOP 1
45 struct pending_credentials
54 static HINSTANCE hinstCredUI
;
56 static struct list pending_credentials_list
= LIST_INIT(pending_credentials_list
);
58 static CRITICAL_SECTION csPendingCredentials
;
59 static CRITICAL_SECTION_DEBUG critsect_debug
=
61 0, 0, &csPendingCredentials
,
62 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
63 0, 0, { (DWORD_PTR
)(__FILE__
": csPendingCredentials") }
65 static CRITICAL_SECTION csPendingCredentials
= { &critsect_debug
, -1, 0, 0, 0, 0 };
68 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
70 struct pending_credentials
*entry
, *cursor2
;
71 TRACE("(0x%p, %d, %p)\n",hinstDLL
,fdwReason
,lpvReserved
);
75 case DLL_WINE_PREATTACH
:
76 return FALSE
; /* prefer native version */
78 case DLL_PROCESS_ATTACH
:
79 DisableThreadLibraryCalls(hinstDLL
);
80 hinstCredUI
= hinstDLL
;
84 case DLL_PROCESS_DETACH
:
85 if (lpvReserved
) break;
86 LIST_FOR_EACH_ENTRY_SAFE(entry
, cursor2
, &pending_credentials_list
, struct pending_credentials
, entry
)
88 list_remove(&entry
->entry
);
90 HeapFree(GetProcessHeap(), 0, entry
->pszTargetName
);
91 HeapFree(GetProcessHeap(), 0, entry
->pszUsername
);
92 SecureZeroMemory(entry
->pszPassword
, strlenW(entry
->pszPassword
) * sizeof(WCHAR
));
93 HeapFree(GetProcessHeap(), 0, entry
->pszPassword
);
94 HeapFree(GetProcessHeap(), 0, entry
);
96 DeleteCriticalSection(&csPendingCredentials
);
103 static DWORD
save_credentials(PCWSTR pszTargetName
, PCWSTR pszUsername
,
104 PCWSTR pszPassword
, BOOL generic
)
108 TRACE("saving servername %s with username %s\n", debugstr_w(pszTargetName
), debugstr_w(pszUsername
));
111 cred
.Type
= generic
? CRED_TYPE_GENERIC
: CRED_TYPE_DOMAIN_PASSWORD
;
112 cred
.TargetName
= (LPWSTR
)pszTargetName
;
114 cred
.CredentialBlobSize
= strlenW(pszPassword
) * sizeof(WCHAR
);
115 cred
.CredentialBlob
= (LPBYTE
)pszPassword
;
116 cred
.Persist
= CRED_PERSIST_ENTERPRISE
;
117 cred
.AttributeCount
= 0;
118 cred
.Attributes
= NULL
;
119 cred
.TargetAlias
= NULL
;
120 cred
.UserName
= (LPWSTR
)pszUsername
;
122 if (CredWriteW(&cred
, 0))
123 return ERROR_SUCCESS
;
126 DWORD ret
= GetLastError();
127 ERR("CredWriteW failed with error %d\n", ret
);
132 struct cred_dialog_params
134 PCWSTR pszTargetName
;
135 PCWSTR pszMessageText
;
136 PCWSTR pszCaptionText
;
139 ULONG ulUsernameMaxChars
;
141 ULONG ulPasswordMaxChars
;
145 BOOL fBalloonTipActive
;
148 static void CredDialogFillUsernameCombo(HWND hwndUsername
, const struct cred_dialog_params
*params
)
152 PCREDENTIALW
*credentials
;
154 if (!CredEnumerateW(NULL
, 0, &count
, &credentials
))
157 for (i
= 0; i
< count
; i
++)
159 COMBOBOXEXITEMW comboitem
;
161 BOOL duplicate
= FALSE
;
163 if (!credentials
[i
]->UserName
)
166 if (params
->dwFlags
& CREDUI_FLAGS_GENERIC_CREDENTIALS
)
168 if (credentials
[i
]->Type
!= CRED_TYPE_GENERIC
)
170 credentials
[i
]->UserName
= NULL
;
174 else if (credentials
[i
]->Type
== CRED_TYPE_GENERIC
)
176 credentials
[i
]->UserName
= NULL
;
180 /* don't add another item with the same name if we've already added it */
181 for (j
= 0; j
< i
; j
++)
182 if (credentials
[j
]->UserName
183 && !strcmpW(credentials
[i
]->UserName
, credentials
[j
]->UserName
))
192 comboitem
.mask
= CBEIF_TEXT
;
193 comboitem
.iItem
= -1;
194 comboitem
.pszText
= credentials
[i
]->UserName
;
195 SendMessageW(hwndUsername
, CBEM_INSERTITEMW
, 0, (LPARAM
)&comboitem
);
198 CredFree(credentials
);
201 static void CredDialogCreateBalloonTip(HWND hwndDlg
, struct cred_dialog_params
*params
)
203 TTTOOLINFOW toolinfo
;
206 if (params
->hwndBalloonTip
)
209 params
->hwndBalloonTip
= CreateWindowExW(WS_EX_TOOLWINDOW
, TOOLTIPS_CLASSW
,
210 NULL
, WS_POPUP
| TTS_NOPREFIX
| TTS_BALLOON
, CW_USEDEFAULT
,
211 CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, hwndDlg
, NULL
,
213 SetWindowPos(params
->hwndBalloonTip
, HWND_TOPMOST
, 0, 0, 0, 0,
214 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
216 if (!LoadStringW(hinstCredUI
, IDS_INCORRECTPASSWORD
, wszText
, ARRAY_SIZE(wszText
)))
218 ERR("failed to load IDS_INCORRECTPASSWORD\n");
222 toolinfo
.cbSize
= sizeof(toolinfo
);
223 toolinfo
.uFlags
= TTF_TRACK
;
224 toolinfo
.hwnd
= hwndDlg
;
225 toolinfo
.uId
= TOOLID_INCORRECTPASSWORD
;
226 SetRectEmpty(&toolinfo
.rect
);
227 toolinfo
.hinst
= NULL
;
228 toolinfo
.lpszText
= wszText
;
230 toolinfo
.lpReserved
= NULL
;
231 SendMessageW(params
->hwndBalloonTip
, TTM_ADDTOOLW
, 0, (LPARAM
)&toolinfo
);
233 if (!LoadStringW(hinstCredUI
, IDS_CAPSLOCKON
, wszText
, ARRAY_SIZE(wszText
)))
235 ERR("failed to load IDS_CAPSLOCKON\n");
239 toolinfo
.uId
= TOOLID_CAPSLOCKON
;
240 SendMessageW(params
->hwndBalloonTip
, TTM_ADDTOOLW
, 0, (LPARAM
)&toolinfo
);
243 static void CredDialogShowIncorrectPasswordBalloon(HWND hwndDlg
, struct cred_dialog_params
*params
)
245 TTTOOLINFOW toolinfo
;
251 /* user name likely wrong so balloon would be confusing. focus is also
252 * not set to the password edit box, so more notification would need to be
254 if (!params
->pszUsername
[0])
257 /* don't show two balloon tips at once */
258 if (params
->fBalloonTipActive
)
261 if (!LoadStringW(hinstCredUI
, IDS_INCORRECTPASSWORDTITLE
, wszTitle
, ARRAY_SIZE(wszTitle
)))
263 ERR("failed to load IDS_INCORRECTPASSWORDTITLE\n");
267 CredDialogCreateBalloonTip(hwndDlg
, params
);
269 memset(&toolinfo
, 0, sizeof(toolinfo
));
270 toolinfo
.cbSize
= sizeof(toolinfo
);
271 toolinfo
.hwnd
= hwndDlg
;
272 toolinfo
.uId
= TOOLID_INCORRECTPASSWORD
;
274 SendMessageW(params
->hwndBalloonTip
, TTM_SETTITLEW
, TTI_ERROR
, (LPARAM
)wszTitle
);
276 GetWindowRect(GetDlgItem(hwndDlg
, IDC_PASSWORD
), &rcPassword
);
277 /* centered vertically and in the right side of the password edit control */
278 x
= rcPassword
.right
- 12;
279 y
= (rcPassword
.top
+ rcPassword
.bottom
) / 2;
280 SendMessageW(params
->hwndBalloonTip
, TTM_TRACKPOSITION
, 0, MAKELONG(x
, y
));
282 SendMessageW(params
->hwndBalloonTip
, TTM_TRACKACTIVATE
, TRUE
, (LPARAM
)&toolinfo
);
284 params
->fBalloonTipActive
= TRUE
;
287 static void CredDialogShowCapsLockBalloon(HWND hwndDlg
, struct cred_dialog_params
*params
)
289 TTTOOLINFOW toolinfo
;
295 /* don't show two balloon tips at once */
296 if (params
->fBalloonTipActive
)
299 if (!LoadStringW(hinstCredUI
, IDS_CAPSLOCKONTITLE
, wszTitle
, ARRAY_SIZE(wszTitle
)))
301 ERR("failed to load IDS_IDSCAPSLOCKONTITLE\n");
305 CredDialogCreateBalloonTip(hwndDlg
, params
);
307 memset(&toolinfo
, 0, sizeof(toolinfo
));
308 toolinfo
.cbSize
= sizeof(toolinfo
);
309 toolinfo
.hwnd
= hwndDlg
;
310 toolinfo
.uId
= TOOLID_CAPSLOCKON
;
312 SendMessageW(params
->hwndBalloonTip
, TTM_SETTITLEW
, TTI_WARNING
, (LPARAM
)wszTitle
);
314 GetWindowRect(GetDlgItem(hwndDlg
, IDC_PASSWORD
), &rcPassword
);
315 /* just inside the left side of the password edit control */
316 x
= rcPassword
.left
+ 12;
317 y
= rcPassword
.bottom
- 3;
318 SendMessageW(params
->hwndBalloonTip
, TTM_TRACKPOSITION
, 0, MAKELONG(x
, y
));
320 SendMessageW(params
->hwndBalloonTip
, TTM_TRACKACTIVATE
, TRUE
, (LPARAM
)&toolinfo
);
322 SetTimer(hwndDlg
, ID_CAPSLOCKPOP
,
323 SendMessageW(params
->hwndBalloonTip
, TTM_GETDELAYTIME
, TTDT_AUTOPOP
, 0),
326 params
->fBalloonTipActive
= TRUE
;
329 static void CredDialogHideBalloonTip(HWND hwndDlg
, struct cred_dialog_params
*params
)
331 TTTOOLINFOW toolinfo
;
333 if (!params
->hwndBalloonTip
)
336 memset(&toolinfo
, 0, sizeof(toolinfo
));
338 toolinfo
.cbSize
= sizeof(toolinfo
);
339 toolinfo
.hwnd
= hwndDlg
;
341 SendMessageW(params
->hwndBalloonTip
, TTM_TRACKACTIVATE
, FALSE
, (LPARAM
)&toolinfo
);
343 SendMessageW(params
->hwndBalloonTip
, TTM_TRACKACTIVATE
, FALSE
, (LPARAM
)&toolinfo
);
345 params
->fBalloonTipActive
= FALSE
;
348 static inline BOOL
CredDialogCapsLockOn(void)
350 return (GetKeyState(VK_CAPITAL
) & 0x1) != 0;
353 static LRESULT CALLBACK
CredDialogPasswordSubclassProc(HWND hwnd
, UINT uMsg
,
354 WPARAM wParam
, LPARAM lParam
, UINT_PTR uIdSubclass
, DWORD_PTR dwRefData
)
356 struct cred_dialog_params
*params
= (struct cred_dialog_params
*)dwRefData
;
360 if (wParam
== VK_CAPITAL
)
362 HWND hwndDlg
= GetParent(hwnd
);
363 if (CredDialogCapsLockOn())
364 CredDialogShowCapsLockBalloon(hwndDlg
, params
);
366 CredDialogHideBalloonTip(hwndDlg
, params
);
370 RemoveWindowSubclass(hwnd
, CredDialogPasswordSubclassProc
, uIdSubclass
);
373 return DefSubclassProc(hwnd
, uMsg
, wParam
, lParam
);
376 static BOOL
CredDialogInit(HWND hwndDlg
, struct cred_dialog_params
*params
)
378 HWND hwndUsername
= GetDlgItem(hwndDlg
, IDC_USERNAME
);
379 HWND hwndPassword
= GetDlgItem(hwndDlg
, IDC_PASSWORD
);
381 SetWindowLongPtrW(hwndDlg
, DWLP_USER
, (LONG_PTR
)params
);
383 if (params
->hbmBanner
)
384 SendMessageW(GetDlgItem(hwndDlg
, IDB_BANNER
), STM_SETIMAGE
,
385 IMAGE_BITMAP
, (LPARAM
)params
->hbmBanner
);
387 if (params
->pszMessageText
)
388 SetDlgItemTextW(hwndDlg
, IDC_MESSAGE
, params
->pszMessageText
);
393 LoadStringW(hinstCredUI
, IDS_MESSAGEFORMAT
, format
, ARRAY_SIZE(format
));
394 snprintfW(message
, ARRAY_SIZE(message
), format
, params
->pszTargetName
);
395 SetDlgItemTextW(hwndDlg
, IDC_MESSAGE
, message
);
397 SetWindowTextW(hwndUsername
, params
->pszUsername
);
398 SetWindowTextW(hwndPassword
, params
->pszPassword
);
400 CredDialogFillUsernameCombo(hwndUsername
, params
);
402 if (params
->pszUsername
[0])
404 /* prevent showing a balloon tip here */
405 params
->fBalloonTipActive
= TRUE
;
406 SetFocus(hwndPassword
);
407 params
->fBalloonTipActive
= FALSE
;
410 SetFocus(hwndUsername
);
412 if (params
->pszCaptionText
)
413 SetWindowTextW(hwndDlg
, params
->pszCaptionText
);
418 LoadStringW(hinstCredUI
, IDS_TITLEFORMAT
, format
, ARRAY_SIZE(format
));
419 snprintfW(title
, ARRAY_SIZE(title
), format
, params
->pszTargetName
);
420 SetWindowTextW(hwndDlg
, title
);
423 if (params
->dwFlags
& CREDUI_FLAGS_PERSIST
||
424 (params
->dwFlags
& CREDUI_FLAGS_DO_NOT_PERSIST
&&
425 !(params
->dwFlags
& CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX
)))
426 ShowWindow(GetDlgItem(hwndDlg
, IDC_SAVE
), SW_HIDE
);
427 else if (params
->fSave
)
428 CheckDlgButton(hwndDlg
, IDC_SAVE
, BST_CHECKED
);
430 /* setup subclassing for Caps Lock detection */
431 SetWindowSubclass(hwndPassword
, CredDialogPasswordSubclassProc
, 1, (DWORD_PTR
)params
);
433 if (params
->dwFlags
& CREDUI_FLAGS_INCORRECT_PASSWORD
)
434 CredDialogShowIncorrectPasswordBalloon(hwndDlg
, params
);
435 else if ((GetFocus() == hwndPassword
) && CredDialogCapsLockOn())
436 CredDialogShowCapsLockBalloon(hwndDlg
, params
);
441 static void CredDialogCommandOk(HWND hwndDlg
, struct cred_dialog_params
*params
)
443 HWND hwndUsername
= GetDlgItem(hwndDlg
, IDC_USERNAME
);
448 len
= GetWindowTextLengthW(hwndUsername
);
449 user
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
450 GetWindowTextW(hwndUsername
, user
, len
+ 1);
454 HeapFree(GetProcessHeap(), 0, user
);
458 if (!strchrW(user
, '\\') && !strchrW(user
, '@'))
460 ULONG len_target
= strlenW(params
->pszTargetName
);
461 memcpy(params
->pszUsername
, params
->pszTargetName
,
462 min(len_target
, params
->ulUsernameMaxChars
) * sizeof(WCHAR
));
463 if (len_target
+ 1 < params
->ulUsernameMaxChars
)
464 params
->pszUsername
[len_target
] = '\\';
465 if (len_target
+ 2 < params
->ulUsernameMaxChars
)
466 params
->pszUsername
[len_target
+ 1] = '\0';
468 else if (params
->ulUsernameMaxChars
> 0)
469 params
->pszUsername
[0] = '\0';
471 len2
= strlenW(params
->pszUsername
);
472 memcpy(params
->pszUsername
+ len2
, user
, min(len
, params
->ulUsernameMaxChars
- len2
) * sizeof(WCHAR
));
473 if (params
->ulUsernameMaxChars
)
474 params
->pszUsername
[len2
+ min(len
, params
->ulUsernameMaxChars
- len2
- 1)] = '\0';
476 HeapFree(GetProcessHeap(), 0, user
);
478 GetDlgItemTextW(hwndDlg
, IDC_PASSWORD
, params
->pszPassword
,
479 params
->ulPasswordMaxChars
);
481 params
->fSave
= IsDlgButtonChecked(hwndDlg
, IDC_SAVE
) == BST_CHECKED
;
483 EndDialog(hwndDlg
, IDOK
);
486 static INT_PTR CALLBACK
CredDialogProc(HWND hwndDlg
, UINT uMsg
, WPARAM wParam
,
493 struct cred_dialog_params
*params
= (struct cred_dialog_params
*)lParam
;
495 return CredDialogInit(hwndDlg
, params
);
500 case MAKELONG(IDOK
, BN_CLICKED
):
502 struct cred_dialog_params
*params
=
503 (struct cred_dialog_params
*)GetWindowLongPtrW(hwndDlg
, DWLP_USER
);
504 CredDialogCommandOk(hwndDlg
, params
);
507 case MAKELONG(IDCANCEL
, BN_CLICKED
):
508 EndDialog(hwndDlg
, IDCANCEL
);
510 case MAKELONG(IDC_PASSWORD
, EN_SETFOCUS
):
511 if (CredDialogCapsLockOn())
513 struct cred_dialog_params
*params
=
514 (struct cred_dialog_params
*)GetWindowLongPtrW(hwndDlg
, DWLP_USER
);
515 CredDialogShowCapsLockBalloon(hwndDlg
, params
);
517 /* don't allow another window to steal focus while the
518 * user is typing their password */
519 LockSetForegroundWindow(LSFW_LOCK
);
521 case MAKELONG(IDC_PASSWORD
, EN_KILLFOCUS
):
523 struct cred_dialog_params
*params
=
524 (struct cred_dialog_params
*)GetWindowLongPtrW(hwndDlg
, DWLP_USER
);
525 /* the user is no longer typing their password, so allow
526 * other windows to become foreground ones */
527 LockSetForegroundWindow(LSFW_UNLOCK
);
528 CredDialogHideBalloonTip(hwndDlg
, params
);
531 case MAKELONG(IDC_PASSWORD
, EN_CHANGE
):
533 struct cred_dialog_params
*params
=
534 (struct cred_dialog_params
*)GetWindowLongPtrW(hwndDlg
, DWLP_USER
);
535 CredDialogHideBalloonTip(hwndDlg
, params
);
541 if (wParam
== ID_CAPSLOCKPOP
)
543 struct cred_dialog_params
*params
=
544 (struct cred_dialog_params
*)GetWindowLongPtrW(hwndDlg
, DWLP_USER
);
545 CredDialogHideBalloonTip(hwndDlg
, params
);
551 struct cred_dialog_params
*params
=
552 (struct cred_dialog_params
*)GetWindowLongPtrW(hwndDlg
, DWLP_USER
);
553 if (params
->hwndBalloonTip
) DestroyWindow(params
->hwndBalloonTip
);
561 static BOOL
find_existing_credential(const WCHAR
*target
, WCHAR
*username
, ULONG len_username
,
562 WCHAR
*password
, ULONG len_password
)
565 CREDENTIALW
**credentials
;
567 if (!CredEnumerateW(target
, 0, &count
, &credentials
)) return FALSE
;
568 for (i
= 0; i
< count
; i
++)
570 if (credentials
[i
]->Type
!= CRED_TYPE_DOMAIN_PASSWORD
&&
571 credentials
[i
]->Type
!= CRED_TYPE_GENERIC
)
573 FIXME("no support for type %u credentials\n", credentials
[i
]->Type
);
576 if ((!*username
|| !strcmpW(username
, credentials
[i
]->UserName
)) &&
577 strlenW(credentials
[i
]->UserName
) < len_username
&&
578 credentials
[i
]->CredentialBlobSize
/ sizeof(WCHAR
) < len_password
)
580 TRACE("found existing credential for %s\n", debugstr_w(credentials
[i
]->UserName
));
582 strcpyW(username
, credentials
[i
]->UserName
);
583 memcpy(password
, credentials
[i
]->CredentialBlob
, credentials
[i
]->CredentialBlobSize
);
584 password
[credentials
[i
]->CredentialBlobSize
/ sizeof(WCHAR
)] = 0;
586 CredFree(credentials
);
590 CredFree(credentials
);
594 /******************************************************************************
595 * CredUIPromptForCredentialsW [CREDUI.@]
597 DWORD WINAPI
CredUIPromptForCredentialsW(PCREDUI_INFOW pUIInfo
,
598 PCWSTR pszTargetName
,
599 PCtxtHandle Reserved
,
602 ULONG ulUsernameMaxChars
,
604 ULONG ulPasswordMaxChars
, PBOOL pfSave
,
608 struct cred_dialog_params params
;
609 DWORD result
= ERROR_SUCCESS
;
611 TRACE("(%p, %s, %p, %d, %s, %d, %p, %d, %p, 0x%08x)\n", pUIInfo
,
612 debugstr_w(pszTargetName
), Reserved
, dwAuthError
, debugstr_w(pszUsername
),
613 ulUsernameMaxChars
, pszPassword
, ulPasswordMaxChars
, pfSave
, dwFlags
);
615 if ((dwFlags
& (CREDUI_FLAGS_ALWAYS_SHOW_UI
|CREDUI_FLAGS_GENERIC_CREDENTIALS
)) == CREDUI_FLAGS_ALWAYS_SHOW_UI
)
616 return ERROR_INVALID_FLAGS
;
619 return ERROR_INVALID_PARAMETER
;
621 if ((dwFlags
& CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX
) && !pfSave
)
622 return ERROR_INVALID_PARAMETER
;
624 if (!(dwFlags
& CREDUI_FLAGS_ALWAYS_SHOW_UI
) &&
625 !(dwFlags
& CREDUI_FLAGS_INCORRECT_PASSWORD
) &&
626 find_existing_credential(pszTargetName
, pszUsername
, ulUsernameMaxChars
, pszPassword
, ulPasswordMaxChars
))
627 return ERROR_SUCCESS
;
629 params
.pszTargetName
= pszTargetName
;
632 params
.pszMessageText
= pUIInfo
->pszMessageText
;
633 params
.pszCaptionText
= pUIInfo
->pszCaptionText
;
634 params
.hbmBanner
= pUIInfo
->hbmBanner
;
638 params
.pszMessageText
= NULL
;
639 params
.pszCaptionText
= NULL
;
640 params
.hbmBanner
= NULL
;
642 params
.pszUsername
= pszUsername
;
643 params
.ulUsernameMaxChars
= ulUsernameMaxChars
;
644 params
.pszPassword
= pszPassword
;
645 params
.ulPasswordMaxChars
= ulPasswordMaxChars
;
646 params
.fSave
= pfSave
? *pfSave
: FALSE
;
647 params
.dwFlags
= dwFlags
;
648 params
.hwndBalloonTip
= NULL
;
649 params
.fBalloonTipActive
= FALSE
;
651 ret
= DialogBoxParamW(hinstCredUI
, MAKEINTRESOURCEW(IDD_CREDDIALOG
),
652 pUIInfo
? pUIInfo
->hwndParent
: NULL
,
653 CredDialogProc
, (LPARAM
)¶ms
);
655 return GetLastError();
659 TRACE("dialog cancelled\n");
660 return ERROR_CANCELLED
;
664 *pfSave
= params
.fSave
;
668 if (dwFlags
& CREDUI_FLAGS_EXPECT_CONFIRMATION
)
671 struct pending_credentials
*entry
;
674 EnterCriticalSection(&csPendingCredentials
);
676 /* find existing pending credentials for the same target and overwrite */
677 /* FIXME: is this correct? */
678 LIST_FOR_EACH_ENTRY(entry
, &pending_credentials_list
, struct pending_credentials
, entry
)
679 if (!strcmpW(pszTargetName
, entry
->pszTargetName
))
682 HeapFree(GetProcessHeap(), 0, entry
->pszUsername
);
683 SecureZeroMemory(entry
->pszPassword
, strlenW(entry
->pszPassword
) * sizeof(WCHAR
));
684 HeapFree(GetProcessHeap(), 0, entry
->pszPassword
);
689 entry
= HeapAlloc(GetProcessHeap(), 0, sizeof(*entry
));
690 len
= strlenW(pszTargetName
);
691 entry
->pszTargetName
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1)*sizeof(WCHAR
));
692 memcpy(entry
->pszTargetName
, pszTargetName
, (len
+ 1)*sizeof(WCHAR
));
693 list_add_tail(&pending_credentials_list
, &entry
->entry
);
696 len
= strlenW(params
.pszUsername
);
697 entry
->pszUsername
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1)*sizeof(WCHAR
));
698 memcpy(entry
->pszUsername
, params
.pszUsername
, (len
+ 1)*sizeof(WCHAR
));
699 len
= strlenW(params
.pszPassword
);
700 entry
->pszPassword
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1)*sizeof(WCHAR
));
701 memcpy(entry
->pszPassword
, params
.pszPassword
, (len
+ 1)*sizeof(WCHAR
));
702 entry
->generic
= (dwFlags
& CREDUI_FLAGS_GENERIC_CREDENTIALS
) != 0;
704 LeaveCriticalSection(&csPendingCredentials
);
706 else if (!(dwFlags
& CREDUI_FLAGS_DO_NOT_PERSIST
))
707 result
= save_credentials(pszTargetName
, pszUsername
, pszPassword
,
708 (dwFlags
& CREDUI_FLAGS_GENERIC_CREDENTIALS
) != 0);
714 /******************************************************************************
715 * CredUIConfirmCredentialsW [CREDUI.@]
717 DWORD WINAPI
CredUIConfirmCredentialsW(PCWSTR pszTargetName
, BOOL bConfirm
)
719 struct pending_credentials
*entry
;
720 DWORD result
= ERROR_NOT_FOUND
;
722 TRACE("(%s, %s)\n", debugstr_w(pszTargetName
), bConfirm
? "TRUE" : "FALSE");
725 return ERROR_INVALID_PARAMETER
;
727 EnterCriticalSection(&csPendingCredentials
);
729 LIST_FOR_EACH_ENTRY(entry
, &pending_credentials_list
, struct pending_credentials
, entry
)
731 if (!strcmpW(pszTargetName
, entry
->pszTargetName
))
734 result
= save_credentials(entry
->pszTargetName
, entry
->pszUsername
,
735 entry
->pszPassword
, entry
->generic
);
737 result
= ERROR_SUCCESS
;
739 list_remove(&entry
->entry
);
741 HeapFree(GetProcessHeap(), 0, entry
->pszTargetName
);
742 HeapFree(GetProcessHeap(), 0, entry
->pszUsername
);
743 SecureZeroMemory(entry
->pszPassword
, strlenW(entry
->pszPassword
) * sizeof(WCHAR
));
744 HeapFree(GetProcessHeap(), 0, entry
->pszPassword
);
745 HeapFree(GetProcessHeap(), 0, entry
);
751 LeaveCriticalSection(&csPendingCredentials
);
756 /******************************************************************************
757 * CredUIParseUserNameW [CREDUI.@]
759 DWORD WINAPI
CredUIParseUserNameW(PCWSTR pszUserName
, PWSTR pszUser
,
760 ULONG ulMaxUserChars
, PWSTR pszDomain
,
761 ULONG ulMaxDomainChars
)
765 TRACE("(%s, %p, %d, %p, %d)\n", debugstr_w(pszUserName
), pszUser
,
766 ulMaxUserChars
, pszDomain
, ulMaxDomainChars
);
768 if (!pszUserName
|| !pszUser
|| !ulMaxUserChars
|| !pszDomain
||
770 return ERROR_INVALID_PARAMETER
;
772 /* FIXME: handle marshaled credentials */
774 p
= strchrW(pszUserName
, '\\');
777 if (p
- pszUserName
> ulMaxDomainChars
- 1)
778 return ERROR_INSUFFICIENT_BUFFER
;
779 if (strlenW(p
+ 1) > ulMaxUserChars
- 1)
780 return ERROR_INSUFFICIENT_BUFFER
;
781 strcpyW(pszUser
, p
+ 1);
782 memcpy(pszDomain
, pszUserName
, (p
- pszUserName
)*sizeof(WCHAR
));
783 pszDomain
[p
- pszUserName
] = '\0';
785 return ERROR_SUCCESS
;
788 p
= strrchrW(pszUserName
, '@');
791 if (p
+ 1 - pszUserName
> ulMaxUserChars
- 1)
792 return ERROR_INSUFFICIENT_BUFFER
;
793 if (strlenW(p
+ 1) > ulMaxDomainChars
- 1)
794 return ERROR_INSUFFICIENT_BUFFER
;
795 strcpyW(pszDomain
, p
+ 1);
796 memcpy(pszUser
, pszUserName
, (p
- pszUserName
)*sizeof(WCHAR
));
797 pszUser
[p
- pszUserName
] = '\0';
799 return ERROR_SUCCESS
;
802 if (strlenW(pszUserName
) > ulMaxUserChars
- 1)
803 return ERROR_INSUFFICIENT_BUFFER
;
804 strcpyW(pszUser
, pszUserName
);
807 return ERROR_SUCCESS
;
810 /******************************************************************************
811 * CredUIStoreSSOCredA [CREDUI.@]
813 DWORD WINAPI
CredUIStoreSSOCredA(PCSTR pszRealm
, PCSTR pszUsername
,
814 PCSTR pszPassword
, BOOL bPersist
)
816 FIXME("(%s, %s, %p, %d)\n", debugstr_a(pszRealm
), debugstr_a(pszUsername
),
817 pszPassword
, bPersist
);
818 return ERROR_SUCCESS
;
821 /******************************************************************************
822 * CredUIStoreSSOCredW [CREDUI.@]
824 DWORD WINAPI
CredUIStoreSSOCredW(PCWSTR pszRealm
, PCWSTR pszUsername
,
825 PCWSTR pszPassword
, BOOL bPersist
)
827 FIXME("(%s, %s, %p, %d)\n", debugstr_w(pszRealm
), debugstr_w(pszUsername
),
828 pszPassword
, bPersist
);
829 return ERROR_SUCCESS
;
832 /******************************************************************************
833 * CredUIReadSSOCredA [CREDUI.@]
835 DWORD WINAPI
CredUIReadSSOCredA(PCSTR pszRealm
, PSTR
*ppszUsername
)
837 FIXME("(%s, %p)\n", debugstr_a(pszRealm
), ppszUsername
);
839 *ppszUsername
= NULL
;
840 return ERROR_NOT_FOUND
;
843 /******************************************************************************
844 * CredUIReadSSOCredW [CREDUI.@]
846 DWORD WINAPI
CredUIReadSSOCredW(PCWSTR pszRealm
, PWSTR
*ppszUsername
)
848 FIXME("(%s, %p)\n", debugstr_w(pszRealm
), ppszUsername
);
850 *ppszUsername
= NULL
;
851 return ERROR_NOT_FOUND
;
854 /******************************************************************************
855 * CredUIInitControls [CREDUI.@]
857 BOOL WINAPI
CredUIInitControls(void)
863 /******************************************************************************
864 * SspiPromptForCredentialsW [CREDUI.@]
866 ULONG SEC_ENTRY
SspiPromptForCredentialsW( PCWSTR target
, void *info
,
867 DWORD error
, PCWSTR package
,
868 PSEC_WINNT_AUTH_IDENTITY_OPAQUE input_id
,
869 PSEC_WINNT_AUTH_IDENTITY_OPAQUE
*output_id
,
870 BOOL
*save
, DWORD sspi_flags
)
872 static const WCHAR basicW
[] = {'B','a','s','i','c',0};
873 static const WCHAR ntlmW
[] = {'N','T','L','M',0};
874 static const WCHAR negotiateW
[] = {'N','e','g','o','t','i','a','t','e',0};
875 WCHAR username
[CREDUI_MAX_USERNAME_LENGTH
+ 1] = {0};
876 WCHAR password
[CREDUI_MAX_PASSWORD_LENGTH
+ 1] = {0};
877 DWORD len_username
= ARRAY_SIZE(username
);
878 DWORD len_password
= ARRAY_SIZE(password
);
880 CREDUI_INFOW
*cred_info
= info
;
881 SEC_WINNT_AUTH_IDENTITY_W
*id
= input_id
;
883 FIXME( "(%s, %p, %u, %s, %p, %p, %p, %x) stub\n", debugstr_w(target
), info
,
884 error
, debugstr_w(package
), input_id
, output_id
, save
, sspi_flags
);
886 if (!target
) return ERROR_INVALID_PARAMETER
;
887 if (!package
|| (strcmpiW( package
, basicW
) && strcmpiW( package
, ntlmW
) &&
888 strcmpiW( package
, negotiateW
)))
890 FIXME( "package %s not supported\n", debugstr_w(package
) );
891 return ERROR_NO_SUCH_PACKAGE
;
894 flags
= CREDUI_FLAGS_ALWAYS_SHOW_UI
| CREDUI_FLAGS_GENERIC_CREDENTIALS
;
896 if (sspi_flags
& SSPIPFC_CREDPROV_DO_NOT_SAVE
)
897 flags
|= CREDUI_FLAGS_DO_NOT_PERSIST
;
899 if (!(sspi_flags
& SSPIPFC_NO_CHECKBOX
))
900 flags
|= CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX
;
902 if (!id
) find_existing_credential( target
, username
, len_username
, password
, len_password
);
905 if (id
->User
&& id
->UserLength
> 0 && id
->UserLength
<= CREDUI_MAX_USERNAME_LENGTH
)
907 memcpy( username
, id
->User
, id
->UserLength
* sizeof(WCHAR
) );
908 username
[id
->UserLength
] = 0;
910 if (id
->Password
&& id
->PasswordLength
> 0 && id
->PasswordLength
<= CREDUI_MAX_PASSWORD_LENGTH
)
912 memcpy( password
, id
->Password
, id
->PasswordLength
* sizeof(WCHAR
) );
913 password
[id
->PasswordLength
] = 0;
917 if (!(ret
= CredUIPromptForCredentialsW( cred_info
, target
, NULL
, error
, username
,
918 len_username
, password
, len_password
, save
, flags
)))
920 DWORD size
= sizeof(*id
), len_domain
= 0;
921 WCHAR
*ptr
, *user
= username
, *domain
= NULL
;
923 if ((ptr
= strchrW( username
, '\\' )))
926 len_username
= strlenW( user
);
927 if (!strcmpiW( package
, ntlmW
) || !strcmpiW( package
, negotiateW
))
930 len_domain
= ptr
- username
;
934 else len_username
= strlenW( username
);
935 len_password
= strlenW( password
);
937 size
+= (len_username
+ 1) * sizeof(WCHAR
);
938 size
+= (len_domain
+ 1) * sizeof(WCHAR
);
939 size
+= (len_password
+ 1) * sizeof(WCHAR
);
940 if (!(id
= HeapAlloc( GetProcessHeap(), 0, size
))) return ERROR_OUTOFMEMORY
;
941 ptr
= (WCHAR
*)(id
+ 1);
943 memcpy( ptr
, user
, (len_username
+ 1) * sizeof(WCHAR
) );
945 id
->UserLength
= len_username
;
946 ptr
+= len_username
+ 1;
949 memcpy( ptr
, domain
, (len_domain
+ 1) * sizeof(WCHAR
) );
951 id
->DomainLength
= len_domain
;
952 ptr
+= len_domain
+ 1;
957 id
->DomainLength
= 0;
959 memcpy( ptr
, password
, (len_password
+ 1) * sizeof(WCHAR
) );
961 id
->PasswordLength
= len_password
;
970 /******************************************************************************
971 * CredUIPromptForWindowsCredentialsW [CREDUI.@]
973 DWORD WINAPI
CredUIPromptForWindowsCredentialsW( CREDUI_INFOW
*info
, DWORD error
, ULONG
*package
,
974 const void *in_buf
, ULONG in_buf_size
, void **out_buf
,
975 ULONG
*out_buf_size
, BOOL
*save
, DWORD flags
)
977 FIXME( "(%p, %u, %p, %p, %u, %p, %p, %p, %08x) stub\n", info
, error
, package
, in_buf
, in_buf_size
,
978 out_buf
, out_buf_size
, save
, flags
);
979 return ERROR_CALL_NOT_IMPLEMENTED
;
982 /******************************************************************************
983 * CredPackAuthenticationBufferW [CREDUI.@]
985 BOOL WINAPI
CredPackAuthenticationBufferW( DWORD flags
, WCHAR
*username
, WCHAR
*password
, BYTE
*buf
,
988 FIXME( "(%08x, %s, %p, %p, %p) stub\n", flags
, debugstr_w(username
), password
, buf
, size
);
989 return ERROR_CALL_NOT_IMPLEMENTED
;
992 /******************************************************************************
993 * CredUnPackAuthenticationBufferW [CREDUI.@]
995 BOOL WINAPI
CredUnPackAuthenticationBufferW( DWORD flags
, void *buf
, DWORD size
, WCHAR
*username
,
996 DWORD
*len_username
, WCHAR
*domain
, DWORD
*len_domain
,
997 WCHAR
*password
, DWORD
*len_password
)
999 FIXME( "(%08x, %p, %u, %p, %p, %p, %p, %p, %p) stub\n", flags
, buf
, size
, username
, len_username
,
1000 domain
, len_domain
, password
, len_password
);
1001 return ERROR_CALL_NOT_IMPLEMENTED
;