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