[TCPIP]
[reactos.git] / reactos / dll / win32 / msgina / gui.c
1 /*
2 * PROJECT: ReactOS msgina.dll
3 * FILE: dll/win32/msgina/gui.c
4 * PURPOSE: ReactOS Logon GINA DLL
5 * PROGRAMMER: Hervé Poussineau (hpoussin@reactos.org)
6 */
7
8 #include "msgina.h"
9
10 #include <wine/debug.h>
11
12 WINE_DEFAULT_DEBUG_CHANNEL(msgina);
13
14 typedef struct _DISPLAYSTATUSMSG
15 {
16 PGINA_CONTEXT Context;
17 HDESK hDesktop;
18 DWORD dwOptions;
19 PWSTR pTitle;
20 PWSTR pMessage;
21 HANDLE StartupEvent;
22 } DISPLAYSTATUSMSG, *PDISPLAYSTATUSMSG;
23
24 static BOOL
25 GUIInitialize(
26 IN OUT PGINA_CONTEXT pgContext)
27 {
28 TRACE("GUIInitialize(%p)\n", pgContext);
29 return TRUE;
30 }
31
32 static INT_PTR CALLBACK
33 StatusMessageWindowProc(
34 IN HWND hwndDlg,
35 IN UINT uMsg,
36 IN WPARAM wParam,
37 IN LPARAM lParam)
38 {
39 UNREFERENCED_PARAMETER(wParam);
40
41 switch (uMsg)
42 {
43 case WM_INITDIALOG:
44 {
45 PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lParam;
46 if (!msg)
47 return FALSE;
48
49 msg->Context->hStatusWindow = hwndDlg;
50
51 if (msg->pTitle)
52 SetWindowTextW(hwndDlg, msg->pTitle);
53 SetDlgItemTextW(hwndDlg, IDC_STATUSLABEL, msg->pMessage);
54 SetEvent(msg->StartupEvent);
55 return TRUE;
56 }
57 }
58 return FALSE;
59 }
60
61 static DWORD WINAPI
62 StartupWindowThread(LPVOID lpParam)
63 {
64 HDESK OldDesk;
65 PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lpParam;
66
67 OldDesk = GetThreadDesktop(GetCurrentThreadId());
68
69 if(!SetThreadDesktop(msg->hDesktop))
70 {
71 HeapFree(GetProcessHeap(), 0, lpParam);
72 return FALSE;
73 }
74 DialogBoxParam(
75 hDllInstance,
76 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG),
77 GetDesktopWindow(),
78 StatusMessageWindowProc,
79 (LPARAM)lpParam);
80 SetThreadDesktop(OldDesk);
81
82 HeapFree(GetProcessHeap(), 0, lpParam);
83 return TRUE;
84 }
85
86 static BOOL
87 GUIDisplayStatusMessage(
88 IN PGINA_CONTEXT pgContext,
89 IN HDESK hDesktop,
90 IN DWORD dwOptions,
91 IN PWSTR pTitle,
92 IN PWSTR pMessage)
93 {
94 PDISPLAYSTATUSMSG msg;
95 HANDLE Thread;
96 DWORD ThreadId;
97
98 TRACE("GUIDisplayStatusMessage(%ws)\n", pMessage);
99
100 if (!pgContext->hStatusWindow)
101 {
102 msg = (PDISPLAYSTATUSMSG)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DISPLAYSTATUSMSG));
103 if(!msg)
104 return FALSE;
105
106 msg->Context = pgContext;
107 msg->dwOptions = dwOptions;
108 msg->pTitle = pTitle;
109 msg->pMessage = pMessage;
110 msg->hDesktop = hDesktop;
111
112 msg->StartupEvent = CreateEventW(
113 NULL,
114 TRUE,
115 FALSE,
116 NULL);
117
118 if (!msg->StartupEvent)
119 return FALSE;
120
121 Thread = CreateThread(
122 NULL,
123 0,
124 StartupWindowThread,
125 (PVOID)msg,
126 0,
127 &ThreadId);
128 if (Thread)
129 {
130 CloseHandle(Thread);
131 WaitForSingleObject(msg->StartupEvent, INFINITE);
132 CloseHandle(msg->StartupEvent);
133 return TRUE;
134 }
135
136 return FALSE;
137 }
138
139 if (pTitle)
140 SetWindowTextW(pgContext->hStatusWindow, pTitle);
141
142 SetDlgItemTextW(pgContext->hStatusWindow, IDC_STATUSLABEL, pMessage);
143
144 return TRUE;
145 }
146
147 static BOOL
148 GUIRemoveStatusMessage(
149 IN PGINA_CONTEXT pgContext)
150 {
151 if (pgContext->hStatusWindow)
152 {
153 EndDialog(pgContext->hStatusWindow, 0);
154 pgContext->hStatusWindow = NULL;
155 }
156
157 return TRUE;
158 }
159
160 static INT_PTR CALLBACK
161 EmptyWindowProc(
162 IN HWND hwndDlg,
163 IN UINT uMsg,
164 IN WPARAM wParam,
165 IN LPARAM lParam)
166 {
167 UNREFERENCED_PARAMETER(hwndDlg);
168 UNREFERENCED_PARAMETER(uMsg);
169 UNREFERENCED_PARAMETER(wParam);
170 UNREFERENCED_PARAMETER(lParam);
171
172 return FALSE;
173 }
174
175 static VOID
176 GUIDisplaySASNotice(
177 IN OUT PGINA_CONTEXT pgContext)
178 {
179 INT result;
180
181 TRACE("GUIDisplaySASNotice()\n");
182
183 /* Display the notice window */
184 result = DialogBoxParam(
185 pgContext->hDllInstance,
186 MAKEINTRESOURCE(IDD_NOTICE_DLG),
187 GetDesktopWindow(),
188 EmptyWindowProc,
189 (LPARAM)NULL);
190 if (result == -1)
191 {
192 /* Failed to display the window. Do as if the user
193 * already has pressed CTRL+ALT+DELETE */
194 pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
195 }
196 }
197
198 /* Get the text contained in a textbox. Allocates memory in pText
199 * to contain the text. Returns TRUE in case of success */
200 static BOOL
201 GetTextboxText(
202 IN HWND hwndDlg,
203 IN INT TextboxId,
204 OUT LPWSTR *pText)
205 {
206 LPWSTR Text;
207 int Count;
208
209 Count = GetWindowTextLength(GetDlgItem(hwndDlg, TextboxId));
210 Text = HeapAlloc(GetProcessHeap(), 0, (Count + 1) * sizeof(WCHAR));
211 if (!Text)
212 return FALSE;
213 if (Count != GetWindowTextW(GetDlgItem(hwndDlg, TextboxId), Text, Count + 1))
214 {
215 HeapFree(GetProcessHeap(), 0, Text);
216 return FALSE;
217 }
218 *pText = Text;
219 return TRUE;
220 }
221
222 static INT_PTR CALLBACK
223 LoggedOnWindowProc(
224 IN HWND hwndDlg,
225 IN UINT uMsg,
226 IN WPARAM wParam,
227 IN LPARAM lParam)
228 {
229 UNREFERENCED_PARAMETER(lParam);
230
231 switch (uMsg)
232 {
233 case WM_COMMAND:
234 {
235 switch (LOWORD(wParam))
236 {
237 case IDC_LOCK:
238 EndDialog(hwndDlg, WLX_SAS_ACTION_LOCK_WKSTA);
239 return TRUE;
240 case IDC_LOGOFF:
241 EndDialog(hwndDlg, WLX_SAS_ACTION_LOGOFF);
242 return TRUE;
243 case IDC_SHUTDOWN:
244 EndDialog(hwndDlg, WLX_SAS_ACTION_SHUTDOWN_POWER_OFF);
245 return TRUE;
246 case IDC_TASKMGR:
247 EndDialog(hwndDlg, WLX_SAS_ACTION_TASKLIST);
248 return TRUE;
249 case IDCANCEL:
250 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
251 return TRUE;
252 }
253 break;
254 }
255 case WM_INITDIALOG:
256 {
257 SetFocus(GetDlgItem(hwndDlg, IDNO));
258 return TRUE;
259 }
260 case WM_CLOSE:
261 {
262 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
263 return TRUE;
264 }
265 }
266
267 return FALSE;
268 }
269
270 static INT
271 GUILoggedOnSAS(
272 IN OUT PGINA_CONTEXT pgContext,
273 IN DWORD dwSasType)
274 {
275 INT result;
276
277 TRACE("GUILoggedOnSAS()\n");
278
279 if (dwSasType != WLX_SAS_TYPE_CTRL_ALT_DEL)
280 {
281 /* Nothing to do for WLX_SAS_TYPE_TIMEOUT ; the dialog will
282 * close itself thanks to the use of WlxDialogBoxParam */
283 return WLX_SAS_ACTION_NONE;
284 }
285
286 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
287 pgContext->hWlx,
288 pgContext->hDllInstance,
289 MAKEINTRESOURCEW(IDD_LOGGEDON_DLG),
290 GetDesktopWindow(),
291 LoggedOnWindowProc,
292 (LPARAM)pgContext);
293 if (result >= WLX_SAS_ACTION_LOGON &&
294 result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
295 {
296 return result;
297 }
298 return WLX_SAS_ACTION_NONE;
299 }
300
301 static INT_PTR CALLBACK
302 LoggedOutWindowProc(
303 IN HWND hwndDlg,
304 IN UINT uMsg,
305 IN WPARAM wParam,
306 IN LPARAM lParam)
307 {
308 PGINA_CONTEXT pgContext;
309
310 pgContext = (PGINA_CONTEXT)GetWindowLongPtr(hwndDlg, GWL_USERDATA);
311
312 switch (uMsg)
313 {
314 case WM_INITDIALOG:
315 {
316 /* FIXME: take care of DontDisplayLastUserName, NoDomainUI, ShutdownWithoutLogon */
317 pgContext = (PGINA_CONTEXT)lParam;
318 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pgContext);
319 SetFocus(GetDlgItem(hwndDlg, IDC_USERNAME));
320
321 pgContext->hBitmap = LoadImage(hDllInstance, MAKEINTRESOURCE(IDI_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
322 return TRUE;
323 }
324 case WM_PAINT:
325 {
326 PAINTSTRUCT ps;
327 HDC hdc;
328 if (pgContext->hBitmap)
329 {
330 hdc = BeginPaint(hwndDlg, &ps);
331 DrawStateW(hdc, NULL, NULL, (LPARAM)pgContext->hBitmap, (WPARAM)0, 0, 0, 0, 0, DST_BITMAP);
332 EndPaint(hwndDlg, &ps);
333 }
334 return TRUE;
335 }
336 case WM_DESTROY:
337 {
338 DeleteObject(pgContext->hBitmap);
339 return TRUE;
340 }
341 case WM_COMMAND:
342 {
343 switch (LOWORD(wParam))
344 {
345 case IDOK:
346 {
347 LPWSTR UserName = NULL, Password = NULL;
348 INT result = WLX_SAS_ACTION_NONE;
349
350 if (GetTextboxText(hwndDlg, IDC_USERNAME, &UserName) && *UserName == '\0')
351 break;
352 if (GetTextboxText(hwndDlg, IDC_PASSWORD, &Password) &&
353 DoLoginTasks(pgContext, UserName, NULL, Password))
354 {
355 result = WLX_SAS_ACTION_LOGON;
356 }
357 HeapFree(GetProcessHeap(), 0, UserName);
358 HeapFree(GetProcessHeap(), 0, Password);
359 EndDialog(hwndDlg, result);
360 return TRUE;
361 }
362 case IDCANCEL:
363 {
364 EndDialog(hwndDlg, WLX_SAS_ACTION_NONE);
365 return TRUE;
366 }
367 case IDC_SHUTDOWN:
368 {
369 EndDialog(hwndDlg, WLX_SAS_ACTION_SHUTDOWN);
370 return TRUE;
371 }
372 }
373 break;
374 }
375 }
376
377 return FALSE;
378 }
379
380 static INT
381 GUILoggedOutSAS(
382 IN OUT PGINA_CONTEXT pgContext)
383 {
384 int result;
385
386 TRACE("GUILoggedOutSAS()\n");
387
388 result = pgContext->pWlxFuncs->WlxDialogBoxParam(
389 pgContext->hWlx,
390 pgContext->hDllInstance,
391 MAKEINTRESOURCEW(IDD_LOGGEDOUT_DLG),
392 GetDesktopWindow(),
393 LoggedOutWindowProc,
394 (LPARAM)pgContext);
395 if (result >= WLX_SAS_ACTION_LOGON &&
396 result <= WLX_SAS_ACTION_SWITCH_CONSOLE)
397 {
398 WARN("WlxLoggedOutSAS() returns 0x%x\n", result);
399 return result;
400 }
401
402 WARN("WlxDialogBoxParam() failed (0x%x)\n", result);
403 return WLX_SAS_ACTION_NONE;
404 }
405
406 static INT
407 GUILockedSAS(
408 IN OUT PGINA_CONTEXT pgContext)
409 {
410 TRACE("GUILockedSAS()\n");
411
412 UNREFERENCED_PARAMETER(pgContext);
413
414 UNIMPLEMENTED;
415 return WLX_SAS_ACTION_UNLOCK_WKSTA;
416 }
417
418 GINA_UI GinaGraphicalUI = {
419 GUIInitialize,
420 GUIDisplayStatusMessage,
421 GUIRemoveStatusMessage,
422 GUIDisplaySASNotice,
423 GUILoggedOnSAS,
424 GUILoggedOutSAS,
425 GUILockedSAS,
426 };