wined3d: Default to GLSL. This is safe because we now have proper ps2.0/vs2.0 detection.
[wine] / dlls / credui / credui_main.c
1 /*
2  * Credentials User Interface
3  *
4  * Copyright 2006 Robert Shearman (for CodeWeavers)
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winnt.h"
26 #include "winuser.h"
27 #include "wincred.h"
28 #include "commctrl.h"
29
30 #include "credui_resources.h"
31
32 #include "wine/debug.h"
33 #include "wine/unicode.h"
34 #include "wine/list.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(credui);
37
38 struct pending_credentials
39 {
40     struct list entry;
41     PWSTR pszTargetName;
42     PWSTR pszUsername;
43     PWSTR pszPassword;
44 };
45
46 static HINSTANCE hinstCredUI;
47
48 struct list pending_credentials_list = LIST_INIT(pending_credentials_list);
49
50 static CRITICAL_SECTION csPendingCredentials;
51 static CRITICAL_SECTION_DEBUG critsect_debug =
52 {
53     0, 0, &csPendingCredentials,
54     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
55     0, 0, { (DWORD_PTR)(__FILE__ ": csPendingCredentials") }
56 };
57 static CRITICAL_SECTION csPendingCredentials = { &critsect_debug, -1, 0, 0, 0, 0 };
58
59
60 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
61 {
62     TRACE("(0x%p, %d, %p)\n",hinstDLL,fdwReason,lpvReserved);
63
64     if (fdwReason == DLL_WINE_PREATTACH) return FALSE;  /* prefer native version */
65
66     if (fdwReason == DLL_PROCESS_ATTACH)
67     {
68         DisableThreadLibraryCalls(hinstDLL);
69         hinstCredUI = hinstDLL;
70         InitCommonControls();
71     }
72     else if (fdwReason == DLL_PROCESS_DETACH)
73     {
74         struct pending_credentials *entry, *cursor2;
75         LIST_FOR_EACH_ENTRY_SAFE(entry, cursor2, &pending_credentials_list, struct pending_credentials, entry)
76         {
77             list_remove(&entry->entry);
78
79             HeapFree(GetProcessHeap(), 0, entry->pszTargetName);
80             HeapFree(GetProcessHeap(), 0, entry->pszUsername);
81             HeapFree(GetProcessHeap(), 0, entry->pszPassword);
82             HeapFree(GetProcessHeap(), 0, entry);
83         }
84     }
85
86     return TRUE;
87 }
88
89 static DWORD save_credentials(PCWSTR pszTargetName, PCWSTR pszUsername,
90                               PCWSTR pszPassword)
91 {
92     FIXME("save servername %s with username %s\n", debugstr_w(pszTargetName), debugstr_w(pszUsername));
93     return ERROR_SUCCESS;
94 }
95
96 struct cred_dialog_params
97 {
98     PCWSTR pszTargetName;
99     PCWSTR pszMessageText;
100     PCWSTR pszCaptionText;
101     HBITMAP hbmBanner;
102     PWSTR pszUsername;
103     ULONG ulUsernameMaxChars;
104     PWSTR pszPassword;
105     ULONG ulPasswordMaxChars;
106     BOOL fSave;
107     DWORD dwFlags;
108 };
109
110 static INT_PTR CALLBACK CredDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
111                                        LPARAM lParam)
112 {
113     switch (uMsg)
114     {
115         case WM_INITDIALOG:
116         {
117             struct cred_dialog_params *params = (struct cred_dialog_params *)lParam;
118
119             SetWindowLongPtrW(hwndDlg, DWLP_USER, (LONG_PTR)params);
120             if (params->pszMessageText)
121                 SetDlgItemTextW(hwndDlg, IDC_MESSAGE, params->pszMessageText);
122             else
123             {
124                 WCHAR format[256];
125                 WCHAR message[256];
126                 LoadStringW(hinstCredUI, IDS_MESSAGEFORMAT, format, sizeof(format)/sizeof(format[0]));
127                 snprintfW(message, sizeof(message)/sizeof(message[0]), format, params->pszTargetName);
128                 SetDlgItemTextW(hwndDlg, IDC_MESSAGE, message);
129             }
130             SetDlgItemTextW(hwndDlg, IDC_USERNAME, params->pszUsername);
131             SetDlgItemTextW(hwndDlg, IDC_PASSWORD, params->pszPassword);
132
133             if (params->pszUsername[0])
134                 SetFocus(GetDlgItem(hwndDlg, IDC_PASSWORD));
135             else
136                 SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME));
137
138             if (params->pszCaptionText)
139                 SetWindowTextW(hwndDlg, params->pszCaptionText);
140             else
141             {
142                 WCHAR format[256];
143                 WCHAR title[256];
144                 LoadStringW(hinstCredUI, IDS_TITLEFORMAT, format, sizeof(format)/sizeof(format[0]));
145                 snprintfW(title, sizeof(title)/sizeof(title[0]), format, params->pszTargetName);
146                 SetWindowTextW(hwndDlg, title);
147             }
148
149             if (params->dwFlags & (CREDUI_FLAGS_DO_NOT_PERSIST|CREDUI_FLAGS_PERSIST))
150                 ShowWindow(GetDlgItem(hwndDlg, IDC_SAVE), SW_HIDE);
151             else if (params->fSave)
152                 CheckDlgButton(hwndDlg, IDC_SAVE, BST_CHECKED);
153
154             return FALSE;
155         }
156         case WM_COMMAND:
157             switch (wParam)
158             {
159                 case MAKELONG(IDOK, BN_CLICKED):
160                 {
161                     struct cred_dialog_params *params =
162                         (struct cred_dialog_params *)GetWindowLongPtrW(hwndDlg, DWLP_USER);
163                     HWND hwndUsername = GetDlgItem(hwndDlg, IDC_USERNAME);
164                     LPWSTR user;
165                     INT len;
166                     INT len2;
167
168                     len = GetWindowTextLengthW(hwndUsername);
169                     user = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
170                     GetWindowTextW(hwndUsername, user, len + 1);
171
172                     if (!user[0])
173                         return TRUE;
174
175                     if (!strchrW(user, '\\') && !strchrW(user, '@'))
176                     {
177                         INT len_target = strlenW(params->pszTargetName);
178                         memcpy(params->pszUsername, params->pszTargetName,
179                                min(len_target, params->ulUsernameMaxChars) * sizeof(WCHAR));
180                         if (len_target + 1 < params->ulUsernameMaxChars)
181                             params->pszUsername[len_target] = '\\';
182                         if (len_target + 2 < params->ulUsernameMaxChars)
183                             params->pszUsername[len_target + 1] = '\0';
184                     }
185                     else if (params->ulUsernameMaxChars > 0)
186                         params->pszUsername[0] = '\0';
187
188                     len2 = strlenW(params->pszUsername);
189                     memcpy(params->pszUsername + len2, user, min(len, params->ulUsernameMaxChars - len2) * sizeof(WCHAR));
190                     if (params->ulUsernameMaxChars)
191                         params->pszUsername[len2 + min(len, params->ulUsernameMaxChars - len2 - 1)] = '\0';
192
193                     HeapFree(GetProcessHeap(), 0, user);
194
195                     GetDlgItemTextW(hwndDlg, IDC_PASSWORD, params->pszPassword,
196                                     params->ulPasswordMaxChars);
197
198                     EndDialog(hwndDlg, IDOK);
199                     return TRUE;
200                 }
201                 case MAKELONG(IDCANCEL, BN_CLICKED):
202                     EndDialog(hwndDlg, IDCANCEL);
203                     return TRUE;
204             }
205             /* fall through */
206         default:
207             return FALSE;
208     }
209 }
210
211 /******************************************************************************
212  *           CredUIPromptForCredentialsW [CREDUI.@]
213  */
214 DWORD WINAPI CredUIPromptForCredentialsW(PCREDUI_INFOW pUIInfo,
215                                          PCWSTR pszTargetName,
216                                          PCtxtHandle Reserved,
217                                          DWORD dwAuthError,
218                                          PWSTR pszUsername,
219                                          ULONG ulUsernameMaxChars,
220                                          PWSTR pszPassword,
221                                          ULONG ulPasswordMaxChars, PBOOL pfSave,
222                                          DWORD dwFlags)
223 {
224     INT_PTR ret;
225     struct cred_dialog_params params;
226     DWORD result = ERROR_SUCCESS;
227
228     TRACE("(%p, %s, %p, %d, %s, %d, %p, %d, %p, 0x%08x)\n", pUIInfo,
229           debugstr_w(pszTargetName), Reserved, dwAuthError, debugstr_w(pszUsername),
230           ulUsernameMaxChars, pszPassword, ulPasswordMaxChars, pfSave, dwFlags);
231
232     if ((dwFlags & (CREDUI_FLAGS_ALWAYS_SHOW_UI|CREDUI_FLAGS_GENERIC_CREDENTIALS)) == CREDUI_FLAGS_ALWAYS_SHOW_UI)
233         return ERROR_INVALID_FLAGS;
234
235     if (!pszTargetName)
236         return ERROR_INVALID_PARAMETER;
237
238     if ((dwFlags & CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX) && !pfSave)
239         return ERROR_INVALID_PARAMETER;
240
241     params.pszTargetName = pszTargetName;
242     if (pUIInfo)
243     {
244         params.pszMessageText = pUIInfo->pszMessageText;
245         params.pszCaptionText = pUIInfo->pszCaptionText;
246         params.hbmBanner  = pUIInfo->hbmBanner;
247     }
248     else
249     {
250         params.pszMessageText = NULL;
251         params.pszCaptionText = NULL;
252         params.hbmBanner = NULL;
253     }
254     params.pszUsername = pszUsername;
255     params.ulUsernameMaxChars = ulUsernameMaxChars;
256     params.pszPassword = pszPassword;
257     params.ulPasswordMaxChars = ulPasswordMaxChars;
258     params.fSave = pfSave ? *pfSave : FALSE;
259     params.dwFlags = dwFlags;
260
261     ret = DialogBoxParamW(hinstCredUI, MAKEINTRESOURCEW(IDD_CREDDIALOG),
262                           pUIInfo ? pUIInfo->hwndParent : NULL,
263                           CredDialogProc, (LPARAM)&params);
264     if (ret <= 0)
265         return GetLastError();
266
267     if (ret == IDCANCEL)
268     {
269         TRACE("dialog cancelled\n");
270         return ERROR_CANCELLED;
271     }
272
273     if (pfSave)
274         *pfSave = params.fSave;
275
276     if (params.fSave)
277     {
278         if (dwFlags & CREDUI_FLAGS_EXPECT_CONFIRMATION)
279         {
280             BOOL found = FALSE;
281             struct pending_credentials *entry;
282             int len;
283
284             EnterCriticalSection(&csPendingCredentials);
285
286             /* find existing pending credentials for the same target and overwrite */
287             /* FIXME: is this correct? */
288             LIST_FOR_EACH_ENTRY(entry, &pending_credentials_list, struct pending_credentials, entry)
289                 if (!strcmpW(pszTargetName, entry->pszTargetName))
290                 {
291                     found = TRUE;
292                     HeapFree(GetProcessHeap(), 0, entry->pszUsername);
293                     HeapFree(GetProcessHeap(), 0, entry->pszPassword);
294                 }
295
296             if (!found)
297             {
298                 entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*entry));
299                 list_init(&entry->entry);
300                 len = strlenW(pszTargetName);
301                 entry->pszTargetName = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
302                 memcpy(entry->pszTargetName, pszTargetName, (len + 1)*sizeof(WCHAR));
303                 list_add_tail(&entry->entry, &pending_credentials_list);
304             }
305
306             len = strlenW(params.pszUsername);
307             entry->pszUsername = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
308             memcpy(entry->pszUsername, params.pszUsername, (len + 1)*sizeof(WCHAR));
309             len = strlenW(params.pszPassword);
310             entry->pszPassword = HeapAlloc(GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
311             memcpy(entry->pszPassword, params.pszPassword, (len + 1)*sizeof(WCHAR));
312
313             LeaveCriticalSection(&csPendingCredentials);
314         }
315         else
316             result = save_credentials(pszTargetName, pszUsername, pszPassword);
317     }
318
319     return result;
320 }
321
322 /******************************************************************************
323  *           CredUIConfirmCredentialsW [CREDUI.@]
324  */
325 DWORD WINAPI CredUIConfirmCredentialsW(PCWSTR pszTargetName, BOOL bConfirm)
326 {
327     struct pending_credentials *entry;
328     DWORD result = ERROR_NOT_FOUND;
329
330     TRACE("(%s, %s)\n", debugstr_w(pszTargetName), bConfirm ? "TRUE" : "FALSE");
331
332     if (!pszTargetName)
333         return ERROR_INVALID_PARAMETER;
334
335     EnterCriticalSection(&csPendingCredentials);
336
337     LIST_FOR_EACH_ENTRY(entry, &pending_credentials_list, struct pending_credentials, entry)
338     {
339         if (!strcmpW(pszTargetName, entry->pszTargetName))
340         {
341             if (bConfirm)
342                 result = save_credentials(entry->pszTargetName, entry->pszUsername, entry->pszPassword);
343             else
344                 result = ERROR_SUCCESS;
345
346             list_remove(&entry->entry);
347
348             HeapFree(GetProcessHeap(), 0, entry->pszTargetName);
349             HeapFree(GetProcessHeap(), 0, entry->pszUsername);
350             HeapFree(GetProcessHeap(), 0, entry->pszPassword);
351             HeapFree(GetProcessHeap(), 0, entry);
352
353             break;
354         }
355     }
356
357     LeaveCriticalSection(&csPendingCredentials);
358
359     return result;
360 }
361
362 /******************************************************************************
363  *           CredUIParseUserNameW [CREDUI.@]
364  */
365 DWORD WINAPI CredUIParseUserNameW(PCWSTR pszUserName, PWSTR pszUser,
366                                   ULONG ulMaxUserChars, PWSTR pszDomain,
367                                   ULONG ulMaxDomainChars)
368 {
369     PWSTR p;
370
371     TRACE("(%s, %p, %d, %p, %d)\n", debugstr_w(pszUserName), pszUser,
372           ulMaxUserChars, pszDomain, ulMaxDomainChars);
373
374     if (!pszUserName || !pszUser || !ulMaxUserChars || !pszDomain ||
375         !ulMaxDomainChars)
376         return ERROR_INVALID_PARAMETER;
377
378     /* FIXME: handle marshaled credentials */
379
380     p = strchrW(pszUserName, '\\');
381     if (p)
382     {
383         if (p - pszUserName > ulMaxDomainChars - 1)
384             return ERROR_INSUFFICIENT_BUFFER;
385         if (strlenW(p + 1) > ulMaxUserChars - 1)
386             return ERROR_INSUFFICIENT_BUFFER;
387         strcpyW(pszUser, p + 1);
388         memcpy(pszDomain, pszUserName, (p - pszUserName)*sizeof(WCHAR));
389         pszDomain[p - pszUserName] = '\0';
390
391         return ERROR_SUCCESS;
392     }
393
394     p = strrchrW(pszUserName, '@');
395     if (p)
396     {
397         if (p + 1 - pszUserName > ulMaxUserChars - 1)
398             return ERROR_INSUFFICIENT_BUFFER;
399         if (strlenW(p + 1) > ulMaxDomainChars - 1)
400             return ERROR_INSUFFICIENT_BUFFER;
401         strcpyW(pszDomain, p + 1);
402         memcpy(pszUser, pszUserName, (p - pszUserName)*sizeof(WCHAR));
403         pszUser[p - pszUserName] = '\0';
404
405         return ERROR_SUCCESS;
406     }
407
408     if (strlenW(pszUserName) > ulMaxUserChars - 1)
409         return ERROR_INSUFFICIENT_BUFFER;
410     strcpyW(pszUser, pszUserName);
411     pszDomain[0] = '\0';
412
413     return ERROR_SUCCESS;
414 }
415
416 /******************************************************************************
417  *           CredUIStoreSSOCredA [CREDUI.@]
418  */
419 DWORD WINAPI CredUIStoreSSOCredA(PCSTR pszRealm, PCSTR pszUsername,
420                                  PCSTR pszPassword, BOOL bPersist)
421 {
422     FIXME("(%s, %s, %p, %d)\n", debugstr_a(pszRealm), debugstr_a(pszUsername),
423           pszPassword, bPersist);
424     return ERROR_SUCCESS;
425 }
426
427 /******************************************************************************
428  *           CredUIStoreSSOCredW [CREDUI.@]
429  */
430 DWORD WINAPI CredUIStoreSSOCredW(PCWSTR pszRealm, PCWSTR pszUsername,
431                                  PCWSTR pszPassword, BOOL bPersist)
432 {
433     FIXME("(%s, %s, %p, %d)\n", debugstr_w(pszRealm), debugstr_w(pszUsername),
434           pszPassword, bPersist);
435     return ERROR_SUCCESS;
436 }
437
438 /******************************************************************************
439  *           CredUIReadSSOCredA [CREDUI.@]
440  */
441 DWORD WINAPI CredUIReadSSOCredA(PCSTR pszRealm, PSTR *ppszUsername)
442 {
443     FIXME("(%s, %p)\n", debugstr_a(pszRealm), ppszUsername);
444     if (ppszUsername)
445         *ppszUsername = NULL;
446     return ERROR_NOT_FOUND;
447 }
448
449 /******************************************************************************
450  *           CredUIReadSSOCredW [CREDUI.@]
451  */
452 DWORD WINAPI CredUIReadSSOCredW(PCWSTR pszRealm, PWSTR *ppszUsername)
453 {
454     FIXME("(%s, %p)\n", debugstr_w(pszRealm), ppszUsername);
455     if (ppszUsername)
456         *ppszUsername = NULL;
457     return ERROR_NOT_FOUND;
458 }