fbd9ef5e99ff4f101fa11939392b6226bba8cb73
[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
576 static
577 BOOL
578 CheckAutoAdminLogon(
579 IN PGINA_CONTEXT pgContext)
580 {
581 HKEY WinLogonKey = NULL;
582 LPWSTR AutoLogon = NULL;
583 BOOL result = FALSE;
584 LONG rc;
585
586 if (pgContext->AutoLogonState == AUTOLOGON_DISABLED)
587 return FALSE;
588
589 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
590 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon",
591 0,
592 KEY_QUERY_VALUE,
593 &WinLogonKey);
594 if (rc != ERROR_SUCCESS)
595 goto cleanup;
596
597 rc = ReadRegSzKey(WinLogonKey,
598 L"AutoAdminLogon",
599 &AutoLogon);
600
601 if (rc != ERROR_SUCCESS)
602 goto cleanup;
603
604 if (wcscmp(AutoLogon, L"1") == 0)
605 result = TRUE;
606
607 cleanup:
608 if (WinLogonKey != NULL)
609 RegCloseKey(WinLogonKey);
610 HeapFree(GetProcessHeap(), 0, AutoLogon);
611
612 return result;
613 }
614
615
616 static BOOL
617 DoAutoLogon(
618 IN PGINA_CONTEXT pgContext)
619 {
620 HKEY WinLogonKey = NULL;
621 LPWSTR AutoLogon = NULL;
622 LPWSTR AutoCount = NULL;
623 LPWSTR IgnoreShiftOverride = NULL;
624 LPWSTR UserName = NULL;
625 LPWSTR DomainName = NULL;
626 LPWSTR Password = NULL;
627 BOOL result = FALSE;
628 LONG rc;
629
630 TRACE("DoAutoLogon(): AutoLogonState = %lu\n",
631 pgContext->AutoLogonState);
632
633 if (pgContext->AutoLogonState == AUTOLOGON_DISABLED)
634 return FALSE;
635
636 rc = RegOpenKeyExW(
637 HKEY_LOCAL_MACHINE,
638 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon",
639 0,
640 KEY_QUERY_VALUE,
641 &WinLogonKey);
642 if (rc != ERROR_SUCCESS)
643 goto cleanup;
644
645 if (pgContext->AutoLogonState == AUTOLOGON_CHECK_REGISTRY)
646 {
647 /* Set it by default to disabled, we might reenable it again later */
648 pgContext->AutoLogonState = AUTOLOGON_DISABLED;
649
650 rc = ReadRegSzKey(WinLogonKey, L"AutoAdminLogon", &AutoLogon);
651 if (rc != ERROR_SUCCESS)
652 goto cleanup;
653 if (wcscmp(AutoLogon, L"1") != 0)
654 goto cleanup;
655
656 rc = ReadRegSzKey(WinLogonKey, L"AutoLogonCount", &AutoCount);
657 if (rc == ERROR_SUCCESS && wcscmp(AutoCount, L"0") == 0)
658 goto cleanup;
659 else if (rc != ERROR_FILE_NOT_FOUND)
660 goto cleanup;
661
662 rc = ReadRegSzKey(WinLogonKey, L"IgnoreShiftOverride", &UserName);
663 if (rc == ERROR_SUCCESS)
664 {
665 if (wcscmp(AutoLogon, L"1") != 0 && GetKeyState(VK_SHIFT) < 0)
666 goto cleanup;
667 }
668 else if (GetKeyState(VK_SHIFT) < 0)
669 {
670 /* User pressed SHIFT */
671 goto cleanup;
672 }
673
674 pgContext->AutoLogonState = AUTOLOGON_ONCE;
675 result = TRUE;
676 }
677 else /* pgContext->AutoLogonState == AUTOLOGON_ONCE */
678 {
679 pgContext->AutoLogonState = AUTOLOGON_DISABLED;
680
681 rc = ReadRegSzKey(WinLogonKey, L"DefaultUserName", &UserName);
682 if (rc != ERROR_SUCCESS)
683 goto cleanup;
684 rc = ReadRegSzKey(WinLogonKey, L"DefaultDomainName", &DomainName);
685 if (rc != ERROR_SUCCESS && rc != ERROR_FILE_NOT_FOUND)
686 goto cleanup;
687 rc = ReadRegSzKey(WinLogonKey, L"DefaultPassword", &Password);
688 if (rc != ERROR_SUCCESS)
689 goto cleanup;
690
691 result = DoLoginTasks(pgContext, UserName, DomainName, Password);
692
693 if (result == TRUE)
694 NotifyBootConfigStatus(TRUE);
695 }
696
697 cleanup:
698 if (WinLogonKey != NULL)
699 RegCloseKey(WinLogonKey);
700 HeapFree(GetProcessHeap(), 0, AutoLogon);
701 HeapFree(GetProcessHeap(), 0, AutoCount);
702 HeapFree(GetProcessHeap(), 0, IgnoreShiftOverride);
703 HeapFree(GetProcessHeap(), 0, UserName);
704 HeapFree(GetProcessHeap(), 0, DomainName);
705 HeapFree(GetProcessHeap(), 0, Password);
706 TRACE("DoAutoLogon(): AutoLogonState = %lu, returning %d\n",
707 pgContext->AutoLogonState, result);
708 return result;
709 }
710
711 /*
712 * @implemented
713 */
714 VOID WINAPI
715 WlxDisplaySASNotice(
716 IN PVOID pWlxContext)
717 {
718 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
719
720 TRACE("WlxDisplaySASNotice(%p)\n", pWlxContext);
721
722 if (GetSystemMetrics(SM_REMOTESESSION))
723 {
724 /* User is remotely logged on. Don't display a notice */
725 pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
726 return;
727 }
728
729 if (CheckAutoAdminLogon(pgContext))
730 {
731 /* Don't display the window, we want to do an automatic logon */
732 pgContext->AutoLogonState = AUTOLOGON_ONCE;
733 pgContext->pWlxFuncs->WlxSasNotify(pgContext->hWlx, WLX_SAS_TYPE_CTRL_ALT_DEL);
734 return;
735 }
736 else
737 pgContext->AutoLogonState = AUTOLOGON_DISABLED;
738
739 pGinaUI->DisplaySASNotice(pgContext);
740
741 TRACE("WlxDisplaySASNotice() done\n");
742 }
743
744 /*
745 * @implemented
746 */
747 INT WINAPI
748 WlxLoggedOutSAS(
749 IN PVOID pWlxContext,
750 IN DWORD dwSasType,
751 OUT PLUID pAuthenticationId,
752 IN OUT PSID pLogonSid,
753 OUT PDWORD pdwOptions,
754 OUT PHANDLE phToken,
755 OUT PWLX_MPR_NOTIFY_INFO pMprNotifyInfo,
756 OUT PVOID *pProfile)
757 {
758 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
759 INT res;
760
761 TRACE("WlxLoggedOutSAS()\n");
762
763 UNREFERENCED_PARAMETER(dwSasType);
764 UNREFERENCED_PARAMETER(pLogonSid);
765
766 pgContext->pAuthenticationId = pAuthenticationId;
767 pgContext->pdwOptions = pdwOptions;
768 pgContext->pMprNotifyInfo = pMprNotifyInfo;
769 pgContext->pProfile = pProfile;
770
771 if (0 == GetSystemMetrics(SM_REMOTESESSION) &&
772 DoAutoLogon(pgContext))
773 {
774 /* User is local and registry contains information
775 * to log on him automatically */
776 *phToken = pgContext->UserToken;
777 return WLX_SAS_ACTION_LOGON;
778 }
779
780 res = pGinaUI->LoggedOutSAS(pgContext);
781 *phToken = pgContext->UserToken;
782 return res;
783 }
784
785 /*
786 * @implemented
787 */
788 int WINAPI
789 WlxWkstaLockedSAS(
790 PVOID pWlxContext,
791 DWORD dwSasType)
792 {
793 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
794
795 TRACE("WlxWkstaLockedSAS()\n");
796
797 UNREFERENCED_PARAMETER(dwSasType);
798
799 return pGinaUI->LockedSAS(pgContext);
800 }
801
802
803 /*
804 * @implemented
805 */
806 VOID
807 WINAPI
808 WlxDisplayLockedNotice(PVOID pWlxContext)
809 {
810 PGINA_CONTEXT pgContext = (PGINA_CONTEXT)pWlxContext;
811
812 TRACE("WlxDisplayLockedNotice()\n");
813
814 pGinaUI->DisplayLockedNotice(pgContext);
815 }
816
817
818 /*
819 * @implemented
820 */
821 BOOL WINAPI
822 WlxIsLogoffOk(
823 PVOID pWlxContext)
824 {
825 TRACE("WlxIsLogoffOk()\n");
826 UNREFERENCED_PARAMETER(pWlxContext);
827 return TRUE;
828 }
829
830 BOOL WINAPI
831 DllMain(
832 IN HINSTANCE hinstDLL,
833 IN DWORD dwReason,
834 IN LPVOID lpvReserved)
835 {
836 UNREFERENCED_PARAMETER(lpvReserved);
837
838 if (dwReason == DLL_PROCESS_ATTACH)
839 hDllInstance = hinstDLL;
840
841 return TRUE;
842 }