c45dbbcd832638b308e8fcc863afa229e30af286
[reactos.git] / reactos / dll / win32 / msgina / msgina.c
1 /*
2 * ReactOS GINA
3 * Copyright (C) 2003-2004, 2006 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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /*
20 * PROJECT: ReactOS msgina.dll
21 * FILE: dll/win32/msgina/msgina.c
22 * PURPOSE: ReactOS Logon GINA DLL
23 * PROGRAMMER: Thomas Weidenmueller (w3seek@users.sourceforge.net)
24 * Hervé Poussineau (hpoussin@reactos.org)
25 */
26
27 #include "msgina.h"
28
29 HINSTANCE hDllInstance;
30
31 extern GINA_UI GinaGraphicalUI;
32 extern GINA_UI GinaTextUI;
33 static PGINA_UI pGinaUI;
34
35 /*
36 * @implemented
37 */
38 BOOL WINAPI
39 WlxNegotiate(
40 IN DWORD dwWinlogonVersion,
41 OUT PDWORD pdwDllVersion)
42 {
43 TRACE("WlxNegotiate(%lx, %p)\n", dwWinlogonVersion, pdwDllVersion);
44
45 if(!pdwDllVersion || (dwWinlogonVersion < WLX_VERSION_1_3))
46 return FALSE;
47
48 *pdwDllVersion = WLX_VERSION_1_3;
49
50 return TRUE;
51 }
52
53 static LONG
54 ReadRegSzKey(
55 IN HKEY hKey,
56 IN LPCWSTR pszKey,
57 OUT LPWSTR* pValue)
58 {
59 LONG rc;
60 DWORD dwType;
61 DWORD cbData = 0;
62 LPWSTR Value;
63
64 if (!pValue)
65 return ERROR_INVALID_PARAMETER;
66
67 *pValue = NULL;
68 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
69 if (rc != ERROR_SUCCESS)
70 return rc;
71 if (dwType != REG_SZ)
72 return ERROR_FILE_NOT_FOUND;
73 Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
74 if (!Value)
75 return ERROR_NOT_ENOUGH_MEMORY;
76 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
77 if (rc != ERROR_SUCCESS)
78 {
79 HeapFree(GetProcessHeap(), 0, Value);
80 return rc;
81 }
82 /* NULL-terminate the string */
83 Value[cbData / sizeof(WCHAR)] = '\0';
84
85 *pValue = Value;
86 return ERROR_SUCCESS;
87 }
88
89 static VOID
90 ChooseGinaUI(VOID)
91 {
92 HKEY ControlKey = NULL;
93 LPWSTR SystemStartOptions = NULL;
94 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
95 BOOL ConsoleBoot = FALSE;
96 LONG rc;
97
98 rc = RegOpenKeyExW(
99 HKEY_LOCAL_MACHINE,
100 L"SYSTEM\\CurrentControlSet\\Control",
101 0,
102 KEY_QUERY_VALUE,
103 &ControlKey);
104
105 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
106 if (rc != ERROR_SUCCESS)
107 goto cleanup;
108
109 /* Check for CONSOLE switch in SystemStartOptions */
110 CurrentOption = SystemStartOptions;
111 while (CurrentOption)
112 {
113 NextOption = wcschr(CurrentOption, L' ');
114 if (NextOption)
115 *NextOption = L'\0';
116 if (wcsicmp(CurrentOption, L"CONSOLE") == 0)
117 {
118 TRACE("Found %S. Switching to console boot\n", CurrentOption);
119 ConsoleBoot = TRUE;
120 goto cleanup;
121 }
122 CurrentOption = NextOption ? NextOption + 1 : NULL;
123 }
124
125 cleanup:
126 if (ConsoleBoot)
127 pGinaUI = &GinaTextUI;
128 else
129 pGinaUI = &GinaGraphicalUI;
130
131 if (ControlKey != NULL)
132 RegCloseKey(ControlKey);
133 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
134 }
135
136 /*
137 * @implemented
138 */
139 BOOL WINAPI
140 WlxInitialize(
141 LPWSTR lpWinsta,
142 HANDLE hWlx,
143 PVOID pvReserved,
144 PVOID pWinlogonFunctions,
145 PVOID *pWlxContext)
146 {
147 PGINA_CONTEXT pgContext;
148
149 UNREFERENCED_PARAMETER(pvReserved);
150
151 pgContext = (PGINA_CONTEXT)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(GINA_CONTEXT));
152 if(!pgContext)
153 {
154 WARN("LocalAlloc() failed\n");
155 return FALSE;
156 }
157
158 /* Return the context to winlogon */
159 *pWlxContext = (PVOID)pgContext;
160 pgContext->hDllInstance = hDllInstance;
161
162 /* Save pointer to dispatch table */
163 pgContext->pWlxFuncs = (PWLX_DISPATCH_VERSION_1_3)pWinlogonFunctions;
164
165 /* Save the winlogon handle used to call the dispatch functions */
166 pgContext->hWlx = hWlx;
167
168 /* Save window station */
169 pgContext->station = lpWinsta;
170
171 /* Clear status window handle */
172 pgContext->hStatusWindow = 0;
173
174 /* Notify winlogon that we will use the default SAS */
175 pgContext->pWlxFuncs->WlxUseCtrlAltDel(hWlx);
176
177 /* Locates the authentification package */
178 //LsaRegisterLogonProcess(...);
179
180 /* Check autologon settings the first time */
181 pgContext->AutoLogonState = AUTOLOGON_CHECK_REGISTRY;
182
183 ChooseGinaUI();
184 return pGinaUI->Initialize(pgContext);
185 }
186
187 /*
188 * @implemented
189 */
190 BOOL
191 WINAPI
192 WlxScreenSaverNotify(
193 PVOID pWlxContext,
194 BOOL *pSecure)
195 {
196 #if 0
197 WCHAR szBuffer[2];
198 HKEY hKey;
199 DWORD bufferSize = sizeof(szBuffer);
200 DWORD varType = REG_SZ;
201 LONG rc;
202
203 TRACE("(%p %p)\n", pWlxContext, pSecure);
204
205 *pSecure = TRUE;
206
207 /*
208 * Policy setting:
209 * HKLM\Software\Policies\Microsoft\Windows\Control Panel\Desktop : ScreenSaverIsSecure
210 * User setting:
211 * HKCU\Control Panel\Desktop : ScreenSaverIsSecure
212 */
213
214 rc = RegOpenKeyExW(HKEY_CURRENT_USER,
215 L"Control Panel\\Desktop",
216 0,
217 KEY_QUERY_VALUE,
218 &hKey);
219 TRACE("RegOpenKeyExW: %ld\n", rc);
220 if (rc == ERROR_SUCCESS)
221 {
222 rc = RegQueryValueExW(hKey,
223 L"ScreenSaverIsSecure",
224 NULL,
225 &varType,
226 (LPBYTE)szBuffer,
227 &bufferSize);
228
229 TRACE("RegQueryValueExW: %ld\n", rc);
230
231 if (rc == ERROR_SUCCESS)
232 {
233 TRACE("szBuffer: \"%S\"\n", szBuffer);
234 *pSecure = _wtoi(szBuffer);
235 }
236
237 RegCloseKey(hKey);
238 }
239
240 TRACE("*pSecure: %ld\n", *pSecure);
241 #endif
242
243 *pSecure = FALSE;
244
245 return TRUE;
246 }
247
248 /*
249 * @implemented
250 */
251 BOOL WINAPI
252 WlxStartApplication(
253 PVOID pWlxContext,
254 PWSTR pszDesktopName,
255 PVOID pEnvironment,
256 PWSTR pszCmdLine)
257 {
258 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
259 STARTUPINFOW StartupInfo;
260 PROCESS_INFORMATION ProcessInformation;
261 WCHAR CurrentDirectory[MAX_PATH];
262 HANDLE hAppToken;
263 UINT len;
264 BOOL ret;
265
266 len = GetWindowsDirectoryW(CurrentDirectory, MAX_PATH);
267 if (len == 0 || len > MAX_PATH)
268 {
269 ERR("GetWindowsDirectoryW() failed\n");
270 return FALSE;
271 }
272
273 ret = DuplicateTokenEx(pgContext->UserToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &hAppToken);
274 if (!ret)
275 {
276 ERR("DuplicateTokenEx() failed with error %lu\n", GetLastError());
277 return FALSE;
278 }
279
280 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
281 ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
282 StartupInfo.cb = sizeof(StartupInfo);
283 StartupInfo.lpTitle = pszCmdLine;
284 StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
285 StartupInfo.wShowWindow = SW_SHOW;
286 StartupInfo.lpDesktop = pszDesktopName;
287
288 len = GetWindowsDirectoryW(CurrentDirectory, MAX_PATH);
289 if (len == 0 || len > MAX_PATH)
290 {
291 ERR("GetWindowsDirectoryW() failed\n");
292 return FALSE;
293 }
294 ret = CreateProcessAsUserW(
295 hAppToken,
296 pszCmdLine,
297 NULL,
298 NULL,
299 NULL,
300 FALSE,
301 CREATE_UNICODE_ENVIRONMENT,
302 pEnvironment,
303 CurrentDirectory,
304 &StartupInfo,
305 &ProcessInformation);
306 CloseHandle(ProcessInformation.hProcess);
307 CloseHandle(ProcessInformation.hThread);
308 CloseHandle(hAppToken);
309 if (!ret)
310 ERR("CreateProcessAsUserW() failed with error %lu\n", GetLastError());
311 return ret;
312 }
313
314 /*
315 * @implemented
316 */
317 BOOL WINAPI
318 WlxActivateUserShell(
319 PVOID pWlxContext,
320 PWSTR pszDesktopName,
321 PWSTR pszMprLogonScript,
322 PVOID pEnvironment)
323 {
324 HKEY hKey;
325 DWORD BufSize, ValueType;
326 WCHAR pszUserInitApp[MAX_PATH + 1];
327 WCHAR pszExpUserInitApp[MAX_PATH];
328 DWORD len;
329 LONG rc;
330
331 TRACE("WlxActivateUserShell()\n");
332
333 UNREFERENCED_PARAMETER(pszMprLogonScript);
334
335 /* Get the path of userinit */
336 rc = RegOpenKeyExW(
337 HKEY_LOCAL_MACHINE,
338 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
339 0,
340 KEY_QUERY_VALUE,
341 &hKey);
342 if (rc != ERROR_SUCCESS)
343 {
344 WARN("RegOpenKeyExW() failed with error %lu\n", rc);
345 return FALSE;
346 }
347
348 /* Query userinit application */
349 BufSize = sizeof(pszUserInitApp) - sizeof(UNICODE_NULL);
350 rc = RegQueryValueExW(
351 hKey,
352 L"Userinit",
353 NULL,
354 &ValueType,
355 (LPBYTE)pszUserInitApp,
356 &BufSize);
357 RegCloseKey(hKey);
358 if (rc != ERROR_SUCCESS || (ValueType != REG_SZ && ValueType != REG_EXPAND_SZ))
359 {
360 WARN("RegQueryValueExW() failed with error %lu\n", rc);
361 return FALSE;
362 }
363 pszUserInitApp[MAX_PATH] = UNICODE_NULL;
364
365 len = ExpandEnvironmentStringsW(pszUserInitApp, pszExpUserInitApp, MAX_PATH);
366 if (len > MAX_PATH)
367 {
368 WARN("ExpandEnvironmentStringsW() failed. Required size %lu\n", len);
369 return FALSE;
370 }
371
372 /* Start userinit app */
373 return WlxStartApplication(pWlxContext, pszDesktopName, pEnvironment, pszExpUserInitApp);
374 }
375
376 /*
377 * @implemented
378 */
379 int WINAPI
380 WlxLoggedOnSAS(
381 PVOID pWlxContext,
382 DWORD dwSasType,
383 PVOID pReserved)
384 {
385 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
386 INT SasAction = WLX_SAS_ACTION_NONE;
387
388 TRACE("WlxLoggedOnSAS(0x%lx)\n", dwSasType);
389
390 UNREFERENCED_PARAMETER(pReserved);
391
392 switch (dwSasType)
393 {
394 case WLX_SAS_TYPE_CTRL_ALT_DEL:
395 case WLX_SAS_TYPE_TIMEOUT:
396 {
397 SasAction = pGinaUI->LoggedOnSAS(pgContext, dwSasType);
398 break;
399 }
400 case WLX_SAS_TYPE_SC_INSERT:
401 {
402 FIXME("WlxLoggedOnSAS: SasType WLX_SAS_TYPE_SC_INSERT not supported!\n");
403 break;
404 }
405 case WLX_SAS_TYPE_SC_REMOVE:
406 {
407 FIXME("WlxLoggedOnSAS: SasType WLX_SAS_TYPE_SC_REMOVE not supported!\n");
408 break;
409 }
410 default:
411 {
412 WARN("WlxLoggedOnSAS: Unknown SasType: 0x%x\n", dwSasType);
413 break;
414 }
415 }
416
417 return SasAction;
418 }
419
420 /*
421 * @implemented
422 */
423 BOOL WINAPI
424 WlxDisplayStatusMessage(
425 IN PVOID pWlxContext,
426 IN HDESK hDesktop,
427 IN DWORD dwOptions,
428 IN PWSTR pTitle,
429 IN PWSTR pMessage)
430 {
431 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
432
433 TRACE("WlxDisplayStatusMessage(\"%S\")\n", pMessage);
434
435 return pGinaUI->DisplayStatusMessage(pgContext, hDesktop, dwOptions, pTitle, pMessage);
436 }
437
438 /*
439 * @implemented
440 */
441 BOOL WINAPI
442 WlxRemoveStatusMessage(
443 IN PVOID pWlxContext)
444 {
445 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
446
447 TRACE("WlxRemoveStatusMessage()\n");
448
449 return pGinaUI->RemoveStatusMessage(pgContext);
450 }
451
452 static PWSTR
453 DuplicationString(PWSTR Str)
454 {
455 DWORD cb;
456 PWSTR NewStr;
457
458 if (Str == NULL) return NULL;
459
460 cb = (wcslen(Str) + 1) * sizeof(WCHAR);
461 if ((NewStr = LocalAlloc(LMEM_FIXED, cb)))
462 memcpy(NewStr, Str, cb);
463 return NewStr;
464 }
465
466 BOOL
467 DoLoginTasks(
468 IN OUT PGINA_CONTEXT pgContext,
469 IN PWSTR UserName,
470 IN PWSTR Domain,
471 IN PWSTR Password)
472 {
473 LPWSTR ProfilePath = NULL;
474 LPWSTR lpEnvironment = NULL;
475 TOKEN_STATISTICS Stats;
476 PWLX_PROFILE_V2_0 pProfile = NULL;
477 DWORD cbStats, cbSize;
478 DWORD dwLength;
479 BOOL bResult;
480
481 if (!LogonUserW(UserName, Domain, Password,
482 LOGON32_LOGON_INTERACTIVE,
483 LOGON32_PROVIDER_DEFAULT,
484 &pgContext->UserToken))
485 {
486 WARN("LogonUserW() failed\n");
487 goto cleanup;
488 }
489
490 /* Store the logon time in the context */
491 GetLocalTime(&pgContext->LogonTime);
492
493 /* Store user and domain in the context */
494 wcscpy(pgContext->UserName, UserName);
495 if (Domain == NULL || wcslen(Domain) == 0)
496 {
497 dwLength = 256;
498 GetComputerNameW(pgContext->Domain, &dwLength);
499 }
500 else
501 {
502 wcscpy(pgContext->Domain, Domain);
503 }
504
505 /* Get profile path */
506 cbSize = 0;
507 bResult = GetProfilesDirectoryW(NULL, &cbSize);
508 if (!bResult && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
509 {
510 ProfilePath = HeapAlloc(GetProcessHeap(), 0, cbSize * sizeof(WCHAR));
511 if (!ProfilePath)
512 {
513 WARN("HeapAlloc() failed\n");
514 goto cleanup;
515 }
516 bResult = GetProfilesDirectoryW(ProfilePath, &cbSize);
517 }
518 if (!bResult)
519 {
520 WARN("GetUserProfileDirectoryW() failed\n");
521 goto cleanup;
522 }
523
524 /* Allocate memory for profile */
525 pProfile = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WLX_PROFILE_V2_0));
526 if (!pProfile)
527 {
528 WARN("HeapAlloc() failed\n");
529 goto cleanup;
530 }
531 pProfile->dwType = WLX_PROFILE_TYPE_V2_0;
532 pProfile->pszProfile = ProfilePath;
533
534 lpEnvironment = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
535 (wcslen(pgContext->Domain)+ 14 + 1) * sizeof(WCHAR));
536 if (!lpEnvironment)
537 {
538 WARN("HeapAlloc() failed\n");
539 goto cleanup;
540 }
541
542 wsprintfW(lpEnvironment, L"LOGONSERVER=\\\\%s", pgContext->Domain);
543
544 pProfile->pszEnvironment = lpEnvironment;
545
546 if (!GetTokenInformation(pgContext->UserToken,
547 TokenStatistics,
548 (PVOID)&Stats,
549 sizeof(TOKEN_STATISTICS),
550 &cbStats))
551 {
552 WARN("Couldn't get Authentication id from user token!\n");
553 goto cleanup;
554 }
555
556 *pgContext->pAuthenticationId = Stats.AuthenticationId;
557 pgContext->pMprNotifyInfo->pszUserName = DuplicationString(UserName);
558 pgContext->pMprNotifyInfo->pszDomain = DuplicationString(Domain);
559 pgContext->pMprNotifyInfo->pszPassword = DuplicationString(Password);
560 pgContext->pMprNotifyInfo->pszOldPassword = NULL;
561 *pgContext->pdwOptions = 0;
562 *pgContext->pProfile = pProfile;
563 return TRUE;
564
565 cleanup:
566 if (pProfile)
567 {
568 HeapFree(GetProcessHeap(), 0, pProfile->pszEnvironment);
569 }
570 HeapFree(GetProcessHeap(), 0, pProfile);
571 HeapFree(GetProcessHeap(), 0, ProfilePath);
572 return FALSE;
573 }
574
575 static BOOL
576 DoAutoLogon(
577 IN PGINA_CONTEXT pgContext)
578 {
579 HKEY WinLogonKey = NULL;
580 LPWSTR AutoLogon = NULL;
581 LPWSTR AutoCount = NULL;
582 LPWSTR IgnoreShiftOverride = NULL;
583 LPWSTR UserName = NULL;
584 LPWSTR DomainName = NULL;
585 LPWSTR Password = NULL;
586 BOOL result = FALSE;
587 LONG rc;
588
589 TRACE("DoAutoLogon(): AutoLogonState = %lu\n",
590 pgContext->AutoLogonState);
591
592 if (pgContext->AutoLogonState == AUTOLOGON_DISABLED)
593 return FALSE;
594
595 rc = RegOpenKeyExW(
596 HKEY_LOCAL_MACHINE,
597 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon",
598 0,
599 KEY_QUERY_VALUE,
600 &WinLogonKey);
601 if (rc != ERROR_SUCCESS)
602 goto cleanup;
603
604 if (pgContext->AutoLogonState == AUTOLOGON_CHECK_REGISTRY)
605 {
606 /* Set it by default to disabled, we might reenable it again later */
607 pgContext->AutoLogonState = AUTOLOGON_DISABLED;
608
609 rc = ReadRegSzKey(WinLogonKey, L"AutoAdminLogon", &AutoLogon);
610 if (rc != ERROR_SUCCESS)
611 goto cleanup;
612 if (wcscmp(AutoLogon, L"1") != 0)
613 goto cleanup;
614
615 rc = ReadRegSzKey(WinLogonKey, L"AutoLogonCount", &AutoCount);
616 if (rc == ERROR_SUCCESS && wcscmp(AutoCount, L"0") == 0)
617 goto cleanup;
618 else if (rc != ERROR_FILE_NOT_FOUND)
619 goto cleanup;
620
621 rc = ReadRegSzKey(WinLogonKey, L"IgnoreShiftOverride", &UserName);
622 if (rc == ERROR_SUCCESS)
623 {
624 if (wcscmp(AutoLogon, L"1") != 0 && GetKeyState(VK_SHIFT) < 0)
625 goto cleanup;
626 }
627 else if (GetKeyState(VK_SHIFT) < 0)
628 {
629 /* User pressed SHIFT */
630 goto cleanup;
631 }
632
633 pgContext->AutoLogonState = AUTOLOGON_ONCE;
634 result = TRUE;
635 }
636 else /* pgContext->AutoLogonState == AUTOLOGON_ONCE */
637 {
638 pgContext->AutoLogonState = AUTOLOGON_DISABLED;
639
640 rc = ReadRegSzKey(WinLogonKey, L"DefaultUserName", &UserName);
641 if (rc != ERROR_SUCCESS)
642 goto cleanup;
643 rc = ReadRegSzKey(WinLogonKey, L"DefaultDomainName", &DomainName);
644 if (rc != ERROR_SUCCESS && rc != ERROR_FILE_NOT_FOUND)
645 goto cleanup;
646 rc = ReadRegSzKey(WinLogonKey, L"DefaultPassword", &Password);
647 if (rc != ERROR_SUCCESS)
648 goto cleanup;
649
650 result = DoLoginTasks(pgContext, UserName, DomainName, Password);
651
652 if (result == TRUE)
653 NotifyBootConfigStatus(TRUE);
654 }
655
656 cleanup:
657 if (WinLogonKey != NULL)
658 RegCloseKey(WinLogonKey);
659 HeapFree(GetProcessHeap(), 0, AutoLogon);
660 HeapFree(GetProcessHeap(), 0, AutoCount);
661 HeapFree(GetProcessHeap(), 0, IgnoreShiftOverride);
662 HeapFree(GetProcessHeap(), 0, UserName);
663 HeapFree(GetProcessHeap(), 0, DomainName);
664 HeapFree(GetProcessHeap(), 0, Password);
665 TRACE("DoAutoLogon(): AutoLogonState = %lu, returning %d\n",
666 pgContext->AutoLogonState, result);
667 return result;
668 }
669
670 /*
671 * @implemented
672 */
673 VOID WINAPI
674 WlxDisplaySASNotice(
675 IN PVOID pWlxContext)
676 {
677 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
678
679 TRACE("WlxDisplaySASNotice(%p)\n", pWlxContext);
680
681 if (GetSystemMetrics(SM_REMOTESESSION))
682 {
683 /* User is remotely logged on. Don't display a notice */
684 pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
685 return;
686 }
687
688 if (DoAutoLogon(pgContext))
689 {
690 /* Don't display the window, we want to do an automatic logon */
691 pgContext->AutoLogonState = AUTOLOGON_ONCE;
692 pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
693 return;
694 }
695 else
696 pgContext->AutoLogonState = AUTOLOGON_DISABLED;
697
698 pGinaUI->DisplaySASNotice(pgContext);
699
700 TRACE("WlxDisplaySASNotice() done\n");
701 }
702
703 /*
704 * @implemented
705 */
706 INT WINAPI
707 WlxLoggedOutSAS(
708 IN PVOID pWlxContext,
709 IN DWORD dwSasType,
710 OUT PLUID pAuthenticationId,
711 IN OUT PSID pLogonSid,
712 OUT PDWORD pdwOptions,
713 OUT PHANDLE phToken,
714 OUT PWLX_MPR_NOTIFY_INFO pMprNotifyInfo,
715 OUT PVOID *pProfile)
716 {
717 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
718 INT res;
719
720 TRACE("WlxLoggedOutSAS()\n");
721
722 UNREFERENCED_PARAMETER(dwSasType);
723 UNREFERENCED_PARAMETER(pLogonSid);
724
725 pgContext->pAuthenticationId = pAuthenticationId;
726 pgContext->pdwOptions = pdwOptions;
727 pgContext->pMprNotifyInfo = pMprNotifyInfo;
728 pgContext->pProfile = pProfile;
729
730 if (0 == GetSystemMetrics(SM_REMOTESESSION) &&
731 DoAutoLogon(pgContext))
732 {
733 /* User is local and registry contains information
734 * to log on him automatically */
735 *phToken = pgContext->UserToken;
736 return WLX_SAS_ACTION_LOGON;
737 }
738
739 res = pGinaUI->LoggedOutSAS(pgContext);
740 *phToken = pgContext->UserToken;
741 return res;
742 }
743
744 /*
745 * @implemented
746 */
747 int WINAPI
748 WlxWkstaLockedSAS(
749 PVOID pWlxContext,
750 DWORD dwSasType)
751 {
752 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
753
754 TRACE("WlxWkstaLockedSAS()\n");
755
756 UNREFERENCED_PARAMETER(dwSasType);
757
758 return pGinaUI->LockedSAS(pgContext);
759 }
760
761
762 /*
763 * @implemented
764 */
765 VOID
766 WINAPI
767 WlxDisplayLockedNotice(PVOID pWlxContext)
768 {
769 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
770
771 TRACE("WlxDisplayLockedNotice()\n");
772
773 pGinaUI->DisplayLockedNotice(pgContext);
774 }
775
776
777 /*
778 * @implemented
779 */
780 BOOL WINAPI
781 WlxIsLogoffOk(
782 PVOID pWlxContext)
783 {
784 TRACE("WlxIsLogoffOk()\n");
785 UNREFERENCED_PARAMETER(pWlxContext);
786 return TRUE;
787 }
788
789 BOOL WINAPI
790 DllMain(
791 IN HINSTANCE hinstDLL,
792 IN DWORD dwReason,
793 IN LPVOID lpvReserved)
794 {
795 UNREFERENCED_PARAMETER(lpvReserved);
796
797 if (dwReason == DLL_PROCESS_ATTACH)
798 hDllInstance = hinstDLL;
799
800 return TRUE;
801 }