reshuffling of dlls
[reactos.git] / reactos / dll / win32 / msgina / msgina.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * PROJECT: ReactOS msgina.dll
22 * FILE: lib/msgina/msgina.c
23 * PURPOSE: ReactOS Logon GINA DLL
24 * PROGRAMMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
25 * UPDATE HISTORY:
26 * 24-11-2003 Created
27 */
28 #include <windows.h>
29 #include <winwlx.h>
30 #include "msgina.h"
31 #include "resource.h"
32
33 #include <wine/debug.h>
34
35 extern HINSTANCE hDllInstance;
36
37 typedef struct _DISPLAYSTATUSMSG
38 {
39 PGINA_CONTEXT Context;
40 HDESK hDesktop;
41 DWORD dwOptions;
42 PWSTR pTitle;
43 PWSTR pMessage;
44 HANDLE StartupEvent;
45 } DISPLAYSTATUSMSG, *PDISPLAYSTATUSMSG;
46
47 INT_PTR CALLBACK
48 LoggedOnDlgProc(
49 HWND hwndDlg,
50 UINT uMsg,
51 WPARAM wParam,
52 LPARAM lParam
53 )
54 {
55 switch(uMsg)
56 {
57 case WM_COMMAND:
58 {
59 switch(LOWORD(wParam))
60 {
61 case IDYES:
62 case IDNO:
63 {
64 EndDialog(hwndDlg, LOWORD(wParam));
65 break;
66 }
67 }
68 return FALSE;
69 }
70 case WM_INITDIALOG:
71 {
72 SetFocus(GetDlgItem(hwndDlg, IDNO));
73 break;
74 }
75 case WM_CLOSE:
76 {
77 EndDialog(hwndDlg, IDNO);
78 return TRUE;
79 }
80 }
81 return FALSE;
82 }
83
84
85 /*
86 * @implemented
87 */
88 BOOL WINAPI
89 WlxNegotiate(
90 DWORD dwWinlogonVersion,
91 PDWORD pdwDllVersion)
92 {
93 if(!pdwDllVersion || (dwWinlogonVersion < GINA_VERSION))
94 return FALSE;
95
96 *pdwDllVersion = GINA_VERSION;
97
98 return TRUE;
99 }
100
101
102 /*
103 * @implemented
104 */
105 BOOL WINAPI
106 WlxInitialize(
107 LPWSTR lpWinsta,
108 HANDLE hWlx,
109 PVOID pvReserved,
110 PVOID pWinlogonFunctions,
111 PVOID *pWlxContext)
112 {
113 PGINA_CONTEXT pgContext;
114
115 pgContext = (PGINA_CONTEXT)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(GINA_CONTEXT));
116 if(!pgContext)
117 return FALSE;
118
119 /* return the context to winlogon */
120 *pWlxContext = (PVOID)pgContext;
121
122 pgContext->hDllInstance = hDllInstance;
123
124 /* save pointer to dispatch table */
125 pgContext->pWlxFuncs = (PWLX_DISPATCH_VERSION)pWinlogonFunctions;
126
127 /* save the winlogon handle used to call the dispatch functions */
128 pgContext->hWlx = hWlx;
129
130 /* save window station */
131 pgContext->station = lpWinsta;
132
133 /* clear status window handle */
134 pgContext->hStatusWindow = 0;
135
136 /* notify winlogon that we will use the default SAS */
137 pgContext->pWlxFuncs->WlxUseCtrlAltDel(hWlx);
138
139 return TRUE;
140 }
141
142
143 /*
144 * @implemented
145 */
146 BOOL WINAPI
147 WlxStartApplication(
148 PVOID pWlxContext,
149 PWSTR pszDesktopName,
150 PVOID pEnvironment,
151 PWSTR pszCmdLine)
152 {
153 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
154 STARTUPINFO si;
155 PROCESS_INFORMATION pi;
156 BOOL Ret;
157
158 si.cb = sizeof(STARTUPINFO);
159 si.lpReserved = NULL;
160 si.lpTitle = pszCmdLine;
161 si.dwX = si.dwY = si.dwXSize = si.dwYSize = 0L;
162 si.dwFlags = 0;
163 si.wShowWindow = SW_SHOW;
164 si.lpReserved2 = NULL;
165 si.cbReserved2 = 0;
166 si.lpDesktop = pszDesktopName;
167
168 Ret = CreateProcessAsUser(pgContext->UserToken,
169 NULL,
170 pszCmdLine,
171 NULL,
172 NULL,
173 FALSE,
174 CREATE_UNICODE_ENVIRONMENT,
175 pEnvironment,
176 NULL,
177 &si,
178 &pi);
179
180 VirtualFree(pEnvironment, 0, MEM_RELEASE);
181 return Ret;
182 }
183
184
185 /*
186 * @implemented
187 */
188 BOOL WINAPI
189 WlxActivateUserShell(
190 PVOID pWlxContext,
191 PWSTR pszDesktopName,
192 PWSTR pszMprLogonScript,
193 PVOID pEnvironment)
194 {
195 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
196 STARTUPINFO si;
197 PROCESS_INFORMATION pi;
198 HKEY hKey;
199 DWORD BufSize, ValueType;
200 WCHAR pszUserInitApp[MAX_PATH];
201 WCHAR pszExpUserInitApp[MAX_PATH];
202 BOOL Ret;
203
204 /* get the path of userinit */
205 if(RegOpenKeyExW(HKEY_LOCAL_MACHINE,
206 L"SOFTWARE\\ReactOS\\Windows NT\\CurrentVersion\\Winlogon",
207 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS)
208 {ERR("GINA: Failed: 1\n");
209 VirtualFree(pEnvironment, 0, MEM_RELEASE);
210 return FALSE;
211 }
212 BufSize = MAX_PATH * sizeof(WCHAR);
213 if((RegQueryValueEx(hKey, L"Userinit", NULL, &ValueType, (LPBYTE)pszUserInitApp,
214 &BufSize) != ERROR_SUCCESS) ||
215 !((ValueType == REG_SZ) || (ValueType == REG_EXPAND_SZ)))
216 {ERR("GINA: Failed: 2\n");
217 RegCloseKey(hKey);
218 VirtualFree(pEnvironment, 0, MEM_RELEASE);
219 return FALSE;
220 }
221 RegCloseKey(hKey);
222
223 /* start userinit */
224 /* FIXME - allow to start more applications that are comma-separated */
225 si.cb = sizeof(STARTUPINFO);
226 si.lpReserved = NULL;
227 si.lpTitle = L"userinit";
228 si.dwX = si.dwY = si.dwXSize = si.dwYSize = 0;
229 si.dwFlags = 0;
230 si.wShowWindow = SW_SHOW;
231 si.lpReserved2 = NULL;
232 si.cbReserved2 = 0;
233 si.lpDesktop = pszDesktopName;
234
235 ExpandEnvironmentStrings(pszUserInitApp, pszExpUserInitApp, MAX_PATH);
236
237 Ret = CreateProcessAsUser(pgContext->UserToken,
238 pszExpUserInitApp,
239 NULL,
240 NULL,
241 NULL,
242 FALSE,
243 CREATE_UNICODE_ENVIRONMENT,
244 pEnvironment,
245 NULL,
246 &si,
247 &pi);
248 if(!Ret) ERR("GINA: Failed: 3\n");
249 VirtualFree(pEnvironment, 0, MEM_RELEASE);
250 return Ret;
251 }
252
253
254 /*
255 * @implemented
256 */
257 int WINAPI
258 WlxLoggedOnSAS(
259 PVOID pWlxContext,
260 DWORD dwSasType,
261 PVOID pReserved)
262 {
263 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
264 int SasAction = WLX_SAS_ACTION_NONE;
265
266 switch(dwSasType)
267 {
268 case WLX_SAS_TYPE_CTRL_ALT_DEL:
269 {
270 int Result;
271 /* display "Are you sure you want to log off?" dialog */
272 Result = pgContext->pWlxFuncs->WlxDialogBoxParam(pgContext->hWlx,
273 pgContext->hDllInstance,
274 (LPTSTR)IDD_LOGOFF_DLG,
275 NULL,
276 LoggedOnDlgProc,
277 (LPARAM)pgContext);
278 if(Result == IDOK)
279 {
280 SasAction = WLX_SAS_ACTION_LOCK_WKSTA;
281 }
282 break;
283 }
284 case WLX_SAS_TYPE_SC_INSERT:
285 {
286 FIXME("WlxLoggedOnSAS: SasType WLX_SAS_TYPE_SC_INSERT not supported!\n");
287 break;
288 }
289 case WLX_SAS_TYPE_SC_REMOVE:
290 {
291 FIXME("WlxLoggedOnSAS: SasType WLX_SAS_TYPE_SC_REMOVE not supported!\n");
292 break;
293 }
294 case WLX_SAS_TYPE_TIMEOUT:
295 {
296 FIXME("WlxLoggedOnSAS: SasType WLX_SAS_TYPE_TIMEOUT not supported!\n");
297 break;
298 }
299 default:
300 {
301 WARN("WlxLoggedOnSAS: Unknown SasType: 0x%x\n", dwSasType);
302 break;
303 }
304 }
305
306 return SasAction;
307 }
308
309
310 BOOL
311 CALLBACK
312 StatusMessageWindowProc(
313 HWND hwndDlg,
314 UINT uMsg,
315 WPARAM wParam,
316 LPARAM lParam
317 )
318 {
319 switch(uMsg)
320 {
321 case WM_INITDIALOG:
322 {
323 PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lParam;
324 if(!msg)
325 return FALSE;
326
327 msg->Context->hStatusWindow = hwndDlg;
328
329 if(msg->pTitle)
330 SetWindowText(hwndDlg, msg->pTitle);
331 SetDlgItemText(hwndDlg, IDC_STATUSLABEL, msg->pMessage);
332 if(!msg->Context->SignaledStatusWindowCreated)
333 {
334 msg->Context->SignaledStatusWindowCreated = TRUE;
335 SetEvent(msg->StartupEvent);
336 }
337 break;
338 }
339 }
340 return FALSE;
341 }
342
343
344 DWORD WINAPI
345 StartupWindowThread(LPVOID lpParam)
346 {
347 HDESK OldDesk;
348 PDISPLAYSTATUSMSG msg = (PDISPLAYSTATUSMSG)lpParam;
349
350 OldDesk = GetThreadDesktop(GetCurrentThreadId());
351
352 if(!SetThreadDesktop(msg->hDesktop))
353 {
354 HeapFree(GetProcessHeap(), 0, lpParam);
355 return FALSE;
356 }
357 DialogBoxParam(hDllInstance,
358 MAKEINTRESOURCE(IDD_STATUSWINDOW),
359 0,
360 StatusMessageWindowProc,
361 (LPARAM)lpParam);
362 SetThreadDesktop(OldDesk);
363
364 msg->Context->hStatusWindow = 0;
365 msg->Context->SignaledStatusWindowCreated = FALSE;
366
367 HeapFree(GetProcessHeap(), 0, lpParam);
368 return TRUE;
369 }
370
371
372 /*
373 * @implemented
374 */
375 BOOL WINAPI
376 WlxDisplayStatusMessage(
377 PVOID pWlxContext,
378 HDESK hDesktop,
379 DWORD dwOptions,
380 PWSTR pTitle,
381 PWSTR pMessage)
382 {
383 PDISPLAYSTATUSMSG msg;
384 HANDLE Thread;
385 DWORD ThreadId;
386 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
387
388 if(!pgContext->hStatusWindow)
389 {
390 msg = (PDISPLAYSTATUSMSG)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DISPLAYSTATUSMSG));
391 if(!msg)
392 return FALSE;
393
394 msg->Context = pgContext;
395 msg->dwOptions = dwOptions;
396 msg->pTitle = pTitle;
397 msg->pMessage = pMessage;
398 msg->hDesktop = hDesktop;
399
400 msg->StartupEvent = CreateEvent(NULL,
401 TRUE,
402 FALSE,
403 NULL);
404
405 if(!msg->StartupEvent)
406 return FALSE;
407
408 Thread = CreateThread(NULL,
409 0,
410 StartupWindowThread,
411 (PVOID)msg,
412 0,
413 &ThreadId);
414 if(Thread)
415 {
416 CloseHandle(Thread);
417 WaitForSingleObject(msg->StartupEvent, INFINITE);
418 CloseHandle(msg->StartupEvent);
419 return TRUE;
420 }
421
422 return FALSE;
423 }
424
425 if(pTitle)
426 SetWindowText(pgContext->hStatusWindow, pTitle);
427
428 SetDlgItemText(pgContext->hStatusWindow, IDC_STATUSLABEL, pMessage);
429
430 return TRUE;
431 }
432
433
434 /*
435 * @implemented
436 */
437 BOOL WINAPI
438 WlxRemoveStatusMessage(
439 PVOID pWlxContext)
440 {
441 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
442 if(pgContext->hStatusWindow)
443 {
444 EndDialog(pgContext->hStatusWindow, 0);
445 pgContext->hStatusWindow = 0;
446 }
447
448 return TRUE;
449 }
450
451
452 /*
453 * @implemented
454 */
455 VOID WINAPI
456 WlxDisplaySASNotice(
457 PVOID pWlxContext)
458 {
459 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
460 pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
461 }
462
463
464 static PWSTR
465 DuplicationString(PWSTR Str)
466 {
467 DWORD cb;
468 PWSTR NewStr;
469
470 cb = (wcslen(Str) + 1) * sizeof(WCHAR);
471 if((NewStr = LocalAlloc(LMEM_FIXED, cb)))
472 {
473 memcpy(NewStr, Str, cb);
474 }
475 return NewStr;
476 }
477
478
479 /*
480 * @unimplemented
481 */
482 int WINAPI
483 WlxLoggedOutSAS(
484 PVOID pWlxContext,
485 DWORD dwSasType,
486 PLUID pAuthenticationId,
487 PSID pLogonSid,
488 PDWORD pdwOptions,
489 PHANDLE phToken,
490 PWLX_MPR_NOTIFY_INFO pNprNotifyInfo,
491 PVOID *pProfile)
492 {
493 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
494 TOKEN_STATISTICS Stats;
495 DWORD cbStats;
496
497 if(!phToken)
498 {
499 WARN("msgina: phToken == NULL!\n");
500 return WLX_SAS_ACTION_NONE;
501 }
502
503 if(!LogonUser(L"Administrator", NULL, L"Secrect",
504 LOGON32_LOGON_INTERACTIVE, /* FIXME - use LOGON32_LOGON_UNLOCK instead! */
505 LOGON32_PROVIDER_DEFAULT,
506 phToken))
507 {
508 WARN("msgina: Logonuser() failed\n");
509 return WLX_SAS_ACTION_NONE;
510 }
511
512 if(!(*phToken))
513 {
514 WARN("msgina: *phToken == NULL!\n");
515 return WLX_SAS_ACTION_NONE;
516 }
517
518 pgContext->UserToken =*phToken;
519
520 *pdwOptions = 0;
521 *pProfile =NULL;
522
523 if(!GetTokenInformation(*phToken,
524 TokenStatistics,
525 (PVOID)&Stats,
526 sizeof(TOKEN_STATISTICS),
527 &cbStats))
528 {
529 WARN("msgina: Couldn't get Autentication id from user token!\n");
530 return WLX_SAS_ACTION_NONE;
531 }
532 *pAuthenticationId = Stats.AuthenticationId;
533 pNprNotifyInfo->pszUserName = DuplicationString(L"Administrator");
534 pNprNotifyInfo->pszDomain = NULL;
535 pNprNotifyInfo->pszPassword = DuplicationString(L"Secret");
536 pNprNotifyInfo->pszOldPassword = NULL;
537
538 return WLX_SAS_ACTION_LOGON;
539 }
540
541
542 BOOL STDCALL
543 DllMain(
544 HINSTANCE hinstDLL,
545 DWORD dwReason,
546 LPVOID lpvReserved)
547 {
548 switch (dwReason)
549 {
550 case DLL_PROCESS_ATTACH:
551 /* fall through */
552 case DLL_THREAD_ATTACH:
553 hDllInstance = hinstDLL;
554 break;
555 case DLL_THREAD_DETACH:
556 break;
557 case DLL_PROCESS_DETACH:
558 break;
559 }
560 return TRUE;
561 }
562